Merge tag 'staging-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Feb 2018 17:51:57 +0000 (09:51 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Feb 2018 17:51:57 +0000 (09:51 -0800)
Pull staging/IIO updates from Greg KH:
 "Here is the big Staging and IIO driver patches for 4.16-rc1.

  There is the normal amount of new IIO drivers added, like all
  releases.

  The networking IPX and the ncpfs filesystem are moved into the staging
  tree, as they are on their way out of the kernel due to lack of use
  anymore.

  The visorbus subsystem finall has started moving out of the staging
  tree to the "real" part of the kernel, and the most and fsl-mc
  codebases are almost ready to move out, that will probably happen for
  4.17-rc1 if all goes well.

  Other than that, there is a bunch of license header cleanups in the
  tree, along with the normal amount of coding style churn that we all
  know and love for this codebase. I also got frustrated at the
  Meltdown/Spectre mess and took it out on the dgnc tty driver, deleting
  huge chunks of it that were never even being used.

  Full details of everything is in the shortlog.

  All of these patches have been in linux-next for a while with no
  reported issues"

* tag 'staging-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (627 commits)
  staging: rtlwifi: remove redundant initialization of 'cfg_cmd'
  staging: rtl8723bs: remove a couple of redundant initializations
  staging: comedi: reformat lines to 80 chars or less
  staging: lustre: separate a connection destroy from free struct kib_conn
  Staging: rtl8723bs: Use !x instead of NULL comparison
  Staging: rtl8723bs: Remove dead code
  Staging: rtl8723bs: Change names to conform to the kernel code
  staging: ccree: Fix missing blank line after declaration
  staging: rtl8188eu: remove redundant initialization of 'pwrcfgcmd'
  staging: rtlwifi: remove unused RTLHALMAC_ST and RTLPHYDM_ST
  staging: fbtft: remove unused FB_TFT_SSD1325 kconfig
  staging: comedi: dt2811: remove redundant initialization of 'ns'
  staging: wilc1000: fix alignments to match open parenthesis
  staging: wilc1000: removed unnecessary defined enums typedef
  staging: wilc1000: remove unnecessary use of parentheses
  staging: rtl8192u: remove redundant initialization of 'timeout'
  staging: sm750fb: fix CamelCase for dispSet var
  staging: lustre: lnet/selftest: fix compile error on UP build
  staging: rtl8723bs: hal_com_phycfg: Remove unneeded semicolons
  staging: rts5208: Fix "seg_no" calculation in reset_ms_card()
  ...

882 files changed:
Documentation/ABI/testing/sysfs-bus-iio
Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
Documentation/devicetree/bindings/iio/adc/aspeed_adc.txt
Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
Documentation/devicetree/bindings/iio/health/max30102.txt
Documentation/devicetree/bindings/iio/light/uvis25.txt [new file with mode: 0644]
MAINTAINERS
drivers/Kconfig
drivers/Makefile
drivers/iio/accel/bmc150-accel-i2c.c
drivers/iio/accel/da280.c
drivers/iio/accel/kxsd9-i2c.c
drivers/iio/accel/mma8452.c
drivers/iio/accel/st_accel_core.c
drivers/iio/adc/Kconfig
drivers/iio/adc/aspeed_adc.c
drivers/iio/adc/at91-sama5d2_adc.c
drivers/iio/adc/at91_adc.c
drivers/iio/adc/axp288_adc.c
drivers/iio/adc/hx711.c
drivers/iio/adc/ina2xx-adc.c
drivers/iio/adc/meson_saradc.c
drivers/iio/adc/qcom-vadc-common.c
drivers/iio/adc/stm32-adc-core.c
drivers/iio/adc/stm32-adc-core.h
drivers/iio/adc/stm32-adc.c
drivers/iio/adc/ti_am335x_adc.c
drivers/iio/chemical/ccs811.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
drivers/iio/common/ssp_sensors/ssp.h
drivers/iio/common/ssp_sensors/ssp_dev.c
drivers/iio/common/ssp_sensors/ssp_spi.c
drivers/iio/counter/stm32-lptimer-cnt.c
drivers/iio/dac/mcp4725.c
drivers/iio/dac/stm32-dac-core.c
drivers/iio/dac/stm32-dac-core.h
drivers/iio/dac/stm32-dac.c
drivers/iio/dummy/iio_dummy_evgen.c
drivers/iio/gyro/adis16136.c
drivers/iio/gyro/bmg160_core.c
drivers/iio/health/max30102.c
drivers/iio/humidity/hts221.h
drivers/iio/humidity/hts221_core.c
drivers/iio/humidity/hts221_i2c.c
drivers/iio/humidity/hts221_spi.c
drivers/iio/imu/adis16480.c
drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
drivers/iio/imu/st_lsm6dsx/Kconfig
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
drivers/iio/industrialio-buffer.c
drivers/iio/industrialio-core.c
drivers/iio/light/Kconfig
drivers/iio/light/Makefile
drivers/iio/light/cros_ec_light_prox.c
drivers/iio/light/st_uvis25.h [new file with mode: 0644]
drivers/iio/light/st_uvis25_core.c [new file with mode: 0644]
drivers/iio/light/st_uvis25_i2c.c [new file with mode: 0644]
drivers/iio/light/st_uvis25_spi.c [new file with mode: 0644]
drivers/iio/light/zopt2201.c [new file with mode: 0644]
drivers/iio/magnetometer/ak8975.c
drivers/iio/pressure/bmp280-core.c
drivers/iio/proximity/sx9500.c
drivers/iio/trigger/stm32-lptimer-trigger.c
drivers/iio/trigger/stm32-timer-trigger.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/android/ashmem.c
drivers/staging/android/ashmem.h
drivers/staging/android/ion/ion-ioctl.c
drivers/staging/android/ion/ion.c
drivers/staging/android/ion/ion.h
drivers/staging/android/ion/ion_carveout_heap.c
drivers/staging/android/ion/ion_chunk_heap.c
drivers/staging/android/ion/ion_cma_heap.c
drivers/staging/android/ion/ion_heap.c
drivers/staging/android/ion/ion_page_pool.c
drivers/staging/android/ion/ion_system_heap.c
drivers/staging/android/uapi/ashmem.h
drivers/staging/android/uapi/ion.h
drivers/staging/ccree/Documentation/devicetree/bindings/crypto/arm-cryptocell.txt [deleted file]
drivers/staging/ccree/Kconfig
drivers/staging/ccree/Makefile
drivers/staging/ccree/TODO
drivers/staging/ccree/cc_aead.c [new file with mode: 0644]
drivers/staging/ccree/cc_aead.h [new file with mode: 0644]
drivers/staging/ccree/cc_buffer_mgr.c [new file with mode: 0644]
drivers/staging/ccree/cc_buffer_mgr.h [new file with mode: 0644]
drivers/staging/ccree/cc_cipher.c [new file with mode: 0644]
drivers/staging/ccree/cc_cipher.h [new file with mode: 0644]
drivers/staging/ccree/cc_crypto_ctx.h
drivers/staging/ccree/cc_debugfs.c [new file with mode: 0644]
drivers/staging/ccree/cc_debugfs.h [new file with mode: 0644]
drivers/staging/ccree/cc_driver.c [new file with mode: 0644]
drivers/staging/ccree/cc_driver.h [new file with mode: 0644]
drivers/staging/ccree/cc_fips.c [new file with mode: 0644]
drivers/staging/ccree/cc_fips.h [new file with mode: 0644]
drivers/staging/ccree/cc_hash.c [new file with mode: 0644]
drivers/staging/ccree/cc_hash.h [new file with mode: 0644]
drivers/staging/ccree/cc_host_regs.h [new file with mode: 0644]
drivers/staging/ccree/cc_hw_queue_defs.h
drivers/staging/ccree/cc_ivgen.c [new file with mode: 0644]
drivers/staging/ccree/cc_ivgen.h [new file with mode: 0644]
drivers/staging/ccree/cc_kernel_regs.h [new file with mode: 0644]
drivers/staging/ccree/cc_lli_defs.h
drivers/staging/ccree/cc_pm.c [new file with mode: 0644]
drivers/staging/ccree/cc_pm.h [new file with mode: 0644]
drivers/staging/ccree/cc_request_mgr.c [new file with mode: 0644]
drivers/staging/ccree/cc_request_mgr.h [new file with mode: 0644]
drivers/staging/ccree/cc_sram_mgr.c [new file with mode: 0644]
drivers/staging/ccree/cc_sram_mgr.h [new file with mode: 0644]
drivers/staging/ccree/dx_crys_kernel.h [deleted file]
drivers/staging/ccree/dx_host.h [deleted file]
drivers/staging/ccree/dx_reg_common.h [deleted file]
drivers/staging/ccree/hash_defs.h [deleted file]
drivers/staging/ccree/ssi_aead.c [deleted file]
drivers/staging/ccree/ssi_aead.h [deleted file]
drivers/staging/ccree/ssi_buffer_mgr.c [deleted file]
drivers/staging/ccree/ssi_buffer_mgr.h [deleted file]
drivers/staging/ccree/ssi_cipher.c [deleted file]
drivers/staging/ccree/ssi_cipher.h [deleted file]
drivers/staging/ccree/ssi_config.h [deleted file]
drivers/staging/ccree/ssi_driver.c [deleted file]
drivers/staging/ccree/ssi_driver.h [deleted file]
drivers/staging/ccree/ssi_fips.c [deleted file]
drivers/staging/ccree/ssi_fips.h [deleted file]
drivers/staging/ccree/ssi_hash.c [deleted file]
drivers/staging/ccree/ssi_hash.h [deleted file]
drivers/staging/ccree/ssi_ivgen.c [deleted file]
drivers/staging/ccree/ssi_ivgen.h [deleted file]
drivers/staging/ccree/ssi_pm.c [deleted file]
drivers/staging/ccree/ssi_pm.h [deleted file]
drivers/staging/ccree/ssi_request_mgr.c [deleted file]
drivers/staging/ccree/ssi_request_mgr.h [deleted file]
drivers/staging/ccree/ssi_sram_mgr.c [deleted file]
drivers/staging/ccree/ssi_sram_mgr.h [deleted file]
drivers/staging/ccree/ssi_sysfs.c [deleted file]
drivers/staging/ccree/ssi_sysfs.h [deleted file]
drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
drivers/staging/comedi/comedi.h
drivers/staging/comedi/comedi_buf.c
drivers/staging/comedi/comedi_compat32.c
drivers/staging/comedi/comedi_compat32.h
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/comedi_pci.c
drivers/staging/comedi/comedi_pci.h
drivers/staging/comedi/comedi_pcmcia.c
drivers/staging/comedi/comedi_pcmcia.h
drivers/staging/comedi/comedi_usb.c
drivers/staging/comedi/comedi_usb.h
drivers/staging/comedi/comedidev.h
drivers/staging/comedi/comedilib.h
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/8255.c
drivers/staging/comedi/drivers/8255.h
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/comedi/drivers/addi_apci_1032.c
drivers/staging/comedi/drivers/addi_apci_1500.c
drivers/staging/comedi/drivers/addi_apci_1516.c
drivers/staging/comedi/drivers/addi_apci_1564.c
drivers/staging/comedi/drivers/addi_apci_16xx.c
drivers/staging/comedi/drivers/addi_apci_2032.c
drivers/staging/comedi/drivers/addi_apci_2200.c
drivers/staging/comedi/drivers/addi_apci_3120.c
drivers/staging/comedi/drivers/addi_apci_3501.c
drivers/staging/comedi/drivers/addi_apci_3xxx.c
drivers/staging/comedi/drivers/addi_watchdog.c
drivers/staging/comedi/drivers/adl_pci6208.c
drivers/staging/comedi/drivers/adl_pci7x3x.c
drivers/staging/comedi/drivers/adl_pci8164.c
drivers/staging/comedi/drivers/adl_pci9111.c
drivers/staging/comedi/drivers/adl_pci9118.c
drivers/staging/comedi/drivers/adq12b.c
drivers/staging/comedi/drivers/adv_pci1710.c
drivers/staging/comedi/drivers/adv_pci1720.c
drivers/staging/comedi/drivers/adv_pci1723.c
drivers/staging/comedi/drivers/adv_pci1724.c
drivers/staging/comedi/drivers/adv_pci1760.c
drivers/staging/comedi/drivers/adv_pci_dio.c
drivers/staging/comedi/drivers/aio_aio12_8.c
drivers/staging/comedi/drivers/aio_iiro_16.c
drivers/staging/comedi/drivers/amplc_dio200.c
drivers/staging/comedi/drivers/amplc_dio200.h
drivers/staging/comedi/drivers/amplc_dio200_common.c
drivers/staging/comedi/drivers/amplc_dio200_pci.c
drivers/staging/comedi/drivers/amplc_pc236.c
drivers/staging/comedi/drivers/amplc_pc236.h
drivers/staging/comedi/drivers/amplc_pc236_common.c
drivers/staging/comedi/drivers/amplc_pc263.c
drivers/staging/comedi/drivers/amplc_pci224.c
drivers/staging/comedi/drivers/amplc_pci230.c
drivers/staging/comedi/drivers/amplc_pci236.c
drivers/staging/comedi/drivers/amplc_pci263.c
drivers/staging/comedi/drivers/c6xdigio.c
drivers/staging/comedi/drivers/cb_das16_cs.c
drivers/staging/comedi/drivers/cb_pcidas.c
drivers/staging/comedi/drivers/cb_pcidas64.c
drivers/staging/comedi/drivers/cb_pcidda.c
drivers/staging/comedi/drivers/cb_pcimdas.c
drivers/staging/comedi/drivers/cb_pcimdda.c
drivers/staging/comedi/drivers/comedi_8254.c
drivers/staging/comedi/drivers/comedi_8254.h
drivers/staging/comedi/drivers/comedi_8255.c
drivers/staging/comedi/drivers/comedi_bond.c
drivers/staging/comedi/drivers/comedi_isadma.c
drivers/staging/comedi/drivers/comedi_isadma.h
drivers/staging/comedi/drivers/comedi_parport.c
drivers/staging/comedi/drivers/comedi_test.c
drivers/staging/comedi/drivers/contec_pci_dio.c
drivers/staging/comedi/drivers/dac02.c
drivers/staging/comedi/drivers/daqboard2000.c
drivers/staging/comedi/drivers/das08.c
drivers/staging/comedi/drivers/das08.h
drivers/staging/comedi/drivers/das08_cs.c
drivers/staging/comedi/drivers/das08_isa.c
drivers/staging/comedi/drivers/das08_pci.c
drivers/staging/comedi/drivers/das16.c
drivers/staging/comedi/drivers/das16m1.c
drivers/staging/comedi/drivers/das1800.c
drivers/staging/comedi/drivers/das6402.c
drivers/staging/comedi/drivers/das800.c
drivers/staging/comedi/drivers/dmm32at.c
drivers/staging/comedi/drivers/dt2801.c
drivers/staging/comedi/drivers/dt2811.c
drivers/staging/comedi/drivers/dt2814.c
drivers/staging/comedi/drivers/dt2815.c
drivers/staging/comedi/drivers/dt2817.c
drivers/staging/comedi/drivers/dt282x.c
drivers/staging/comedi/drivers/dt3000.c
drivers/staging/comedi/drivers/dt9812.c
drivers/staging/comedi/drivers/dyna_pci10xx.c
drivers/staging/comedi/drivers/fl512.c
drivers/staging/comedi/drivers/gsc_hpdi.c
drivers/staging/comedi/drivers/icp_multi.c
drivers/staging/comedi/drivers/ii_pci20kc.c
drivers/staging/comedi/drivers/jr3_pci.c
drivers/staging/comedi/drivers/ke_counter.c
drivers/staging/comedi/drivers/me4000.c
drivers/staging/comedi/drivers/me_daq.c
drivers/staging/comedi/drivers/mf6x4.c
drivers/staging/comedi/drivers/mite.c
drivers/staging/comedi/drivers/mite.h
drivers/staging/comedi/drivers/mpc624.c
drivers/staging/comedi/drivers/multiq3.c
drivers/staging/comedi/drivers/ni_6527.c
drivers/staging/comedi/drivers/ni_65xx.c
drivers/staging/comedi/drivers/ni_660x.c
drivers/staging/comedi/drivers/ni_670x.c
drivers/staging/comedi/drivers/ni_at_a2150.c
drivers/staging/comedi/drivers/ni_at_ao.c
drivers/staging/comedi/drivers/ni_atmio.c
drivers/staging/comedi/drivers/ni_atmio16d.c
drivers/staging/comedi/drivers/ni_daq_700.c
drivers/staging/comedi/drivers/ni_daq_dio24.c
drivers/staging/comedi/drivers/ni_labpc.c
drivers/staging/comedi/drivers/ni_labpc.h
drivers/staging/comedi/drivers/ni_labpc_common.c
drivers/staging/comedi/drivers/ni_labpc_cs.c
drivers/staging/comedi/drivers/ni_labpc_isadma.c
drivers/staging/comedi/drivers/ni_labpc_pci.c
drivers/staging/comedi/drivers/ni_mio_common.c
drivers/staging/comedi/drivers/ni_mio_cs.c
drivers/staging/comedi/drivers/ni_pcidio.c
drivers/staging/comedi/drivers/ni_pcimio.c
drivers/staging/comedi/drivers/ni_stc.h
drivers/staging/comedi/drivers/ni_tio.c
drivers/staging/comedi/drivers/ni_tio.h
drivers/staging/comedi/drivers/ni_tio_internal.h
drivers/staging/comedi/drivers/ni_tiocmd.c
drivers/staging/comedi/drivers/ni_usb6501.c
drivers/staging/comedi/drivers/pcl711.c
drivers/staging/comedi/drivers/pcl724.c
drivers/staging/comedi/drivers/pcl726.c
drivers/staging/comedi/drivers/pcl730.c
drivers/staging/comedi/drivers/pcl812.c
drivers/staging/comedi/drivers/pcl816.c
drivers/staging/comedi/drivers/pcl818.c
drivers/staging/comedi/drivers/pcm3724.c
drivers/staging/comedi/drivers/pcmad.c
drivers/staging/comedi/drivers/pcmda12.c
drivers/staging/comedi/drivers/pcmmio.c
drivers/staging/comedi/drivers/pcmuio.c
drivers/staging/comedi/drivers/plx9052.h
drivers/staging/comedi/drivers/plx9080.h
drivers/staging/comedi/drivers/rtd520.c
drivers/staging/comedi/drivers/rti800.c
drivers/staging/comedi/drivers/rti802.c
drivers/staging/comedi/drivers/s526.c
drivers/staging/comedi/drivers/s626.c
drivers/staging/comedi/drivers/s626.h
drivers/staging/comedi/drivers/serial2002.c
drivers/staging/comedi/drivers/ssv_dnp.c
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/comedi/drivers/usbduxfast.c
drivers/staging/comedi/drivers/usbduxsigma.c
drivers/staging/comedi/drivers/vmk80xx.c
drivers/staging/comedi/kcomedilib/kcomedilib_main.c
drivers/staging/comedi/proc.c
drivers/staging/comedi/range.c
drivers/staging/dgnc/Makefile
drivers/staging/dgnc/dgnc_cls.c
drivers/staging/dgnc/dgnc_cls.h
drivers/staging/dgnc/dgnc_driver.c
drivers/staging/dgnc/dgnc_driver.h
drivers/staging/dgnc/dgnc_mgmt.c [deleted file]
drivers/staging/dgnc/dgnc_mgmt.h [deleted file]
drivers/staging/dgnc/dgnc_neo.c [deleted file]
drivers/staging/dgnc/dgnc_neo.h [deleted file]
drivers/staging/dgnc/dgnc_pci.h [deleted file]
drivers/staging/dgnc/dgnc_tty.c
drivers/staging/dgnc/dgnc_tty.h
drivers/staging/dgnc/dgnc_utils.c [deleted file]
drivers/staging/dgnc/dgnc_utils.h [deleted file]
drivers/staging/dgnc/digi.h
drivers/staging/emxx_udc/emxx_udc.c
drivers/staging/emxx_udc/emxx_udc.h
drivers/staging/fbtft/Kconfig
drivers/staging/fbtft/fb_agm1264k-fl.c
drivers/staging/fbtft/fb_bd663474.c
drivers/staging/fbtft/fb_hx8340bn.c
drivers/staging/fbtft/fb_hx8347d.c
drivers/staging/fbtft/fb_hx8353d.c
drivers/staging/fbtft/fb_hx8357d.c
drivers/staging/fbtft/fb_hx8357d.h
drivers/staging/fbtft/fb_ili9163.c
drivers/staging/fbtft/fb_ili9320.c
drivers/staging/fbtft/fb_ili9325.c
drivers/staging/fbtft/fb_ili9340.c
drivers/staging/fbtft/fb_ili9341.c
drivers/staging/fbtft/fb_ili9481.c
drivers/staging/fbtft/fb_ili9486.c
drivers/staging/fbtft/fb_pcd8544.c
drivers/staging/fbtft/fb_ra8875.c
drivers/staging/fbtft/fb_s6d02a1.c
drivers/staging/fbtft/fb_s6d1121.c
drivers/staging/fbtft/fb_sh1106.c
drivers/staging/fbtft/fb_ssd1289.c
drivers/staging/fbtft/fb_ssd1305.c
drivers/staging/fbtft/fb_ssd1306.c
drivers/staging/fbtft/fb_ssd1325.c
drivers/staging/fbtft/fb_ssd1331.c
drivers/staging/fbtft/fb_ssd1351.c
drivers/staging/fbtft/fb_st7735r.c
drivers/staging/fbtft/fb_st7789v.c
drivers/staging/fbtft/fb_tinylcd.c
drivers/staging/fbtft/fb_tls8204.c
drivers/staging/fbtft/fb_uc1611.c
drivers/staging/fbtft/fb_uc1701.c
drivers/staging/fbtft/fb_upd161704.c
drivers/staging/fbtft/fb_watterott.c
drivers/staging/fbtft/fbtft-core.c
drivers/staging/fbtft/fbtft.h
drivers/staging/fbtft/fbtft_device.c
drivers/staging/fbtft/flexfb.c
drivers/staging/fbtft/internal.h
drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
drivers/staging/fsl-mc/Kconfig
drivers/staging/fsl-mc/Makefile
drivers/staging/fsl-mc/README.txt [deleted file]
drivers/staging/fsl-mc/bus/Kconfig
drivers/staging/fsl-mc/bus/Makefile
drivers/staging/fsl-mc/bus/dpbp-cmd.h
drivers/staging/fsl-mc/bus/dpbp.c
drivers/staging/fsl-mc/bus/dpcon-cmd.h
drivers/staging/fsl-mc/bus/dpcon.c
drivers/staging/fsl-mc/bus/dpio/Makefile
drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h
drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
drivers/staging/fsl-mc/bus/dpio/dpio-service.c
drivers/staging/fsl-mc/bus/dpio/dpio.c
drivers/staging/fsl-mc/bus/dpio/dpio.h
drivers/staging/fsl-mc/bus/dpio/qbman-portal.c
drivers/staging/fsl-mc/bus/dpio/qbman-portal.h
drivers/staging/fsl-mc/bus/dpmcp-cmd.h [deleted file]
drivers/staging/fsl-mc/bus/dpmcp.c
drivers/staging/fsl-mc/bus/dpmcp.h [deleted file]
drivers/staging/fsl-mc/bus/dpmng-cmd.h [deleted file]
drivers/staging/fsl-mc/bus/dprc-cmd.h [deleted file]
drivers/staging/fsl-mc/bus/dprc-driver.c
drivers/staging/fsl-mc/bus/dprc.c
drivers/staging/fsl-mc/bus/dprc.h [deleted file]
drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
drivers/staging/fsl-mc/bus/fsl-mc-bus.c
drivers/staging/fsl-mc/bus/fsl-mc-msi.c
drivers/staging/fsl-mc/bus/fsl-mc-private.h
drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
drivers/staging/fsl-mc/bus/mc-io.c
drivers/staging/fsl-mc/bus/mc-sys.c
drivers/staging/fsl-mc/include/dpaa2-fd.h
drivers/staging/fsl-mc/include/dpaa2-global.h
drivers/staging/fsl-mc/include/dpaa2-io.h
drivers/staging/fsl-mc/include/dpbp.h
drivers/staging/fsl-mc/include/dpcon.h
drivers/staging/fsl-mc/include/mc.h
drivers/staging/fsl-mc/overview.rst [new file with mode: 0644]
drivers/staging/fwserial/dma_fifo.c
drivers/staging/fwserial/dma_fifo.h
drivers/staging/fwserial/fwserial.c
drivers/staging/greybus/arche-apb-ctrl.c
drivers/staging/greybus/arche-platform.c
drivers/staging/greybus/audio_codec.c
drivers/staging/greybus/audio_codec.h
drivers/staging/greybus/authentication.c
drivers/staging/greybus/camera.c
drivers/staging/gs_fpgaboot/io.h
drivers/staging/iio/adc/ad7192.c
drivers/staging/iio/cdc/ad7152.c
drivers/staging/iio/cdc/ad7746.c
drivers/staging/iio/light/tsl2x7x.c
drivers/staging/iio/trigger/iio-trig-bfin-timer.c
drivers/staging/ipx/Kconfig [new file with mode: 0644]
drivers/staging/ipx/Makefile [new file with mode: 0644]
drivers/staging/ipx/TODO [new file with mode: 0644]
drivers/staging/ipx/af_ipx.c [new file with mode: 0644]
drivers/staging/ipx/ipx_proc.c [new file with mode: 0644]
drivers/staging/ipx/ipx_route.c [new file with mode: 0644]
drivers/staging/ipx/pe2.c [new file with mode: 0644]
drivers/staging/ipx/sysctl_net_ipx.c [new file with mode: 0644]
drivers/staging/irda/drivers/pxaficp_ir.c
drivers/staging/irda/net/irlmp.c
drivers/staging/ks7010/ks_wlan_net.c
drivers/staging/lustre/include/linux/libcfs/libcfs.h
drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h
drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
drivers/staging/lustre/include/linux/libcfs/libcfs_string.h
drivers/staging/lustre/include/linux/libcfs/libcfs_workitem.h [deleted file]
drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h
drivers/staging/lustre/include/linux/lnet/lib-lnet.h
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c
drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c
drivers/staging/lustre/lnet/libcfs/Makefile
drivers/staging/lustre/lnet/libcfs/fail.c
drivers/staging/lustre/lnet/libcfs/hash.c
drivers/staging/lustre/lnet/libcfs/libcfs_cpu.c
drivers/staging/lustre/lnet/libcfs/libcfs_lock.c
drivers/staging/lustre/lnet/libcfs/libcfs_mem.c
drivers/staging/lustre/lnet/libcfs/libcfs_string.c
drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c
drivers/staging/lustre/lnet/libcfs/linux/linux-module.c
drivers/staging/lustre/lnet/libcfs/module.c
drivers/staging/lustre/lnet/libcfs/prng.c [deleted file]
drivers/staging/lustre/lnet/libcfs/tracefile.c
drivers/staging/lustre/lnet/libcfs/workitem.c [deleted file]
drivers/staging/lustre/lnet/lnet/api-ni.c
drivers/staging/lustre/lnet/lnet/config.c
drivers/staging/lustre/lnet/lnet/lib-eq.c
drivers/staging/lustre/lnet/lnet/lib-md.c
drivers/staging/lustre/lnet/lnet/lib-me.c
drivers/staging/lustre/lnet/lnet/lib-move.c
drivers/staging/lustre/lnet/lnet/lib-msg.c
drivers/staging/lustre/lnet/lnet/lib-ptl.c
drivers/staging/lustre/lnet/lnet/lib-socket.c
drivers/staging/lustre/lnet/lnet/net_fault.c
drivers/staging/lustre/lnet/lnet/nidstrings.c
drivers/staging/lustre/lnet/lnet/peer.c
drivers/staging/lustre/lnet/lnet/router.c
drivers/staging/lustre/lnet/lnet/router_proc.c
drivers/staging/lustre/lnet/selftest/conctl.c
drivers/staging/lustre/lnet/selftest/conrpc.c
drivers/staging/lustre/lnet/selftest/console.c
drivers/staging/lustre/lnet/selftest/framework.c
drivers/staging/lustre/lnet/selftest/module.c
drivers/staging/lustre/lnet/selftest/rpc.c
drivers/staging/lustre/lnet/selftest/selftest.h
drivers/staging/lustre/lustre/fld/fld_cache.c
drivers/staging/lustre/lustre/include/lustre_disk.h
drivers/staging/lustre/lustre/include/lustre_sec.h
drivers/staging/lustre/lustre/include/obd_class.h
drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
drivers/staging/lustre/lustre/ldlm/ldlm_request.c
drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
drivers/staging/lustre/lustre/llite/dir.c
drivers/staging/lustre/lustre/llite/llite_internal.h
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/llite/super25.c
drivers/staging/lustre/lustre/llite/vvp_dev.c
drivers/staging/lustre/lustre/llite/vvp_io.c
drivers/staging/lustre/lustre/lov/lov_internal.h
drivers/staging/lustre/lustre/lov/lov_obd.c
drivers/staging/lustre/lustre/lov/lov_object.c
drivers/staging/lustre/lustre/lov/lov_request.c
drivers/staging/lustre/lustre/mgc/mgc_request.c
drivers/staging/lustre/lustre/obdclass/cl_lock.c
drivers/staging/lustre/lustre/obdclass/cl_object.c
drivers/staging/lustre/lustre/obdclass/cl_page.c
drivers/staging/lustre/lustre/obdclass/class_obd.c
drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
drivers/staging/lustre/lustre/obdclass/lu_object.c
drivers/staging/lustre/lustre/obdclass/lustre_handles.c
drivers/staging/lustre/lustre/obdclass/obd_config.c
drivers/staging/lustre/lustre/obdclass/obd_mount.c
drivers/staging/lustre/lustre/osc/osc_internal.h
drivers/staging/lustre/lustre/osc/osc_request.c
drivers/staging/lustre/lustre/ptlrpc/client.c
drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
drivers/staging/media/imx/imx-media-csi.c
drivers/staging/media/imx/imx-media-fim.c
drivers/staging/media/imx/imx-media.h
drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt [new file with mode: 0644]
drivers/staging/most/Documentation/driver_usage.txt
drivers/staging/most/Kconfig
drivers/staging/most/Makefile
drivers/staging/most/aim-cdev/Kconfig [deleted file]
drivers/staging/most/aim-cdev/Makefile [deleted file]
drivers/staging/most/aim-cdev/cdev.c [deleted file]
drivers/staging/most/aim-network/Kconfig [deleted file]
drivers/staging/most/aim-network/Makefile [deleted file]
drivers/staging/most/aim-network/networking.c [deleted file]
drivers/staging/most/aim-sound/Kconfig [deleted file]
drivers/staging/most/aim-sound/Makefile [deleted file]
drivers/staging/most/aim-sound/sound.c [deleted file]
drivers/staging/most/aim-v4l2/Kconfig [deleted file]
drivers/staging/most/aim-v4l2/Makefile [deleted file]
drivers/staging/most/aim-v4l2/video.c [deleted file]
drivers/staging/most/cdev/Kconfig [new file with mode: 0644]
drivers/staging/most/cdev/Makefile [new file with mode: 0644]
drivers/staging/most/cdev/cdev.c [new file with mode: 0644]
drivers/staging/most/core.c [new file with mode: 0644]
drivers/staging/most/core.h [new file with mode: 0644]
drivers/staging/most/dim2/Kconfig [new file with mode: 0644]
drivers/staging/most/dim2/Makefile [new file with mode: 0644]
drivers/staging/most/dim2/dim2.c [new file with mode: 0644]
drivers/staging/most/dim2/dim2.h [new file with mode: 0644]
drivers/staging/most/dim2/errors.h [new file with mode: 0644]
drivers/staging/most/dim2/hal.c [new file with mode: 0644]
drivers/staging/most/dim2/hal.h [new file with mode: 0644]
drivers/staging/most/dim2/reg.h [new file with mode: 0644]
drivers/staging/most/dim2/sysfs.c [new file with mode: 0644]
drivers/staging/most/dim2/sysfs.h [new file with mode: 0644]
drivers/staging/most/hdm-dim2/Kconfig [deleted file]
drivers/staging/most/hdm-dim2/Makefile [deleted file]
drivers/staging/most/hdm-dim2/dim2_errors.h [deleted file]
drivers/staging/most/hdm-dim2/dim2_hal.c [deleted file]
drivers/staging/most/hdm-dim2/dim2_hal.h [deleted file]
drivers/staging/most/hdm-dim2/dim2_hdm.c [deleted file]
drivers/staging/most/hdm-dim2/dim2_hdm.h [deleted file]
drivers/staging/most/hdm-dim2/dim2_reg.h [deleted file]
drivers/staging/most/hdm-dim2/dim2_sysfs.c [deleted file]
drivers/staging/most/hdm-dim2/dim2_sysfs.h [deleted file]
drivers/staging/most/hdm-i2c/Kconfig [deleted file]
drivers/staging/most/hdm-i2c/Makefile [deleted file]
drivers/staging/most/hdm-i2c/hdm_i2c.c [deleted file]
drivers/staging/most/hdm-usb/Kconfig [deleted file]
drivers/staging/most/hdm-usb/Makefile [deleted file]
drivers/staging/most/hdm-usb/hdm_usb.c [deleted file]
drivers/staging/most/i2c/Kconfig [new file with mode: 0644]
drivers/staging/most/i2c/Makefile [new file with mode: 0644]
drivers/staging/most/i2c/i2c.c [new file with mode: 0644]
drivers/staging/most/mostcore/Kconfig [deleted file]
drivers/staging/most/mostcore/Makefile [deleted file]
drivers/staging/most/mostcore/core.c [deleted file]
drivers/staging/most/mostcore/mostcore.h [deleted file]
drivers/staging/most/net/Kconfig [new file with mode: 0644]
drivers/staging/most/net/Makefile [new file with mode: 0644]
drivers/staging/most/net/net.c [new file with mode: 0644]
drivers/staging/most/sound/Kconfig [new file with mode: 0644]
drivers/staging/most/sound/Makefile [new file with mode: 0644]
drivers/staging/most/sound/sound.c [new file with mode: 0644]
drivers/staging/most/usb/Kconfig [new file with mode: 0644]
drivers/staging/most/usb/Makefile [new file with mode: 0644]
drivers/staging/most/usb/usb.c [new file with mode: 0644]
drivers/staging/most/video/Kconfig [new file with mode: 0644]
drivers/staging/most/video/Makefile [new file with mode: 0644]
drivers/staging/most/video/video.c [new file with mode: 0644]
drivers/staging/ncpfs/Kconfig [new file with mode: 0644]
drivers/staging/ncpfs/Makefile [new file with mode: 0644]
drivers/staging/ncpfs/TODO [new file with mode: 0644]
drivers/staging/ncpfs/dir.c [new file with mode: 0644]
drivers/staging/ncpfs/file.c [new file with mode: 0644]
drivers/staging/ncpfs/getopt.c [new file with mode: 0644]
drivers/staging/ncpfs/getopt.h [new file with mode: 0644]
drivers/staging/ncpfs/inode.c [new file with mode: 0644]
drivers/staging/ncpfs/ioctl.c [new file with mode: 0644]
drivers/staging/ncpfs/mmap.c [new file with mode: 0644]
drivers/staging/ncpfs/ncp_fs.h [new file with mode: 0644]
drivers/staging/ncpfs/ncp_fs_i.h [new file with mode: 0644]
drivers/staging/ncpfs/ncp_fs_sb.h [new file with mode: 0644]
drivers/staging/ncpfs/ncplib_kernel.c [new file with mode: 0644]
drivers/staging/ncpfs/ncplib_kernel.h [new file with mode: 0644]
drivers/staging/ncpfs/ncpsign_kernel.c [new file with mode: 0644]
drivers/staging/ncpfs/ncpsign_kernel.h [new file with mode: 0644]
drivers/staging/ncpfs/sock.c [new file with mode: 0644]
drivers/staging/ncpfs/symlink.c [new file with mode: 0644]
drivers/staging/nvec/nvec-keytable.h
drivers/staging/nvec/nvec.c
drivers/staging/nvec/nvec.h
drivers/staging/nvec/nvec_kbd.c
drivers/staging/nvec/nvec_paz00.c
drivers/staging/nvec/nvec_power.c
drivers/staging/nvec/nvec_ps2.c
drivers/staging/octeon/Makefile
drivers/staging/octeon/ethernet-defines.h
drivers/staging/octeon/ethernet-mdio.c
drivers/staging/octeon/ethernet-mdio.h
drivers/staging/octeon/ethernet-mem.c
drivers/staging/octeon/ethernet-mem.h
drivers/staging/octeon/ethernet-rgmii.c
drivers/staging/octeon/ethernet-rx.c
drivers/staging/octeon/ethernet-rx.h
drivers/staging/octeon/ethernet-sgmii.c
drivers/staging/octeon/ethernet-spi.c
drivers/staging/octeon/ethernet-tx.c
drivers/staging/octeon/ethernet-tx.h
drivers/staging/octeon/ethernet-util.h
drivers/staging/octeon/ethernet.c
drivers/staging/octeon/octeon-ethernet.h
drivers/staging/olpc_dcon/olpc_dcon.c
drivers/staging/olpc_dcon/olpc_dcon.h
drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts
drivers/staging/pi433/Documentation/pi433.txt
drivers/staging/pi433/pi433_if.c
drivers/staging/pi433/pi433_if.h
drivers/staging/pi433/rf69.c
drivers/staging/pi433/rf69.h
drivers/staging/pi433/rf69_enum.h
drivers/staging/pi433/rf69_registers.h
drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
drivers/staging/rtl8188eu/hal/pwrseqcmd.c
drivers/staging/rtl8192e/rtllib_rx.c
drivers/staging/rtl8192e/rtllib_softmac.c
drivers/staging/rtl8192u/ieee80211/dot11d.c
drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8192u/r8192U_core.c
drivers/staging/rtl8712/hal_init.c
drivers/staging/rtl8712/ieee80211.c
drivers/staging/rtl8712/os_intfs.c
drivers/staging/rtl8712/rtl8712_cmd.c
drivers/staging/rtl8712/rtl8712_recv.c
drivers/staging/rtl8712/rtl8712_xmit.c
drivers/staging/rtl8712/rtl871x_cmd.c
drivers/staging/rtl8712/rtl871x_ioctl_linux.c
drivers/staging/rtl8712/rtl871x_ioctl_set.c
drivers/staging/rtl8712/rtl871x_mlme.c
drivers/staging/rtl8712/rtl871x_mlme.h
drivers/staging/rtl8712/rtl871x_mp.c
drivers/staging/rtl8712/rtl871x_security.c
drivers/staging/rtl8712/usb_ops_linux.c
drivers/staging/rtl8723bs/core/rtw_cmd.c
drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c
drivers/staging/rtl8723bs/hal/HalPwrSeqCmd.c
drivers/staging/rtl8723bs/hal/hal_com_phycfg.c
drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
drivers/staging/rtl8723bs/hal/sdio_ops.c
drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
drivers/staging/rtlwifi/Kconfig
drivers/staging/rtlwifi/btcoexist/halbtcoutsrc.c
drivers/staging/rtlwifi/cam.c
drivers/staging/rtlwifi/core.c
drivers/staging/rtlwifi/rtl8822be/fw.c
drivers/staging/rtlwifi/wifi.h
drivers/staging/rts5208/ms.c
drivers/staging/rts5208/rtsx.c
drivers/staging/rts5208/rtsx.h
drivers/staging/rts5208/sd.h
drivers/staging/sm750fb/TODO
drivers/staging/sm750fb/ddk750_sii164.c
drivers/staging/sm750fb/ddk750_sii164.h
drivers/staging/sm750fb/sm750_hw.c
drivers/staging/speakup/buffers.c
drivers/staging/speakup/fakekey.c
drivers/staging/speakup/keyhelp.c
drivers/staging/speakup/kobjects.c
drivers/staging/speakup/main.c
drivers/staging/speakup/selection.c
drivers/staging/speakup/serialio.c
drivers/staging/speakup/speakup_acntpc.c
drivers/staging/speakup/speakup_acntsa.c
drivers/staging/speakup/speakup_apollo.c
drivers/staging/speakup/speakup_audptr.c
drivers/staging/speakup/speakup_bns.c
drivers/staging/speakup/speakup_decext.c
drivers/staging/speakup/speakup_decpc.c
drivers/staging/speakup/speakup_dectlk.c
drivers/staging/speakup/speakup_dtlk.c
drivers/staging/speakup/speakup_dummy.c
drivers/staging/speakup/speakup_keypc.c
drivers/staging/speakup/speakup_ltlk.c
drivers/staging/speakup/speakup_soft.c
drivers/staging/speakup/speakup_spkout.c
drivers/staging/speakup/speakup_txprt.c
drivers/staging/speakup/spk_priv.h
drivers/staging/speakup/spk_priv_keyinfo.h
drivers/staging/speakup/spk_ttyio.c
drivers/staging/speakup/synth.c
drivers/staging/speakup/thread.c
drivers/staging/speakup/varhandlers.c
drivers/staging/typec/tcpci.c
drivers/staging/typec/tcpci.h
drivers/staging/unisys/Kconfig
drivers/staging/unisys/Makefile
drivers/staging/unisys/include/iochannel.h
drivers/staging/unisys/include/visorbus.h [deleted file]
drivers/staging/unisys/include/visorchannel.h [deleted file]
drivers/staging/unisys/visorbus/Kconfig [deleted file]
drivers/staging/unisys/visorbus/Makefile [deleted file]
drivers/staging/unisys/visorbus/controlvmchannel.h [deleted file]
drivers/staging/unisys/visorbus/vbuschannel.h [deleted file]
drivers/staging/unisys/visorbus/visorbus_main.c [deleted file]
drivers/staging/unisys/visorbus/visorbus_private.h [deleted file]
drivers/staging/unisys/visorbus/visorchannel.c [deleted file]
drivers/staging/unisys/visorbus/visorchipset.c [deleted file]
drivers/staging/unisys/visorhba/visorhba_main.c
drivers/staging/unisys/visorinput/ultrainputreport.h
drivers/staging/unisys/visorinput/visorinput.c
drivers/staging/unisys/visornic/visornic_main.c
drivers/staging/vboxvideo/vbox_fb.c
drivers/staging/vboxvideo/vbox_main.c
drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h
drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h
drivers/staging/vc04_services/bcm2835-camera/controls.c
drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c
drivers/staging/vme/devices/vme_user.c
drivers/staging/vt6655/baseband.c
drivers/staging/vt6655/baseband.h
drivers/staging/vt6655/card.c
drivers/staging/vt6655/card.h
drivers/staging/vt6655/channel.c
drivers/staging/vt6655/channel.h
drivers/staging/vt6655/desc.h
drivers/staging/vt6655/device.h
drivers/staging/vt6655/device_cfg.h
drivers/staging/vt6655/device_main.c
drivers/staging/vt6655/dpc.c
drivers/staging/vt6655/dpc.h
drivers/staging/vt6655/key.c
drivers/staging/vt6655/key.h
drivers/staging/vt6655/mac.c
drivers/staging/vt6655/mac.h
drivers/staging/vt6655/power.c
drivers/staging/vt6655/power.h
drivers/staging/vt6655/rf.c
drivers/staging/vt6655/rf.h
drivers/staging/vt6655/rxtx.c
drivers/staging/vt6655/rxtx.h
drivers/staging/vt6655/srom.c
drivers/staging/vt6655/srom.h
drivers/staging/vt6655/tmacro.h
drivers/staging/vt6655/upc.h
drivers/staging/vt6656/baseband.c
drivers/staging/vt6656/baseband.h
drivers/staging/vt6656/card.c
drivers/staging/vt6656/card.h
drivers/staging/vt6656/channel.c
drivers/staging/vt6656/channel.h
drivers/staging/vt6656/desc.h
drivers/staging/vt6656/device.h
drivers/staging/vt6656/dpc.c
drivers/staging/vt6656/dpc.h
drivers/staging/vt6656/firmware.c
drivers/staging/vt6656/firmware.h
drivers/staging/vt6656/int.c
drivers/staging/vt6656/int.h
drivers/staging/vt6656/key.c
drivers/staging/vt6656/key.h
drivers/staging/vt6656/mac.c
drivers/staging/vt6656/mac.h
drivers/staging/vt6656/main_usb.c
drivers/staging/vt6656/power.c
drivers/staging/vt6656/power.h
drivers/staging/vt6656/rf.c
drivers/staging/vt6656/rf.h
drivers/staging/vt6656/rxtx.c
drivers/staging/vt6656/rxtx.h
drivers/staging/vt6656/usbpipe.c
drivers/staging/vt6656/usbpipe.h
drivers/staging/vt6656/wcmd.c
drivers/staging/vt6656/wcmd.h
drivers/staging/wilc1000/coreconfigurator.c
drivers/staging/wilc1000/host_interface.c
drivers/staging/wilc1000/linux_wlan.c
drivers/staging/wilc1000/wilc_debugfs.c
drivers/staging/wilc1000/wilc_sdio.c
drivers/staging/wilc1000/wilc_spi.c
drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
drivers/staging/wilc1000/wilc_wfi_netdevice.h
drivers/staging/wilc1000/wilc_wlan.c
drivers/staging/wilc1000/wilc_wlan_cfg.c
drivers/staging/wilc1000/wilc_wlan_if.h
drivers/staging/wlan-ng/hfa384x.h
drivers/staging/wlan-ng/hfa384x_usb.c
drivers/staging/wlan-ng/p80211conv.c
drivers/staging/wlan-ng/p80211conv.h
drivers/staging/wlan-ng/p80211hdr.h
drivers/staging/wlan-ng/p80211ioctl.h
drivers/staging/wlan-ng/p80211metadef.h
drivers/staging/wlan-ng/p80211metastruct.h
drivers/staging/wlan-ng/p80211mgmt.h
drivers/staging/wlan-ng/p80211msg.h
drivers/staging/wlan-ng/p80211netdev.c
drivers/staging/wlan-ng/p80211netdev.h
drivers/staging/wlan-ng/p80211req.c
drivers/staging/wlan-ng/p80211req.h
drivers/staging/wlan-ng/p80211types.h
drivers/staging/wlan-ng/p80211wep.c
drivers/staging/wlan-ng/prism2fw.c
drivers/staging/wlan-ng/prism2mgmt.c
drivers/staging/wlan-ng/prism2mgmt.h
drivers/staging/wlan-ng/prism2mib.c
drivers/staging/wlan-ng/prism2sta.c
drivers/staging/xgifb/XGI_main.h
drivers/staging/xgifb/XGI_main_26.c
drivers/staging/xgifb/vb_setmode.c
drivers/staging/xgifb/vb_table.h
drivers/visorbus/Kconfig [new file with mode: 0644]
drivers/visorbus/Makefile [new file with mode: 0644]
drivers/visorbus/controlvmchannel.h [new file with mode: 0644]
drivers/visorbus/vbuschannel.h [new file with mode: 0644]
drivers/visorbus/visorbus_main.c [new file with mode: 0644]
drivers/visorbus/visorbus_private.h [new file with mode: 0644]
drivers/visorbus/visorchannel.c [new file with mode: 0644]
drivers/visorbus/visorchipset.c [new file with mode: 0644]
fs/Kconfig
fs/Makefile
fs/ncpfs/Kconfig [deleted file]
fs/ncpfs/Makefile [deleted file]
fs/ncpfs/dir.c [deleted file]
fs/ncpfs/file.c [deleted file]
fs/ncpfs/getopt.c [deleted file]
fs/ncpfs/getopt.h [deleted file]
fs/ncpfs/inode.c [deleted file]
fs/ncpfs/ioctl.c [deleted file]
fs/ncpfs/mmap.c [deleted file]
fs/ncpfs/ncp_fs.h [deleted file]
fs/ncpfs/ncp_fs_i.h [deleted file]
fs/ncpfs/ncp_fs_sb.h [deleted file]
fs/ncpfs/ncplib_kernel.c [deleted file]
fs/ncpfs/ncplib_kernel.h [deleted file]
fs/ncpfs/ncpsign_kernel.c [deleted file]
fs/ncpfs/ncpsign_kernel.h [deleted file]
fs/ncpfs/sock.c [deleted file]
fs/ncpfs/symlink.c [deleted file]
include/linux/iio/iio.h
include/linux/iio/machine.h
include/linux/iio/trigger.h
include/linux/visorbus.h [new file with mode: 0644]
kernel/workqueue.c
net/Kconfig
net/Makefile
net/ipx/Kconfig [deleted file]
net/ipx/Makefile [deleted file]
net/ipx/af_ipx.c [deleted file]
net/ipx/ipx_proc.c [deleted file]
net/ipx/ipx_route.c [deleted file]
net/ipx/pe2.c [deleted file]
net/ipx/sysctl_net_ipx.c [deleted file]

index 2e3f919485f49f8a11904614bafb99e74404c51a..6a5f34b4d5b96d1a522ee4172b3712677e659060 100644 (file)
@@ -32,7 +32,7 @@ Description:
                Description of the physical chip / device for device X.
                Typically a part number.
 
-What:          /sys/bus/iio/devices/iio:deviceX/timestamp_clock
+What:          /sys/bus/iio/devices/iio:deviceX/current_timestamp_clock
 KernelVersion: 4.5
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -1290,7 +1290,7 @@ KernelVersion:    3.4
 Contact:       linux-iio@vger.kernel.org
 Description:
                Unit-less light intensity. Modifiers both and ir indicate
-               that measurements contains visible and infrared light
+               that measurements contain visible and infrared light
                components or just infrared light, respectively. Modifier uv indicates
                that measurements contain ultraviolet light components.
 
@@ -1413,6 +1413,16 @@ Description:
                the available samples after the timeout expires and thus have a
                maximum delay guarantee.
 
+What:          /sys/bus/iio/devices/iio:deviceX/buffer/data_available
+KernelVersion: 4.16
+Contact:       linux-iio@vger.kernel.org
+Description:
+               A read-only value indicating the bytes of data available in the
+               buffer. In the case of an output buffer, this indicates the
+               amount of empty space available to write data to. In the case of
+               an input buffer, this indicates the amount of data available for
+               reading.
+
 What:          /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_enabled
 KernelVersion: 4.2
 Contact:       linux-iio@vger.kernel.org
index f413e82c8b837516ec5c72196fc19e43839dfd02..1e6ee3deb4fa214bfca84403d4da1c05df4f1121 100644 (file)
@@ -15,7 +15,6 @@ Required properties:
                        - "clkin" for the reference clock (typically XTAL)
                        - "core" for the SAR ADC core clock
                optional clocks:
-                       - "sana" for the analog clock
                        - "adc_clk" for the ADC (sampling) clock
                        - "adc_sel" for the ADC (sampling) clock mux
 - vref-supply: the regulator supply for the ADC reference voltage
index 674e133b7cd7d72aeb81efb4f7cb304ce0204644..034fc2ba100e7924dfafcc93ffbb0ed66a5c1609 100644 (file)
@@ -8,6 +8,7 @@ Required properties:
 - reg: memory window mapping address and length
 - clocks: Input clock used to derive the sample clock. Expected to be the
           SoC's APB clock.
+- resets: Reset controller phandle
 - #io-channel-cells: Must be set to <1> to indicate channels are selected
                      by index.
 
@@ -15,6 +16,7 @@ Example:
        adc@1e6e9000 {
                compatible = "aspeed,ast2400-adc";
                reg = <0x1e6e9000 0xb0>;
-               clocks = <&clk_apb>;
+               clocks = <&syscon ASPEED_CLK_APB>;
+               resets = <&syscon ASPEED_RESET_ADC>;
                #io-channel-cells = <1>;
        };
index 552e7a83951d774bacb1b9e0211b72b766bbb7fa..6469a4cd2a6d73d1c01fa0effa8e7425cef9fa27 100644 (file)
@@ -17,6 +17,11 @@ Required properties:
   This property uses the IRQ edge types values: IRQ_TYPE_EDGE_RISING ,
   IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH
 
+Optional properties:
+  - dmas: Phandle to dma channel for the ADC.
+  - dma-names: Must be "rx" when dmas property is being used.
+  See ../../dma/dma.txt for details.
+
 Example:
 
 adc: adc@fc030000 {
@@ -31,4 +36,6 @@ adc: adc@fc030000 {
        vddana-supply = <&vdd_3v3_lp_reg>;
        vref-supply = <&vdd_3v3_lp_reg>;
        atmel,trigger-edge-type = <IRQ_TYPE_EDGE_BOTH>;
+       dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(25))>;
+       dma-names = "rx";
 }
index 48bfcaa3ffcdd6e04e4acb8c60c62344e1b677fc..e8bb8243e92c1c2a54090ab397e45f8bfbd55e5f 100644 (file)
@@ -62,6 +62,15 @@ Required properties:
 - st,adc-channels: List of single-ended channels muxed for this ADC.
   It can have up to 16 channels on stm32f4 or 20 channels on stm32h7, numbered
   from 0 to 15 or 19 (resp. for in0..in15 or in0..in19).
+- st,adc-diff-channels: List of differential channels muxed for this ADC.
+  Depending on part used, some channels can be configured as differential
+  instead of single-ended (e.g. stm32h7). List here positive and negative
+  inputs pairs as <vinp vinn>, <vinp vinn>,... vinp and vinn are numbered
+  from 0 to 19 on stm32h7)
+  Note: At least one of "st,adc-channels" or "st,adc-diff-channels" is required.
+  Both properties can be used together. Some channels can be used as
+  single-ended and some other ones as differential (mixed). But channels
+  can't be configured both as single-ended and differential (invalid).
 - #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
   Documentation/devicetree/bindings/iio/iio-bindings.txt
 
@@ -111,3 +120,18 @@ Example:
                ...
                other adc child nodes follow...
        };
+
+Example to setup:
+- channel 1 as single-ended
+- channels 2 & 3 as differential (with resp. 6 & 7 negative inputs)
+
+       adc: adc@40022000 {
+               compatible = "st,stm32h7-adc-core";
+               ...
+               adc1: adc@0 {
+                       compatible = "st,stm32h7-adc";
+                       ...
+                       st,adc-channels = <1>;
+                       st,adc-diff-channels = <2 6>, <3 7>;
+               };
+       };
index 8629c18b0e78fb1fd665464f661cee9f4cfef091..ef2ca0a0306fdee1ce8d71ffb6684d3b25626d3e 100644 (file)
@@ -1,9 +1,11 @@
 Maxim MAX30102 heart rate and pulse oximeter sensor
+Maxim MAX30105 optical particle-sensing module
 
 * https://datasheets.maximintegrated.com/en/ds/MAX30102.pdf
+* https://datasheets.maximintegrated.com/en/ds/MAX30105.pdf
 
 Required properties:
-  - compatible: must be "maxim,max30102"
+  - compatible: must be "maxim,max30102" or "maxim,max30105"
   - reg: the I2C address of the sensor
   - interrupt-parent: should be the phandle for the interrupt controller
   - interrupts: the sole interrupt generated by the device
@@ -12,8 +14,10 @@ Required properties:
   interrupt client node bindings.
 
 Optional properties:
-  - maxim,red-led-current-microamp: configuration for RED LED current
+  - maxim,red-led-current-microamp: configuration for red LED current
   - maxim,ir-led-current-microamp: configuration for IR LED current
+  - maxim,green-led-current-microamp: configuration for green LED current
+    (max30105 only)
 
     Note that each step is approximately 200 microamps, ranging from 0 uA to
     50800 uA.
diff --git a/Documentation/devicetree/bindings/iio/light/uvis25.txt b/Documentation/devicetree/bindings/iio/light/uvis25.txt
new file mode 100644 (file)
index 0000000..3041207
--- /dev/null
@@ -0,0 +1,23 @@
+* ST UVIS25 uv sensor
+
+Required properties:
+- compatible: should be "st,uvis25"
+- reg: i2c address of the sensor / spi cs line
+
+Optional properties:
+- interrupt-parent: should be the phandle for the interrupt controller
+- interrupts: interrupt mapping for IRQ. It should be configured with
+  flags IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or
+  IRQ_TYPE_EDGE_FALLING.
+
+  Refer to interrupt-controller/interrupts.txt for generic interrupt
+  client node bindings.
+
+Example:
+
+uvis25@47 {
+       compatible = "st,uvis25";
+       reg = <0x47>;
+       interrupt-parent = <&gpio0>;
+       interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+};
index 48c7ff07bfdc4e29cfb3d055d1a2b5431487a468..64c47587d1d4e5cee40cd573e4efd5f62a1377e0 100644 (file)
@@ -270,6 +270,7 @@ ACCES 104-QUAD-8 IIO DRIVER
 M:     William Breathitt Gray <vilhelm.gray@gmail.com>
 L:     linux-iio@vger.kernel.org
 S:     Maintained
+F:     Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8
 F:     drivers/iio/counter/104-quad-8.c
 
 ACCES PCI-IDIO-16 GPIO DRIVER
@@ -859,6 +860,8 @@ M:  Michael Hennerich <Michael.Hennerich@analog.com>
 W:     http://wiki.analog.com/
 W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
+F:     Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523
+F:     Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350
 F:     drivers/iio/*/ad*
 F:     drivers/iio/adc/ltc2497*
 X:     drivers/iio/*/adjd*
@@ -4145,6 +4148,7 @@ DEVANTECH SRF ULTRASONIC RANGER IIO DRIVER
 M:     Andreas Klinger <ak@it-klinger.de>
 L:     linux-iio@vger.kernel.org
 S:     Maintained
+F:     Documentation/ABI/testing/sysfs-bus-iio-distance-srf08
 F:     drivers/iio/proximity/srf*.c
 
 DEVICE COREDUMP (DEV_COREDUMP)
@@ -6850,6 +6854,8 @@ R:        Peter Meerwald-Stadler <pmeerw@pmeerw.net>
 L:     linux-iio@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
 S:     Maintained
+F:     Documentation/ABI/testing/configfs-iio*
+F:     Documentation/ABI/testing/sysfs-bus-iio*
 F:     Documentation/devicetree/bindings/iio/
 F:     drivers/iio/
 F:     drivers/staging/iio/
@@ -7331,17 +7337,16 @@ F:      drivers/tty/ipwireless/
 
 IPX NETWORK LAYER
 L:     netdev@vger.kernel.org
-S:     Odd fixes
-F:     include/net/ipx.h
+S:     Obsolete
 F:     include/uapi/linux/ipx.h
-F:     net/ipx/
+F:     drivers/staging/ipx/
 
 IRDA SUBSYSTEM
 M:     Samuel Ortiz <samuel@sortiz.org>
 L:     irda-users@lists.sourceforge.net (subscribers-only)
 L:     netdev@vger.kernel.org
 W:     http://irda.sourceforge.net/
-S:     Maintained
+S:     Obsolete
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/irda-2.6.git
 F:     Documentation/networking/irda.txt
 F:     drivers/staging/irda/
@@ -9408,8 +9413,8 @@ F:        drivers/net/ethernet/natsemi/natsemi.c
 
 NCP FILESYSTEM
 M:     Petr Vandrovec <petr@vandrovec.name>
-S:     Odd Fixes
-F:     fs/ncpfs/
+S:     Obsolete
+F:     drivers/staging/ncpfs/
 
 NCR 5380 SCSI DRIVERS
 M:     Finn Thain <fthain@telegraphics.com.au>
@@ -14119,6 +14124,8 @@ UNISYS S-PAR DRIVERS
 M:     David Kershner <david.kershner@unisys.com>
 L:     sparmaintainer@unisys.com (Unisys internal)
 S:     Supported
+F:     include/linux/visorbus.h
+F:     drivers/visorbus/
 F:     drivers/staging/unisys/
 
 UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
index 152744c5ef0f394afe1c32971053fd796b9fc6aa..ef5fb8395d76d0c726f2f2ce8c03bde0d9ccb694 100644 (file)
@@ -211,4 +211,6 @@ source "drivers/mux/Kconfig"
 
 source "drivers/opp/Kconfig"
 
+source "drivers/visorbus/Kconfig"
+
 endmenu
index e06f7f633f73ff285c64e19b89041d17e2be23ce..7a2330077e4721ae485a4f5e94ac91438d938b83 100644 (file)
@@ -184,3 +184,4 @@ obj-$(CONFIG_FPGA)          += fpga/
 obj-$(CONFIG_FSI)              += fsi/
 obj-$(CONFIG_TEE)              += tee/
 obj-$(CONFIG_MULTIPLEXER)      += mux/
+obj-$(CONFIG_UNISYS_VISORBUS)  += visorbus/
index f85014fbaa1297ea32e3a847df5fb8c6ff4f9923..8ffc308d5fd052bf73d52ba4d5bb5e1180c51fde 100644 (file)
@@ -81,9 +81,21 @@ static const struct i2c_device_id bmc150_accel_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, bmc150_accel_id);
 
+static const struct of_device_id bmc150_accel_of_match[] = {
+       { .compatible = "bosch,bmc150_accel" },
+       { .compatible = "bosch,bmi055_accel" },
+       { .compatible = "bosch,bma255" },
+       { .compatible = "bosch,bma250e" },
+       { .compatible = "bosch,bma222e" },
+       { .compatible = "bosch,bma280" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, bmc150_accel_of_match);
+
 static struct i2c_driver bmc150_accel_driver = {
        .driver = {
                .name   = "bmc150_accel_i2c",
+               .of_match_table = bmc150_accel_of_match,
                .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
                .pm     = &bmc150_accel_pm_ops,
        },
index 6c214783241c0a3363f8c19d879e5b122b32a783..d4b555203427837b55f700845739b1981365007f 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/acpi.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/byteorder/generic.h>
@@ -25,7 +26,7 @@
 #define DA280_MODE_ENABLE              0x1e
 #define DA280_MODE_DISABLE             0x9e
 
-enum { da226, da280 };
+enum da280_chipset { da226, da280 };
 
 /*
  * a value of + or -4096 corresponds to + or - 1G
@@ -91,12 +92,24 @@ static const struct iio_info da280_info = {
        .read_raw       = da280_read_raw,
 };
 
+static enum da280_chipset da280_match_acpi_device(struct device *dev)
+{
+       const struct acpi_device_id *id;
+
+       id = acpi_match_device(dev->driver->acpi_match_table, dev);
+       if (!id)
+               return -EINVAL;
+
+       return (enum da280_chipset) id->driver_data;
+}
+
 static int da280_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        int ret;
        struct iio_dev *indio_dev;
        struct da280_data *data;
+       enum da280_chipset chip;
 
        ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
        if (ret != DA280_CHIP_ID)
@@ -114,7 +127,14 @@ static int da280_probe(struct i2c_client *client,
        indio_dev->info = &da280_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = da280_channels;
-       if (id->driver_data == da226) {
+
+       if (ACPI_HANDLE(&client->dev)) {
+               chip = da280_match_acpi_device(&client->dev);
+       } else {
+               chip = id->driver_data;
+       }
+
+       if (chip == da226) {
                indio_dev->name = "da226";
                indio_dev->num_channels = 2;
        } else {
@@ -158,6 +178,12 @@ static int da280_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume);
 
+static const struct acpi_device_id da280_acpi_match[] = {
+       {"MIRAACC", da280},
+       {},
+};
+MODULE_DEVICE_TABLE(acpi, da280_acpi_match);
+
 static const struct i2c_device_id da280_i2c_id[] = {
        { "da226", da226 },
        { "da280", da280 },
@@ -168,6 +194,7 @@ MODULE_DEVICE_TABLE(i2c, da280_i2c_id);
 static struct i2c_driver da280_driver = {
        .driver = {
                .name = "da280",
+               .acpi_match_table = ACPI_PTR(da280_acpi_match),
                .pm = &da280_pm_ops,
        },
        .probe          = da280_probe,
index 98fbb628d5bdd13a5f0fb85ff37d1dd776db5a0f..38411e1c155bd38c93ba0d559b4f5f0c025594ed 100644 (file)
@@ -63,3 +63,6 @@ static struct i2c_driver kxsd9_i2c_driver = {
        .id_table       = kxsd9_i2c_id,
 };
 module_i2c_driver(kxsd9_i2c_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("KXSD9 accelerometer I2C interface");
index bfd4bc806fc26ba4047cbb9f9aab780bc5d3a0e7..7a2da7f9d4dcf33ee6ee28aaf30c9d61e2a455da 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * mma8452.c - Support for following Freescale / NXP 3-axis accelerometers:
  *
@@ -13,9 +14,6 @@
  * Copyright 2015 Martin Kepplinger <martink@posteo.de>
  * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
  *
- * This file is subject to the terms and conditions of version 2 of
- * the GNU General Public License.  See the file COPYING in the main
- * directory of this archive for more details.
  *
  * TODO: orientation events
  */
@@ -135,7 +133,7 @@ struct mma8452_event_regs {
                u8 ev_count;
 };
 
-static const struct mma8452_event_regs ev_regs_accel_falling = {
+static const struct mma8452_event_regs ff_mt_ev_regs = {
                .ev_cfg = MMA8452_FF_MT_CFG,
                .ev_cfg_ele = MMA8452_FF_MT_CFG_ELE,
                .ev_cfg_chan_shift = MMA8452_FF_MT_CHAN_SHIFT,
@@ -145,7 +143,7 @@ static const struct mma8452_event_regs ev_regs_accel_falling = {
                .ev_count = MMA8452_FF_MT_COUNT
 };
 
-static const struct mma8452_event_regs ev_regs_accel_rising = {
+static const struct mma8452_event_regs trans_ev_regs = {
                .ev_cfg = MMA8452_TRANSIENT_CFG,
                .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
                .ev_cfg_chan_shift = MMA8452_TRANSIENT_CHAN_SHIFT,
@@ -284,7 +282,7 @@ static const int mma8452_samp_freq[8][2] = {
 };
 
 /* Datasheet table: step time "Relationship with the ODR" (sample frequency) */
-static const unsigned int mma8452_transient_time_step_us[4][8] = {
+static const unsigned int mma8452_time_step_us[4][8] = {
        { 1250, 2500, 5000, 10000, 20000, 20000, 20000, 20000 },  /* normal */
        { 1250, 2500, 5000, 10000, 20000, 80000, 80000, 80000 },  /* l p l n */
        { 1250, 2500, 2500, 2500, 2500, 2500, 2500, 2500 },       /* high res*/
@@ -777,12 +775,12 @@ static int mma8452_get_event_regs(struct mma8452_data *data,
                                        & MMA8452_INT_TRANS) &&
                                (data->chip_info->enabled_events
                                        & MMA8452_INT_TRANS))
-                               *ev_reg = &ev_regs_accel_rising;
+                               *ev_reg = &trans_ev_regs;
                        else
-                               *ev_reg = &ev_regs_accel_falling;
+                               *ev_reg = &ff_mt_ev_regs;
                        return 0;
                case IIO_EV_DIR_FALLING:
-                       *ev_reg = &ev_regs_accel_falling;
+                       *ev_reg = &ff_mt_ev_regs;
                        return 0;
                default:
                        return -EINVAL;
@@ -826,7 +824,7 @@ static int mma8452_read_event_value(struct iio_dev *indio_dev,
                if (power_mode < 0)
                        return power_mode;
 
-               us = ret * mma8452_transient_time_step_us[power_mode][
+               us = ret * mma8452_time_step_us[power_mode][
                                mma8452_get_odr_index(data)];
                *val = us / USEC_PER_SEC;
                *val2 = us % USEC_PER_SEC;
@@ -883,7 +881,7 @@ static int mma8452_write_event_value(struct iio_dev *indio_dev,
                        return ret;
 
                steps = (val * USEC_PER_SEC + val2) /
-                               mma8452_transient_time_step_us[ret][
+                               mma8452_time_step_us[ret][
                                        mma8452_get_odr_index(data)];
 
                if (steps < 0 || steps > 0xff)
index 460aa58e0159dabc9c228cac2f07da949ad1b4e4..6fe995cf16a6a7eb49403784dcaf0ffe25f65a64 100644 (file)
@@ -920,8 +920,6 @@ static const struct iio_trigger_ops st_accel_trigger_ops = {
 int st_accel_common_probe(struct iio_dev *indio_dev)
 {
        struct st_sensor_data *adata = iio_priv(indio_dev);
-       struct st_sensors_platform_data *pdata =
-               (struct st_sensors_platform_data *)adata->dev->platform_data;
        int irq = adata->get_irq_data_ready(indio_dev);
        int err;
 
@@ -948,9 +946,6 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
                                        &adata->sensor_settings->fs.fs_avl[0];
        adata->odr = adata->sensor_settings->odr.odr_avl[0].hz;
 
-       if (!pdata)
-               pdata = (struct st_sensors_platform_data *)&default_accel_pdata;
-
        err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data);
        if (err < 0)
                goto st_accel_power_off;
index 39e3b345a6c8403300ca52b6f885d6c295a577c9..72bc2b71765ae2ff4a0199e0e507c1944ba74593 100644 (file)
@@ -158,6 +158,7 @@ config AT91_SAMA5D2_ADC
        tristate "Atmel AT91 SAMA5D2 ADC"
        depends on ARCH_AT91 || COMPILE_TEST
        depends on HAS_IOMEM
+       depends on HAS_DMA
        select IIO_TRIGGERED_BUFFER
        help
          Say yes here to build support for Atmel SAMA5D2 ADC which is
@@ -318,6 +319,8 @@ config HI8435
 config HX711
        tristate "AVIA HX711 ADC for weight cells"
        depends on GPIOLIB
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
        help
          If you say yes here you get support for AVIA HX711 ADC which is used
          for weigh cells
index 8a958d5f1905cf0d4b98ffbe1e0db0f27ac6df18..327a49ba19916e1405c41980ef7677f5bf7a8bdb 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/reset.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
@@ -53,11 +54,12 @@ struct aspeed_adc_model_data {
 };
 
 struct aspeed_adc_data {
-       struct device   *dev;
-       void __iomem    *base;
-       spinlock_t      clk_lock;
-       struct clk_hw   *clk_prescaler;
-       struct clk_hw   *clk_scaler;
+       struct device           *dev;
+       void __iomem            *base;
+       spinlock_t              clk_lock;
+       struct clk_hw           *clk_prescaler;
+       struct clk_hw           *clk_scaler;
+       struct reset_control    *rst;
 };
 
 #define ASPEED_CHAN(_idx, _data_reg_addr) {                    \
@@ -217,6 +219,15 @@ static int aspeed_adc_probe(struct platform_device *pdev)
                goto scaler_error;
        }
 
+       data->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+       if (IS_ERR(data->rst)) {
+               dev_err(&pdev->dev,
+                       "invalid or missing reset controller device tree entry");
+               ret = PTR_ERR(data->rst);
+               goto reset_error;
+       }
+       reset_control_deassert(data->rst);
+
        model_data = of_device_get_match_data(&pdev->dev);
 
        if (model_data->wait_init_sequence) {
@@ -263,9 +274,10 @@ iio_register_error:
        writel(ASPEED_OPERATION_MODE_POWER_DOWN,
                data->base + ASPEED_REG_ENGINE_CONTROL);
        clk_disable_unprepare(data->clk_scaler->clk);
+reset_error:
+       reset_control_assert(data->rst);
 clk_enable_error:
        clk_hw_unregister_divider(data->clk_scaler);
-
 scaler_error:
        clk_hw_unregister_divider(data->clk_prescaler);
        return ret;
@@ -280,6 +292,7 @@ static int aspeed_adc_remove(struct platform_device *pdev)
        writel(ASPEED_OPERATION_MODE_POWER_DOWN,
                data->base + ASPEED_REG_ENGINE_CONTROL);
        clk_disable_unprepare(data->clk_scaler->clk);
+       reset_control_assert(data->rst);
        clk_hw_unregister_divider(data->clk_scaler);
        clk_hw_unregister_divider(data->clk_prescaler);
 
index 755a493c2a2c4206cbc5650d318594750ad89132..4eff8351ce2994c51483964f2b4345e57b2e7056 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <linux/bitops.h>
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #define AT91_SAMA5D2_LCDR      0x20
 /* Interrupt Enable Register */
 #define AT91_SAMA5D2_IER       0x24
+/* Interrupt Enable Register - general overrun error */
+#define AT91_SAMA5D2_IER_GOVRE BIT(25)
 /* Interrupt Disable Register */
 #define AT91_SAMA5D2_IDR       0x28
 /* Interrupt Mask Register */
 
 /*
  * Maximum number of bytes to hold conversion from all channels
- * plus the timestamp
+ * without the timestamp.
  */
-#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT +         \
-                               AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8)
+#define AT91_BUFFER_MAX_CONVERSION_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
+                                        AT91_SAMA5D2_DIFF_CHAN_CNT) * 2)
+
+/* This total must also include the timestamp */
+#define AT91_BUFFER_MAX_BYTES (AT91_BUFFER_MAX_CONVERSION_BYTES + 8)
 
 #define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
 
+#define AT91_HWFIFO_MAX_SIZE_STR       "128"
+#define AT91_HWFIFO_MAX_SIZE           128
+
 #define AT91_SAMA5D2_CHAN_SINGLE(num, addr)                            \
        {                                                               \
                .type = IIO_VOLTAGE,                                    \
@@ -228,6 +238,28 @@ struct at91_adc_trigger {
        bool                            hw_trig;
 };
 
+/**
+ * at91_adc_dma - at91-sama5d2 dma information struct
+ * @dma_chan:          the dma channel acquired
+ * @rx_buf:            dma coherent allocated area
+ * @rx_dma_buf:                dma handler for the buffer
+ * @phys_addr:         physical address of the ADC base register
+ * @buf_idx:           index inside the dma buffer where reading was last done
+ * @rx_buf_sz:         size of buffer used by DMA operation
+ * @watermark:         number of conversions to copy before DMA triggers irq
+ * @dma_ts:            hold the start timestamp of dma operation
+ */
+struct at91_adc_dma {
+       struct dma_chan                 *dma_chan;
+       u8                              *rx_buf;
+       dma_addr_t                      rx_dma_buf;
+       phys_addr_t                     phys_addr;
+       int                             buf_idx;
+       int                             rx_buf_sz;
+       int                             watermark;
+       s64                             dma_ts;
+};
+
 struct at91_adc_state {
        void __iomem                    *base;
        int                             irq;
@@ -242,6 +274,7 @@ struct at91_adc_state {
        u32                             conversion_value;
        struct at91_adc_soc_info        soc_info;
        wait_queue_head_t               wq_data_available;
+       struct at91_adc_dma             dma_st;
        u16                             buffer[AT91_BUFFER_MAX_HWORDS];
        /*
         * lock to prevent concurrent 'single conversion' requests through
@@ -322,11 +355,17 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
                if (state) {
                        at91_adc_writel(st, AT91_SAMA5D2_CHER,
                                        BIT(chan->channel));
-                       at91_adc_writel(st, AT91_SAMA5D2_IER,
-                                       BIT(chan->channel));
+                       /* enable irq only if not using DMA */
+                       if (!st->dma_st.dma_chan) {
+                               at91_adc_writel(st, AT91_SAMA5D2_IER,
+                                               BIT(chan->channel));
+                       }
                } else {
-                       at91_adc_writel(st, AT91_SAMA5D2_IDR,
-                                       BIT(chan->channel));
+                       /* disable irq only if not using DMA */
+                       if (!st->dma_st.dma_chan) {
+                               at91_adc_writel(st, AT91_SAMA5D2_IDR,
+                                               BIT(chan->channel));
+                       }
                        at91_adc_writel(st, AT91_SAMA5D2_CHDR,
                                        BIT(chan->channel));
                }
@@ -340,6 +379,10 @@ static int at91_adc_reenable_trigger(struct iio_trigger *trig)
        struct iio_dev *indio = iio_trigger_get_drvdata(trig);
        struct at91_adc_state *st = iio_priv(indio);
 
+       /* if we are using DMA, we must not reenable irq after each trigger */
+       if (st->dma_st.dma_chan)
+               return 0;
+
        enable_irq(st->irq);
 
        /* Needed to ACK the DRDY interruption */
@@ -350,6 +393,153 @@ static int at91_adc_reenable_trigger(struct iio_trigger *trig)
 static const struct iio_trigger_ops at91_adc_trigger_ops = {
        .set_trigger_state = &at91_adc_configure_trigger,
        .try_reenable = &at91_adc_reenable_trigger,
+       .validate_device = iio_trigger_validate_own_device,
+};
+
+static int at91_adc_dma_size_done(struct at91_adc_state *st)
+{
+       struct dma_tx_state state;
+       enum dma_status status;
+       int i, size;
+
+       status = dmaengine_tx_status(st->dma_st.dma_chan,
+                                    st->dma_st.dma_chan->cookie,
+                                    &state);
+       if (status != DMA_IN_PROGRESS)
+               return 0;
+
+       /* Transferred length is size in bytes from end of buffer */
+       i = st->dma_st.rx_buf_sz - state.residue;
+
+       /* Return available bytes */
+       if (i >= st->dma_st.buf_idx)
+               size = i - st->dma_st.buf_idx;
+       else
+               size = st->dma_st.rx_buf_sz + i - st->dma_st.buf_idx;
+       return size;
+}
+
+static void at91_dma_buffer_done(void *data)
+{
+       struct iio_dev *indio_dev = data;
+
+       iio_trigger_poll_chained(indio_dev->trig);
+}
+
+static int at91_adc_dma_start(struct iio_dev *indio_dev)
+{
+       struct at91_adc_state *st = iio_priv(indio_dev);
+       struct dma_async_tx_descriptor *desc;
+       dma_cookie_t cookie;
+       int ret;
+       u8 bit;
+
+       if (!st->dma_st.dma_chan)
+               return 0;
+
+       /* we start a new DMA, so set buffer index to start */
+       st->dma_st.buf_idx = 0;
+
+       /*
+        * compute buffer size w.r.t. watermark and enabled channels.
+        * scan_bytes is aligned so we need an exact size for DMA
+        */
+       st->dma_st.rx_buf_sz = 0;
+
+       for_each_set_bit(bit, indio_dev->active_scan_mask,
+                        indio_dev->num_channels) {
+               struct iio_chan_spec const *chan = indio_dev->channels + bit;
+
+               st->dma_st.rx_buf_sz += chan->scan_type.storagebits / 8;
+       }
+       st->dma_st.rx_buf_sz *= st->dma_st.watermark;
+
+       /* Prepare a DMA cyclic transaction */
+       desc = dmaengine_prep_dma_cyclic(st->dma_st.dma_chan,
+                                        st->dma_st.rx_dma_buf,
+                                        st->dma_st.rx_buf_sz,
+                                        st->dma_st.rx_buf_sz / 2,
+                                        DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
+
+       if (!desc) {
+               dev_err(&indio_dev->dev, "cannot prepare DMA cyclic\n");
+               return -EBUSY;
+       }
+
+       desc->callback = at91_dma_buffer_done;
+       desc->callback_param = indio_dev;
+
+       cookie = dmaengine_submit(desc);
+       ret = dma_submit_error(cookie);
+       if (ret) {
+               dev_err(&indio_dev->dev, "cannot submit DMA cyclic\n");
+               dmaengine_terminate_async(st->dma_st.dma_chan);
+               return ret;
+       }
+
+       /* enable general overrun error signaling */
+       at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_GOVRE);
+       /* Issue pending DMA requests */
+       dma_async_issue_pending(st->dma_st.dma_chan);
+
+       /* consider current time as DMA start time for timestamps */
+       st->dma_st.dma_ts = iio_get_time_ns(indio_dev);
+
+       dev_dbg(&indio_dev->dev, "DMA cyclic started\n");
+
+       return 0;
+}
+
+static int at91_adc_buffer_postenable(struct iio_dev *indio_dev)
+{
+       int ret;
+
+       ret = at91_adc_dma_start(indio_dev);
+       if (ret) {
+               dev_err(&indio_dev->dev, "buffer postenable failed\n");
+               return ret;
+       }
+
+       return iio_triggered_buffer_postenable(indio_dev);
+}
+
+static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
+{
+       struct at91_adc_state *st = iio_priv(indio_dev);
+       int ret;
+       u8 bit;
+
+       ret = iio_triggered_buffer_predisable(indio_dev);
+       if (ret < 0)
+               dev_err(&indio_dev->dev, "buffer predisable failed\n");
+
+       if (!st->dma_st.dma_chan)
+               return ret;
+
+       /* if we are using DMA we must clear registers and end DMA */
+       dmaengine_terminate_sync(st->dma_st.dma_chan);
+
+       /*
+        * For each enabled channel we must read the last converted value
+        * to clear EOC status and not get a possible interrupt later.
+        * This value is being read by DMA from LCDR anyway
+        */
+       for_each_set_bit(bit, indio_dev->active_scan_mask,
+                        indio_dev->num_channels) {
+               struct iio_chan_spec const *chan = indio_dev->channels + bit;
+
+               if (st->dma_st.dma_chan)
+                       at91_adc_readl(st, chan->address);
+       }
+
+       /* read overflow register to clear possible overflow status */
+       at91_adc_readl(st, AT91_SAMA5D2_OVER);
+       return ret;
+}
+
+static const struct iio_buffer_setup_ops at91_buffer_setup_ops = {
+       .postenable = &at91_adc_buffer_postenable,
+       .predisable = &at91_adc_buffer_predisable,
 };
 
 static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
@@ -388,24 +578,77 @@ static int at91_adc_trigger_init(struct iio_dev *indio)
        return 0;
 }
 
-static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
+static void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev,
+                                          struct iio_poll_func *pf)
 {
-       struct iio_poll_func *pf = p;
-       struct iio_dev *indio = pf->indio_dev;
-       struct at91_adc_state *st = iio_priv(indio);
+       struct at91_adc_state *st = iio_priv(indio_dev);
        int i = 0;
        u8 bit;
 
-       for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
-               struct iio_chan_spec const *chan = indio->channels + bit;
+       for_each_set_bit(bit, indio_dev->active_scan_mask,
+                        indio_dev->num_channels) {
+               struct iio_chan_spec const *chan = indio_dev->channels + bit;
 
                st->buffer[i] = at91_adc_readl(st, chan->address);
                i++;
        }
+       iio_push_to_buffers_with_timestamp(indio_dev, st->buffer,
+                                          pf->timestamp);
+}
 
-       iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
+static void at91_adc_trigger_handler_dma(struct iio_dev *indio_dev)
+{
+       struct at91_adc_state *st = iio_priv(indio_dev);
+       int transferred_len = at91_adc_dma_size_done(st);
+       s64 ns = iio_get_time_ns(indio_dev);
+       s64 interval;
+       int sample_index = 0, sample_count, sample_size;
+
+       u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
+       /* if we reached this point, we cannot sample faster */
+       if (status & AT91_SAMA5D2_IER_GOVRE)
+               pr_info_ratelimited("%s: conversion overrun detected\n",
+                                   indio_dev->name);
 
-       iio_trigger_notify_done(indio->trig);
+       sample_size = div_s64(st->dma_st.rx_buf_sz, st->dma_st.watermark);
+
+       sample_count = div_s64(transferred_len, sample_size);
+
+       /*
+        * interval between samples is total time since last transfer handling
+        * divided by the number of samples (total size divided by sample size)
+        */
+       interval = div_s64((ns - st->dma_st.dma_ts), sample_count);
+
+       while (transferred_len >= sample_size) {
+               iio_push_to_buffers_with_timestamp(indio_dev,
+                               (st->dma_st.rx_buf + st->dma_st.buf_idx),
+                               (st->dma_st.dma_ts + interval * sample_index));
+               /* adjust remaining length */
+               transferred_len -= sample_size;
+               /* adjust buffer index */
+               st->dma_st.buf_idx += sample_size;
+               /* in case of reaching end of buffer, reset index */
+               if (st->dma_st.buf_idx >= st->dma_st.rx_buf_sz)
+                       st->dma_st.buf_idx = 0;
+               sample_index++;
+       }
+       /* adjust saved time for next transfer handling */
+       st->dma_st.dma_ts = iio_get_time_ns(indio_dev);
+}
+
+static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct at91_adc_state *st = iio_priv(indio_dev);
+
+       if (st->dma_st.dma_chan)
+               at91_adc_trigger_handler_dma(indio_dev);
+       else
+               at91_adc_trigger_handler_nodma(indio_dev, pf);
+
+       iio_trigger_notify_done(indio_dev->trig);
 
        return IRQ_HANDLED;
 }
@@ -414,7 +657,7 @@ static int at91_adc_buffer_init(struct iio_dev *indio)
 {
        return devm_iio_triggered_buffer_setup(&indio->dev, indio,
                        &iio_pollfunc_store_time,
-                       &at91_adc_trigger_handler, NULL);
+                       &at91_adc_trigger_handler, &at91_buffer_setup_ops);
 }
 
 static unsigned at91_adc_startup_time(unsigned startup_time_min,
@@ -485,10 +728,13 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
        if (!(status & imr))
                return IRQ_NONE;
 
-       if (iio_buffer_enabled(indio)) {
+       if (iio_buffer_enabled(indio) && !st->dma_st.dma_chan) {
                disable_irq_nosync(irq);
                iio_trigger_poll(indio->trig);
-       } else {
+       } else if (iio_buffer_enabled(indio) && st->dma_st.dma_chan) {
+               disable_irq_nosync(irq);
+               WARN(true, "Unexpected irq occurred\n");
+       } else if (!iio_buffer_enabled(indio)) {
                st->conversion_value = at91_adc_readl(st, st->chan->address);
                st->conversion_done = true;
                wake_up_interruptible(&st->wq_data_available);
@@ -510,7 +756,6 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
                ret = iio_device_claim_direct_mode(indio_dev);
                if (ret)
                        return ret;
-
                mutex_lock(&st->lock);
 
                st->chan = chan;
@@ -541,6 +786,9 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
                at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel));
                at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
 
+               /* Needed to ACK the DRDY interruption */
+               at91_adc_readl(st, AT91_SAMA5D2_LCDR);
+
                mutex_unlock(&st->lock);
 
                iio_device_release_direct_mode(indio_dev);
@@ -580,9 +828,123 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev,
        return 0;
 }
 
+static void at91_adc_dma_init(struct platform_device *pdev)
+{
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct at91_adc_state *st = iio_priv(indio_dev);
+       struct dma_slave_config config = {0};
+       /*
+        * We make the buffer double the size of the fifo,
+        * such that DMA uses one half of the buffer (full fifo size)
+        * and the software uses the other half to read/write.
+        */
+       unsigned int pages = DIV_ROUND_UP(AT91_HWFIFO_MAX_SIZE *
+                                         AT91_BUFFER_MAX_CONVERSION_BYTES * 2,
+                                         PAGE_SIZE);
+
+       if (st->dma_st.dma_chan)
+               return;
+
+       st->dma_st.dma_chan = dma_request_slave_channel(&pdev->dev, "rx");
+
+       if (!st->dma_st.dma_chan)  {
+               dev_info(&pdev->dev, "can't get DMA channel\n");
+               goto dma_exit;
+       }
+
+       st->dma_st.rx_buf = dma_alloc_coherent(st->dma_st.dma_chan->device->dev,
+                                              pages * PAGE_SIZE,
+                                              &st->dma_st.rx_dma_buf,
+                                              GFP_KERNEL);
+       if (!st->dma_st.rx_buf) {
+               dev_info(&pdev->dev, "can't allocate coherent DMA area\n");
+               goto dma_chan_disable;
+       }
+
+       /* Configure DMA channel to read data register */
+       config.direction = DMA_DEV_TO_MEM;
+       config.src_addr = (phys_addr_t)(st->dma_st.phys_addr
+                         + AT91_SAMA5D2_LCDR);
+       config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+       config.src_maxburst = 1;
+       config.dst_maxburst = 1;
+
+       if (dmaengine_slave_config(st->dma_st.dma_chan, &config)) {
+               dev_info(&pdev->dev, "can't configure DMA slave\n");
+               goto dma_free_area;
+       }
+
+       dev_info(&pdev->dev, "using %s for rx DMA transfers\n",
+                dma_chan_name(st->dma_st.dma_chan));
+
+       return;
+
+dma_free_area:
+       dma_free_coherent(st->dma_st.dma_chan->device->dev, pages * PAGE_SIZE,
+                         st->dma_st.rx_buf, st->dma_st.rx_dma_buf);
+dma_chan_disable:
+       dma_release_channel(st->dma_st.dma_chan);
+       st->dma_st.dma_chan = 0;
+dma_exit:
+       dev_info(&pdev->dev, "continuing without DMA support\n");
+}
+
+static void at91_adc_dma_disable(struct platform_device *pdev)
+{
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct at91_adc_state *st = iio_priv(indio_dev);
+       unsigned int pages = DIV_ROUND_UP(AT91_HWFIFO_MAX_SIZE *
+                                         AT91_BUFFER_MAX_CONVERSION_BYTES * 2,
+                                         PAGE_SIZE);
+
+       /* if we are not using DMA, just return */
+       if (!st->dma_st.dma_chan)
+               return;
+
+       /* wait for all transactions to be terminated first*/
+       dmaengine_terminate_sync(st->dma_st.dma_chan);
+
+       dma_free_coherent(st->dma_st.dma_chan->device->dev, pages * PAGE_SIZE,
+                         st->dma_st.rx_buf, st->dma_st.rx_dma_buf);
+       dma_release_channel(st->dma_st.dma_chan);
+       st->dma_st.dma_chan = 0;
+
+       dev_info(&pdev->dev, "continuing without DMA support\n");
+}
+
+static int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
+{
+       struct at91_adc_state *st = iio_priv(indio_dev);
+
+       if (val > AT91_HWFIFO_MAX_SIZE)
+               return -EINVAL;
+
+       if (!st->selected_trig->hw_trig) {
+               dev_dbg(&indio_dev->dev, "we need hw trigger for DMA\n");
+               return 0;
+       }
+
+       dev_dbg(&indio_dev->dev, "new watermark is %u\n", val);
+       st->dma_st.watermark = val;
+
+       /*
+        * The logic here is: if we have watermark 1, it means we do
+        * each conversion with it's own IRQ, thus we don't need DMA.
+        * If the watermark is higher, we do DMA to do all the transfers in bulk
+        */
+
+       if (val == 1)
+               at91_adc_dma_disable(to_platform_device(&indio_dev->dev));
+       else if (val > 1)
+               at91_adc_dma_init(to_platform_device(&indio_dev->dev));
+
+       return 0;
+}
+
 static const struct iio_info at91_adc_info = {
        .read_raw = &at91_adc_read_raw,
        .write_raw = &at91_adc_write_raw,
+       .hwfifo_set_watermark = &at91_adc_set_watermark,
 };
 
 static void at91_adc_hw_init(struct at91_adc_state *st)
@@ -599,6 +961,42 @@ static void at91_adc_hw_init(struct at91_adc_state *st)
        at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
 }
 
+static ssize_t at91_adc_get_fifo_state(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
+{
+       struct iio_dev *indio_dev =
+                       platform_get_drvdata(to_platform_device(dev));
+       struct at91_adc_state *st = iio_priv(indio_dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", !!st->dma_st.dma_chan);
+}
+
+static ssize_t at91_adc_get_watermark(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct iio_dev *indio_dev =
+                       platform_get_drvdata(to_platform_device(dev));
+       struct at91_adc_state *st = iio_priv(indio_dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", st->dma_st.watermark);
+}
+
+static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
+                      at91_adc_get_fifo_state, NULL, 0);
+static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
+                      at91_adc_get_watermark, NULL, 0);
+
+static IIO_CONST_ATTR(hwfifo_watermark_min, "2");
+static IIO_CONST_ATTR(hwfifo_watermark_max, AT91_HWFIFO_MAX_SIZE_STR);
+
+static const struct attribute *at91_adc_fifo_attributes[] = {
+       &iio_const_attr_hwfifo_watermark_min.dev_attr.attr,
+       &iio_const_attr_hwfifo_watermark_max.dev_attr.attr,
+       &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
+       &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+       NULL,
+};
+
 static int at91_adc_probe(struct platform_device *pdev)
 {
        struct iio_dev *indio_dev;
@@ -674,6 +1072,9 @@ static int at91_adc_probe(struct platform_device *pdev)
        if (!res)
                return -EINVAL;
 
+       /* if we plan to use DMA, we need the physical address of the regs */
+       st->dma_st.phys_addr = res->start;
+
        st->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(st->base))
                return PTR_ERR(st->base);
@@ -737,11 +1138,22 @@ static int at91_adc_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "couldn't setup the triggers.\n");
                        goto per_clk_disable_unprepare;
                }
+               /*
+                * Initially the iio buffer has a length of 2 and
+                * a watermark of 1
+                */
+               st->dma_st.watermark = 1;
+
+               iio_buffer_set_attrs(indio_dev->buffer,
+                                    at91_adc_fifo_attributes);
        }
 
+       if (dma_coerce_mask_and_coherent(&indio_dev->dev, DMA_BIT_MASK(32)))
+               dev_info(&pdev->dev, "cannot set DMA mask to 32-bit\n");
+
        ret = iio_device_register(indio_dev);
        if (ret < 0)
-               goto per_clk_disable_unprepare;
+               goto dma_disable;
 
        if (st->selected_trig->hw_trig)
                dev_info(&pdev->dev, "setting up trigger as %s\n",
@@ -752,6 +1164,8 @@ static int at91_adc_probe(struct platform_device *pdev)
 
        return 0;
 
+dma_disable:
+       at91_adc_dma_disable(pdev);
 per_clk_disable_unprepare:
        clk_disable_unprepare(st->per_clk);
 vref_disable:
@@ -768,6 +1182,8 @@ static int at91_adc_remove(struct platform_device *pdev)
 
        iio_device_unregister(indio_dev);
 
+       at91_adc_dma_disable(pdev);
+
        clk_disable_unprepare(st->per_clk);
 
        regulator_disable(st->vref);
index 3836d4222a3e58c7866500c0daf95c9a6d8fe0be..71a5ee652b796f8666be32d174c466536c6c6244 100644 (file)
@@ -1177,9 +1177,9 @@ static int at91_adc_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
        st->reg_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(st->reg_base)) {
+       if (IS_ERR(st->reg_base))
                return PTR_ERR(st->reg_base);
-       }
+
 
        /*
         * Disable all IRQs before setting up the handler
index 60c9e853dd81a9108b7109fc0409d258a23646cb..031d568b4972fa59e6426b3dfe013b0c3b94ad9e 100644 (file)
@@ -92,22 +92,14 @@ static const struct iio_chan_spec axp288_adc_channels[] = {
        },
 };
 
-#define AXP288_ADC_MAP(_adc_channel_label, _consumer_dev_name, \
-               _consumer_channel)                              \
-       {                                                       \
-               .adc_channel_label = _adc_channel_label,        \
-               .consumer_dev_name = _consumer_dev_name,        \
-               .consumer_channel = _consumer_channel,          \
-       }
-
 /* for consumer drivers */
 static struct iio_map axp288_adc_default_maps[] = {
-       AXP288_ADC_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"),
-       AXP288_ADC_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"),
-       AXP288_ADC_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"),
-       AXP288_ADC_MAP("BATT_CHG_I", "axp288-chrg", "axp288-chrg-curr"),
-       AXP288_ADC_MAP("BATT_DISCHRG_I", "axp288-chrg", "axp288-chrg-d-curr"),
-       AXP288_ADC_MAP("BATT_V", "axp288-batt", "axp288-batt-volt"),
+       IIO_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"),
+       IIO_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"),
+       IIO_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"),
+       IIO_MAP("BATT_CHG_I", "axp288-chrg", "axp288-chrg-curr"),
+       IIO_MAP("BATT_DISCHRG_I", "axp288-chrg", "axp288-chrg-d-curr"),
+       IIO_MAP("BATT_V", "axp288-batt", "axp288-batt-volt"),
        {},
 };
 
index d10b9f13d557df3b7239eb0cdaf76cc41db58656..9430b54121e002a9985879bf489f48fbd3c3e798 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/delay.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 #include <linux/gpio/consumer.h>
 #include <linux/regulator/consumer.h>
 
@@ -89,6 +92,11 @@ struct hx711_data {
        int                     gain_set;       /* gain set on device */
        int                     gain_chan_a;    /* gain for channel A */
        struct mutex            lock;
+       /*
+        * triggered buffer
+        * 2x32-bit channel + 64-bit timestamp
+        */
+       u32                     buffer[4];
 };
 
 static int hx711_cycle(struct hx711_data *hx711_data)
@@ -145,15 +153,16 @@ static int hx711_wait_for_ready(struct hx711_data *hx711_data)
        int i, val;
 
        /*
-        * a maximum reset cycle time of 56 ms was measured.
-        * we round it up to 100 ms
+        * in some rare cases the reset takes quite a long time
+        * especially when the channel is changed.
+        * Allow up to one second for it
         */
        for (i = 0; i < 100; i++) {
                val = gpiod_get_value(hx711_data->gpiod_dout);
                if (!val)
                        break;
-               /* sleep at least 1 ms */
-               msleep(1);
+               /* sleep at least 10 ms */
+               msleep(10);
        }
        if (val)
                return -EIO;
@@ -195,9 +204,7 @@ static int hx711_reset(struct hx711_data *hx711_data)
                 * after a dummy read we need to wait vor readiness
                 * for not mixing gain pulses with the clock
                 */
-               ret = hx711_wait_for_ready(hx711_data);
-               if (ret)
-                       return ret;
+               val = hx711_wait_for_ready(hx711_data);
        }
 
        return val;
@@ -236,34 +243,40 @@ static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
        return 0;
 }
 
+static int hx711_reset_read(struct hx711_data *hx711_data, int chan)
+{
+       int ret;
+       int val;
+
+       /*
+        * hx711_reset() must be called from here
+        * because it could be calling hx711_read() by itself
+        */
+       if (hx711_reset(hx711_data)) {
+               dev_err(hx711_data->dev, "reset failed!");
+               return -EIO;
+       }
+
+       ret = hx711_set_gain_for_channel(hx711_data, chan);
+       if (ret < 0)
+               return ret;
+
+       val = hx711_read(hx711_data);
+
+       return val;
+}
+
 static int hx711_read_raw(struct iio_dev *indio_dev,
                                const struct iio_chan_spec *chan,
                                int *val, int *val2, long mask)
 {
        struct hx711_data *hx711_data = iio_priv(indio_dev);
-       int ret;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
                mutex_lock(&hx711_data->lock);
 
-               /*
-                * hx711_reset() must be called from here
-                * because it could be calling hx711_read() by itself
-                */
-               if (hx711_reset(hx711_data)) {
-                       mutex_unlock(&hx711_data->lock);
-                       dev_err(hx711_data->dev, "reset failed!");
-                       return -EIO;
-               }
-
-               ret = hx711_set_gain_for_channel(hx711_data, chan->channel);
-               if (ret < 0) {
-                       mutex_unlock(&hx711_data->lock);
-                       return ret;
-               }
-
-               *val = hx711_read(hx711_data);
+               *val = hx711_reset_read(hx711_data, chan->channel);
 
                mutex_unlock(&hx711_data->lock);
 
@@ -339,6 +352,36 @@ static int hx711_write_raw_get_fmt(struct iio_dev *indio_dev,
        return IIO_VAL_INT_PLUS_NANO;
 }
 
+static irqreturn_t hx711_trigger(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct hx711_data *hx711_data = iio_priv(indio_dev);
+       int i, j = 0;
+
+       mutex_lock(&hx711_data->lock);
+
+       memset(hx711_data->buffer, 0, sizeof(hx711_data->buffer));
+
+       for (i = 0; i < indio_dev->masklength; i++) {
+               if (!test_bit(i, indio_dev->active_scan_mask))
+                       continue;
+
+               hx711_data->buffer[j] = hx711_reset_read(hx711_data,
+                                       indio_dev->channels[i].channel);
+               j++;
+       }
+
+       iio_push_to_buffers_with_timestamp(indio_dev, hx711_data->buffer,
+                                                       pf->timestamp);
+
+       mutex_unlock(&hx711_data->lock);
+
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
 static ssize_t hx711_scale_available_show(struct device *dev,
                                struct device_attribute *attr,
                                char *buf)
@@ -387,6 +430,13 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
                .indexed = 1,
                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .scan_index = 0,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 24,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
        },
        {
                .type = IIO_VOLTAGE,
@@ -394,7 +444,15 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
                .indexed = 1,
                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .scan_index = 1,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 24,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
        },
+       IIO_CHAN_SOFT_TIMESTAMP(2),
 };
 
 static int hx711_probe(struct platform_device *pdev)
@@ -459,10 +517,9 @@ static int hx711_probe(struct platform_device *pdev)
         * 1 LSB = (AVDD * 100) / GAIN / 1678 [10^-9 mV]
         */
        ret = regulator_get_voltage(hx711_data->reg_avdd);
-       if (ret < 0) {
-               regulator_disable(hx711_data->reg_avdd);
-               return ret;
-       }
+       if (ret < 0)
+               goto error_regulator;
+
        /* we need 10^-9 mV */
        ret *= 100;
 
@@ -482,12 +539,27 @@ static int hx711_probe(struct platform_device *pdev)
        indio_dev->channels = hx711_chan_spec;
        indio_dev->num_channels = ARRAY_SIZE(hx711_chan_spec);
 
+       ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time,
+                                                       hx711_trigger, NULL);
+       if (ret < 0) {
+               dev_err(dev, "setup of iio triggered buffer failed\n");
+               goto error_regulator;
+       }
+
        ret = iio_device_register(indio_dev);
        if (ret < 0) {
                dev_err(dev, "Couldn't register the device\n");
-               regulator_disable(hx711_data->reg_avdd);
+               goto error_buffer;
        }
 
+       return 0;
+
+error_buffer:
+       iio_triggered_buffer_cleanup(indio_dev);
+
+error_regulator:
+       regulator_disable(hx711_data->reg_avdd);
+
        return ret;
 }
 
@@ -501,6 +573,8 @@ static int hx711_remove(struct platform_device *pdev)
 
        iio_device_unregister(indio_dev);
 
+       iio_triggered_buffer_cleanup(indio_dev);
+
        regulator_disable(hx711_data->reg_avdd);
 
        return 0;
index 84a43871f7dca60b723dab86dd1934349bf02a51..0635a79864bf93f5fca84c3e367ecae141e39cde 100644 (file)
 
 #define INA226_MASK_ENABLE             0x06
 #define INA226_CVRF                    BIT(3)
-#define INA219_CNVR                    BIT(1)
 
 #define INA2XX_MAX_REGISTERS            8
 
 /* settings - depend on use case */
-#define INA219_CONFIG_DEFAULT           0x399F /* PGA=8 */
+#define INA219_CONFIG_DEFAULT           0x399F /* PGA=1/8, BRNG=32V */
 #define INA219_DEFAULT_IT              532
+#define INA219_DEFAULT_BRNG             1   /* 32V */
+#define INA219_DEFAULT_PGA              125 /* 1000/8 */
 #define INA226_CONFIG_DEFAULT           0x4327
 #define INA226_DEFAULT_AVG              4
 #define INA226_DEFAULT_IT              1110
  */
 #define INA2XX_MODE_MASK       GENMASK(3, 0)
 
+/* Gain for VShunt: 1/8 (default), 1/4, 1/2, 1 */
+#define INA219_PGA_MASK                GENMASK(12, 11)
+#define INA219_SHIFT_PGA(val)  ((val) << 11)
+
+/* VBus range: 32V (default), 16V */
+#define INA219_BRNG_MASK       BIT(13)
+#define INA219_SHIFT_BRNG(val) ((val) << 13)
+
 /* Averaging for VBus/VShunt/Power */
 #define INA226_AVG_MASK                GENMASK(11, 9)
 #define INA226_SHIFT_AVG(val)  ((val) << 9)
 #define INA226_ITS_MASK                GENMASK(5, 3)
 #define INA226_SHIFT_ITS(val)  ((val) << 3)
 
+/* INA219 Bus voltage register, low bits are flags */
+#define INA219_OVF             BIT(0)
+#define INA219_CNVR            BIT(1)
+#define INA219_BUS_VOLTAGE_SHIFT       3
+
 /* Cosmetic macro giving the sampling period for a full P=UxI cycle */
 #define SAMPLING_PERIOD(c)     ((c->int_time_vbus + c->int_time_vshunt) \
                                 * c->avg)
@@ -110,11 +124,12 @@ enum ina2xx_ids { ina219, ina226 };
 
 struct ina2xx_config {
        u16 config_default;
-       int calibration_factor;
-       int shunt_div;
-       int bus_voltage_shift;
+       int calibration_value;
+       int shunt_voltage_lsb;  /* nV */
+       int bus_voltage_shift;  /* position of lsb */
        int bus_voltage_lsb;    /* uV */
-       int power_lsb;          /* uW */
+       /* fixed relation between current and power lsb, uW/uA */
+       int power_lsb_factor;
        enum ina2xx_ids chip_id;
 };
 
@@ -127,26 +142,28 @@ struct ina2xx_chip_info {
        int avg;
        int int_time_vbus; /* Bus voltage integration time uS */
        int int_time_vshunt; /* Shunt voltage integration time uS */
+       int range_vbus; /* Bus voltage maximum in V */
+       int pga_gain_vshunt; /* Shunt voltage PGA gain */
        bool allow_async_readout;
 };
 
 static const struct ina2xx_config ina2xx_config[] = {
        [ina219] = {
                .config_default = INA219_CONFIG_DEFAULT,
-               .calibration_factor = 40960000,
-               .shunt_div = 100,
-               .bus_voltage_shift = 3,
+               .calibration_value = 4096,
+               .shunt_voltage_lsb = 10000,
+               .bus_voltage_shift = INA219_BUS_VOLTAGE_SHIFT,
                .bus_voltage_lsb = 4000,
-               .power_lsb = 20000,
+               .power_lsb_factor = 20,
                .chip_id = ina219,
        },
        [ina226] = {
                .config_default = INA226_CONFIG_DEFAULT,
-               .calibration_factor = 5120000,
-               .shunt_div = 400,
+               .calibration_value = 2048,
+               .shunt_voltage_lsb = 2500,
                .bus_voltage_shift = 0,
                .bus_voltage_lsb = 1250,
-               .power_lsb = 25000,
+               .power_lsb_factor = 25,
                .chip_id = ina226,
        },
 };
@@ -170,6 +187,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev,
                else
                        *val  = regval;
 
+               if (chan->address == INA2XX_BUS_VOLTAGE)
+                       *val >>= chip->config->bus_voltage_shift;
+
                return IIO_VAL_INT;
 
        case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
@@ -197,26 +217,48 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->address) {
                case INA2XX_SHUNT_VOLTAGE:
-                       /* processed (mV) = raw/shunt_div */
-                       *val2 = chip->config->shunt_div;
-                       *val = 1;
+                       /* processed (mV) = raw * lsb(nV) / 1000000 */
+                       *val = chip->config->shunt_voltage_lsb;
+                       *val2 = 1000000;
                        return IIO_VAL_FRACTIONAL;
 
                case INA2XX_BUS_VOLTAGE:
-                       /* processed (mV) = raw*lsb (uV) / (1000 << shift) */
+                       /* processed (mV) = raw * lsb (uV) / 1000 */
                        *val = chip->config->bus_voltage_lsb;
-                       *val2 = 1000 << chip->config->bus_voltage_shift;
+                       *val2 = 1000;
+                       return IIO_VAL_FRACTIONAL;
+
+               case INA2XX_CURRENT:
+                       /*
+                        * processed (mA) = raw * current_lsb (mA)
+                        * current_lsb (mA) = shunt_voltage_lsb (nV) /
+                        *                    shunt_resistor (uOhm)
+                        */
+                       *val = chip->config->shunt_voltage_lsb;
+                       *val2 = chip->shunt_resistor_uohm;
                        return IIO_VAL_FRACTIONAL;
 
                case INA2XX_POWER:
-                       /* processed (mW) = raw*lsb (uW) / 1000 */
-                       *val = chip->config->power_lsb;
+                       /*
+                        * processed (mW) = raw * power_lsb (mW)
+                        * power_lsb (mW) = power_lsb_factor (mW/mA) *
+                        *                  current_lsb (mA)
+                        */
+                       *val = chip->config->power_lsb_factor *
+                              chip->config->shunt_voltage_lsb;
+                       *val2 = chip->shunt_resistor_uohm;
+                       return IIO_VAL_FRACTIONAL;
+               }
+
+       case IIO_CHAN_INFO_HARDWAREGAIN:
+               switch (chan->address) {
+               case INA2XX_SHUNT_VOLTAGE:
+                       *val = chip->pga_gain_vshunt;
                        *val2 = 1000;
                        return IIO_VAL_FRACTIONAL;
 
-               case INA2XX_CURRENT:
-                       /* processed (mA) = raw (mA) */
-                       *val = 1;
+               case INA2XX_BUS_VOLTAGE:
+                       *val = chip->range_vbus == 32 ? 1 : 2;
                        return IIO_VAL_INT;
                }
        }
@@ -353,6 +395,74 @@ static int ina219_set_int_time_vshunt(struct ina2xx_chip_info *chip,
        return 0;
 }
 
+static const int ina219_vbus_range_tab[] = { 1, 2 };
+static int ina219_set_vbus_range_denom(struct ina2xx_chip_info *chip,
+                                      unsigned int range,
+                                      unsigned int *config)
+{
+       if (range == 1)
+               chip->range_vbus = 32;
+       else if (range == 2)
+               chip->range_vbus = 16;
+       else
+               return -EINVAL;
+
+       *config &= ~INA219_BRNG_MASK;
+       *config |= INA219_SHIFT_BRNG(range == 1 ? 1 : 0) & INA219_BRNG_MASK;
+
+       return 0;
+}
+
+static const int ina219_vshunt_gain_tab[] = { 125, 250, 500, 1000 };
+static const int ina219_vshunt_gain_frac[] = {
+       125, 1000, 250, 1000, 500, 1000, 1000, 1000 };
+
+static int ina219_set_vshunt_pga_gain(struct ina2xx_chip_info *chip,
+                                     unsigned int gain,
+                                     unsigned int *config)
+{
+       int bits;
+
+       if (gain < 125 || gain > 1000)
+               return -EINVAL;
+
+       bits = find_closest(gain, ina219_vshunt_gain_tab,
+                           ARRAY_SIZE(ina219_vshunt_gain_tab));
+
+       chip->pga_gain_vshunt = ina219_vshunt_gain_tab[bits];
+       bits = 3 - bits;
+
+       *config &= ~INA219_PGA_MASK;
+       *config |= INA219_SHIFT_PGA(bits) & INA219_PGA_MASK;
+
+       return 0;
+}
+
+static int ina2xx_read_avail(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan,
+                            const int **vals, int *type, int *length,
+                            long mask)
+{
+       switch (mask) {
+       case IIO_CHAN_INFO_HARDWAREGAIN:
+               switch (chan->address) {
+               case INA2XX_SHUNT_VOLTAGE:
+                       *type = IIO_VAL_FRACTIONAL;
+                       *length = sizeof(ina219_vshunt_gain_frac) / sizeof(int);
+                       *vals = ina219_vshunt_gain_frac;
+                       return IIO_AVAIL_LIST;
+
+               case INA2XX_BUS_VOLTAGE:
+                       *type = IIO_VAL_INT;
+                       *length = sizeof(ina219_vbus_range_tab) / sizeof(int);
+                       *vals = ina219_vbus_range_tab;
+                       return IIO_AVAIL_LIST;
+               }
+       }
+
+       return -EINVAL;
+}
+
 static int ina2xx_write_raw(struct iio_dev *indio_dev,
                            struct iio_chan_spec const *chan,
                            int val, int val2, long mask)
@@ -395,6 +505,14 @@ static int ina2xx_write_raw(struct iio_dev *indio_dev,
                }
                break;
 
+       case IIO_CHAN_INFO_HARDWAREGAIN:
+               if (chan->address == INA2XX_SHUNT_VOLTAGE)
+                       ret = ina219_set_vshunt_pga_gain(chip, val * 1000 +
+                                                        val2 / 1000, &tmp);
+               else
+                       ret = ina219_set_vbus_range_denom(chip, val, &tmp);
+               break;
+
        default:
                ret = -EINVAL;
        }
@@ -434,25 +552,21 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev,
 }
 
 /*
- * Set current LSB to 1mA, shunt is in uOhms
- * (equation 13 in datasheet). We hardcode a Current_LSB
- * of 1.0 x10-3. The only remaining parameter is RShunt.
- * There is no need to expose the CALIBRATION register
- * to the user for now. But we need to reset this register
- * if the user updates RShunt after driver init, e.g upon
- * reading an EEPROM/Probe-type value.
+ * Calibration register is set to the best value, which eliminates
+ * truncation errors on calculating current register in hardware.
+ * According to datasheet (INA 226: eq. 3, INA219: eq. 4) the best values
+ * are 2048 for ina226 and 4096 for ina219. They are hardcoded as
+ * calibration_value.
  */
 static int ina2xx_set_calibration(struct ina2xx_chip_info *chip)
 {
-       u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
-                                  chip->shunt_resistor_uohm);
-
-       return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
+       return regmap_write(chip->regmap, INA2XX_CALIBRATION,
+                           chip->config->calibration_value);
 }
 
 static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val)
 {
-       if (val <= 0 || val > chip->config->calibration_factor)
+       if (val == 0 || val > INT_MAX)
                return -EINVAL;
 
        chip->shunt_resistor_uohm = val;
@@ -485,11 +599,6 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
        if (ret)
                return ret;
 
-       /* Update the Calibration register */
-       ret = ina2xx_set_calibration(chip);
-       if (ret)
-               return ret;
-
        return len;
 }
 
@@ -532,19 +641,23 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
  * Sampling Freq is a consequence of the integration times of
  * the Voltage channels.
  */
-#define INA219_CHAN_VOLTAGE(_index, _address) { \
+#define INA219_CHAN_VOLTAGE(_index, _address, _shift) { \
        .type = IIO_VOLTAGE, \
        .address = (_address), \
        .indexed = 1, \
        .channel = (_index), \
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
                              BIT(IIO_CHAN_INFO_SCALE) | \
-                             BIT(IIO_CHAN_INFO_INT_TIME), \
+                             BIT(IIO_CHAN_INFO_INT_TIME) | \
+                             BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
+       .info_mask_separate_available = \
+                             BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
        .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
        .scan_index = (_index), \
        .scan_type = { \
                .sign = 'u', \
-               .realbits = 16, \
+               .shift = _shift, \
+               .realbits = 16 - _shift, \
                .storagebits = 16, \
                .endianness = IIO_LE, \
        } \
@@ -579,23 +692,18 @@ static const struct iio_chan_spec ina226_channels[] = {
 };
 
 static const struct iio_chan_spec ina219_channels[] = {
-       INA219_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE),
-       INA219_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE),
+       INA219_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE, 0),
+       INA219_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE, INA219_BUS_VOLTAGE_SHIFT),
        INA219_CHAN(IIO_POWER, 2, INA2XX_POWER),
        INA219_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT),
        IIO_CHAN_SOFT_TIMESTAMP(4),
 };
 
-static int ina2xx_work_buffer(struct iio_dev *indio_dev)
+static int ina2xx_conversion_ready(struct iio_dev *indio_dev)
 {
        struct ina2xx_chip_info *chip = iio_priv(indio_dev);
-       unsigned short data[8];
-       int bit, ret, i = 0;
-       s64 time_a, time_b;
+       int ret;
        unsigned int alert;
-       int cnvr_need_clear = 0;
-
-       time_a = iio_get_time_ns(indio_dev);
 
        /*
         * Because the timer thread and the chip conversion clock
@@ -608,23 +716,31 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
         * For now, we do an extra read of the MASK_ENABLE register (INA226)
         * resp. the BUS_VOLTAGE register (INA219).
         */
-       if (!chip->allow_async_readout)
-               do {
-                       if (chip->config->chip_id == ina226) {
-                               ret = regmap_read(chip->regmap,
-                                                 INA226_MASK_ENABLE, &alert);
-                               alert &= INA226_CVRF;
-                       } else {
-                               ret = regmap_read(chip->regmap,
-                                                 INA2XX_BUS_VOLTAGE, &alert);
-                               alert &= INA219_CNVR;
-                               cnvr_need_clear = alert;
-                       }
+       if (chip->config->chip_id == ina226) {
+               ret = regmap_read(chip->regmap,
+                                 INA226_MASK_ENABLE, &alert);
+               alert &= INA226_CVRF;
+       } else {
+               ret = regmap_read(chip->regmap,
+                                 INA2XX_BUS_VOLTAGE, &alert);
+               alert &= INA219_CNVR;
+       }
 
-                       if (ret < 0)
-                               return ret;
+       if (ret < 0)
+               return ret;
+
+       return !!alert;
+}
+
+static int ina2xx_work_buffer(struct iio_dev *indio_dev)
+{
+       struct ina2xx_chip_info *chip = iio_priv(indio_dev);
+       /* data buffer needs space for channel data and timestap */
+       unsigned short data[4 + sizeof(s64)/sizeof(short)];
+       int bit, ret, i = 0;
+       s64 time;
 
-               } while (!alert);
+       time = iio_get_time_ns(indio_dev);
 
        /*
         * Single register reads: bulk_read will not work with ina226/219
@@ -640,26 +756,11 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
                        return ret;
 
                data[i++] = val;
-
-               if (INA2XX_SHUNT_VOLTAGE + bit == INA2XX_POWER)
-                       cnvr_need_clear = 0;
-       }
-
-       /* Dummy read on INA219 power register to clear CNVR flag */
-       if (cnvr_need_clear && chip->config->chip_id == ina219) {
-               unsigned int val;
-
-               ret = regmap_read(chip->regmap, INA2XX_POWER, &val);
-               if (ret < 0)
-                       return ret;
        }
 
-       time_b = iio_get_time_ns(indio_dev);
+       iio_push_to_buffers_with_timestamp(indio_dev, data, time);
 
-       iio_push_to_buffers_with_timestamp(indio_dev,
-                                          (unsigned int *)data, time_a);
-
-       return (unsigned long)(time_b - time_a) / 1000;
+       return 0;
 };
 
 static int ina2xx_capture_thread(void *data)
@@ -667,7 +768,9 @@ static int ina2xx_capture_thread(void *data)
        struct iio_dev *indio_dev = data;
        struct ina2xx_chip_info *chip = iio_priv(indio_dev);
        int sampling_us = SAMPLING_PERIOD(chip);
-       int buffer_us;
+       int ret;
+       struct timespec64 next, now, delta;
+       s64 delay_us;
 
        /*
         * Poll a bit faster than the chip internal Fs, in case
@@ -676,13 +779,43 @@ static int ina2xx_capture_thread(void *data)
        if (!chip->allow_async_readout)
                sampling_us -= 200;
 
+       ktime_get_ts64(&next);
+
        do {
-               buffer_us = ina2xx_work_buffer(indio_dev);
-               if (buffer_us < 0)
-                       return buffer_us;
+               while (!chip->allow_async_readout) {
+                       ret = ina2xx_conversion_ready(indio_dev);
+                       if (ret < 0)
+                               return ret;
 
-               if (sampling_us > buffer_us)
-                       udelay(sampling_us - buffer_us);
+                       /*
+                        * If the conversion was not yet finished,
+                        * reset the reference timestamp.
+                        */
+                       if (ret == 0)
+                               ktime_get_ts64(&next);
+                       else
+                               break;
+               }
+
+               ret = ina2xx_work_buffer(indio_dev);
+               if (ret < 0)
+                       return ret;
+
+               ktime_get_ts64(&now);
+
+               /*
+                * Advance the timestamp for the next poll by one sampling
+                * interval, and sleep for the remainder (next - now)
+                * In case "next" has already passed, the interval is added
+                * multiple times, i.e. samples are dropped.
+                */
+               do {
+                       timespec64_add_ns(&next, 1000 * sampling_us);
+                       delta = timespec64_sub(next, now);
+                       delay_us = div_s64(timespec64_to_ns(&delta), 1000);
+               } while (delay_us <= 0);
+
+               usleep_range(delay_us, (delay_us * 3) >> 1);
 
        } while (!kthread_should_stop());
 
@@ -746,7 +879,6 @@ static IIO_CONST_ATTR_NAMED(ina226_integration_time_available,
                            integration_time_available,
                            "0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244");
 
-
 static IIO_DEVICE_ATTR(in_allow_async_readout, S_IRUGO | S_IWUSR,
                       ina2xx_allow_async_readout_show,
                       ina2xx_allow_async_readout_store, 0);
@@ -780,6 +912,7 @@ static const struct attribute_group ina226_attribute_group = {
 static const struct iio_info ina219_info = {
        .attrs = &ina219_attribute_group,
        .read_raw = ina2xx_read_raw,
+       .read_avail = ina2xx_read_avail,
        .write_raw = ina2xx_write_raw,
        .debugfs_reg_access = ina2xx_debug_reg,
 };
@@ -860,6 +993,8 @@ static int ina2xx_probe(struct i2c_client *client,
                chip->avg = 1;
                ina219_set_int_time_vbus(chip, INA219_DEFAULT_IT, &val);
                ina219_set_int_time_vshunt(chip, INA219_DEFAULT_IT, &val);
+               ina219_set_vbus_range_denom(chip, INA219_DEFAULT_BRNG, &val);
+               ina219_set_vshunt_pga_gain(chip, INA219_DEFAULT_PGA, &val);
        }
 
        ret = ina2xx_init(chip, val);
index 36047147ce7c727003a0f08df34880302ebd2e08..29fa7736d80caae392095123d207695cc87f53df 100644 (file)
@@ -96,8 +96,8 @@
        #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK         GENMASK(11, 0)
 
 #define MESON_SAR_ADC_AUX_SW                                   0x1c
-       #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_MASK(_chan)   \
-                                       (GENMASK(10, 8) << (((_chan) - 2) * 2))
+       #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan)  \
+                                       (8 + (((_chan) - 2) * 3))
        #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX                 BIT(6)
        #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX                 BIT(5)
        #define MESON_SAR_ADC_AUX_SW_MODE_SEL                   BIT(4)
@@ -221,6 +221,7 @@ enum meson_sar_adc_chan7_mux_sel {
 
 struct meson_sar_adc_data {
        bool                                    has_bl30_integration;
+       unsigned long                           clock_rate;
        u32                                     bandgap_reg;
        unsigned int                            resolution;
        const char                              *name;
@@ -233,7 +234,6 @@ struct meson_sar_adc_priv {
        const struct meson_sar_adc_data         *data;
        struct clk                              *clkin;
        struct clk                              *core_clk;
-       struct clk                              *sana_clk;
        struct clk                              *adc_sel_clk;
        struct clk                              *adc_clk;
        struct clk_gate                         clk_gate;
@@ -622,7 +622,7 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
 static int meson_sar_adc_init(struct iio_dev *indio_dev)
 {
        struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
-       int regval, ret;
+       int regval, i, ret;
 
        /*
         * make sure we start at CH7 input since the other muxes are only used
@@ -677,6 +677,32 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
                           FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK,
                                      1));
 
+       /*
+        * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW
+        * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1)
+        */
+       regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0);
+       regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
+                          MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK,
+                          regval);
+       regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1);
+       regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
+                          MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK,
+                          regval);
+
+       /*
+        * set up the input channel muxes in MESON_SAR_ADC_AUX_SW
+        * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable
+        * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and
+        * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver.
+        */
+       regval = 0;
+       for (i = 2; i <= 7; i++)
+               regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i);
+       regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW;
+       regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW;
+       regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval);
+
        ret = clk_set_parent(priv->adc_sel_clk, priv->clkin);
        if (ret) {
                dev_err(indio_dev->dev.parent,
@@ -684,7 +710,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
                return ret;
        }
 
-       ret = clk_set_rate(priv->adc_clk, 1200000);
+       ret = clk_set_rate(priv->adc_clk, priv->data->clock_rate);
        if (ret) {
                dev_err(indio_dev->dev.parent,
                        "failed to set adc clock rate\n");
@@ -731,12 +757,6 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
                goto err_core_clk;
        }
 
-       ret = clk_prepare_enable(priv->sana_clk);
-       if (ret) {
-               dev_err(indio_dev->dev.parent, "failed to enable sana clk\n");
-               goto err_sana_clk;
-       }
-
        regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
        regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
                           MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
@@ -763,8 +783,6 @@ err_adc_clk:
        regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
                           MESON_SAR_ADC_REG3_ADC_EN, 0);
        meson_sar_adc_set_bandgap(indio_dev, false);
-       clk_disable_unprepare(priv->sana_clk);
-err_sana_clk:
        clk_disable_unprepare(priv->core_clk);
 err_core_clk:
        regulator_disable(priv->vref);
@@ -790,7 +808,6 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
 
        meson_sar_adc_set_bandgap(indio_dev, false);
 
-       clk_disable_unprepare(priv->sana_clk);
        clk_disable_unprepare(priv->core_clk);
 
        regulator_disable(priv->vref);
@@ -866,6 +883,7 @@ static const struct iio_info meson_sar_adc_iio_info = {
 
 static const struct meson_sar_adc_data meson_sar_adc_meson8_data = {
        .has_bl30_integration = false,
+       .clock_rate = 1150000,
        .bandgap_reg = MESON_SAR_ADC_DELTA_10,
        .regmap_config = &meson_sar_adc_regmap_config_meson8,
        .resolution = 10,
@@ -874,6 +892,7 @@ static const struct meson_sar_adc_data meson_sar_adc_meson8_data = {
 
 static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = {
        .has_bl30_integration = false,
+       .clock_rate = 1150000,
        .bandgap_reg = MESON_SAR_ADC_DELTA_10,
        .regmap_config = &meson_sar_adc_regmap_config_meson8,
        .resolution = 10,
@@ -882,6 +901,7 @@ static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = {
 
 static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = {
        .has_bl30_integration = true,
+       .clock_rate = 1200000,
        .bandgap_reg = MESON_SAR_ADC_REG11,
        .regmap_config = &meson_sar_adc_regmap_config_gxbb,
        .resolution = 10,
@@ -890,6 +910,7 @@ static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = {
 
 static const struct meson_sar_adc_data meson_sar_adc_gxl_data = {
        .has_bl30_integration = true,
+       .clock_rate = 1200000,
        .bandgap_reg = MESON_SAR_ADC_REG11,
        .regmap_config = &meson_sar_adc_regmap_config_gxbb,
        .resolution = 12,
@@ -898,6 +919,7 @@ static const struct meson_sar_adc_data meson_sar_adc_gxl_data = {
 
 static const struct meson_sar_adc_data meson_sar_adc_gxm_data = {
        .has_bl30_integration = true,
+       .clock_rate = 1200000,
        .bandgap_reg = MESON_SAR_ADC_REG11,
        .regmap_config = &meson_sar_adc_regmap_config_gxbb,
        .resolution = 12,
@@ -993,16 +1015,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
                return PTR_ERR(priv->core_clk);
        }
 
-       priv->sana_clk = devm_clk_get(&pdev->dev, "sana");
-       if (IS_ERR(priv->sana_clk)) {
-               if (PTR_ERR(priv->sana_clk) == -ENOENT) {
-                       priv->sana_clk = NULL;
-               } else {
-                       dev_err(&pdev->dev, "failed to get sana clk\n");
-                       return PTR_ERR(priv->sana_clk);
-               }
-       }
-
        priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk");
        if (IS_ERR(priv->adc_clk)) {
                if (PTR_ERR(priv->adc_clk) == -ENOENT) {
index 47d24ae5462fe8afd131f9d771c7d00e9da1d03d..fe3d7826783c0fcd0bae1831f356ba0d5acc86a4 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/math64.h>
 #include <linux/log2.h>
 #include <linux/err.h>
+#include <linux/module.h>
 
 #include "qcom-vadc-common.h"
 
@@ -229,3 +230,6 @@ int qcom_vadc_decimation_from_dt(u32 value)
        return __ffs64(value / VADC_DECIMATION_MIN);
 }
 EXPORT_SYMBOL(qcom_vadc_decimation_from_dt);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm ADC common functionality");
index 6aefef99f935e5d3aee23481c2b9c0ff370773f1..40be7d9fadbf58c6afdb897a5386e271fca72a1c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is part of STM32 ADC driver
  *
@@ -6,19 +7,6 @@
  *
  * Inspired from: fsl-imx25-tsadc
  *
- * License type: GPLv2
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/clk.h>
index 250ee958a6695a605d0c06b8878104882b3d05b8..8af507b3f32d914d70307bfff7e8819b4284581d 100644 (file)
@@ -1,22 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * This file is part of STM32 ADC driver
  *
  * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
  * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
  *
- * License type: GPLv2
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __STM32_ADC_H
index c9d96f935dba4751a1e9e29bac3d3ed3753e1283..7f5def465340e6444e8023a2e11d8b0b877d89b0 100644 (file)
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is part of STM32 ADC driver
  *
  * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
  * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
- *
- * License type: GPLv2
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/clk.h>
@@ -92,6 +79,7 @@
 #define STM32H7_ADC_SQR3               0x38
 #define STM32H7_ADC_SQR4               0x3C
 #define STM32H7_ADC_DR                 0x40
+#define STM32H7_ADC_DIFSEL             0xC0
 #define STM32H7_ADC_CALFACT            0xC4
 #define STM32H7_ADC_CALFACT2           0xC8
 
@@ -153,6 +141,8 @@ enum stm32h7_adc_dmngt {
 /* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
 #define STM32H7_BOOST_CLKRATE          20000000UL
 
+#define STM32_ADC_CH_MAX               20      /* max number of channels */
+#define STM32_ADC_CH_SZ                        10      /* max channel name size */
 #define STM32_ADC_MAX_SQ               16      /* SQ1..SQ16 */
 #define STM32_ADC_MAX_SMP              7       /* SMPx range is [0..7] */
 #define STM32_ADC_TIMEOUT_US           100000
@@ -297,9 +287,11 @@ struct stm32_adc_cfg {
  * @rx_buf:            dma rx buffer cpu address
  * @rx_dma_buf:                dma rx buffer bus address
  * @rx_buf_sz:         dma rx buffer size
+ * @difsel             bitmask to set single-ended/differential channel
  * @pcsel              bitmask to preselect channels on some devices
  * @smpr_val:          sampling time settings (e.g. smpr1 / smpr2)
  * @cal:               optional calibration data on some devices
+ * @chan_name:         channel name array
  */
 struct stm32_adc {
        struct stm32_adc_common *common;
@@ -318,72 +310,37 @@ struct stm32_adc {
        u8                      *rx_buf;
        dma_addr_t              rx_dma_buf;
        unsigned int            rx_buf_sz;
+       u32                     difsel;
        u32                     pcsel;
        u32                     smpr_val[2];
        struct stm32_adc_calib  cal;
+       char                    chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ];
 };
 
-/**
- * struct stm32_adc_chan_spec - specification of stm32 adc channel
- * @type:      IIO channel type
- * @channel:   channel number (single ended)
- * @name:      channel name (single ended)
- */
-struct stm32_adc_chan_spec {
-       enum iio_chan_type      type;
-       int                     channel;
-       const char              *name;
+struct stm32_adc_diff_channel {
+       u32 vinp;
+       u32 vinn;
 };
 
 /**
  * struct stm32_adc_info - stm32 ADC, per instance config data
- * @channels:          Reference to stm32 channels spec
  * @max_channels:      Number of channels
  * @resolutions:       available resolutions
  * @num_res:           number of available resolutions
  */
 struct stm32_adc_info {
-       const struct stm32_adc_chan_spec *channels;
        int max_channels;
        const unsigned int *resolutions;
        const unsigned int num_res;
 };
 
-/*
- * Input definitions common for all instances:
- * stm32f4 can have up to 16 channels
- * stm32h7 can have up to 20 channels
- */
-static const struct stm32_adc_chan_spec stm32_adc_channels[] = {
-       { IIO_VOLTAGE, 0, "in0" },
-       { IIO_VOLTAGE, 1, "in1" },
-       { IIO_VOLTAGE, 2, "in2" },
-       { IIO_VOLTAGE, 3, "in3" },
-       { IIO_VOLTAGE, 4, "in4" },
-       { IIO_VOLTAGE, 5, "in5" },
-       { IIO_VOLTAGE, 6, "in6" },
-       { IIO_VOLTAGE, 7, "in7" },
-       { IIO_VOLTAGE, 8, "in8" },
-       { IIO_VOLTAGE, 9, "in9" },
-       { IIO_VOLTAGE, 10, "in10" },
-       { IIO_VOLTAGE, 11, "in11" },
-       { IIO_VOLTAGE, 12, "in12" },
-       { IIO_VOLTAGE, 13, "in13" },
-       { IIO_VOLTAGE, 14, "in14" },
-       { IIO_VOLTAGE, 15, "in15" },
-       { IIO_VOLTAGE, 16, "in16" },
-       { IIO_VOLTAGE, 17, "in17" },
-       { IIO_VOLTAGE, 18, "in18" },
-       { IIO_VOLTAGE, 19, "in19" },
-};
-
 static const unsigned int stm32f4_adc_resolutions[] = {
        /* sorted values so the index matches RES[1:0] in STM32F4_ADC_CR1 */
        12, 10, 8, 6,
 };
 
+/* stm32f4 can have up to 16 channels */
 static const struct stm32_adc_info stm32f4_adc_info = {
-       .channels = stm32_adc_channels,
        .max_channels = 16,
        .resolutions = stm32f4_adc_resolutions,
        .num_res = ARRAY_SIZE(stm32f4_adc_resolutions),
@@ -394,9 +351,9 @@ static const unsigned int stm32h7_adc_resolutions[] = {
        16, 14, 12, 10, 8,
 };
 
+/* stm32h7 can have up to 20 channels */
 static const struct stm32_adc_info stm32h7_adc_info = {
-       .channels = stm32_adc_channels,
-       .max_channels = 20,
+       .max_channels = STM32_ADC_CH_MAX,
        .resolutions = stm32h7_adc_resolutions,
        .num_res = ARRAY_SIZE(stm32h7_adc_resolutions),
 };
@@ -983,15 +940,19 @@ pwr_dwn:
  * stm32h7_adc_prepare() - Leave power down mode to enable ADC.
  * @adc: stm32 adc instance
  * Leave power down mode.
+ * Configure channels as single ended or differential before enabling ADC.
  * Enable ADC.
  * Restore calibration data.
- * Pre-select channels that may be used in PCSEL (required by input MUX / IO).
+ * Pre-select channels that may be used in PCSEL (required by input MUX / IO):
+ * - Only one input is selected for single ended (e.g. 'vinp')
+ * - Two inputs are selected for differential channels (e.g. 'vinp' & 'vinn')
  */
 static int stm32h7_adc_prepare(struct stm32_adc *adc)
 {
        int ret;
 
        stm32h7_adc_exit_pwr_down(adc);
+       stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel);
 
        ret = stm32h7_adc_enable(adc);
        if (ret)
@@ -1263,10 +1224,23 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
                return ret;
 
        case IIO_CHAN_INFO_SCALE:
-               *val = adc->common->vref_mv;
-               *val2 = chan->scan_type.realbits;
+               if (chan->differential) {
+                       *val = adc->common->vref_mv * 2;
+                       *val2 = chan->scan_type.realbits;
+               } else {
+                       *val = adc->common->vref_mv;
+                       *val2 = chan->scan_type.realbits;
+               }
                return IIO_VAL_FRACTIONAL_LOG2;
 
+       case IIO_CHAN_INFO_OFFSET:
+               if (chan->differential)
+                       /* ADC_full_scale / 2 */
+                       *val = -((1 << chan->scan_type.realbits) / 2);
+               else
+                       *val = 0;
+               return IIO_VAL_INT;
+
        default:
                return -EINVAL;
        }
@@ -1315,6 +1289,7 @@ static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
 {
        struct stm32_adc *adc = iio_priv(indio_dev);
        unsigned int watermark = STM32_DMA_BUFFER_SIZE / 2;
+       unsigned int rx_buf_sz = STM32_DMA_BUFFER_SIZE;
 
        /*
         * dma cyclic transfers are used, buffer is split into two periods.
@@ -1323,7 +1298,7 @@ static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
         * - one buffer (period) driver can push with iio_trigger_poll().
         */
        watermark = min(watermark, val * (unsigned)(sizeof(u16)));
-       adc->rx_buf_sz = watermark * 2;
+       adc->rx_buf_sz = min(rx_buf_sz, watermark * 2 * adc->num_conv);
 
        return 0;
 }
@@ -1628,29 +1603,40 @@ static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns)
 }
 
 static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
-                                   struct iio_chan_spec *chan,
-                                   const struct stm32_adc_chan_spec *channel,
-                                   int scan_index, u32 smp)
+                                   struct iio_chan_spec *chan, u32 vinp,
+                                   u32 vinn, int scan_index, bool differential)
 {
        struct stm32_adc *adc = iio_priv(indio_dev);
-
-       chan->type = channel->type;
-       chan->channel = channel->channel;
-       chan->datasheet_name = channel->name;
+       char *name = adc->chan_name[vinp];
+
+       chan->type = IIO_VOLTAGE;
+       chan->channel = vinp;
+       if (differential) {
+               chan->differential = 1;
+               chan->channel2 = vinn;
+               snprintf(name, STM32_ADC_CH_SZ, "in%d-in%d", vinp, vinn);
+       } else {
+               snprintf(name, STM32_ADC_CH_SZ, "in%d", vinp);
+       }
+       chan->datasheet_name = name;
        chan->scan_index = scan_index;
        chan->indexed = 1;
        chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
-       chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+       chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+                                        BIT(IIO_CHAN_INFO_OFFSET);
        chan->scan_type.sign = 'u';
        chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res];
        chan->scan_type.storagebits = 16;
        chan->ext_info = stm32_adc_ext_info;
 
-       /* Prepare sampling time settings */
-       stm32_adc_smpr_init(adc, chan->channel, smp);
-
        /* pre-build selected channels mask */
        adc->pcsel |= BIT(chan->channel);
+       if (differential) {
+               /* pre-build diff channels mask */
+               adc->difsel |= BIT(chan->channel);
+               /* Also add negative input to pre-selected channels */
+               adc->pcsel |= BIT(chan->channel2);
+       }
 }
 
 static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
@@ -1658,17 +1644,40 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
        struct device_node *node = indio_dev->dev.of_node;
        struct stm32_adc *adc = iio_priv(indio_dev);
        const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
+       struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX];
        struct property *prop;
        const __be32 *cur;
        struct iio_chan_spec *channels;
-       int scan_index = 0, num_channels, ret;
+       int scan_index = 0, num_channels = 0, num_diff = 0, ret, i;
        u32 val, smp = 0;
 
-       num_channels = of_property_count_u32_elems(node, "st,adc-channels");
-       if (num_channels < 0 ||
-           num_channels > adc_info->max_channels) {
+       ret = of_property_count_u32_elems(node, "st,adc-channels");
+       if (ret > adc_info->max_channels) {
                dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
-               return num_channels < 0 ? num_channels : -EINVAL;
+               return -EINVAL;
+       } else if (ret > 0) {
+               num_channels += ret;
+       }
+
+       ret = of_property_count_elems_of_size(node, "st,adc-diff-channels",
+                                             sizeof(*diff));
+       if (ret > adc_info->max_channels) {
+               dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n");
+               return -EINVAL;
+       } else if (ret > 0) {
+               int size = ret * sizeof(*diff) / sizeof(u32);
+
+               num_diff = ret;
+               num_channels += ret;
+               ret = of_property_read_u32_array(node, "st,adc-diff-channels",
+                                                (u32 *)diff, size);
+               if (ret)
+                       return ret;
+       }
+
+       if (!num_channels) {
+               dev_err(&indio_dev->dev, "No channels configured\n");
+               return -ENODATA;
        }
 
        /* Optional sample time is provided either for each, or all channels */
@@ -1689,6 +1698,33 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
                        return -EINVAL;
                }
 
+               /* Channel can't be configured both as single-ended & diff */
+               for (i = 0; i < num_diff; i++) {
+                       if (val == diff[i].vinp) {
+                               dev_err(&indio_dev->dev,
+                                       "channel %d miss-configured\n", val);
+                               return -EINVAL;
+                       }
+               }
+               stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val,
+                                       0, scan_index, false);
+               scan_index++;
+       }
+
+       for (i = 0; i < num_diff; i++) {
+               if (diff[i].vinp >= adc_info->max_channels ||
+                   diff[i].vinn >= adc_info->max_channels) {
+                       dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
+                               diff[i].vinp, diff[i].vinn);
+                       return -EINVAL;
+               }
+               stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
+                                       diff[i].vinp, diff[i].vinn, scan_index,
+                                       true);
+               scan_index++;
+       }
+
+       for (i = 0; i < scan_index; i++) {
                /*
                 * Using of_property_read_u32_index(), smp value will only be
                 * modified if valid u32 value can be decoded. This allows to
@@ -1696,12 +1732,9 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
                 * value per channel.
                 */
                of_property_read_u32_index(node, "st,min-sample-time-nsecs",
-                                          scan_index, &smp);
-
-               stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
-                                       &adc_info->channels[val],
-                                       scan_index, smp);
-               scan_index++;
+                                          i, &smp);
+               /* Prepare sampling time settings */
+               stm32_adc_smpr_init(adc, channels[i].channel, smp);
        }
 
        indio_dev->num_channels = scan_index;
index b3e573cc6f5fc19ca43354b58fb84a0caf54e749..80df5a377d30a335d601a94aa9d1d2e0925aff13 100644 (file)
@@ -523,7 +523,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
        }
        am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
 
-       if (found == false)
+       if (!found)
                ret =  -EBUSY;
 
 err_unlock:
index 97bce8345c6a88b84269dce60a04c6df6100801e..fbe2431f5b81b25dcd14647ca656ae70c4925e7e 100644 (file)
@@ -96,7 +96,6 @@ static const struct iio_chan_spec ccs811_channels[] = {
                .channel2 = IIO_MOD_CO2,
                .modified = 1,
                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                                     BIT(IIO_CHAN_INFO_OFFSET) |
                                      BIT(IIO_CHAN_INFO_SCALE),
                .scan_index = 0,
                .scan_type = {
@@ -255,24 +254,18 @@ static int ccs811_read_raw(struct iio_dev *indio_dev,
                        switch (chan->channel2) {
                        case IIO_MOD_CO2:
                                *val = 0;
-                               *val2 = 12834;
+                               *val2 = 100;
                                return IIO_VAL_INT_PLUS_MICRO;
                        case IIO_MOD_VOC:
                                *val = 0;
-                               *val2 = 84246;
-                               return IIO_VAL_INT_PLUS_MICRO;
+                               *val2 = 100;
+                               return IIO_VAL_INT_PLUS_NANO;
                        default:
                                return -EINVAL;
                        }
                default:
                        return -EINVAL;
                }
-       case IIO_CHAN_INFO_OFFSET:
-               if (!(chan->type == IIO_CONCENTRATION &&
-                     chan->channel2 == IIO_MOD_CO2))
-                       return -EINVAL;
-               *val = -400;
-               return IIO_VAL_INT;
        default:
                return -EINVAL;
        }
index ed8063f2da9966ed9e2a49194d7ea7976169168d..7d30c59da3e200ab739b3db533f70307fa5df18b 100644 (file)
@@ -191,7 +191,6 @@ static int cros_ec_sensors_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
-       struct cros_ec_device *ec_device;
        struct iio_dev *indio_dev;
        struct cros_ec_sensors_state *state;
        struct iio_chan_spec *channel;
@@ -201,7 +200,6 @@ static int cros_ec_sensors_probe(struct platform_device *pdev)
                dev_warn(&pdev->dev, "No CROS EC device found.\n");
                return -EINVAL;
        }
-       ec_device = ec_dev->ec_dev;
 
        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
        if (!indio_dev)
index b910e91d7c0d3edc703e26146c014cd69ddd7284..82a01addd91997974a46c06b15b19aa49ae85d5c 100644 (file)
@@ -188,7 +188,7 @@ struct ssp_sensorhub_info {
  */
 struct ssp_data {
        struct spi_device *spi;
-       struct ssp_sensorhub_info *sensorhub_info;
+       const struct ssp_sensorhub_info *sensorhub_info;
        struct timer_list wdt_timer;
        struct work_struct work_wdt;
        struct delayed_work work_refresh;
index 2ba2ff5e59c47c125af52e86c32badba3d633249..af3aa38f67cda7683b30c2cd82d0b90d28cc1f8d 100644 (file)
@@ -486,7 +486,7 @@ static struct ssp_data *ssp_parse_dt(struct device *dev)
        if (!match)
                goto err_mcu_reset_gpio;
 
-       data->sensorhub_info = (struct ssp_sensorhub_info *)match->data;
+       data->sensorhub_info = match->data;
 
        dev_set_drvdata(dev, data);
 
index 704284a475aeca0218bbf83517d8479e4fbcd4e2..2ab106bb3e03232abbdab3bc996e4afb96337aee 100644 (file)
@@ -277,12 +277,9 @@ static int ssp_handle_big_data(struct ssp_data *data, char *dataframe, int *idx)
 static int ssp_parse_dataframe(struct ssp_data *data, char *dataframe, int len)
 {
        int idx, sd;
-       struct timespec ts;
        struct ssp_sensor_data *spd;
        struct iio_dev **indio_devs = data->sensor_devs;
 
-       getnstimeofday(&ts);
-
        for (idx = 0; idx < len;) {
                switch (dataframe[idx++]) {
                case SSP_MSG2AP_INST_BYPASS_DATA:
@@ -329,7 +326,7 @@ static int ssp_parse_dataframe(struct ssp_data *data, char *dataframe, int len)
        }
 
        if (data->time_syncing)
-               data->timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec;
+               data->timestamp = ktime_get_real_ns();
 
        return 0;
 }
index 81ae5f74216d5cac4c2361de0a76f10a487bb5ef..42fb8ba670903a9450dc77fb1d04efd13e69546f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * STM32 Low-Power Timer Encoder and Counter driver
  *
@@ -7,7 +8,6 @@
  *
  * Inspired by 104-quad-8 and stm32-timer-trigger drivers.
  *
- * License terms:  GNU General Public License (GPL), version 2
  */
 
 #include <linux/bitfield.h>
index afa856d10c26f8ea0ed9193af55b185f2eb7ec1e..8b5aad4c32d90effd27cb6a19f3373d5c9060879 100644 (file)
@@ -476,7 +476,7 @@ static int mcp4725_probe(struct i2c_client *client,
                goto err_disable_vref_reg;
        }
        pd = (inbuf[0] >> 1) & 0x3;
-       data->powerdown = pd > 0 ? true : false;
+       data->powerdown = pd > 0;
        data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
        data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
        if (data->id == MCP4726)
index 55026fe1c6102fdfd6550e6af67879b34a873ca1..d0fb3124de0768dd5bdf8608c6453da46d9cb63b 100644 (file)
@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is part of STM32 DAC driver
  *
  * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
  * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
  *
- * License type: GPLv2
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/clk.h>
index daf09931857cd9a9a58b2a59fd84a23ce675424a..d3b415fb9575a1c2aa00add5f63124fa043f2b56 100644 (file)
@@ -1,22 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * This file is part of STM32 DAC driver
  *
  * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
  * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
- *
- * License type: GPLv2
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __STM32_DAC_CORE_H
index 9ffab02bf9f9cd81b6e534c87cfde83c79555091..cce26a3a6627cb2bd6fbdfe337eeecc07606b2a2 100644 (file)
@@ -1,23 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is part of STM32 DAC driver
  *
  * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
  * Authors: Amelie Delaunay <amelie.delaunay@st.com>
  *         Fabrice Gasnier <fabrice.gasnier@st.com>
- *
- * License type: GPLv2
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/bitfield.h>
index fe8884543da0a33d8132c1f9368ac99a60314cbd..efd0005f59b4d0d61a492949971ba198ee7885e5 100644 (file)
@@ -56,7 +56,7 @@ static int iio_dummy_evgen_create(void)
                return -ENOMEM;
 
        ret = irq_sim_init(&iio_evgen->irq_sim, IIO_EVENTGEN_NO);
-       if (ret) {
+       if (ret < 0) {
                kfree(iio_evgen);
                return ret;
        }
index 90ec4bed62b788f1f09b9ea908a8901f4f730925..605eee23780c005a75e172f67b7636f8f6d8cc08 100644 (file)
@@ -124,7 +124,7 @@ static int adis16136_show_product_id(void *arg, u64 *val)
 
        return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(adis16136_product_id_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16136_product_id_fops,
        adis16136_show_product_id, NULL, "%llu\n");
 
 static int adis16136_show_flash_count(void *arg, u64 *val)
@@ -142,18 +142,21 @@ static int adis16136_show_flash_count(void *arg, u64 *val)
 
        return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(adis16136_flash_count_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16136_flash_count_fops,
        adis16136_show_flash_count, NULL, "%lld\n");
 
 static int adis16136_debugfs_init(struct iio_dev *indio_dev)
 {
        struct adis16136 *adis16136 = iio_priv(indio_dev);
 
-       debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
-               adis16136, &adis16136_serial_fops);
-       debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
+       debugfs_create_file_unsafe("serial_number", 0400,
+               indio_dev->debugfs_dentry, adis16136,
+               &adis16136_serial_fops);
+       debugfs_create_file_unsafe("product_id", 0400,
+               indio_dev->debugfs_dentry,
                adis16136, &adis16136_product_id_fops);
-       debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
+       debugfs_create_file_unsafe("flash_count", 0400,
+               indio_dev->debugfs_dentry,
                adis16136, &adis16136_flash_count_fops);
 
        return 0;
index 15046172e437f4324ac7d04d167ec51c5c34339e..63ca31628a93af8454f5fce9ced15d752f28f16d 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/regmap.h>
-#include <linux/delay.h>
 #include "bmg160.h"
 
 #define BMG160_IRQ_NAME                "bmg160_event"
index 147a8c14235f3f8b39302c8f78beec811f6871dd..15ccadc74891f73dca409acb0806cb4136646da9 100644 (file)
@@ -3,6 +3,9 @@
  *
  * Copyright (C) 2017 Matt Ranostay <matt@ranostay.consulting>
  *
+ * Support for MAX30105 optical particle sensor
+ * Copyright (C) 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -13,6 +16,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
  *
+ * 7-bit I2C chip address: 0x57
  * TODO: proximity power saving feature
  */
 
 
 #define MAX30102_REGMAP_NAME   "max30102_regmap"
 #define MAX30102_DRV_NAME      "max30102"
+#define MAX30102_PART_NUMBER   0x15
+
+enum max30102_chip_id {
+       max30102,
+       max30105,
+};
+
+enum max3012_led_idx {
+       MAX30102_LED_RED,
+       MAX30102_LED_IR,
+       MAX30105_LED_GREEN,
+};
 
 #define MAX30102_REG_INT_STATUS                        0x00
 #define MAX30102_REG_INT_STATUS_PWR_RDY                BIT(0)
@@ -52,7 +68,7 @@
 #define MAX30102_REG_FIFO_OVR_CTR              0x05
 #define MAX30102_REG_FIFO_RD_PTR               0x06
 #define MAX30102_REG_FIFO_DATA                 0x07
-#define MAX30102_REG_FIFO_DATA_ENTRY_LEN       6
+#define MAX30102_REG_FIFO_DATA_BYTES           3
 
 #define MAX30102_REG_FIFO_CONFIG               0x08
 #define MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES  BIT(1)
 #define MAX30102_REG_FIFO_CONFIG_AFULL         BIT(0)
 
 #define MAX30102_REG_MODE_CONFIG               0x09
-#define MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN  BIT(0)
-#define MAX30102_REG_MODE_CONFIG_MODE_HR_EN    BIT(1)
-#define MAX30102_REG_MODE_CONFIG_MODE_MASK     0x03
+#define MAX30102_REG_MODE_CONFIG_MODE_NONE     0x00
+#define MAX30102_REG_MODE_CONFIG_MODE_HR       0x02 /* red LED */
+#define MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2  0x03 /* red + IR LED */
+#define MAX30102_REG_MODE_CONFIG_MODE_MULTI    0x07 /* multi-LED mode */
+#define MAX30102_REG_MODE_CONFIG_MODE_MASK     GENMASK(2, 0)
 #define MAX30102_REG_MODE_CONFIG_PWR           BIT(7)
 
+#define MAX30102_REG_MODE_CONTROL_SLOT21       0x11 /* multi-LED control */
+#define MAX30102_REG_MODE_CONTROL_SLOT43       0x12
+#define MAX30102_REG_MODE_CONTROL_SLOT_MASK    (GENMASK(6, 4) | GENMASK(2, 0))
+#define MAX30102_REG_MODE_CONTROL_SLOT_SHIFT   4
+
 #define MAX30102_REG_SPO2_CONFIG               0x0a
 #define MAX30102_REG_SPO2_CONFIG_PULSE_411_US  0x03
 #define MAX30102_REG_SPO2_CONFIG_SR_400HZ      0x03
@@ -75,6 +98,7 @@
 
 #define MAX30102_REG_RED_LED_CONFIG            0x0c
 #define MAX30102_REG_IR_LED_CONFIG             0x0d
+#define MAX30105_REG_GREEN_LED_CONFIG          0x0e
 
 #define MAX30102_REG_TEMP_CONFIG               0x21
 #define MAX30102_REG_TEMP_CONFIG_TEMP_EN       BIT(0)
 #define MAX30102_REG_TEMP_INTEGER              0x1f
 #define MAX30102_REG_TEMP_FRACTION             0x20
 
+#define MAX30102_REG_REV_ID                    0xfe
+#define MAX30102_REG_PART_ID                   0xff
+
 struct max30102_data {
        struct i2c_client *client;
        struct iio_dev *indio_dev;
        struct mutex lock;
        struct regmap *regmap;
+       enum max30102_chip_id chip_id;
 
-       u8 buffer[8];
-       __be32 processed_buffer[2]; /* 2 x 18-bit (padded to 32-bits) */
+       u8 buffer[12];
+       __be32 processed_buffer[3]; /* 3 x 18-bit (padded to 32-bits) */
 };
 
 static const struct regmap_config max30102_regmap_config = {
@@ -99,37 +127,47 @@ static const struct regmap_config max30102_regmap_config = {
        .val_bits = 8,
 };
 
-static const unsigned long max30102_scan_masks[] = {0x3, 0};
+static const unsigned long max30102_scan_masks[] = {
+       BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
+       0
+};
+
+static const unsigned long max30105_scan_masks[] = {
+       BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
+       BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |
+               BIT(MAX30105_LED_GREEN),
+       0
+};
+
+#define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
+               .type = IIO_INTENSITY, \
+               .channel2 = _mod, \
+               .modified = 1, \
+               .scan_index = _si, \
+               .scan_type = { \
+                       .sign = 'u', \
+                       .shift = 8, \
+                       .realbits = 18, \
+                       .storagebits = 32, \
+                       .endianness = IIO_BE, \
+               }, \
+       }
 
 static const struct iio_chan_spec max30102_channels[] = {
+       MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),
+       MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),
        {
-               .type = IIO_INTENSITY,
-               .channel2 = IIO_MOD_LIGHT_RED,
-               .modified = 1,
-
-               .scan_index = 0,
-               .scan_type = {
-                       .sign = 'u',
-                       .shift = 8,
-                       .realbits = 18,
-                       .storagebits = 32,
-                       .endianness = IIO_BE,
-               },
-       },
-       {
-               .type = IIO_INTENSITY,
-               .channel2 = IIO_MOD_LIGHT_IR,
-               .modified = 1,
-
-               .scan_index = 1,
-               .scan_type = {
-                       .sign = 'u',
-                       .shift = 8,
-                       .realbits = 18,
-                       .storagebits = 32,
-                       .endianness = IIO_BE,
-               },
+               .type = IIO_TEMP,
+               .info_mask_separate =
+                       BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+               .scan_index = -1,
        },
+};
+
+static const struct iio_chan_spec max30105_channels[] = {
+       MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),
+       MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),
+       MAX30102_INTENSITY_CHANNEL(MAX30105_LED_GREEN, IIO_MOD_LIGHT_GREEN),
        {
                .type = IIO_TEMP,
                .info_mask_separate =
@@ -138,25 +176,69 @@ static const struct iio_chan_spec max30102_channels[] = {
        },
 };
 
-static int max30102_set_powermode(struct max30102_data *data, bool state)
+static int max30102_set_power(struct max30102_data *data, bool en)
 {
        return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
                                  MAX30102_REG_MODE_CONFIG_PWR,
-                                 state ? 0 : MAX30102_REG_MODE_CONFIG_PWR);
+                                 en ? 0 : MAX30102_REG_MODE_CONFIG_PWR);
 }
 
+static int max30102_set_powermode(struct max30102_data *data, u8 mode, bool en)
+{
+       u8 reg = mode;
+
+       if (!en)
+               reg |= MAX30102_REG_MODE_CONFIG_PWR;
+
+       return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
+                                 MAX30102_REG_MODE_CONFIG_PWR |
+                                 MAX30102_REG_MODE_CONFIG_MODE_MASK, reg);
+}
+
+#define MAX30102_MODE_CONTROL_LED_SLOTS(slot2, slot1) \
+       ((slot2 << MAX30102_REG_MODE_CONTROL_SLOT_SHIFT) | slot1)
+
 static int max30102_buffer_postenable(struct iio_dev *indio_dev)
 {
        struct max30102_data *data = iio_priv(indio_dev);
+       int ret;
+       u8 reg;
 
-       return max30102_set_powermode(data, true);
+       switch (*indio_dev->active_scan_mask) {
+       case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR):
+               reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
+               break;
+       case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |
+            BIT(MAX30105_LED_GREEN):
+               ret = regmap_update_bits(data->regmap,
+                                        MAX30102_REG_MODE_CONTROL_SLOT21,
+                                        MAX30102_REG_MODE_CONTROL_SLOT_MASK,
+                                        MAX30102_MODE_CONTROL_LED_SLOTS(2, 1));
+               if (ret)
+                       return ret;
+
+               ret = regmap_update_bits(data->regmap,
+                                        MAX30102_REG_MODE_CONTROL_SLOT43,
+                                        MAX30102_REG_MODE_CONTROL_SLOT_MASK,
+                                        MAX30102_MODE_CONTROL_LED_SLOTS(0, 3));
+               if (ret)
+                       return ret;
+
+               reg = MAX30102_REG_MODE_CONFIG_MODE_MULTI;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return max30102_set_powermode(data, reg, true);
 }
 
 static int max30102_buffer_predisable(struct iio_dev *indio_dev)
 {
        struct max30102_data *data = iio_priv(indio_dev);
 
-       return max30102_set_powermode(data, false);
+       return max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
+                                     false);
 }
 
 static const struct iio_buffer_setup_ops max30102_buffer_setup_ops = {
@@ -180,32 +262,51 @@ static inline int max30102_fifo_count(struct max30102_data *data)
        return 0;
 }
 
-static int max30102_read_measurement(struct max30102_data *data)
+#define MAX30102_COPY_DATA(i) \
+       memcpy(&data->processed_buffer[(i)], \
+              &buffer[(i) * MAX30102_REG_FIFO_DATA_BYTES], \
+              MAX30102_REG_FIFO_DATA_BYTES)
+
+static int max30102_read_measurement(struct max30102_data *data,
+                                    unsigned int measurements)
 {
        int ret;
        u8 *buffer = (u8 *) &data->buffer;
 
        ret = i2c_smbus_read_i2c_block_data(data->client,
                                            MAX30102_REG_FIFO_DATA,
-                                           MAX30102_REG_FIFO_DATA_ENTRY_LEN,
+                                           measurements *
+                                           MAX30102_REG_FIFO_DATA_BYTES,
                                            buffer);
 
-       memcpy(&data->processed_buffer[0], &buffer[0], 3);
-       memcpy(&data->processed_buffer[1], &buffer[3], 3);
+       switch (measurements) {
+       case 3:
+               MAX30102_COPY_DATA(2);
+       case 2: /* fall-through */
+               MAX30102_COPY_DATA(1);
+       case 1: /* fall-through */
+               MAX30102_COPY_DATA(0);
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       return (ret == MAX30102_REG_FIFO_DATA_ENTRY_LEN) ? 0 : -EINVAL;
+       return (ret == measurements * MAX30102_REG_FIFO_DATA_BYTES) ?
+              0 : -EINVAL;
 }
 
 static irqreturn_t max30102_interrupt_handler(int irq, void *private)
 {
        struct iio_dev *indio_dev = private;
        struct max30102_data *data = iio_priv(indio_dev);
+       unsigned int measurements = bitmap_weight(indio_dev->active_scan_mask,
+                                                 indio_dev->masklength);
        int ret, cnt = 0;
 
        mutex_lock(&data->lock);
 
        while (cnt || (cnt = max30102_fifo_count(data)) > 0) {
-               ret = max30102_read_measurement(data);
+               ret = max30102_read_measurement(data, measurements);
                if (ret)
                        break;
 
@@ -251,6 +352,29 @@ static int max30102_led_init(struct max30102_data *data)
        if (ret)
                return ret;
 
+       if (data->chip_id == max30105) {
+               ret = of_property_read_u32(np,
+                       "maxim,green-led-current-microamp", &val);
+               if (ret) {
+                       dev_info(dev, "no green-led-current-microamp set\n");
+
+                       /* Default to 7 mA green LED */
+                       val = 7000;
+               }
+
+               ret = max30102_get_current_idx(val, &reg);
+               if (ret) {
+                       dev_err(dev, "invalid green LED current setting %d\n",
+                               val);
+                       return ret;
+               }
+
+               ret = regmap_write(data->regmap, MAX30105_REG_GREEN_LED_CONFIG,
+                                  reg);
+               if (ret)
+                       return ret;
+       }
+
        ret = of_property_read_u32(np, "maxim,ir-led-current-microamp", &val);
        if (ret) {
                dev_info(dev, "no ir-led-current-microamp set\n");
@@ -261,7 +385,7 @@ static int max30102_led_init(struct max30102_data *data)
 
        ret = max30102_get_current_idx(val, &reg);
        if (ret) {
-               dev_err(dev, "invalid IR LED current setting %d", val);
+               dev_err(dev, "invalid IR LED current setting %d\n", val);
                return ret;
        }
 
@@ -277,7 +401,7 @@ static int max30102_chip_init(struct max30102_data *data)
        if (ret)
                return ret;
 
-       /* enable 18-bit HR + SPO2 readings at 400Hz */
+       /* configure 18-bit HR + SpO2 readings at 400Hz */
        ret = regmap_write(data->regmap, MAX30102_REG_SPO2_CONFIG,
                                (MAX30102_REG_SPO2_CONFIG_ADC_4096_STEPS
                                 << MAX30102_REG_SPO2_CONFIG_ADC_MASK_SHIFT) |
@@ -287,14 +411,6 @@ static int max30102_chip_init(struct max30102_data *data)
        if (ret)
                return ret;
 
-       /* enable SPO2 mode */
-       ret = regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
-                                MAX30102_REG_MODE_CONFIG_MODE_MASK,
-                                MAX30102_REG_MODE_CONFIG_MODE_HR_EN |
-                                MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN);
-       if (ret)
-               return ret;
-
        /* average 4 samples + generate FIFO interrupt */
        ret = regmap_write(data->regmap, MAX30102_REG_FIFO_CONFIG,
                                (MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES
@@ -329,20 +445,31 @@ static int max30102_read_temp(struct max30102_data *data, int *val)
        return 0;
 }
 
-static int max30102_get_temp(struct max30102_data *data, int *val)
+static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
 {
        int ret;
 
+       if (en) {
+               ret = max30102_set_power(data, true);
+               if (ret)
+                       return ret;
+       }
+
        /* start acquisition */
        ret = regmap_update_bits(data->regmap, MAX30102_REG_TEMP_CONFIG,
                                 MAX30102_REG_TEMP_CONFIG_TEMP_EN,
                                 MAX30102_REG_TEMP_CONFIG_TEMP_EN);
        if (ret)
-               return ret;
+               goto out;
 
        msleep(35);
+       ret = max30102_read_temp(data, val);
 
-       return max30102_read_temp(data, val);
+out:
+       if (en)
+               max30102_set_power(data, false);
+
+       return ret;
 }
 
 static int max30102_read_raw(struct iio_dev *indio_dev,
@@ -355,20 +482,19 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
                /*
-                * Temperature reading can only be acquired while engine
-                * is running
+                * Temperature reading can only be acquired when not in
+                * shutdown; leave shutdown briefly when buffer not running
                 */
                mutex_lock(&indio_dev->mlock);
-
                if (!iio_buffer_enabled(indio_dev))
-                       ret = -EBUSY;
-               else {
-                       ret = max30102_get_temp(data, val);
-                       if (!ret)
-                               ret = IIO_VAL_INT;
-               }
-
+                       ret = max30102_get_temp(data, val, true);
+               else
+                       ret = max30102_get_temp(data, val, false);
                mutex_unlock(&indio_dev->mlock);
+               if (ret)
+                       return ret;
+
+               ret = IIO_VAL_INT;
                break;
        case IIO_CHAN_INFO_SCALE:
                *val = 1000;  /* 62.5 */
@@ -391,6 +517,7 @@ static int max30102_probe(struct i2c_client *client,
        struct iio_buffer *buffer;
        struct iio_dev *indio_dev;
        int ret;
+       unsigned int reg;
 
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
        if (!indio_dev)
@@ -403,10 +530,7 @@ static int max30102_probe(struct i2c_client *client,
        iio_device_attach_buffer(indio_dev, buffer);
 
        indio_dev->name = MAX30102_DRV_NAME;
-       indio_dev->channels = max30102_channels;
        indio_dev->info = &max30102_info;
-       indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
-       indio_dev->available_scan_masks = max30102_scan_masks;
        indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
        indio_dev->setup_ops = &max30102_buffer_setup_ops;
        indio_dev->dev.parent = &client->dev;
@@ -414,16 +538,50 @@ static int max30102_probe(struct i2c_client *client,
        data = iio_priv(indio_dev);
        data->indio_dev = indio_dev;
        data->client = client;
+       data->chip_id = id->driver_data;
 
        mutex_init(&data->lock);
        i2c_set_clientdata(client, indio_dev);
 
+       switch (data->chip_id) {
+       case max30105:
+               indio_dev->channels = max30105_channels;
+               indio_dev->num_channels = ARRAY_SIZE(max30105_channels);
+               indio_dev->available_scan_masks = max30105_scan_masks;
+               break;
+       case max30102:
+               indio_dev->channels = max30102_channels;
+               indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
+               indio_dev->available_scan_masks = max30102_scan_masks;
+               break;
+       default:
+               return -ENODEV;
+       }
+
        data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
        if (IS_ERR(data->regmap)) {
-               dev_err(&client->dev, "regmap initialization failed.\n");
+               dev_err(&client->dev, "regmap initialization failed\n");
                return PTR_ERR(data->regmap);
        }
-       max30102_set_powermode(data, false);
+
+       /* check part ID */
+       ret = regmap_read(data->regmap, MAX30102_REG_PART_ID, &reg);
+       if (ret)
+               return ret;
+       if (reg != MAX30102_PART_NUMBER)
+               return -ENODEV;
+
+       /* show revision ID */
+       ret = regmap_read(data->regmap, MAX30102_REG_REV_ID, &reg);
+       if (ret)
+               return ret;
+       dev_dbg(&client->dev, "max3010x revision %02x\n", reg);
+
+       /* clear mode setting, chip shutdown */
+       ret = max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
+                                    false);
+       if (ret)
+               return ret;
 
        ret = max30102_chip_init(data);
        if (ret)
@@ -452,19 +610,21 @@ static int max30102_remove(struct i2c_client *client)
        struct max30102_data *data = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
-       max30102_set_powermode(data, false);
+       max30102_set_power(data, false);
 
        return 0;
 }
 
 static const struct i2c_device_id max30102_id[] = {
-       { "max30102", 0 },
+       { "max30102", max30102 },
+       { "max30105", max30105 },
        {}
 };
 MODULE_DEVICE_TABLE(i2c, max30102_id);
 
 static const struct of_device_id max30102_dt_ids[] = {
        { .compatible = "maxim,max30102" },
+       { .compatible = "maxim,max30105" },
        { }
 };
 MODULE_DEVICE_TABLE(of, max30102_dt_ids);
@@ -481,5 +641,5 @@ static struct i2c_driver max30102_driver = {
 module_i2c_driver(max30102_driver);
 
 MODULE_AUTHOR("Matt Ranostay <matt@ranostay.consulting>");
-MODULE_DESCRIPTION("MAX30102 heart rate and pulse oximeter sensor");
+MODULE_DESCRIPTION("MAX30102 heart rate/pulse oximeter and MAX30105 particle sensor driver");
 MODULE_LICENSE("GPL");
index 51d021966222f572dd4300a1f77c3ea0d5385d50..c581af8c0f5d3f78cd0dd4461faee79404d3b99b 100644 (file)
@@ -61,7 +61,8 @@ struct hts221_hw {
 extern const struct dev_pm_ops hts221_pm_ops;
 
 int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, u8 val);
-int hts221_probe(struct iio_dev *iio_dev);
+int hts221_probe(struct device *dev, int irq, const char *name,
+                const struct hts221_transfer_function *tf_ops);
 int hts221_set_enable(struct hts221_hw *hw, bool enable);
 int hts221_allocate_buffers(struct hts221_hw *hw);
 int hts221_allocate_trigger(struct hts221_hw *hw);
index daef177219b60be6623b4e96ca203deff172f7b6..d3f7904766bd3f477343c91d45d3280e8c23ac1c 100644 (file)
@@ -581,12 +581,26 @@ static const struct iio_info hts221_info = {
 
 static const unsigned long hts221_scan_masks[] = {0x3, 0x0};
 
-int hts221_probe(struct iio_dev *iio_dev)
+int hts221_probe(struct device *dev, int irq, const char *name,
+                const struct hts221_transfer_function *tf_ops)
 {
-       struct hts221_hw *hw = iio_priv(iio_dev);
+       struct iio_dev *iio_dev;
+       struct hts221_hw *hw;
        int err;
        u8 data;
 
+       iio_dev = devm_iio_device_alloc(dev, sizeof(*hw));
+       if (!iio_dev)
+               return -ENOMEM;
+
+       dev_set_drvdata(dev, (void *)iio_dev);
+
+       hw = iio_priv(iio_dev);
+       hw->name = name;
+       hw->dev = dev;
+       hw->irq = irq;
+       hw->tf = tf_ops;
+
        mutex_init(&hw->lock);
 
        err = hts221_check_whoami(hw);
index f38e4b7e0160746ee2bbe094c9dddb712a3834f1..2c97350a0f760dd46f3586a1fa124d65515b18cd 100644 (file)
@@ -66,22 +66,8 @@ static const struct hts221_transfer_function hts221_transfer_fn = {
 static int hts221_i2c_probe(struct i2c_client *client,
                            const struct i2c_device_id *id)
 {
-       struct hts221_hw *hw;
-       struct iio_dev *iio_dev;
-
-       iio_dev = devm_iio_device_alloc(&client->dev, sizeof(*hw));
-       if (!iio_dev)
-               return -ENOMEM;
-
-       i2c_set_clientdata(client, iio_dev);
-
-       hw = iio_priv(iio_dev);
-       hw->name = client->name;
-       hw->dev = &client->dev;
-       hw->irq = client->irq;
-       hw->tf = &hts221_transfer_fn;
-
-       return hts221_probe(iio_dev);
+       return hts221_probe(&client->dev, client->irq,
+                           client->name, &hts221_transfer_fn);
 }
 
 static const struct acpi_device_id hts221_acpi_match[] = {
index 57cbc256771bce39ebab42475b420f1ac535ce2f..55b29b53b9d1b97861ab21b99f064561300b91ac 100644 (file)
@@ -80,22 +80,8 @@ static const struct hts221_transfer_function hts221_transfer_fn = {
 
 static int hts221_spi_probe(struct spi_device *spi)
 {
-       struct hts221_hw *hw;
-       struct iio_dev *iio_dev;
-
-       iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*hw));
-       if (!iio_dev)
-               return -ENOMEM;
-
-       spi_set_drvdata(spi, iio_dev);
-
-       hw = iio_priv(iio_dev);
-       hw->name = spi->modalias;
-       hw->dev = &spi->dev;
-       hw->irq = spi->irq;
-       hw->tf = &hts221_transfer_fn;
-
-       return hts221_probe(iio_dev);
+       return hts221_probe(&spi->dev, spi->irq,
+                           spi->modalias, &hts221_transfer_fn);
 }
 
 static const struct of_device_id hts221_spi_of_match[] = {
index 7a33d6bd60e0501832aae844f6767839aa407c39..a27fe208f3aed80a949f50e98be96dc1f1a8f92e 100644 (file)
@@ -194,7 +194,7 @@ static int adis16480_show_serial_number(void *arg, u64 *val)
 
        return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(adis16480_serial_number_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16480_serial_number_fops,
        adis16480_show_serial_number, NULL, "0x%.4llx\n");
 
 static int adis16480_show_product_id(void *arg, u64 *val)
@@ -212,7 +212,7 @@ static int adis16480_show_product_id(void *arg, u64 *val)
 
        return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(adis16480_product_id_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16480_product_id_fops,
        adis16480_show_product_id, NULL, "%llu\n");
 
 static int adis16480_show_flash_count(void *arg, u64 *val)
@@ -230,24 +230,28 @@ static int adis16480_show_flash_count(void *arg, u64 *val)
 
        return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(adis16480_flash_count_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16480_flash_count_fops,
        adis16480_show_flash_count, NULL, "%lld\n");
 
 static int adis16480_debugfs_init(struct iio_dev *indio_dev)
 {
        struct adis16480 *adis16480 = iio_priv(indio_dev);
 
-       debugfs_create_file("firmware_revision", 0400,
+       debugfs_create_file_unsafe("firmware_revision", 0400,
                indio_dev->debugfs_dentry, adis16480,
                &adis16480_firmware_revision_fops);
-       debugfs_create_file("firmware_date", 0400, indio_dev->debugfs_dentry,
-               adis16480, &adis16480_firmware_date_fops);
-       debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
-               adis16480, &adis16480_serial_number_fops);
-       debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
-               adis16480, &adis16480_product_id_fops);
-       debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
-               adis16480, &adis16480_flash_count_fops);
+       debugfs_create_file_unsafe("firmware_date", 0400,
+               indio_dev->debugfs_dentry, adis16480,
+               &adis16480_firmware_date_fops);
+       debugfs_create_file_unsafe("serial_number", 0400,
+               indio_dev->debugfs_dentry, adis16480,
+               &adis16480_serial_number_fops);
+       debugfs_create_file_unsafe("product_id", 0400,
+               indio_dev->debugfs_dentry, adis16480,
+               &adis16480_product_id_fops);
+       debugfs_create_file_unsafe("flash_count", 0400,
+               indio_dev->debugfs_dentry, adis16480,
+               &adis16480_flash_count_fops);
 
        return 0;
 }
index dd6fc6d21f9d0c6057b6b5029800eef2fa82dacb..d78a10403bace100457193c64df2aa39a05b5fb0 100644 (file)
@@ -196,8 +196,7 @@ void inv_mpu_acpi_delete_mux_client(struct i2c_client *client)
 {
        struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(&client->dev));
 
-       if (st->mux_client)
-               i2c_unregister_device(st->mux_client);
+       i2c_unregister_device(st->mux_client);
 }
 #else
 
index e57337159b57ae2de8442737bcde769994e5d550..14f2eb6e9fb70054282c2fad9f52e2674efc033e 100644 (file)
@@ -16,7 +16,9 @@ config IIO_ST_LSM6DSX
 config IIO_ST_LSM6DSX_I2C
        tristate
        depends on IIO_ST_LSM6DSX
+       select REGMAP_I2C
 
 config IIO_ST_LSM6DSX_SPI
        tristate
        depends on IIO_ST_LSM6DSX
+       select REGMAP_SPI
index 4fdb7fcc3ea88193f14c66910678b6571b9463b6..8fdd723afa050bdefd41b90e86c831300674bfa6 100644 (file)
@@ -27,23 +27,12 @@ enum st_lsm6dsx_hw_id {
        ST_LSM6DSX_MAX_ID,
 };
 
+#define ST_LSM6DSX_BUFF_SIZE           256
 #define ST_LSM6DSX_CHAN_SIZE           2
 #define ST_LSM6DSX_SAMPLE_SIZE         6
-
-#if defined(CONFIG_SPI_MASTER)
-#define ST_LSM6DSX_RX_MAX_LENGTH       256
-#define ST_LSM6DSX_TX_MAX_LENGTH       8
-
-struct st_lsm6dsx_transfer_buffer {
-       u8 rx_buf[ST_LSM6DSX_RX_MAX_LENGTH];
-       u8 tx_buf[ST_LSM6DSX_TX_MAX_LENGTH] ____cacheline_aligned;
-};
-#endif /* CONFIG_SPI_MASTER */
-
-struct st_lsm6dsx_transfer_function {
-       int (*read)(struct device *dev, u8 addr, int len, u8 *data);
-       int (*write)(struct device *dev, u8 addr, int len, u8 *data);
-};
+#define ST_LSM6DSX_MAX_WORD_LEN                ((32 / ST_LSM6DSX_SAMPLE_SIZE) * \
+                                        ST_LSM6DSX_SAMPLE_SIZE)
+#define ST_LSM6DSX_SHIFT_VAL(val, mask)        (((val) << __ffs(mask)) & (mask))
 
 struct st_lsm6dsx_reg {
        u8 addr;
@@ -127,47 +116,43 @@ struct st_lsm6dsx_sensor {
 /**
  * struct st_lsm6dsx_hw - ST IMU MEMS hw instance
  * @dev: Pointer to instance of struct device (I2C or SPI).
+ * @regmap: Register map of the device.
  * @irq: Device interrupt line (I2C or SPI).
- * @lock: Mutex to protect read and write operations.
  * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO.
+ * @conf_lock: Mutex to prevent concurrent FIFO configuration update.
  * @fifo_mode: FIFO operating mode supported by the device.
  * @enable_mask: Enabled sensor bitmask.
  * @sip: Total number of samples (acc/gyro) in a given pattern.
+ * @buff: Device read buffer.
  * @iio_devs: Pointers to acc/gyro iio_dev instances.
  * @settings: Pointer to the specific sensor settings in use.
- * @tf: Transfer function structure used by I/O operations.
- * @tb: Transfer buffers used by SPI I/O operations.
  */
 struct st_lsm6dsx_hw {
        struct device *dev;
+       struct regmap *regmap;
        int irq;
 
-       struct mutex lock;
        struct mutex fifo_lock;
+       struct mutex conf_lock;
 
        enum st_lsm6dsx_fifo_mode fifo_mode;
        u8 enable_mask;
        u8 sip;
 
+       u8 *buff;
+
        struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX];
 
        const struct st_lsm6dsx_settings *settings;
-
-       const struct st_lsm6dsx_transfer_function *tf;
-#if defined(CONFIG_SPI_MASTER)
-       struct st_lsm6dsx_transfer_buffer tb;
-#endif /* CONFIG_SPI_MASTER */
 };
 
 extern const struct dev_pm_ops st_lsm6dsx_pm_ops;
 
 int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
-                    const struct st_lsm6dsx_transfer_function *tf_ops);
+                    struct regmap *regmap);
 int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor);
 int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor);
 int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw);
-int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
-                              u8 val);
 int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor,
                                u16 watermark);
 int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw);
index 755c472e8a05732ab0928b156af77f7b8fd8d471..1d6aa9b1a4cf19a0f4d91c1fede63199b9a572b7 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/iio/kfifo_buf.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/buffer.h>
+#include <linux/regmap.h>
+#include <linux/bitfield.h>
 
 #include <linux/platform_data/st_sensors_pdata.h>
 
@@ -120,8 +122,10 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
 
                dec_reg = &hw->settings->decimator[sensor->id];
                if (dec_reg->addr) {
-                       err = st_lsm6dsx_write_with_mask(hw, dec_reg->addr,
-                                                        dec_reg->mask, data);
+                       int val = ST_LSM6DSX_SHIFT_VAL(data, dec_reg->mask);
+
+                       err = regmap_update_bits(hw->regmap, dec_reg->addr,
+                                                dec_reg->mask, val);
                        if (err < 0)
                                return err;
                }
@@ -137,8 +141,10 @@ int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
 {
        int err;
 
-       err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_FIFO_MODE_ADDR,
-                                        ST_LSM6DSX_FIFO_MODE_MASK, fifo_mode);
+       err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_FIFO_MODE_ADDR,
+                                ST_LSM6DSX_FIFO_MODE_MASK,
+                                FIELD_PREP(ST_LSM6DSX_FIFO_MODE_MASK,
+                                           fifo_mode));
        if (err < 0)
                return err;
 
@@ -154,8 +160,9 @@ static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_sensor *sensor,
        u8 data;
 
        data = hw->enable_mask ? ST_LSM6DSX_MAX_FIFO_ODR_VAL : 0;
-       return st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_FIFO_MODE_ADDR,
-                                         ST_LSM6DSX_FIFO_ODR_MASK, data);
+       return regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_FIFO_MODE_ADDR,
+                                ST_LSM6DSX_FIFO_ODR_MASK,
+                                FIELD_PREP(ST_LSM6DSX_FIFO_ODR_MASK, data));
 }
 
 int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark)
@@ -163,9 +170,8 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark)
        u16 fifo_watermark = ~0, cur_watermark, sip = 0, fifo_th_mask;
        struct st_lsm6dsx_hw *hw = sensor->hw;
        struct st_lsm6dsx_sensor *cur_sensor;
+       int i, err, data;
        __le16 wdata;
-       int i, err;
-       u8 data;
 
        for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
                cur_sensor = iio_priv(hw->iio_devs[i]);
@@ -187,24 +193,42 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark)
        fifo_watermark = (fifo_watermark / sip) * sip;
        fifo_watermark = fifo_watermark * hw->settings->fifo_ops.th_wl;
 
-       mutex_lock(&hw->lock);
-
-       err = hw->tf->read(hw->dev, hw->settings->fifo_ops.fifo_th.addr + 1,
-                          sizeof(data), &data);
+       err = regmap_read(hw->regmap, hw->settings->fifo_ops.fifo_th.addr + 1,
+                         &data);
        if (err < 0)
-               goto out;
+               return err;
 
        fifo_th_mask = hw->settings->fifo_ops.fifo_th.mask;
        fifo_watermark = ((data << 8) & ~fifo_th_mask) |
                         (fifo_watermark & fifo_th_mask);
 
        wdata = cpu_to_le16(fifo_watermark);
-       err = hw->tf->write(hw->dev, hw->settings->fifo_ops.fifo_th.addr,
-                           sizeof(wdata), (u8 *)&wdata);
-out:
-       mutex_unlock(&hw->lock);
+       return regmap_bulk_write(hw->regmap,
+                                hw->settings->fifo_ops.fifo_th.addr,
+                                &wdata, sizeof(wdata));
+}
 
-       return err < 0 ? err : 0;
+/*
+ * Set max bulk read to ST_LSM6DSX_MAX_WORD_LEN in order to avoid
+ * a kmalloc for each bus access
+ */
+static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 *data,
+                                       unsigned int data_len)
+{
+       unsigned int word_len, read_len = 0;
+       int err;
+
+       while (read_len < data_len) {
+               word_len = min_t(unsigned int, data_len - read_len,
+                                ST_LSM6DSX_MAX_WORD_LEN);
+               err = regmap_bulk_read(hw->regmap,
+                                      ST_LSM6DSX_REG_FIFO_OUTL_ADDR,
+                                      data + read_len, word_len);
+               if (err < 0)
+                       return err;
+               read_len += word_len;
+       }
+       return 0;
 }
 
 /**
@@ -223,11 +247,11 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
        struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor;
        s64 acc_ts, acc_delta_ts, gyro_ts, gyro_delta_ts;
        u8 iio_buff[ALIGN(ST_LSM6DSX_SAMPLE_SIZE, sizeof(s64)) + sizeof(s64)];
-       u8 buff[pattern_len];
        __le16 fifo_status;
 
-       err = hw->tf->read(hw->dev, hw->settings->fifo_ops.fifo_diff.addr,
-                          sizeof(fifo_status), (u8 *)&fifo_status);
+       err = regmap_bulk_read(hw->regmap,
+                              hw->settings->fifo_ops.fifo_diff.addr,
+                              &fifo_status, sizeof(fifo_status));
        if (err < 0)
                return err;
 
@@ -255,8 +279,7 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
                                samples);
 
        for (read_len = 0; read_len < fifo_len; read_len += pattern_len) {
-               err = hw->tf->read(hw->dev, ST_LSM6DSX_REG_FIFO_OUTL_ADDR,
-                                  sizeof(buff), buff);
+               err = st_lsm6dsx_read_block(hw, hw->buff, pattern_len);
                if (err < 0)
                        return err;
 
@@ -281,7 +304,7 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
 
                while (acc_sip > 0 || gyro_sip > 0) {
                        if (gyro_sip-- > 0) {
-                               memcpy(iio_buff, &buff[offset],
+                               memcpy(iio_buff, &hw->buff[offset],
                                       ST_LSM6DSX_SAMPLE_SIZE);
                                iio_push_to_buffers_with_timestamp(
                                        hw->iio_devs[ST_LSM6DSX_ID_GYRO],
@@ -291,7 +314,7 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
                        }
 
                        if (acc_sip-- > 0) {
-                               memcpy(iio_buff, &buff[offset],
+                               memcpy(iio_buff, &hw->buff[offset],
                                       ST_LSM6DSX_SAMPLE_SIZE);
                                iio_push_to_buffers_with_timestamp(
                                        hw->iio_devs[ST_LSM6DSX_ID_ACC],
@@ -325,38 +348,40 @@ static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
        struct st_lsm6dsx_hw *hw = sensor->hw;
        int err;
 
+       mutex_lock(&hw->conf_lock);
+
        if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) {
                err = st_lsm6dsx_flush_fifo(hw);
                if (err < 0)
-                       return err;
+                       goto out;
        }
 
        if (enable) {
                err = st_lsm6dsx_sensor_enable(sensor);
                if (err < 0)
-                       return err;
+                       goto out;
        } else {
                err = st_lsm6dsx_sensor_disable(sensor);
                if (err < 0)
-                       return err;
+                       goto out;
        }
 
        err = st_lsm6dsx_set_fifo_odr(sensor, enable);
        if (err < 0)
-               return err;
+               goto out;
 
        err = st_lsm6dsx_update_decimators(hw);
        if (err < 0)
-               return err;
+               goto out;
 
        err = st_lsm6dsx_update_watermark(sensor, sensor->watermark);
        if (err < 0)
-               return err;
+               goto out;
 
        if (hw->enable_mask) {
                err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
                if (err < 0)
-                       return err;
+                       goto out;
 
                /*
                 * store enable buffer timestamp as reference to compute
@@ -365,7 +390,10 @@ static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
                sensor->ts = iio_get_time_ns(iio_dev);
        }
 
-       return 0;
+out:
+       mutex_unlock(&hw->conf_lock);
+
+       return err;
 }
 
 static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private)
@@ -444,17 +472,20 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
                return -EINVAL;
        }
 
-       err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_HLACTIVE_ADDR,
-                                        ST_LSM6DSX_REG_HLACTIVE_MASK,
-                                        irq_active_low);
+       err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_HLACTIVE_ADDR,
+                                ST_LSM6DSX_REG_HLACTIVE_MASK,
+                                FIELD_PREP(ST_LSM6DSX_REG_HLACTIVE_MASK,
+                                           irq_active_low));
        if (err < 0)
                return err;
 
        pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
        if ((np && of_property_read_bool(np, "drive-open-drain")) ||
            (pdata && pdata->open_drain)) {
-               err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_PP_OD_ADDR,
-                                                ST_LSM6DSX_REG_PP_OD_MASK, 1);
+               err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_PP_OD_ADDR,
+                                        ST_LSM6DSX_REG_PP_OD_MASK,
+                                        FIELD_PREP(ST_LSM6DSX_REG_PP_OD_MASK,
+                                                   1));
                if (err < 0)
                        return err;
 
index 239c735242bee596ce5c808a21f46f59a3806604..c2fa3239b9c64584ddf14eebb6b307d6b53f997d 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/bitfield.h>
 
 #include <linux/platform_data/st_sensors_pdata.h>
 
@@ -277,36 +279,9 @@ static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
-int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
-                              u8 val)
-{
-       u8 data;
-       int err;
-
-       mutex_lock(&hw->lock);
-
-       err = hw->tf->read(hw->dev, addr, sizeof(data), &data);
-       if (err < 0) {
-               dev_err(hw->dev, "failed to read %02x register\n", addr);
-               goto out;
-       }
-
-       data = (data & ~mask) | ((val << __ffs(mask)) & mask);
-
-       err = hw->tf->write(hw->dev, addr, sizeof(data), &data);
-       if (err < 0)
-               dev_err(hw->dev, "failed to write %02x register\n", addr);
-
-out:
-       mutex_unlock(&hw->lock);
-
-       return err;
-}
-
 static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id)
 {
-       int err, i, j;
-       u8 data;
+       int err, i, j, data;
 
        for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
                for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) {
@@ -322,8 +297,7 @@ static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id)
                return -ENODEV;
        }
 
-       err = hw->tf->read(hw->dev, ST_LSM6DSX_REG_WHOAMI_ADDR, sizeof(data),
-                          &data);
+       err = regmap_read(hw->regmap, ST_LSM6DSX_REG_WHOAMI_ADDR, &data);
        if (err < 0) {
                dev_err(hw->dev, "failed to read whoami register\n");
                return err;
@@ -342,22 +316,22 @@ static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id)
 static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor,
                                     u32 gain)
 {
-       enum st_lsm6dsx_sensor_id id = sensor->id;
+       struct st_lsm6dsx_hw *hw = sensor->hw;
+       const struct st_lsm6dsx_reg *reg;
        int i, err;
        u8 val;
 
        for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++)
-               if (st_lsm6dsx_fs_table[id].fs_avl[i].gain == gain)
+               if (st_lsm6dsx_fs_table[sensor->id].fs_avl[i].gain == gain)
                        break;
 
        if (i == ST_LSM6DSX_FS_LIST_SIZE)
                return -EINVAL;
 
-       val = st_lsm6dsx_fs_table[id].fs_avl[i].val;
-       err = st_lsm6dsx_write_with_mask(sensor->hw,
-                                        st_lsm6dsx_fs_table[id].reg.addr,
-                                        st_lsm6dsx_fs_table[id].reg.mask,
-                                        val);
+       val = st_lsm6dsx_fs_table[sensor->id].fs_avl[i].val;
+       reg = &st_lsm6dsx_fs_table[sensor->id].reg;
+       err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+                                ST_LSM6DSX_SHIFT_VAL(val, reg->mask));
        if (err < 0)
                return err;
 
@@ -385,7 +359,8 @@ static int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr,
 
 static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
 {
-       enum st_lsm6dsx_sensor_id id = sensor->id;
+       struct st_lsm6dsx_hw *hw = sensor->hw;
+       const struct st_lsm6dsx_reg *reg;
        int err;
        u8 val;
 
@@ -393,10 +368,9 @@ static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
        if (err < 0)
                return err;
 
-       return st_lsm6dsx_write_with_mask(sensor->hw,
-                                         st_lsm6dsx_odr_table[id].reg.addr,
-                                         st_lsm6dsx_odr_table[id].reg.mask,
-                                         val);
+       reg = &st_lsm6dsx_odr_table[sensor->id].reg;
+       return regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+                                 ST_LSM6DSX_SHIFT_VAL(val, reg->mask));
 }
 
 int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor)
@@ -414,16 +388,17 @@ int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor)
 
 int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor)
 {
-       enum st_lsm6dsx_sensor_id id = sensor->id;
+       struct st_lsm6dsx_hw *hw = sensor->hw;
+       const struct st_lsm6dsx_reg *reg;
        int err;
 
-       err = st_lsm6dsx_write_with_mask(sensor->hw,
-                                        st_lsm6dsx_odr_table[id].reg.addr,
-                                        st_lsm6dsx_odr_table[id].reg.mask, 0);
+       reg = &st_lsm6dsx_odr_table[sensor->id].reg;
+       err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+                                ST_LSM6DSX_SHIFT_VAL(0, reg->mask));
        if (err < 0)
                return err;
 
-       sensor->hw->enable_mask &= ~BIT(id);
+       sensor->hw->enable_mask &= ~BIT(sensor->id);
 
        return 0;
 }
@@ -431,6 +406,7 @@ int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor)
 static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
                                   u8 addr, int *val)
 {
+       struct st_lsm6dsx_hw *hw = sensor->hw;
        int err, delay;
        __le16 data;
 
@@ -441,14 +417,13 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
        delay = 1000000 / sensor->odr;
        usleep_range(delay, 2 * delay);
 
-       err = sensor->hw->tf->read(sensor->hw->dev, addr, sizeof(data),
-                                  (u8 *)&data);
+       err = regmap_bulk_read(hw->regmap, addr, &data, sizeof(data));
        if (err < 0)
                return err;
 
        st_lsm6dsx_sensor_disable(sensor);
 
-       *val = (s16)data;
+       *val = (s16)le16_to_cpu(data);
 
        return IIO_VAL_INT;
 }
@@ -528,7 +503,12 @@ static int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val)
        if (val < 1 || val > hw->settings->max_fifo_size)
                return -EINVAL;
 
+       mutex_lock(&hw->conf_lock);
+
        err = st_lsm6dsx_update_watermark(sensor, val);
+
+       mutex_unlock(&hw->conf_lock);
+
        if (err < 0)
                return err;
 
@@ -652,20 +632,20 @@ static int st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, u8 *drdy_reg)
 
 static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
 {
-       u8 data, drdy_int_reg;
+       u8 drdy_int_reg;
        int err;
 
-       data = ST_LSM6DSX_REG_RESET_MASK;
-       err = hw->tf->write(hw->dev, ST_LSM6DSX_REG_RESET_ADDR, sizeof(data),
-                           &data);
+       err = regmap_write(hw->regmap, ST_LSM6DSX_REG_RESET_ADDR,
+                          ST_LSM6DSX_REG_RESET_MASK);
        if (err < 0)
                return err;
 
        msleep(200);
 
        /* enable Block Data Update */
-       err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_BDU_ADDR,
-                                        ST_LSM6DSX_REG_BDU_MASK, 1);
+       err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_BDU_ADDR,
+                                ST_LSM6DSX_REG_BDU_MASK,
+                                FIELD_PREP(ST_LSM6DSX_REG_BDU_MASK, 1));
        if (err < 0)
                return err;
 
@@ -674,8 +654,10 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
        if (err < 0)
                return err;
 
-       return st_lsm6dsx_write_with_mask(hw, drdy_int_reg,
-                                         ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK, 1);
+       return regmap_update_bits(hw->regmap, drdy_int_reg,
+                                 ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK,
+                                 FIELD_PREP(ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK,
+                                            1));
 }
 
 static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
@@ -726,7 +708,7 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
 }
 
 int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
-                    const struct st_lsm6dsx_transfer_function *tf_ops)
+                    struct regmap *regmap)
 {
        struct st_lsm6dsx_hw *hw;
        int i, err;
@@ -737,12 +719,16 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
 
        dev_set_drvdata(dev, (void *)hw);
 
-       mutex_init(&hw->lock);
        mutex_init(&hw->fifo_lock);
+       mutex_init(&hw->conf_lock);
+
+       hw->buff = devm_kzalloc(dev, ST_LSM6DSX_BUFF_SIZE, GFP_KERNEL);
+       if (!hw->buff)
+               return -ENOMEM;
 
        hw->dev = dev;
        hw->irq = irq;
-       hw->tf = tf_ops;
+       hw->regmap = regmap;
 
        err = st_lsm6dsx_check_whoami(hw, hw_id);
        if (err < 0)
@@ -778,6 +764,7 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
 {
        struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
        struct st_lsm6dsx_sensor *sensor;
+       const struct st_lsm6dsx_reg *reg;
        int i, err = 0;
 
        for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
@@ -785,9 +772,9 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
                if (!(hw->enable_mask & BIT(sensor->id)))
                        continue;
 
-               err = st_lsm6dsx_write_with_mask(hw,
-                               st_lsm6dsx_odr_table[sensor->id].reg.addr,
-                               st_lsm6dsx_odr_table[sensor->id].reg.mask, 0);
+               reg = &st_lsm6dsx_odr_table[sensor->id].reg;
+               err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+                                        ST_LSM6DSX_SHIFT_VAL(0, reg->mask));
                if (err < 0)
                        return err;
        }
index 305fec712ab043669619a6a0bbcff692d1ca804e..41525dd2aab70334b31e89131ced33d76e954aa2 100644 (file)
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/regmap.h>
 
 #include "st_lsm6dsx.h"
 
-static int st_lsm6dsx_i2c_read(struct device *dev, u8 addr, int len, u8 *data)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       struct i2c_msg msg[2];
-
-       msg[0].addr = client->addr;
-       msg[0].flags = client->flags;
-       msg[0].len = 1;
-       msg[0].buf = &addr;
-
-       msg[1].addr = client->addr;
-       msg[1].flags = client->flags | I2C_M_RD;
-       msg[1].len = len;
-       msg[1].buf = data;
-
-       return i2c_transfer(client->adapter, msg, 2);
-}
-
-static int st_lsm6dsx_i2c_write(struct device *dev, u8 addr, int len, u8 *data)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       struct i2c_msg msg;
-       u8 send[len + 1];
-
-       send[0] = addr;
-       memcpy(&send[1], data, len * sizeof(u8));
-
-       msg.addr = client->addr;
-       msg.flags = client->flags;
-       msg.len = len + 1;
-       msg.buf = send;
-
-       return i2c_transfer(client->adapter, &msg, 1);
-}
-
-static const struct st_lsm6dsx_transfer_function st_lsm6dsx_transfer_fn = {
-       .read = st_lsm6dsx_i2c_read,
-       .write = st_lsm6dsx_i2c_write,
+static const struct regmap_config st_lsm6dsx_i2c_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
 };
 
 static int st_lsm6dsx_i2c_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
+       int hw_id = id->driver_data;
+       struct regmap *regmap;
+
+       regmap = devm_regmap_init_i2c(client, &st_lsm6dsx_i2c_regmap_config);
+       if (IS_ERR(regmap)) {
+               dev_err(&client->dev, "Failed to register i2c regmap %d\n",
+                       (int)PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
        return st_lsm6dsx_probe(&client->dev, client->irq,
-                               (int)id->driver_data, id->name,
-                               &st_lsm6dsx_transfer_fn);
+                               hw_id, id->name, regmap);
 }
 
 static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
index 95472f153ad2f181f2139a9a4f0f26a6f18e881c..2c813583447934f5141798e27d7429510deef787 100644 (file)
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/regmap.h>
 
 #include "st_lsm6dsx.h"
 
-#define SENSORS_SPI_READ       BIT(7)
-
-static int st_lsm6dsx_spi_read(struct device *dev, u8 addr, int len,
-                              u8 *data)
-{
-       struct spi_device *spi = to_spi_device(dev);
-       struct st_lsm6dsx_hw *hw = spi_get_drvdata(spi);
-       int err;
-
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = hw->tb.tx_buf,
-                       .bits_per_word = 8,
-                       .len = 1,
-               },
-               {
-                       .rx_buf = hw->tb.rx_buf,
-                       .bits_per_word = 8,
-                       .len = len,
-               }
-       };
-
-       hw->tb.tx_buf[0] = addr | SENSORS_SPI_READ;
-
-       err = spi_sync_transfer(spi, xfers,  ARRAY_SIZE(xfers));
-       if (err < 0)
-               return err;
-
-       memcpy(data, hw->tb.rx_buf, len * sizeof(u8));
-
-       return len;
-}
-
-static int st_lsm6dsx_spi_write(struct device *dev, u8 addr, int len,
-                               u8 *data)
-{
-       struct st_lsm6dsx_hw *hw;
-       struct spi_device *spi;
-
-       if (len >= ST_LSM6DSX_TX_MAX_LENGTH)
-               return -ENOMEM;
-
-       spi = to_spi_device(dev);
-       hw = spi_get_drvdata(spi);
-
-       hw->tb.tx_buf[0] = addr;
-       memcpy(&hw->tb.tx_buf[1], data, len);
-
-       return spi_write(spi, hw->tb.tx_buf, len + 1);
-}
-
-static const struct st_lsm6dsx_transfer_function st_lsm6dsx_transfer_fn = {
-       .read = st_lsm6dsx_spi_read,
-       .write = st_lsm6dsx_spi_write,
+static const struct regmap_config st_lsm6dsx_spi_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
 };
 
 static int st_lsm6dsx_spi_probe(struct spi_device *spi)
 {
        const struct spi_device_id *id = spi_get_device_id(spi);
+       int hw_id = id->driver_data;
+       struct regmap *regmap;
+
+       regmap = devm_regmap_init_spi(spi, &st_lsm6dsx_spi_regmap_config);
+       if (IS_ERR(regmap)) {
+               dev_err(&spi->dev, "Failed to register spi regmap %d\n",
+                       (int)PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
 
        return st_lsm6dsx_probe(&spi->dev, spi->irq,
-                               (int)id->driver_data, id->name,
-                               &st_lsm6dsx_transfer_fn);
+                               hw_id, id->name, regmap);
 }
 
 static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
index 0bc2fe31f211f0c3fe5ff3e101e62cd67ce6560c..6184c100a94a5cd0f7e94aa998db50b898522bda 100644 (file)
@@ -1198,6 +1198,18 @@ out:
        return ret ? ret : len;
 }
 
+static ssize_t iio_dma_show_data_available(struct device *dev,
+                                               struct device_attribute *attr,
+                                               char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       size_t bytes;
+
+       bytes = iio_buffer_data_available(indio_dev->buffer);
+
+       return sprintf(buf, "%zu\n", bytes);
+}
+
 static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length,
                   iio_buffer_write_length);
 static struct device_attribute dev_attr_length_ro = __ATTR(length,
@@ -1208,11 +1220,14 @@ static DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR,
                   iio_buffer_show_watermark, iio_buffer_store_watermark);
 static struct device_attribute dev_attr_watermark_ro = __ATTR(watermark,
        S_IRUGO, iio_buffer_show_watermark, NULL);
+static DEVICE_ATTR(data_available, S_IRUGO,
+               iio_dma_show_data_available, NULL);
 
 static struct attribute *iio_buffer_attrs[] = {
        &dev_attr_length.attr,
        &dev_attr_enable.attr,
        &dev_attr_watermark.attr,
+       &dev_attr_data_available.attr,
 };
 
 int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
index 2f0998ebeed214dc0f062664595e1d4362d27e3e..19bdf3d2962ab9bcc1f8b86bc3d2bb5db5587215 100644 (file)
@@ -588,6 +588,7 @@ static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type,
                return snprintf(buf, len, "%d", vals[0]);
        case IIO_VAL_INT_PLUS_MICRO_DB:
                scale_db = true;
+               /* fall through */
        case IIO_VAL_INT_PLUS_MICRO:
                if (vals[1] < 0)
                        return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
index 2356ed9285df6c5796a114083f188b6a8c072267..93fd421b10d73f3ea5dbfe3c0c669744c55eb26c 100644 (file)
@@ -334,6 +334,30 @@ config STK3310
         Choosing M will build the driver as a module. If so, the module
         will be called stk3310.
 
+config ST_UVIS25
+       tristate "STMicroelectronics UVIS25 sensor driver"
+       depends on (I2C || SPI)
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+       select ST_UVIS25_I2C if (I2C)
+       select ST_UVIS25_SPI if (SPI_MASTER)
+       help
+         Say yes here to build support for STMicroelectronics UVIS25
+         uv sensor
+
+         To compile this driver as a module, choose M here: the module
+         will be called st_uvis25.
+
+config ST_UVIS25_I2C
+       tristate
+       depends on ST_UVIS25
+       select REGMAP_I2C
+
+config ST_UVIS25_SPI
+       tristate
+       depends on ST_UVIS25
+       select REGMAP_SPI
+
 config TCS3414
        tristate "TAOS TCS3414 digital color sensor"
        depends on I2C
@@ -425,4 +449,14 @@ config VL6180
         To compile this driver as a module, choose M here: the
         module will be called vl6180.
 
+config ZOPT2201
+       tristate "ZOPT2201 ALS and UV B sensor"
+       depends on I2C
+       help
+        Say Y here if you want to build a driver for the IDT
+        ZOPT2201 ambient light and UV B sensor.
+
+        To compile this driver as a module, choose M here: the
+        module will be called zopt2201.
+
 endmenu
index c263469b7ce9ef38c69707880d6117e44359bf19..f714067a78169406e7dee471269e460ac2218ed8 100644 (file)
@@ -33,6 +33,9 @@ obj-$(CONFIG_RPR0521)         += rpr0521.o
 obj-$(CONFIG_SENSORS_TSL2563)  += tsl2563.o
 obj-$(CONFIG_SI1145)           += si1145.o
 obj-$(CONFIG_STK3310)          += stk3310.o
+obj-$(CONFIG_ST_UVIS25)                += st_uvis25_core.o
+obj-$(CONFIG_ST_UVIS25_I2C)    += st_uvis25_i2c.o
+obj-$(CONFIG_ST_UVIS25_SPI)    += st_uvis25_spi.o
 obj-$(CONFIG_TCS3414)          += tcs3414.o
 obj-$(CONFIG_TCS3472)          += tcs3472.o
 obj-$(CONFIG_TSL2583)          += tsl2583.o
@@ -41,3 +44,4 @@ obj-$(CONFIG_US5182D)         += us5182d.o
 obj-$(CONFIG_VCNL4000)         += vcnl4000.o
 obj-$(CONFIG_VEML6070)         += veml6070.o
 obj-$(CONFIG_VL6180)           += vl6180.o
+obj-$(CONFIG_ZOPT2201)         += zopt2201.o
index b2a46b390d5c08c14896e09bd9d78bf6a89e2780..acfad4aeb27aff4a51fbb979ca6c219c920926d4 100644 (file)
@@ -181,7 +181,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
-       struct cros_ec_device *ec_device;
        struct iio_dev *indio_dev;
        struct cros_ec_light_prox_state *state;
        struct iio_chan_spec *channel;
@@ -191,7 +190,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev)
                dev_warn(dev, "No CROS EC device found.\n");
                return -EINVAL;
        }
-       ec_device = ec_dev->ec_dev;
 
        indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
        if (!indio_dev)
diff --git a/drivers/iio/light/st_uvis25.h b/drivers/iio/light/st_uvis25.h
new file mode 100644 (file)
index 0000000..5e970ab
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * STMicroelectronics uvis25 sensor driver
+ *
+ * Copyright 2017 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_UVIS25_H
+#define ST_UVIS25_H
+
+#define ST_UVIS25_DEV_NAME             "uvis25"
+
+#include <linux/iio/iio.h>
+
+/**
+ * struct st_uvis25_hw - ST UVIS25 sensor instance
+ * @regmap: Register map of the device.
+ * @trig: The trigger in use by the driver.
+ * @enabled: Status of the sensor (false->off, true->on).
+ * @irq: Device interrupt line (I2C or SPI).
+ */
+struct st_uvis25_hw {
+       struct regmap *regmap;
+
+       struct iio_trigger *trig;
+       bool enabled;
+       int irq;
+};
+
+extern const struct dev_pm_ops st_uvis25_pm_ops;
+
+int st_uvis25_probe(struct device *dev, int irq, struct regmap *regmap);
+
+#endif /* ST_UVIS25_H */
diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c
new file mode 100644 (file)
index 0000000..3026358
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * STMicroelectronics uvis25 sensor driver
+ *
+ * Copyright 2017 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/iio/sysfs.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/buffer.h>
+#include <linux/regmap.h>
+
+#include "st_uvis25.h"
+
+#define ST_UVIS25_REG_WHOAMI_ADDR      0x0f
+#define ST_UVIS25_REG_WHOAMI_VAL       0xca
+#define ST_UVIS25_REG_CTRL1_ADDR       0x20
+#define ST_UVIS25_REG_ODR_MASK         BIT(0)
+#define ST_UVIS25_REG_BDU_MASK         BIT(1)
+#define ST_UVIS25_REG_CTRL2_ADDR       0x21
+#define ST_UVIS25_REG_BOOT_MASK                BIT(7)
+#define ST_UVIS25_REG_CTRL3_ADDR       0x22
+#define ST_UVIS25_REG_HL_MASK          BIT(7)
+#define ST_UVIS25_REG_STATUS_ADDR      0x27
+#define ST_UVIS25_REG_UV_DA_MASK       BIT(0)
+#define ST_UVIS25_REG_OUT_ADDR         0x28
+
+static const struct iio_chan_spec st_uvis25_channels[] = {
+       {
+               .type = IIO_UVINDEX,
+               .address = ST_UVIS25_REG_OUT_ADDR,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+               .scan_index = 0,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 8,
+                       .storagebits = 8,
+               },
+       },
+       IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int st_uvis25_check_whoami(struct st_uvis25_hw *hw)
+{
+       int err, data;
+
+       err = regmap_read(hw->regmap, ST_UVIS25_REG_WHOAMI_ADDR, &data);
+       if (err < 0) {
+               dev_err(regmap_get_device(hw->regmap),
+                       "failed to read whoami register\n");
+               return err;
+       }
+
+       if (data != ST_UVIS25_REG_WHOAMI_VAL) {
+               dev_err(regmap_get_device(hw->regmap),
+                       "wrong whoami {%02x vs %02x}\n",
+                       data, ST_UVIS25_REG_WHOAMI_VAL);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int st_uvis25_set_enable(struct st_uvis25_hw *hw, bool enable)
+{
+       int err;
+
+       err = regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR,
+                                ST_UVIS25_REG_ODR_MASK, enable);
+       if (err < 0)
+               return err;
+
+       hw->enabled = enable;
+
+       return 0;
+}
+
+static int st_uvis25_read_oneshot(struct st_uvis25_hw *hw, u8 addr, int *val)
+{
+       int err;
+
+       err = st_uvis25_set_enable(hw, true);
+       if (err < 0)
+               return err;
+
+       msleep(1500);
+
+       /*
+        * in order to avoid possible race conditions with interrupt
+        * generation, disable the sensor first and then poll output
+        * register. That sequence guarantees the interrupt will be reset
+        * when irq line is unmasked
+        */
+       err = st_uvis25_set_enable(hw, false);
+       if (err < 0)
+               return err;
+
+       err = regmap_read(hw->regmap, addr, val);
+
+       return err < 0 ? err : IIO_VAL_INT;
+}
+
+static int st_uvis25_read_raw(struct iio_dev *iio_dev,
+                             struct iio_chan_spec const *ch,
+                             int *val, int *val2, long mask)
+{
+       int ret;
+
+       ret = iio_device_claim_direct_mode(iio_dev);
+       if (ret)
+               return ret;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_PROCESSED: {
+               struct st_uvis25_hw *hw = iio_priv(iio_dev);
+
+               /*
+                * mask irq line during oneshot read since the sensor
+                * does not export the capability to disable data-ready line
+                * in the register map and it is enabled by default.
+                * If the line is unmasked during read_raw() it will be set
+                * active and never reset since the trigger is disabled
+                */
+               if (hw->irq > 0)
+                       disable_irq(hw->irq);
+               ret = st_uvis25_read_oneshot(hw, ch->address, val);
+               if (hw->irq > 0)
+                       enable_irq(hw->irq);
+               break;
+       }
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       iio_device_release_direct_mode(iio_dev);
+
+       return ret;
+}
+
+static irqreturn_t st_uvis25_trigger_handler_thread(int irq, void *private)
+{
+       struct st_uvis25_hw *hw = private;
+       int err, status;
+
+       err = regmap_read(hw->regmap, ST_UVIS25_REG_STATUS_ADDR, &status);
+       if (err < 0)
+               return IRQ_HANDLED;
+
+       if (!(status & ST_UVIS25_REG_UV_DA_MASK))
+               return IRQ_NONE;
+
+       iio_trigger_poll_chained(hw->trig);
+
+       return IRQ_HANDLED;
+}
+
+static int st_uvis25_allocate_trigger(struct iio_dev *iio_dev)
+{
+       struct st_uvis25_hw *hw = iio_priv(iio_dev);
+       struct device *dev = regmap_get_device(hw->regmap);
+       bool irq_active_low = false;
+       unsigned long irq_type;
+       int err;
+
+       irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
+
+       switch (irq_type) {
+       case IRQF_TRIGGER_HIGH:
+       case IRQF_TRIGGER_RISING:
+               break;
+       case IRQF_TRIGGER_LOW:
+       case IRQF_TRIGGER_FALLING:
+               irq_active_low = true;
+               break;
+       default:
+               dev_info(dev, "mode %lx unsupported\n", irq_type);
+               return -EINVAL;
+       }
+
+       err = regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL3_ADDR,
+                                ST_UVIS25_REG_HL_MASK, irq_active_low);
+       if (err < 0)
+               return err;
+
+       err = devm_request_threaded_irq(dev, hw->irq, NULL,
+                                       st_uvis25_trigger_handler_thread,
+                                       irq_type | IRQF_ONESHOT,
+                                       iio_dev->name, hw);
+       if (err) {
+               dev_err(dev, "failed to request trigger irq %d\n",
+                       hw->irq);
+               return err;
+       }
+
+       hw->trig = devm_iio_trigger_alloc(dev, "%s-trigger",
+                                         iio_dev->name);
+       if (!hw->trig)
+               return -ENOMEM;
+
+       iio_trigger_set_drvdata(hw->trig, iio_dev);
+       hw->trig->dev.parent = dev;
+
+       return devm_iio_trigger_register(dev, hw->trig);
+}
+
+static int st_uvis25_buffer_preenable(struct iio_dev *iio_dev)
+{
+       return st_uvis25_set_enable(iio_priv(iio_dev), true);
+}
+
+static int st_uvis25_buffer_postdisable(struct iio_dev *iio_dev)
+{
+       return st_uvis25_set_enable(iio_priv(iio_dev), false);
+}
+
+static const struct iio_buffer_setup_ops st_uvis25_buffer_ops = {
+       .preenable = st_uvis25_buffer_preenable,
+       .postenable = iio_triggered_buffer_postenable,
+       .predisable = iio_triggered_buffer_predisable,
+       .postdisable = st_uvis25_buffer_postdisable,
+};
+
+static irqreturn_t st_uvis25_buffer_handler_thread(int irq, void *p)
+{
+       u8 buffer[ALIGN(sizeof(u8), sizeof(s64)) + sizeof(s64)];
+       struct iio_poll_func *pf = p;
+       struct iio_dev *iio_dev = pf->indio_dev;
+       struct st_uvis25_hw *hw = iio_priv(iio_dev);
+       int err;
+
+       err = regmap_read(hw->regmap, ST_UVIS25_REG_OUT_ADDR, (int *)buffer);
+       if (err < 0)
+               goto out;
+
+       iio_push_to_buffers_with_timestamp(iio_dev, buffer,
+                                          iio_get_time_ns(iio_dev));
+
+out:
+       iio_trigger_notify_done(hw->trig);
+
+       return IRQ_HANDLED;
+}
+
+static int st_uvis25_allocate_buffer(struct iio_dev *iio_dev)
+{
+       struct st_uvis25_hw *hw = iio_priv(iio_dev);
+
+       return devm_iio_triggered_buffer_setup(regmap_get_device(hw->regmap),
+                                              iio_dev, NULL,
+                                              st_uvis25_buffer_handler_thread,
+                                              &st_uvis25_buffer_ops);
+}
+
+static const struct iio_info st_uvis25_info = {
+       .read_raw = st_uvis25_read_raw,
+};
+
+static int st_uvis25_init_sensor(struct st_uvis25_hw *hw)
+{
+       int err;
+
+       err = regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL2_ADDR,
+                                ST_UVIS25_REG_BOOT_MASK, 1);
+       if (err < 0)
+               return err;
+
+       msleep(2000);
+
+       return regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR,
+                                 ST_UVIS25_REG_BDU_MASK, 1);
+}
+
+int st_uvis25_probe(struct device *dev, int irq, struct regmap *regmap)
+{
+       struct st_uvis25_hw *hw;
+       struct iio_dev *iio_dev;
+       int err;
+
+       iio_dev = devm_iio_device_alloc(dev, sizeof(*hw));
+       if (!iio_dev)
+               return -ENOMEM;
+
+       dev_set_drvdata(dev, (void *)iio_dev);
+
+       hw = iio_priv(iio_dev);
+       hw->irq = irq;
+       hw->regmap = regmap;
+
+       err = st_uvis25_check_whoami(hw);
+       if (err < 0)
+               return err;
+
+       iio_dev->modes = INDIO_DIRECT_MODE;
+       iio_dev->dev.parent = dev;
+       iio_dev->channels = st_uvis25_channels;
+       iio_dev->num_channels = ARRAY_SIZE(st_uvis25_channels);
+       iio_dev->name = ST_UVIS25_DEV_NAME;
+       iio_dev->info = &st_uvis25_info;
+
+       err = st_uvis25_init_sensor(hw);
+       if (err < 0)
+               return err;
+
+       if (hw->irq > 0) {
+               err = st_uvis25_allocate_buffer(iio_dev);
+               if (err < 0)
+                       return err;
+
+               err = st_uvis25_allocate_trigger(iio_dev);
+               if (err)
+                       return err;
+       }
+
+       return devm_iio_device_register(dev, iio_dev);
+}
+EXPORT_SYMBOL(st_uvis25_probe);
+
+static int __maybe_unused st_uvis25_suspend(struct device *dev)
+{
+       struct iio_dev *iio_dev = dev_get_drvdata(dev);
+       struct st_uvis25_hw *hw = iio_priv(iio_dev);
+
+       return regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR,
+                                 ST_UVIS25_REG_ODR_MASK, 0);
+}
+
+static int __maybe_unused st_uvis25_resume(struct device *dev)
+{
+       struct iio_dev *iio_dev = dev_get_drvdata(dev);
+       struct st_uvis25_hw *hw = iio_priv(iio_dev);
+
+       if (hw->enabled)
+               return regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR,
+                                         ST_UVIS25_REG_ODR_MASK, 1);
+
+       return 0;
+}
+
+const struct dev_pm_ops st_uvis25_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(st_uvis25_suspend, st_uvis25_resume)
+};
+EXPORT_SYMBOL(st_uvis25_pm_ops);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
+MODULE_DESCRIPTION("STMicroelectronics uvis25 sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/st_uvis25_i2c.c b/drivers/iio/light/st_uvis25_i2c.c
new file mode 100644 (file)
index 0000000..afd6eb0
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * STMicroelectronics uvis25 i2c driver
+ *
+ * Copyright 2017 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+
+#include "st_uvis25.h"
+
+#define UVIS25_I2C_AUTO_INCREMENT      BIT(7)
+
+static const struct regmap_config st_uvis25_i2c_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .write_flag_mask = UVIS25_I2C_AUTO_INCREMENT,
+       .read_flag_mask = UVIS25_I2C_AUTO_INCREMENT,
+};
+
+static int st_uvis25_i2c_probe(struct i2c_client *client,
+                              const struct i2c_device_id *id)
+{
+       struct regmap *regmap;
+
+       regmap = devm_regmap_init_i2c(client, &st_uvis25_i2c_regmap_config);
+       if (IS_ERR(regmap)) {
+               dev_err(&client->dev, "Failed to register i2c regmap %d\n",
+                       (int)PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
+       return st_uvis25_probe(&client->dev, client->irq, regmap);
+}
+
+static const struct of_device_id st_uvis25_i2c_of_match[] = {
+       { .compatible = "st,uvis25", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, st_uvis25_i2c_of_match);
+
+static const struct i2c_device_id st_uvis25_i2c_id_table[] = {
+       { ST_UVIS25_DEV_NAME },
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, st_uvis25_i2c_id_table);
+
+static struct i2c_driver st_uvis25_driver = {
+       .driver = {
+               .name = "st_uvis25_i2c",
+               .pm = &st_uvis25_pm_ops,
+               .of_match_table = of_match_ptr(st_uvis25_i2c_of_match),
+       },
+       .probe = st_uvis25_i2c_probe,
+       .id_table = st_uvis25_i2c_id_table,
+};
+module_i2c_driver(st_uvis25_driver);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
+MODULE_DESCRIPTION("STMicroelectronics uvis25 i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/st_uvis25_spi.c b/drivers/iio/light/st_uvis25_spi.c
new file mode 100644 (file)
index 0000000..cdfee5e
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * STMicroelectronics uvis25 spi driver
+ *
+ * Copyright 2017 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+
+#include "st_uvis25.h"
+
+#define UVIS25_SENSORS_SPI_READ                BIT(7)
+#define UVIS25_SPI_AUTO_INCREMENT      BIT(6)
+
+static const struct regmap_config st_uvis25_spi_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .read_flag_mask = UVIS25_SENSORS_SPI_READ | UVIS25_SPI_AUTO_INCREMENT,
+       .write_flag_mask = UVIS25_SPI_AUTO_INCREMENT,
+};
+
+static int st_uvis25_spi_probe(struct spi_device *spi)
+{
+       struct regmap *regmap;
+
+       regmap = devm_regmap_init_spi(spi, &st_uvis25_spi_regmap_config);
+       if (IS_ERR(regmap)) {
+               dev_err(&spi->dev, "Failed to register spi regmap %d\n",
+                       (int)PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
+       return st_uvis25_probe(&spi->dev, spi->irq, regmap);
+}
+
+static const struct of_device_id st_uvis25_spi_of_match[] = {
+       { .compatible = "st,uvis25", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, st_uvis25_spi_of_match);
+
+static const struct spi_device_id st_uvis25_spi_id_table[] = {
+       { ST_UVIS25_DEV_NAME },
+       {},
+};
+MODULE_DEVICE_TABLE(spi, st_uvis25_spi_id_table);
+
+static struct spi_driver st_uvis25_driver = {
+       .driver = {
+               .name = "st_uvis25_spi",
+               .pm = &st_uvis25_pm_ops,
+               .of_match_table = of_match_ptr(st_uvis25_spi_of_match),
+       },
+       .probe = st_uvis25_spi_probe,
+       .id_table = st_uvis25_spi_id_table,
+};
+module_spi_driver(st_uvis25_driver);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
+MODULE_DESCRIPTION("STMicroelectronics uvis25 spi driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c
new file mode 100644 (file)
index 0000000..041ac9e
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+ * zopt2201.c - Support for IDT ZOPT2201 ambient light and UV B sensor
+ *
+ * Copyright 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Datasheet: https://www.idt.com/document/dst/zopt2201-datasheet
+ * 7-bit I2C slave addresses 0x53 (default) or 0x52 (programmed)
+ *
+ * TODO: interrupt support, ALS/UVB raw mode
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define ZOPT2201_DRV_NAME "zopt2201"
+
+/* Registers */
+#define ZOPT2201_MAIN_CTRL             0x00
+#define ZOPT2201_LS_MEAS_RATE          0x04
+#define ZOPT2201_LS_GAIN               0x05
+#define ZOPT2201_PART_ID               0x06
+#define ZOPT2201_MAIN_STATUS           0x07
+#define ZOPT2201_ALS_DATA              0x0d /* LSB first, 13 to 20 bits */
+#define ZOPT2201_UVB_DATA              0x10 /* LSB first, 13 to 20 bits */
+#define ZOPT2201_UV_COMP_DATA          0x13 /* LSB first, 13 to 20 bits */
+#define ZOPT2201_COMP_DATA             0x16 /* LSB first, 13 to 20 bits */
+#define ZOPT2201_INT_CFG               0x19
+#define ZOPT2201_INT_PST               0x1a
+
+#define ZOPT2201_MAIN_CTRL_LS_MODE     BIT(3) /* 0 .. ALS, 1 .. UV B */
+#define ZOPT2201_MAIN_CTRL_LS_EN       BIT(1)
+
+/* Values for ZOPT2201_LS_MEAS_RATE resolution / bit width */
+#define ZOPT2201_MEAS_RES_20BIT                0 /* takes 400 ms */
+#define ZOPT2201_MEAS_RES_19BIT                1 /* takes 200 ms */
+#define ZOPT2201_MEAS_RES_18BIT                2 /* takes 100 ms, default */
+#define ZOPT2201_MEAS_RES_17BIT                3 /* takes 50 ms */
+#define ZOPT2201_MEAS_RES_16BIT                4 /* takes 25 ms */
+#define ZOPT2201_MEAS_RES_13BIT                5 /* takes 3.125 ms */
+#define ZOPT2201_MEAS_RES_SHIFT                4
+
+/* Values for ZOPT2201_LS_MEAS_RATE measurement rate */
+#define ZOPT2201_MEAS_FREQ_25MS                0
+#define ZOPT2201_MEAS_FREQ_50MS                1
+#define ZOPT2201_MEAS_FREQ_100MS       2 /* default */
+#define ZOPT2201_MEAS_FREQ_200MS       3
+#define ZOPT2201_MEAS_FREQ_500MS       4
+#define ZOPT2201_MEAS_FREQ_1000MS      5
+#define ZOPT2201_MEAS_FREQ_2000MS      6
+
+/* Values for ZOPT2201_LS_GAIN */
+#define ZOPT2201_LS_GAIN_1             0
+#define ZOPT2201_LS_GAIN_3             1
+#define ZOPT2201_LS_GAIN_6             2
+#define ZOPT2201_LS_GAIN_9             3
+#define ZOPT2201_LS_GAIN_18            4
+
+/* Values for ZOPT2201_MAIN_STATUS */
+#define ZOPT2201_MAIN_STATUS_POWERON   BIT(5)
+#define ZOPT2201_MAIN_STATUS_INT       BIT(4)
+#define ZOPT2201_MAIN_STATUS_DRDY      BIT(3)
+
+#define ZOPT2201_PART_NUMBER           0xb2
+
+struct zopt2201_data {
+       struct i2c_client *client;
+       struct mutex lock;
+       u8 gain;
+       u8 res;
+       u8 rate;
+};
+
+static const struct {
+       unsigned int gain; /* gain factor */
+       unsigned int scale; /* micro lux per count */
+} zopt2201_gain_als[] = {
+       {  1, 19200000 },
+       {  3,  6400000 },
+       {  6,  3200000 },
+       {  9,  2133333 },
+       { 18,  1066666 },
+};
+
+static const struct {
+       unsigned int gain; /* gain factor */
+       unsigned int scale; /* micro W/m2 per count */
+} zopt2201_gain_uvb[] = {
+       {  1, 460800 },
+       {  3, 153600 },
+       {  6,  76800 },
+       {  9,  51200 },
+       { 18,  25600 },
+};
+
+static const struct {
+       unsigned int bits; /* sensor resolution in bits */
+       unsigned long us; /* measurement time in micro seconds */
+} zopt2201_resolution[] = {
+       { 20, 400000 },
+       { 19, 200000 },
+       { 18, 100000 },
+       { 17,  50000 },
+       { 16,  25000 },
+       { 13,   3125 },
+};
+
+static const struct {
+       unsigned int scale, uscale; /* scale factor as integer + micro */
+       u8 gain; /* gain register value */
+       u8 res; /* resolution register value */
+} zopt2201_scale_als[] = {
+       { 19, 200000, 0, 5 },
+       {  6, 400000, 1, 5 },
+       {  3, 200000, 2, 5 },
+       {  2, 400000, 0, 4 },
+       {  2, 133333, 3, 5 },
+       {  1, 200000, 0, 3 },
+       {  1,  66666, 4, 5 },
+       {  0, 800000, 1, 4 },
+       {  0, 600000, 0, 2 },
+       {  0, 400000, 2, 4 },
+       {  0, 300000, 0, 1 },
+       {  0, 266666, 3, 4 },
+       {  0, 200000, 2, 3 },
+       {  0, 150000, 0, 0 },
+       {  0, 133333, 4, 4 },
+       {  0, 100000, 2, 2 },
+       {  0,  66666, 4, 3 },
+       {  0,  50000, 2, 1 },
+       {  0,  33333, 4, 2 },
+       {  0,  25000, 2, 0 },
+       {  0,  16666, 4, 1 },
+       {  0,   8333, 4, 0 },
+};
+
+static const struct {
+       unsigned int scale, uscale; /* scale factor as integer + micro */
+       u8 gain; /* gain register value */
+       u8 res; /* resolution register value */
+} zopt2201_scale_uvb[] = {
+       { 0, 460800, 0, 5 },
+       { 0, 153600, 1, 5 },
+       { 0,  76800, 2, 5 },
+       { 0,  57600, 0, 4 },
+       { 0,  51200, 3, 5 },
+       { 0,  28800, 0, 3 },
+       { 0,  25600, 4, 5 },
+       { 0,  19200, 1, 4 },
+       { 0,  14400, 0, 2 },
+       { 0,   9600, 2, 4 },
+       { 0,   7200, 0, 1 },
+       { 0,   6400, 3, 4 },
+       { 0,   4800, 2, 3 },
+       { 0,   3600, 0, 0 },
+       { 0,   3200, 4, 4 },
+       { 0,   2400, 2, 2 },
+       { 0,   1600, 4, 3 },
+       { 0,   1200, 2, 1 },
+       { 0,    800, 4, 2 },
+       { 0,    600, 2, 0 },
+       { 0,    400, 4, 1 },
+       { 0,    200, 4, 0 },
+};
+
+static int zopt2201_enable_mode(struct zopt2201_data *data, bool uvb_mode)
+{
+       u8 out = ZOPT2201_MAIN_CTRL_LS_EN;
+
+       if (uvb_mode)
+               out |= ZOPT2201_MAIN_CTRL_LS_MODE;
+
+       return i2c_smbus_write_byte_data(data->client, ZOPT2201_MAIN_CTRL, out);
+}
+
+static int zopt2201_read(struct zopt2201_data *data, u8 reg)
+{
+       struct i2c_client *client = data->client;
+       int tries = 10;
+       u8 buf[3];
+       int ret;
+
+       mutex_lock(&data->lock);
+       ret = zopt2201_enable_mode(data, reg == ZOPT2201_UVB_DATA);
+       if (ret < 0)
+               goto fail;
+
+       while (tries--) {
+               unsigned long t = zopt2201_resolution[data->res].us;
+
+               if (t <= 20000)
+                       usleep_range(t, t + 1000);
+               else
+                       msleep(t / 1000);
+               ret = i2c_smbus_read_byte_data(client, ZOPT2201_MAIN_STATUS);
+               if (ret < 0)
+                       goto fail;
+               if (ret & ZOPT2201_MAIN_STATUS_DRDY)
+                       break;
+       }
+
+       if (tries < 0) {
+               ret = -ETIMEDOUT;
+               goto fail;
+       }
+
+       ret = i2c_smbus_read_i2c_block_data(client, reg, sizeof(buf), buf);
+       if (ret < 0)
+               goto fail;
+
+       ret = i2c_smbus_write_byte_data(client, ZOPT2201_MAIN_CTRL, 0x00);
+       if (ret < 0)
+               goto fail;
+       mutex_unlock(&data->lock);
+
+       return (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+fail:
+       mutex_unlock(&data->lock);
+       return ret;
+}
+
+static const struct iio_chan_spec zopt2201_channels[] = {
+       {
+               .type = IIO_LIGHT,
+               .address = ZOPT2201_ALS_DATA,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+               .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+       },
+       {
+               .type = IIO_INTENSITY,
+               .modified = 1,
+               .channel2 = IIO_MOD_LIGHT_UV,
+               .address = ZOPT2201_UVB_DATA,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+               .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+       },
+       {
+               .type = IIO_UVINDEX,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+       },
+};
+
+static int zopt2201_read_raw(struct iio_dev *indio_dev,
+                               struct iio_chan_spec const *chan,
+                               int *val, int *val2, long mask)
+{
+       struct zopt2201_data *data = iio_priv(indio_dev);
+       u64 tmp;
+       int ret;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               ret = zopt2201_read(data, chan->address);
+               if (ret < 0)
+                       return ret;
+               *val = ret;
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_PROCESSED:
+               ret = zopt2201_read(data, ZOPT2201_UVB_DATA);
+               if (ret < 0)
+                       return ret;
+               *val = ret * 18 *
+                       (1 << (20 - zopt2201_resolution[data->res].bits)) /
+                       zopt2201_gain_uvb[data->gain].gain;
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               switch (chan->address) {
+               case ZOPT2201_ALS_DATA:
+                       *val = zopt2201_gain_als[data->gain].scale;
+                       break;
+               case ZOPT2201_UVB_DATA:
+                       *val = zopt2201_gain_uvb[data->gain].scale;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               *val2 = 1000000;
+               *val2 *= (1 << (zopt2201_resolution[data->res].bits - 13));
+               tmp = div_s64(*val * 1000000ULL, *val2);
+               *val = div_s64_rem(tmp, 1000000, val2);
+
+               return IIO_VAL_INT_PLUS_MICRO;
+       case IIO_CHAN_INFO_INT_TIME:
+               *val = 0;
+               *val2 = zopt2201_resolution[data->res].us;
+               return IIO_VAL_INT_PLUS_MICRO;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int zopt2201_set_resolution(struct zopt2201_data *data, u8 res)
+{
+       int ret;
+
+       ret = i2c_smbus_write_byte_data(data->client, ZOPT2201_LS_MEAS_RATE,
+                                       (res << ZOPT2201_MEAS_RES_SHIFT) |
+                                       data->rate);
+       if (ret < 0)
+               return ret;
+
+       data->res = res;
+
+       return 0;
+}
+
+static int zopt2201_write_resolution(struct zopt2201_data *data,
+                                    int val, int val2)
+{
+       int i, ret;
+
+       if (val != 0)
+               return -EINVAL;
+
+       for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++)
+               if (val2 == zopt2201_resolution[i].us) {
+                       mutex_lock(&data->lock);
+                       ret = zopt2201_set_resolution(data, i);
+                       mutex_unlock(&data->lock);
+                       return ret;
+               }
+
+       return -EINVAL;
+}
+
+static int zopt2201_set_gain(struct zopt2201_data *data, u8 gain)
+{
+       int ret;
+
+       ret = i2c_smbus_write_byte_data(data->client, ZOPT2201_LS_GAIN, gain);
+       if (ret < 0)
+               return ret;
+
+       data->gain = gain;
+
+       return 0;
+}
+
+static int zopt2201_write_scale_als_by_idx(struct zopt2201_data *data, int idx)
+{
+       int ret;
+
+       mutex_lock(&data->lock);
+       ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res);
+       if (ret < 0)
+               goto unlock;
+
+       ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain);
+
+unlock:
+       mutex_unlock(&data->lock);
+       return ret;
+}
+
+static int zopt2201_write_scale_als(struct zopt2201_data *data,
+                                    int val, int val2)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(zopt2201_scale_als); i++)
+               if (val == zopt2201_scale_als[i].scale &&
+                   val2 == zopt2201_scale_als[i].uscale) {
+                       return zopt2201_write_scale_als_by_idx(data, i);
+               }
+
+       return -EINVAL;
+}
+
+static int zopt2201_write_scale_uvb_by_idx(struct zopt2201_data *data, int idx)
+{
+       int ret;
+
+       mutex_lock(&data->lock);
+       ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res);
+       if (ret < 0)
+               goto unlock;
+
+       ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain);
+
+unlock:
+       mutex_unlock(&data->lock);
+       return ret;
+}
+
+static int zopt2201_write_scale_uvb(struct zopt2201_data *data,
+                                    int val, int val2)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(zopt2201_scale_uvb); i++)
+               if (val == zopt2201_scale_uvb[i].scale &&
+                   val2 == zopt2201_scale_uvb[i].uscale)
+                       return zopt2201_write_scale_uvb_by_idx(data, i);
+
+       return -EINVAL;
+}
+
+static int zopt2201_write_raw(struct iio_dev *indio_dev,
+                             struct iio_chan_spec const *chan,
+                             int val, int val2, long mask)
+{
+       struct zopt2201_data *data = iio_priv(indio_dev);
+
+       switch (mask) {
+       case IIO_CHAN_INFO_INT_TIME:
+               return zopt2201_write_resolution(data, val, val2);
+       case IIO_CHAN_INFO_SCALE:
+               switch (chan->address) {
+               case ZOPT2201_ALS_DATA:
+                       return zopt2201_write_scale_als(data, val, val2);
+               case ZOPT2201_UVB_DATA:
+                       return zopt2201_write_scale_uvb(data, val, val2);
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static ssize_t zopt2201_show_int_time_available(struct device *dev,
+                                               struct device_attribute *attr,
+                                               char *buf)
+{
+       size_t len = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++)
+               len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06lu ",
+                                zopt2201_resolution[i].us);
+       buf[len - 1] = '\n';
+
+       return len;
+}
+
+static IIO_DEV_ATTR_INT_TIME_AVAIL(zopt2201_show_int_time_available);
+
+static ssize_t zopt2201_show_als_scale_avail(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buf)
+{
+       ssize_t len = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(zopt2201_scale_als); i++)
+               len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ",
+                                zopt2201_scale_als[i].scale,
+                                zopt2201_scale_als[i].uscale);
+       buf[len - 1] = '\n';
+
+       return len;
+}
+
+static ssize_t zopt2201_show_uvb_scale_avail(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buf)
+{
+       ssize_t len = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(zopt2201_scale_uvb); i++)
+               len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ",
+                                zopt2201_scale_uvb[i].scale,
+                                zopt2201_scale_uvb[i].uscale);
+       buf[len - 1] = '\n';
+
+       return len;
+}
+
+static IIO_DEVICE_ATTR(in_illuminance_scale_available, 0444,
+                      zopt2201_show_als_scale_avail, NULL, 0);
+static IIO_DEVICE_ATTR(in_intensity_uv_scale_available, 0444,
+                      zopt2201_show_uvb_scale_avail, NULL, 0);
+
+static struct attribute *zopt2201_attributes[] = {
+       &iio_dev_attr_integration_time_available.dev_attr.attr,
+       &iio_dev_attr_in_illuminance_scale_available.dev_attr.attr,
+       &iio_dev_attr_in_intensity_uv_scale_available.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group zopt2201_attribute_group = {
+       .attrs = zopt2201_attributes,
+};
+
+static const struct iio_info zopt2201_info = {
+       .read_raw = zopt2201_read_raw,
+       .write_raw = zopt2201_write_raw,
+       .attrs = &zopt2201_attribute_group,
+};
+
+static int zopt2201_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
+{
+       struct zopt2201_data *data;
+       struct iio_dev *indio_dev;
+       int ret;
+
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+               return -EOPNOTSUPP;
+
+       ret = i2c_smbus_read_byte_data(client, ZOPT2201_PART_ID);
+       if (ret < 0)
+               return ret;
+       if (ret != ZOPT2201_PART_NUMBER)
+               return -ENODEV;
+
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       data = iio_priv(indio_dev);
+       i2c_set_clientdata(client, indio_dev);
+       data->client = client;
+       mutex_init(&data->lock);
+
+       indio_dev->dev.parent = &client->dev;
+       indio_dev->info = &zopt2201_info;
+       indio_dev->channels = zopt2201_channels;
+       indio_dev->num_channels = ARRAY_SIZE(zopt2201_channels);
+       indio_dev->name = ZOPT2201_DRV_NAME;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       data->rate = ZOPT2201_MEAS_FREQ_100MS;
+       ret = zopt2201_set_resolution(data, ZOPT2201_MEAS_RES_18BIT);
+       if (ret < 0)
+               return ret;
+
+       ret = zopt2201_set_gain(data, ZOPT2201_LS_GAIN_3);
+       if (ret < 0)
+               return ret;
+
+       return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id zopt2201_id[] = {
+       { "zopt2201", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, zopt2201_id);
+
+static struct i2c_driver zopt2201_driver = {
+       .driver = {
+               .name   = ZOPT2201_DRV_NAME,
+       },
+       .probe  = zopt2201_probe,
+       .id_table = zopt2201_id,
+};
+
+module_i2c_driver(zopt2201_driver);
+
+MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("IDT ZOPT2201 ambient light and UV B sensor driver");
+MODULE_LICENSE("GPL");
index c09329069d0a1b3b1db962b8660816751f637772..42a827a66512182485678b53a534e079aee82a3c 100644 (file)
@@ -788,6 +788,7 @@ static const struct acpi_device_id ak_acpi_match[] = {
        {"AK8975", AK8975},
        {"AK8963", AK8963},
        {"INVN6500", AK8963},
+       {"AK009911", AK09911},
        {"AK09911", AK09911},
        {"AK09912", AK09912},
        { },
index fd1da26a62e47014906deda23180b39e0509828f..5ec3e41b65f2b8f991626a4522d6263d66ca2a27 100644 (file)
@@ -55,6 +55,28 @@ struct bmp180_calib {
        s16 MD;
 };
 
+/* See datasheet Section 4.2.2. */
+struct bmp280_calib {
+       u16 T1;
+       s16 T2;
+       s16 T3;
+       u16 P1;
+       s16 P2;
+       s16 P3;
+       s16 P4;
+       s16 P5;
+       s16 P6;
+       s16 P7;
+       s16 P8;
+       s16 P9;
+       u8  H1;
+       s16 H2;
+       u8  H3;
+       s16 H4;
+       s16 H5;
+       s8  H6;
+};
+
 struct bmp280_data {
        struct device *dev;
        struct mutex lock;
@@ -62,7 +84,10 @@ struct bmp280_data {
        struct completion done;
        bool use_eoc;
        const struct bmp280_chip_info *chip_info;
-       struct bmp180_calib calib;
+       union {
+               struct bmp180_calib bmp180;
+               struct bmp280_calib bmp280;
+       } calib;
        struct regulator *vddd;
        struct regulator *vdda;
        unsigned int start_up_time; /* in microseconds */
@@ -120,67 +145,121 @@ static const struct iio_chan_spec bmp280_channels[] = {
        },
 };
 
-/*
- * Returns humidity in percent, resolution is 0.01 percent. Output value of
- * "47445" represents 47445/1024 = 46.333 %RH.
- *
- * Taken from BME280 datasheet, Section 4.2.3, "Compensation formula".
- */
-
-static u32 bmp280_compensate_humidity(struct bmp280_data *data,
-                                     s32 adc_humidity)
+static int bmp280_read_calib(struct bmp280_data *data,
+                            struct bmp280_calib *calib,
+                            unsigned int chip)
 {
+       int ret;
+       unsigned int tmp;
        struct device *dev = data->dev;
-       unsigned int H1, H3, tmp;
-       int H2, H4, H5, H6, ret, var;
+       __le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
+       __le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
+
+       /* Read temperature calibration values. */
+       ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
+                              t_buf, BMP280_COMP_TEMP_REG_COUNT);
+       if (ret < 0) {
+               dev_err(data->dev,
+                       "failed to read temperature calibration parameters\n");
+               return ret;
+       }
+
+       calib->T1 = le16_to_cpu(t_buf[T1]);
+       calib->T2 = le16_to_cpu(t_buf[T2]);
+       calib->T3 = le16_to_cpu(t_buf[T3]);
 
-       ret = regmap_read(data->regmap, BMP280_REG_COMP_H1, &H1);
+       /* Read pressure calibration values. */
+       ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START,
+                              p_buf, BMP280_COMP_PRESS_REG_COUNT);
+       if (ret < 0) {
+               dev_err(data->dev,
+                       "failed to read pressure calibration parameters\n");
+               return ret;
+       }
+
+       calib->P1 = le16_to_cpu(p_buf[P1]);
+       calib->P2 = le16_to_cpu(p_buf[P2]);
+       calib->P3 = le16_to_cpu(p_buf[P3]);
+       calib->P4 = le16_to_cpu(p_buf[P4]);
+       calib->P5 = le16_to_cpu(p_buf[P5]);
+       calib->P6 = le16_to_cpu(p_buf[P6]);
+       calib->P7 = le16_to_cpu(p_buf[P7]);
+       calib->P8 = le16_to_cpu(p_buf[P8]);
+       calib->P9 = le16_to_cpu(p_buf[P9]);
+
+       /*
+        * Read humidity calibration values.
+        * Due to some odd register addressing we cannot just
+        * do a big bulk read. Instead, we have to read each Hx
+        * value separately and sometimes do some bit shifting...
+        * Humidity data is only available on BME280.
+        */
+       if (chip != BME280_CHIP_ID)
+               return 0;
+
+       ret = regmap_read(data->regmap, BMP280_REG_COMP_H1, &tmp);
        if (ret < 0) {
                dev_err(dev, "failed to read H1 comp value\n");
                return ret;
        }
+       calib->H1 = tmp;
 
        ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, &tmp, 2);
        if (ret < 0) {
                dev_err(dev, "failed to read H2 comp value\n");
                return ret;
        }
-       H2 = sign_extend32(le16_to_cpu(tmp), 15);
+       calib->H2 = sign_extend32(le16_to_cpu(tmp), 15);
 
-       ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &H3);
+       ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &tmp);
        if (ret < 0) {
                dev_err(dev, "failed to read H3 comp value\n");
                return ret;
        }
+       calib->H3 = tmp;
 
        ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, &tmp, 2);
        if (ret < 0) {
                dev_err(dev, "failed to read H4 comp value\n");
                return ret;
        }
-       H4 = sign_extend32(((be16_to_cpu(tmp) >> 4) & 0xff0) |
-                         (be16_to_cpu(tmp) & 0xf), 11);
+       calib->H4 = sign_extend32(((be16_to_cpu(tmp) >> 4) & 0xff0) |
+                                 (be16_to_cpu(tmp) & 0xf), 11);
 
        ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5, &tmp, 2);
        if (ret < 0) {
                dev_err(dev, "failed to read H5 comp value\n");
                return ret;
        }
-       H5 = sign_extend32(((le16_to_cpu(tmp) >> 4) & 0xfff), 11);
+       calib->H5 = sign_extend32(((le16_to_cpu(tmp) >> 4) & 0xfff), 11);
 
        ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp);
        if (ret < 0) {
                dev_err(dev, "failed to read H6 comp value\n");
                return ret;
        }
-       H6 = sign_extend32(tmp, 7);
+       calib->H6 = sign_extend32(tmp, 7);
+
+       return 0;
+}
+/*
+ * Returns humidity in percent, resolution is 0.01 percent. Output value of
+ * "47445" represents 47445/1024 = 46.333 %RH.
+ *
+ * Taken from BME280 datasheet, Section 4.2.3, "Compensation formula".
+ */
+static u32 bmp280_compensate_humidity(struct bmp280_data *data,
+                                     s32 adc_humidity)
+{
+       s32 var;
+       struct bmp280_calib *calib = &data->calib.bmp280;
 
        var = ((s32)data->t_fine) - (s32)76800;
-       var = ((((adc_humidity << 14) - (H4 << 20) - (H5 * var))
-               + (s32)16384) >> 15) * (((((((var * H6) >> 10)
-               * (((var * (s32)H3) >> 11) + (s32)32768)) >> 10)
-               + (s32)2097152) * H2 + 8192) >> 14);
-       var -= ((((var >> 15) * (var >> 15)) >> 7) * (s32)H1) >> 4;
+       var = ((((adc_humidity << 14) - (calib->H4 << 20) - (calib->H5 * var))
+               + (s32)16384) >> 15) * (((((((var * calib->H6) >> 10)
+               * (((var * (s32)calib->H3) >> 11) + (s32)32768)) >> 10)
+               + (s32)2097152) * calib->H2 + 8192) >> 14);
+       var -= ((((var >> 15) * (var >> 15)) >> 7) * (s32)calib->H1) >> 4;
 
        return var >> 12;
 };
@@ -195,31 +274,14 @@ static u32 bmp280_compensate_humidity(struct bmp280_data *data,
 static s32 bmp280_compensate_temp(struct bmp280_data *data,
                                  s32 adc_temp)
 {
-       int ret;
        s32 var1, var2;
-       __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2];
+       struct bmp280_calib *calib = &data->calib.bmp280;
 
-       ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
-                              buf, BMP280_COMP_TEMP_REG_COUNT);
-       if (ret < 0) {
-               dev_err(data->dev,
-                       "failed to read temperature calibration parameters\n");
-               return ret;
-       }
-
-       /*
-        * The double casts are necessary because le16_to_cpu returns an
-        * unsigned 16-bit value.  Casting that value directly to a
-        * signed 32-bit will not do proper sign extension.
-        *
-        * Conversely, T1 and P1 are unsigned values, so they can be
-        * cast straight to the larger type.
-        */
-       var1 = (((adc_temp >> 3) - ((s32)le16_to_cpu(buf[T1]) << 1)) *
-               ((s32)(s16)le16_to_cpu(buf[T2]))) >> 11;
-       var2 = (((((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1]))) *
-                 ((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1])))) >> 12) *
-               ((s32)(s16)le16_to_cpu(buf[T3]))) >> 14;
+       var1 = (((adc_temp >> 3) - ((s32)calib->T1 << 1)) *
+               ((s32)calib->T2)) >> 11;
+       var2 = (((((adc_temp >> 4) - ((s32)calib->T1)) *
+                 ((adc_temp >> 4) - ((s32)calib->T1))) >> 12) *
+               ((s32)calib->T3)) >> 14;
        data->t_fine = var1 + var2;
 
        return (data->t_fine * 5 + 128) >> 8;
@@ -235,34 +297,25 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data,
 static u32 bmp280_compensate_press(struct bmp280_data *data,
                                   s32 adc_press)
 {
-       int ret;
        s64 var1, var2, p;
-       __le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2];
-
-       ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START,
-                              buf, BMP280_COMP_PRESS_REG_COUNT);
-       if (ret < 0) {
-               dev_err(data->dev,
-                       "failed to read pressure calibration parameters\n");
-               return ret;
-       }
+       struct bmp280_calib *calib = &data->calib.bmp280;
 
        var1 = ((s64)data->t_fine) - 128000;
-       var2 = var1 * var1 * (s64)(s16)le16_to_cpu(buf[P6]);
-       var2 += (var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17;
-       var2 += ((s64)(s16)le16_to_cpu(buf[P4])) << 35;
-       var1 = ((var1 * var1 * (s64)(s16)le16_to_cpu(buf[P3])) >> 8) +
-               ((var1 * (s64)(s16)le16_to_cpu(buf[P2])) << 12);
-       var1 = ((((s64)1) << 47) + var1) * ((s64)le16_to_cpu(buf[P1])) >> 33;
+       var2 = var1 * var1 * (s64)calib->P6;
+       var2 += (var1 * (s64)calib->P5) << 17;
+       var2 += ((s64)calib->P4) << 35;
+       var1 = ((var1 * var1 * (s64)calib->P3) >> 8) +
+               ((var1 * (s64)calib->P2) << 12);
+       var1 = ((((s64)1) << 47) + var1) * ((s64)calib->P1) >> 33;
 
        if (var1 == 0)
                return 0;
 
        p = ((((s64)1048576 - adc_press) << 31) - var2) * 3125;
        p = div64_s64(p, var1);
-       var1 = (((s64)(s16)le16_to_cpu(buf[P9])) * (p >> 13) * (p >> 13)) >> 25;
-       var2 = (((s64)(s16)le16_to_cpu(buf[P8])) * p) >> 19;
-       p = ((p + var1 + var2) >> 8) + (((s64)(s16)le16_to_cpu(buf[P7])) << 4);
+       var1 = (((s64)calib->P9) * (p >> 13) * (p >> 13)) >> 25;
+       var2 = ((s64)(calib->P8) * p) >> 19;
+       p = ((p + var1 + var2) >> 8) + (((s64)calib->P7) << 4);
 
        return (u32)p;
 }
@@ -752,7 +805,7 @@ static int bmp180_read_calib(struct bmp280_data *data,
 static s32 bmp180_compensate_temp(struct bmp280_data *data, s32 adc_temp)
 {
        s32 x1, x2;
-       struct bmp180_calib *calib = &data->calib;
+       struct bmp180_calib *calib = &data->calib.bmp180;
 
        x1 = ((adc_temp - calib->AC6) * calib->AC5) >> 15;
        x2 = (calib->MC << 11) / (x1 + calib->MD);
@@ -814,7 +867,7 @@ static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press)
        s32 b3, b6;
        u32 b4, b7;
        s32 oss = data->oversampling_press;
-       struct bmp180_calib *calib = &data->calib;
+       struct bmp180_calib *calib = &data->calib.bmp180;
 
        b6 = data->t_fine - 4000;
        x1 = (calib->B2 * (b6 * b6 >> 12)) >> 11;
@@ -1028,11 +1081,19 @@ int bmp280_common_probe(struct device *dev,
        dev_set_drvdata(dev, indio_dev);
 
        /*
-        * The BMP085 and BMP180 has calibration in an E2PROM, read it out
-        * at probe time. It will not change.
+        * Some chips have calibration parameters "programmed into the devices'
+        * non-volatile memory during production". Let's read them out at probe
+        * time once. They will not change.
         */
        if (chip_id  == BMP180_CHIP_ID) {
-               ret = bmp180_read_calib(data, &data->calib);
+               ret = bmp180_read_calib(data, &data->calib.bmp180);
+               if (ret < 0) {
+                       dev_err(data->dev,
+                               "failed to read calibration coefficients\n");
+                       goto out_disable_vdda;
+               }
+       } else if (chip_id == BMP280_CHIP_ID || chip_id == BME280_CHIP_ID) {
+               ret = bmp280_read_calib(data, &data->calib.bmp280, chip_id);
                if (ret < 0) {
                        dev_err(data->dev,
                                "failed to read calibration coefficients\n");
index df23dbcc030aea5b2d6e0ddde7237b4d906bf365..b8a2c2c8cac510f2dac62eec7c39d42939776984 100644 (file)
@@ -1031,6 +1031,7 @@ static const struct dev_pm_ops sx9500_pm_ops = {
 
 static const struct acpi_device_id sx9500_acpi_match[] = {
        {"SSX9500", 0},
+       {"SASX9500", 0},
        { },
 };
 MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match);
index de361d8799291d19df83d46ec1f464872ed994fa..98cdc7e47f3dd75fbb156e24674e0bcf22e1b7fe 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * STM32 Low-Power Timer Trigger driver
  *
@@ -5,8 +6,6 @@
  *
  * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
  *
- * License terms:  GNU General Public License (GPL), version 2
- *
  * Inspired by Benjamin Gaignard's stm32-timer-trigger driver
  */
 
index b542dc484969c72cbbd55ae1d5de3839d3fed0f7..ccf1ce653b2516f0d0c9160eceaedf12bc57b2b0 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) STMicroelectronics 2016
  *
  * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
  *
- * License terms:  GNU General Public License (GPL), version 2
  */
 
 #include <linux/iio/iio.h>
index 554683912cff2fce97fd328da8268339458f15af..e95ab683331e7fdb2329675b28814de08d1eea7b 100644 (file)
@@ -26,6 +26,10 @@ if STAGING
 
 source "drivers/staging/irda/net/Kconfig"
 
+source "drivers/staging/ipx/Kconfig"
+
+source "drivers/staging/ncpfs/Kconfig"
+
 source "drivers/staging/wlan-ng/Kconfig"
 
 source "drivers/staging/comedi/Kconfig"
index 6e536020029a213fd7ea912f1a5e47de64551575..af8cd6a3a1f6d1da721831ef6d89d42533611c5f 100644 (file)
@@ -3,6 +3,8 @@
 
 obj-y                          += media/
 obj-y                          += typec/
+obj-$(CONFIG_IPX)              += ipx/
+obj-$(CONFIG_NCP_FS)           += ncpfs/
 obj-$(CONFIG_IRDA)             += irda/net/
 obj-$(CONFIG_IRDA)             += irda/drivers/
 obj-$(CONFIG_PRISM2_USB)       += wlan-ng/
index 372ce9913e6dea373d4cdd06ca51f2419c7a7373..bbdc53b686dd19503796ed8fdfd97fd01596195f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /* mm/ashmem.c
  *
  * Anonymous Shared Memory Subsystem, ashmem
@@ -5,15 +6,6 @@
  * Copyright (C) 2008 Google, Inc.
  *
  * Robert Love <rlove@google.com>
- *
- * 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.
  */
 
 #define pr_fmt(fmt) "ashmem: " fmt
@@ -818,7 +810,23 @@ static long compat_ashmem_ioctl(struct file *file, unsigned int cmd,
        return ashmem_ioctl(file, cmd, arg);
 }
 #endif
+#ifdef CONFIG_PROC_FS
+static void ashmem_show_fdinfo(struct seq_file *m, struct file *file)
+{
+       struct ashmem_area *asma = file->private_data;
+
+       mutex_lock(&ashmem_mutex);
+
+       if (asma->file)
+               seq_printf(m, "inode:\t%ld\n", file_inode(asma->file)->i_ino);
+
+       if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0')
+               seq_printf(m, "name:\t%s\n",
+                          asma->name + ASHMEM_NAME_PREFIX_LEN);
 
+       mutex_unlock(&ashmem_mutex);
+}
+#endif
 static const struct file_operations ashmem_fops = {
        .owner = THIS_MODULE,
        .open = ashmem_open,
@@ -830,6 +838,9 @@ static const struct file_operations ashmem_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl = compat_ashmem_ioctl,
 #endif
+#ifdef CONFIG_PROC_FS
+       .show_fdinfo = ashmem_show_fdinfo,
+#endif
 };
 
 static struct miscdevice ashmem_misc = {
@@ -864,12 +875,18 @@ static int __init ashmem_init(void)
                goto out_free2;
        }
 
-       register_shrinker(&ashmem_shrinker);
+       ret = register_shrinker(&ashmem_shrinker);
+       if (ret) {
+               pr_err("failed to register shrinker!\n");
+               goto out_demisc;
+       }
 
        pr_info("initialized\n");
 
        return 0;
 
+out_demisc:
+       misc_deregister(&ashmem_misc);
 out_free2:
        kmem_cache_destroy(ashmem_range_cachep);
 out_free1:
index 5abcfd7aa706c37ac6c214323429bfbe6dfeff51..60d7208f110a88e2c67f927f3079cd1b62ad9e38 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR Apache-2.0)
 /*
  * include/linux/ashmem.h
  *
index c78989351f9cfa7bf5913ba226e09019027fa85d..a8d3cc412fb9013aabd42f74dd9995b718ea841f 100644 (file)
@@ -1,16 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- *
  * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 
 #include <linux/kernel.h>
@@ -70,8 +60,10 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return -EFAULT;
 
        ret = validate_ioctl_arg(cmd, &data);
-       if (WARN_ON_ONCE(ret))
+       if (ret) {
+               pr_warn_once("%s: ioctl validate failed\n", __func__);
                return ret;
+       }
 
        if (!(dir & _IOC_WRITE))
                memset(&data, 0, sizeof(data));
index f480885e346b69cb6ec881abefca0ee3aaf9fd15..57e0d8035b2e0e734c24124facd8da7824b7170d 100644 (file)
@@ -1,42 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- *
  * drivers/staging/android/ion/ion.c
  *
  * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 
+#include <linux/anon_inodes.h>
+#include <linux/debugfs.h>
 #include <linux/device.h>
+#include <linux/dma-buf.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/file.h>
 #include <linux/freezer.h>
 #include <linux/fs.h>
-#include <linux/anon_inodes.h>
+#include <linux/idr.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/memblock.h>
 #include <linux/miscdevice.h>
-#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/mm_types.h>
 #include <linux/rbtree.h>
-#include <linux/slab.h>
+#include <linux/sched/task.h>
 #include <linux/seq_file.h>
+#include <linux/slab.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
-#include <linux/debugfs.h>
-#include <linux/dma-buf.h>
-#include <linux/idr.h>
-#include <linux/sched/task.h>
 
 #include "ion.h"
 
@@ -539,6 +529,7 @@ void ion_device_add_heap(struct ion_heap *heap)
 {
        struct dentry *debug_file;
        struct ion_device *dev = internal_dev;
+       int ret;
 
        if (!heap->ops->allocate || !heap->ops->free)
                pr_err("%s: can not add heap with invalid ops struct.\n",
@@ -550,8 +541,11 @@ void ion_device_add_heap(struct ion_heap *heap)
        if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
                ion_heap_init_deferred_free(heap);
 
-       if ((heap->flags & ION_HEAP_FLAG_DEFER_FREE) || heap->ops->shrink)
-               ion_heap_init_shrinker(heap);
+       if ((heap->flags & ION_HEAP_FLAG_DEFER_FREE) || heap->ops->shrink) {
+               ret = ion_heap_init_shrinker(heap);
+               if (ret)
+                       pr_err("%s: Failed to register shrinker\n", __func__);
+       }
 
        heap->dev = dev;
        down_write(&dev->lock);
@@ -567,9 +561,9 @@ void ion_device_add_heap(struct ion_heap *heap)
                char debug_name[64];
 
                snprintf(debug_name, 64, "%s_shrink", heap->name);
-               debug_file = debugfs_create_file(
-                       debug_name, 0644, dev->debug_root, heap,
-                       &debug_shrink_fops);
+               debug_file = debugfs_create_file(debug_name,
+                                                0644, dev->debug_root, heap,
+                                                &debug_shrink_fops);
                if (!debug_file) {
                        char buf[256], *path;
 
index f5f9cd63f8e9df6039cf5513372e51968558f200..a238f23c911621b50534931f378f9c01167d5de3 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * drivers/staging/android/ion/ion.h
  *
  * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 
 #ifndef _ION_H
@@ -189,7 +180,8 @@ struct ion_heap {
        wait_queue_head_t waitqueue;
        struct task_struct *task;
 
-       int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *);
+       int (*debug_show)(struct ion_heap *heap, struct seq_file *s,
+                         void *unused);
 };
 
 /**
@@ -238,7 +230,7 @@ int ion_alloc(size_t len,
  * this function will be called to setup a shrinker to shrink the freelists
  * and call the heap's shrink op.
  */
-void ion_heap_init_shrinker(struct ion_heap *heap);
+int ion_heap_init_shrinker(struct ion_heap *heap);
 
 /**
  * ion_heap_init_deferred_free -- initialize deferred free functionality
index fee7650d6fbb391a44f24a130323e07425b4229b..e129237a0417a07ced1038f41528772ae3d7337c 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * drivers/staging/android/ion/ion_carveout_heap.c
  *
  * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
index 102c09398317c37997023e216c180e559f8c098f..159d72f5bc426fe6f2800768612cd87d3abcfa9a 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * drivers/staging/android/ion/ion_chunk_heap.c
  *
  * Copyright (C) 2012 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
index 86196ffd2faf9a7733cd931fa48e24e5ace3fd22..94e06925c712b5e52bb06d240ee33057077f8b0a 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * drivers/staging/android/ion/ion_cma_heap.c
  *
  * Copyright (C) Linaro 2012
  * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
- *
- * 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/device.h>
index 91faa7f035b93c1befecff04c29dfc16827f59b5..772dad65396ed68015f7d00563fb116138dfeff8 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * drivers/staging/android/ion/ion_heap.c
  *
  * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 
 #include <linux/err.h>
@@ -306,11 +297,12 @@ static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker,
        return freed;
 }
 
-void ion_heap_init_shrinker(struct ion_heap *heap)
+int ion_heap_init_shrinker(struct ion_heap *heap)
 {
        heap->shrinker.count_objects = ion_heap_shrink_count;
        heap->shrinker.scan_objects = ion_heap_shrink_scan;
        heap->shrinker.seeks = DEFAULT_SEEKS;
        heap->shrinker.batch = 0;
-       register_shrinker(&heap->shrinker);
+
+       return register_shrinker(&heap->shrinker);
 }
index 817849df9de33dd0ecc92940098ac92a66fabb1c..b3017f12835fd1ac7e9273926a36e94a4308e9a5 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * drivers/staging/android/ion/ion_mem_pool.c
  *
  * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 
 #include <linux/debugfs.h>
index 4dc5d7a589c28bb945ff076b7d21f66fff16d553..bc19cdd3063727d8ce40dfa6727dac77c2dcccbd 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * drivers/staging/android/ion/ion_system_heap.c
  *
  * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 
 #include <asm/page.h>
@@ -371,7 +362,7 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap,
        unsigned long i;
        int ret;
 
-       page = alloc_pages(low_order_gfp_flags, order);
+       page = alloc_pages(low_order_gfp_flags | __GFP_NOWARN, order);
        if (!page)
                return -ENOMEM;
 
index 13df42d200b7cc003e46cebd0e28b1997341fa87..5b531af6820ed6d8524895881088e2434fbd4a83 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR Apache-2.0)
 /*
  * drivers/staging/android/uapi/ashmem.h
  *
index 9e21451149d06fed279289d87c3a7d29163a6ed9..825d3e95ccd3ccb9c6740367a4f9fdca18ef0182 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * drivers/staging/android/uapi/ion.h
  *
  * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 
 #ifndef _UAPI_LINUX_ION_H
diff --git a/drivers/staging/ccree/Documentation/devicetree/bindings/crypto/arm-cryptocell.txt b/drivers/staging/ccree/Documentation/devicetree/bindings/crypto/arm-cryptocell.txt
deleted file mode 100644 (file)
index 2ea6517..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-Arm TrustZone CryptoCell cryptographic accelerators
-
-Required properties:
-- compatible: must be "arm,cryptocell-712-ree".
-- reg: shall contain base register location and length.
-       Typically length is 0x10000.
-- interrupts: shall contain the interrupt for the device.
-
-Optional properties:
-- interrupt-parent: can designate the interrupt controller the
-       device interrupt is connected to, if needed.
-- clocks: may contain the clock handling the device, if needed.
-- power-domains: may contain a reference to the PM domain, if applicable.
-
-
-Examples:
-
-Zynq FPGA device
-----------------
-
-       arm_cc7x: arm_cc7x@80000000 {
-               compatible = "arm,cryptocell-712-ree";
-               interrupt-parent = <&intc>;
-               interrupts = < 0 30 4 >;
-               reg = < 0x80000000 0x10000 >;
-       };
-
index 0b3092ba2fcb40a93f83efc11712ff75f8020612..c94dfe8adb6346800581fca192a93c725173fff1 100644 (file)
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
 config CRYPTO_DEV_CCREE
        tristate "Support for ARM TrustZone CryptoCell C7XX family of Crypto accelerators"
        depends on CRYPTO && CRYPTO_HW && OF && HAS_DMA
index ae702f3b53690d51e9fe0a8f0cc3460c986ff2be..bdc27970f95f704727104e77f357ba45d88e6ac8 100644 (file)
@@ -1,3 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
 obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o
-ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_cipher.o ssi_hash.o ssi_aead.o ssi_ivgen.o ssi_sram_mgr.o ssi_pm.o
-ccree-$(CONFIG_CRYPTO_FIPS) += ssi_fips.o
+ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_cipher.o cc_hash.o cc_aead.o cc_ivgen.o cc_sram_mgr.o
+ccree-$(CONFIG_CRYPTO_FIPS) += cc_fips.o
+ccree-$(CONFIG_DEBUG_FS) += cc_debugfs.o
+ccree-$(CONFIG_PM) += cc_pm.o
index c9f5754d062dd67b7cbbddfe7729a30cf0830060..b8e163d98f91b93300da4e355371e4c67a240559 100644 (file)
@@ -6,25 +6,5 @@
 *                                                                      *
 *************************************************************************
 
-ccree specific items
-a.k.a stuff fixing for this driver to move out of staging
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1. ???
 
-1.  Move to using Crypto Engine to handle backlog queueing.
-2.  Remove synchronous algorithm support leftovers.
-3.  Separate platform specific code for FIPS and power management into separate platform modules.
-4.  Drop legacy kernel support code.
-5.  Move most (all?) #ifdef CONFIG into inline functions.
-6.  Remove all unused definitions.
-7.  Re-factor to accomediate newer/older HW revisions besides the 712.
-8.  Handle the many checkpatch errors.
-9.  Implement ahash import/export correctly.
-10. Go through a proper review of DT bindings and sysfs ABI
-11. Sort out FIPS mode: bake tests into testmgr, sort out behaviour on error, 
-    figure if 3DES weak key check is needed
-
-Kernel infrastructure items
-a.k.a stuff we either neither need to fix in the kernel or understand what we're doing wrong
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. ahash import/export context has a PAGE_SIZE/8 size limit.  We need more.
-2. Crypto Engine seems to be built for HW with hardware queue depth of 1, we have 600++.
diff --git a/drivers/staging/ccree/cc_aead.c b/drivers/staging/ccree/cc_aead.c
new file mode 100644 (file)
index 0000000..b584131
--- /dev/null
@@ -0,0 +1,2701 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/aead.h>
+#include <crypto/authenc.h>
+#include <crypto/des.h>
+#include <linux/rtnetlink.h>
+#include "cc_driver.h"
+#include "cc_buffer_mgr.h"
+#include "cc_aead.h"
+#include "cc_request_mgr.h"
+#include "cc_hash.h"
+#include "cc_sram_mgr.h"
+
+#define template_aead  template_u.aead
+
+#define MAX_AEAD_SETKEY_SEQ 12
+#define MAX_AEAD_PROCESS_SEQ 23
+
+#define MAX_HMAC_DIGEST_SIZE (SHA256_DIGEST_SIZE)
+#define MAX_HMAC_BLOCK_SIZE (SHA256_BLOCK_SIZE)
+
+#define AES_CCM_RFC4309_NONCE_SIZE 3
+#define MAX_NONCE_SIZE CTR_RFC3686_NONCE_SIZE
+
+/* Value of each ICV_CMP byte (of 8) in case of success */
+#define ICV_VERIF_OK 0x01
+
+struct cc_aead_handle {
+       cc_sram_addr_t sram_workspace_addr;
+       struct list_head aead_list;
+};
+
+struct cc_hmac_s {
+       u8 *padded_authkey;
+       u8 *ipad_opad; /* IPAD, OPAD*/
+       dma_addr_t padded_authkey_dma_addr;
+       dma_addr_t ipad_opad_dma_addr;
+};
+
+struct cc_xcbc_s {
+       u8 *xcbc_keys; /* K1,K2,K3 */
+       dma_addr_t xcbc_keys_dma_addr;
+};
+
+struct cc_aead_ctx {
+       struct cc_drvdata *drvdata;
+       u8 ctr_nonce[MAX_NONCE_SIZE]; /* used for ctr3686 iv and aes ccm */
+       u8 *enckey;
+       dma_addr_t enckey_dma_addr;
+       union {
+               struct cc_hmac_s hmac;
+               struct cc_xcbc_s xcbc;
+       } auth_state;
+       unsigned int enc_keylen;
+       unsigned int auth_keylen;
+       unsigned int authsize; /* Actual (reduced?) size of the MAC/ICv */
+       enum drv_cipher_mode cipher_mode;
+       enum cc_flow_mode flow_mode;
+       enum drv_hash_mode auth_mode;
+};
+
+static inline bool valid_assoclen(struct aead_request *req)
+{
+       return ((req->assoclen == 16) || (req->assoclen == 20));
+}
+
+static void cc_aead_exit(struct crypto_aead *tfm)
+{
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "Clearing context @%p for %s\n", crypto_aead_ctx(tfm),
+               crypto_tfm_alg_name(&tfm->base));
+
+       /* Unmap enckey buffer */
+       if (ctx->enckey) {
+               dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey,
+                                 ctx->enckey_dma_addr);
+               dev_dbg(dev, "Freed enckey DMA buffer enckey_dma_addr=%pad\n",
+                       &ctx->enckey_dma_addr);
+               ctx->enckey_dma_addr = 0;
+               ctx->enckey = NULL;
+       }
+
+       if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */
+               struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc;
+
+               if (xcbc->xcbc_keys) {
+                       dma_free_coherent(dev, CC_AES_128_BIT_KEY_SIZE * 3,
+                                         xcbc->xcbc_keys,
+                                         xcbc->xcbc_keys_dma_addr);
+               }
+               dev_dbg(dev, "Freed xcbc_keys DMA buffer xcbc_keys_dma_addr=%pad\n",
+                       &xcbc->xcbc_keys_dma_addr);
+               xcbc->xcbc_keys_dma_addr = 0;
+               xcbc->xcbc_keys = NULL;
+       } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC auth. */
+               struct cc_hmac_s *hmac = &ctx->auth_state.hmac;
+
+               if (hmac->ipad_opad) {
+                       dma_free_coherent(dev, 2 * MAX_HMAC_DIGEST_SIZE,
+                                         hmac->ipad_opad,
+                                         hmac->ipad_opad_dma_addr);
+                       dev_dbg(dev, "Freed ipad_opad DMA buffer ipad_opad_dma_addr=%pad\n",
+                               &hmac->ipad_opad_dma_addr);
+                       hmac->ipad_opad_dma_addr = 0;
+                       hmac->ipad_opad = NULL;
+               }
+               if (hmac->padded_authkey) {
+                       dma_free_coherent(dev, MAX_HMAC_BLOCK_SIZE,
+                                         hmac->padded_authkey,
+                                         hmac->padded_authkey_dma_addr);
+                       dev_dbg(dev, "Freed padded_authkey DMA buffer padded_authkey_dma_addr=%pad\n",
+                               &hmac->padded_authkey_dma_addr);
+                       hmac->padded_authkey_dma_addr = 0;
+                       hmac->padded_authkey = NULL;
+               }
+       }
+}
+
+static int cc_aead_init(struct crypto_aead *tfm)
+{
+       struct aead_alg *alg = crypto_aead_alg(tfm);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct cc_crypto_alg *cc_alg =
+                       container_of(alg, struct cc_crypto_alg, aead_alg);
+       struct device *dev = drvdata_to_dev(cc_alg->drvdata);
+
+       dev_dbg(dev, "Initializing context @%p for %s\n", ctx,
+               crypto_tfm_alg_name(&tfm->base));
+
+       /* Initialize modes in instance */
+       ctx->cipher_mode = cc_alg->cipher_mode;
+       ctx->flow_mode = cc_alg->flow_mode;
+       ctx->auth_mode = cc_alg->auth_mode;
+       ctx->drvdata = cc_alg->drvdata;
+       crypto_aead_set_reqsize(tfm, sizeof(struct aead_req_ctx));
+
+       /* Allocate key buffer, cache line aligned */
+       ctx->enckey = dma_alloc_coherent(dev, AES_MAX_KEY_SIZE,
+                                        &ctx->enckey_dma_addr, GFP_KERNEL);
+       if (!ctx->enckey) {
+               dev_err(dev, "Failed allocating key buffer\n");
+               goto init_failed;
+       }
+       dev_dbg(dev, "Allocated enckey buffer in context ctx->enckey=@%p\n",
+               ctx->enckey);
+
+       /* Set default authlen value */
+
+       if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */
+               struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc;
+               const unsigned int key_size = CC_AES_128_BIT_KEY_SIZE * 3;
+
+               /* Allocate dma-coherent buffer for XCBC's K1+K2+K3 */
+               /* (and temporary for user key - up to 256b) */
+               xcbc->xcbc_keys = dma_alloc_coherent(dev, key_size,
+                                                    &xcbc->xcbc_keys_dma_addr,
+                                                    GFP_KERNEL);
+               if (!xcbc->xcbc_keys) {
+                       dev_err(dev, "Failed allocating buffer for XCBC keys\n");
+                       goto init_failed;
+               }
+       } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC authentication */
+               struct cc_hmac_s *hmac = &ctx->auth_state.hmac;
+               const unsigned int digest_size = 2 * MAX_HMAC_DIGEST_SIZE;
+               dma_addr_t *pkey_dma = &hmac->padded_authkey_dma_addr;
+
+               /* Allocate dma-coherent buffer for IPAD + OPAD */
+               hmac->ipad_opad = dma_alloc_coherent(dev, digest_size,
+                                                    &hmac->ipad_opad_dma_addr,
+                                                    GFP_KERNEL);
+
+               if (!hmac->ipad_opad) {
+                       dev_err(dev, "Failed allocating IPAD/OPAD buffer\n");
+                       goto init_failed;
+               }
+
+               dev_dbg(dev, "Allocated authkey buffer in context ctx->authkey=@%p\n",
+                       hmac->ipad_opad);
+
+               hmac->padded_authkey = dma_alloc_coherent(dev,
+                                                         MAX_HMAC_BLOCK_SIZE,
+                                                         pkey_dma,
+                                                         GFP_KERNEL);
+
+               if (!hmac->padded_authkey) {
+                       dev_err(dev, "failed to allocate padded_authkey\n");
+                       goto init_failed;
+               }
+       } else {
+               ctx->auth_state.hmac.ipad_opad = NULL;
+               ctx->auth_state.hmac.padded_authkey = NULL;
+       }
+
+       return 0;
+
+init_failed:
+       cc_aead_exit(tfm);
+       return -ENOMEM;
+}
+
+static void cc_aead_complete(struct device *dev, void *cc_req, int err)
+{
+       struct aead_request *areq = (struct aead_request *)cc_req;
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(areq);
+       struct crypto_aead *tfm = crypto_aead_reqtfm(cc_req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+
+       cc_unmap_aead_request(dev, areq);
+
+       /* Restore ordinary iv pointer */
+       areq->iv = areq_ctx->backup_iv;
+
+       if (err)
+               goto done;
+
+       if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
+               if (memcmp(areq_ctx->mac_buf, areq_ctx->icv_virt_addr,
+                          ctx->authsize) != 0) {
+                       dev_dbg(dev, "Payload authentication failure, (auth-size=%d, cipher=%d)\n",
+                               ctx->authsize, ctx->cipher_mode);
+                       /* In case of payload authentication failure, MUST NOT
+                        * revealed the decrypted message --> zero its memory.
+                        */
+                       cc_zero_sgl(areq->dst, areq_ctx->cryptlen);
+                       err = -EBADMSG;
+               }
+       } else { /*ENCRYPT*/
+               if (areq_ctx->is_icv_fragmented) {
+                       u32 skip = areq->cryptlen + areq_ctx->dst_offset;
+
+                       cc_copy_sg_portion(dev, areq_ctx->mac_buf,
+                                          areq_ctx->dst_sgl, skip,
+                                          (skip + ctx->authsize),
+                                          CC_SG_FROM_BUF);
+               }
+
+               /* If an IV was generated, copy it back to the user provided
+                * buffer.
+                */
+               if (areq_ctx->backup_giv) {
+                       if (ctx->cipher_mode == DRV_CIPHER_CTR)
+                               memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv +
+                                      CTR_RFC3686_NONCE_SIZE,
+                                      CTR_RFC3686_IV_SIZE);
+                       else if (ctx->cipher_mode == DRV_CIPHER_CCM)
+                               memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv +
+                                      CCM_BLOCK_IV_OFFSET, CCM_BLOCK_IV_SIZE);
+               }
+       }
+done:
+       aead_request_complete(areq, err);
+}
+
+static int xcbc_setkey(struct cc_hw_desc *desc, struct cc_aead_ctx *ctx)
+{
+       /* Load the AES key */
+       hw_desc_init(&desc[0]);
+       /* We are using for the source/user key the same buffer
+        * as for the output keys, * because after this key loading it
+        * is not needed anymore
+        */
+       set_din_type(&desc[0], DMA_DLLI,
+                    ctx->auth_state.xcbc.xcbc_keys_dma_addr, ctx->auth_keylen,
+                    NS_BIT);
+       set_cipher_mode(&desc[0], DRV_CIPHER_ECB);
+       set_cipher_config0(&desc[0], DRV_CRYPTO_DIRECTION_ENCRYPT);
+       set_key_size_aes(&desc[0], ctx->auth_keylen);
+       set_flow_mode(&desc[0], S_DIN_to_AES);
+       set_setup_mode(&desc[0], SETUP_LOAD_KEY0);
+
+       hw_desc_init(&desc[1]);
+       set_din_const(&desc[1], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[1], DIN_AES_DOUT);
+       set_dout_dlli(&desc[1], ctx->auth_state.xcbc.xcbc_keys_dma_addr,
+                     AES_KEYSIZE_128, NS_BIT, 0);
+
+       hw_desc_init(&desc[2]);
+       set_din_const(&desc[2], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[2], DIN_AES_DOUT);
+       set_dout_dlli(&desc[2], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
+                                        + AES_KEYSIZE_128),
+                             AES_KEYSIZE_128, NS_BIT, 0);
+
+       hw_desc_init(&desc[3]);
+       set_din_const(&desc[3], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[3], DIN_AES_DOUT);
+       set_dout_dlli(&desc[3], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
+                                         + 2 * AES_KEYSIZE_128),
+                             AES_KEYSIZE_128, NS_BIT, 0);
+
+       return 4;
+}
+
+static int hmac_setkey(struct cc_hw_desc *desc, struct cc_aead_ctx *ctx)
+{
+       unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST };
+       unsigned int digest_ofs = 0;
+       unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
+                       DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
+       unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
+                       CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
+       struct cc_hmac_s *hmac = &ctx->auth_state.hmac;
+
+       int idx = 0;
+       int i;
+
+       /* calc derived HMAC key */
+       for (i = 0; i < 2; i++) {
+               /* Load hash initial state */
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], hash_mode);
+               set_din_sram(&desc[idx],
+                            cc_larval_digest_addr(ctx->drvdata,
+                                                  ctx->auth_mode),
+                            digest_size);
+               set_flow_mode(&desc[idx], S_DIN_to_HASH);
+               set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+               idx++;
+
+               /* Load the hash current length*/
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], hash_mode);
+               set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+               set_flow_mode(&desc[idx], S_DIN_to_HASH);
+               set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+               idx++;
+
+               /* Prepare ipad key */
+               hw_desc_init(&desc[idx]);
+               set_xor_val(&desc[idx], hmac_pad_const[i]);
+               set_cipher_mode(&desc[idx], hash_mode);
+               set_flow_mode(&desc[idx], S_DIN_to_HASH);
+               set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+               idx++;
+
+               /* Perform HASH update */
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_DLLI,
+                            hmac->padded_authkey_dma_addr,
+                            SHA256_BLOCK_SIZE, NS_BIT);
+               set_cipher_mode(&desc[idx], hash_mode);
+               set_xor_active(&desc[idx]);
+               set_flow_mode(&desc[idx], DIN_HASH);
+               idx++;
+
+               /* Get the digset */
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], hash_mode);
+               set_dout_dlli(&desc[idx],
+                             (hmac->ipad_opad_dma_addr + digest_ofs),
+                             digest_size, NS_BIT, 0);
+               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+               set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+               idx++;
+
+               digest_ofs += digest_size;
+       }
+
+       return idx;
+}
+
+static int validate_keys_sizes(struct cc_aead_ctx *ctx)
+{
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "enc_keylen=%u  authkeylen=%u\n",
+               ctx->enc_keylen, ctx->auth_keylen);
+
+       switch (ctx->auth_mode) {
+       case DRV_HASH_SHA1:
+       case DRV_HASH_SHA256:
+               break;
+       case DRV_HASH_XCBC_MAC:
+               if (ctx->auth_keylen != AES_KEYSIZE_128 &&
+                   ctx->auth_keylen != AES_KEYSIZE_192 &&
+                   ctx->auth_keylen != AES_KEYSIZE_256)
+                       return -ENOTSUPP;
+               break;
+       case DRV_HASH_NULL: /* Not authenc (e.g., CCM) - no auth_key) */
+               if (ctx->auth_keylen > 0)
+                       return -EINVAL;
+               break;
+       default:
+               dev_err(dev, "Invalid auth_mode=%d\n", ctx->auth_mode);
+               return -EINVAL;
+       }
+       /* Check cipher key size */
+       if (ctx->flow_mode == S_DIN_to_DES) {
+               if (ctx->enc_keylen != DES3_EDE_KEY_SIZE) {
+                       dev_err(dev, "Invalid cipher(3DES) key size: %u\n",
+                               ctx->enc_keylen);
+                       return -EINVAL;
+               }
+       } else { /* Default assumed to be AES ciphers */
+               if (ctx->enc_keylen != AES_KEYSIZE_128 &&
+                   ctx->enc_keylen != AES_KEYSIZE_192 &&
+                   ctx->enc_keylen != AES_KEYSIZE_256) {
+                       dev_err(dev, "Invalid cipher(AES) key size: %u\n",
+                               ctx->enc_keylen);
+                       return -EINVAL;
+               }
+       }
+
+       return 0; /* All tests of keys sizes passed */
+}
+
+/* This function prepers the user key so it can pass to the hmac processing
+ * (copy to intenral buffer or hash in case of key longer than block
+ */
+static int
+cc_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key,
+                     unsigned int keylen)
+{
+       dma_addr_t key_dma_addr = 0;
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       u32 larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->auth_mode);
+       struct cc_crypto_req cc_req = {};
+       unsigned int blocksize;
+       unsigned int digestsize;
+       unsigned int hashmode;
+       unsigned int idx = 0;
+       int rc = 0;
+       struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
+       dma_addr_t padded_authkey_dma_addr =
+               ctx->auth_state.hmac.padded_authkey_dma_addr;
+
+       switch (ctx->auth_mode) { /* auth_key required and >0 */
+       case DRV_HASH_SHA1:
+               blocksize = SHA1_BLOCK_SIZE;
+               digestsize = SHA1_DIGEST_SIZE;
+               hashmode = DRV_HASH_HW_SHA1;
+               break;
+       case DRV_HASH_SHA256:
+       default:
+               blocksize = SHA256_BLOCK_SIZE;
+               digestsize = SHA256_DIGEST_SIZE;
+               hashmode = DRV_HASH_HW_SHA256;
+       }
+
+       if (keylen != 0) {
+               key_dma_addr = dma_map_single(dev, (void *)key, keylen,
+                                             DMA_TO_DEVICE);
+               if (dma_mapping_error(dev, key_dma_addr)) {
+                       dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
+                               key, keylen);
+                       return -ENOMEM;
+               }
+               if (keylen > blocksize) {
+                       /* Load hash initial state */
+                       hw_desc_init(&desc[idx]);
+                       set_cipher_mode(&desc[idx], hashmode);
+                       set_din_sram(&desc[idx], larval_addr, digestsize);
+                       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+                       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+                       idx++;
+
+                       /* Load the hash current length*/
+                       hw_desc_init(&desc[idx]);
+                       set_cipher_mode(&desc[idx], hashmode);
+                       set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+                       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+                       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+                       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+                       idx++;
+
+                       hw_desc_init(&desc[idx]);
+                       set_din_type(&desc[idx], DMA_DLLI,
+                                    key_dma_addr, keylen, NS_BIT);
+                       set_flow_mode(&desc[idx], DIN_HASH);
+                       idx++;
+
+                       /* Get hashed key */
+                       hw_desc_init(&desc[idx]);
+                       set_cipher_mode(&desc[idx], hashmode);
+                       set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
+                                     digestsize, NS_BIT, 0);
+                       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+                       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+                       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+                       set_cipher_config0(&desc[idx],
+                                          HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+                       idx++;
+
+                       hw_desc_init(&desc[idx]);
+                       set_din_const(&desc[idx], 0, (blocksize - digestsize));
+                       set_flow_mode(&desc[idx], BYPASS);
+                       set_dout_dlli(&desc[idx], (padded_authkey_dma_addr +
+                                     digestsize), (blocksize - digestsize),
+                                     NS_BIT, 0);
+                       idx++;
+               } else {
+                       hw_desc_init(&desc[idx]);
+                       set_din_type(&desc[idx], DMA_DLLI, key_dma_addr,
+                                    keylen, NS_BIT);
+                       set_flow_mode(&desc[idx], BYPASS);
+                       set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
+                                     keylen, NS_BIT, 0);
+                       idx++;
+
+                       if ((blocksize - keylen) != 0) {
+                               hw_desc_init(&desc[idx]);
+                               set_din_const(&desc[idx], 0,
+                                             (blocksize - keylen));
+                               set_flow_mode(&desc[idx], BYPASS);
+                               set_dout_dlli(&desc[idx],
+                                             (padded_authkey_dma_addr +
+                                              keylen),
+                                             (blocksize - keylen), NS_BIT, 0);
+                               idx++;
+                       }
+               }
+       } else {
+               hw_desc_init(&desc[idx]);
+               set_din_const(&desc[idx], 0, (blocksize - keylen));
+               set_flow_mode(&desc[idx], BYPASS);
+               set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
+                             blocksize, NS_BIT, 0);
+               idx++;
+       }
+
+       rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx);
+       if (rc)
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+
+       if (key_dma_addr)
+               dma_unmap_single(dev, key_dma_addr, keylen, DMA_TO_DEVICE);
+
+       return rc;
+}
+
+static int
+cc_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
+{
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct rtattr *rta = (struct rtattr *)key;
+       struct cc_crypto_req cc_req = {};
+       struct crypto_authenc_key_param *param;
+       struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
+       int seq_len = 0, rc = -EINVAL;
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "Setting key in context @%p for %s. key=%p keylen=%u\n",
+               ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen);
+
+       /* STAT_PHASE_0: Init and sanity checks */
+
+       if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */
+               if (!RTA_OK(rta, keylen))
+                       goto badkey;
+               if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+                       goto badkey;
+               if (RTA_PAYLOAD(rta) < sizeof(*param))
+                       goto badkey;
+               param = RTA_DATA(rta);
+               ctx->enc_keylen = be32_to_cpu(param->enckeylen);
+               key += RTA_ALIGN(rta->rta_len);
+               keylen -= RTA_ALIGN(rta->rta_len);
+               if (keylen < ctx->enc_keylen)
+                       goto badkey;
+               ctx->auth_keylen = keylen - ctx->enc_keylen;
+
+               if (ctx->cipher_mode == DRV_CIPHER_CTR) {
+                       /* the nonce is stored in bytes at end of key */
+                       if (ctx->enc_keylen <
+                           (AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE))
+                               goto badkey;
+                       /* Copy nonce from last 4 bytes in CTR key to
+                        *  first 4 bytes in CTR IV
+                        */
+                       memcpy(ctx->ctr_nonce, key + ctx->auth_keylen +
+                              ctx->enc_keylen - CTR_RFC3686_NONCE_SIZE,
+                              CTR_RFC3686_NONCE_SIZE);
+                       /* Set CTR key size */
+                       ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE;
+               }
+       } else { /* non-authenc - has just one key */
+               ctx->enc_keylen = keylen;
+               ctx->auth_keylen = 0;
+       }
+
+       rc = validate_keys_sizes(ctx);
+       if (rc)
+               goto badkey;
+
+       /* STAT_PHASE_1: Copy key to ctx */
+
+       /* Get key material */
+       memcpy(ctx->enckey, key + ctx->auth_keylen, ctx->enc_keylen);
+       if (ctx->enc_keylen == 24)
+               memset(ctx->enckey + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
+       if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
+               memcpy(ctx->auth_state.xcbc.xcbc_keys, key, ctx->auth_keylen);
+       } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */
+               rc = cc_get_plain_hmac_key(tfm, key, ctx->auth_keylen);
+               if (rc)
+                       goto badkey;
+       }
+
+       /* STAT_PHASE_2: Create sequence */
+
+       switch (ctx->auth_mode) {
+       case DRV_HASH_SHA1:
+       case DRV_HASH_SHA256:
+               seq_len = hmac_setkey(desc, ctx);
+               break;
+       case DRV_HASH_XCBC_MAC:
+               seq_len = xcbc_setkey(desc, ctx);
+               break;
+       case DRV_HASH_NULL: /* non-authenc modes, e.g., CCM */
+               break; /* No auth. key setup */
+       default:
+               dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode);
+               rc = -ENOTSUPP;
+               goto badkey;
+       }
+
+       /* STAT_PHASE_3: Submit sequence to HW */
+
+       if (seq_len > 0) { /* For CCM there is no sequence to setup the key */
+               rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, seq_len);
+               if (rc) {
+                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+                       goto setkey_error;
+               }
+       }
+
+       /* Update STAT_PHASE_3 */
+       return rc;
+
+badkey:
+       crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+
+setkey_error:
+       return rc;
+}
+
+static int cc_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key,
+                                unsigned int keylen)
+{
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+
+       if (keylen < 3)
+               return -EINVAL;
+
+       keylen -= 3;
+       memcpy(ctx->ctr_nonce, key + keylen, 3);
+
+       return cc_aead_setkey(tfm, key, keylen);
+}
+
+static int cc_aead_setauthsize(struct crypto_aead *authenc,
+                              unsigned int authsize)
+{
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       /* Unsupported auth. sizes */
+       if (authsize == 0 ||
+           authsize > crypto_aead_maxauthsize(authenc)) {
+               return -ENOTSUPP;
+       }
+
+       ctx->authsize = authsize;
+       dev_dbg(dev, "authlen=%d\n", ctx->authsize);
+
+       return 0;
+}
+
+static int cc_rfc4309_ccm_setauthsize(struct crypto_aead *authenc,
+                                     unsigned int authsize)
+{
+       switch (authsize) {
+       case 8:
+       case 12:
+       case 16:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return cc_aead_setauthsize(authenc, authsize);
+}
+
+static int cc_ccm_setauthsize(struct crypto_aead *authenc,
+                             unsigned int authsize)
+{
+       switch (authsize) {
+       case 4:
+       case 6:
+       case 8:
+       case 10:
+       case 12:
+       case 14:
+       case 16:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return cc_aead_setauthsize(authenc, authsize);
+}
+
+static void cc_set_assoc_desc(struct aead_request *areq, unsigned int flow_mode,
+                             struct cc_hw_desc desc[], unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(areq);
+       enum cc_req_dma_buf_type assoc_dma_type = areq_ctx->assoc_buff_type;
+       unsigned int idx = *seq_size;
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       switch (assoc_dma_type) {
+       case CC_DMA_BUF_DLLI:
+               dev_dbg(dev, "ASSOC buffer type DLLI\n");
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_DLLI, sg_dma_address(areq->src),
+                            areq->assoclen, NS_BIT);
+               set_flow_mode(&desc[idx], flow_mode);
+               if (ctx->auth_mode == DRV_HASH_XCBC_MAC &&
+                   areq_ctx->cryptlen > 0)
+                       set_din_not_last_indication(&desc[idx]);
+               break;
+       case CC_DMA_BUF_MLLI:
+               dev_dbg(dev, "ASSOC buffer type MLLI\n");
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_MLLI, areq_ctx->assoc.sram_addr,
+                            areq_ctx->assoc.mlli_nents, NS_BIT);
+               set_flow_mode(&desc[idx], flow_mode);
+               if (ctx->auth_mode == DRV_HASH_XCBC_MAC &&
+                   areq_ctx->cryptlen > 0)
+                       set_din_not_last_indication(&desc[idx]);
+               break;
+       case CC_DMA_BUF_NULL:
+       default:
+               dev_err(dev, "Invalid ASSOC buffer type\n");
+       }
+
+       *seq_size = (++idx);
+}
+
+static void cc_proc_authen_desc(struct aead_request *areq,
+                               unsigned int flow_mode,
+                               struct cc_hw_desc desc[],
+                               unsigned int *seq_size, int direct)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(areq);
+       enum cc_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type;
+       unsigned int idx = *seq_size;
+       struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       switch (data_dma_type) {
+       case CC_DMA_BUF_DLLI:
+       {
+               struct scatterlist *cipher =
+                       (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+                       areq_ctx->dst_sgl : areq_ctx->src_sgl;
+
+               unsigned int offset =
+                       (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+                       areq_ctx->dst_offset : areq_ctx->src_offset;
+               dev_dbg(dev, "AUTHENC: SRC/DST buffer type DLLI\n");
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_DLLI,
+                            (sg_dma_address(cipher) + offset),
+                            areq_ctx->cryptlen, NS_BIT);
+               set_flow_mode(&desc[idx], flow_mode);
+               break;
+       }
+       case CC_DMA_BUF_MLLI:
+       {
+               /* DOUBLE-PASS flow (as default)
+                * assoc. + iv + data -compact in one table
+                * if assoclen is ZERO only IV perform
+                */
+               cc_sram_addr_t mlli_addr = areq_ctx->assoc.sram_addr;
+               u32 mlli_nents = areq_ctx->assoc.mlli_nents;
+
+               if (areq_ctx->is_single_pass) {
+                       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
+                               mlli_addr = areq_ctx->dst.sram_addr;
+                               mlli_nents = areq_ctx->dst.mlli_nents;
+                       } else {
+                               mlli_addr = areq_ctx->src.sram_addr;
+                               mlli_nents = areq_ctx->src.mlli_nents;
+                       }
+               }
+
+               dev_dbg(dev, "AUTHENC: SRC/DST buffer type MLLI\n");
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_MLLI, mlli_addr, mlli_nents,
+                            NS_BIT);
+               set_flow_mode(&desc[idx], flow_mode);
+               break;
+       }
+       case CC_DMA_BUF_NULL:
+       default:
+               dev_err(dev, "AUTHENC: Invalid SRC/DST buffer type\n");
+       }
+
+       *seq_size = (++idx);
+}
+
+static void cc_proc_cipher_desc(struct aead_request *areq,
+                               unsigned int flow_mode,
+                               struct cc_hw_desc desc[],
+                               unsigned int *seq_size)
+{
+       unsigned int idx = *seq_size;
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(areq);
+       enum cc_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type;
+       struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       if (areq_ctx->cryptlen == 0)
+               return; /*null processing*/
+
+       switch (data_dma_type) {
+       case CC_DMA_BUF_DLLI:
+               dev_dbg(dev, "CIPHER: SRC/DST buffer type DLLI\n");
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_DLLI,
+                            (sg_dma_address(areq_ctx->src_sgl) +
+                             areq_ctx->src_offset), areq_ctx->cryptlen,
+                             NS_BIT);
+               set_dout_dlli(&desc[idx],
+                             (sg_dma_address(areq_ctx->dst_sgl) +
+                              areq_ctx->dst_offset),
+                             areq_ctx->cryptlen, NS_BIT, 0);
+               set_flow_mode(&desc[idx], flow_mode);
+               break;
+       case CC_DMA_BUF_MLLI:
+               dev_dbg(dev, "CIPHER: SRC/DST buffer type MLLI\n");
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_MLLI, areq_ctx->src.sram_addr,
+                            areq_ctx->src.mlli_nents, NS_BIT);
+               set_dout_mlli(&desc[idx], areq_ctx->dst.sram_addr,
+                             areq_ctx->dst.mlli_nents, NS_BIT, 0);
+               set_flow_mode(&desc[idx], flow_mode);
+               break;
+       case CC_DMA_BUF_NULL:
+       default:
+               dev_err(dev, "CIPHER: Invalid SRC/DST buffer type\n");
+       }
+
+       *seq_size = (++idx);
+}
+
+static void cc_proc_digest_desc(struct aead_request *req,
+                               struct cc_hw_desc desc[],
+                               unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       unsigned int idx = *seq_size;
+       unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
+                               DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
+       int direct = req_ctx->gen_ctx.op_type;
+
+       /* Get final ICV result */
+       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
+               hw_desc_init(&desc[idx]);
+               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+               set_dout_dlli(&desc[idx], req_ctx->icv_dma_addr, ctx->authsize,
+                             NS_BIT, 1);
+               set_queue_last_ind(&desc[idx]);
+               if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
+                       set_aes_not_hash_mode(&desc[idx]);
+                       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+               } else {
+                       set_cipher_config0(&desc[idx],
+                                          HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+                       set_cipher_mode(&desc[idx], hash_mode);
+               }
+       } else { /*Decrypt*/
+               /* Get ICV out from hardware */
+               hw_desc_init(&desc[idx]);
+               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+               set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr,
+                             ctx->authsize, NS_BIT, 1);
+               set_queue_last_ind(&desc[idx]);
+               set_cipher_config0(&desc[idx],
+                                  HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+               set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+               if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
+                       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+                       set_aes_not_hash_mode(&desc[idx]);
+               } else {
+                       set_cipher_mode(&desc[idx], hash_mode);
+               }
+       }
+
+       *seq_size = (++idx);
+}
+
+static void cc_set_cipher_desc(struct aead_request *req,
+                              struct cc_hw_desc desc[],
+                              unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       unsigned int hw_iv_size = req_ctx->hw_iv_size;
+       unsigned int idx = *seq_size;
+       int direct = req_ctx->gen_ctx.op_type;
+
+       /* Setup cipher state */
+       hw_desc_init(&desc[idx]);
+       set_cipher_config0(&desc[idx], direct);
+       set_flow_mode(&desc[idx], ctx->flow_mode);
+       set_din_type(&desc[idx], DMA_DLLI, req_ctx->gen_ctx.iv_dma_addr,
+                    hw_iv_size, NS_BIT);
+       if (ctx->cipher_mode == DRV_CIPHER_CTR)
+               set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+       else
+               set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       set_cipher_mode(&desc[idx], ctx->cipher_mode);
+       idx++;
+
+       /* Setup enc. key */
+       hw_desc_init(&desc[idx]);
+       set_cipher_config0(&desc[idx], direct);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       set_flow_mode(&desc[idx], ctx->flow_mode);
+       if (ctx->flow_mode == S_DIN_to_AES) {
+               set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+                            ((ctx->enc_keylen == 24) ? CC_AES_KEY_SIZE_MAX :
+                             ctx->enc_keylen), NS_BIT);
+               set_key_size_aes(&desc[idx], ctx->enc_keylen);
+       } else {
+               set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+                            ctx->enc_keylen, NS_BIT);
+               set_key_size_des(&desc[idx], ctx->enc_keylen);
+       }
+       set_cipher_mode(&desc[idx], ctx->cipher_mode);
+       idx++;
+
+       *seq_size = idx;
+}
+
+static void cc_proc_cipher(struct aead_request *req, struct cc_hw_desc desc[],
+                          unsigned int *seq_size, unsigned int data_flow_mode)
+{
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       int direct = req_ctx->gen_ctx.op_type;
+       unsigned int idx = *seq_size;
+
+       if (req_ctx->cryptlen == 0)
+               return; /*null processing*/
+
+       cc_set_cipher_desc(req, desc, &idx);
+       cc_proc_cipher_desc(req, data_flow_mode, desc, &idx);
+       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
+               /* We must wait for DMA to write all cipher */
+               hw_desc_init(&desc[idx]);
+               set_din_no_dma(&desc[idx], 0, 0xfffff0);
+               set_dout_no_dma(&desc[idx], 0, 0, 1);
+               idx++;
+       }
+
+       *seq_size = idx;
+}
+
+static void cc_set_hmac_desc(struct aead_request *req, struct cc_hw_desc desc[],
+                            unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
+                               DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
+       unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
+                               CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
+       unsigned int idx = *seq_size;
+
+       /* Loading hash ipad xor key state */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], hash_mode);
+       set_din_type(&desc[idx], DMA_DLLI,
+                    ctx->auth_state.hmac.ipad_opad_dma_addr, digest_size,
+                    NS_BIT);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       idx++;
+
+       /* Load init. digest len (64 bytes) */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], hash_mode);
+       set_din_sram(&desc[idx], cc_digest_len_addr(ctx->drvdata, hash_mode),
+                    HASH_LEN_SIZE);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       idx++;
+
+       *seq_size = idx;
+}
+
+static void cc_set_xcbc_desc(struct aead_request *req, struct cc_hw_desc desc[],
+                            unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       unsigned int idx = *seq_size;
+
+       /* Loading MAC state */
+       hw_desc_init(&desc[idx]);
+       set_din_const(&desc[idx], 0, CC_AES_BLOCK_SIZE);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_aes_not_hash_mode(&desc[idx]);
+       idx++;
+
+       /* Setup XCBC MAC K1 */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI,
+                    ctx->auth_state.xcbc.xcbc_keys_dma_addr,
+                    AES_KEYSIZE_128, NS_BIT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_aes_not_hash_mode(&desc[idx]);
+       idx++;
+
+       /* Setup XCBC MAC K2 */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI,
+                    (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
+                     AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_aes_not_hash_mode(&desc[idx]);
+       idx++;
+
+       /* Setup XCBC MAC K3 */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI,
+                    (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
+                     2 * AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE2);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_aes_not_hash_mode(&desc[idx]);
+       idx++;
+
+       *seq_size = idx;
+}
+
+static void cc_proc_header_desc(struct aead_request *req,
+                               struct cc_hw_desc desc[],
+                               unsigned int *seq_size)
+{
+       unsigned int idx = *seq_size;
+       /* Hash associated data */
+       if (req->assoclen > 0)
+               cc_set_assoc_desc(req, DIN_HASH, desc, &idx);
+
+       /* Hash IV */
+       *seq_size = idx;
+}
+
+static void cc_proc_scheme_desc(struct aead_request *req,
+                               struct cc_hw_desc desc[],
+                               unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct cc_aead_handle *aead_handle = ctx->drvdata->aead_handle;
+       unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
+                               DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
+       unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
+                               CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
+       unsigned int idx = *seq_size;
+
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], hash_mode);
+       set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr,
+                     HASH_LEN_SIZE);
+       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
+       set_cipher_do(&desc[idx], DO_PAD);
+       idx++;
+
+       /* Get final ICV result */
+       hw_desc_init(&desc[idx]);
+       set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr,
+                     digest_size);
+       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+       set_cipher_mode(&desc[idx], hash_mode);
+       idx++;
+
+       /* Loading hash opad xor key state */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], hash_mode);
+       set_din_type(&desc[idx], DMA_DLLI,
+                    (ctx->auth_state.hmac.ipad_opad_dma_addr + digest_size),
+                    digest_size, NS_BIT);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       idx++;
+
+       /* Load init. digest len (64 bytes) */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], hash_mode);
+       set_din_sram(&desc[idx], cc_digest_len_addr(ctx->drvdata, hash_mode),
+                    HASH_LEN_SIZE);
+       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       idx++;
+
+       /* Perform HASH update */
+       hw_desc_init(&desc[idx]);
+       set_din_sram(&desc[idx], aead_handle->sram_workspace_addr,
+                    digest_size);
+       set_flow_mode(&desc[idx], DIN_HASH);
+       idx++;
+
+       *seq_size = idx;
+}
+
+static void cc_mlli_to_sram(struct aead_request *req,
+                           struct cc_hw_desc desc[], unsigned int *seq_size)
+{
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       if (req_ctx->assoc_buff_type == CC_DMA_BUF_MLLI ||
+           req_ctx->data_buff_type == CC_DMA_BUF_MLLI ||
+           !req_ctx->is_single_pass) {
+               dev_dbg(dev, "Copy-to-sram: mlli_dma=%08x, mlli_size=%u\n",
+                       (unsigned int)ctx->drvdata->mlli_sram_addr,
+                       req_ctx->mlli_params.mlli_len);
+               /* Copy MLLI table host-to-sram */
+               hw_desc_init(&desc[*seq_size]);
+               set_din_type(&desc[*seq_size], DMA_DLLI,
+                            req_ctx->mlli_params.mlli_dma_addr,
+                            req_ctx->mlli_params.mlli_len, NS_BIT);
+               set_dout_sram(&desc[*seq_size],
+                             ctx->drvdata->mlli_sram_addr,
+                             req_ctx->mlli_params.mlli_len);
+               set_flow_mode(&desc[*seq_size], BYPASS);
+               (*seq_size)++;
+       }
+}
+
+static enum cc_flow_mode cc_get_data_flow(enum drv_crypto_direction direct,
+                                         enum cc_flow_mode setup_flow_mode,
+                                         bool is_single_pass)
+{
+       enum cc_flow_mode data_flow_mode;
+
+       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
+               if (setup_flow_mode == S_DIN_to_AES)
+                       data_flow_mode = is_single_pass ?
+                               AES_to_HASH_and_DOUT : DIN_AES_DOUT;
+               else
+                       data_flow_mode = is_single_pass ?
+                               DES_to_HASH_and_DOUT : DIN_DES_DOUT;
+       } else { /* Decrypt */
+               if (setup_flow_mode == S_DIN_to_AES)
+                       data_flow_mode = is_single_pass ?
+                               AES_and_HASH : DIN_AES_DOUT;
+               else
+                       data_flow_mode = is_single_pass ?
+                               DES_and_HASH : DIN_DES_DOUT;
+       }
+
+       return data_flow_mode;
+}
+
+static void cc_hmac_authenc(struct aead_request *req, struct cc_hw_desc desc[],
+                           unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       int direct = req_ctx->gen_ctx.op_type;
+       unsigned int data_flow_mode =
+               cc_get_data_flow(direct, ctx->flow_mode,
+                                req_ctx->is_single_pass);
+
+       if (req_ctx->is_single_pass) {
+               /**
+                * Single-pass flow
+                */
+               cc_set_hmac_desc(req, desc, seq_size);
+               cc_set_cipher_desc(req, desc, seq_size);
+               cc_proc_header_desc(req, desc, seq_size);
+               cc_proc_cipher_desc(req, data_flow_mode, desc, seq_size);
+               cc_proc_scheme_desc(req, desc, seq_size);
+               cc_proc_digest_desc(req, desc, seq_size);
+               return;
+       }
+
+       /**
+        * Double-pass flow
+        * Fallback for unsupported single-pass modes,
+        * i.e. using assoc. data of non-word-multiple
+        */
+       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
+               /* encrypt first.. */
+               cc_proc_cipher(req, desc, seq_size, data_flow_mode);
+               /* authenc after..*/
+               cc_set_hmac_desc(req, desc, seq_size);
+               cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct);
+               cc_proc_scheme_desc(req, desc, seq_size);
+               cc_proc_digest_desc(req, desc, seq_size);
+
+       } else { /*DECRYPT*/
+               /* authenc first..*/
+               cc_set_hmac_desc(req, desc, seq_size);
+               cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct);
+               cc_proc_scheme_desc(req, desc, seq_size);
+               /* decrypt after.. */
+               cc_proc_cipher(req, desc, seq_size, data_flow_mode);
+               /* read the digest result with setting the completion bit
+                * must be after the cipher operation
+                */
+               cc_proc_digest_desc(req, desc, seq_size);
+       }
+}
+
+static void
+cc_xcbc_authenc(struct aead_request *req, struct cc_hw_desc desc[],
+               unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       int direct = req_ctx->gen_ctx.op_type;
+       unsigned int data_flow_mode =
+               cc_get_data_flow(direct, ctx->flow_mode,
+                                req_ctx->is_single_pass);
+
+       if (req_ctx->is_single_pass) {
+               /**
+                * Single-pass flow
+                */
+               cc_set_xcbc_desc(req, desc, seq_size);
+               cc_set_cipher_desc(req, desc, seq_size);
+               cc_proc_header_desc(req, desc, seq_size);
+               cc_proc_cipher_desc(req, data_flow_mode, desc, seq_size);
+               cc_proc_digest_desc(req, desc, seq_size);
+               return;
+       }
+
+       /**
+        * Double-pass flow
+        * Fallback for unsupported single-pass modes,
+        * i.e. using assoc. data of non-word-multiple
+        */
+       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
+               /* encrypt first.. */
+               cc_proc_cipher(req, desc, seq_size, data_flow_mode);
+               /* authenc after.. */
+               cc_set_xcbc_desc(req, desc, seq_size);
+               cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct);
+               cc_proc_digest_desc(req, desc, seq_size);
+       } else { /*DECRYPT*/
+               /* authenc first.. */
+               cc_set_xcbc_desc(req, desc, seq_size);
+               cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct);
+               /* decrypt after..*/
+               cc_proc_cipher(req, desc, seq_size, data_flow_mode);
+               /* read the digest result with setting the completion bit
+                * must be after the cipher operation
+                */
+               cc_proc_digest_desc(req, desc, seq_size);
+       }
+}
+
+static int validate_data_size(struct cc_aead_ctx *ctx,
+                             enum drv_crypto_direction direct,
+                             struct aead_request *req)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       unsigned int assoclen = req->assoclen;
+       unsigned int cipherlen = (direct == DRV_CRYPTO_DIRECTION_DECRYPT) ?
+                       (req->cryptlen - ctx->authsize) : req->cryptlen;
+
+       if (direct == DRV_CRYPTO_DIRECTION_DECRYPT &&
+           req->cryptlen < ctx->authsize)
+               goto data_size_err;
+
+       areq_ctx->is_single_pass = true; /*defaulted to fast flow*/
+
+       switch (ctx->flow_mode) {
+       case S_DIN_to_AES:
+               if (ctx->cipher_mode == DRV_CIPHER_CBC &&
+                   !IS_ALIGNED(cipherlen, AES_BLOCK_SIZE))
+                       goto data_size_err;
+               if (ctx->cipher_mode == DRV_CIPHER_CCM)
+                       break;
+               if (ctx->cipher_mode == DRV_CIPHER_GCTR) {
+                       if (areq_ctx->plaintext_authenticate_only)
+                               areq_ctx->is_single_pass = false;
+                       break;
+               }
+
+               if (!IS_ALIGNED(assoclen, sizeof(u32)))
+                       areq_ctx->is_single_pass = false;
+
+               if (ctx->cipher_mode == DRV_CIPHER_CTR &&
+                   !IS_ALIGNED(cipherlen, sizeof(u32)))
+                       areq_ctx->is_single_pass = false;
+
+               break;
+       case S_DIN_to_DES:
+               if (!IS_ALIGNED(cipherlen, DES_BLOCK_SIZE))
+                       goto data_size_err;
+               if (!IS_ALIGNED(assoclen, DES_BLOCK_SIZE))
+                       areq_ctx->is_single_pass = false;
+               break;
+       default:
+               dev_err(dev, "Unexpected flow mode (%d)\n", ctx->flow_mode);
+               goto data_size_err;
+       }
+
+       return 0;
+
+data_size_err:
+       return -EINVAL;
+}
+
+static unsigned int format_ccm_a0(u8 *pa0_buff, u32 header_size)
+{
+       unsigned int len = 0;
+
+       if (header_size == 0)
+               return 0;
+
+       if (header_size < ((1UL << 16) - (1UL << 8))) {
+               len = 2;
+
+               pa0_buff[0] = (header_size >> 8) & 0xFF;
+               pa0_buff[1] = header_size & 0xFF;
+       } else {
+               len = 6;
+
+               pa0_buff[0] = 0xFF;
+               pa0_buff[1] = 0xFE;
+               pa0_buff[2] = (header_size >> 24) & 0xFF;
+               pa0_buff[3] = (header_size >> 16) & 0xFF;
+               pa0_buff[4] = (header_size >> 8) & 0xFF;
+               pa0_buff[5] = header_size & 0xFF;
+       }
+
+       return len;
+}
+
+static int set_msg_len(u8 *block, unsigned int msglen, unsigned int csize)
+{
+       __be32 data;
+
+       memset(block, 0, csize);
+       block += csize;
+
+       if (csize >= 4)
+               csize = 4;
+       else if (msglen > (1 << (8 * csize)))
+               return -EOVERFLOW;
+
+       data = cpu_to_be32(msglen);
+       memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
+
+       return 0;
+}
+
+static int cc_ccm(struct aead_request *req, struct cc_hw_desc desc[],
+                 unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       unsigned int idx = *seq_size;
+       unsigned int cipher_flow_mode;
+       dma_addr_t mac_result;
+
+       if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
+               cipher_flow_mode = AES_to_HASH_and_DOUT;
+               mac_result = req_ctx->mac_buf_dma_addr;
+       } else { /* Encrypt */
+               cipher_flow_mode = AES_and_HASH;
+               mac_result = req_ctx->icv_dma_addr;
+       }
+
+       /* load key */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
+       set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+                    ((ctx->enc_keylen == 24) ?  CC_AES_KEY_SIZE_MAX :
+                     ctx->enc_keylen), NS_BIT);
+       set_key_size_aes(&desc[idx], ctx->enc_keylen);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       /* load ctr state */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
+       set_key_size_aes(&desc[idx], ctx->enc_keylen);
+       set_din_type(&desc[idx], DMA_DLLI,
+                    req_ctx->gen_ctx.iv_dma_addr, AES_BLOCK_SIZE, NS_BIT);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       /* load MAC key */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
+       set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+                    ((ctx->enc_keylen == 24) ?  CC_AES_KEY_SIZE_MAX :
+                     ctx->enc_keylen), NS_BIT);
+       set_key_size_aes(&desc[idx], ctx->enc_keylen);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_aes_not_hash_mode(&desc[idx]);
+       idx++;
+
+       /* load MAC state */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
+       set_key_size_aes(&desc[idx], ctx->enc_keylen);
+       set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
+                    AES_BLOCK_SIZE, NS_BIT);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_aes_not_hash_mode(&desc[idx]);
+       idx++;
+
+       /* process assoc data */
+       if (req->assoclen > 0) {
+               cc_set_assoc_desc(req, DIN_HASH, desc, &idx);
+       } else {
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_DLLI,
+                            sg_dma_address(&req_ctx->ccm_adata_sg),
+                            AES_BLOCK_SIZE + req_ctx->ccm_hdr_size, NS_BIT);
+               set_flow_mode(&desc[idx], DIN_HASH);
+               idx++;
+       }
+
+       /* process the cipher */
+       if (req_ctx->cryptlen)
+               cc_proc_cipher_desc(req, cipher_flow_mode, desc, &idx);
+
+       /* Read temporal MAC */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
+       set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, ctx->authsize,
+                     NS_BIT, 0);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+       set_aes_not_hash_mode(&desc[idx]);
+       idx++;
+
+       /* load AES-CTR state (for last MAC calculation)*/
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
+       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+       set_din_type(&desc[idx], DMA_DLLI, req_ctx->ccm_iv0_dma_addr,
+                    AES_BLOCK_SIZE, NS_BIT);
+       set_key_size_aes(&desc[idx], ctx->enc_keylen);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       hw_desc_init(&desc[idx]);
+       set_din_no_dma(&desc[idx], 0, 0xfffff0);
+       set_dout_no_dma(&desc[idx], 0, 0, 1);
+       idx++;
+
+       /* encrypt the "T" value and store MAC in mac_state */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
+                    ctx->authsize, NS_BIT);
+       set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1);
+       set_queue_last_ind(&desc[idx]);
+       set_flow_mode(&desc[idx], DIN_AES_DOUT);
+       idx++;
+
+       *seq_size = idx;
+       return 0;
+}
+
+static int config_ccm_adata(struct aead_request *req)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       //unsigned int size_of_a = 0, rem_a_size = 0;
+       unsigned int lp = req->iv[0];
+       /* Note: The code assume that req->iv[0] already contains the value
+        * of L' of RFC3610
+        */
+       unsigned int l = lp + 1;  /* This is L' of RFC 3610. */
+       unsigned int m = ctx->authsize;  /* This is M' of RFC 3610. */
+       u8 *b0 = req_ctx->ccm_config + CCM_B0_OFFSET;
+       u8 *a0 = req_ctx->ccm_config + CCM_A0_OFFSET;
+       u8 *ctr_count_0 = req_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET;
+       unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
+                                DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+                               req->cryptlen :
+                               (req->cryptlen - ctx->authsize);
+       int rc;
+
+       memset(req_ctx->mac_buf, 0, AES_BLOCK_SIZE);
+       memset(req_ctx->ccm_config, 0, AES_BLOCK_SIZE * 3);
+
+       /* taken from crypto/ccm.c */
+       /* 2 <= L <= 8, so 1 <= L' <= 7. */
+       if (l < 2 || l > 8) {
+               dev_err(dev, "illegal iv value %X\n", req->iv[0]);
+               return -EINVAL;
+       }
+       memcpy(b0, req->iv, AES_BLOCK_SIZE);
+
+       /* format control info per RFC 3610 and
+        * NIST Special Publication 800-38C
+        */
+       *b0 |= (8 * ((m - 2) / 2));
+       if (req->assoclen > 0)
+               *b0 |= 64;  /* Enable bit 6 if Adata exists. */
+
+       rc = set_msg_len(b0 + 16 - l, cryptlen, l);  /* Write L'. */
+       if (rc) {
+               dev_err(dev, "message len overflow detected");
+               return rc;
+       }
+        /* END of "taken from crypto/ccm.c" */
+
+       /* l(a) - size of associated data. */
+       req_ctx->ccm_hdr_size = format_ccm_a0(a0, req->assoclen);
+
+       memset(req->iv + 15 - req->iv[0], 0, req->iv[0] + 1);
+       req->iv[15] = 1;
+
+       memcpy(ctr_count_0, req->iv, AES_BLOCK_SIZE);
+       ctr_count_0[15] = 0;
+
+       return 0;
+}
+
+static void cc_proc_rfc4309_ccm(struct aead_request *req)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+
+       /* L' */
+       memset(areq_ctx->ctr_iv, 0, AES_BLOCK_SIZE);
+       /* For RFC 4309, always use 4 bytes for message length
+        * (at most 2^32-1 bytes).
+        */
+       areq_ctx->ctr_iv[0] = 3;
+
+       /* In RFC 4309 there is an 11-bytes nonce+IV part,
+        * that we build here.
+        */
+       memcpy(areq_ctx->ctr_iv + CCM_BLOCK_NONCE_OFFSET, ctx->ctr_nonce,
+              CCM_BLOCK_NONCE_SIZE);
+       memcpy(areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, req->iv,
+              CCM_BLOCK_IV_SIZE);
+       req->iv = areq_ctx->ctr_iv;
+       req->assoclen -= CCM_BLOCK_IV_SIZE;
+}
+
+static void cc_set_ghash_desc(struct aead_request *req,
+                             struct cc_hw_desc desc[], unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       unsigned int idx = *seq_size;
+
+       /* load key to AES*/
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
+       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+       set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+                    ctx->enc_keylen, NS_BIT);
+       set_key_size_aes(&desc[idx], ctx->enc_keylen);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       /* process one zero block to generate hkey */
+       hw_desc_init(&desc[idx]);
+       set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
+       set_dout_dlli(&desc[idx], req_ctx->hkey_dma_addr, AES_BLOCK_SIZE,
+                     NS_BIT, 0);
+       set_flow_mode(&desc[idx], DIN_AES_DOUT);
+       idx++;
+
+       /* Memory Barrier */
+       hw_desc_init(&desc[idx]);
+       set_din_no_dma(&desc[idx], 0, 0xfffff0);
+       set_dout_no_dma(&desc[idx], 0, 0, 1);
+       idx++;
+
+       /* Load GHASH subkey */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI, req_ctx->hkey_dma_addr,
+                    AES_BLOCK_SIZE, NS_BIT);
+       set_dout_no_dma(&desc[idx], 0, 0, 1);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_aes_not_hash_mode(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       idx++;
+
+       /* Configure Hash Engine to work with GHASH.
+        * Since it was not possible to extend HASH submodes to add GHASH,
+        * The following command is necessary in order to
+        * select GHASH (according to HW designers)
+        */
+       hw_desc_init(&desc[idx]);
+       set_din_no_dma(&desc[idx], 0, 0xfffff0);
+       set_dout_no_dma(&desc[idx], 0, 0, 1);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_aes_not_hash_mode(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+       set_cipher_do(&desc[idx], 1); //1=AES_SK RKEK
+       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       idx++;
+
+       /* Load GHASH initial STATE (which is 0). (for any hash there is an
+        * initial state)
+        */
+       hw_desc_init(&desc[idx]);
+       set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
+       set_dout_no_dma(&desc[idx], 0, 0, 1);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_aes_not_hash_mode(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       idx++;
+
+       *seq_size = idx;
+}
+
+static void cc_set_gctr_desc(struct aead_request *req, struct cc_hw_desc desc[],
+                            unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       unsigned int idx = *seq_size;
+
+       /* load key to AES*/
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+       set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+                    ctx->enc_keylen, NS_BIT);
+       set_key_size_aes(&desc[idx], ctx->enc_keylen);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       if (req_ctx->cryptlen && !req_ctx->plaintext_authenticate_only) {
+               /* load AES/CTR initial CTR value inc by 2*/
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+               set_key_size_aes(&desc[idx], ctx->enc_keylen);
+               set_din_type(&desc[idx], DMA_DLLI,
+                            req_ctx->gcm_iv_inc2_dma_addr, AES_BLOCK_SIZE,
+                            NS_BIT);
+               set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+               set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+               set_flow_mode(&desc[idx], S_DIN_to_AES);
+               idx++;
+       }
+
+       *seq_size = idx;
+}
+
+static void cc_proc_gcm_result(struct aead_request *req,
+                              struct cc_hw_desc desc[],
+                              unsigned int *seq_size)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       dma_addr_t mac_result;
+       unsigned int idx = *seq_size;
+
+       if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
+               mac_result = req_ctx->mac_buf_dma_addr;
+       } else { /* Encrypt */
+               mac_result = req_ctx->icv_dma_addr;
+       }
+
+       /* process(ghash) gcm_block_len */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_block_len_dma_addr,
+                    AES_BLOCK_SIZE, NS_BIT);
+       set_flow_mode(&desc[idx], DIN_HASH);
+       idx++;
+
+       /* Store GHASH state after GHASH(Associated Data + Cipher +LenBlock) */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+       set_din_no_dma(&desc[idx], 0, 0xfffff0);
+       set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, AES_BLOCK_SIZE,
+                     NS_BIT, 0);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+       set_aes_not_hash_mode(&desc[idx]);
+
+       idx++;
+
+       /* load AES/CTR initial CTR value inc by 1*/
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+       set_key_size_aes(&desc[idx], ctx->enc_keylen);
+       set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_iv_inc1_dma_addr,
+                    AES_BLOCK_SIZE, NS_BIT);
+       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       /* Memory Barrier */
+       hw_desc_init(&desc[idx]);
+       set_din_no_dma(&desc[idx], 0, 0xfffff0);
+       set_dout_no_dma(&desc[idx], 0, 0, 1);
+       idx++;
+
+       /* process GCTR on stored GHASH and store MAC in mac_state*/
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+       set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
+                    AES_BLOCK_SIZE, NS_BIT);
+       set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1);
+       set_queue_last_ind(&desc[idx]);
+       set_flow_mode(&desc[idx], DIN_AES_DOUT);
+       idx++;
+
+       *seq_size = idx;
+}
+
+static int cc_gcm(struct aead_request *req, struct cc_hw_desc desc[],
+                 unsigned int *seq_size)
+{
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       unsigned int cipher_flow_mode;
+
+       if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
+               cipher_flow_mode = AES_and_HASH;
+       } else { /* Encrypt */
+               cipher_flow_mode = AES_to_HASH_and_DOUT;
+       }
+
+       //in RFC4543 no data to encrypt. just copy data from src to dest.
+       if (req_ctx->plaintext_authenticate_only) {
+               cc_proc_cipher_desc(req, BYPASS, desc, seq_size);
+               cc_set_ghash_desc(req, desc, seq_size);
+               /* process(ghash) assoc data */
+               cc_set_assoc_desc(req, DIN_HASH, desc, seq_size);
+               cc_set_gctr_desc(req, desc, seq_size);
+               cc_proc_gcm_result(req, desc, seq_size);
+               return 0;
+       }
+
+       // for gcm and rfc4106.
+       cc_set_ghash_desc(req, desc, seq_size);
+       /* process(ghash) assoc data */
+       if (req->assoclen > 0)
+               cc_set_assoc_desc(req, DIN_HASH, desc, seq_size);
+       cc_set_gctr_desc(req, desc, seq_size);
+       /* process(gctr+ghash) */
+       if (req_ctx->cryptlen)
+               cc_proc_cipher_desc(req, cipher_flow_mode, desc, seq_size);
+       cc_proc_gcm_result(req, desc, seq_size);
+
+       return 0;
+}
+
+static int config_gcm_context(struct aead_request *req)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
+                                DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+                               req->cryptlen :
+                               (req->cryptlen - ctx->authsize);
+       __be32 counter = cpu_to_be32(2);
+
+       dev_dbg(dev, "%s() cryptlen = %d, req->assoclen = %d ctx->authsize = %d\n",
+               __func__, cryptlen, req->assoclen, ctx->authsize);
+
+       memset(req_ctx->hkey, 0, AES_BLOCK_SIZE);
+
+       memset(req_ctx->mac_buf, 0, AES_BLOCK_SIZE);
+
+       memcpy(req->iv + 12, &counter, 4);
+       memcpy(req_ctx->gcm_iv_inc2, req->iv, 16);
+
+       counter = cpu_to_be32(1);
+       memcpy(req->iv + 12, &counter, 4);
+       memcpy(req_ctx->gcm_iv_inc1, req->iv, 16);
+
+       if (!req_ctx->plaintext_authenticate_only) {
+               __be64 temp64;
+
+               temp64 = cpu_to_be64(req->assoclen * 8);
+               memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64));
+               temp64 = cpu_to_be64(cryptlen * 8);
+               memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8);
+       } else {
+               /* rfc4543=>  all data(AAD,IV,Plain) are considered additional
+                * data that is nothing is encrypted.
+                */
+               __be64 temp64;
+
+               temp64 = cpu_to_be64((req->assoclen + GCM_BLOCK_RFC4_IV_SIZE +
+                                     cryptlen) * 8);
+               memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64));
+               temp64 = 0;
+               memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8);
+       }
+
+       return 0;
+}
+
+static void cc_proc_rfc4_gcm(struct aead_request *req)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+
+       memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_NONCE_OFFSET,
+              ctx->ctr_nonce, GCM_BLOCK_RFC4_NONCE_SIZE);
+       memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_IV_OFFSET, req->iv,
+              GCM_BLOCK_RFC4_IV_SIZE);
+       req->iv = areq_ctx->ctr_iv;
+       req->assoclen -= GCM_BLOCK_RFC4_IV_SIZE;
+}
+
+static int cc_proc_aead(struct aead_request *req,
+                       enum drv_crypto_direction direct)
+{
+       int rc = 0;
+       int seq_len = 0;
+       struct cc_hw_desc desc[MAX_AEAD_PROCESS_SEQ];
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       struct cc_crypto_req cc_req = {};
+
+       dev_dbg(dev, "%s context=%p req=%p iv=%p src=%p src_ofs=%d dst=%p dst_ofs=%d cryptolen=%d\n",
+               ((direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Enc" : "Dec"),
+               ctx, req, req->iv, sg_virt(req->src), req->src->offset,
+               sg_virt(req->dst), req->dst->offset, req->cryptlen);
+
+       /* STAT_PHASE_0: Init and sanity checks */
+
+       /* Check data length according to mode */
+       if (validate_data_size(ctx, direct, req)) {
+               dev_err(dev, "Unsupported crypt/assoc len %d/%d.\n",
+                       req->cryptlen, req->assoclen);
+               crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_BLOCK_LEN);
+               return -EINVAL;
+       }
+
+       /* Setup DX request structure */
+       cc_req.user_cb = (void *)cc_aead_complete;
+       cc_req.user_arg = (void *)req;
+
+       /* Setup request context */
+       areq_ctx->gen_ctx.op_type = direct;
+       areq_ctx->req_authsize = ctx->authsize;
+       areq_ctx->cipher_mode = ctx->cipher_mode;
+
+       /* STAT_PHASE_1: Map buffers */
+
+       if (ctx->cipher_mode == DRV_CIPHER_CTR) {
+               /* Build CTR IV - Copy nonce from last 4 bytes in
+                * CTR key to first 4 bytes in CTR IV
+                */
+               memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce,
+                      CTR_RFC3686_NONCE_SIZE);
+               if (!areq_ctx->backup_giv) /*User none-generated IV*/
+                       memcpy(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE,
+                              req->iv, CTR_RFC3686_IV_SIZE);
+               /* Initialize counter portion of counter block */
+               *(__be32 *)(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE +
+                           CTR_RFC3686_IV_SIZE) = cpu_to_be32(1);
+
+               /* Replace with counter iv */
+               req->iv = areq_ctx->ctr_iv;
+               areq_ctx->hw_iv_size = CTR_RFC3686_BLOCK_SIZE;
+       } else if ((ctx->cipher_mode == DRV_CIPHER_CCM) ||
+                  (ctx->cipher_mode == DRV_CIPHER_GCTR)) {
+               areq_ctx->hw_iv_size = AES_BLOCK_SIZE;
+               if (areq_ctx->ctr_iv != req->iv) {
+                       memcpy(areq_ctx->ctr_iv, req->iv,
+                              crypto_aead_ivsize(tfm));
+                       req->iv = areq_ctx->ctr_iv;
+               }
+       }  else {
+               areq_ctx->hw_iv_size = crypto_aead_ivsize(tfm);
+       }
+
+       if (ctx->cipher_mode == DRV_CIPHER_CCM) {
+               rc = config_ccm_adata(req);
+               if (rc) {
+                       dev_dbg(dev, "config_ccm_adata() returned with a failure %d!",
+                               rc);
+                       goto exit;
+               }
+       } else {
+               areq_ctx->ccm_hdr_size = ccm_header_size_null;
+       }
+
+       if (ctx->cipher_mode == DRV_CIPHER_GCTR) {
+               rc = config_gcm_context(req);
+               if (rc) {
+                       dev_dbg(dev, "config_gcm_context() returned with a failure %d!",
+                               rc);
+                       goto exit;
+               }
+       }
+
+       rc = cc_map_aead_request(ctx->drvdata, req);
+       if (rc) {
+               dev_err(dev, "map_request() failed\n");
+               goto exit;
+       }
+
+       /* do we need to generate IV? */
+       if (areq_ctx->backup_giv) {
+               /* set the DMA mapped IV address*/
+               if (ctx->cipher_mode == DRV_CIPHER_CTR) {
+                       cc_req.ivgen_dma_addr[0] =
+                               areq_ctx->gen_ctx.iv_dma_addr +
+                               CTR_RFC3686_NONCE_SIZE;
+                       cc_req.ivgen_dma_addr_len = 1;
+               } else if (ctx->cipher_mode == DRV_CIPHER_CCM) {
+                       /* In ccm, the IV needs to exist both inside B0 and
+                        * inside the counter.It is also copied to iv_dma_addr
+                        * for other reasons (like returning it to the user).
+                        * So, using 3 (identical) IV outputs.
+                        */
+                       cc_req.ivgen_dma_addr[0] =
+                               areq_ctx->gen_ctx.iv_dma_addr +
+                               CCM_BLOCK_IV_OFFSET;
+                       cc_req.ivgen_dma_addr[1] =
+                               sg_dma_address(&areq_ctx->ccm_adata_sg) +
+                               CCM_B0_OFFSET + CCM_BLOCK_IV_OFFSET;
+                       cc_req.ivgen_dma_addr[2] =
+                               sg_dma_address(&areq_ctx->ccm_adata_sg) +
+                               CCM_CTR_COUNT_0_OFFSET + CCM_BLOCK_IV_OFFSET;
+                       cc_req.ivgen_dma_addr_len = 3;
+               } else {
+                       cc_req.ivgen_dma_addr[0] =
+                               areq_ctx->gen_ctx.iv_dma_addr;
+                       cc_req.ivgen_dma_addr_len = 1;
+               }
+
+               /* set the IV size (8/16 B long)*/
+               cc_req.ivgen_size = crypto_aead_ivsize(tfm);
+       }
+
+       /* STAT_PHASE_2: Create sequence */
+
+       /* Load MLLI tables to SRAM if necessary */
+       cc_mlli_to_sram(req, desc, &seq_len);
+
+       /*TODO: move seq len by reference */
+       switch (ctx->auth_mode) {
+       case DRV_HASH_SHA1:
+       case DRV_HASH_SHA256:
+               cc_hmac_authenc(req, desc, &seq_len);
+               break;
+       case DRV_HASH_XCBC_MAC:
+               cc_xcbc_authenc(req, desc, &seq_len);
+               break;
+       case DRV_HASH_NULL:
+               if (ctx->cipher_mode == DRV_CIPHER_CCM)
+                       cc_ccm(req, desc, &seq_len);
+               if (ctx->cipher_mode == DRV_CIPHER_GCTR)
+                       cc_gcm(req, desc, &seq_len);
+               break;
+       default:
+               dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode);
+               cc_unmap_aead_request(dev, req);
+               rc = -ENOTSUPP;
+               goto exit;
+       }
+
+       /* STAT_PHASE_3: Lock HW and push sequence */
+
+       rc = cc_send_request(ctx->drvdata, &cc_req, desc, seq_len, &req->base);
+
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               cc_unmap_aead_request(dev, req);
+       }
+
+exit:
+       return rc;
+}
+
+static int cc_aead_encrypt(struct aead_request *req)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       int rc;
+
+       /* No generated IV required */
+       areq_ctx->backup_iv = req->iv;
+       areq_ctx->backup_giv = NULL;
+       areq_ctx->is_gcm4543 = false;
+
+       areq_ctx->plaintext_authenticate_only = false;
+
+       rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
+       if (rc != -EINPROGRESS && rc != -EBUSY)
+               req->iv = areq_ctx->backup_iv;
+
+       return rc;
+}
+
+static int cc_rfc4309_ccm_encrypt(struct aead_request *req)
+{
+       /* Very similar to cc_aead_encrypt() above. */
+
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       int rc = -EINVAL;
+
+       if (!valid_assoclen(req)) {
+               dev_err(dev, "invalid Assoclen:%u\n", req->assoclen);
+               goto out;
+       }
+
+       /* No generated IV required */
+       areq_ctx->backup_iv = req->iv;
+       areq_ctx->backup_giv = NULL;
+       areq_ctx->is_gcm4543 = true;
+
+       cc_proc_rfc4309_ccm(req);
+
+       rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
+       if (rc != -EINPROGRESS && rc != -EBUSY)
+               req->iv = areq_ctx->backup_iv;
+out:
+       return rc;
+}
+
+static int cc_aead_decrypt(struct aead_request *req)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       int rc;
+
+       /* No generated IV required */
+       areq_ctx->backup_iv = req->iv;
+       areq_ctx->backup_giv = NULL;
+       areq_ctx->is_gcm4543 = false;
+
+       areq_ctx->plaintext_authenticate_only = false;
+
+       rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT);
+       if (rc != -EINPROGRESS && rc != -EBUSY)
+               req->iv = areq_ctx->backup_iv;
+
+       return rc;
+}
+
+static int cc_rfc4309_ccm_decrypt(struct aead_request *req)
+{
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       int rc = -EINVAL;
+
+       if (!valid_assoclen(req)) {
+               dev_err(dev, "invalid Assoclen:%u\n", req->assoclen);
+               goto out;
+       }
+
+       /* No generated IV required */
+       areq_ctx->backup_iv = req->iv;
+       areq_ctx->backup_giv = NULL;
+
+       areq_ctx->is_gcm4543 = true;
+       cc_proc_rfc4309_ccm(req);
+
+       rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT);
+       if (rc != -EINPROGRESS && rc != -EBUSY)
+               req->iv = areq_ctx->backup_iv;
+
+out:
+       return rc;
+}
+
+static int cc_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
+                                unsigned int keylen)
+{
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "%s()  keylen %d, key %p\n", __func__, keylen, key);
+
+       if (keylen < 4)
+               return -EINVAL;
+
+       keylen -= 4;
+       memcpy(ctx->ctr_nonce, key + keylen, 4);
+
+       return cc_aead_setkey(tfm, key, keylen);
+}
+
+static int cc_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
+                                unsigned int keylen)
+{
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "%s()  keylen %d, key %p\n", __func__, keylen, key);
+
+       if (keylen < 4)
+               return -EINVAL;
+
+       keylen -= 4;
+       memcpy(ctx->ctr_nonce, key + keylen, 4);
+
+       return cc_aead_setkey(tfm, key, keylen);
+}
+
+static int cc_gcm_setauthsize(struct crypto_aead *authenc,
+                             unsigned int authsize)
+{
+       switch (authsize) {
+       case 4:
+       case 8:
+       case 12:
+       case 13:
+       case 14:
+       case 15:
+       case 16:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return cc_aead_setauthsize(authenc, authsize);
+}
+
+static int cc_rfc4106_gcm_setauthsize(struct crypto_aead *authenc,
+                                     unsigned int authsize)
+{
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "authsize %d\n", authsize);
+
+       switch (authsize) {
+       case 8:
+       case 12:
+       case 16:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return cc_aead_setauthsize(authenc, authsize);
+}
+
+static int cc_rfc4543_gcm_setauthsize(struct crypto_aead *authenc,
+                                     unsigned int authsize)
+{
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "authsize %d\n", authsize);
+
+       if (authsize != 16)
+               return -EINVAL;
+
+       return cc_aead_setauthsize(authenc, authsize);
+}
+
+static int cc_rfc4106_gcm_encrypt(struct aead_request *req)
+{
+       /* Very similar to cc_aead_encrypt() above. */
+
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       int rc = -EINVAL;
+
+       if (!valid_assoclen(req)) {
+               dev_err(dev, "invalid Assoclen:%u\n", req->assoclen);
+               goto out;
+       }
+
+       /* No generated IV required */
+       areq_ctx->backup_iv = req->iv;
+       areq_ctx->backup_giv = NULL;
+
+       areq_ctx->plaintext_authenticate_only = false;
+
+       cc_proc_rfc4_gcm(req);
+       areq_ctx->is_gcm4543 = true;
+
+       rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
+       if (rc != -EINPROGRESS && rc != -EBUSY)
+               req->iv = areq_ctx->backup_iv;
+out:
+       return rc;
+}
+
+static int cc_rfc4543_gcm_encrypt(struct aead_request *req)
+{
+       /* Very similar to cc_aead_encrypt() above. */
+
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       int rc;
+
+       //plaintext is not encryped with rfc4543
+       areq_ctx->plaintext_authenticate_only = true;
+
+       /* No generated IV required */
+       areq_ctx->backup_iv = req->iv;
+       areq_ctx->backup_giv = NULL;
+
+       cc_proc_rfc4_gcm(req);
+       areq_ctx->is_gcm4543 = true;
+
+       rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
+       if (rc != -EINPROGRESS && rc != -EBUSY)
+               req->iv = areq_ctx->backup_iv;
+
+       return rc;
+}
+
+static int cc_rfc4106_gcm_decrypt(struct aead_request *req)
+{
+       /* Very similar to cc_aead_decrypt() above. */
+
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       int rc = -EINVAL;
+
+       if (!valid_assoclen(req)) {
+               dev_err(dev, "invalid Assoclen:%u\n", req->assoclen);
+               goto out;
+       }
+
+       /* No generated IV required */
+       areq_ctx->backup_iv = req->iv;
+       areq_ctx->backup_giv = NULL;
+
+       areq_ctx->plaintext_authenticate_only = false;
+
+       cc_proc_rfc4_gcm(req);
+       areq_ctx->is_gcm4543 = true;
+
+       rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT);
+       if (rc != -EINPROGRESS && rc != -EBUSY)
+               req->iv = areq_ctx->backup_iv;
+out:
+       return rc;
+}
+
+static int cc_rfc4543_gcm_decrypt(struct aead_request *req)
+{
+       /* Very similar to cc_aead_decrypt() above. */
+
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       int rc;
+
+       //plaintext is not decryped with rfc4543
+       areq_ctx->plaintext_authenticate_only = true;
+
+       /* No generated IV required */
+       areq_ctx->backup_iv = req->iv;
+       areq_ctx->backup_giv = NULL;
+
+       cc_proc_rfc4_gcm(req);
+       areq_ctx->is_gcm4543 = true;
+
+       rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT);
+       if (rc != -EINPROGRESS && rc != -EBUSY)
+               req->iv = areq_ctx->backup_iv;
+
+       return rc;
+}
+
+/* DX Block aead alg */
+static struct cc_alg_template aead_algs[] = {
+       {
+               .name = "authenc(hmac(sha1),cbc(aes))",
+               .driver_name = "authenc-hmac-sha1-cbc-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_aead_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CBC,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_SHA1,
+       },
+       {
+               .name = "authenc(hmac(sha1),cbc(des3_ede))",
+               .driver_name = "authenc-hmac-sha1-cbc-des3-dx",
+               .blocksize = DES3_EDE_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_aead_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CBC,
+               .flow_mode = S_DIN_to_DES,
+               .auth_mode = DRV_HASH_SHA1,
+       },
+       {
+               .name = "authenc(hmac(sha256),cbc(aes))",
+               .driver_name = "authenc-hmac-sha256-cbc-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_aead_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CBC,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_SHA256,
+       },
+       {
+               .name = "authenc(hmac(sha256),cbc(des3_ede))",
+               .driver_name = "authenc-hmac-sha256-cbc-des3-dx",
+               .blocksize = DES3_EDE_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_aead_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CBC,
+               .flow_mode = S_DIN_to_DES,
+               .auth_mode = DRV_HASH_SHA256,
+       },
+       {
+               .name = "authenc(xcbc(aes),cbc(aes))",
+               .driver_name = "authenc-xcbc-aes-cbc-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_aead_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CBC,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_XCBC_MAC,
+       },
+       {
+               .name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
+               .driver_name = "authenc-hmac-sha1-rfc3686-ctr-aes-dx",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_aead_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = CTR_RFC3686_IV_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CTR,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_SHA1,
+       },
+       {
+               .name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
+               .driver_name = "authenc-hmac-sha256-rfc3686-ctr-aes-dx",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_aead_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = CTR_RFC3686_IV_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CTR,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_SHA256,
+       },
+       {
+               .name = "authenc(xcbc(aes),rfc3686(ctr(aes)))",
+               .driver_name = "authenc-xcbc-aes-rfc3686-ctr-aes-dx",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_aead_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = CTR_RFC3686_IV_SIZE,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CTR,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_XCBC_MAC,
+       },
+       {
+               .name = "ccm(aes)",
+               .driver_name = "ccm-aes-dx",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_ccm_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CCM,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_NULL,
+       },
+       {
+               .name = "rfc4309(ccm(aes))",
+               .driver_name = "rfc4309-ccm-aes-dx",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_rfc4309_ccm_setkey,
+                       .setauthsize = cc_rfc4309_ccm_setauthsize,
+                       .encrypt = cc_rfc4309_ccm_encrypt,
+                       .decrypt = cc_rfc4309_ccm_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = CCM_BLOCK_IV_SIZE,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CCM,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_NULL,
+       },
+       {
+               .name = "gcm(aes)",
+               .driver_name = "gcm-aes-dx",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_aead_setkey,
+                       .setauthsize = cc_gcm_setauthsize,
+                       .encrypt = cc_aead_encrypt,
+                       .decrypt = cc_aead_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = 12,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_GCTR,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_NULL,
+       },
+       {
+               .name = "rfc4106(gcm(aes))",
+               .driver_name = "rfc4106-gcm-aes-dx",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_rfc4106_gcm_setkey,
+                       .setauthsize = cc_rfc4106_gcm_setauthsize,
+                       .encrypt = cc_rfc4106_gcm_encrypt,
+                       .decrypt = cc_rfc4106_gcm_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = GCM_BLOCK_RFC4_IV_SIZE,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_GCTR,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_NULL,
+       },
+       {
+               .name = "rfc4543(gcm(aes))",
+               .driver_name = "rfc4543-gcm-aes-dx",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = cc_rfc4543_gcm_setkey,
+                       .setauthsize = cc_rfc4543_gcm_setauthsize,
+                       .encrypt = cc_rfc4543_gcm_encrypt,
+                       .decrypt = cc_rfc4543_gcm_decrypt,
+                       .init = cc_aead_init,
+                       .exit = cc_aead_exit,
+                       .ivsize = GCM_BLOCK_RFC4_IV_SIZE,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_GCTR,
+               .flow_mode = S_DIN_to_AES,
+               .auth_mode = DRV_HASH_NULL,
+       },
+};
+
+static struct cc_crypto_alg *cc_create_aead_alg(struct cc_alg_template *tmpl,
+                                               struct device *dev)
+{
+       struct cc_crypto_alg *t_alg;
+       struct aead_alg *alg;
+
+       t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
+       if (!t_alg)
+               return ERR_PTR(-ENOMEM);
+
+       alg = &tmpl->template_aead;
+
+       snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", tmpl->name);
+       snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+                tmpl->driver_name);
+       alg->base.cra_module = THIS_MODULE;
+       alg->base.cra_priority = CC_CRA_PRIO;
+
+       alg->base.cra_ctxsize = sizeof(struct cc_aead_ctx);
+       alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
+                        tmpl->type;
+       alg->init = cc_aead_init;
+       alg->exit = cc_aead_exit;
+
+       t_alg->aead_alg = *alg;
+
+       t_alg->cipher_mode = tmpl->cipher_mode;
+       t_alg->flow_mode = tmpl->flow_mode;
+       t_alg->auth_mode = tmpl->auth_mode;
+
+       return t_alg;
+}
+
+int cc_aead_free(struct cc_drvdata *drvdata)
+{
+       struct cc_crypto_alg *t_alg, *n;
+       struct cc_aead_handle *aead_handle =
+               (struct cc_aead_handle *)drvdata->aead_handle;
+
+       if (aead_handle) {
+               /* Remove registered algs */
+               list_for_each_entry_safe(t_alg, n, &aead_handle->aead_list,
+                                        entry) {
+                       crypto_unregister_aead(&t_alg->aead_alg);
+                       list_del(&t_alg->entry);
+                       kfree(t_alg);
+               }
+               kfree(aead_handle);
+               drvdata->aead_handle = NULL;
+       }
+
+       return 0;
+}
+
+int cc_aead_alloc(struct cc_drvdata *drvdata)
+{
+       struct cc_aead_handle *aead_handle;
+       struct cc_crypto_alg *t_alg;
+       int rc = -ENOMEM;
+       int alg;
+       struct device *dev = drvdata_to_dev(drvdata);
+
+       aead_handle = kmalloc(sizeof(*aead_handle), GFP_KERNEL);
+       if (!aead_handle) {
+               rc = -ENOMEM;
+               goto fail0;
+       }
+
+       INIT_LIST_HEAD(&aead_handle->aead_list);
+       drvdata->aead_handle = aead_handle;
+
+       aead_handle->sram_workspace_addr = cc_sram_alloc(drvdata,
+                                                        MAX_HMAC_DIGEST_SIZE);
+
+       if (aead_handle->sram_workspace_addr == NULL_SRAM_ADDR) {
+               dev_err(dev, "SRAM pool exhausted\n");
+               rc = -ENOMEM;
+               goto fail1;
+       }
+
+       /* Linux crypto */
+       for (alg = 0; alg < ARRAY_SIZE(aead_algs); alg++) {
+               t_alg = cc_create_aead_alg(&aead_algs[alg], dev);
+               if (IS_ERR(t_alg)) {
+                       rc = PTR_ERR(t_alg);
+                       dev_err(dev, "%s alg allocation failed\n",
+                               aead_algs[alg].driver_name);
+                       goto fail1;
+               }
+               t_alg->drvdata = drvdata;
+               rc = crypto_register_aead(&t_alg->aead_alg);
+               if (rc) {
+                       dev_err(dev, "%s alg registration failed\n",
+                               t_alg->aead_alg.base.cra_driver_name);
+                       goto fail2;
+               } else {
+                       list_add_tail(&t_alg->entry, &aead_handle->aead_list);
+                       dev_dbg(dev, "Registered %s\n",
+                               t_alg->aead_alg.base.cra_driver_name);
+               }
+       }
+
+       return 0;
+
+fail2:
+       kfree(t_alg);
+fail1:
+       cc_aead_free(drvdata);
+fail0:
+       return rc;
+}
diff --git a/drivers/staging/ccree/cc_aead.h b/drivers/staging/ccree/cc_aead.h
new file mode 100644 (file)
index 0000000..5edf3b3
--- /dev/null
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+/* \file cc_aead.h
+ * ARM CryptoCell AEAD Crypto API
+ */
+
+#ifndef __CC_AEAD_H__
+#define __CC_AEAD_H__
+
+#include <linux/kernel.h>
+#include <crypto/algapi.h>
+#include <crypto/ctr.h>
+
+/* mac_cmp - HW writes 8 B but all bytes hold the same value */
+#define ICV_CMP_SIZE 8
+#define CCM_CONFIG_BUF_SIZE (AES_BLOCK_SIZE * 3)
+#define MAX_MAC_SIZE SHA256_DIGEST_SIZE
+
+/* defines for AES GCM configuration buffer */
+#define GCM_BLOCK_LEN_SIZE 8
+
+#define GCM_BLOCK_RFC4_IV_OFFSET       4
+#define GCM_BLOCK_RFC4_IV_SIZE         8  /* IV size for rfc's */
+#define GCM_BLOCK_RFC4_NONCE_OFFSET    0
+#define GCM_BLOCK_RFC4_NONCE_SIZE      4
+
+/* Offsets into AES CCM configuration buffer */
+#define CCM_B0_OFFSET 0
+#define CCM_A0_OFFSET 16
+#define CCM_CTR_COUNT_0_OFFSET 32
+/* CCM B0 and CTR_COUNT constants. */
+#define CCM_BLOCK_NONCE_OFFSET 1  /* Nonce offset inside B0 and CTR_COUNT */
+#define CCM_BLOCK_NONCE_SIZE   3  /* Nonce size inside B0 and CTR_COUNT */
+#define CCM_BLOCK_IV_OFFSET    4  /* IV offset inside B0 and CTR_COUNT */
+#define CCM_BLOCK_IV_SIZE      8  /* IV size inside B0 and CTR_COUNT */
+
+enum aead_ccm_header_size {
+       ccm_header_size_null = -1,
+       ccm_header_size_zero = 0,
+       ccm_header_size_2 = 2,
+       ccm_header_size_6 = 6,
+       ccm_header_size_max = S32_MAX
+};
+
+struct aead_req_ctx {
+       /* Allocate cache line although only 4 bytes are needed to
+        *  assure next field falls @ cache line
+        *  Used for both: digest HW compare and CCM/GCM MAC value
+        */
+       u8 mac_buf[MAX_MAC_SIZE] ____cacheline_aligned;
+       u8 ctr_iv[AES_BLOCK_SIZE] ____cacheline_aligned;
+
+       //used in gcm
+       u8 gcm_iv_inc1[AES_BLOCK_SIZE] ____cacheline_aligned;
+       u8 gcm_iv_inc2[AES_BLOCK_SIZE] ____cacheline_aligned;
+       u8 hkey[AES_BLOCK_SIZE] ____cacheline_aligned;
+       struct {
+               u8 len_a[GCM_BLOCK_LEN_SIZE] ____cacheline_aligned;
+               u8 len_c[GCM_BLOCK_LEN_SIZE];
+       } gcm_len_block;
+
+       u8 ccm_config[CCM_CONFIG_BUF_SIZE] ____cacheline_aligned;
+       /* HW actual size input */
+       unsigned int hw_iv_size ____cacheline_aligned;
+       /* used to prevent cache coherence problem */
+       u8 backup_mac[MAX_MAC_SIZE];
+       u8 *backup_iv; /*store iv for generated IV flow*/
+       u8 *backup_giv; /*store iv for rfc3686(ctr) flow*/
+       dma_addr_t mac_buf_dma_addr; /* internal ICV DMA buffer */
+       /* buffer for internal ccm configurations */
+       dma_addr_t ccm_iv0_dma_addr;
+       dma_addr_t icv_dma_addr; /* Phys. address of ICV */
+
+       //used in gcm
+       /* buffer for internal gcm configurations */
+       dma_addr_t gcm_iv_inc1_dma_addr;
+       /* buffer for internal gcm configurations */
+       dma_addr_t gcm_iv_inc2_dma_addr;
+       dma_addr_t hkey_dma_addr; /* Phys. address of hkey */
+       dma_addr_t gcm_block_len_dma_addr; /* Phys. address of gcm block len */
+       bool is_gcm4543;
+
+       u8 *icv_virt_addr; /* Virt. address of ICV */
+       struct async_gen_req_ctx gen_ctx;
+       struct cc_mlli assoc;
+       struct cc_mlli src;
+       struct cc_mlli dst;
+       struct scatterlist *src_sgl;
+       struct scatterlist *dst_sgl;
+       unsigned int src_offset;
+       unsigned int dst_offset;
+       enum cc_req_dma_buf_type assoc_buff_type;
+       enum cc_req_dma_buf_type data_buff_type;
+       struct mlli_params mlli_params;
+       unsigned int cryptlen;
+       struct scatterlist ccm_adata_sg;
+       enum aead_ccm_header_size ccm_hdr_size;
+       unsigned int req_authsize;
+       enum drv_cipher_mode cipher_mode;
+       bool is_icv_fragmented;
+       bool is_single_pass;
+       bool plaintext_authenticate_only; //for gcm_rfc4543
+};
+
+int cc_aead_alloc(struct cc_drvdata *drvdata);
+int cc_aead_free(struct cc_drvdata *drvdata);
+
+#endif /*__CC_AEAD_H__*/
diff --git a/drivers/staging/ccree/cc_buffer_mgr.c b/drivers/staging/ccree/cc_buffer_mgr.c
new file mode 100644 (file)
index 0000000..14b2eab
--- /dev/null
@@ -0,0 +1,1651 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <crypto/internal/aead.h>
+#include <crypto/authenc.h>
+#include <crypto/scatterwalk.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
+
+#include "cc_buffer_mgr.h"
+#include "cc_lli_defs.h"
+#include "cc_cipher.h"
+#include "cc_hash.h"
+#include "cc_aead.h"
+
+enum dma_buffer_type {
+       DMA_NULL_TYPE = -1,
+       DMA_SGL_TYPE = 1,
+       DMA_BUFF_TYPE = 2,
+};
+
+struct buff_mgr_handle {
+       struct dma_pool *mlli_buffs_pool;
+};
+
+union buffer_array_entry {
+       struct scatterlist *sgl;
+       dma_addr_t buffer_dma;
+};
+
+struct buffer_array {
+       unsigned int num_of_buffers;
+       union buffer_array_entry entry[MAX_NUM_OF_BUFFERS_IN_MLLI];
+       unsigned int offset[MAX_NUM_OF_BUFFERS_IN_MLLI];
+       int nents[MAX_NUM_OF_BUFFERS_IN_MLLI];
+       int total_data_len[MAX_NUM_OF_BUFFERS_IN_MLLI];
+       enum dma_buffer_type type[MAX_NUM_OF_BUFFERS_IN_MLLI];
+       bool is_last[MAX_NUM_OF_BUFFERS_IN_MLLI];
+       u32 *mlli_nents[MAX_NUM_OF_BUFFERS_IN_MLLI];
+};
+
+static inline char *cc_dma_buf_type(enum cc_req_dma_buf_type type)
+{
+       switch (type) {
+       case CC_DMA_BUF_NULL:
+               return "BUF_NULL";
+       case CC_DMA_BUF_DLLI:
+               return "BUF_DLLI";
+       case CC_DMA_BUF_MLLI:
+               return "BUF_MLLI";
+       default:
+               return "BUF_INVALID";
+       }
+}
+
+/**
+ * cc_copy_mac() - Copy MAC to temporary location
+ *
+ * @dev: device object
+ * @req: aead request object
+ * @dir: [IN] copy from/to sgl
+ */
+static void cc_copy_mac(struct device *dev, struct aead_request *req,
+                       enum cc_sg_cpy_direct dir)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       u32 skip = req->assoclen + req->cryptlen;
+
+       if (areq_ctx->is_gcm4543)
+               skip += crypto_aead_ivsize(tfm);
+
+       cc_copy_sg_portion(dev, areq_ctx->backup_mac, req->src,
+                          (skip - areq_ctx->req_authsize), skip, dir);
+}
+
+/**
+ * cc_get_sgl_nents() - Get scatterlist number of entries.
+ *
+ * @sg_list: SG list
+ * @nbytes: [IN] Total SGL data bytes.
+ * @lbytes: [OUT] Returns the amount of bytes at the last entry
+ */
+static unsigned int cc_get_sgl_nents(struct device *dev,
+                                    struct scatterlist *sg_list,
+                                    unsigned int nbytes, u32 *lbytes,
+                                    bool *is_chained)
+{
+       unsigned int nents = 0;
+
+       while (nbytes && sg_list) {
+               if (sg_list->length) {
+                       nents++;
+                       /* get the number of bytes in the last entry */
+                       *lbytes = nbytes;
+                       nbytes -= (sg_list->length > nbytes) ?
+                                       nbytes : sg_list->length;
+                       sg_list = sg_next(sg_list);
+               } else {
+                       sg_list = (struct scatterlist *)sg_page(sg_list);
+                       if (is_chained)
+                               *is_chained = true;
+               }
+       }
+       dev_dbg(dev, "nents %d last bytes %d\n", nents, *lbytes);
+       return nents;
+}
+
+/**
+ * cc_zero_sgl() - Zero scatter scatter list data.
+ *
+ * @sgl:
+ */
+void cc_zero_sgl(struct scatterlist *sgl, u32 data_len)
+{
+       struct scatterlist *current_sg = sgl;
+       int sg_index = 0;
+
+       while (sg_index <= data_len) {
+               if (!current_sg) {
+                       /* reached the end of the sgl --> just return back */
+                       return;
+               }
+               memset(sg_virt(current_sg), 0, current_sg->length);
+               sg_index += current_sg->length;
+               current_sg = sg_next(current_sg);
+       }
+}
+
+/**
+ * cc_copy_sg_portion() - Copy scatter list data,
+ * from to_skip to end, to dest and vice versa
+ *
+ * @dest:
+ * @sg:
+ * @to_skip:
+ * @end:
+ * @direct:
+ */
+void cc_copy_sg_portion(struct device *dev, u8 *dest, struct scatterlist *sg,
+                       u32 to_skip, u32 end, enum cc_sg_cpy_direct direct)
+{
+       u32 nents, lbytes;
+
+       nents = cc_get_sgl_nents(dev, sg, end, &lbytes, NULL);
+       sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip + 1), to_skip,
+                      (direct == CC_SG_TO_BUF));
+}
+
+static int cc_render_buff_to_mlli(struct device *dev, dma_addr_t buff_dma,
+                                 u32 buff_size, u32 *curr_nents,
+                                 u32 **mlli_entry_pp)
+{
+       u32 *mlli_entry_p = *mlli_entry_pp;
+       u32 new_nents;
+
+       /* Verify there is no memory overflow*/
+       new_nents = (*curr_nents + buff_size / CC_MAX_MLLI_ENTRY_SIZE + 1);
+       if (new_nents > MAX_NUM_OF_TOTAL_MLLI_ENTRIES)
+               return -ENOMEM;
+
+       /*handle buffer longer than 64 kbytes */
+       while (buff_size > CC_MAX_MLLI_ENTRY_SIZE) {
+               cc_lli_set_addr(mlli_entry_p, buff_dma);
+               cc_lli_set_size(mlli_entry_p, CC_MAX_MLLI_ENTRY_SIZE);
+               dev_dbg(dev, "entry[%d]: single_buff=0x%08X size=%08X\n",
+                       *curr_nents, mlli_entry_p[LLI_WORD0_OFFSET],
+                       mlli_entry_p[LLI_WORD1_OFFSET]);
+               buff_dma += CC_MAX_MLLI_ENTRY_SIZE;
+               buff_size -= CC_MAX_MLLI_ENTRY_SIZE;
+               mlli_entry_p = mlli_entry_p + 2;
+               (*curr_nents)++;
+       }
+       /*Last entry */
+       cc_lli_set_addr(mlli_entry_p, buff_dma);
+       cc_lli_set_size(mlli_entry_p, buff_size);
+       dev_dbg(dev, "entry[%d]: single_buff=0x%08X size=%08X\n",
+               *curr_nents, mlli_entry_p[LLI_WORD0_OFFSET],
+               mlli_entry_p[LLI_WORD1_OFFSET]);
+       mlli_entry_p = mlli_entry_p + 2;
+       *mlli_entry_pp = mlli_entry_p;
+       (*curr_nents)++;
+       return 0;
+}
+
+static int cc_render_sg_to_mlli(struct device *dev, struct scatterlist *sgl,
+                               u32 sgl_data_len, u32 sgl_offset,
+                               u32 *curr_nents, u32 **mlli_entry_pp)
+{
+       struct scatterlist *curr_sgl = sgl;
+       u32 *mlli_entry_p = *mlli_entry_pp;
+       s32 rc = 0;
+
+       for ( ; (curr_sgl && sgl_data_len);
+             curr_sgl = sg_next(curr_sgl)) {
+               u32 entry_data_len =
+                       (sgl_data_len > sg_dma_len(curr_sgl) - sgl_offset) ?
+                               sg_dma_len(curr_sgl) - sgl_offset :
+                               sgl_data_len;
+               sgl_data_len -= entry_data_len;
+               rc = cc_render_buff_to_mlli(dev, sg_dma_address(curr_sgl) +
+                                           sgl_offset, entry_data_len,
+                                           curr_nents, &mlli_entry_p);
+               if (rc)
+                       return rc;
+
+               sgl_offset = 0;
+       }
+       *mlli_entry_pp = mlli_entry_p;
+       return 0;
+}
+
+static int cc_generate_mlli(struct device *dev, struct buffer_array *sg_data,
+                           struct mlli_params *mlli_params, gfp_t flags)
+{
+       u32 *mlli_p;
+       u32 total_nents = 0, prev_total_nents = 0;
+       int rc = 0, i;
+
+       dev_dbg(dev, "NUM of SG's = %d\n", sg_data->num_of_buffers);
+
+       /* Allocate memory from the pointed pool */
+       mlli_params->mlli_virt_addr =
+               dma_pool_alloc(mlli_params->curr_pool, flags,
+                              &mlli_params->mlli_dma_addr);
+       if (!mlli_params->mlli_virt_addr) {
+               dev_err(dev, "dma_pool_alloc() failed\n");
+               rc = -ENOMEM;
+               goto build_mlli_exit;
+       }
+       /* Point to start of MLLI */
+       mlli_p = (u32 *)mlli_params->mlli_virt_addr;
+       /* go over all SG's and link it to one MLLI table */
+       for (i = 0; i < sg_data->num_of_buffers; i++) {
+               union buffer_array_entry *entry = &sg_data->entry[i];
+               u32 tot_len = sg_data->total_data_len[i];
+               u32 offset = sg_data->offset[i];
+
+               if (sg_data->type[i] == DMA_SGL_TYPE)
+                       rc = cc_render_sg_to_mlli(dev, entry->sgl, tot_len,
+                                                 offset, &total_nents,
+                                                 &mlli_p);
+               else /*DMA_BUFF_TYPE*/
+                       rc = cc_render_buff_to_mlli(dev, entry->buffer_dma,
+                                                   tot_len, &total_nents,
+                                                   &mlli_p);
+               if (rc)
+                       return rc;
+
+               /* set last bit in the current table */
+               if (sg_data->mlli_nents[i]) {
+                       /*Calculate the current MLLI table length for the
+                        *length field in the descriptor
+                        */
+                       *sg_data->mlli_nents[i] +=
+                               (total_nents - prev_total_nents);
+                       prev_total_nents = total_nents;
+               }
+       }
+
+       /* Set MLLI size for the bypass operation */
+       mlli_params->mlli_len = (total_nents * LLI_ENTRY_BYTE_SIZE);
+
+       dev_dbg(dev, "MLLI params: virt_addr=%pK dma_addr=%pad mlli_len=0x%X\n",
+               mlli_params->mlli_virt_addr, &mlli_params->mlli_dma_addr,
+               mlli_params->mlli_len);
+
+build_mlli_exit:
+       return rc;
+}
+
+static void cc_add_buffer_entry(struct device *dev,
+                               struct buffer_array *sgl_data,
+                               dma_addr_t buffer_dma, unsigned int buffer_len,
+                               bool is_last_entry, u32 *mlli_nents)
+{
+       unsigned int index = sgl_data->num_of_buffers;
+
+       dev_dbg(dev, "index=%u single_buff=%pad buffer_len=0x%08X is_last=%d\n",
+               index, &buffer_dma, buffer_len, is_last_entry);
+       sgl_data->nents[index] = 1;
+       sgl_data->entry[index].buffer_dma = buffer_dma;
+       sgl_data->offset[index] = 0;
+       sgl_data->total_data_len[index] = buffer_len;
+       sgl_data->type[index] = DMA_BUFF_TYPE;
+       sgl_data->is_last[index] = is_last_entry;
+       sgl_data->mlli_nents[index] = mlli_nents;
+       if (sgl_data->mlli_nents[index])
+               *sgl_data->mlli_nents[index] = 0;
+       sgl_data->num_of_buffers++;
+}
+
+static void cc_add_sg_entry(struct device *dev, struct buffer_array *sgl_data,
+                           unsigned int nents, struct scatterlist *sgl,
+                           unsigned int data_len, unsigned int data_offset,
+                           bool is_last_table, u32 *mlli_nents)
+{
+       unsigned int index = sgl_data->num_of_buffers;
+
+       dev_dbg(dev, "index=%u nents=%u sgl=%pK data_len=0x%08X is_last=%d\n",
+               index, nents, sgl, data_len, is_last_table);
+       sgl_data->nents[index] = nents;
+       sgl_data->entry[index].sgl = sgl;
+       sgl_data->offset[index] = data_offset;
+       sgl_data->total_data_len[index] = data_len;
+       sgl_data->type[index] = DMA_SGL_TYPE;
+       sgl_data->is_last[index] = is_last_table;
+       sgl_data->mlli_nents[index] = mlli_nents;
+       if (sgl_data->mlli_nents[index])
+               *sgl_data->mlli_nents[index] = 0;
+       sgl_data->num_of_buffers++;
+}
+
+static int cc_dma_map_sg(struct device *dev, struct scatterlist *sg, u32 nents,
+                        enum dma_data_direction direction)
+{
+       u32 i, j;
+       struct scatterlist *l_sg = sg;
+
+       for (i = 0; i < nents; i++) {
+               if (!l_sg)
+                       break;
+               if (dma_map_sg(dev, l_sg, 1, direction) != 1) {
+                       dev_err(dev, "dma_map_page() sg buffer failed\n");
+                       goto err;
+               }
+               l_sg = sg_next(l_sg);
+       }
+       return nents;
+
+err:
+       /* Restore mapped parts */
+       for (j = 0; j < i; j++) {
+               if (!sg)
+                       break;
+               dma_unmap_sg(dev, sg, 1, direction);
+               sg = sg_next(sg);
+       }
+       return 0;
+}
+
+static int cc_map_sg(struct device *dev, struct scatterlist *sg,
+                    unsigned int nbytes, int direction, u32 *nents,
+                    u32 max_sg_nents, u32 *lbytes, u32 *mapped_nents)
+{
+       bool is_chained = false;
+
+       if (sg_is_last(sg)) {
+               /* One entry only case -set to DLLI */
+               if (dma_map_sg(dev, sg, 1, direction) != 1) {
+                       dev_err(dev, "dma_map_sg() single buffer failed\n");
+                       return -ENOMEM;
+               }
+               dev_dbg(dev, "Mapped sg: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n",
+                       &sg_dma_address(sg), sg_page(sg), sg_virt(sg),
+                       sg->offset, sg->length);
+               *lbytes = nbytes;
+               *nents = 1;
+               *mapped_nents = 1;
+       } else {  /*sg_is_last*/
+               *nents = cc_get_sgl_nents(dev, sg, nbytes, lbytes,
+                                         &is_chained);
+               if (*nents > max_sg_nents) {
+                       *nents = 0;
+                       dev_err(dev, "Too many fragments. current %d max %d\n",
+                               *nents, max_sg_nents);
+                       return -ENOMEM;
+               }
+               if (!is_chained) {
+                       /* In case of mmu the number of mapped nents might
+                        * be changed from the original sgl nents
+                        */
+                       *mapped_nents = dma_map_sg(dev, sg, *nents, direction);
+                       if (*mapped_nents == 0) {
+                               *nents = 0;
+                               dev_err(dev, "dma_map_sg() sg buffer failed\n");
+                               return -ENOMEM;
+                       }
+               } else {
+                       /*In this case the driver maps entry by entry so it
+                        * must have the same nents before and after map
+                        */
+                       *mapped_nents = cc_dma_map_sg(dev, sg, *nents,
+                                                     direction);
+                       if (*mapped_nents != *nents) {
+                               *nents = *mapped_nents;
+                               dev_err(dev, "dma_map_sg() sg buffer failed\n");
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int
+cc_set_aead_conf_buf(struct device *dev, struct aead_req_ctx *areq_ctx,
+                    u8 *config_data, struct buffer_array *sg_data,
+                    unsigned int assoclen)
+{
+       dev_dbg(dev, " handle additional data config set to DLLI\n");
+       /* create sg for the current buffer */
+       sg_init_one(&areq_ctx->ccm_adata_sg, config_data,
+                   AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size);
+       if (dma_map_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE) != 1) {
+               dev_err(dev, "dma_map_sg() config buffer failed\n");
+               return -ENOMEM;
+       }
+       dev_dbg(dev, "Mapped curr_buff: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n",
+               &sg_dma_address(&areq_ctx->ccm_adata_sg),
+               sg_page(&areq_ctx->ccm_adata_sg),
+               sg_virt(&areq_ctx->ccm_adata_sg),
+               areq_ctx->ccm_adata_sg.offset, areq_ctx->ccm_adata_sg.length);
+       /* prepare for case of MLLI */
+       if (assoclen > 0) {
+               cc_add_sg_entry(dev, sg_data, 1, &areq_ctx->ccm_adata_sg,
+                               (AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size),
+                               0, false, NULL);
+       }
+       return 0;
+}
+
+static int cc_set_hash_buf(struct device *dev, struct ahash_req_ctx *areq_ctx,
+                          u8 *curr_buff, u32 curr_buff_cnt,
+                          struct buffer_array *sg_data)
+{
+       dev_dbg(dev, " handle curr buff %x set to   DLLI\n", curr_buff_cnt);
+       /* create sg for the current buffer */
+       sg_init_one(areq_ctx->buff_sg, curr_buff, curr_buff_cnt);
+       if (dma_map_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE) != 1) {
+               dev_err(dev, "dma_map_sg() src buffer failed\n");
+               return -ENOMEM;
+       }
+       dev_dbg(dev, "Mapped curr_buff: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n",
+               &sg_dma_address(areq_ctx->buff_sg), sg_page(areq_ctx->buff_sg),
+               sg_virt(areq_ctx->buff_sg), areq_ctx->buff_sg->offset,
+               areq_ctx->buff_sg->length);
+       areq_ctx->data_dma_buf_type = CC_DMA_BUF_DLLI;
+       areq_ctx->curr_sg = areq_ctx->buff_sg;
+       areq_ctx->in_nents = 0;
+       /* prepare for case of MLLI */
+       cc_add_sg_entry(dev, sg_data, 1, areq_ctx->buff_sg, curr_buff_cnt, 0,
+                       false, NULL);
+       return 0;
+}
+
+void cc_unmap_blkcipher_request(struct device *dev, void *ctx,
+                               unsigned int ivsize, struct scatterlist *src,
+                               struct scatterlist *dst)
+{
+       struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx;
+
+       if (req_ctx->gen_ctx.iv_dma_addr) {
+               dev_dbg(dev, "Unmapped iv: iv_dma_addr=%pad iv_size=%u\n",
+                       &req_ctx->gen_ctx.iv_dma_addr, ivsize);
+               dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr,
+                                ivsize,
+                                req_ctx->is_giv ? DMA_BIDIRECTIONAL :
+                                DMA_TO_DEVICE);
+       }
+       /* Release pool */
+       if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI &&
+           req_ctx->mlli_params.mlli_virt_addr) {
+               dma_pool_free(req_ctx->mlli_params.curr_pool,
+                             req_ctx->mlli_params.mlli_virt_addr,
+                             req_ctx->mlli_params.mlli_dma_addr);
+       }
+
+       dma_unmap_sg(dev, src, req_ctx->in_nents, DMA_BIDIRECTIONAL);
+       dev_dbg(dev, "Unmapped req->src=%pK\n", sg_virt(src));
+
+       if (src != dst) {
+               dma_unmap_sg(dev, dst, req_ctx->out_nents, DMA_BIDIRECTIONAL);
+               dev_dbg(dev, "Unmapped req->dst=%pK\n", sg_virt(dst));
+       }
+}
+
+int cc_map_blkcipher_request(struct cc_drvdata *drvdata, void *ctx,
+                            unsigned int ivsize, unsigned int nbytes,
+                            void *info, struct scatterlist *src,
+                            struct scatterlist *dst, gfp_t flags)
+{
+       struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx;
+       struct mlli_params *mlli_params = &req_ctx->mlli_params;
+       struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
+       struct device *dev = drvdata_to_dev(drvdata);
+       struct buffer_array sg_data;
+       u32 dummy = 0;
+       int rc = 0;
+       u32 mapped_nents = 0;
+
+       req_ctx->dma_buf_type = CC_DMA_BUF_DLLI;
+       mlli_params->curr_pool = NULL;
+       sg_data.num_of_buffers = 0;
+
+       /* Map IV buffer */
+       if (ivsize) {
+               dump_byte_array("iv", (u8 *)info, ivsize);
+               req_ctx->gen_ctx.iv_dma_addr =
+                       dma_map_single(dev, (void *)info,
+                                      ivsize,
+                                      req_ctx->is_giv ? DMA_BIDIRECTIONAL :
+                                      DMA_TO_DEVICE);
+               if (dma_mapping_error(dev, req_ctx->gen_ctx.iv_dma_addr)) {
+                       dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n",
+                               ivsize, info);
+                       return -ENOMEM;
+               }
+               dev_dbg(dev, "Mapped iv %u B at va=%pK to dma=%pad\n",
+                       ivsize, info, &req_ctx->gen_ctx.iv_dma_addr);
+       } else {
+               req_ctx->gen_ctx.iv_dma_addr = 0;
+       }
+
+       /* Map the src SGL */
+       rc = cc_map_sg(dev, src, nbytes, DMA_BIDIRECTIONAL, &req_ctx->in_nents,
+                      LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents);
+       if (rc) {
+               rc = -ENOMEM;
+               goto ablkcipher_exit;
+       }
+       if (mapped_nents > 1)
+               req_ctx->dma_buf_type = CC_DMA_BUF_MLLI;
+
+       if (src == dst) {
+               /* Handle inplace operation */
+               if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI) {
+                       req_ctx->out_nents = 0;
+                       cc_add_sg_entry(dev, &sg_data, req_ctx->in_nents, src,
+                                       nbytes, 0, true,
+                                       &req_ctx->in_mlli_nents);
+               }
+       } else {
+               /* Map the dst sg */
+               if (cc_map_sg(dev, dst, nbytes, DMA_BIDIRECTIONAL,
+                             &req_ctx->out_nents, LLI_MAX_NUM_OF_DATA_ENTRIES,
+                             &dummy, &mapped_nents)) {
+                       rc = -ENOMEM;
+                       goto ablkcipher_exit;
+               }
+               if (mapped_nents > 1)
+                       req_ctx->dma_buf_type = CC_DMA_BUF_MLLI;
+
+               if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI) {
+                       cc_add_sg_entry(dev, &sg_data, req_ctx->in_nents, src,
+                                       nbytes, 0, true,
+                                       &req_ctx->in_mlli_nents);
+                       cc_add_sg_entry(dev, &sg_data, req_ctx->out_nents, dst,
+                                       nbytes, 0, true,
+                                       &req_ctx->out_mlli_nents);
+               }
+       }
+
+       if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI) {
+               mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
+               rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags);
+               if (rc)
+                       goto ablkcipher_exit;
+       }
+
+       dev_dbg(dev, "areq_ctx->dma_buf_type = %s\n",
+               cc_dma_buf_type(req_ctx->dma_buf_type));
+
+       return 0;
+
+ablkcipher_exit:
+       cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
+       return rc;
+}
+
+void cc_unmap_aead_request(struct device *dev, struct aead_request *req)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       unsigned int hw_iv_size = areq_ctx->hw_iv_size;
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct cc_drvdata *drvdata = dev_get_drvdata(dev);
+       u32 dummy;
+       bool chained;
+       u32 size_to_unmap = 0;
+
+       if (areq_ctx->mac_buf_dma_addr) {
+               dma_unmap_single(dev, areq_ctx->mac_buf_dma_addr,
+                                MAX_MAC_SIZE, DMA_BIDIRECTIONAL);
+       }
+
+       if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) {
+               if (areq_ctx->hkey_dma_addr) {
+                       dma_unmap_single(dev, areq_ctx->hkey_dma_addr,
+                                        AES_BLOCK_SIZE, DMA_BIDIRECTIONAL);
+               }
+
+               if (areq_ctx->gcm_block_len_dma_addr) {
+                       dma_unmap_single(dev, areq_ctx->gcm_block_len_dma_addr,
+                                        AES_BLOCK_SIZE, DMA_TO_DEVICE);
+               }
+
+               if (areq_ctx->gcm_iv_inc1_dma_addr) {
+                       dma_unmap_single(dev, areq_ctx->gcm_iv_inc1_dma_addr,
+                                        AES_BLOCK_SIZE, DMA_TO_DEVICE);
+               }
+
+               if (areq_ctx->gcm_iv_inc2_dma_addr) {
+                       dma_unmap_single(dev, areq_ctx->gcm_iv_inc2_dma_addr,
+                                        AES_BLOCK_SIZE, DMA_TO_DEVICE);
+               }
+       }
+
+       if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
+               if (areq_ctx->ccm_iv0_dma_addr) {
+                       dma_unmap_single(dev, areq_ctx->ccm_iv0_dma_addr,
+                                        AES_BLOCK_SIZE, DMA_TO_DEVICE);
+               }
+
+               dma_unmap_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE);
+       }
+       if (areq_ctx->gen_ctx.iv_dma_addr) {
+               dma_unmap_single(dev, areq_ctx->gen_ctx.iv_dma_addr,
+                                hw_iv_size, DMA_BIDIRECTIONAL);
+       }
+
+       /*In case a pool was set, a table was
+        *allocated and should be released
+        */
+       if (areq_ctx->mlli_params.curr_pool) {
+               dev_dbg(dev, "free MLLI buffer: dma=%pad virt=%pK\n",
+                       &areq_ctx->mlli_params.mlli_dma_addr,
+                       areq_ctx->mlli_params.mlli_virt_addr);
+               dma_pool_free(areq_ctx->mlli_params.curr_pool,
+                             areq_ctx->mlli_params.mlli_virt_addr,
+                             areq_ctx->mlli_params.mlli_dma_addr);
+       }
+
+       dev_dbg(dev, "Unmapping src sgl: req->src=%pK areq_ctx->src.nents=%u areq_ctx->assoc.nents=%u assoclen:%u cryptlen=%u\n",
+               sg_virt(req->src), areq_ctx->src.nents, areq_ctx->assoc.nents,
+               req->assoclen, req->cryptlen);
+       size_to_unmap = req->assoclen + req->cryptlen;
+       if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT)
+               size_to_unmap += areq_ctx->req_authsize;
+       if (areq_ctx->is_gcm4543)
+               size_to_unmap += crypto_aead_ivsize(tfm);
+
+       dma_unmap_sg(dev, req->src,
+                    cc_get_sgl_nents(dev, req->src, size_to_unmap,
+                                     &dummy, &chained),
+                    DMA_BIDIRECTIONAL);
+       if (req->src != req->dst) {
+               dev_dbg(dev, "Unmapping dst sgl: req->dst=%pK\n",
+                       sg_virt(req->dst));
+               dma_unmap_sg(dev, req->dst,
+                            cc_get_sgl_nents(dev, req->dst, size_to_unmap,
+                                             &dummy, &chained),
+                            DMA_BIDIRECTIONAL);
+       }
+       if (drvdata->coherent &&
+           areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT &&
+           req->src == req->dst) {
+               /* copy back mac from temporary location to deal with possible
+                * data memory overriding that caused by cache coherence
+                * problem.
+                */
+               cc_copy_mac(dev, req, CC_SG_FROM_BUF);
+       }
+}
+
+static int cc_get_aead_icv_nents(struct device *dev, struct scatterlist *sgl,
+                                unsigned int sgl_nents, unsigned int authsize,
+                                u32 last_entry_data_size,
+                                bool *is_icv_fragmented)
+{
+       unsigned int icv_max_size = 0;
+       unsigned int icv_required_size = authsize > last_entry_data_size ?
+                                       (authsize - last_entry_data_size) :
+                                       authsize;
+       unsigned int nents;
+       unsigned int i;
+
+       if (sgl_nents < MAX_ICV_NENTS_SUPPORTED) {
+               *is_icv_fragmented = false;
+               return 0;
+       }
+
+       for (i = 0 ; i < (sgl_nents - MAX_ICV_NENTS_SUPPORTED) ; i++) {
+               if (!sgl)
+                       break;
+               sgl = sg_next(sgl);
+       }
+
+       if (sgl)
+               icv_max_size = sgl->length;
+
+       if (last_entry_data_size > authsize) {
+               /* ICV attached to data in last entry (not fragmented!) */
+               nents = 0;
+               *is_icv_fragmented = false;
+       } else if (last_entry_data_size == authsize) {
+               /* ICV placed in whole last entry (not fragmented!) */
+               nents = 1;
+               *is_icv_fragmented = false;
+       } else if (icv_max_size > icv_required_size) {
+               nents = 1;
+               *is_icv_fragmented = true;
+       } else if (icv_max_size == icv_required_size) {
+               nents = 2;
+               *is_icv_fragmented = true;
+       } else {
+               dev_err(dev, "Unsupported num. of ICV fragments (> %d)\n",
+                       MAX_ICV_NENTS_SUPPORTED);
+               nents = -1; /*unsupported*/
+       }
+       dev_dbg(dev, "is_frag=%s icv_nents=%u\n",
+               (*is_icv_fragmented ? "true" : "false"), nents);
+
+       return nents;
+}
+
+static int cc_aead_chain_iv(struct cc_drvdata *drvdata,
+                           struct aead_request *req,
+                           struct buffer_array *sg_data,
+                           bool is_last, bool do_chain)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       unsigned int hw_iv_size = areq_ctx->hw_iv_size;
+       struct device *dev = drvdata_to_dev(drvdata);
+       int rc = 0;
+
+       if (!req->iv) {
+               areq_ctx->gen_ctx.iv_dma_addr = 0;
+               goto chain_iv_exit;
+       }
+
+       areq_ctx->gen_ctx.iv_dma_addr = dma_map_single(dev, req->iv,
+                                                      hw_iv_size,
+                                                      DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(dev, areq_ctx->gen_ctx.iv_dma_addr)) {
+               dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n",
+                       hw_iv_size, req->iv);
+               rc = -ENOMEM;
+               goto chain_iv_exit;
+       }
+
+       dev_dbg(dev, "Mapped iv %u B at va=%pK to dma=%pad\n",
+               hw_iv_size, req->iv, &areq_ctx->gen_ctx.iv_dma_addr);
+       // TODO: what about CTR?? ask Ron
+       if (do_chain && areq_ctx->plaintext_authenticate_only) {
+               struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+               unsigned int iv_size_to_authenc = crypto_aead_ivsize(tfm);
+               unsigned int iv_ofs = GCM_BLOCK_RFC4_IV_OFFSET;
+               /* Chain to given list */
+               cc_add_buffer_entry(dev, sg_data,
+                                   (areq_ctx->gen_ctx.iv_dma_addr + iv_ofs),
+                                   iv_size_to_authenc, is_last,
+                                   &areq_ctx->assoc.mlli_nents);
+               areq_ctx->assoc_buff_type = CC_DMA_BUF_MLLI;
+       }
+
+chain_iv_exit:
+       return rc;
+}
+
+static int cc_aead_chain_assoc(struct cc_drvdata *drvdata,
+                              struct aead_request *req,
+                              struct buffer_array *sg_data,
+                              bool is_last, bool do_chain)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       int rc = 0;
+       u32 mapped_nents = 0;
+       struct scatterlist *current_sg = req->src;
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       unsigned int sg_index = 0;
+       u32 size_of_assoc = req->assoclen;
+       struct device *dev = drvdata_to_dev(drvdata);
+
+       if (areq_ctx->is_gcm4543)
+               size_of_assoc += crypto_aead_ivsize(tfm);
+
+       if (!sg_data) {
+               rc = -EINVAL;
+               goto chain_assoc_exit;
+       }
+
+       if (req->assoclen == 0) {
+               areq_ctx->assoc_buff_type = CC_DMA_BUF_NULL;
+               areq_ctx->assoc.nents = 0;
+               areq_ctx->assoc.mlli_nents = 0;
+               dev_dbg(dev, "Chain assoc of length 0: buff_type=%s nents=%u\n",
+                       cc_dma_buf_type(areq_ctx->assoc_buff_type),
+                       areq_ctx->assoc.nents);
+               goto chain_assoc_exit;
+       }
+
+       //iterate over the sgl to see how many entries are for associated data
+       //it is assumed that if we reach here , the sgl is already mapped
+       sg_index = current_sg->length;
+       //the first entry in the scatter list contains all the associated data
+       if (sg_index > size_of_assoc) {
+               mapped_nents++;
+       } else {
+               while (sg_index <= size_of_assoc) {
+                       current_sg = sg_next(current_sg);
+                       /* if have reached the end of the sgl, then this is
+                        * unexpected
+                        */
+                       if (!current_sg) {
+                               dev_err(dev, "reached end of sg list. unexpected\n");
+                               return -EINVAL;
+                       }
+                       sg_index += current_sg->length;
+                       mapped_nents++;
+               }
+       }
+       if (mapped_nents > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) {
+               dev_err(dev, "Too many fragments. current %d max %d\n",
+                       mapped_nents, LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES);
+               return -ENOMEM;
+       }
+       areq_ctx->assoc.nents = mapped_nents;
+
+       /* in CCM case we have additional entry for
+        * ccm header configurations
+        */
+       if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
+               if ((mapped_nents + 1) > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) {
+                       dev_err(dev, "CCM case.Too many fragments. Current %d max %d\n",
+                               (areq_ctx->assoc.nents + 1),
+                               LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES);
+                       rc = -ENOMEM;
+                       goto chain_assoc_exit;
+               }
+       }
+
+       if (mapped_nents == 1 && areq_ctx->ccm_hdr_size == ccm_header_size_null)
+               areq_ctx->assoc_buff_type = CC_DMA_BUF_DLLI;
+       else
+               areq_ctx->assoc_buff_type = CC_DMA_BUF_MLLI;
+
+       if (do_chain || areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI) {
+               dev_dbg(dev, "Chain assoc: buff_type=%s nents=%u\n",
+                       cc_dma_buf_type(areq_ctx->assoc_buff_type),
+                       areq_ctx->assoc.nents);
+               cc_add_sg_entry(dev, sg_data, areq_ctx->assoc.nents, req->src,
+                               req->assoclen, 0, is_last,
+                               &areq_ctx->assoc.mlli_nents);
+               areq_ctx->assoc_buff_type = CC_DMA_BUF_MLLI;
+       }
+
+chain_assoc_exit:
+       return rc;
+}
+
+static void cc_prepare_aead_data_dlli(struct aead_request *req,
+                                     u32 *src_last_bytes, u32 *dst_last_bytes)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
+       unsigned int authsize = areq_ctx->req_authsize;
+
+       areq_ctx->is_icv_fragmented = false;
+       if (req->src == req->dst) {
+               /*INPLACE*/
+               areq_ctx->icv_dma_addr = sg_dma_address(areq_ctx->src_sgl) +
+                       (*src_last_bytes - authsize);
+               areq_ctx->icv_virt_addr = sg_virt(areq_ctx->src_sgl) +
+                       (*src_last_bytes - authsize);
+       } else if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
+               /*NON-INPLACE and DECRYPT*/
+               areq_ctx->icv_dma_addr = sg_dma_address(areq_ctx->src_sgl) +
+                       (*src_last_bytes - authsize);
+               areq_ctx->icv_virt_addr = sg_virt(areq_ctx->src_sgl) +
+                       (*src_last_bytes - authsize);
+       } else {
+               /*NON-INPLACE and ENCRYPT*/
+               areq_ctx->icv_dma_addr = sg_dma_address(areq_ctx->dst_sgl) +
+                       (*dst_last_bytes - authsize);
+               areq_ctx->icv_virt_addr = sg_virt(areq_ctx->dst_sgl) +
+                       (*dst_last_bytes - authsize);
+       }
+}
+
+static int cc_prepare_aead_data_mlli(struct cc_drvdata *drvdata,
+                                    struct aead_request *req,
+                                    struct buffer_array *sg_data,
+                                    u32 *src_last_bytes, u32 *dst_last_bytes,
+                                    bool is_last_table)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
+       unsigned int authsize = areq_ctx->req_authsize;
+       int rc = 0, icv_nents;
+       struct device *dev = drvdata_to_dev(drvdata);
+       struct scatterlist *sg;
+
+       if (req->src == req->dst) {
+               /*INPLACE*/
+               cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents,
+                               areq_ctx->src_sgl, areq_ctx->cryptlen,
+                               areq_ctx->src_offset, is_last_table,
+                               &areq_ctx->src.mlli_nents);
+
+               icv_nents = cc_get_aead_icv_nents(dev, areq_ctx->src_sgl,
+                                                 areq_ctx->src.nents,
+                                                 authsize, *src_last_bytes,
+                                                 &areq_ctx->is_icv_fragmented);
+               if (icv_nents < 0) {
+                       rc = -ENOTSUPP;
+                       goto prepare_data_mlli_exit;
+               }
+
+               if (areq_ctx->is_icv_fragmented) {
+                       /* Backup happens only when ICV is fragmented, ICV
+                        * verification is made by CPU compare in order to
+                        * simplify MAC verification upon request completion
+                        */
+                       if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
+                               /* In coherent platforms (e.g. ACP)
+                                * already copying ICV for any
+                                * INPLACE-DECRYPT operation, hence
+                                * we must neglect this code.
+                                */
+                               if (!drvdata->coherent)
+                                       cc_copy_mac(dev, req, CC_SG_TO_BUF);
+
+                               areq_ctx->icv_virt_addr = areq_ctx->backup_mac;
+                       } else {
+                               areq_ctx->icv_virt_addr = areq_ctx->mac_buf;
+                               areq_ctx->icv_dma_addr =
+                                       areq_ctx->mac_buf_dma_addr;
+                       }
+               } else { /* Contig. ICV */
+                       sg = &areq_ctx->src_sgl[areq_ctx->src.nents - 1];
+                       /*Should hanlde if the sg is not contig.*/
+                       areq_ctx->icv_dma_addr = sg_dma_address(sg) +
+                               (*src_last_bytes - authsize);
+                       areq_ctx->icv_virt_addr = sg_virt(sg) +
+                               (*src_last_bytes - authsize);
+               }
+
+       } else if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
+               /*NON-INPLACE and DECRYPT*/
+               cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents,
+                               areq_ctx->src_sgl, areq_ctx->cryptlen,
+                               areq_ctx->src_offset, is_last_table,
+                               &areq_ctx->src.mlli_nents);
+               cc_add_sg_entry(dev, sg_data, areq_ctx->dst.nents,
+                               areq_ctx->dst_sgl, areq_ctx->cryptlen,
+                               areq_ctx->dst_offset, is_last_table,
+                               &areq_ctx->dst.mlli_nents);
+
+               icv_nents = cc_get_aead_icv_nents(dev, areq_ctx->src_sgl,
+                                                 areq_ctx->src.nents,
+                                                 authsize, *src_last_bytes,
+                                                 &areq_ctx->is_icv_fragmented);
+               if (icv_nents < 0) {
+                       rc = -ENOTSUPP;
+                       goto prepare_data_mlli_exit;
+               }
+
+               /* Backup happens only when ICV is fragmented, ICV
+                * verification is made by CPU compare in order to simplify
+                * MAC verification upon request completion
+                */
+               if (areq_ctx->is_icv_fragmented) {
+                       cc_copy_mac(dev, req, CC_SG_TO_BUF);
+                       areq_ctx->icv_virt_addr = areq_ctx->backup_mac;
+
+               } else { /* Contig. ICV */
+                       sg = &areq_ctx->src_sgl[areq_ctx->src.nents - 1];
+                       /*Should hanlde if the sg is not contig.*/
+                       areq_ctx->icv_dma_addr = sg_dma_address(sg) +
+                               (*src_last_bytes - authsize);
+                       areq_ctx->icv_virt_addr = sg_virt(sg) +
+                               (*src_last_bytes - authsize);
+               }
+
+       } else {
+               /*NON-INPLACE and ENCRYPT*/
+               cc_add_sg_entry(dev, sg_data, areq_ctx->dst.nents,
+                               areq_ctx->dst_sgl, areq_ctx->cryptlen,
+                               areq_ctx->dst_offset, is_last_table,
+                               &areq_ctx->dst.mlli_nents);
+               cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents,
+                               areq_ctx->src_sgl, areq_ctx->cryptlen,
+                               areq_ctx->src_offset, is_last_table,
+                               &areq_ctx->src.mlli_nents);
+
+               icv_nents = cc_get_aead_icv_nents(dev, areq_ctx->dst_sgl,
+                                                 areq_ctx->dst.nents,
+                                                 authsize, *dst_last_bytes,
+                                                 &areq_ctx->is_icv_fragmented);
+               if (icv_nents < 0) {
+                       rc = -ENOTSUPP;
+                       goto prepare_data_mlli_exit;
+               }
+
+               if (!areq_ctx->is_icv_fragmented) {
+                       sg = &areq_ctx->dst_sgl[areq_ctx->dst.nents - 1];
+                       /* Contig. ICV */
+                       areq_ctx->icv_dma_addr = sg_dma_address(sg) +
+                               (*dst_last_bytes - authsize);
+                       areq_ctx->icv_virt_addr = sg_virt(sg) +
+                               (*dst_last_bytes - authsize);
+               } else {
+                       areq_ctx->icv_dma_addr = areq_ctx->mac_buf_dma_addr;
+                       areq_ctx->icv_virt_addr = areq_ctx->mac_buf;
+               }
+       }
+
+prepare_data_mlli_exit:
+       return rc;
+}
+
+static int cc_aead_chain_data(struct cc_drvdata *drvdata,
+                             struct aead_request *req,
+                             struct buffer_array *sg_data,
+                             bool is_last_table, bool do_chain)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       struct device *dev = drvdata_to_dev(drvdata);
+       enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
+       unsigned int authsize = areq_ctx->req_authsize;
+       int src_last_bytes = 0, dst_last_bytes = 0;
+       int rc = 0;
+       u32 src_mapped_nents = 0, dst_mapped_nents = 0;
+       u32 offset = 0;
+       /* non-inplace mode */
+       unsigned int size_for_map = req->assoclen + req->cryptlen;
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       u32 sg_index = 0;
+       bool chained = false;
+       bool is_gcm4543 = areq_ctx->is_gcm4543;
+       u32 size_to_skip = req->assoclen;
+
+       if (is_gcm4543)
+               size_to_skip += crypto_aead_ivsize(tfm);
+
+       offset = size_to_skip;
+
+       if (!sg_data)
+               return -EINVAL;
+
+       areq_ctx->src_sgl = req->src;
+       areq_ctx->dst_sgl = req->dst;
+
+       if (is_gcm4543)
+               size_for_map += crypto_aead_ivsize(tfm);
+
+       size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+                       authsize : 0;
+       src_mapped_nents = cc_get_sgl_nents(dev, req->src, size_for_map,
+                                           &src_last_bytes, &chained);
+       sg_index = areq_ctx->src_sgl->length;
+       //check where the data starts
+       while (sg_index <= size_to_skip) {
+               offset -= areq_ctx->src_sgl->length;
+               areq_ctx->src_sgl = sg_next(areq_ctx->src_sgl);
+               //if have reached the end of the sgl, then this is unexpected
+               if (!areq_ctx->src_sgl) {
+                       dev_err(dev, "reached end of sg list. unexpected\n");
+                       return -EINVAL;
+               }
+               sg_index += areq_ctx->src_sgl->length;
+               src_mapped_nents--;
+       }
+       if (src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) {
+               dev_err(dev, "Too many fragments. current %d max %d\n",
+                       src_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES);
+                       return -ENOMEM;
+       }
+
+       areq_ctx->src.nents = src_mapped_nents;
+
+       areq_ctx->src_offset = offset;
+
+       if (req->src != req->dst) {
+               size_for_map = req->assoclen + req->cryptlen;
+               size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+                               authsize : 0;
+               if (is_gcm4543)
+                       size_for_map += crypto_aead_ivsize(tfm);
+
+               rc = cc_map_sg(dev, req->dst, size_for_map, DMA_BIDIRECTIONAL,
+                              &areq_ctx->dst.nents,
+                              LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes,
+                              &dst_mapped_nents);
+               if (rc) {
+                       rc = -ENOMEM;
+                       goto chain_data_exit;
+               }
+       }
+
+       dst_mapped_nents = cc_get_sgl_nents(dev, req->dst, size_for_map,
+                                           &dst_last_bytes, &chained);
+       sg_index = areq_ctx->dst_sgl->length;
+       offset = size_to_skip;
+
+       //check where the data starts
+       while (sg_index <= size_to_skip) {
+               offset -= areq_ctx->dst_sgl->length;
+               areq_ctx->dst_sgl = sg_next(areq_ctx->dst_sgl);
+               //if have reached the end of the sgl, then this is unexpected
+               if (!areq_ctx->dst_sgl) {
+                       dev_err(dev, "reached end of sg list. unexpected\n");
+                       return -EINVAL;
+               }
+               sg_index += areq_ctx->dst_sgl->length;
+               dst_mapped_nents--;
+       }
+       if (dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) {
+               dev_err(dev, "Too many fragments. current %d max %d\n",
+                       dst_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES);
+               return -ENOMEM;
+       }
+       areq_ctx->dst.nents = dst_mapped_nents;
+       areq_ctx->dst_offset = offset;
+       if (src_mapped_nents > 1 ||
+           dst_mapped_nents  > 1 ||
+           do_chain) {
+               areq_ctx->data_buff_type = CC_DMA_BUF_MLLI;
+               rc = cc_prepare_aead_data_mlli(drvdata, req, sg_data,
+                                              &src_last_bytes,
+                                              &dst_last_bytes, is_last_table);
+       } else {
+               areq_ctx->data_buff_type = CC_DMA_BUF_DLLI;
+               cc_prepare_aead_data_dlli(req, &src_last_bytes,
+                                         &dst_last_bytes);
+       }
+
+chain_data_exit:
+       return rc;
+}
+
+static void cc_update_aead_mlli_nents(struct cc_drvdata *drvdata,
+                                     struct aead_request *req)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       u32 curr_mlli_size = 0;
+
+       if (areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI) {
+               areq_ctx->assoc.sram_addr = drvdata->mlli_sram_addr;
+               curr_mlli_size = areq_ctx->assoc.mlli_nents *
+                                               LLI_ENTRY_BYTE_SIZE;
+       }
+
+       if (areq_ctx->data_buff_type == CC_DMA_BUF_MLLI) {
+               /*Inplace case dst nents equal to src nents*/
+               if (req->src == req->dst) {
+                       areq_ctx->dst.mlli_nents = areq_ctx->src.mlli_nents;
+                       areq_ctx->src.sram_addr = drvdata->mlli_sram_addr +
+                                                               curr_mlli_size;
+                       areq_ctx->dst.sram_addr = areq_ctx->src.sram_addr;
+                       if (!areq_ctx->is_single_pass)
+                               areq_ctx->assoc.mlli_nents +=
+                                       areq_ctx->src.mlli_nents;
+               } else {
+                       if (areq_ctx->gen_ctx.op_type ==
+                                       DRV_CRYPTO_DIRECTION_DECRYPT) {
+                               areq_ctx->src.sram_addr =
+                                               drvdata->mlli_sram_addr +
+                                                               curr_mlli_size;
+                               areq_ctx->dst.sram_addr =
+                                               areq_ctx->src.sram_addr +
+                                               areq_ctx->src.mlli_nents *
+                                               LLI_ENTRY_BYTE_SIZE;
+                               if (!areq_ctx->is_single_pass)
+                                       areq_ctx->assoc.mlli_nents +=
+                                               areq_ctx->src.mlli_nents;
+                       } else {
+                               areq_ctx->dst.sram_addr =
+                                               drvdata->mlli_sram_addr +
+                                                               curr_mlli_size;
+                               areq_ctx->src.sram_addr =
+                                               areq_ctx->dst.sram_addr +
+                                               areq_ctx->dst.mlli_nents *
+                                               LLI_ENTRY_BYTE_SIZE;
+                               if (!areq_ctx->is_single_pass)
+                                       areq_ctx->assoc.mlli_nents +=
+                                               areq_ctx->dst.mlli_nents;
+                       }
+               }
+       }
+}
+
+int cc_map_aead_request(struct cc_drvdata *drvdata, struct aead_request *req)
+{
+       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
+       struct mlli_params *mlli_params = &areq_ctx->mlli_params;
+       struct device *dev = drvdata_to_dev(drvdata);
+       struct buffer_array sg_data;
+       unsigned int authsize = areq_ctx->req_authsize;
+       struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
+       int rc = 0;
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       bool is_gcm4543 = areq_ctx->is_gcm4543;
+       dma_addr_t dma_addr;
+       u32 mapped_nents = 0;
+       u32 dummy = 0; /*used for the assoc data fragments */
+       u32 size_to_map = 0;
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       mlli_params->curr_pool = NULL;
+       sg_data.num_of_buffers = 0;
+
+       /* copy mac to a temporary location to deal with possible
+        * data memory overriding that caused by cache coherence problem.
+        */
+       if (drvdata->coherent &&
+           areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT &&
+           req->src == req->dst)
+               cc_copy_mac(dev, req, CC_SG_TO_BUF);
+
+       /* cacluate the size for cipher remove ICV in decrypt*/
+       areq_ctx->cryptlen = (areq_ctx->gen_ctx.op_type ==
+                                DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+                               req->cryptlen :
+                               (req->cryptlen - authsize);
+
+       dma_addr = dma_map_single(dev, areq_ctx->mac_buf, MAX_MAC_SIZE,
+                                 DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(dev, dma_addr)) {
+               dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n",
+                       MAX_MAC_SIZE, areq_ctx->mac_buf);
+               rc = -ENOMEM;
+               goto aead_map_failure;
+       }
+       areq_ctx->mac_buf_dma_addr = dma_addr;
+
+       if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
+               void *addr = areq_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET;
+
+               dma_addr = dma_map_single(dev, addr, AES_BLOCK_SIZE,
+                                         DMA_TO_DEVICE);
+
+               if (dma_mapping_error(dev, dma_addr)) {
+                       dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n",
+                               AES_BLOCK_SIZE, addr);
+                       areq_ctx->ccm_iv0_dma_addr = 0;
+                       rc = -ENOMEM;
+                       goto aead_map_failure;
+               }
+               areq_ctx->ccm_iv0_dma_addr = dma_addr;
+
+               if (cc_set_aead_conf_buf(dev, areq_ctx, areq_ctx->ccm_config,
+                                        &sg_data, req->assoclen)) {
+                       rc = -ENOMEM;
+                       goto aead_map_failure;
+               }
+       }
+
+       if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) {
+               dma_addr = dma_map_single(dev, areq_ctx->hkey, AES_BLOCK_SIZE,
+                                         DMA_BIDIRECTIONAL);
+               if (dma_mapping_error(dev, dma_addr)) {
+                       dev_err(dev, "Mapping hkey %u B at va=%pK for DMA failed\n",
+                               AES_BLOCK_SIZE, areq_ctx->hkey);
+                       rc = -ENOMEM;
+                       goto aead_map_failure;
+               }
+               areq_ctx->hkey_dma_addr = dma_addr;
+
+               dma_addr = dma_map_single(dev, &areq_ctx->gcm_len_block,
+                                         AES_BLOCK_SIZE, DMA_TO_DEVICE);
+               if (dma_mapping_error(dev, dma_addr)) {
+                       dev_err(dev, "Mapping gcm_len_block %u B at va=%pK for DMA failed\n",
+                               AES_BLOCK_SIZE, &areq_ctx->gcm_len_block);
+                       rc = -ENOMEM;
+                       goto aead_map_failure;
+               }
+               areq_ctx->gcm_block_len_dma_addr = dma_addr;
+
+               dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc1,
+                                         AES_BLOCK_SIZE, DMA_TO_DEVICE);
+
+               if (dma_mapping_error(dev, dma_addr)) {
+                       dev_err(dev, "Mapping gcm_iv_inc1 %u B at va=%pK for DMA failed\n",
+                               AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc1));
+                       areq_ctx->gcm_iv_inc1_dma_addr = 0;
+                       rc = -ENOMEM;
+                       goto aead_map_failure;
+               }
+               areq_ctx->gcm_iv_inc1_dma_addr = dma_addr;
+
+               dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc2,
+                                         AES_BLOCK_SIZE, DMA_TO_DEVICE);
+
+               if (dma_mapping_error(dev, dma_addr)) {
+                       dev_err(dev, "Mapping gcm_iv_inc2 %u B at va=%pK for DMA failed\n",
+                               AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc2));
+                       areq_ctx->gcm_iv_inc2_dma_addr = 0;
+                       rc = -ENOMEM;
+                       goto aead_map_failure;
+               }
+               areq_ctx->gcm_iv_inc2_dma_addr = dma_addr;
+       }
+
+       size_to_map = req->cryptlen + req->assoclen;
+       if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT)
+               size_to_map += authsize;
+
+       if (is_gcm4543)
+               size_to_map += crypto_aead_ivsize(tfm);
+       rc = cc_map_sg(dev, req->src, size_to_map, DMA_BIDIRECTIONAL,
+                      &areq_ctx->src.nents,
+                      (LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES +
+                       LLI_MAX_NUM_OF_DATA_ENTRIES),
+                      &dummy, &mapped_nents);
+       if (rc) {
+               rc = -ENOMEM;
+               goto aead_map_failure;
+       }
+
+       if (areq_ctx->is_single_pass) {
+               /*
+                * Create MLLI table for:
+                *   (1) Assoc. data
+                *   (2) Src/Dst SGLs
+                *   Note: IV is contg. buffer (not an SGL)
+                */
+               rc = cc_aead_chain_assoc(drvdata, req, &sg_data, true, false);
+               if (rc)
+                       goto aead_map_failure;
+               rc = cc_aead_chain_iv(drvdata, req, &sg_data, true, false);
+               if (rc)
+                       goto aead_map_failure;
+               rc = cc_aead_chain_data(drvdata, req, &sg_data, true, false);
+               if (rc)
+                       goto aead_map_failure;
+       } else { /* DOUBLE-PASS flow */
+               /*
+                * Prepare MLLI table(s) in this order:
+                *
+                * If ENCRYPT/DECRYPT (inplace):
+                *   (1) MLLI table for assoc
+                *   (2) IV entry (chained right after end of assoc)
+                *   (3) MLLI for src/dst (inplace operation)
+                *
+                * If ENCRYPT (non-inplace)
+                *   (1) MLLI table for assoc
+                *   (2) IV entry (chained right after end of assoc)
+                *   (3) MLLI for dst
+                *   (4) MLLI for src
+                *
+                * If DECRYPT (non-inplace)
+                *   (1) MLLI table for assoc
+                *   (2) IV entry (chained right after end of assoc)
+                *   (3) MLLI for src
+                *   (4) MLLI for dst
+                */
+               rc = cc_aead_chain_assoc(drvdata, req, &sg_data, false, true);
+               if (rc)
+                       goto aead_map_failure;
+               rc = cc_aead_chain_iv(drvdata, req, &sg_data, false, true);
+               if (rc)
+                       goto aead_map_failure;
+               rc = cc_aead_chain_data(drvdata, req, &sg_data, true, true);
+               if (rc)
+                       goto aead_map_failure;
+       }
+
+       /* Mlli support -start building the MLLI according to the above
+        * results
+        */
+       if (areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI ||
+           areq_ctx->data_buff_type == CC_DMA_BUF_MLLI) {
+               mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
+               rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags);
+               if (rc)
+                       goto aead_map_failure;
+
+               cc_update_aead_mlli_nents(drvdata, req);
+               dev_dbg(dev, "assoc params mn %d\n",
+                       areq_ctx->assoc.mlli_nents);
+               dev_dbg(dev, "src params mn %d\n", areq_ctx->src.mlli_nents);
+               dev_dbg(dev, "dst params mn %d\n", areq_ctx->dst.mlli_nents);
+       }
+       return 0;
+
+aead_map_failure:
+       cc_unmap_aead_request(dev, req);
+       return rc;
+}
+
+int cc_map_hash_request_final(struct cc_drvdata *drvdata, void *ctx,
+                             struct scatterlist *src, unsigned int nbytes,
+                             bool do_update, gfp_t flags)
+{
+       struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
+       struct device *dev = drvdata_to_dev(drvdata);
+       u8 *curr_buff = cc_hash_buf(areq_ctx);
+       u32 *curr_buff_cnt = cc_hash_buf_cnt(areq_ctx);
+       struct mlli_params *mlli_params = &areq_ctx->mlli_params;
+       struct buffer_array sg_data;
+       struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
+       u32 dummy = 0;
+       u32 mapped_nents = 0;
+
+       dev_dbg(dev, "final params : curr_buff=%pK curr_buff_cnt=0x%X nbytes = 0x%X src=%pK curr_index=%u\n",
+               curr_buff, *curr_buff_cnt, nbytes, src, areq_ctx->buff_index);
+       /* Init the type of the dma buffer */
+       areq_ctx->data_dma_buf_type = CC_DMA_BUF_NULL;
+       mlli_params->curr_pool = NULL;
+       sg_data.num_of_buffers = 0;
+       areq_ctx->in_nents = 0;
+
+       if (nbytes == 0 && *curr_buff_cnt == 0) {
+               /* nothing to do */
+               return 0;
+       }
+
+       /*TODO: copy data in case that buffer is enough for operation */
+       /* map the previous buffer */
+       if (*curr_buff_cnt) {
+               if (cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt,
+                                   &sg_data)) {
+                       return -ENOMEM;
+               }
+       }
+
+       if (src && nbytes > 0 && do_update) {
+               if (cc_map_sg(dev, src, nbytes, DMA_TO_DEVICE,
+                             &areq_ctx->in_nents, LLI_MAX_NUM_OF_DATA_ENTRIES,
+                             &dummy, &mapped_nents)) {
+                       goto unmap_curr_buff;
+               }
+               if (src && mapped_nents == 1 &&
+                   areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) {
+                       memcpy(areq_ctx->buff_sg, src,
+                              sizeof(struct scatterlist));
+                       areq_ctx->buff_sg->length = nbytes;
+                       areq_ctx->curr_sg = areq_ctx->buff_sg;
+                       areq_ctx->data_dma_buf_type = CC_DMA_BUF_DLLI;
+               } else {
+                       areq_ctx->data_dma_buf_type = CC_DMA_BUF_MLLI;
+               }
+       }
+
+       /*build mlli */
+       if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_MLLI) {
+               mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
+               /* add the src data to the sg_data */
+               cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, nbytes,
+                               0, true, &areq_ctx->mlli_nents);
+               if (cc_generate_mlli(dev, &sg_data, mlli_params, flags))
+                       goto fail_unmap_din;
+       }
+       /* change the buffer index for the unmap function */
+       areq_ctx->buff_index = (areq_ctx->buff_index ^ 1);
+       dev_dbg(dev, "areq_ctx->data_dma_buf_type = %s\n",
+               cc_dma_buf_type(areq_ctx->data_dma_buf_type));
+       return 0;
+
+fail_unmap_din:
+       dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);
+
+unmap_curr_buff:
+       if (*curr_buff_cnt)
+               dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
+
+       return -ENOMEM;
+}
+
+int cc_map_hash_request_update(struct cc_drvdata *drvdata, void *ctx,
+                              struct scatterlist *src, unsigned int nbytes,
+                              unsigned int block_size, gfp_t flags)
+{
+       struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
+       struct device *dev = drvdata_to_dev(drvdata);
+       u8 *curr_buff = cc_hash_buf(areq_ctx);
+       u32 *curr_buff_cnt = cc_hash_buf_cnt(areq_ctx);
+       u8 *next_buff = cc_next_buf(areq_ctx);
+       u32 *next_buff_cnt = cc_next_buf_cnt(areq_ctx);
+       struct mlli_params *mlli_params = &areq_ctx->mlli_params;
+       unsigned int update_data_len;
+       u32 total_in_len = nbytes + *curr_buff_cnt;
+       struct buffer_array sg_data;
+       struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
+       unsigned int swap_index = 0;
+       u32 dummy = 0;
+       u32 mapped_nents = 0;
+
+       dev_dbg(dev, " update params : curr_buff=%pK curr_buff_cnt=0x%X nbytes=0x%X src=%pK curr_index=%u\n",
+               curr_buff, *curr_buff_cnt, nbytes, src, areq_ctx->buff_index);
+       /* Init the type of the dma buffer */
+       areq_ctx->data_dma_buf_type = CC_DMA_BUF_NULL;
+       mlli_params->curr_pool = NULL;
+       areq_ctx->curr_sg = NULL;
+       sg_data.num_of_buffers = 0;
+       areq_ctx->in_nents = 0;
+
+       if (total_in_len < block_size) {
+               dev_dbg(dev, " less than one block: curr_buff=%pK *curr_buff_cnt=0x%X copy_to=%pK\n",
+                       curr_buff, *curr_buff_cnt, &curr_buff[*curr_buff_cnt]);
+               areq_ctx->in_nents =
+                       cc_get_sgl_nents(dev, src, nbytes, &dummy, NULL);
+               sg_copy_to_buffer(src, areq_ctx->in_nents,
+                                 &curr_buff[*curr_buff_cnt], nbytes);
+               *curr_buff_cnt += nbytes;
+               return 1;
+       }
+
+       /* Calculate the residue size*/
+       *next_buff_cnt = total_in_len & (block_size - 1);
+       /* update data len */
+       update_data_len = total_in_len - *next_buff_cnt;
+
+       dev_dbg(dev, " temp length : *next_buff_cnt=0x%X update_data_len=0x%X\n",
+               *next_buff_cnt, update_data_len);
+
+       /* Copy the new residue to next buffer */
+       if (*next_buff_cnt) {
+               dev_dbg(dev, " handle residue: next buff %pK skip data %u residue %u\n",
+                       next_buff, (update_data_len - *curr_buff_cnt),
+                       *next_buff_cnt);
+               cc_copy_sg_portion(dev, next_buff, src,
+                                  (update_data_len - *curr_buff_cnt),
+                                  nbytes, CC_SG_TO_BUF);
+               /* change the buffer index for next operation */
+               swap_index = 1;
+       }
+
+       if (*curr_buff_cnt) {
+               if (cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt,
+                                   &sg_data)) {
+                       return -ENOMEM;
+               }
+               /* change the buffer index for next operation */
+               swap_index = 1;
+       }
+
+       if (update_data_len > *curr_buff_cnt) {
+               if (cc_map_sg(dev, src, (update_data_len - *curr_buff_cnt),
+                             DMA_TO_DEVICE, &areq_ctx->in_nents,
+                             LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy,
+                             &mapped_nents)) {
+                       goto unmap_curr_buff;
+               }
+               if (mapped_nents == 1 &&
+                   areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) {
+                       /* only one entry in the SG and no previous data */
+                       memcpy(areq_ctx->buff_sg, src,
+                              sizeof(struct scatterlist));
+                       areq_ctx->buff_sg->length = update_data_len;
+                       areq_ctx->data_dma_buf_type = CC_DMA_BUF_DLLI;
+                       areq_ctx->curr_sg = areq_ctx->buff_sg;
+               } else {
+                       areq_ctx->data_dma_buf_type = CC_DMA_BUF_MLLI;
+               }
+       }
+
+       if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_MLLI) {
+               mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
+               /* add the src data to the sg_data */
+               cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src,
+                               (update_data_len - *curr_buff_cnt), 0, true,
+                               &areq_ctx->mlli_nents);
+               if (cc_generate_mlli(dev, &sg_data, mlli_params, flags))
+                       goto fail_unmap_din;
+       }
+       areq_ctx->buff_index = (areq_ctx->buff_index ^ swap_index);
+
+       return 0;
+
+fail_unmap_din:
+       dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);
+
+unmap_curr_buff:
+       if (*curr_buff_cnt)
+               dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
+
+       return -ENOMEM;
+}
+
+void cc_unmap_hash_request(struct device *dev, void *ctx,
+                          struct scatterlist *src, bool do_revert)
+{
+       struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
+       u32 *prev_len = cc_next_buf_cnt(areq_ctx);
+
+       /*In case a pool was set, a table was
+        *allocated and should be released
+        */
+       if (areq_ctx->mlli_params.curr_pool) {
+               dev_dbg(dev, "free MLLI buffer: dma=%pad virt=%pK\n",
+                       &areq_ctx->mlli_params.mlli_dma_addr,
+                       areq_ctx->mlli_params.mlli_virt_addr);
+               dma_pool_free(areq_ctx->mlli_params.curr_pool,
+                             areq_ctx->mlli_params.mlli_virt_addr,
+                             areq_ctx->mlli_params.mlli_dma_addr);
+       }
+
+       if (src && areq_ctx->in_nents) {
+               dev_dbg(dev, "Unmapped sg src: virt=%pK dma=%pad len=0x%X\n",
+                       sg_virt(src), &sg_dma_address(src), sg_dma_len(src));
+               dma_unmap_sg(dev, src,
+                            areq_ctx->in_nents, DMA_TO_DEVICE);
+       }
+
+       if (*prev_len) {
+               dev_dbg(dev, "Unmapped buffer: areq_ctx->buff_sg=%pK dma=%pad len 0x%X\n",
+                       sg_virt(areq_ctx->buff_sg),
+                       &sg_dma_address(areq_ctx->buff_sg),
+                       sg_dma_len(areq_ctx->buff_sg));
+               dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
+               if (!do_revert) {
+                       /* clean the previous data length for update
+                        * operation
+                        */
+                       *prev_len = 0;
+               } else {
+                       areq_ctx->buff_index ^= 1;
+               }
+       }
+}
+
+int cc_buffer_mgr_init(struct cc_drvdata *drvdata)
+{
+       struct buff_mgr_handle *buff_mgr_handle;
+       struct device *dev = drvdata_to_dev(drvdata);
+
+       buff_mgr_handle = kmalloc(sizeof(*buff_mgr_handle), GFP_KERNEL);
+       if (!buff_mgr_handle)
+               return -ENOMEM;
+
+       drvdata->buff_mgr_handle = buff_mgr_handle;
+
+       buff_mgr_handle->mlli_buffs_pool =
+               dma_pool_create("dx_single_mlli_tables", dev,
+                               MAX_NUM_OF_TOTAL_MLLI_ENTRIES *
+                               LLI_ENTRY_BYTE_SIZE,
+                               MLLI_TABLE_MIN_ALIGNMENT, 0);
+
+       if (!buff_mgr_handle->mlli_buffs_pool)
+               goto error;
+
+       return 0;
+
+error:
+       cc_buffer_mgr_fini(drvdata);
+       return -ENOMEM;
+}
+
+int cc_buffer_mgr_fini(struct cc_drvdata *drvdata)
+{
+       struct buff_mgr_handle *buff_mgr_handle = drvdata->buff_mgr_handle;
+
+       if (buff_mgr_handle) {
+               dma_pool_destroy(buff_mgr_handle->mlli_buffs_pool);
+               kfree(drvdata->buff_mgr_handle);
+               drvdata->buff_mgr_handle = NULL;
+       }
+       return 0;
+}
diff --git a/drivers/staging/ccree/cc_buffer_mgr.h b/drivers/staging/ccree/cc_buffer_mgr.h
new file mode 100644 (file)
index 0000000..99b752a
--- /dev/null
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+/* \file cc_buffer_mgr.h
+ * Buffer Manager
+ */
+
+#ifndef __CC_BUFFER_MGR_H__
+#define __CC_BUFFER_MGR_H__
+
+#include <crypto/algapi.h>
+
+#include "cc_driver.h"
+
+enum cc_req_dma_buf_type {
+       CC_DMA_BUF_NULL = 0,
+       CC_DMA_BUF_DLLI,
+       CC_DMA_BUF_MLLI
+};
+
+enum cc_sg_cpy_direct {
+       CC_SG_TO_BUF = 0,
+       CC_SG_FROM_BUF = 1
+};
+
+struct cc_mlli {
+       cc_sram_addr_t sram_addr;
+       unsigned int nents; //sg nents
+       unsigned int mlli_nents; //mlli nents might be different than the above
+};
+
+struct mlli_params {
+       struct dma_pool *curr_pool;
+       u8 *mlli_virt_addr;
+       dma_addr_t mlli_dma_addr;
+       u32 mlli_len;
+};
+
+int cc_buffer_mgr_init(struct cc_drvdata *drvdata);
+
+int cc_buffer_mgr_fini(struct cc_drvdata *drvdata);
+
+int cc_map_blkcipher_request(struct cc_drvdata *drvdata, void *ctx,
+                            unsigned int ivsize, unsigned int nbytes,
+                            void *info, struct scatterlist *src,
+                            struct scatterlist *dst, gfp_t flags);
+
+void cc_unmap_blkcipher_request(struct device *dev, void *ctx,
+                               unsigned int ivsize,
+                               struct scatterlist *src,
+                               struct scatterlist *dst);
+
+int cc_map_aead_request(struct cc_drvdata *drvdata, struct aead_request *req);
+
+void cc_unmap_aead_request(struct device *dev, struct aead_request *req);
+
+int cc_map_hash_request_final(struct cc_drvdata *drvdata, void *ctx,
+                             struct scatterlist *src, unsigned int nbytes,
+                             bool do_update, gfp_t flags);
+
+int cc_map_hash_request_update(struct cc_drvdata *drvdata, void *ctx,
+                              struct scatterlist *src, unsigned int nbytes,
+                              unsigned int block_size, gfp_t flags);
+
+void cc_unmap_hash_request(struct device *dev, void *ctx,
+                          struct scatterlist *src, bool do_revert);
+
+void cc_copy_sg_portion(struct device *dev, u8 *dest, struct scatterlist *sg,
+                       u32 to_skip, u32 end, enum cc_sg_cpy_direct direct);
+
+void cc_zero_sgl(struct scatterlist *sgl, u32 data_len);
+
+#endif /*__BUFFER_MGR_H__*/
+
diff --git a/drivers/staging/ccree/cc_cipher.c b/drivers/staging/ccree/cc_cipher.c
new file mode 100644 (file)
index 0000000..d4ac0ff
--- /dev/null
@@ -0,0 +1,1164 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/des.h>
+#include <crypto/xts.h>
+#include <crypto/scatterwalk.h>
+
+#include "cc_driver.h"
+#include "cc_lli_defs.h"
+#include "cc_buffer_mgr.h"
+#include "cc_cipher.h"
+#include "cc_request_mgr.h"
+
+#define MAX_ABLKCIPHER_SEQ_LEN 6
+
+#define template_ablkcipher    template_u.ablkcipher
+
+#define CC_MIN_AES_XTS_SIZE 0x10
+#define CC_MAX_AES_XTS_SIZE 0x2000
+struct cc_cipher_handle {
+       struct list_head blkcipher_alg_list;
+};
+
+struct cc_user_key_info {
+       u8 *key;
+       dma_addr_t key_dma_addr;
+};
+
+struct cc_hw_key_info {
+       enum cc_hw_crypto_key key1_slot;
+       enum cc_hw_crypto_key key2_slot;
+};
+
+struct cc_cipher_ctx {
+       struct cc_drvdata *drvdata;
+       int keylen;
+       int key_round_number;
+       int cipher_mode;
+       int flow_mode;
+       unsigned int flags;
+       struct blkcipher_req_ctx *sync_ctx;
+       struct cc_user_key_info user;
+       struct cc_hw_key_info hw;
+       struct crypto_shash *shash_tfm;
+};
+
+static void cc_cipher_complete(struct device *dev, void *cc_req, int err);
+
+static int validate_keys_sizes(struct cc_cipher_ctx *ctx_p, u32 size)
+{
+       switch (ctx_p->flow_mode) {
+       case S_DIN_to_AES:
+               switch (size) {
+               case CC_AES_128_BIT_KEY_SIZE:
+               case CC_AES_192_BIT_KEY_SIZE:
+                       if (ctx_p->cipher_mode != DRV_CIPHER_XTS &&
+                           ctx_p->cipher_mode != DRV_CIPHER_ESSIV &&
+                           ctx_p->cipher_mode != DRV_CIPHER_BITLOCKER)
+                               return 0;
+                       break;
+               case CC_AES_256_BIT_KEY_SIZE:
+                       return 0;
+               case (CC_AES_192_BIT_KEY_SIZE * 2):
+               case (CC_AES_256_BIT_KEY_SIZE * 2):
+                       if (ctx_p->cipher_mode == DRV_CIPHER_XTS ||
+                           ctx_p->cipher_mode == DRV_CIPHER_ESSIV ||
+                           ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER)
+                               return 0;
+                       break;
+               default:
+                       break;
+               }
+       case S_DIN_to_DES:
+               if (size == DES3_EDE_KEY_SIZE || size == DES_KEY_SIZE)
+                       return 0;
+               break;
+       default:
+               break;
+       }
+       return -EINVAL;
+}
+
+static int validate_data_size(struct cc_cipher_ctx *ctx_p,
+                             unsigned int size)
+{
+       switch (ctx_p->flow_mode) {
+       case S_DIN_to_AES:
+               switch (ctx_p->cipher_mode) {
+               case DRV_CIPHER_XTS:
+                       if (size >= CC_MIN_AES_XTS_SIZE &&
+                           size <= CC_MAX_AES_XTS_SIZE &&
+                           IS_ALIGNED(size, AES_BLOCK_SIZE))
+                               return 0;
+                       break;
+               case DRV_CIPHER_CBC_CTS:
+                       if (size >= AES_BLOCK_SIZE)
+                               return 0;
+                       break;
+               case DRV_CIPHER_OFB:
+               case DRV_CIPHER_CTR:
+                               return 0;
+               case DRV_CIPHER_ECB:
+               case DRV_CIPHER_CBC:
+               case DRV_CIPHER_ESSIV:
+               case DRV_CIPHER_BITLOCKER:
+                       if (IS_ALIGNED(size, AES_BLOCK_SIZE))
+                               return 0;
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case S_DIN_to_DES:
+               if (IS_ALIGNED(size, DES_BLOCK_SIZE))
+                       return 0;
+               break;
+       default:
+               break;
+       }
+       return -EINVAL;
+}
+
+static unsigned int get_max_keysize(struct crypto_tfm *tfm)
+{
+       struct cc_crypto_alg *cc_alg =
+               container_of(tfm->__crt_alg, struct cc_crypto_alg, crypto_alg);
+
+       if ((cc_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+           CRYPTO_ALG_TYPE_ABLKCIPHER)
+               return cc_alg->crypto_alg.cra_ablkcipher.max_keysize;
+
+       if ((cc_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+           CRYPTO_ALG_TYPE_BLKCIPHER)
+               return cc_alg->crypto_alg.cra_blkcipher.max_keysize;
+
+       return 0;
+}
+
+static int cc_cipher_init(struct crypto_tfm *tfm)
+{
+       struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
+       struct crypto_alg *alg = tfm->__crt_alg;
+       struct cc_crypto_alg *cc_alg =
+                       container_of(alg, struct cc_crypto_alg, crypto_alg);
+       struct device *dev = drvdata_to_dev(cc_alg->drvdata);
+       int rc = 0;
+       unsigned int max_key_buf_size = get_max_keysize(tfm);
+       struct ablkcipher_tfm *ablktfm = &tfm->crt_ablkcipher;
+
+       dev_dbg(dev, "Initializing context @%p for %s\n", ctx_p,
+               crypto_tfm_alg_name(tfm));
+
+       ablktfm->reqsize = sizeof(struct blkcipher_req_ctx);
+
+       ctx_p->cipher_mode = cc_alg->cipher_mode;
+       ctx_p->flow_mode = cc_alg->flow_mode;
+       ctx_p->drvdata = cc_alg->drvdata;
+
+       /* Allocate key buffer, cache line aligned */
+       ctx_p->user.key = kmalloc(max_key_buf_size, GFP_KERNEL);
+       if (!ctx_p->user.key)
+               return -ENOMEM;
+
+       dev_dbg(dev, "Allocated key buffer in context. key=@%p\n",
+               ctx_p->user.key);
+
+       /* Map key buffer */
+       ctx_p->user.key_dma_addr = dma_map_single(dev, (void *)ctx_p->user.key,
+                                                 max_key_buf_size,
+                                                 DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, ctx_p->user.key_dma_addr)) {
+               dev_err(dev, "Mapping Key %u B at va=%pK for DMA failed\n",
+                       max_key_buf_size, ctx_p->user.key);
+               return -ENOMEM;
+       }
+       dev_dbg(dev, "Mapped key %u B at va=%pK to dma=%pad\n",
+               max_key_buf_size, ctx_p->user.key, &ctx_p->user.key_dma_addr);
+
+       if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {
+               /* Alloc hash tfm for essiv */
+               ctx_p->shash_tfm = crypto_alloc_shash("sha256-generic", 0, 0);
+               if (IS_ERR(ctx_p->shash_tfm)) {
+                       dev_err(dev, "Error allocating hash tfm for ESSIV.\n");
+                       return PTR_ERR(ctx_p->shash_tfm);
+               }
+       }
+
+       return rc;
+}
+
+static void cc_cipher_exit(struct crypto_tfm *tfm)
+{
+       struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
+       unsigned int max_key_buf_size = get_max_keysize(tfm);
+
+       dev_dbg(dev, "Clearing context @%p for %s\n",
+               crypto_tfm_ctx(tfm), crypto_tfm_alg_name(tfm));
+
+       if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {
+               /* Free hash tfm for essiv */
+               crypto_free_shash(ctx_p->shash_tfm);
+               ctx_p->shash_tfm = NULL;
+       }
+
+       /* Unmap key buffer */
+       dma_unmap_single(dev, ctx_p->user.key_dma_addr, max_key_buf_size,
+                        DMA_TO_DEVICE);
+       dev_dbg(dev, "Unmapped key buffer key_dma_addr=%pad\n",
+               &ctx_p->user.key_dma_addr);
+
+       /* Free key buffer in context */
+       kfree(ctx_p->user.key);
+       dev_dbg(dev, "Free key buffer in context. key=@%p\n", ctx_p->user.key);
+}
+
+struct tdes_keys {
+       u8      key1[DES_KEY_SIZE];
+       u8      key2[DES_KEY_SIZE];
+       u8      key3[DES_KEY_SIZE];
+};
+
+static const u8 zero_buff[] = {        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+/* The function verifies that tdes keys are not weak.*/
+static int cc_verify_3des_keys(const u8 *key, unsigned int keylen)
+{
+       struct tdes_keys *tdes_key = (struct tdes_keys *)key;
+
+       /* verify key1 != key2 and key3 != key2*/
+       if ((memcmp((u8 *)tdes_key->key1, (u8 *)tdes_key->key2,
+                   sizeof(tdes_key->key1)) == 0) ||
+           (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2,
+                   sizeof(tdes_key->key3)) == 0)) {
+               return -ENOEXEC;
+       }
+
+       return 0;
+}
+
+static enum cc_hw_crypto_key hw_key_to_cc_hw_key(int slot_num)
+{
+       switch (slot_num) {
+       case 0:
+               return KFDE0_KEY;
+       case 1:
+               return KFDE1_KEY;
+       case 2:
+               return KFDE2_KEY;
+       case 3:
+               return KFDE3_KEY;
+       }
+       return END_OF_KEYS;
+}
+
+static int cc_cipher_setkey(struct crypto_ablkcipher *atfm, const u8 *key,
+                           unsigned int keylen)
+{
+       struct crypto_tfm *tfm = crypto_ablkcipher_tfm(atfm);
+       struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
+       u32 tmp[DES_EXPKEY_WORDS];
+       unsigned int max_key_buf_size = get_max_keysize(tfm);
+
+       dev_dbg(dev, "Setting key in context @%p for %s. keylen=%u\n",
+               ctx_p, crypto_tfm_alg_name(tfm), keylen);
+       dump_byte_array("key", (u8 *)key, keylen);
+
+       /* STAT_PHASE_0: Init and sanity checks */
+
+       if (validate_keys_sizes(ctx_p, keylen)) {
+               dev_err(dev, "Unsupported key size %d.\n", keylen);
+               crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+
+       if (cc_is_hw_key(tfm)) {
+               /* setting HW key slots */
+               struct arm_hw_key_info *hki = (struct arm_hw_key_info *)key;
+
+               if (ctx_p->flow_mode != S_DIN_to_AES) {
+                       dev_err(dev, "HW key not supported for non-AES flows\n");
+                       return -EINVAL;
+               }
+
+               ctx_p->hw.key1_slot = hw_key_to_cc_hw_key(hki->hw_key1);
+               if (ctx_p->hw.key1_slot == END_OF_KEYS) {
+                       dev_err(dev, "Unsupported hw key1 number (%d)\n",
+                               hki->hw_key1);
+                       return -EINVAL;
+               }
+
+               if (ctx_p->cipher_mode == DRV_CIPHER_XTS ||
+                   ctx_p->cipher_mode == DRV_CIPHER_ESSIV ||
+                   ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER) {
+                       if (hki->hw_key1 == hki->hw_key2) {
+                               dev_err(dev, "Illegal hw key numbers (%d,%d)\n",
+                                       hki->hw_key1, hki->hw_key2);
+                               return -EINVAL;
+                       }
+                       ctx_p->hw.key2_slot =
+                               hw_key_to_cc_hw_key(hki->hw_key2);
+                       if (ctx_p->hw.key2_slot == END_OF_KEYS) {
+                               dev_err(dev, "Unsupported hw key2 number (%d)\n",
+                                       hki->hw_key2);
+                               return -EINVAL;
+                       }
+               }
+
+               ctx_p->keylen = keylen;
+               dev_dbg(dev, "cc_is_hw_key ret 0");
+
+               return 0;
+       }
+
+       // verify weak keys
+       if (ctx_p->flow_mode == S_DIN_to_DES) {
+               if (!des_ekey(tmp, key) &&
+                   (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_WEAK_KEY)) {
+                       tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
+                       dev_dbg(dev, "weak DES key");
+                       return -EINVAL;
+               }
+       }
+       if (ctx_p->cipher_mode == DRV_CIPHER_XTS &&
+           xts_check_key(tfm, key, keylen)) {
+               dev_dbg(dev, "weak XTS key");
+               return -EINVAL;
+       }
+       if (ctx_p->flow_mode == S_DIN_to_DES &&
+           keylen == DES3_EDE_KEY_SIZE &&
+           cc_verify_3des_keys(key, keylen)) {
+               dev_dbg(dev, "weak 3DES key");
+               return -EINVAL;
+       }
+
+       /* STAT_PHASE_1: Copy key to ctx */
+       dma_sync_single_for_cpu(dev, ctx_p->user.key_dma_addr,
+                               max_key_buf_size, DMA_TO_DEVICE);
+
+       memcpy(ctx_p->user.key, key, keylen);
+       if (keylen == 24)
+               memset(ctx_p->user.key + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
+
+       if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {
+               /* sha256 for key2 - use sw implementation */
+               int key_len = keylen >> 1;
+               int err;
+
+               SHASH_DESC_ON_STACK(desc, ctx_p->shash_tfm);
+
+               desc->tfm = ctx_p->shash_tfm;
+
+               err = crypto_shash_digest(desc, ctx_p->user.key, key_len,
+                                         ctx_p->user.key + key_len);
+               if (err) {
+                       dev_err(dev, "Failed to hash ESSIV key.\n");
+                       return err;
+               }
+       }
+       dma_sync_single_for_device(dev, ctx_p->user.key_dma_addr,
+                                  max_key_buf_size, DMA_TO_DEVICE);
+       ctx_p->keylen = keylen;
+
+        dev_dbg(dev, "return safely");
+       return 0;
+}
+
+static void cc_setup_cipher_desc(struct crypto_tfm *tfm,
+                                struct blkcipher_req_ctx *req_ctx,
+                                unsigned int ivsize, unsigned int nbytes,
+                                struct cc_hw_desc desc[],
+                                unsigned int *seq_size)
+{
+       struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
+       int cipher_mode = ctx_p->cipher_mode;
+       int flow_mode = ctx_p->flow_mode;
+       int direction = req_ctx->gen_ctx.op_type;
+       dma_addr_t key_dma_addr = ctx_p->user.key_dma_addr;
+       unsigned int key_len = ctx_p->keylen;
+       dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr;
+       unsigned int du_size = nbytes;
+
+       struct cc_crypto_alg *cc_alg =
+               container_of(tfm->__crt_alg, struct cc_crypto_alg, crypto_alg);
+
+       if ((cc_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) ==
+           CRYPTO_ALG_BULK_DU_512)
+               du_size = 512;
+       if ((cc_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) ==
+           CRYPTO_ALG_BULK_DU_4096)
+               du_size = 4096;
+
+       switch (cipher_mode) {
+       case DRV_CIPHER_CBC:
+       case DRV_CIPHER_CBC_CTS:
+       case DRV_CIPHER_CTR:
+       case DRV_CIPHER_OFB:
+               /* Load cipher state */
+               hw_desc_init(&desc[*seq_size]);
+               set_din_type(&desc[*seq_size], DMA_DLLI, iv_dma_addr, ivsize,
+                            NS_BIT);
+               set_cipher_config0(&desc[*seq_size], direction);
+               set_flow_mode(&desc[*seq_size], flow_mode);
+               set_cipher_mode(&desc[*seq_size], cipher_mode);
+               if (cipher_mode == DRV_CIPHER_CTR ||
+                   cipher_mode == DRV_CIPHER_OFB) {
+                       set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1);
+               } else {
+                       set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE0);
+               }
+               (*seq_size)++;
+               /*FALLTHROUGH*/
+       case DRV_CIPHER_ECB:
+               /* Load key */
+               hw_desc_init(&desc[*seq_size]);
+               set_cipher_mode(&desc[*seq_size], cipher_mode);
+               set_cipher_config0(&desc[*seq_size], direction);
+               if (flow_mode == S_DIN_to_AES) {
+                       if (cc_is_hw_key(tfm)) {
+                               set_hw_crypto_key(&desc[*seq_size],
+                                                 ctx_p->hw.key1_slot);
+                       } else {
+                               set_din_type(&desc[*seq_size], DMA_DLLI,
+                                            key_dma_addr, ((key_len == 24) ?
+                                                           AES_MAX_KEY_SIZE :
+                                                           key_len), NS_BIT);
+                       }
+                       set_key_size_aes(&desc[*seq_size], key_len);
+               } else {
+                       /*des*/
+                       set_din_type(&desc[*seq_size], DMA_DLLI, key_dma_addr,
+                                    key_len, NS_BIT);
+                       set_key_size_des(&desc[*seq_size], key_len);
+               }
+               set_flow_mode(&desc[*seq_size], flow_mode);
+               set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0);
+               (*seq_size)++;
+               break;
+       case DRV_CIPHER_XTS:
+       case DRV_CIPHER_ESSIV:
+       case DRV_CIPHER_BITLOCKER:
+               /* Load AES key */
+               hw_desc_init(&desc[*seq_size]);
+               set_cipher_mode(&desc[*seq_size], cipher_mode);
+               set_cipher_config0(&desc[*seq_size], direction);
+               if (cc_is_hw_key(tfm)) {
+                       set_hw_crypto_key(&desc[*seq_size],
+                                         ctx_p->hw.key1_slot);
+               } else {
+                       set_din_type(&desc[*seq_size], DMA_DLLI, key_dma_addr,
+                                    (key_len / 2), NS_BIT);
+               }
+               set_key_size_aes(&desc[*seq_size], (key_len / 2));
+               set_flow_mode(&desc[*seq_size], flow_mode);
+               set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0);
+               (*seq_size)++;
+
+               /* load XEX key */
+               hw_desc_init(&desc[*seq_size]);
+               set_cipher_mode(&desc[*seq_size], cipher_mode);
+               set_cipher_config0(&desc[*seq_size], direction);
+               if (cc_is_hw_key(tfm)) {
+                       set_hw_crypto_key(&desc[*seq_size],
+                                         ctx_p->hw.key2_slot);
+               } else {
+                       set_din_type(&desc[*seq_size], DMA_DLLI,
+                                    (key_dma_addr + (key_len / 2)),
+                                    (key_len / 2), NS_BIT);
+               }
+               set_xex_data_unit_size(&desc[*seq_size], du_size);
+               set_flow_mode(&desc[*seq_size], S_DIN_to_AES2);
+               set_key_size_aes(&desc[*seq_size], (key_len / 2));
+               set_setup_mode(&desc[*seq_size], SETUP_LOAD_XEX_KEY);
+               (*seq_size)++;
+
+               /* Set state */
+               hw_desc_init(&desc[*seq_size]);
+               set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1);
+               set_cipher_mode(&desc[*seq_size], cipher_mode);
+               set_cipher_config0(&desc[*seq_size], direction);
+               set_key_size_aes(&desc[*seq_size], (key_len / 2));
+               set_flow_mode(&desc[*seq_size], flow_mode);
+               set_din_type(&desc[*seq_size], DMA_DLLI, iv_dma_addr,
+                            CC_AES_BLOCK_SIZE, NS_BIT);
+               (*seq_size)++;
+               break;
+       default:
+               dev_err(dev, "Unsupported cipher mode (%d)\n", cipher_mode);
+       }
+}
+
+static void cc_setup_cipher_data(struct crypto_tfm *tfm,
+                                struct blkcipher_req_ctx *req_ctx,
+                                struct scatterlist *dst,
+                                struct scatterlist *src, unsigned int nbytes,
+                                void *areq, struct cc_hw_desc desc[],
+                                unsigned int *seq_size)
+{
+       struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
+       unsigned int flow_mode = ctx_p->flow_mode;
+
+       switch (ctx_p->flow_mode) {
+       case S_DIN_to_AES:
+               flow_mode = DIN_AES_DOUT;
+               break;
+       case S_DIN_to_DES:
+               flow_mode = DIN_DES_DOUT;
+               break;
+       default:
+               dev_err(dev, "invalid flow mode, flow_mode = %d\n", flow_mode);
+               return;
+       }
+       /* Process */
+       if (req_ctx->dma_buf_type == CC_DMA_BUF_DLLI) {
+               dev_dbg(dev, " data params addr %pad length 0x%X\n",
+                       &sg_dma_address(src), nbytes);
+               dev_dbg(dev, " data params addr %pad length 0x%X\n",
+                       &sg_dma_address(dst), nbytes);
+               hw_desc_init(&desc[*seq_size]);
+               set_din_type(&desc[*seq_size], DMA_DLLI, sg_dma_address(src),
+                            nbytes, NS_BIT);
+               set_dout_dlli(&desc[*seq_size], sg_dma_address(dst),
+                             nbytes, NS_BIT, (!areq ? 0 : 1));
+               if (areq)
+                       set_queue_last_ind(&desc[*seq_size]);
+
+               set_flow_mode(&desc[*seq_size], flow_mode);
+               (*seq_size)++;
+       } else {
+               /* bypass */
+               dev_dbg(dev, " bypass params addr %pad length 0x%X addr 0x%08X\n",
+                       &req_ctx->mlli_params.mlli_dma_addr,
+                       req_ctx->mlli_params.mlli_len,
+                       (unsigned int)ctx_p->drvdata->mlli_sram_addr);
+               hw_desc_init(&desc[*seq_size]);
+               set_din_type(&desc[*seq_size], DMA_DLLI,
+                            req_ctx->mlli_params.mlli_dma_addr,
+                            req_ctx->mlli_params.mlli_len, NS_BIT);
+               set_dout_sram(&desc[*seq_size],
+                             ctx_p->drvdata->mlli_sram_addr,
+                             req_ctx->mlli_params.mlli_len);
+               set_flow_mode(&desc[*seq_size], BYPASS);
+               (*seq_size)++;
+
+               hw_desc_init(&desc[*seq_size]);
+               set_din_type(&desc[*seq_size], DMA_MLLI,
+                            ctx_p->drvdata->mlli_sram_addr,
+                            req_ctx->in_mlli_nents, NS_BIT);
+               if (req_ctx->out_nents == 0) {
+                       dev_dbg(dev, " din/dout params addr 0x%08X addr 0x%08X\n",
+                               (unsigned int)ctx_p->drvdata->mlli_sram_addr,
+                               (unsigned int)ctx_p->drvdata->mlli_sram_addr);
+                       set_dout_mlli(&desc[*seq_size],
+                                     ctx_p->drvdata->mlli_sram_addr,
+                                     req_ctx->in_mlli_nents, NS_BIT,
+                                     (!areq ? 0 : 1));
+               } else {
+                       dev_dbg(dev, " din/dout params addr 0x%08X addr 0x%08X\n",
+                               (unsigned int)ctx_p->drvdata->mlli_sram_addr,
+                               (unsigned int)ctx_p->drvdata->mlli_sram_addr +
+                               (u32)LLI_ENTRY_BYTE_SIZE * req_ctx->in_nents);
+                       set_dout_mlli(&desc[*seq_size],
+                                     (ctx_p->drvdata->mlli_sram_addr +
+                                      (LLI_ENTRY_BYTE_SIZE *
+                                       req_ctx->in_mlli_nents)),
+                                     req_ctx->out_mlli_nents, NS_BIT,
+                                     (!areq ? 0 : 1));
+               }
+               if (areq)
+                       set_queue_last_ind(&desc[*seq_size]);
+
+               set_flow_mode(&desc[*seq_size], flow_mode);
+               (*seq_size)++;
+       }
+}
+
+static void cc_cipher_complete(struct device *dev, void *cc_req, int err)
+{
+       struct ablkcipher_request *areq = (struct ablkcipher_request *)cc_req;
+       struct scatterlist *dst = areq->dst;
+       struct scatterlist *src = areq->src;
+       struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(areq);
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       unsigned int ivsize = crypto_ablkcipher_ivsize(tfm);
+       struct ablkcipher_request *req = (struct ablkcipher_request *)areq;
+
+       cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
+       kfree(req_ctx->iv);
+
+       /*
+        * The crypto API expects us to set the req->info to the last
+        * ciphertext block. For encrypt, simply copy from the result.
+        * For decrypt, we must copy from a saved buffer since this
+        * could be an in-place decryption operation and the src is
+        * lost by this point.
+        */
+       if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT)  {
+               memcpy(req->info, req_ctx->backup_info, ivsize);
+               kfree(req_ctx->backup_info);
+       } else if (!err) {
+               scatterwalk_map_and_copy(req->info, req->dst,
+                                        (req->nbytes - ivsize), ivsize, 0);
+       }
+
+       ablkcipher_request_complete(areq, err);
+}
+
+static int cc_cipher_process(struct ablkcipher_request *req,
+                            enum drv_crypto_direction direction)
+{
+       struct crypto_ablkcipher *ablk_tfm = crypto_ablkcipher_reqtfm(req);
+       struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk_tfm);
+       struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(req);
+       unsigned int ivsize = crypto_ablkcipher_ivsize(ablk_tfm);
+       struct scatterlist *dst = req->dst;
+       struct scatterlist *src = req->src;
+       unsigned int nbytes = req->nbytes;
+       void *info = req->info;
+       struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
+       struct cc_hw_desc desc[MAX_ABLKCIPHER_SEQ_LEN];
+       struct cc_crypto_req cc_req = {};
+       int rc, seq_len = 0, cts_restore_flag = 0;
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       dev_dbg(dev, "%s req=%p info=%p nbytes=%d\n",
+               ((direction == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+               "Encrypt" : "Decrypt"), req, info, nbytes);
+
+       /* STAT_PHASE_0: Init and sanity checks */
+
+       /* TODO: check data length according to mode */
+       if (validate_data_size(ctx_p, nbytes)) {
+               dev_err(dev, "Unsupported data size %d.\n", nbytes);
+               crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_BLOCK_LEN);
+               rc = -EINVAL;
+               goto exit_process;
+       }
+       if (nbytes == 0) {
+               /* No data to process is valid */
+               rc = 0;
+               goto exit_process;
+       }
+
+       /* The IV we are handed may be allocted from the stack so
+        * we must copy it to a DMAable buffer before use.
+        */
+       req_ctx->iv = kmalloc(ivsize, flags);
+       if (!req_ctx->iv) {
+               rc = -ENOMEM;
+               goto exit_process;
+       }
+       memcpy(req_ctx->iv, info, ivsize);
+
+       /*For CTS in case of data size aligned to 16 use CBC mode*/
+       if (((nbytes % AES_BLOCK_SIZE) == 0) &&
+           ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS) {
+               ctx_p->cipher_mode = DRV_CIPHER_CBC;
+               cts_restore_flag = 1;
+       }
+
+       /* Setup DX request structure */
+       cc_req.user_cb = (void *)cc_cipher_complete;
+       cc_req.user_arg = (void *)req;
+
+#ifdef ENABLE_CYCLE_COUNT
+       cc_req.op_type = (direction == DRV_CRYPTO_DIRECTION_DECRYPT) ?
+               STAT_OP_TYPE_DECODE : STAT_OP_TYPE_ENCODE;
+
+#endif
+
+       /* Setup request context */
+       req_ctx->gen_ctx.op_type = direction;
+
+       /* STAT_PHASE_1: Map buffers */
+
+       rc = cc_map_blkcipher_request(ctx_p->drvdata, req_ctx, ivsize, nbytes,
+                                     req_ctx->iv, src, dst, flags);
+       if (rc) {
+               dev_err(dev, "map_request() failed\n");
+               goto exit_process;
+       }
+
+       /* STAT_PHASE_2: Create sequence */
+
+       /* Setup processing */
+       cc_setup_cipher_desc(tfm, req_ctx, ivsize, nbytes, desc, &seq_len);
+       /* Data processing */
+       cc_setup_cipher_data(tfm, req_ctx, dst, src, nbytes, req, desc,
+                            &seq_len);
+
+       /* do we need to generate IV? */
+       if (req_ctx->is_giv) {
+               cc_req.ivgen_dma_addr[0] = req_ctx->gen_ctx.iv_dma_addr;
+               cc_req.ivgen_dma_addr_len = 1;
+               /* set the IV size (8/16 B long)*/
+               cc_req.ivgen_size = ivsize;
+       }
+
+       /* STAT_PHASE_3: Lock HW and push sequence */
+
+       rc = cc_send_request(ctx_p->drvdata, &cc_req, desc, seq_len,
+                            &req->base);
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               /* Failed to send the request or request completed
+                * synchronously
+                */
+               cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
+       }
+
+exit_process:
+       if (cts_restore_flag)
+               ctx_p->cipher_mode = DRV_CIPHER_CBC_CTS;
+
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               kfree(req_ctx->backup_info);
+               kfree(req_ctx->iv);
+       }
+
+       return rc;
+}
+
+static int cc_cipher_encrypt(struct ablkcipher_request *req)
+{
+       struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(req);
+
+       req_ctx->is_giv = false;
+       req_ctx->backup_info = NULL;
+
+       return cc_cipher_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
+}
+
+static int cc_cipher_decrypt(struct ablkcipher_request *req)
+{
+       struct crypto_ablkcipher *ablk_tfm = crypto_ablkcipher_reqtfm(req);
+       struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(req);
+       unsigned int ivsize = crypto_ablkcipher_ivsize(ablk_tfm);
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       /*
+        * Allocate and save the last IV sized bytes of the source, which will
+        * be lost in case of in-place decryption and might be needed for CTS.
+        */
+       req_ctx->backup_info = kmalloc(ivsize, flags);
+       if (!req_ctx->backup_info)
+               return -ENOMEM;
+
+       scatterwalk_map_and_copy(req_ctx->backup_info, req->src,
+                                (req->nbytes - ivsize), ivsize, 0);
+       req_ctx->is_giv = false;
+
+       return cc_cipher_process(req, DRV_CRYPTO_DIRECTION_DECRYPT);
+}
+
+/* DX Block cipher alg */
+static struct cc_alg_template blkcipher_algs[] = {
+       {
+               .name = "xts(aes)",
+               .driver_name = "xts-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE * 2,
+                       .max_keysize = AES_MAX_KEY_SIZE * 2,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .geniv = "eseqiv",
+                       },
+               .cipher_mode = DRV_CIPHER_XTS,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "xts(aes)",
+               .driver_name = "xts-aes-du512-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_512,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE * 2,
+                       .max_keysize = AES_MAX_KEY_SIZE * 2,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_XTS,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "xts(aes)",
+               .driver_name = "xts-aes-du4096-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_4096,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE * 2,
+                       .max_keysize = AES_MAX_KEY_SIZE * 2,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_XTS,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "essiv(aes)",
+               .driver_name = "essiv-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE * 2,
+                       .max_keysize = AES_MAX_KEY_SIZE * 2,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_ESSIV,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "essiv(aes)",
+               .driver_name = "essiv-aes-du512-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_512,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE * 2,
+                       .max_keysize = AES_MAX_KEY_SIZE * 2,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_ESSIV,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "essiv(aes)",
+               .driver_name = "essiv-aes-du4096-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_4096,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE * 2,
+                       .max_keysize = AES_MAX_KEY_SIZE * 2,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_ESSIV,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "bitlocker(aes)",
+               .driver_name = "bitlocker-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE * 2,
+                       .max_keysize = AES_MAX_KEY_SIZE * 2,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_BITLOCKER,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "bitlocker(aes)",
+               .driver_name = "bitlocker-aes-du512-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_512,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE * 2,
+                       .max_keysize = AES_MAX_KEY_SIZE * 2,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_BITLOCKER,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "bitlocker(aes)",
+               .driver_name = "bitlocker-aes-du4096-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_4096,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE * 2,
+                       .max_keysize = AES_MAX_KEY_SIZE * 2,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_BITLOCKER,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "ecb(aes)",
+               .driver_name = "ecb-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE,
+                       .max_keysize = AES_MAX_KEY_SIZE,
+                       .ivsize = 0,
+                       },
+               .cipher_mode = DRV_CIPHER_ECB,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "cbc(aes)",
+               .driver_name = "cbc-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE,
+                       .max_keysize = AES_MAX_KEY_SIZE,
+                       .ivsize = AES_BLOCK_SIZE,
+               },
+               .cipher_mode = DRV_CIPHER_CBC,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "ofb(aes)",
+               .driver_name = "ofb-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE,
+                       .max_keysize = AES_MAX_KEY_SIZE,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_OFB,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "cts1(cbc(aes))",
+               .driver_name = "cts1-cbc-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE,
+                       .max_keysize = AES_MAX_KEY_SIZE,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_CBC_CTS,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "ctr(aes)",
+               .driver_name = "ctr-aes-dx",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = AES_MIN_KEY_SIZE,
+                       .max_keysize = AES_MAX_KEY_SIZE,
+                       .ivsize = AES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_CTR,
+               .flow_mode = S_DIN_to_AES,
+       },
+       {
+               .name = "cbc(des3_ede)",
+               .driver_name = "cbc-3des-dx",
+               .blocksize = DES3_EDE_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = DES3_EDE_KEY_SIZE,
+                       .max_keysize = DES3_EDE_KEY_SIZE,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_CBC,
+               .flow_mode = S_DIN_to_DES,
+       },
+       {
+               .name = "ecb(des3_ede)",
+               .driver_name = "ecb-3des-dx",
+               .blocksize = DES3_EDE_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = DES3_EDE_KEY_SIZE,
+                       .max_keysize = DES3_EDE_KEY_SIZE,
+                       .ivsize = 0,
+                       },
+               .cipher_mode = DRV_CIPHER_ECB,
+               .flow_mode = S_DIN_to_DES,
+       },
+       {
+               .name = "cbc(des)",
+               .driver_name = "cbc-des-dx",
+               .blocksize = DES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = DES_KEY_SIZE,
+                       .max_keysize = DES_KEY_SIZE,
+                       .ivsize = DES_BLOCK_SIZE,
+                       },
+               .cipher_mode = DRV_CIPHER_CBC,
+               .flow_mode = S_DIN_to_DES,
+       },
+       {
+               .name = "ecb(des)",
+               .driver_name = "ecb-des-dx",
+               .blocksize = DES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = cc_cipher_setkey,
+                       .encrypt = cc_cipher_encrypt,
+                       .decrypt = cc_cipher_decrypt,
+                       .min_keysize = DES_KEY_SIZE,
+                       .max_keysize = DES_KEY_SIZE,
+                       .ivsize = 0,
+                       },
+               .cipher_mode = DRV_CIPHER_ECB,
+               .flow_mode = S_DIN_to_DES,
+       },
+};
+
+static
+struct cc_crypto_alg *cc_cipher_create_alg(struct cc_alg_template *template,
+                                          struct device *dev)
+{
+       struct cc_crypto_alg *t_alg;
+       struct crypto_alg *alg;
+
+       t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
+       if (!t_alg)
+               return ERR_PTR(-ENOMEM);
+
+       alg = &t_alg->crypto_alg;
+
+       snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", template->name);
+       snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+                template->driver_name);
+       alg->cra_module = THIS_MODULE;
+       alg->cra_priority = CC_CRA_PRIO;
+       alg->cra_blocksize = template->blocksize;
+       alg->cra_alignmask = 0;
+       alg->cra_ctxsize = sizeof(struct cc_cipher_ctx);
+
+       alg->cra_init = cc_cipher_init;
+       alg->cra_exit = cc_cipher_exit;
+       alg->cra_type = &crypto_ablkcipher_type;
+       alg->cra_ablkcipher = template->template_ablkcipher;
+       alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
+                               template->type;
+
+       t_alg->cipher_mode = template->cipher_mode;
+       t_alg->flow_mode = template->flow_mode;
+
+       return t_alg;
+}
+
+int cc_cipher_free(struct cc_drvdata *drvdata)
+{
+       struct cc_crypto_alg *t_alg, *n;
+       struct cc_cipher_handle *blkcipher_handle = drvdata->blkcipher_handle;
+
+       if (blkcipher_handle) {
+               /* Remove registered algs */
+               list_for_each_entry_safe(t_alg, n,
+                                        &blkcipher_handle->blkcipher_alg_list,
+                                        entry) {
+                       crypto_unregister_alg(&t_alg->crypto_alg);
+                       list_del(&t_alg->entry);
+                       kfree(t_alg);
+               }
+               kfree(blkcipher_handle);
+               drvdata->blkcipher_handle = NULL;
+       }
+       return 0;
+}
+
+int cc_cipher_alloc(struct cc_drvdata *drvdata)
+{
+       struct cc_cipher_handle *ablkcipher_handle;
+       struct cc_crypto_alg *t_alg;
+       struct device *dev = drvdata_to_dev(drvdata);
+       int rc = -ENOMEM;
+       int alg;
+
+       ablkcipher_handle = kmalloc(sizeof(*ablkcipher_handle), GFP_KERNEL);
+       if (!ablkcipher_handle)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&ablkcipher_handle->blkcipher_alg_list);
+       drvdata->blkcipher_handle = ablkcipher_handle;
+
+       /* Linux crypto */
+       dev_dbg(dev, "Number of algorithms = %zu\n",
+               ARRAY_SIZE(blkcipher_algs));
+       for (alg = 0; alg < ARRAY_SIZE(blkcipher_algs); alg++) {
+               dev_dbg(dev, "creating %s\n", blkcipher_algs[alg].driver_name);
+               t_alg = cc_cipher_create_alg(&blkcipher_algs[alg], dev);
+               if (IS_ERR(t_alg)) {
+                       rc = PTR_ERR(t_alg);
+                       dev_err(dev, "%s alg allocation failed\n",
+                               blkcipher_algs[alg].driver_name);
+                       goto fail0;
+               }
+               t_alg->drvdata = drvdata;
+
+               dev_dbg(dev, "registering %s\n",
+                       blkcipher_algs[alg].driver_name);
+               rc = crypto_register_alg(&t_alg->crypto_alg);
+               dev_dbg(dev, "%s alg registration rc = %x\n",
+                       t_alg->crypto_alg.cra_driver_name, rc);
+               if (rc) {
+                       dev_err(dev, "%s alg registration failed\n",
+                               t_alg->crypto_alg.cra_driver_name);
+                       kfree(t_alg);
+                       goto fail0;
+               } else {
+                       list_add_tail(&t_alg->entry,
+                                     &ablkcipher_handle->blkcipher_alg_list);
+                       dev_dbg(dev, "Registered %s\n",
+                               t_alg->crypto_alg.cra_driver_name);
+               }
+       }
+       return 0;
+
+fail0:
+       cc_cipher_free(drvdata);
+       return rc;
+}
diff --git a/drivers/staging/ccree/cc_cipher.h b/drivers/staging/ccree/cc_cipher.h
new file mode 100644 (file)
index 0000000..4c181c7
--- /dev/null
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+/* \file cc_cipher.h
+ * ARM CryptoCell Cipher Crypto API
+ */
+
+#ifndef __CC_CIPHER_H__
+#define __CC_CIPHER_H__
+
+#include <linux/kernel.h>
+#include <crypto/algapi.h>
+#include "cc_driver.h"
+#include "cc_buffer_mgr.h"
+
+/* Crypto cipher flags */
+#define CC_CRYPTO_CIPHER_KEY_KFDE0     BIT(0)
+#define CC_CRYPTO_CIPHER_KEY_KFDE1     BIT(1)
+#define CC_CRYPTO_CIPHER_KEY_KFDE2     BIT(2)
+#define CC_CRYPTO_CIPHER_KEY_KFDE3     BIT(3)
+#define CC_CRYPTO_CIPHER_DU_SIZE_512B  BIT(4)
+
+#define CC_CRYPTO_CIPHER_KEY_KFDE_MASK (CC_CRYPTO_CIPHER_KEY_KFDE0 | \
+                                       CC_CRYPTO_CIPHER_KEY_KFDE1 | \
+                                       CC_CRYPTO_CIPHER_KEY_KFDE2 | \
+                                       CC_CRYPTO_CIPHER_KEY_KFDE3)
+
+struct blkcipher_req_ctx {
+       struct async_gen_req_ctx gen_ctx;
+       enum cc_req_dma_buf_type dma_buf_type;
+       u32 in_nents;
+       u32 in_mlli_nents;
+       u32 out_nents;
+       u32 out_mlli_nents;
+       u8 *backup_info; /*store iv for generated IV flow*/
+       u8 *iv;
+       bool is_giv;
+       struct mlli_params mlli_params;
+};
+
+int cc_cipher_alloc(struct cc_drvdata *drvdata);
+
+int cc_cipher_free(struct cc_drvdata *drvdata);
+
+#ifndef CRYPTO_ALG_BULK_MASK
+
+#define CRYPTO_ALG_BULK_DU_512 0x00002000
+#define CRYPTO_ALG_BULK_DU_4096        0x00004000
+#define CRYPTO_ALG_BULK_MASK   (CRYPTO_ALG_BULK_DU_512 |\
+                               CRYPTO_ALG_BULK_DU_4096)
+#endif /* CRYPTO_ALG_BULK_MASK */
+
+#ifdef CRYPTO_TFM_REQ_HW_KEY
+
+static inline bool cc_is_hw_key(struct crypto_tfm *tfm)
+{
+       return (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_HW_KEY);
+}
+
+#else
+
+struct arm_hw_key_info {
+       int hw_key1;
+       int hw_key2;
+};
+
+static inline bool cc_is_hw_key(struct crypto_tfm *tfm)
+{
+       return false;
+}
+
+#endif /* CRYPTO_TFM_REQ_HW_KEY */
+
+#endif /*__CC_CIPHER_H__*/
index 591f6fdadc59f1193f1d3f857ea2402ccfaa494a..eb16842d7db90784cb35a865c198927e82fbb5d4 100644 (file)
@@ -1,18 +1,5 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
 
 #ifndef _CC_CRYPTO_CTX_H_
 #define _CC_CRYPTO_CTX_H_
@@ -21,7 +8,7 @@
 
 /* context size */
 #ifndef CC_CTX_SIZE_LOG2
-#if (CC_SUPPORT_SHA > 256)
+#if (CC_DEV_SHA_MAX > 256)
 #define CC_CTX_SIZE_LOG2 8
 #else
 #define CC_CTX_SIZE_LOG2 7
@@ -72,7 +59,7 @@
 #define CC_SHA384_BLOCK_SIZE 128
 #define CC_SHA512_BLOCK_SIZE 128
 
-#if (CC_SUPPORT_SHA > 256)
+#if (CC_DEV_SHA_MAX > 256)
 #define CC_DIGEST_SIZE_MAX CC_SHA512_DIGEST_SIZE
 #define CC_HASH_BLOCK_SIZE_MAX CC_SHA512_BLOCK_SIZE /*1024b*/
 #else /* Only up to SHA256 */
 
 #define CC_HMAC_BLOCK_SIZE_MAX CC_HASH_BLOCK_SIZE_MAX
 
-#define CC_MULTI2_SYSTEM_KEY_SIZE              32
-#define CC_MULTI2_DATA_KEY_SIZE                8
-#define CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE \
-               (CC_MULTI2_SYSTEM_KEY_SIZE + CC_MULTI2_DATA_KEY_SIZE)
-#define        CC_MULTI2_BLOCK_SIZE                                    8
-#define        CC_MULTI2_IV_SIZE                                       8
-#define        CC_MULTI2_MIN_NUM_ROUNDS                                8
-#define        CC_MULTI2_MAX_NUM_ROUNDS                                128
-
 #define CC_DRV_ALG_MAX_BLOCK_SIZE CC_HASH_BLOCK_SIZE_MAX
 
 enum drv_engine_type {
@@ -168,14 +146,6 @@ enum drv_hash_hw_mode {
        DRV_HASH_HW_RESERVE32B = S32_MAX
 };
 
-enum drv_multi2_mode {
-       DRV_MULTI2_NULL = -1,
-       DRV_MULTI2_ECB = 0,
-       DRV_MULTI2_CBC = 1,
-       DRV_MULTI2_OFB = 2,
-       DRV_MULTI2_RESERVE32B = S32_MAX
-};
-
 /* drv_crypto_key_type[1:0] is mapped to cipher_do[1:0] */
 /* drv_crypto_key_type[2] is mapped to cipher_config2 */
 enum drv_crypto_key_type {
diff --git a/drivers/staging/ccree/cc_debugfs.c b/drivers/staging/ccree/cc_debugfs.c
new file mode 100644 (file)
index 0000000..08f8db4
--- /dev/null
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/stringify.h>
+#include "cc_driver.h"
+#include "cc_crypto_ctx.h"
+#include "cc_debugfs.h"
+
+struct cc_debugfs_ctx {
+       struct dentry *dir;
+};
+
+#define CC_DEBUG_REG(_X) {     \
+       .name = __stringify(_X),\
+       .offset = CC_REG(_X)    \
+       }
+
+/*
+ * This is a global var for the dentry of the
+ * debugfs ccree/ dir. It is not tied down to
+ * a specific instance of ccree, hence it is
+ * global.
+ */
+static struct dentry *cc_debugfs_dir;
+
+static struct debugfs_reg32 debug_regs[] = {
+       CC_DEBUG_REG(HOST_SIGNATURE),
+       CC_DEBUG_REG(HOST_IRR),
+       CC_DEBUG_REG(HOST_POWER_DOWN_EN),
+       CC_DEBUG_REG(AXIM_MON_ERR),
+       CC_DEBUG_REG(DSCRPTR_QUEUE_CONTENT),
+       CC_DEBUG_REG(HOST_IMR),
+       CC_DEBUG_REG(AXIM_CFG),
+       CC_DEBUG_REG(AXIM_CACHE_PARAMS),
+       CC_DEBUG_REG(HOST_VERSION),
+       CC_DEBUG_REG(GPR_HOST),
+       CC_DEBUG_REG(AXIM_MON_COMP),
+};
+
+int __init cc_debugfs_global_init(void)
+{
+       cc_debugfs_dir = debugfs_create_dir("ccree", NULL);
+
+       return !cc_debugfs_dir;
+}
+
+void __exit cc_debugfs_global_fini(void)
+{
+       debugfs_remove(cc_debugfs_dir);
+}
+
+int cc_debugfs_init(struct cc_drvdata *drvdata)
+{
+       struct device *dev = drvdata_to_dev(drvdata);
+       struct cc_debugfs_ctx *ctx;
+       struct debugfs_regset32 *regset;
+       struct dentry *file;
+
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL);
+       if (!regset)
+               return -ENOMEM;
+
+       regset->regs = debug_regs;
+       regset->nregs = ARRAY_SIZE(debug_regs);
+       regset->base = drvdata->cc_base;
+
+       ctx->dir = debugfs_create_dir(drvdata->plat_dev->name, cc_debugfs_dir);
+       if (!ctx->dir)
+               return -ENFILE;
+
+       file = debugfs_create_regset32("regs", 0400, ctx->dir, regset);
+       if (!file) {
+               debugfs_remove(ctx->dir);
+               return -ENFILE;
+       }
+
+       file = debugfs_create_bool("coherent", 0400, ctx->dir,
+                                  &drvdata->coherent);
+
+       if (!file) {
+               debugfs_remove_recursive(ctx->dir);
+               return -ENFILE;
+       }
+
+       drvdata->debugfs = ctx;
+
+       return 0;
+}
+
+void cc_debugfs_fini(struct cc_drvdata *drvdata)
+{
+       struct cc_debugfs_ctx *ctx = (struct cc_debugfs_ctx *)drvdata->debugfs;
+
+       debugfs_remove_recursive(ctx->dir);
+}
diff --git a/drivers/staging/ccree/cc_debugfs.h b/drivers/staging/ccree/cc_debugfs.h
new file mode 100644 (file)
index 0000000..5b5320e
--- /dev/null
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#ifndef __CC_DEBUGFS_H__
+#define __CC_DEBUGFS_H__
+
+#ifdef CONFIG_DEBUG_FS
+int cc_debugfs_global_init(void);
+void cc_debugfs_global_fini(void);
+
+int cc_debugfs_init(struct cc_drvdata *drvdata);
+void cc_debugfs_fini(struct cc_drvdata *drvdata);
+
+#else
+
+static inline int cc_debugfs_global_init(void)
+{
+       return 0;
+}
+
+static inline void cc_debugfs_global_fini(void) {}
+
+static inline int cc_debugfs_init(struct cc_drvdata *drvdata)
+{
+       return 0;
+}
+
+static inline void cc_debugfs_fini(struct cc_drvdata *drvdata) {}
+
+#endif
+
+#endif /*__CC_SYSFS_H__*/
diff --git a/drivers/staging/ccree/cc_driver.c b/drivers/staging/ccree/cc_driver.c
new file mode 100644 (file)
index 0000000..3a1cb0c
--- /dev/null
@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/crypto.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/of_address.h>
+
+#include "cc_driver.h"
+#include "cc_request_mgr.h"
+#include "cc_buffer_mgr.h"
+#include "cc_debugfs.h"
+#include "cc_cipher.h"
+#include "cc_aead.h"
+#include "cc_hash.h"
+#include "cc_ivgen.h"
+#include "cc_sram_mgr.h"
+#include "cc_pm.h"
+#include "cc_fips.h"
+
+bool cc_dump_desc;
+module_param_named(dump_desc, cc_dump_desc, bool, 0600);
+MODULE_PARM_DESC(cc_dump_desc, "Dump descriptors to kernel log as debugging aid");
+
+bool cc_dump_bytes;
+module_param_named(dump_bytes, cc_dump_bytes, bool, 0600);
+MODULE_PARM_DESC(cc_dump_bytes, "Dump buffers to kernel log as debugging aid");
+
+void __dump_byte_array(const char *name, const u8 *buf, size_t len)
+{
+       char prefix[64];
+
+       if (!buf)
+               return;
+
+       snprintf(prefix, sizeof(prefix), "%s[%zu]: ", name, len);
+
+       print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_ADDRESS, 16, 1, buf,
+                      len, false);
+}
+
+static irqreturn_t cc_isr(int irq, void *dev_id)
+{
+       struct cc_drvdata *drvdata = (struct cc_drvdata *)dev_id;
+       struct device *dev = drvdata_to_dev(drvdata);
+       u32 irr;
+       u32 imr;
+
+       /* STAT_OP_TYPE_GENERIC STAT_PHASE_0: Interrupt */
+
+       /* read the interrupt status */
+       irr = cc_ioread(drvdata, CC_REG(HOST_IRR));
+       dev_dbg(dev, "Got IRR=0x%08X\n", irr);
+       if (irr == 0) { /* Probably shared interrupt line */
+               dev_err(dev, "Got interrupt with empty IRR\n");
+               return IRQ_NONE;
+       }
+       imr = cc_ioread(drvdata, CC_REG(HOST_IMR));
+
+       /* clear interrupt - must be before processing events */
+       cc_iowrite(drvdata, CC_REG(HOST_ICR), irr);
+
+       drvdata->irq = irr;
+       /* Completion interrupt - most probable */
+       if (irr & CC_COMP_IRQ_MASK) {
+               /* Mask AXI completion interrupt - will be unmasked in
+                * Deferred service handler
+                */
+               cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | CC_COMP_IRQ_MASK);
+               irr &= ~CC_COMP_IRQ_MASK;
+               complete_request(drvdata);
+       }
+#ifdef CONFIG_CRYPTO_FIPS
+       /* TEE FIPS interrupt */
+       if (irr & CC_GPR0_IRQ_MASK) {
+               /* Mask interrupt - will be unmasked in Deferred service
+                * handler
+                */
+               cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | CC_GPR0_IRQ_MASK);
+               irr &= ~CC_GPR0_IRQ_MASK;
+               fips_handler(drvdata);
+       }
+#endif
+       /* AXI error interrupt */
+       if (irr & CC_AXI_ERR_IRQ_MASK) {
+               u32 axi_err;
+
+               /* Read the AXI error ID */
+               axi_err = cc_ioread(drvdata, CC_REG(AXIM_MON_ERR));
+               dev_dbg(dev, "AXI completion error: axim_mon_err=0x%08X\n",
+                       axi_err);
+
+               irr &= ~CC_AXI_ERR_IRQ_MASK;
+       }
+
+       if (irr) {
+               dev_dbg(dev, "IRR includes unknown cause bits (0x%08X)\n",
+                       irr);
+               /* Just warning */
+       }
+
+       return IRQ_HANDLED;
+}
+
+int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe)
+{
+       unsigned int val, cache_params;
+       struct device *dev = drvdata_to_dev(drvdata);
+
+       /* Unmask all AXI interrupt sources AXI_CFG1 register */
+       val = cc_ioread(drvdata, CC_REG(AXIM_CFG));
+       cc_iowrite(drvdata, CC_REG(AXIM_CFG), val & ~CC_AXI_IRQ_MASK);
+       dev_dbg(dev, "AXIM_CFG=0x%08X\n",
+               cc_ioread(drvdata, CC_REG(AXIM_CFG)));
+
+       /* Clear all pending interrupts */
+       val = cc_ioread(drvdata, CC_REG(HOST_IRR));
+       dev_dbg(dev, "IRR=0x%08X\n", val);
+       cc_iowrite(drvdata, CC_REG(HOST_ICR), val);
+
+       /* Unmask relevant interrupt cause */
+       val = (unsigned int)(~(CC_COMP_IRQ_MASK | CC_AXI_ERR_IRQ_MASK |
+                              CC_GPR0_IRQ_MASK));
+       cc_iowrite(drvdata, CC_REG(HOST_IMR), val);
+
+       cache_params = (drvdata->coherent ? CC_COHERENT_CACHE_PARAMS : 0x0);
+
+       val = cc_ioread(drvdata, CC_REG(AXIM_CACHE_PARAMS));
+
+       if (is_probe)
+               dev_info(dev, "Cache params previous: 0x%08X\n", val);
+
+       cc_iowrite(drvdata, CC_REG(AXIM_CACHE_PARAMS), cache_params);
+       val = cc_ioread(drvdata, CC_REG(AXIM_CACHE_PARAMS));
+
+       if (is_probe)
+               dev_info(dev, "Cache params current: 0x%08X (expect: 0x%08X)\n",
+                        val, cache_params);
+
+       return 0;
+}
+
+static int init_cc_resources(struct platform_device *plat_dev)
+{
+       struct resource *req_mem_cc_regs = NULL;
+       struct cc_drvdata *new_drvdata;
+       struct device *dev = &plat_dev->dev;
+       struct device_node *np = dev->of_node;
+       u32 signature_val;
+       u64 dma_mask;
+       int rc = 0;
+
+       new_drvdata = devm_kzalloc(dev, sizeof(*new_drvdata), GFP_KERNEL);
+       if (!new_drvdata)
+               return -ENOMEM;
+
+       platform_set_drvdata(plat_dev, new_drvdata);
+       new_drvdata->plat_dev = plat_dev;
+
+       new_drvdata->clk = of_clk_get(np, 0);
+       new_drvdata->coherent = of_dma_is_coherent(np);
+
+       /* Get device resources */
+       /* First CC registers space */
+       req_mem_cc_regs = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
+       /* Map registers space */
+       new_drvdata->cc_base = devm_ioremap_resource(dev, req_mem_cc_regs);
+       if (IS_ERR(new_drvdata->cc_base))
+               return PTR_ERR(new_drvdata->cc_base);
+
+       dev_dbg(dev, "Got MEM resource (%s): %pR\n", req_mem_cc_regs->name,
+               req_mem_cc_regs);
+       dev_dbg(dev, "CC registers mapped from %pa to 0x%p\n",
+               &req_mem_cc_regs->start, new_drvdata->cc_base);
+
+       /* Then IRQ */
+       new_drvdata->irq = platform_get_irq(plat_dev, 0);
+       if (new_drvdata->irq < 0) {
+               dev_err(dev, "Failed getting IRQ resource\n");
+               return new_drvdata->irq;
+       }
+
+       rc = devm_request_irq(dev, new_drvdata->irq, cc_isr,
+                             IRQF_SHARED, "arm_cc7x", new_drvdata);
+       if (rc) {
+               dev_err(dev, "Could not register to interrupt %d\n",
+                       new_drvdata->irq);
+               return rc;
+       }
+       dev_dbg(dev, "Registered to IRQ: %d\n", new_drvdata->irq);
+
+       init_completion(&new_drvdata->hw_queue_avail);
+
+       if (!plat_dev->dev.dma_mask)
+               plat_dev->dev.dma_mask = &plat_dev->dev.coherent_dma_mask;
+
+       dma_mask = DMA_BIT_MASK(DMA_BIT_MASK_LEN);
+       while (dma_mask > 0x7fffffffUL) {
+               if (dma_supported(&plat_dev->dev, dma_mask)) {
+                       rc = dma_set_coherent_mask(&plat_dev->dev, dma_mask);
+                       if (!rc)
+                               break;
+               }
+               dma_mask >>= 1;
+       }
+
+       if (rc) {
+               dev_err(dev, "Failed in dma_set_mask, mask=%par\n", &dma_mask);
+               return rc;
+       }
+
+       rc = cc_clk_on(new_drvdata);
+       if (rc) {
+               dev_err(dev, "Failed to enable clock");
+               return rc;
+       }
+
+       /* Verify correct mapping */
+       signature_val = cc_ioread(new_drvdata, CC_REG(HOST_SIGNATURE));
+       if (signature_val != CC_DEV_SIGNATURE) {
+               dev_err(dev, "Invalid CC signature: SIGNATURE=0x%08X != expected=0x%08X\n",
+                       signature_val, (u32)CC_DEV_SIGNATURE);
+               rc = -EINVAL;
+               goto post_clk_err;
+       }
+       dev_dbg(dev, "CC SIGNATURE=0x%08X\n", signature_val);
+
+       /* Display HW versions */
+       dev_info(dev, "ARM CryptoCell %s Driver: HW version 0x%08X, Driver version %s\n",
+                CC_DEV_NAME_STR,
+                cc_ioread(new_drvdata, CC_REG(HOST_VERSION)),
+                DRV_MODULE_VERSION);
+
+       rc = init_cc_regs(new_drvdata, true);
+       if (rc) {
+               dev_err(dev, "init_cc_regs failed\n");
+               goto post_clk_err;
+       }
+
+       rc = cc_debugfs_init(new_drvdata);
+       if (rc) {
+               dev_err(dev, "Failed registering debugfs interface\n");
+               goto post_regs_err;
+       }
+
+       rc = cc_fips_init(new_drvdata);
+       if (rc) {
+               dev_err(dev, "CC_FIPS_INIT failed 0x%x\n", rc);
+               goto post_debugfs_err;
+       }
+       rc = cc_sram_mgr_init(new_drvdata);
+       if (rc) {
+               dev_err(dev, "cc_sram_mgr_init failed\n");
+               goto post_fips_init_err;
+       }
+
+       new_drvdata->mlli_sram_addr =
+               cc_sram_alloc(new_drvdata, MAX_MLLI_BUFF_SIZE);
+       if (new_drvdata->mlli_sram_addr == NULL_SRAM_ADDR) {
+               dev_err(dev, "Failed to alloc MLLI Sram buffer\n");
+               rc = -ENOMEM;
+               goto post_sram_mgr_err;
+       }
+
+       rc = cc_req_mgr_init(new_drvdata);
+       if (rc) {
+               dev_err(dev, "cc_req_mgr_init failed\n");
+               goto post_sram_mgr_err;
+       }
+
+       rc = cc_buffer_mgr_init(new_drvdata);
+       if (rc) {
+               dev_err(dev, "buffer_mgr_init failed\n");
+               goto post_req_mgr_err;
+       }
+
+       rc = cc_pm_init(new_drvdata);
+       if (rc) {
+               dev_err(dev, "ssi_power_mgr_init failed\n");
+               goto post_buf_mgr_err;
+       }
+
+       rc = cc_ivgen_init(new_drvdata);
+       if (rc) {
+               dev_err(dev, "cc_ivgen_init failed\n");
+               goto post_power_mgr_err;
+       }
+
+       /* Allocate crypto algs */
+       rc = cc_cipher_alloc(new_drvdata);
+       if (rc) {
+               dev_err(dev, "cc_cipher_alloc failed\n");
+               goto post_ivgen_err;
+       }
+
+       /* hash must be allocated before aead since hash exports APIs */
+       rc = cc_hash_alloc(new_drvdata);
+       if (rc) {
+               dev_err(dev, "cc_hash_alloc failed\n");
+               goto post_cipher_err;
+       }
+
+       rc = cc_aead_alloc(new_drvdata);
+       if (rc) {
+               dev_err(dev, "cc_aead_alloc failed\n");
+               goto post_hash_err;
+       }
+
+       /* If we got here and FIPS mode is enabled
+        * it means all FIPS test passed, so let TEE
+        * know we're good.
+        */
+       cc_set_ree_fips_status(new_drvdata, true);
+
+       return 0;
+
+post_hash_err:
+       cc_hash_free(new_drvdata);
+post_cipher_err:
+       cc_cipher_free(new_drvdata);
+post_ivgen_err:
+       cc_ivgen_fini(new_drvdata);
+post_power_mgr_err:
+       cc_pm_fini(new_drvdata);
+post_buf_mgr_err:
+        cc_buffer_mgr_fini(new_drvdata);
+post_req_mgr_err:
+       cc_req_mgr_fini(new_drvdata);
+post_sram_mgr_err:
+       cc_sram_mgr_fini(new_drvdata);
+post_fips_init_err:
+       cc_fips_fini(new_drvdata);
+post_debugfs_err:
+       cc_debugfs_fini(new_drvdata);
+post_regs_err:
+       fini_cc_regs(new_drvdata);
+post_clk_err:
+       cc_clk_off(new_drvdata);
+       return rc;
+}
+
+void fini_cc_regs(struct cc_drvdata *drvdata)
+{
+       /* Mask all interrupts */
+       cc_iowrite(drvdata, CC_REG(HOST_IMR), 0xFFFFFFFF);
+}
+
+static void cleanup_cc_resources(struct platform_device *plat_dev)
+{
+       struct cc_drvdata *drvdata =
+               (struct cc_drvdata *)platform_get_drvdata(plat_dev);
+
+       cc_aead_free(drvdata);
+       cc_hash_free(drvdata);
+       cc_cipher_free(drvdata);
+       cc_ivgen_fini(drvdata);
+       cc_pm_fini(drvdata);
+       cc_buffer_mgr_fini(drvdata);
+       cc_req_mgr_fini(drvdata);
+       cc_sram_mgr_fini(drvdata);
+       cc_fips_fini(drvdata);
+       cc_debugfs_fini(drvdata);
+       fini_cc_regs(drvdata);
+       cc_clk_off(drvdata);
+}
+
+int cc_clk_on(struct cc_drvdata *drvdata)
+{
+       struct clk *clk = drvdata->clk;
+       int rc;
+
+       if (IS_ERR(clk))
+               /* Not all devices have a clock associated with CCREE  */
+               return 0;
+
+       rc = clk_prepare_enable(clk);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+void cc_clk_off(struct cc_drvdata *drvdata)
+{
+       struct clk *clk = drvdata->clk;
+
+       if (IS_ERR(clk))
+               /* Not all devices have a clock associated with CCREE */
+               return;
+
+       clk_disable_unprepare(clk);
+}
+
+static int cc7x_probe(struct platform_device *plat_dev)
+{
+       int rc;
+       struct device *dev = &plat_dev->dev;
+
+       /* Map registers space */
+       rc = init_cc_resources(plat_dev);
+       if (rc)
+               return rc;
+
+       dev_info(dev, "ARM ccree device initialized\n");
+
+       return 0;
+}
+
+static int cc7x_remove(struct platform_device *plat_dev)
+{
+       struct device *dev = &plat_dev->dev;
+
+       dev_dbg(dev, "Releasing cc7x resources...\n");
+
+       cleanup_cc_resources(plat_dev);
+
+       dev_info(dev, "ARM ccree device terminated\n");
+
+       return 0;
+}
+
+static const struct of_device_id arm_cc7x_dev_of_match[] = {
+       {.compatible = "arm,cryptocell-712-ree"},
+       {}
+};
+MODULE_DEVICE_TABLE(of, arm_cc7x_dev_of_match);
+
+static struct platform_driver cc7x_driver = {
+       .driver = {
+                  .name = "cc7xree",
+                  .of_match_table = arm_cc7x_dev_of_match,
+#ifdef CONFIG_PM
+                  .pm = &ccree_pm,
+#endif
+       },
+       .probe = cc7x_probe,
+       .remove = cc7x_remove,
+};
+
+static int __init ccree_init(void)
+{
+       int ret;
+
+       cc_hash_global_init();
+
+       ret = cc_debugfs_global_init();
+       if (ret)
+               return ret;
+
+       return platform_driver_register(&cc7x_driver);
+}
+module_init(ccree_init);
+
+static void __exit ccree_exit(void)
+{
+       platform_driver_unregister(&cc7x_driver);
+       cc_debugfs_global_fini();
+}
+module_exit(ccree_exit);
+
+/* Module description */
+MODULE_DESCRIPTION("ARM TrustZone CryptoCell REE Driver");
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_AUTHOR("ARM");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/ccree/cc_driver.h b/drivers/staging/ccree/cc_driver.h
new file mode 100644 (file)
index 0000000..773ac59
--- /dev/null
@@ -0,0 +1,194 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+/* \file cc_driver.h
+ * ARM CryptoCell Linux Crypto Driver
+ */
+
+#ifndef __CC_DRIVER_H__
+#define __CC_DRIVER_H__
+
+#ifdef COMP_IN_WQ
+#include <linux/workqueue.h>
+#else
+#include <linux/interrupt.h>
+#endif
+#include <linux/dma-mapping.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/aes.h>
+#include <crypto/sha.h>
+#include <crypto/aead.h>
+#include <crypto/authenc.h>
+#include <crypto/hash.h>
+#include <linux/version.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/* Registers definitions from shared/hw/ree_include */
+#include "cc_host_regs.h"
+#define CC_DEV_SHA_MAX 512
+#include "cc_crypto_ctx.h"
+#include "cc_hw_queue_defs.h"
+#include "cc_sram_mgr.h"
+
+extern bool cc_dump_desc;
+extern bool cc_dump_bytes;
+
+#define DRV_MODULE_VERSION "3.0"
+
+#define CC_DEV_NAME_STR "cc715ree"
+#define CC_COHERENT_CACHE_PARAMS 0xEEE
+
+/* Maximum DMA mask supported by IP */
+#define DMA_BIT_MASK_LEN 48
+
+#define CC_DEV_SIGNATURE 0xDCC71200UL
+
+#define CC_AXI_IRQ_MASK ((1 << CC_AXIM_CFG_BRESPMASK_BIT_SHIFT) | \
+                         (1 << CC_AXIM_CFG_RRESPMASK_BIT_SHIFT) | \
+                         (1 << CC_AXIM_CFG_INFLTMASK_BIT_SHIFT) | \
+                         (1 << CC_AXIM_CFG_COMPMASK_BIT_SHIFT))
+
+#define CC_AXI_ERR_IRQ_MASK BIT(CC_HOST_IRR_AXI_ERR_INT_BIT_SHIFT)
+
+#define CC_COMP_IRQ_MASK BIT(CC_HOST_IRR_AXIM_COMP_INT_BIT_SHIFT)
+
+#define AXIM_MON_COMP_VALUE GENMASK(CC_AXIM_MON_COMP_VALUE_BIT_SIZE + \
+                                   CC_AXIM_MON_COMP_VALUE_BIT_SHIFT, \
+                                   CC_AXIM_MON_COMP_VALUE_BIT_SHIFT)
+
+/* Register name mangling macro */
+#define CC_REG(reg_name) CC_ ## reg_name ## _REG_OFFSET
+
+/* TEE FIPS status interrupt */
+#define CC_GPR0_IRQ_MASK BIT(CC_HOST_IRR_GPR0_BIT_SHIFT)
+
+#define CC_CRA_PRIO 3000
+
+#define MIN_HW_QUEUE_SIZE 50 /* Minimum size required for proper function */
+
+#define MAX_REQUEST_QUEUE_SIZE 4096
+#define MAX_MLLI_BUFF_SIZE 2080
+#define MAX_ICV_NENTS_SUPPORTED 2
+
+/* Definitions for HW descriptors DIN/DOUT fields */
+#define NS_BIT 1
+#define AXI_ID 0
+/* AXI_ID is not actually the AXI ID of the transaction but the value of AXI_ID
+ * field in the HW descriptor. The DMA engine +8 that value.
+ */
+
+#define CC_MAX_IVGEN_DMA_ADDRESSES     3
+struct cc_crypto_req {
+       void (*user_cb)(struct device *dev, void *req, int err);
+       void *user_arg;
+       dma_addr_t ivgen_dma_addr[CC_MAX_IVGEN_DMA_ADDRESSES];
+       /* For the first 'ivgen_dma_addr_len' addresses of this array,
+        * generated IV would be placed in it by send_request().
+        * Same generated IV for all addresses!
+        */
+       /* Amount of 'ivgen_dma_addr' elements to be filled. */
+       unsigned int ivgen_dma_addr_len;
+       /* The generated IV size required, 8/16 B allowed. */
+       unsigned int ivgen_size;
+       struct completion seq_compl; /* request completion */
+};
+
+/**
+ * struct cc_drvdata - driver private data context
+ * @cc_base:   virt address of the CC registers
+ * @irq:       device IRQ number
+ * @irq_mask:  Interrupt mask shadow (1 for masked interrupts)
+ * @fw_ver:    SeP loaded firmware version
+ */
+struct cc_drvdata {
+       void __iomem *cc_base;
+       int irq;
+       u32 irq_mask;
+       u32 fw_ver;
+       struct completion hw_queue_avail; /* wait for HW queue availability */
+       struct platform_device *plat_dev;
+       cc_sram_addr_t mlli_sram_addr;
+       void *buff_mgr_handle;
+       void *hash_handle;
+       void *aead_handle;
+       void *blkcipher_handle;
+       void *request_mgr_handle;
+       void *fips_handle;
+       void *ivgen_handle;
+       void *sram_mgr_handle;
+       void *debugfs;
+       struct clk *clk;
+       bool coherent;
+};
+
+struct cc_crypto_alg {
+       struct list_head entry;
+       int cipher_mode;
+       int flow_mode; /* Note: currently, refers to the cipher mode only. */
+       int auth_mode;
+       struct cc_drvdata *drvdata;
+       struct crypto_alg crypto_alg;
+       struct aead_alg aead_alg;
+};
+
+struct cc_alg_template {
+       char name[CRYPTO_MAX_ALG_NAME];
+       char driver_name[CRYPTO_MAX_ALG_NAME];
+       unsigned int blocksize;
+       u32 type;
+       union {
+               struct ablkcipher_alg ablkcipher;
+               struct aead_alg aead;
+               struct blkcipher_alg blkcipher;
+               struct cipher_alg cipher;
+               struct compress_alg compress;
+       } template_u;
+       int cipher_mode;
+       int flow_mode; /* Note: currently, refers to the cipher mode only. */
+       int auth_mode;
+       struct cc_drvdata *drvdata;
+};
+
+struct async_gen_req_ctx {
+       dma_addr_t iv_dma_addr;
+       enum drv_crypto_direction op_type;
+};
+
+static inline struct device *drvdata_to_dev(struct cc_drvdata *drvdata)
+{
+       return &drvdata->plat_dev->dev;
+}
+
+void __dump_byte_array(const char *name, const u8 *buf, size_t len);
+static inline void dump_byte_array(const char *name, const u8 *the_array,
+                                  size_t size)
+{
+       if (cc_dump_bytes)
+               __dump_byte_array(name, the_array, size);
+}
+
+int init_cc_regs(struct cc_drvdata *drvdata, bool is_probe);
+void fini_cc_regs(struct cc_drvdata *drvdata);
+int cc_clk_on(struct cc_drvdata *drvdata);
+void cc_clk_off(struct cc_drvdata *drvdata);
+
+static inline void cc_iowrite(struct cc_drvdata *drvdata, u32 reg, u32 val)
+{
+       iowrite32(val, (drvdata->cc_base + reg));
+}
+
+static inline u32 cc_ioread(struct cc_drvdata *drvdata, u32 reg)
+{
+       return ioread32(drvdata->cc_base + reg);
+}
+
+static inline gfp_t cc_gfp_flags(struct crypto_async_request *req)
+{
+       return (req->flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
+                       GFP_KERNEL : GFP_ATOMIC;
+}
+
+#endif /*__CC_DRIVER_H__*/
+
diff --git a/drivers/staging/ccree/cc_fips.c b/drivers/staging/ccree/cc_fips.c
new file mode 100644 (file)
index 0000000..de08af9
--- /dev/null
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <linux/kernel.h>
+#include <linux/fips.h>
+
+#include "cc_driver.h"
+#include "cc_fips.h"
+
+static void fips_dsr(unsigned long devarg);
+
+struct cc_fips_handle {
+       struct tasklet_struct tasklet;
+};
+
+/* The function called once at driver entry point to check
+ * whether TEE FIPS error occurred.
+ */
+static bool cc_get_tee_fips_status(struct cc_drvdata *drvdata)
+{
+       u32 reg;
+
+       reg = cc_ioread(drvdata, CC_REG(GPR_HOST));
+       return (reg == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK));
+}
+
+/*
+ * This function should push the FIPS REE library status towards the TEE library
+ * by writing the error state to HOST_GPR0 register.
+ */
+void cc_set_ree_fips_status(struct cc_drvdata *drvdata, bool status)
+{
+       int val = CC_FIPS_SYNC_REE_STATUS;
+
+       val |= (status ? CC_FIPS_SYNC_MODULE_OK : CC_FIPS_SYNC_MODULE_ERROR);
+
+       cc_iowrite(drvdata, CC_REG(HOST_GPR0), val);
+}
+
+void cc_fips_fini(struct cc_drvdata *drvdata)
+{
+       struct cc_fips_handle *fips_h = drvdata->fips_handle;
+
+       if (!fips_h)
+               return; /* Not allocated */
+
+       /* Kill tasklet */
+       tasklet_kill(&fips_h->tasklet);
+
+       kfree(fips_h);
+       drvdata->fips_handle = NULL;
+}
+
+void fips_handler(struct cc_drvdata *drvdata)
+{
+       struct cc_fips_handle *fips_handle_ptr = drvdata->fips_handle;
+
+       tasklet_schedule(&fips_handle_ptr->tasklet);
+}
+
+static inline void tee_fips_error(struct device *dev)
+{
+       if (fips_enabled)
+               panic("ccree: TEE reported cryptographic error in fips mode!\n");
+       else
+               dev_err(dev, "TEE reported error!\n");
+}
+
+/* Deferred service handler, run as interrupt-fired tasklet */
+static void fips_dsr(unsigned long devarg)
+{
+       struct cc_drvdata *drvdata = (struct cc_drvdata *)devarg;
+       struct device *dev = drvdata_to_dev(drvdata);
+       u32 irq, state, val;
+
+       irq = (drvdata->irq & (CC_GPR0_IRQ_MASK));
+
+       if (irq) {
+               state = cc_ioread(drvdata, CC_REG(GPR_HOST));
+
+               if (state != (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK))
+                       tee_fips_error(dev);
+       }
+
+       /* after verifing that there is nothing to do,
+        * unmask AXI completion interrupt.
+        */
+       val = (CC_REG(HOST_IMR) & ~irq);
+       cc_iowrite(drvdata, CC_REG(HOST_IMR), val);
+}
+
+/* The function called once at driver entry point .*/
+int cc_fips_init(struct cc_drvdata *p_drvdata)
+{
+       struct cc_fips_handle *fips_h;
+       struct device *dev = drvdata_to_dev(p_drvdata);
+
+       fips_h = kzalloc(sizeof(*fips_h), GFP_KERNEL);
+       if (!fips_h)
+               return -ENOMEM;
+
+       p_drvdata->fips_handle = fips_h;
+
+       dev_dbg(dev, "Initializing fips tasklet\n");
+       tasklet_init(&fips_h->tasklet, fips_dsr, (unsigned long)p_drvdata);
+
+       if (!cc_get_tee_fips_status(p_drvdata))
+               tee_fips_error(dev);
+
+       return 0;
+}
diff --git a/drivers/staging/ccree/cc_fips.h b/drivers/staging/ccree/cc_fips.h
new file mode 100644 (file)
index 0000000..0d52003
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#ifndef __CC_FIPS_H__
+#define __CC_FIPS_H__
+
+#ifdef CONFIG_CRYPTO_FIPS
+
+enum cc_fips_status {
+       CC_FIPS_SYNC_MODULE_OK = 0x0,
+       CC_FIPS_SYNC_MODULE_ERROR = 0x1,
+       CC_FIPS_SYNC_REE_STATUS = 0x4,
+       CC_FIPS_SYNC_TEE_STATUS = 0x8,
+       CC_FIPS_SYNC_STATUS_RESERVE32B = S32_MAX
+};
+
+int cc_fips_init(struct cc_drvdata *p_drvdata);
+void cc_fips_fini(struct cc_drvdata *drvdata);
+void fips_handler(struct cc_drvdata *drvdata);
+void cc_set_ree_fips_status(struct cc_drvdata *drvdata, bool ok);
+
+#else  /* CONFIG_CRYPTO_FIPS */
+
+static inline int cc_fips_init(struct cc_drvdata *p_drvdata)
+{
+       return 0;
+}
+
+static inline void cc_fips_fini(struct cc_drvdata *drvdata) {}
+static inline void cc_set_ree_fips_status(struct cc_drvdata *drvdata,
+                                         bool ok) {}
+static inline void fips_handler(struct cc_drvdata *drvdata) {}
+
+#endif /* CONFIG_CRYPTO_FIPS */
+
+#endif  /*__CC_FIPS_H__*/
+
diff --git a/drivers/staging/ccree/cc_hash.c b/drivers/staging/ccree/cc_hash.c
new file mode 100644 (file)
index 0000000..8afc39f
--- /dev/null
@@ -0,0 +1,2295 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <crypto/algapi.h>
+#include <crypto/hash.h>
+#include <crypto/md5.h>
+#include <crypto/internal/hash.h>
+
+#include "cc_driver.h"
+#include "cc_request_mgr.h"
+#include "cc_buffer_mgr.h"
+#include "cc_hash.h"
+#include "cc_sram_mgr.h"
+
+#define CC_MAX_HASH_SEQ_LEN 12
+#define CC_MAX_OPAD_KEYS_SIZE CC_MAX_HASH_BLCK_SIZE
+
+struct cc_hash_handle {
+       cc_sram_addr_t digest_len_sram_addr; /* const value in SRAM*/
+       cc_sram_addr_t larval_digest_sram_addr;   /* const value in SRAM */
+       struct list_head hash_list;
+};
+
+static const u32 digest_len_init[] = {
+       0x00000040, 0x00000000, 0x00000000, 0x00000000 };
+static const u32 md5_init[] = {
+       SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 };
+static const u32 sha1_init[] = {
+       SHA1_H4, SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 };
+static const u32 sha224_init[] = {
+       SHA224_H7, SHA224_H6, SHA224_H5, SHA224_H4,
+       SHA224_H3, SHA224_H2, SHA224_H1, SHA224_H0 };
+static const u32 sha256_init[] = {
+       SHA256_H7, SHA256_H6, SHA256_H5, SHA256_H4,
+       SHA256_H3, SHA256_H2, SHA256_H1, SHA256_H0 };
+#if (CC_DEV_SHA_MAX > 256)
+static const u32 digest_len_sha512_init[] = {
+       0x00000080, 0x00000000, 0x00000000, 0x00000000 };
+static u64 sha384_init[] = {
+       SHA384_H7, SHA384_H6, SHA384_H5, SHA384_H4,
+       SHA384_H3, SHA384_H2, SHA384_H1, SHA384_H0 };
+static u64 sha512_init[] = {
+       SHA512_H7, SHA512_H6, SHA512_H5, SHA512_H4,
+       SHA512_H3, SHA512_H2, SHA512_H1, SHA512_H0 };
+#endif
+
+static void cc_setup_xcbc(struct ahash_request *areq, struct cc_hw_desc desc[],
+                         unsigned int *seq_size);
+
+static void cc_setup_cmac(struct ahash_request *areq, struct cc_hw_desc desc[],
+                         unsigned int *seq_size);
+
+static const void *cc_larval_digest(struct device *dev, u32 mode);
+
+struct cc_hash_alg {
+       struct list_head entry;
+       int hash_mode;
+       int hw_mode;
+       int inter_digestsize;
+       struct cc_drvdata *drvdata;
+       struct ahash_alg ahash_alg;
+};
+
+struct hash_key_req_ctx {
+       u32 keylen;
+       dma_addr_t key_dma_addr;
+};
+
+/* hash per-session context */
+struct cc_hash_ctx {
+       struct cc_drvdata *drvdata;
+       /* holds the origin digest; the digest after "setkey" if HMAC,*
+        * the initial digest if HASH.
+        */
+       u8 digest_buff[CC_MAX_HASH_DIGEST_SIZE]  ____cacheline_aligned;
+       u8 opad_tmp_keys_buff[CC_MAX_OPAD_KEYS_SIZE]  ____cacheline_aligned;
+
+       dma_addr_t opad_tmp_keys_dma_addr  ____cacheline_aligned;
+       dma_addr_t digest_buff_dma_addr;
+       /* use for hmac with key large then mode block size */
+       struct hash_key_req_ctx key_params;
+       int hash_mode;
+       int hw_mode;
+       int inter_digestsize;
+       struct completion setkey_comp;
+       bool is_hmac;
+};
+
+static void cc_set_desc(struct ahash_req_ctx *areq_ctx, struct cc_hash_ctx *ctx,
+                       unsigned int flow_mode, struct cc_hw_desc desc[],
+                       bool is_not_last_data, unsigned int *seq_size);
+
+static void cc_set_endianity(u32 mode, struct cc_hw_desc *desc)
+{
+       if (mode == DRV_HASH_MD5 || mode == DRV_HASH_SHA384 ||
+           mode == DRV_HASH_SHA512) {
+               set_bytes_swap(desc, 1);
+       } else {
+               set_cipher_config0(desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+       }
+}
+
+static int cc_map_result(struct device *dev, struct ahash_req_ctx *state,
+                        unsigned int digestsize)
+{
+       state->digest_result_dma_addr =
+               dma_map_single(dev, state->digest_result_buff,
+                              digestsize, DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(dev, state->digest_result_dma_addr)) {
+               dev_err(dev, "Mapping digest result buffer %u B for DMA failed\n",
+                       digestsize);
+               return -ENOMEM;
+       }
+       dev_dbg(dev, "Mapped digest result buffer %u B at va=%pK to dma=%pad\n",
+               digestsize, state->digest_result_buff,
+               &state->digest_result_dma_addr);
+
+       return 0;
+}
+
+static void cc_init_req(struct device *dev, struct ahash_req_ctx *state,
+                       struct cc_hash_ctx *ctx)
+{
+       bool is_hmac = ctx->is_hmac;
+
+       memset(state, 0, sizeof(*state));
+
+       if (is_hmac) {
+               if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC &&
+                   ctx->hw_mode != DRV_CIPHER_CMAC) {
+                       dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr,
+                                               ctx->inter_digestsize,
+                                               DMA_BIDIRECTIONAL);
+
+                       memcpy(state->digest_buff, ctx->digest_buff,
+                              ctx->inter_digestsize);
+#if (CC_DEV_SHA_MAX > 256)
+                       if (ctx->hash_mode == DRV_HASH_SHA512 ||
+                           ctx->hash_mode == DRV_HASH_SHA384)
+                               memcpy(state->digest_bytes_len,
+                                      digest_len_sha512_init, HASH_LEN_SIZE);
+                       else
+                               memcpy(state->digest_bytes_len,
+                                      digest_len_init, HASH_LEN_SIZE);
+#else
+                       memcpy(state->digest_bytes_len, digest_len_init,
+                              HASH_LEN_SIZE);
+#endif
+               }
+
+               if (ctx->hash_mode != DRV_HASH_NULL) {
+                       dma_sync_single_for_cpu(dev,
+                                               ctx->opad_tmp_keys_dma_addr,
+                                               ctx->inter_digestsize,
+                                               DMA_BIDIRECTIONAL);
+                       memcpy(state->opad_digest_buff,
+                              ctx->opad_tmp_keys_buff, ctx->inter_digestsize);
+               }
+       } else { /*hash*/
+               /* Copy the initial digests if hash flow. */
+               const void *larval = cc_larval_digest(dev, ctx->hash_mode);
+
+               memcpy(state->digest_buff, larval, ctx->inter_digestsize);
+       }
+}
+
+static int cc_map_req(struct device *dev, struct ahash_req_ctx *state,
+                     struct cc_hash_ctx *ctx)
+{
+       bool is_hmac = ctx->is_hmac;
+
+       state->digest_buff_dma_addr =
+               dma_map_single(dev, state->digest_buff,
+                              ctx->inter_digestsize, DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(dev, state->digest_buff_dma_addr)) {
+               dev_err(dev, "Mapping digest len %d B at va=%pK for DMA failed\n",
+                       ctx->inter_digestsize, state->digest_buff);
+               return -EINVAL;
+       }
+       dev_dbg(dev, "Mapped digest %d B at va=%pK to dma=%pad\n",
+               ctx->inter_digestsize, state->digest_buff,
+               &state->digest_buff_dma_addr);
+
+       if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) {
+               state->digest_bytes_len_dma_addr =
+                       dma_map_single(dev, state->digest_bytes_len,
+                                      HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
+               if (dma_mapping_error(dev, state->digest_bytes_len_dma_addr)) {
+                       dev_err(dev, "Mapping digest len %u B at va=%pK for DMA failed\n",
+                               HASH_LEN_SIZE, state->digest_bytes_len);
+                       goto unmap_digest_buf;
+               }
+               dev_dbg(dev, "Mapped digest len %u B at va=%pK to dma=%pad\n",
+                       HASH_LEN_SIZE, state->digest_bytes_len,
+                       &state->digest_bytes_len_dma_addr);
+       }
+
+       if (is_hmac && ctx->hash_mode != DRV_HASH_NULL) {
+               state->opad_digest_dma_addr =
+                       dma_map_single(dev, state->opad_digest_buff,
+                                      ctx->inter_digestsize,
+                                      DMA_BIDIRECTIONAL);
+               if (dma_mapping_error(dev, state->opad_digest_dma_addr)) {
+                       dev_err(dev, "Mapping opad digest %d B at va=%pK for DMA failed\n",
+                               ctx->inter_digestsize,
+                               state->opad_digest_buff);
+                       goto unmap_digest_len;
+               }
+               dev_dbg(dev, "Mapped opad digest %d B at va=%pK to dma=%pad\n",
+                       ctx->inter_digestsize, state->opad_digest_buff,
+                       &state->opad_digest_dma_addr);
+       }
+
+       return 0;
+
+unmap_digest_len:
+       if (state->digest_bytes_len_dma_addr) {
+               dma_unmap_single(dev, state->digest_bytes_len_dma_addr,
+                                HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
+               state->digest_bytes_len_dma_addr = 0;
+       }
+unmap_digest_buf:
+       if (state->digest_buff_dma_addr) {
+               dma_unmap_single(dev, state->digest_buff_dma_addr,
+                                ctx->inter_digestsize, DMA_BIDIRECTIONAL);
+               state->digest_buff_dma_addr = 0;
+       }
+
+       return -EINVAL;
+}
+
+static void cc_unmap_req(struct device *dev, struct ahash_req_ctx *state,
+                        struct cc_hash_ctx *ctx)
+{
+       if (state->digest_buff_dma_addr) {
+               dma_unmap_single(dev, state->digest_buff_dma_addr,
+                                ctx->inter_digestsize, DMA_BIDIRECTIONAL);
+               dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n",
+                       &state->digest_buff_dma_addr);
+               state->digest_buff_dma_addr = 0;
+       }
+       if (state->digest_bytes_len_dma_addr) {
+               dma_unmap_single(dev, state->digest_bytes_len_dma_addr,
+                                HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
+               dev_dbg(dev, "Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=%pad\n",
+                       &state->digest_bytes_len_dma_addr);
+               state->digest_bytes_len_dma_addr = 0;
+       }
+       if (state->opad_digest_dma_addr) {
+               dma_unmap_single(dev, state->opad_digest_dma_addr,
+                                ctx->inter_digestsize, DMA_BIDIRECTIONAL);
+               dev_dbg(dev, "Unmapped opad-digest: opad_digest_dma_addr=%pad\n",
+                       &state->opad_digest_dma_addr);
+               state->opad_digest_dma_addr = 0;
+       }
+}
+
+static void cc_unmap_result(struct device *dev, struct ahash_req_ctx *state,
+                           unsigned int digestsize, u8 *result)
+{
+       if (state->digest_result_dma_addr) {
+               dma_unmap_single(dev, state->digest_result_dma_addr, digestsize,
+                                DMA_BIDIRECTIONAL);
+               dev_dbg(dev, "unmpa digest result buffer va (%pK) pa (%pad) len %u\n",
+                       state->digest_result_buff,
+                       &state->digest_result_dma_addr, digestsize);
+               memcpy(result, state->digest_result_buff, digestsize);
+       }
+       state->digest_result_dma_addr = 0;
+}
+
+static void cc_update_complete(struct device *dev, void *cc_req, int err)
+{
+       struct ahash_request *req = (struct ahash_request *)cc_req;
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+
+       dev_dbg(dev, "req=%pK\n", req);
+
+       cc_unmap_hash_request(dev, state, req->src, false);
+       cc_unmap_req(dev, state, ctx);
+       req->base.complete(&req->base, err);
+}
+
+static void cc_digest_complete(struct device *dev, void *cc_req, int err)
+{
+       struct ahash_request *req = (struct ahash_request *)cc_req;
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+
+       dev_dbg(dev, "req=%pK\n", req);
+
+       cc_unmap_hash_request(dev, state, req->src, false);
+       cc_unmap_result(dev, state, digestsize, req->result);
+       cc_unmap_req(dev, state, ctx);
+       req->base.complete(&req->base, err);
+}
+
+static void cc_hash_complete(struct device *dev, void *cc_req, int err)
+{
+       struct ahash_request *req = (struct ahash_request *)cc_req;
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+
+       dev_dbg(dev, "req=%pK\n", req);
+
+       cc_unmap_hash_request(dev, state, req->src, false);
+       cc_unmap_result(dev, state, digestsize, req->result);
+       cc_unmap_req(dev, state, ctx);
+       req->base.complete(&req->base, err);
+}
+
+static int cc_fin_result(struct cc_hw_desc *desc, struct ahash_request *req,
+                        int idx)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+
+       /* Get final MAC result */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       /* TODO */
+       set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize,
+                     NS_BIT, 1);
+       set_queue_last_ind(&desc[idx]);
+       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+       cc_set_endianity(ctx->hash_mode, &desc[idx]);
+       idx++;
+
+       return idx;
+}
+
+static int cc_fin_hmac(struct cc_hw_desc *desc, struct ahash_request *req,
+                      int idx)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+
+       /* store the hash digest result in the context */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, digestsize,
+                     NS_BIT, 0);
+       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+       cc_set_endianity(ctx->hash_mode, &desc[idx]);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       idx++;
+
+       /* Loading hash opad xor key state */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr,
+                    ctx->inter_digestsize, NS_BIT);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       idx++;
+
+       /* Load the hash current length */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       set_din_sram(&desc[idx],
+                    cc_digest_len_addr(ctx->drvdata, ctx->hash_mode),
+                    HASH_LEN_SIZE);
+       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       idx++;
+
+       /* Memory Barrier: wait for IPAD/OPAD axi write to complete */
+       hw_desc_init(&desc[idx]);
+       set_din_no_dma(&desc[idx], 0, 0xfffff0);
+       set_dout_no_dma(&desc[idx], 0, 0, 1);
+       idx++;
+
+       /* Perform HASH update */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+                    digestsize, NS_BIT);
+       set_flow_mode(&desc[idx], DIN_HASH);
+       idx++;
+
+       return idx;
+}
+
+static int cc_hash_digest(struct ahash_request *req)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+       struct scatterlist *src = req->src;
+       unsigned int nbytes = req->nbytes;
+       u8 *result = req->result;
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       bool is_hmac = ctx->is_hmac;
+       struct cc_crypto_req cc_req = {};
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+       cc_sram_addr_t larval_digest_addr =
+               cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode);
+       int idx = 0;
+       int rc = 0;
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       dev_dbg(dev, "===== %s-digest (%d) ====\n", is_hmac ? "hmac" : "hash",
+               nbytes);
+
+       cc_init_req(dev, state, ctx);
+
+       if (cc_map_req(dev, state, ctx)) {
+               dev_err(dev, "map_ahash_source() failed\n");
+               return -ENOMEM;
+       }
+
+       if (cc_map_result(dev, state, digestsize)) {
+               dev_err(dev, "map_ahash_digest() failed\n");
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1,
+                                     flags)) {
+               dev_err(dev, "map_ahash_request_final() failed\n");
+               cc_unmap_result(dev, state, digestsize, result);
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       /* Setup DX request structure */
+       cc_req.user_cb = cc_digest_complete;
+       cc_req.user_arg = req;
+
+       /* If HMAC then load hash IPAD xor key, if HASH then load initial
+        * digest
+        */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       if (is_hmac) {
+               set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+                            ctx->inter_digestsize, NS_BIT);
+       } else {
+               set_din_sram(&desc[idx], larval_digest_addr,
+                            ctx->inter_digestsize);
+       }
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       idx++;
+
+       /* Load the hash current length */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+
+       if (is_hmac) {
+               set_din_type(&desc[idx], DMA_DLLI,
+                            state->digest_bytes_len_dma_addr, HASH_LEN_SIZE,
+                            NS_BIT);
+       } else {
+               set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+               if (nbytes)
+                       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+               else
+                       set_cipher_do(&desc[idx], DO_PAD);
+       }
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       idx++;
+
+       cc_set_desc(state, ctx, DIN_HASH, desc, false, &idx);
+
+       if (is_hmac) {
+               /* HW last hash block padding (aka. "DO_PAD") */
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], ctx->hw_mode);
+               set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+                             HASH_LEN_SIZE, NS_BIT, 0);
+               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+               set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
+               set_cipher_do(&desc[idx], DO_PAD);
+               idx++;
+
+               idx = cc_fin_hmac(desc, req, idx);
+       }
+
+       idx = cc_fin_result(desc, req, idx);
+
+       rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               cc_unmap_hash_request(dev, state, src, true);
+               cc_unmap_result(dev, state, digestsize, result);
+               cc_unmap_req(dev, state, ctx);
+       }
+       return rc;
+}
+
+static int cc_restore_hash(struct cc_hw_desc *desc, struct cc_hash_ctx *ctx,
+                          struct ahash_req_ctx *state, int idx)
+{
+       /* Restore hash digest */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+                    ctx->inter_digestsize, NS_BIT);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       idx++;
+
+       /* Restore hash current length */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+       set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr,
+                    HASH_LEN_SIZE, NS_BIT);
+       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       idx++;
+
+       cc_set_desc(state, ctx, DIN_HASH, desc, false, &idx);
+
+       return idx;
+}
+
+static int cc_hash_update(struct ahash_request *req)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base);
+       struct scatterlist *src = req->src;
+       unsigned int nbytes = req->nbytes;
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       struct cc_crypto_req cc_req = {};
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+       u32 idx = 0;
+       int rc;
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       dev_dbg(dev, "===== %s-update (%d) ====\n", ctx->is_hmac ?
+               "hmac" : "hash", nbytes);
+
+       if (nbytes == 0) {
+               /* no real updates required */
+               return 0;
+       }
+
+       rc = cc_map_hash_request_update(ctx->drvdata, state, src, nbytes,
+                                       block_size, flags);
+       if (rc) {
+               if (rc == 1) {
+                       dev_dbg(dev, " data size not require HW update %x\n",
+                               nbytes);
+                       /* No hardware updates are required */
+                       return 0;
+               }
+               dev_err(dev, "map_ahash_request_update() failed\n");
+               return -ENOMEM;
+       }
+
+       if (cc_map_req(dev, state, ctx)) {
+               dev_err(dev, "map_ahash_source() failed\n");
+               cc_unmap_hash_request(dev, state, src, true);
+               return -EINVAL;
+       }
+
+       /* Setup DX request structure */
+       cc_req.user_cb = cc_update_complete;
+       cc_req.user_arg = req;
+
+       idx = cc_restore_hash(desc, ctx, state, idx);
+
+       /* store the hash digest result in context */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+                     ctx->inter_digestsize, NS_BIT, 0);
+       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       idx++;
+
+       /* store current hash length in context */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr,
+                     HASH_LEN_SIZE, NS_BIT, 1);
+       set_queue_last_ind(&desc[idx]);
+       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
+       idx++;
+
+       rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               cc_unmap_hash_request(dev, state, src, true);
+               cc_unmap_req(dev, state, ctx);
+       }
+       return rc;
+}
+
+static int cc_hash_finup(struct ahash_request *req)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+       struct scatterlist *src = req->src;
+       unsigned int nbytes = req->nbytes;
+       u8 *result = req->result;
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       bool is_hmac = ctx->is_hmac;
+       struct cc_crypto_req cc_req = {};
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+       int idx = 0;
+       int rc;
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       dev_dbg(dev, "===== %s-finup (%d) ====\n", is_hmac ? "hmac" : "hash",
+               nbytes);
+
+       if (cc_map_req(dev, state, ctx)) {
+               dev_err(dev, "map_ahash_source() failed\n");
+               return -EINVAL;
+       }
+
+       if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1,
+                                     flags)) {
+               dev_err(dev, "map_ahash_request_final() failed\n");
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+       if (cc_map_result(dev, state, digestsize)) {
+               dev_err(dev, "map_ahash_digest() failed\n");
+               cc_unmap_hash_request(dev, state, src, true);
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       /* Setup DX request structure */
+       cc_req.user_cb = cc_hash_complete;
+       cc_req.user_arg = req;
+
+       idx = cc_restore_hash(desc, ctx, state, idx);
+
+       if (is_hmac)
+               idx = cc_fin_hmac(desc, req, idx);
+
+       idx = cc_fin_result(desc, req, idx);
+
+       rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               cc_unmap_hash_request(dev, state, src, true);
+               cc_unmap_result(dev, state, digestsize, result);
+               cc_unmap_req(dev, state, ctx);
+       }
+       return rc;
+}
+
+static int cc_hash_final(struct ahash_request *req)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+       struct scatterlist *src = req->src;
+       unsigned int nbytes = req->nbytes;
+       u8 *result = req->result;
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       bool is_hmac = ctx->is_hmac;
+       struct cc_crypto_req cc_req = {};
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+       int idx = 0;
+       int rc;
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       dev_dbg(dev, "===== %s-final (%d) ====\n", is_hmac ? "hmac" : "hash",
+               nbytes);
+
+       if (cc_map_req(dev, state, ctx)) {
+               dev_err(dev, "map_ahash_source() failed\n");
+               return -EINVAL;
+       }
+
+       if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, 0,
+                                     flags)) {
+               dev_err(dev, "map_ahash_request_final() failed\n");
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       if (cc_map_result(dev, state, digestsize)) {
+               dev_err(dev, "map_ahash_digest() failed\n");
+               cc_unmap_hash_request(dev, state, src, true);
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       /* Setup DX request structure */
+       cc_req.user_cb = cc_hash_complete;
+       cc_req.user_arg = req;
+
+       idx = cc_restore_hash(desc, ctx, state, idx);
+
+       /* "DO-PAD" must be enabled only when writing current length to HW */
+       hw_desc_init(&desc[idx]);
+       set_cipher_do(&desc[idx], DO_PAD);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr,
+                     HASH_LEN_SIZE, NS_BIT, 0);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
+       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+       idx++;
+
+       if (is_hmac)
+               idx = cc_fin_hmac(desc, req, idx);
+
+       idx = cc_fin_result(desc, req, idx);
+
+       rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               cc_unmap_hash_request(dev, state, src, true);
+               cc_unmap_result(dev, state, digestsize, result);
+               cc_unmap_req(dev, state, ctx);
+       }
+       return rc;
+}
+
+static int cc_hash_init(struct ahash_request *req)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "===== init (%d) ====\n", req->nbytes);
+
+       cc_init_req(dev, state, ctx);
+
+       return 0;
+}
+
+static int cc_hash_setkey(struct crypto_ahash *ahash, const u8 *key,
+                         unsigned int keylen)
+{
+       unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST };
+       struct cc_crypto_req cc_req = {};
+       struct cc_hash_ctx *ctx = NULL;
+       int blocksize = 0;
+       int digestsize = 0;
+       int i, idx = 0, rc = 0;
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+       cc_sram_addr_t larval_addr;
+       struct device *dev;
+
+       ctx = crypto_ahash_ctx(ahash);
+       dev = drvdata_to_dev(ctx->drvdata);
+       dev_dbg(dev, "start keylen: %d", keylen);
+
+       blocksize = crypto_tfm_alg_blocksize(&ahash->base);
+       digestsize = crypto_ahash_digestsize(ahash);
+
+       larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode);
+
+       /* The keylen value distinguishes HASH in case keylen is ZERO bytes,
+        * any NON-ZERO value utilizes HMAC flow
+        */
+       ctx->key_params.keylen = keylen;
+       ctx->key_params.key_dma_addr = 0;
+       ctx->is_hmac = true;
+
+       if (keylen) {
+               ctx->key_params.key_dma_addr =
+                       dma_map_single(dev, (void *)key, keylen, DMA_TO_DEVICE);
+               if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) {
+                       dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
+                               key, keylen);
+                       return -ENOMEM;
+               }
+               dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n",
+                       &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
+
+               if (keylen > blocksize) {
+                       /* Load hash initial state */
+                       hw_desc_init(&desc[idx]);
+                       set_cipher_mode(&desc[idx], ctx->hw_mode);
+                       set_din_sram(&desc[idx], larval_addr,
+                                    ctx->inter_digestsize);
+                       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+                       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+                       idx++;
+
+                       /* Load the hash current length*/
+                       hw_desc_init(&desc[idx]);
+                       set_cipher_mode(&desc[idx], ctx->hw_mode);
+                       set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+                       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+                       set_flow_mode(&desc[idx], S_DIN_to_HASH);
+                       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+                       idx++;
+
+                       hw_desc_init(&desc[idx]);
+                       set_din_type(&desc[idx], DMA_DLLI,
+                                    ctx->key_params.key_dma_addr, keylen,
+                                    NS_BIT);
+                       set_flow_mode(&desc[idx], DIN_HASH);
+                       idx++;
+
+                       /* Get hashed key */
+                       hw_desc_init(&desc[idx]);
+                       set_cipher_mode(&desc[idx], ctx->hw_mode);
+                       set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
+                                     digestsize, NS_BIT, 0);
+                       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+                       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+                       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+                       cc_set_endianity(ctx->hash_mode, &desc[idx]);
+                       idx++;
+
+                       hw_desc_init(&desc[idx]);
+                       set_din_const(&desc[idx], 0, (blocksize - digestsize));
+                       set_flow_mode(&desc[idx], BYPASS);
+                       set_dout_dlli(&desc[idx],
+                                     (ctx->opad_tmp_keys_dma_addr +
+                                      digestsize),
+                                     (blocksize - digestsize), NS_BIT, 0);
+                       idx++;
+               } else {
+                       hw_desc_init(&desc[idx]);
+                       set_din_type(&desc[idx], DMA_DLLI,
+                                    ctx->key_params.key_dma_addr, keylen,
+                                    NS_BIT);
+                       set_flow_mode(&desc[idx], BYPASS);
+                       set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
+                                     keylen, NS_BIT, 0);
+                       idx++;
+
+                       if ((blocksize - keylen)) {
+                               hw_desc_init(&desc[idx]);
+                               set_din_const(&desc[idx], 0,
+                                             (blocksize - keylen));
+                               set_flow_mode(&desc[idx], BYPASS);
+                               set_dout_dlli(&desc[idx],
+                                             (ctx->opad_tmp_keys_dma_addr +
+                                              keylen), (blocksize - keylen),
+                                             NS_BIT, 0);
+                               idx++;
+                       }
+               }
+       } else {
+               hw_desc_init(&desc[idx]);
+               set_din_const(&desc[idx], 0, blocksize);
+               set_flow_mode(&desc[idx], BYPASS);
+               set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr),
+                             blocksize, NS_BIT, 0);
+               idx++;
+       }
+
+       rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx);
+       if (rc) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               goto out;
+       }
+
+       /* calc derived HMAC key */
+       for (idx = 0, i = 0; i < 2; i++) {
+               /* Load hash initial state */
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], ctx->hw_mode);
+               set_din_sram(&desc[idx], larval_addr, ctx->inter_digestsize);
+               set_flow_mode(&desc[idx], S_DIN_to_HASH);
+               set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+               idx++;
+
+               /* Load the hash current length*/
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], ctx->hw_mode);
+               set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+               set_flow_mode(&desc[idx], S_DIN_to_HASH);
+               set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+               idx++;
+
+               /* Prepare ipad key */
+               hw_desc_init(&desc[idx]);
+               set_xor_val(&desc[idx], hmac_pad_const[i]);
+               set_cipher_mode(&desc[idx], ctx->hw_mode);
+               set_flow_mode(&desc[idx], S_DIN_to_HASH);
+               set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+               idx++;
+
+               /* Perform HASH update */
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr,
+                            blocksize, NS_BIT);
+               set_cipher_mode(&desc[idx], ctx->hw_mode);
+               set_xor_active(&desc[idx]);
+               set_flow_mode(&desc[idx], DIN_HASH);
+               idx++;
+
+               /* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest
+                * of the first HASH "update" state)
+                */
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], ctx->hw_mode);
+               if (i > 0) /* Not first iteration */
+                       set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
+                                     ctx->inter_digestsize, NS_BIT, 0);
+               else /* First iteration */
+                       set_dout_dlli(&desc[idx], ctx->digest_buff_dma_addr,
+                                     ctx->inter_digestsize, NS_BIT, 0);
+               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+               idx++;
+       }
+
+       rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx);
+
+out:
+       if (rc)
+               crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+
+       if (ctx->key_params.key_dma_addr) {
+               dma_unmap_single(dev, ctx->key_params.key_dma_addr,
+                                ctx->key_params.keylen, DMA_TO_DEVICE);
+               dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n",
+                       &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
+       }
+       return rc;
+}
+
+static int cc_xcbc_setkey(struct crypto_ahash *ahash,
+                         const u8 *key, unsigned int keylen)
+{
+       struct cc_crypto_req cc_req = {};
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       int idx = 0, rc = 0;
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+
+       dev_dbg(dev, "===== setkey (%d) ====\n", keylen);
+
+       switch (keylen) {
+       case AES_KEYSIZE_128:
+       case AES_KEYSIZE_192:
+       case AES_KEYSIZE_256:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ctx->key_params.keylen = keylen;
+
+       ctx->key_params.key_dma_addr =
+               dma_map_single(dev, (void *)key, keylen, DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) {
+               dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
+                       key, keylen);
+               return -ENOMEM;
+       }
+       dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n",
+               &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
+
+       ctx->is_hmac = true;
+       /* 1. Load the AES key */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI, ctx->key_params.key_dma_addr,
+                    keylen, NS_BIT);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
+       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+       set_key_size_aes(&desc[idx], keylen);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       idx++;
+
+       hw_desc_init(&desc[idx]);
+       set_din_const(&desc[idx], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], DIN_AES_DOUT);
+       set_dout_dlli(&desc[idx],
+                     (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K1_OFFSET),
+                     CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
+       idx++;
+
+       hw_desc_init(&desc[idx]);
+       set_din_const(&desc[idx], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], DIN_AES_DOUT);
+       set_dout_dlli(&desc[idx],
+                     (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K2_OFFSET),
+                     CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
+       idx++;
+
+       hw_desc_init(&desc[idx]);
+       set_din_const(&desc[idx], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], DIN_AES_DOUT);
+       set_dout_dlli(&desc[idx],
+                     (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K3_OFFSET),
+                     CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
+       idx++;
+
+       rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx);
+
+       if (rc)
+               crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+
+       dma_unmap_single(dev, ctx->key_params.key_dma_addr,
+                        ctx->key_params.keylen, DMA_TO_DEVICE);
+       dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n",
+               &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
+
+       return rc;
+}
+
+static int cc_cmac_setkey(struct crypto_ahash *ahash,
+                         const u8 *key, unsigned int keylen)
+{
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "===== setkey (%d) ====\n", keylen);
+
+       ctx->is_hmac = true;
+
+       switch (keylen) {
+       case AES_KEYSIZE_128:
+       case AES_KEYSIZE_192:
+       case AES_KEYSIZE_256:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ctx->key_params.keylen = keylen;
+
+       /* STAT_PHASE_1: Copy key to ctx */
+
+       dma_sync_single_for_cpu(dev, ctx->opad_tmp_keys_dma_addr,
+                               keylen, DMA_TO_DEVICE);
+
+       memcpy(ctx->opad_tmp_keys_buff, key, keylen);
+       if (keylen == 24) {
+               memset(ctx->opad_tmp_keys_buff + 24, 0,
+                      CC_AES_KEY_SIZE_MAX - 24);
+       }
+
+       dma_sync_single_for_device(dev, ctx->opad_tmp_keys_dma_addr,
+                                  keylen, DMA_TO_DEVICE);
+
+       ctx->key_params.keylen = keylen;
+
+       return 0;
+}
+
+static void cc_free_ctx(struct cc_hash_ctx *ctx)
+{
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       if (ctx->digest_buff_dma_addr) {
+               dma_unmap_single(dev, ctx->digest_buff_dma_addr,
+                                sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL);
+               dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n",
+                       &ctx->digest_buff_dma_addr);
+               ctx->digest_buff_dma_addr = 0;
+       }
+       if (ctx->opad_tmp_keys_dma_addr) {
+               dma_unmap_single(dev, ctx->opad_tmp_keys_dma_addr,
+                                sizeof(ctx->opad_tmp_keys_buff),
+                                DMA_BIDIRECTIONAL);
+               dev_dbg(dev, "Unmapped opad-digest: opad_tmp_keys_dma_addr=%pad\n",
+                       &ctx->opad_tmp_keys_dma_addr);
+               ctx->opad_tmp_keys_dma_addr = 0;
+       }
+
+       ctx->key_params.keylen = 0;
+}
+
+static int cc_alloc_ctx(struct cc_hash_ctx *ctx)
+{
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       ctx->key_params.keylen = 0;
+
+       ctx->digest_buff_dma_addr =
+               dma_map_single(dev, (void *)ctx->digest_buff,
+                              sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(dev, ctx->digest_buff_dma_addr)) {
+               dev_err(dev, "Mapping digest len %zu B at va=%pK for DMA failed\n",
+                       sizeof(ctx->digest_buff), ctx->digest_buff);
+               goto fail;
+       }
+       dev_dbg(dev, "Mapped digest %zu B at va=%pK to dma=%pad\n",
+               sizeof(ctx->digest_buff), ctx->digest_buff,
+               &ctx->digest_buff_dma_addr);
+
+       ctx->opad_tmp_keys_dma_addr =
+               dma_map_single(dev, (void *)ctx->opad_tmp_keys_buff,
+                              sizeof(ctx->opad_tmp_keys_buff),
+                              DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(dev, ctx->opad_tmp_keys_dma_addr)) {
+               dev_err(dev, "Mapping opad digest %zu B at va=%pK for DMA failed\n",
+                       sizeof(ctx->opad_tmp_keys_buff),
+                       ctx->opad_tmp_keys_buff);
+               goto fail;
+       }
+       dev_dbg(dev, "Mapped opad_tmp_keys %zu B at va=%pK to dma=%pad\n",
+               sizeof(ctx->opad_tmp_keys_buff), ctx->opad_tmp_keys_buff,
+               &ctx->opad_tmp_keys_dma_addr);
+
+       ctx->is_hmac = false;
+       return 0;
+
+fail:
+       cc_free_ctx(ctx);
+       return -ENOMEM;
+}
+
+static int cc_cra_init(struct crypto_tfm *tfm)
+{
+       struct cc_hash_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct hash_alg_common *hash_alg_common =
+               container_of(tfm->__crt_alg, struct hash_alg_common, base);
+       struct ahash_alg *ahash_alg =
+               container_of(hash_alg_common, struct ahash_alg, halg);
+       struct cc_hash_alg *cc_alg =
+                       container_of(ahash_alg, struct cc_hash_alg, ahash_alg);
+
+       crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+                                sizeof(struct ahash_req_ctx));
+
+       ctx->hash_mode = cc_alg->hash_mode;
+       ctx->hw_mode = cc_alg->hw_mode;
+       ctx->inter_digestsize = cc_alg->inter_digestsize;
+       ctx->drvdata = cc_alg->drvdata;
+
+       return cc_alloc_ctx(ctx);
+}
+
+static void cc_cra_exit(struct crypto_tfm *tfm)
+{
+       struct cc_hash_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       dev_dbg(dev, "cc_cra_exit");
+       cc_free_ctx(ctx);
+}
+
+static int cc_mac_update(struct ahash_request *req)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base);
+       struct cc_crypto_req cc_req = {};
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+       int rc;
+       u32 idx = 0;
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       if (req->nbytes == 0) {
+               /* no real updates required */
+               return 0;
+       }
+
+       state->xcbc_count++;
+
+       rc = cc_map_hash_request_update(ctx->drvdata, state, req->src,
+                                       req->nbytes, block_size, flags);
+       if (rc) {
+               if (rc == 1) {
+                       dev_dbg(dev, " data size not require HW update %x\n",
+                               req->nbytes);
+                       /* No hardware updates are required */
+                       return 0;
+               }
+               dev_err(dev, "map_ahash_request_update() failed\n");
+               return -ENOMEM;
+       }
+
+       if (cc_map_req(dev, state, ctx)) {
+               dev_err(dev, "map_ahash_source() failed\n");
+               return -EINVAL;
+       }
+
+       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC)
+               cc_setup_xcbc(req, desc, &idx);
+       else
+               cc_setup_cmac(req, desc, &idx);
+
+       cc_set_desc(state, ctx, DIN_AES_DOUT, desc, true, &idx);
+
+       /* store the hash digest result in context */
+       hw_desc_init(&desc[idx]);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+                     ctx->inter_digestsize, NS_BIT, 1);
+       set_queue_last_ind(&desc[idx]);
+       set_flow_mode(&desc[idx], S_AES_to_DOUT);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       idx++;
+
+       /* Setup DX request structure */
+       cc_req.user_cb = (void *)cc_update_complete;
+       cc_req.user_arg = (void *)req;
+
+       rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               cc_unmap_hash_request(dev, state, req->src, true);
+               cc_unmap_req(dev, state, ctx);
+       }
+       return rc;
+}
+
+static int cc_mac_final(struct ahash_request *req)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       struct cc_crypto_req cc_req = {};
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+       int idx = 0;
+       int rc = 0;
+       u32 key_size, key_len;
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+       gfp_t flags = cc_gfp_flags(&req->base);
+       u32 rem_cnt = *cc_hash_buf_cnt(state);
+
+       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
+               key_size = CC_AES_128_BIT_KEY_SIZE;
+               key_len  = CC_AES_128_BIT_KEY_SIZE;
+       } else {
+               key_size = (ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE :
+                       ctx->key_params.keylen;
+               key_len =  ctx->key_params.keylen;
+       }
+
+       dev_dbg(dev, "===== final  xcbc reminder (%d) ====\n", rem_cnt);
+
+       if (cc_map_req(dev, state, ctx)) {
+               dev_err(dev, "map_ahash_source() failed\n");
+               return -EINVAL;
+       }
+
+       if (cc_map_hash_request_final(ctx->drvdata, state, req->src,
+                                     req->nbytes, 0, flags)) {
+               dev_err(dev, "map_ahash_request_final() failed\n");
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       if (cc_map_result(dev, state, digestsize)) {
+               dev_err(dev, "map_ahash_digest() failed\n");
+               cc_unmap_hash_request(dev, state, req->src, true);
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       /* Setup DX request structure */
+       cc_req.user_cb = (void *)cc_hash_complete;
+       cc_req.user_arg = (void *)req;
+
+       if (state->xcbc_count && rem_cnt == 0) {
+               /* Load key for ECB decryption */
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
+               set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_DECRYPT);
+               set_din_type(&desc[idx], DMA_DLLI,
+                            (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K1_OFFSET),
+                            key_size, NS_BIT);
+               set_key_size_aes(&desc[idx], key_len);
+               set_flow_mode(&desc[idx], S_DIN_to_AES);
+               set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+               idx++;
+
+               /* Initiate decryption of block state to previous
+                * block_state-XOR-M[n]
+                */
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+                            CC_AES_BLOCK_SIZE, NS_BIT);
+               set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+                             CC_AES_BLOCK_SIZE, NS_BIT, 0);
+               set_flow_mode(&desc[idx], DIN_AES_DOUT);
+               idx++;
+
+               /* Memory Barrier: wait for axi write to complete */
+               hw_desc_init(&desc[idx]);
+               set_din_no_dma(&desc[idx], 0, 0xfffff0);
+               set_dout_no_dma(&desc[idx], 0, 0, 1);
+               idx++;
+       }
+
+       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC)
+               cc_setup_xcbc(req, desc, &idx);
+       else
+               cc_setup_cmac(req, desc, &idx);
+
+       if (state->xcbc_count == 0) {
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], ctx->hw_mode);
+               set_key_size_aes(&desc[idx], key_len);
+               set_cmac_size0_mode(&desc[idx]);
+               set_flow_mode(&desc[idx], S_DIN_to_AES);
+               idx++;
+       } else if (rem_cnt > 0) {
+               cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
+       } else {
+               hw_desc_init(&desc[idx]);
+               set_din_const(&desc[idx], 0x00, CC_AES_BLOCK_SIZE);
+               set_flow_mode(&desc[idx], DIN_AES_DOUT);
+               idx++;
+       }
+
+       /* Get final MAC result */
+       hw_desc_init(&desc[idx]);
+       /* TODO */
+       set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
+                     digestsize, NS_BIT, 1);
+       set_queue_last_ind(&desc[idx]);
+       set_flow_mode(&desc[idx], S_AES_to_DOUT);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       idx++;
+
+       rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               cc_unmap_hash_request(dev, state, req->src, true);
+               cc_unmap_result(dev, state, digestsize, req->result);
+               cc_unmap_req(dev, state, ctx);
+       }
+       return rc;
+}
+
+static int cc_mac_finup(struct ahash_request *req)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       struct cc_crypto_req cc_req = {};
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+       int idx = 0;
+       int rc = 0;
+       u32 key_len = 0;
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       dev_dbg(dev, "===== finup xcbc(%d) ====\n", req->nbytes);
+       if (state->xcbc_count > 0 && req->nbytes == 0) {
+               dev_dbg(dev, "No data to update. Call to fdx_mac_final\n");
+               return cc_mac_final(req);
+       }
+
+       if (cc_map_req(dev, state, ctx)) {
+               dev_err(dev, "map_ahash_source() failed\n");
+               return -EINVAL;
+       }
+
+       if (cc_map_hash_request_final(ctx->drvdata, state, req->src,
+                                     req->nbytes, 1, flags)) {
+               dev_err(dev, "map_ahash_request_final() failed\n");
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+       if (cc_map_result(dev, state, digestsize)) {
+               dev_err(dev, "map_ahash_digest() failed\n");
+               cc_unmap_hash_request(dev, state, req->src, true);
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       /* Setup DX request structure */
+       cc_req.user_cb = (void *)cc_hash_complete;
+       cc_req.user_arg = (void *)req;
+
+       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
+               key_len = CC_AES_128_BIT_KEY_SIZE;
+               cc_setup_xcbc(req, desc, &idx);
+       } else {
+               key_len = ctx->key_params.keylen;
+               cc_setup_cmac(req, desc, &idx);
+       }
+
+       if (req->nbytes == 0) {
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], ctx->hw_mode);
+               set_key_size_aes(&desc[idx], key_len);
+               set_cmac_size0_mode(&desc[idx]);
+               set_flow_mode(&desc[idx], S_DIN_to_AES);
+               idx++;
+       } else {
+               cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
+       }
+
+       /* Get final MAC result */
+       hw_desc_init(&desc[idx]);
+       /* TODO */
+       set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
+                     digestsize, NS_BIT, 1);
+       set_queue_last_ind(&desc[idx]);
+       set_flow_mode(&desc[idx], S_AES_to_DOUT);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       idx++;
+
+       rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               cc_unmap_hash_request(dev, state, req->src, true);
+               cc_unmap_result(dev, state, digestsize, req->result);
+               cc_unmap_req(dev, state, ctx);
+       }
+       return rc;
+}
+
+static int cc_mac_digest(struct ahash_request *req)
+{
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       u32 digestsize = crypto_ahash_digestsize(tfm);
+       struct cc_crypto_req cc_req = {};
+       struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
+       u32 key_len;
+       int idx = 0;
+       int rc;
+       gfp_t flags = cc_gfp_flags(&req->base);
+
+       dev_dbg(dev, "===== -digest mac (%d) ====\n",  req->nbytes);
+
+       cc_init_req(dev, state, ctx);
+
+       if (cc_map_req(dev, state, ctx)) {
+               dev_err(dev, "map_ahash_source() failed\n");
+               return -ENOMEM;
+       }
+       if (cc_map_result(dev, state, digestsize)) {
+               dev_err(dev, "map_ahash_digest() failed\n");
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       if (cc_map_hash_request_final(ctx->drvdata, state, req->src,
+                                     req->nbytes, 1, flags)) {
+               dev_err(dev, "map_ahash_request_final() failed\n");
+               cc_unmap_req(dev, state, ctx);
+               return -ENOMEM;
+       }
+
+       /* Setup DX request structure */
+       cc_req.user_cb = (void *)cc_digest_complete;
+       cc_req.user_arg = (void *)req;
+
+       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
+               key_len = CC_AES_128_BIT_KEY_SIZE;
+               cc_setup_xcbc(req, desc, &idx);
+       } else {
+               key_len = ctx->key_params.keylen;
+               cc_setup_cmac(req, desc, &idx);
+       }
+
+       if (req->nbytes == 0) {
+               hw_desc_init(&desc[idx]);
+               set_cipher_mode(&desc[idx], ctx->hw_mode);
+               set_key_size_aes(&desc[idx], key_len);
+               set_cmac_size0_mode(&desc[idx]);
+               set_flow_mode(&desc[idx], S_DIN_to_AES);
+               idx++;
+       } else {
+               cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
+       }
+
+       /* Get final MAC result */
+       hw_desc_init(&desc[idx]);
+       set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
+                     CC_AES_BLOCK_SIZE, NS_BIT, 1);
+       set_queue_last_ind(&desc[idx]);
+       set_flow_mode(&desc[idx], S_AES_to_DOUT);
+       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_cipher_mode(&desc[idx], ctx->hw_mode);
+       idx++;
+
+       rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
+       if (rc != -EINPROGRESS && rc != -EBUSY) {
+               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
+               cc_unmap_hash_request(dev, state, req->src, true);
+               cc_unmap_result(dev, state, digestsize, req->result);
+               cc_unmap_req(dev, state, ctx);
+       }
+       return rc;
+}
+
+static int cc_hash_export(struct ahash_request *req, void *out)
+{
+       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       u8 *curr_buff = cc_hash_buf(state);
+       u32 curr_buff_cnt = *cc_hash_buf_cnt(state);
+       const u32 tmp = CC_EXPORT_MAGIC;
+
+       memcpy(out, &tmp, sizeof(u32));
+       out += sizeof(u32);
+
+       memcpy(out, state->digest_buff, ctx->inter_digestsize);
+       out += ctx->inter_digestsize;
+
+       memcpy(out, state->digest_bytes_len, HASH_LEN_SIZE);
+       out += HASH_LEN_SIZE;
+
+       memcpy(out, &curr_buff_cnt, sizeof(u32));
+       out += sizeof(u32);
+
+       memcpy(out, curr_buff, curr_buff_cnt);
+
+       return 0;
+}
+
+static int cc_hash_import(struct ahash_request *req, const void *in)
+{
+       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+       struct ahash_req_ctx *state = ahash_request_ctx(req);
+       u32 tmp;
+
+       memcpy(&tmp, in, sizeof(u32));
+       if (tmp != CC_EXPORT_MAGIC)
+               return -EINVAL;
+       in += sizeof(u32);
+
+       cc_init_req(dev, state, ctx);
+
+       memcpy(state->digest_buff, in, ctx->inter_digestsize);
+       in += ctx->inter_digestsize;
+
+       memcpy(state->digest_bytes_len, in, HASH_LEN_SIZE);
+       in += HASH_LEN_SIZE;
+
+       /* Sanity check the data as much as possible */
+       memcpy(&tmp, in, sizeof(u32));
+       if (tmp > CC_MAX_HASH_BLCK_SIZE)
+               return -EINVAL;
+       in += sizeof(u32);
+
+       state->buf_cnt[0] = tmp;
+       memcpy(state->buffers[0], in, tmp);
+
+       return 0;
+}
+
+struct cc_hash_template {
+       char name[CRYPTO_MAX_ALG_NAME];
+       char driver_name[CRYPTO_MAX_ALG_NAME];
+       char mac_name[CRYPTO_MAX_ALG_NAME];
+       char mac_driver_name[CRYPTO_MAX_ALG_NAME];
+       unsigned int blocksize;
+       bool synchronize;
+       struct ahash_alg template_ahash;
+       int hash_mode;
+       int hw_mode;
+       int inter_digestsize;
+       struct cc_drvdata *drvdata;
+};
+
+#define CC_STATE_SIZE(_x) \
+       ((_x) + HASH_LEN_SIZE + CC_MAX_HASH_BLCK_SIZE + (2 * sizeof(u32)))
+
+/* hash descriptors */
+static struct cc_hash_template driver_hash[] = {
+       //Asynchronize hash template
+       {
+               .name = "sha1",
+               .driver_name = "sha1-dx",
+               .mac_name = "hmac(sha1)",
+               .mac_driver_name = "hmac-sha1-dx",
+               .blocksize = SHA1_BLOCK_SIZE,
+               .synchronize = false,
+               .template_ahash = {
+                       .init = cc_hash_init,
+                       .update = cc_hash_update,
+                       .final = cc_hash_final,
+                       .finup = cc_hash_finup,
+                       .digest = cc_hash_digest,
+                       .export = cc_hash_export,
+                       .import = cc_hash_import,
+                       .setkey = cc_hash_setkey,
+                       .halg = {
+                               .digestsize = SHA1_DIGEST_SIZE,
+                               .statesize = CC_STATE_SIZE(SHA1_DIGEST_SIZE),
+                       },
+               },
+               .hash_mode = DRV_HASH_SHA1,
+               .hw_mode = DRV_HASH_HW_SHA1,
+               .inter_digestsize = SHA1_DIGEST_SIZE,
+       },
+       {
+               .name = "sha256",
+               .driver_name = "sha256-dx",
+               .mac_name = "hmac(sha256)",
+               .mac_driver_name = "hmac-sha256-dx",
+               .blocksize = SHA256_BLOCK_SIZE,
+               .template_ahash = {
+                       .init = cc_hash_init,
+                       .update = cc_hash_update,
+                       .final = cc_hash_final,
+                       .finup = cc_hash_finup,
+                       .digest = cc_hash_digest,
+                       .export = cc_hash_export,
+                       .import = cc_hash_import,
+                       .setkey = cc_hash_setkey,
+                       .halg = {
+                               .digestsize = SHA256_DIGEST_SIZE,
+                               .statesize = CC_STATE_SIZE(SHA256_DIGEST_SIZE)
+                       },
+               },
+               .hash_mode = DRV_HASH_SHA256,
+               .hw_mode = DRV_HASH_HW_SHA256,
+               .inter_digestsize = SHA256_DIGEST_SIZE,
+       },
+       {
+               .name = "sha224",
+               .driver_name = "sha224-dx",
+               .mac_name = "hmac(sha224)",
+               .mac_driver_name = "hmac-sha224-dx",
+               .blocksize = SHA224_BLOCK_SIZE,
+               .template_ahash = {
+                       .init = cc_hash_init,
+                       .update = cc_hash_update,
+                       .final = cc_hash_final,
+                       .finup = cc_hash_finup,
+                       .digest = cc_hash_digest,
+                       .export = cc_hash_export,
+                       .import = cc_hash_import,
+                       .setkey = cc_hash_setkey,
+                       .halg = {
+                               .digestsize = SHA224_DIGEST_SIZE,
+                               .statesize = CC_STATE_SIZE(SHA224_DIGEST_SIZE),
+                       },
+               },
+               .hash_mode = DRV_HASH_SHA224,
+               .hw_mode = DRV_HASH_HW_SHA256,
+               .inter_digestsize = SHA256_DIGEST_SIZE,
+       },
+#if (CC_DEV_SHA_MAX > 256)
+       {
+               .name = "sha384",
+               .driver_name = "sha384-dx",
+               .mac_name = "hmac(sha384)",
+               .mac_driver_name = "hmac-sha384-dx",
+               .blocksize = SHA384_BLOCK_SIZE,
+               .template_ahash = {
+                       .init = cc_hash_init,
+                       .update = cc_hash_update,
+                       .final = cc_hash_final,
+                       .finup = cc_hash_finup,
+                       .digest = cc_hash_digest,
+                       .export = cc_hash_export,
+                       .import = cc_hash_import,
+                       .setkey = cc_hash_setkey,
+                       .halg = {
+                               .digestsize = SHA384_DIGEST_SIZE,
+                               .statesize = CC_STATE_SIZE(SHA384_DIGEST_SIZE),
+                       },
+               },
+               .hash_mode = DRV_HASH_SHA384,
+               .hw_mode = DRV_HASH_HW_SHA512,
+               .inter_digestsize = SHA512_DIGEST_SIZE,
+       },
+       {
+               .name = "sha512",
+               .driver_name = "sha512-dx",
+               .mac_name = "hmac(sha512)",
+               .mac_driver_name = "hmac-sha512-dx",
+               .blocksize = SHA512_BLOCK_SIZE,
+               .template_ahash = {
+                       .init = cc_hash_init,
+                       .update = cc_hash_update,
+                       .final = cc_hash_final,
+                       .finup = cc_hash_finup,
+                       .digest = cc_hash_digest,
+                       .export = cc_hash_export,
+                       .import = cc_hash_import,
+                       .setkey = cc_hash_setkey,
+                       .halg = {
+                               .digestsize = SHA512_DIGEST_SIZE,
+                               .statesize = CC_STATE_SIZE(SHA512_DIGEST_SIZE),
+                       },
+               },
+               .hash_mode = DRV_HASH_SHA512,
+               .hw_mode = DRV_HASH_HW_SHA512,
+               .inter_digestsize = SHA512_DIGEST_SIZE,
+       },
+#endif
+       {
+               .name = "md5",
+               .driver_name = "md5-dx",
+               .mac_name = "hmac(md5)",
+               .mac_driver_name = "hmac-md5-dx",
+               .blocksize = MD5_HMAC_BLOCK_SIZE,
+               .template_ahash = {
+                       .init = cc_hash_init,
+                       .update = cc_hash_update,
+                       .final = cc_hash_final,
+                       .finup = cc_hash_finup,
+                       .digest = cc_hash_digest,
+                       .export = cc_hash_export,
+                       .import = cc_hash_import,
+                       .setkey = cc_hash_setkey,
+                       .halg = {
+                               .digestsize = MD5_DIGEST_SIZE,
+                               .statesize = CC_STATE_SIZE(MD5_DIGEST_SIZE),
+                       },
+               },
+               .hash_mode = DRV_HASH_MD5,
+               .hw_mode = DRV_HASH_HW_MD5,
+               .inter_digestsize = MD5_DIGEST_SIZE,
+       },
+       {
+               .mac_name = "xcbc(aes)",
+               .mac_driver_name = "xcbc-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .template_ahash = {
+                       .init = cc_hash_init,
+                       .update = cc_mac_update,
+                       .final = cc_mac_final,
+                       .finup = cc_mac_finup,
+                       .digest = cc_mac_digest,
+                       .setkey = cc_xcbc_setkey,
+                       .export = cc_hash_export,
+                       .import = cc_hash_import,
+                       .halg = {
+                               .digestsize = AES_BLOCK_SIZE,
+                               .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE),
+                       },
+               },
+               .hash_mode = DRV_HASH_NULL,
+               .hw_mode = DRV_CIPHER_XCBC_MAC,
+               .inter_digestsize = AES_BLOCK_SIZE,
+       },
+       {
+               .mac_name = "cmac(aes)",
+               .mac_driver_name = "cmac-aes-dx",
+               .blocksize = AES_BLOCK_SIZE,
+               .template_ahash = {
+                       .init = cc_hash_init,
+                       .update = cc_mac_update,
+                       .final = cc_mac_final,
+                       .finup = cc_mac_finup,
+                       .digest = cc_mac_digest,
+                       .setkey = cc_cmac_setkey,
+                       .export = cc_hash_export,
+                       .import = cc_hash_import,
+                       .halg = {
+                               .digestsize = AES_BLOCK_SIZE,
+                               .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE),
+                       },
+               },
+               .hash_mode = DRV_HASH_NULL,
+               .hw_mode = DRV_CIPHER_CMAC,
+               .inter_digestsize = AES_BLOCK_SIZE,
+       },
+};
+
+static struct cc_hash_alg *cc_alloc_hash_alg(struct cc_hash_template *template,
+                                            struct device *dev, bool keyed)
+{
+       struct cc_hash_alg *t_crypto_alg;
+       struct crypto_alg *alg;
+       struct ahash_alg *halg;
+
+       t_crypto_alg = kzalloc(sizeof(*t_crypto_alg), GFP_KERNEL);
+       if (!t_crypto_alg)
+               return ERR_PTR(-ENOMEM);
+
+       t_crypto_alg->ahash_alg = template->template_ahash;
+       halg = &t_crypto_alg->ahash_alg;
+       alg = &halg->halg.base;
+
+       if (keyed) {
+               snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
+                        template->mac_name);
+               snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+                        template->mac_driver_name);
+       } else {
+               halg->setkey = NULL;
+               snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
+                        template->name);
+               snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+                        template->driver_name);
+       }
+       alg->cra_module = THIS_MODULE;
+       alg->cra_ctxsize = sizeof(struct cc_hash_ctx);
+       alg->cra_priority = CC_CRA_PRIO;
+       alg->cra_blocksize = template->blocksize;
+       alg->cra_alignmask = 0;
+       alg->cra_exit = cc_cra_exit;
+
+       alg->cra_init = cc_cra_init;
+       alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_TYPE_AHASH |
+                       CRYPTO_ALG_KERN_DRIVER_ONLY;
+       alg->cra_type = &crypto_ahash_type;
+
+       t_crypto_alg->hash_mode = template->hash_mode;
+       t_crypto_alg->hw_mode = template->hw_mode;
+       t_crypto_alg->inter_digestsize = template->inter_digestsize;
+
+       return t_crypto_alg;
+}
+
+int cc_init_hash_sram(struct cc_drvdata *drvdata)
+{
+       struct cc_hash_handle *hash_handle = drvdata->hash_handle;
+       cc_sram_addr_t sram_buff_ofs = hash_handle->digest_len_sram_addr;
+       unsigned int larval_seq_len = 0;
+       struct cc_hw_desc larval_seq[CC_DIGEST_SIZE_MAX / sizeof(u32)];
+       int rc = 0;
+
+       /* Copy-to-sram digest-len */
+       cc_set_sram_desc(digest_len_init, sram_buff_ofs,
+                        ARRAY_SIZE(digest_len_init), larval_seq,
+                        &larval_seq_len);
+       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
+       if (rc)
+               goto init_digest_const_err;
+
+       sram_buff_ofs += sizeof(digest_len_init);
+       larval_seq_len = 0;
+
+#if (CC_DEV_SHA_MAX > 256)
+       /* Copy-to-sram digest-len for sha384/512 */
+       cc_set_sram_desc(digest_len_sha512_init, sram_buff_ofs,
+                        ARRAY_SIZE(digest_len_sha512_init),
+                        larval_seq, &larval_seq_len);
+       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
+       if (rc)
+               goto init_digest_const_err;
+
+       sram_buff_ofs += sizeof(digest_len_sha512_init);
+       larval_seq_len = 0;
+#endif
+
+       /* The initial digests offset */
+       hash_handle->larval_digest_sram_addr = sram_buff_ofs;
+
+       /* Copy-to-sram initial SHA* digests */
+       cc_set_sram_desc(md5_init, sram_buff_ofs, ARRAY_SIZE(md5_init),
+                        larval_seq, &larval_seq_len);
+       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
+       if (rc)
+               goto init_digest_const_err;
+       sram_buff_ofs += sizeof(md5_init);
+       larval_seq_len = 0;
+
+       cc_set_sram_desc(sha1_init, sram_buff_ofs,
+                        ARRAY_SIZE(sha1_init), larval_seq,
+                        &larval_seq_len);
+       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
+       if (rc)
+               goto init_digest_const_err;
+       sram_buff_ofs += sizeof(sha1_init);
+       larval_seq_len = 0;
+
+       cc_set_sram_desc(sha224_init, sram_buff_ofs,
+                        ARRAY_SIZE(sha224_init), larval_seq,
+                        &larval_seq_len);
+       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
+       if (rc)
+               goto init_digest_const_err;
+       sram_buff_ofs += sizeof(sha224_init);
+       larval_seq_len = 0;
+
+       cc_set_sram_desc(sha256_init, sram_buff_ofs,
+                        ARRAY_SIZE(sha256_init), larval_seq,
+                        &larval_seq_len);
+       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
+       if (rc)
+               goto init_digest_const_err;
+       sram_buff_ofs += sizeof(sha256_init);
+       larval_seq_len = 0;
+
+#if (CC_DEV_SHA_MAX > 256)
+       cc_set_sram_desc((u32 *)sha384_init, sram_buff_ofs,
+                        (ARRAY_SIZE(sha384_init) * 2), larval_seq,
+                        &larval_seq_len);
+       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
+       if (rc)
+               goto init_digest_const_err;
+       sram_buff_ofs += sizeof(sha384_init);
+       larval_seq_len = 0;
+
+       cc_set_sram_desc((u32 *)sha512_init, sram_buff_ofs,
+                        (ARRAY_SIZE(sha512_init) * 2), larval_seq,
+                        &larval_seq_len);
+       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
+       if (rc)
+               goto init_digest_const_err;
+#endif
+
+init_digest_const_err:
+       return rc;
+}
+
+static void __init cc_swap_dwords(u32 *buf, unsigned long size)
+{
+       int i;
+       u32 tmp;
+
+       for (i = 0; i < size; i += 2) {
+               tmp = buf[i];
+               buf[i] = buf[i + 1];
+               buf[i + 1] = tmp;
+       }
+}
+
+/*
+ * Due to the way the HW works we need to swap every
+ * double word in the SHA384 and SHA512 larval hashes
+ */
+void __init cc_hash_global_init(void)
+{
+       cc_swap_dwords((u32 *)&sha384_init, (ARRAY_SIZE(sha384_init) * 2));
+       cc_swap_dwords((u32 *)&sha512_init, (ARRAY_SIZE(sha512_init) * 2));
+}
+
+int cc_hash_alloc(struct cc_drvdata *drvdata)
+{
+       struct cc_hash_handle *hash_handle;
+       cc_sram_addr_t sram_buff;
+       u32 sram_size_to_alloc;
+       struct device *dev = drvdata_to_dev(drvdata);
+       int rc = 0;
+       int alg;
+
+       hash_handle = kzalloc(sizeof(*hash_handle), GFP_KERNEL);
+       if (!hash_handle)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&hash_handle->hash_list);
+       drvdata->hash_handle = hash_handle;
+
+       sram_size_to_alloc = sizeof(digest_len_init) +
+#if (CC_DEV_SHA_MAX > 256)
+                       sizeof(digest_len_sha512_init) +
+                       sizeof(sha384_init) +
+                       sizeof(sha512_init) +
+#endif
+                       sizeof(md5_init) +
+                       sizeof(sha1_init) +
+                       sizeof(sha224_init) +
+                       sizeof(sha256_init);
+
+       sram_buff = cc_sram_alloc(drvdata, sram_size_to_alloc);
+       if (sram_buff == NULL_SRAM_ADDR) {
+               dev_err(dev, "SRAM pool exhausted\n");
+               rc = -ENOMEM;
+               goto fail;
+       }
+
+       /* The initial digest-len offset */
+       hash_handle->digest_len_sram_addr = sram_buff;
+
+       /*must be set before the alg registration as it is being used there*/
+       rc = cc_init_hash_sram(drvdata);
+       if (rc) {
+               dev_err(dev, "Init digest CONST failed (rc=%d)\n", rc);
+               goto fail;
+       }
+
+       /* ahash registration */
+       for (alg = 0; alg < ARRAY_SIZE(driver_hash); alg++) {
+               struct cc_hash_alg *t_alg;
+               int hw_mode = driver_hash[alg].hw_mode;
+
+               /* register hmac version */
+               t_alg = cc_alloc_hash_alg(&driver_hash[alg], dev, true);
+               if (IS_ERR(t_alg)) {
+                       rc = PTR_ERR(t_alg);
+                       dev_err(dev, "%s alg allocation failed\n",
+                               driver_hash[alg].driver_name);
+                       goto fail;
+               }
+               t_alg->drvdata = drvdata;
+
+               rc = crypto_register_ahash(&t_alg->ahash_alg);
+               if (rc) {
+                       dev_err(dev, "%s alg registration failed\n",
+                               driver_hash[alg].driver_name);
+                       kfree(t_alg);
+                       goto fail;
+               } else {
+                       list_add_tail(&t_alg->entry, &hash_handle->hash_list);
+               }
+
+               if (hw_mode == DRV_CIPHER_XCBC_MAC ||
+                   hw_mode == DRV_CIPHER_CMAC)
+                       continue;
+
+               /* register hash version */
+               t_alg = cc_alloc_hash_alg(&driver_hash[alg], dev, false);
+               if (IS_ERR(t_alg)) {
+                       rc = PTR_ERR(t_alg);
+                       dev_err(dev, "%s alg allocation failed\n",
+                               driver_hash[alg].driver_name);
+                       goto fail;
+               }
+               t_alg->drvdata = drvdata;
+
+               rc = crypto_register_ahash(&t_alg->ahash_alg);
+               if (rc) {
+                       dev_err(dev, "%s alg registration failed\n",
+                               driver_hash[alg].driver_name);
+                       kfree(t_alg);
+                       goto fail;
+               } else {
+                       list_add_tail(&t_alg->entry, &hash_handle->hash_list);
+               }
+       }
+
+       return 0;
+
+fail:
+       kfree(drvdata->hash_handle);
+       drvdata->hash_handle = NULL;
+       return rc;
+}
+
+int cc_hash_free(struct cc_drvdata *drvdata)
+{
+       struct cc_hash_alg *t_hash_alg, *hash_n;
+       struct cc_hash_handle *hash_handle = drvdata->hash_handle;
+
+       if (hash_handle) {
+               list_for_each_entry_safe(t_hash_alg, hash_n,
+                                        &hash_handle->hash_list, entry) {
+                       crypto_unregister_ahash(&t_hash_alg->ahash_alg);
+                       list_del(&t_hash_alg->entry);
+                       kfree(t_hash_alg);
+               }
+
+               kfree(hash_handle);
+               drvdata->hash_handle = NULL;
+       }
+       return 0;
+}
+
+static void cc_setup_xcbc(struct ahash_request *areq, struct cc_hw_desc desc[],
+                         unsigned int *seq_size)
+{
+       unsigned int idx = *seq_size;
+       struct ahash_req_ctx *state = ahash_request_ctx(areq);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+
+       /* Setup XCBC MAC K1 */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr +
+                                           XCBC_MAC_K1_OFFSET),
+                    CC_AES_128_BIT_KEY_SIZE, NS_BIT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       /* Setup XCBC MAC K2 */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI,
+                    (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K2_OFFSET),
+                    CC_AES_128_BIT_KEY_SIZE, NS_BIT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       /* Setup XCBC MAC K3 */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI,
+                    (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K3_OFFSET),
+                    CC_AES_128_BIT_KEY_SIZE, NS_BIT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE2);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       /* Loading MAC state */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+                    CC_AES_BLOCK_SIZE, NS_BIT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+       *seq_size = idx;
+}
+
+static void cc_setup_cmac(struct ahash_request *areq, struct cc_hw_desc desc[],
+                         unsigned int *seq_size)
+{
+       unsigned int idx = *seq_size;
+       struct ahash_req_ctx *state = ahash_request_ctx(areq);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+       struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+
+       /* Setup CMAC Key */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr,
+                    ((ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE :
+                     ctx->key_params.keylen), NS_BIT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], ctx->key_params.keylen);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+
+       /* Load MAC state */
+       hw_desc_init(&desc[idx]);
+       set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+                    CC_AES_BLOCK_SIZE, NS_BIT);
+       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+       set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
+       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_key_size_aes(&desc[idx], ctx->key_params.keylen);
+       set_flow_mode(&desc[idx], S_DIN_to_AES);
+       idx++;
+       *seq_size = idx;
+}
+
+static void cc_set_desc(struct ahash_req_ctx *areq_ctx,
+                       struct cc_hash_ctx *ctx, unsigned int flow_mode,
+                       struct cc_hw_desc desc[], bool is_not_last_data,
+                       unsigned int *seq_size)
+{
+       unsigned int idx = *seq_size;
+       struct device *dev = drvdata_to_dev(ctx->drvdata);
+
+       if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_DLLI) {
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_DLLI,
+                            sg_dma_address(areq_ctx->curr_sg),
+                            areq_ctx->curr_sg->length, NS_BIT);
+               set_flow_mode(&desc[idx], flow_mode);
+               idx++;
+       } else {
+               if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) {
+                       dev_dbg(dev, " NULL mode\n");
+                       /* nothing to build */
+                       return;
+               }
+               /* bypass */
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_DLLI,
+                            areq_ctx->mlli_params.mlli_dma_addr,
+                            areq_ctx->mlli_params.mlli_len, NS_BIT);
+               set_dout_sram(&desc[idx], ctx->drvdata->mlli_sram_addr,
+                             areq_ctx->mlli_params.mlli_len);
+               set_flow_mode(&desc[idx], BYPASS);
+               idx++;
+               /* process */
+               hw_desc_init(&desc[idx]);
+               set_din_type(&desc[idx], DMA_MLLI,
+                            ctx->drvdata->mlli_sram_addr,
+                            areq_ctx->mlli_nents, NS_BIT);
+               set_flow_mode(&desc[idx], flow_mode);
+               idx++;
+       }
+       if (is_not_last_data)
+               set_din_not_last_indication(&desc[(idx - 1)]);
+       /* return updated desc sequence size */
+       *seq_size = idx;
+}
+
+static const void *cc_larval_digest(struct device *dev, u32 mode)
+{
+       switch (mode) {
+       case DRV_HASH_MD5:
+               return md5_init;
+       case DRV_HASH_SHA1:
+               return sha1_init;
+       case DRV_HASH_SHA224:
+               return sha224_init;
+       case DRV_HASH_SHA256:
+               return sha256_init;
+#if (CC_DEV_SHA_MAX > 256)
+       case DRV_HASH_SHA384:
+               return sha384_init;
+       case DRV_HASH_SHA512:
+               return sha512_init;
+#endif
+       default:
+               dev_err(dev, "Invalid hash mode (%d)\n", mode);
+               return md5_init;
+       }
+}
+
+/*!
+ * Gets the address of the initial digest in SRAM
+ * according to the given hash mode
+ *
+ * \param drvdata
+ * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256
+ *
+ * \return u32 The address of the initial digest in SRAM
+ */
+cc_sram_addr_t cc_larval_digest_addr(void *drvdata, u32 mode)
+{
+       struct cc_drvdata *_drvdata = (struct cc_drvdata *)drvdata;
+       struct cc_hash_handle *hash_handle = _drvdata->hash_handle;
+       struct device *dev = drvdata_to_dev(_drvdata);
+
+       switch (mode) {
+       case DRV_HASH_NULL:
+               break; /*Ignore*/
+       case DRV_HASH_MD5:
+               return (hash_handle->larval_digest_sram_addr);
+       case DRV_HASH_SHA1:
+               return (hash_handle->larval_digest_sram_addr +
+                       sizeof(md5_init));
+       case DRV_HASH_SHA224:
+               return (hash_handle->larval_digest_sram_addr +
+                       sizeof(md5_init) +
+                       sizeof(sha1_init));
+       case DRV_HASH_SHA256:
+               return (hash_handle->larval_digest_sram_addr +
+                       sizeof(md5_init) +
+                       sizeof(sha1_init) +
+                       sizeof(sha224_init));
+#if (CC_DEV_SHA_MAX > 256)
+       case DRV_HASH_SHA384:
+               return (hash_handle->larval_digest_sram_addr +
+                       sizeof(md5_init) +
+                       sizeof(sha1_init) +
+                       sizeof(sha224_init) +
+                       sizeof(sha256_init));
+       case DRV_HASH_SHA512:
+               return (hash_handle->larval_digest_sram_addr +
+                       sizeof(md5_init) +
+                       sizeof(sha1_init) +
+                       sizeof(sha224_init) +
+                       sizeof(sha256_init) +
+                       sizeof(sha384_init));
+#endif
+       default:
+               dev_err(dev, "Invalid hash mode (%d)\n", mode);
+       }
+
+       /*This is valid wrong value to avoid kernel crash*/
+       return hash_handle->larval_digest_sram_addr;
+}
+
+cc_sram_addr_t
+cc_digest_len_addr(void *drvdata, u32 mode)
+{
+       struct cc_drvdata *_drvdata = (struct cc_drvdata *)drvdata;
+       struct cc_hash_handle *hash_handle = _drvdata->hash_handle;
+       cc_sram_addr_t digest_len_addr = hash_handle->digest_len_sram_addr;
+
+       switch (mode) {
+       case DRV_HASH_SHA1:
+       case DRV_HASH_SHA224:
+       case DRV_HASH_SHA256:
+       case DRV_HASH_MD5:
+               return digest_len_addr;
+#if (CC_DEV_SHA_MAX > 256)
+       case DRV_HASH_SHA384:
+       case DRV_HASH_SHA512:
+               return  digest_len_addr + sizeof(digest_len_init);
+#endif
+       default:
+               return digest_len_addr; /*to avoid kernel crash*/
+       }
+}
+
diff --git a/drivers/staging/ccree/cc_hash.h b/drivers/staging/ccree/cc_hash.h
new file mode 100644 (file)
index 0000000..aa42b8f
--- /dev/null
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+/* \file cc_hash.h
+ * ARM CryptoCell Hash Crypto API
+ */
+
+#ifndef __CC_HASH_H__
+#define __CC_HASH_H__
+
+#include "cc_buffer_mgr.h"
+
+#define HMAC_IPAD_CONST        0x36363636
+#define HMAC_OPAD_CONST        0x5C5C5C5C
+#if (CC_DEV_SHA_MAX > 256)
+#define HASH_LEN_SIZE 16
+#define CC_MAX_HASH_DIGEST_SIZE        SHA512_DIGEST_SIZE
+#define CC_MAX_HASH_BLCK_SIZE SHA512_BLOCK_SIZE
+#else
+#define HASH_LEN_SIZE 8
+#define CC_MAX_HASH_DIGEST_SIZE        SHA256_DIGEST_SIZE
+#define CC_MAX_HASH_BLCK_SIZE SHA256_BLOCK_SIZE
+#endif
+
+#define XCBC_MAC_K1_OFFSET 0
+#define XCBC_MAC_K2_OFFSET 16
+#define XCBC_MAC_K3_OFFSET 32
+
+#define CC_EXPORT_MAGIC 0xC2EE1070U
+
+/* this struct was taken from drivers/crypto/nx/nx-aes-xcbc.c and it is used
+ * for xcbc/cmac statesize
+ */
+struct aeshash_state {
+       u8 state[AES_BLOCK_SIZE];
+       unsigned int count;
+       u8 buffer[AES_BLOCK_SIZE];
+};
+
+/* ahash state */
+struct ahash_req_ctx {
+       u8 buffers[2][CC_MAX_HASH_BLCK_SIZE] ____cacheline_aligned;
+       u8 digest_result_buff[CC_MAX_HASH_DIGEST_SIZE] ____cacheline_aligned;
+       u8 digest_buff[CC_MAX_HASH_DIGEST_SIZE] ____cacheline_aligned;
+       u8 opad_digest_buff[CC_MAX_HASH_DIGEST_SIZE] ____cacheline_aligned;
+       u8 digest_bytes_len[HASH_LEN_SIZE] ____cacheline_aligned;
+       struct async_gen_req_ctx gen_ctx ____cacheline_aligned;
+       enum cc_req_dma_buf_type data_dma_buf_type;
+       dma_addr_t opad_digest_dma_addr;
+       dma_addr_t digest_buff_dma_addr;
+       dma_addr_t digest_bytes_len_dma_addr;
+       dma_addr_t digest_result_dma_addr;
+       u32 buf_cnt[2];
+       u32 buff_index;
+       u32 xcbc_count; /* count xcbc update operatations */
+       struct scatterlist buff_sg[2];
+       struct scatterlist *curr_sg;
+       u32 in_nents;
+       u32 mlli_nents;
+       struct mlli_params mlli_params;
+};
+
+static inline u32 *cc_hash_buf_cnt(struct ahash_req_ctx *state)
+{
+       return &state->buf_cnt[state->buff_index];
+}
+
+static inline u8 *cc_hash_buf(struct ahash_req_ctx *state)
+{
+       return state->buffers[state->buff_index];
+}
+
+static inline u32 *cc_next_buf_cnt(struct ahash_req_ctx *state)
+{
+       return &state->buf_cnt[state->buff_index ^ 1];
+}
+
+static inline u8 *cc_next_buf(struct ahash_req_ctx *state)
+{
+       return state->buffers[state->buff_index ^ 1];
+}
+
+int cc_hash_alloc(struct cc_drvdata *drvdata);
+int cc_init_hash_sram(struct cc_drvdata *drvdata);
+int cc_hash_free(struct cc_drvdata *drvdata);
+
+/*!
+ * Gets the initial digest length
+ *
+ * \param drvdata
+ * \param mode The Hash mode. Supported modes:
+ *             MD5/SHA1/SHA224/SHA256/SHA384/SHA512
+ *
+ * \return u32 returns the address of the initial digest length in SRAM
+ */
+cc_sram_addr_t
+cc_digest_len_addr(void *drvdata, u32 mode);
+
+/*!
+ * Gets the address of the initial digest in SRAM
+ * according to the given hash mode
+ *
+ * \param drvdata
+ * \param mode The Hash mode. Supported modes:
+ *             MD5/SHA1/SHA224/SHA256/SHA384/SHA512
+ *
+ * \return u32 The address of the initial digest in SRAM
+ */
+cc_sram_addr_t cc_larval_digest_addr(void *drvdata, u32 mode);
+
+void cc_hash_global_init(void);
+
+#endif /*__CC_HASH_H__*/
+
diff --git a/drivers/staging/ccree/cc_host_regs.h b/drivers/staging/ccree/cc_host_regs.h
new file mode 100644 (file)
index 0000000..69ef2fa
--- /dev/null
@@ -0,0 +1,142 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#ifndef __CC_HOST_H__
+#define __CC_HOST_H__
+
+// --------------------------------------
+// BLOCK: HOST_P
+// --------------------------------------
+#define CC_HOST_IRR_REG_OFFSET 0xA00UL
+#define CC_HOST_IRR_DSCRPTR_COMPLETION_LOW_INT_BIT_SHIFT       0x2UL
+#define CC_HOST_IRR_DSCRPTR_COMPLETION_LOW_INT_BIT_SIZE        0x1UL
+#define CC_HOST_IRR_AXI_ERR_INT_BIT_SHIFT      0x8UL
+#define CC_HOST_IRR_AXI_ERR_INT_BIT_SIZE       0x1UL
+#define CC_HOST_IRR_GPR0_BIT_SHIFT     0xBUL
+#define CC_HOST_IRR_GPR0_BIT_SIZE      0x1UL
+#define CC_HOST_IRR_DSCRPTR_WATERMARK_INT_BIT_SHIFT    0x13UL
+#define CC_HOST_IRR_DSCRPTR_WATERMARK_INT_BIT_SIZE     0x1UL
+#define CC_HOST_IRR_AXIM_COMP_INT_BIT_SHIFT    0x17UL
+#define CC_HOST_IRR_AXIM_COMP_INT_BIT_SIZE     0x1UL
+#define CC_HOST_IMR_REG_OFFSET 0xA04UL
+#define CC_HOST_IMR_NOT_USED_MASK_BIT_SHIFT    0x1UL
+#define CC_HOST_IMR_NOT_USED_MASK_BIT_SIZE     0x1UL
+#define CC_HOST_IMR_DSCRPTR_COMPLETION_MASK_BIT_SHIFT  0x2UL
+#define CC_HOST_IMR_DSCRPTR_COMPLETION_MASK_BIT_SIZE   0x1UL
+#define CC_HOST_IMR_AXI_ERR_MASK_BIT_SHIFT     0x8UL
+#define CC_HOST_IMR_AXI_ERR_MASK_BIT_SIZE      0x1UL
+#define CC_HOST_IMR_GPR0_BIT_SHIFT     0xBUL
+#define CC_HOST_IMR_GPR0_BIT_SIZE      0x1UL
+#define CC_HOST_IMR_DSCRPTR_WATERMARK_MASK0_BIT_SHIFT  0x13UL
+#define CC_HOST_IMR_DSCRPTR_WATERMARK_MASK0_BIT_SIZE   0x1UL
+#define CC_HOST_IMR_AXIM_COMP_INT_MASK_BIT_SHIFT       0x17UL
+#define CC_HOST_IMR_AXIM_COMP_INT_MASK_BIT_SIZE        0x1UL
+#define CC_HOST_ICR_REG_OFFSET 0xA08UL
+#define CC_HOST_ICR_DSCRPTR_COMPLETION_BIT_SHIFT       0x2UL
+#define CC_HOST_ICR_DSCRPTR_COMPLETION_BIT_SIZE        0x1UL
+#define CC_HOST_ICR_AXI_ERR_CLEAR_BIT_SHIFT    0x8UL
+#define CC_HOST_ICR_AXI_ERR_CLEAR_BIT_SIZE     0x1UL
+#define CC_HOST_ICR_GPR_INT_CLEAR_BIT_SHIFT    0xBUL
+#define CC_HOST_ICR_GPR_INT_CLEAR_BIT_SIZE     0x1UL
+#define CC_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SHIFT   0x13UL
+#define CC_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SIZE    0x1UL
+#define CC_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SHIFT      0x17UL
+#define CC_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SIZE       0x1UL
+#define CC_HOST_SIGNATURE_REG_OFFSET   0xA24UL
+#define CC_HOST_SIGNATURE_VALUE_BIT_SHIFT      0x0UL
+#define CC_HOST_SIGNATURE_VALUE_BIT_SIZE       0x20UL
+#define CC_HOST_BOOT_REG_OFFSET        0xA28UL
+#define CC_HOST_BOOT_SYNTHESIS_CONFIG_BIT_SHIFT        0x0UL
+#define CC_HOST_BOOT_SYNTHESIS_CONFIG_BIT_SIZE 0x1UL
+#define CC_HOST_BOOT_LARGE_RKEK_LOCAL_BIT_SHIFT        0x1UL
+#define CC_HOST_BOOT_LARGE_RKEK_LOCAL_BIT_SIZE 0x1UL
+#define CC_HOST_BOOT_HASH_IN_FUSES_LOCAL_BIT_SHIFT     0x2UL
+#define CC_HOST_BOOT_HASH_IN_FUSES_LOCAL_BIT_SIZE      0x1UL
+#define CC_HOST_BOOT_EXT_MEM_SECURED_LOCAL_BIT_SHIFT   0x3UL
+#define CC_HOST_BOOT_EXT_MEM_SECURED_LOCAL_BIT_SIZE    0x1UL
+#define CC_HOST_BOOT_RKEK_ECC_EXISTS_LOCAL_N_BIT_SHIFT 0x5UL
+#define CC_HOST_BOOT_RKEK_ECC_EXISTS_LOCAL_N_BIT_SIZE  0x1UL
+#define CC_HOST_BOOT_SRAM_SIZE_LOCAL_BIT_SHIFT 0x6UL
+#define CC_HOST_BOOT_SRAM_SIZE_LOCAL_BIT_SIZE  0x3UL
+#define CC_HOST_BOOT_DSCRPTR_EXISTS_LOCAL_BIT_SHIFT    0x9UL
+#define CC_HOST_BOOT_DSCRPTR_EXISTS_LOCAL_BIT_SIZE     0x1UL
+#define CC_HOST_BOOT_PAU_EXISTS_LOCAL_BIT_SHIFT        0xAUL
+#define CC_HOST_BOOT_PAU_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define CC_HOST_BOOT_RNG_EXISTS_LOCAL_BIT_SHIFT        0xBUL
+#define CC_HOST_BOOT_RNG_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define CC_HOST_BOOT_PKA_EXISTS_LOCAL_BIT_SHIFT        0xCUL
+#define CC_HOST_BOOT_PKA_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define CC_HOST_BOOT_RC4_EXISTS_LOCAL_BIT_SHIFT        0xDUL
+#define CC_HOST_BOOT_RC4_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define CC_HOST_BOOT_SHA_512_PRSNT_LOCAL_BIT_SHIFT     0xEUL
+#define CC_HOST_BOOT_SHA_512_PRSNT_LOCAL_BIT_SIZE      0x1UL
+#define CC_HOST_BOOT_SHA_256_PRSNT_LOCAL_BIT_SHIFT     0xFUL
+#define CC_HOST_BOOT_SHA_256_PRSNT_LOCAL_BIT_SIZE      0x1UL
+#define CC_HOST_BOOT_MD5_PRSNT_LOCAL_BIT_SHIFT 0x10UL
+#define CC_HOST_BOOT_MD5_PRSNT_LOCAL_BIT_SIZE  0x1UL
+#define CC_HOST_BOOT_HASH_EXISTS_LOCAL_BIT_SHIFT       0x11UL
+#define CC_HOST_BOOT_HASH_EXISTS_LOCAL_BIT_SIZE        0x1UL
+#define CC_HOST_BOOT_C2_EXISTS_LOCAL_BIT_SHIFT 0x12UL
+#define CC_HOST_BOOT_C2_EXISTS_LOCAL_BIT_SIZE  0x1UL
+#define CC_HOST_BOOT_DES_EXISTS_LOCAL_BIT_SHIFT        0x13UL
+#define CC_HOST_BOOT_DES_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define CC_HOST_BOOT_AES_XCBC_MAC_EXISTS_LOCAL_BIT_SHIFT       0x14UL
+#define CC_HOST_BOOT_AES_XCBC_MAC_EXISTS_LOCAL_BIT_SIZE        0x1UL
+#define CC_HOST_BOOT_AES_CMAC_EXISTS_LOCAL_BIT_SHIFT   0x15UL
+#define CC_HOST_BOOT_AES_CMAC_EXISTS_LOCAL_BIT_SIZE    0x1UL
+#define CC_HOST_BOOT_AES_CCM_EXISTS_LOCAL_BIT_SHIFT    0x16UL
+#define CC_HOST_BOOT_AES_CCM_EXISTS_LOCAL_BIT_SIZE     0x1UL
+#define CC_HOST_BOOT_AES_XEX_HW_T_CALC_LOCAL_BIT_SHIFT 0x17UL
+#define CC_HOST_BOOT_AES_XEX_HW_T_CALC_LOCAL_BIT_SIZE  0x1UL
+#define CC_HOST_BOOT_AES_XEX_EXISTS_LOCAL_BIT_SHIFT    0x18UL
+#define CC_HOST_BOOT_AES_XEX_EXISTS_LOCAL_BIT_SIZE     0x1UL
+#define CC_HOST_BOOT_CTR_EXISTS_LOCAL_BIT_SHIFT        0x19UL
+#define CC_HOST_BOOT_CTR_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define CC_HOST_BOOT_AES_DIN_BYTE_RESOLUTION_LOCAL_BIT_SHIFT   0x1AUL
+#define CC_HOST_BOOT_AES_DIN_BYTE_RESOLUTION_LOCAL_BIT_SIZE    0x1UL
+#define CC_HOST_BOOT_TUNNELING_ENB_LOCAL_BIT_SHIFT     0x1BUL
+#define CC_HOST_BOOT_TUNNELING_ENB_LOCAL_BIT_SIZE      0x1UL
+#define CC_HOST_BOOT_SUPPORT_256_192_KEY_LOCAL_BIT_SHIFT       0x1CUL
+#define CC_HOST_BOOT_SUPPORT_256_192_KEY_LOCAL_BIT_SIZE        0x1UL
+#define CC_HOST_BOOT_ONLY_ENCRYPT_LOCAL_BIT_SHIFT      0x1DUL
+#define CC_HOST_BOOT_ONLY_ENCRYPT_LOCAL_BIT_SIZE       0x1UL
+#define CC_HOST_BOOT_AES_EXISTS_LOCAL_BIT_SHIFT        0x1EUL
+#define CC_HOST_BOOT_AES_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define CC_HOST_VERSION_REG_OFFSET     0xA40UL
+#define CC_HOST_VERSION_VALUE_BIT_SHIFT        0x0UL
+#define CC_HOST_VERSION_VALUE_BIT_SIZE 0x20UL
+#define CC_HOST_KFDE0_VALID_REG_OFFSET 0xA60UL
+#define CC_HOST_KFDE0_VALID_VALUE_BIT_SHIFT    0x0UL
+#define CC_HOST_KFDE0_VALID_VALUE_BIT_SIZE     0x1UL
+#define CC_HOST_KFDE1_VALID_REG_OFFSET 0xA64UL
+#define CC_HOST_KFDE1_VALID_VALUE_BIT_SHIFT    0x0UL
+#define CC_HOST_KFDE1_VALID_VALUE_BIT_SIZE     0x1UL
+#define CC_HOST_KFDE2_VALID_REG_OFFSET 0xA68UL
+#define CC_HOST_KFDE2_VALID_VALUE_BIT_SHIFT    0x0UL
+#define CC_HOST_KFDE2_VALID_VALUE_BIT_SIZE     0x1UL
+#define CC_HOST_KFDE3_VALID_REG_OFFSET 0xA6CUL
+#define CC_HOST_KFDE3_VALID_VALUE_BIT_SHIFT    0x0UL
+#define CC_HOST_KFDE3_VALID_VALUE_BIT_SIZE     0x1UL
+#define CC_HOST_GPR0_REG_OFFSET        0xA70UL
+#define CC_HOST_GPR0_VALUE_BIT_SHIFT   0x0UL
+#define CC_HOST_GPR0_VALUE_BIT_SIZE    0x20UL
+#define CC_GPR_HOST_REG_OFFSET 0xA74UL
+#define CC_GPR_HOST_VALUE_BIT_SHIFT    0x0UL
+#define CC_GPR_HOST_VALUE_BIT_SIZE     0x20UL
+#define CC_HOST_POWER_DOWN_EN_REG_OFFSET       0xA78UL
+#define CC_HOST_POWER_DOWN_EN_VALUE_BIT_SHIFT  0x0UL
+#define CC_HOST_POWER_DOWN_EN_VALUE_BIT_SIZE   0x1UL
+// --------------------------------------
+// BLOCK: HOST_SRAM
+// --------------------------------------
+#define CC_SRAM_DATA_REG_OFFSET        0xF00UL
+#define CC_SRAM_DATA_VALUE_BIT_SHIFT   0x0UL
+#define CC_SRAM_DATA_VALUE_BIT_SIZE    0x20UL
+#define CC_SRAM_ADDR_REG_OFFSET        0xF04UL
+#define CC_SRAM_ADDR_VALUE_BIT_SHIFT   0x0UL
+#define CC_SRAM_ADDR_VALUE_BIT_SIZE    0xFUL
+#define CC_SRAM_DATA_READY_REG_OFFSET  0xF08UL
+#define CC_SRAM_DATA_READY_VALUE_BIT_SHIFT     0x0UL
+#define CC_SRAM_DATA_READY_VALUE_BIT_SIZE      0x1UL
+
+#endif //__CC_HOST_H__
index 2ae0f655e7a0e13c435597e5be17e985319b74d3..a79f28cec5ae87294c3314074416a4aa4be259a0 100644 (file)
@@ -1,25 +1,12 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
 
 #ifndef __CC_HW_QUEUE_DEFS_H__
 #define __CC_HW_QUEUE_DEFS_H__
 
 #include <linux/types.h>
 
-#include "dx_crys_kernel.h"
+#include "cc_kernel_regs.h"
 #include <linux/bitfield.h>
 
 /******************************************************************************
 /* Define max. available slots in HW queue */
 #define HW_QUEUE_SLOTS_MAX              15
 
-#define CC_REG_NAME(word, name) DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name
-
 #define CC_REG_LOW(word, name)  \
-       (DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name ## _BIT_SHIFT)
+       (CC_DSCRPTR_QUEUE_WORD ## word ## _ ## name ## _BIT_SHIFT)
 
 #define CC_REG_HIGH(word, name) \
        (CC_REG_LOW(word, name) + \
-        DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name ## _BIT_SIZE - 1)
+        CC_DSCRPTR_QUEUE_WORD ## word ## _ ## name ## _BIT_SIZE - 1)
 
 #define CC_GENMASK(word, name) \
        GENMASK(CC_REG_HIGH(word, name), CC_REG_LOW(word, name))
@@ -122,7 +107,6 @@ enum cc_flow_mode {
        AES_to_AES_to_HASH_and_DOUT     = 13,
        AES_to_AES_to_HASH      = 14,
        AES_to_HASH_and_AES     = 15,
-       DIN_MULTI2_DOUT         = 16,
        DIN_AES_AESMAC          = 17,
        HASH_to_DOUT            = 18,
        /* setup flows */
@@ -130,7 +114,6 @@ enum cc_flow_mode {
        S_DIN_to_AES2           = 33,
        S_DIN_to_DES            = 34,
        S_DIN_to_RC4            = 35,
-       S_DIN_to_MULTI2         = 36,
        S_DIN_to_HASH           = 37,
        S_AES_to_DOUT           = 38,
        S_AES2_to_DOUT          = 39,
@@ -203,6 +186,19 @@ enum cc_hw_des_key_size {
        END_OF_DES_KEYS = S32_MAX,
 };
 
+enum cc_hash_conf_pad {
+       HASH_PADDING_DISABLED = 0,
+       HASH_PADDING_ENABLED = 1,
+       HASH_DIGEST_RESULT_LITTLE_ENDIAN = 2,
+       HASH_CONFIG1_PADDING_RESERVE32 = S32_MAX,
+};
+
+enum cc_hash_cipher_pad {
+       DO_NOT_PAD = 0,
+       DO_PAD = 1,
+       HASH_CIPHER_DO_PADDING_RESERVE32 = S32_MAX,
+};
+
 /*****************************/
 /* Descriptor packing macros */
 /*****************************/
diff --git a/drivers/staging/ccree/cc_ivgen.c b/drivers/staging/ccree/cc_ivgen.c
new file mode 100644 (file)
index 0000000..c47f419
--- /dev/null
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <crypto/ctr.h>
+#include "cc_driver.h"
+#include "cc_ivgen.h"
+#include "cc_request_mgr.h"
+#include "cc_sram_mgr.h"
+#include "cc_buffer_mgr.h"
+
+/* The max. size of pool *MUST* be <= SRAM total size */
+#define CC_IVPOOL_SIZE 1024
+/* The first 32B fraction of pool are dedicated to the
+ * next encryption "key" & "IV" for pool regeneration
+ */
+#define CC_IVPOOL_META_SIZE (CC_AES_IV_SIZE + AES_KEYSIZE_128)
+#define CC_IVPOOL_GEN_SEQ_LEN  4
+
+/**
+ * struct cc_ivgen_ctx -IV pool generation context
+ * @pool:          the start address of the iv-pool resides in internal RAM
+ * @ctr_key_dma:   address of pool's encryption key material in internal RAM
+ * @ctr_iv_dma:    address of pool's counter iv in internal RAM
+ * @next_iv_ofs:   the offset to the next available IV in pool
+ * @pool_meta:     virt. address of the initial enc. key/IV
+ * @pool_meta_dma: phys. address of the initial enc. key/IV
+ */
+struct cc_ivgen_ctx {
+       cc_sram_addr_t pool;
+       cc_sram_addr_t ctr_key;
+       cc_sram_addr_t ctr_iv;
+       u32 next_iv_ofs;
+       u8 *pool_meta;
+       dma_addr_t pool_meta_dma;
+};
+
+/*!
+ * Generates CC_IVPOOL_SIZE of random bytes by
+ * encrypting 0's using AES128-CTR.
+ *
+ * \param ivgen iv-pool context
+ * \param iv_seq IN/OUT array to the descriptors sequence
+ * \param iv_seq_len IN/OUT pointer to the sequence length
+ */
+static int cc_gen_iv_pool(struct cc_ivgen_ctx *ivgen_ctx,
+                         struct cc_hw_desc iv_seq[], unsigned int *iv_seq_len)
+{
+       unsigned int idx = *iv_seq_len;
+
+       if ((*iv_seq_len + CC_IVPOOL_GEN_SEQ_LEN) > CC_IVPOOL_SEQ_LEN) {
+               /* The sequence will be longer than allowed */
+               return -EINVAL;
+       }
+       /* Setup key */
+       hw_desc_init(&iv_seq[idx]);
+       set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_key, AES_KEYSIZE_128);
+       set_setup_mode(&iv_seq[idx], SETUP_LOAD_KEY0);
+       set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_flow_mode(&iv_seq[idx], S_DIN_to_AES);
+       set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR);
+       idx++;
+
+       /* Setup cipher state */
+       hw_desc_init(&iv_seq[idx]);
+       set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_iv, CC_AES_IV_SIZE);
+       set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+       set_flow_mode(&iv_seq[idx], S_DIN_to_AES);
+       set_setup_mode(&iv_seq[idx], SETUP_LOAD_STATE1);
+       set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
+       set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR);
+       idx++;
+
+       /* Perform dummy encrypt to skip first block */
+       hw_desc_init(&iv_seq[idx]);
+       set_din_const(&iv_seq[idx], 0, CC_AES_IV_SIZE);
+       set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, CC_AES_IV_SIZE);
+       set_flow_mode(&iv_seq[idx], DIN_AES_DOUT);
+       idx++;
+
+       /* Generate IV pool */
+       hw_desc_init(&iv_seq[idx]);
+       set_din_const(&iv_seq[idx], 0, CC_IVPOOL_SIZE);
+       set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, CC_IVPOOL_SIZE);
+       set_flow_mode(&iv_seq[idx], DIN_AES_DOUT);
+       idx++;
+
+       *iv_seq_len = idx; /* Update sequence length */
+
+       /* queue ordering assures pool readiness */
+       ivgen_ctx->next_iv_ofs = CC_IVPOOL_META_SIZE;
+
+       return 0;
+}
+
+/*!
+ * Generates the initial pool in SRAM.
+ * This function should be invoked when resuming DX driver.
+ *
+ * \param drvdata
+ *
+ * \return int Zero for success, negative value otherwise.
+ */
+int cc_init_iv_sram(struct cc_drvdata *drvdata)
+{
+       struct cc_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
+       struct cc_hw_desc iv_seq[CC_IVPOOL_SEQ_LEN];
+       unsigned int iv_seq_len = 0;
+       int rc;
+
+       /* Generate initial enc. key/iv */
+       get_random_bytes(ivgen_ctx->pool_meta, CC_IVPOOL_META_SIZE);
+
+       /* The first 32B reserved for the enc. Key/IV */
+       ivgen_ctx->ctr_key = ivgen_ctx->pool;
+       ivgen_ctx->ctr_iv = ivgen_ctx->pool + AES_KEYSIZE_128;
+
+       /* Copy initial enc. key and IV to SRAM at a single descriptor */
+       hw_desc_init(&iv_seq[iv_seq_len]);
+       set_din_type(&iv_seq[iv_seq_len], DMA_DLLI, ivgen_ctx->pool_meta_dma,
+                    CC_IVPOOL_META_SIZE, NS_BIT);
+       set_dout_sram(&iv_seq[iv_seq_len], ivgen_ctx->pool,
+                     CC_IVPOOL_META_SIZE);
+       set_flow_mode(&iv_seq[iv_seq_len], BYPASS);
+       iv_seq_len++;
+
+       /* Generate initial pool */
+       rc = cc_gen_iv_pool(ivgen_ctx, iv_seq, &iv_seq_len);
+       if (rc)
+               return rc;
+
+       /* Fire-and-forget */
+       return send_request_init(drvdata, iv_seq, iv_seq_len);
+}
+
+/*!
+ * Free iv-pool and ivgen context.
+ *
+ * \param drvdata
+ */
+void cc_ivgen_fini(struct cc_drvdata *drvdata)
+{
+       struct cc_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
+       struct device *device = &drvdata->plat_dev->dev;
+
+       if (!ivgen_ctx)
+               return;
+
+       if (ivgen_ctx->pool_meta) {
+               memset(ivgen_ctx->pool_meta, 0, CC_IVPOOL_META_SIZE);
+               dma_free_coherent(device, CC_IVPOOL_META_SIZE,
+                                 ivgen_ctx->pool_meta,
+                                 ivgen_ctx->pool_meta_dma);
+       }
+
+       ivgen_ctx->pool = NULL_SRAM_ADDR;
+
+       /* release "this" context */
+       kfree(ivgen_ctx);
+}
+
+/*!
+ * Allocates iv-pool and maps resources.
+ * This function generates the first IV pool.
+ *
+ * \param drvdata Driver's private context
+ *
+ * \return int Zero for success, negative value otherwise.
+ */
+int cc_ivgen_init(struct cc_drvdata *drvdata)
+{
+       struct cc_ivgen_ctx *ivgen_ctx;
+       struct device *device = &drvdata->plat_dev->dev;
+       int rc;
+
+       /* Allocate "this" context */
+       ivgen_ctx = kzalloc(sizeof(*ivgen_ctx), GFP_KERNEL);
+       if (!ivgen_ctx)
+               return -ENOMEM;
+
+       drvdata->ivgen_handle = ivgen_ctx;
+
+       /* Allocate pool's header for initial enc. key/IV */
+       ivgen_ctx->pool_meta = dma_alloc_coherent(device, CC_IVPOOL_META_SIZE,
+                                                 &ivgen_ctx->pool_meta_dma,
+                                                 GFP_KERNEL);
+       if (!ivgen_ctx->pool_meta) {
+               dev_err(device, "Not enough memory to allocate DMA of pool_meta (%u B)\n",
+                       CC_IVPOOL_META_SIZE);
+               rc = -ENOMEM;
+               goto out;
+       }
+       /* Allocate IV pool in SRAM */
+       ivgen_ctx->pool = cc_sram_alloc(drvdata, CC_IVPOOL_SIZE);
+       if (ivgen_ctx->pool == NULL_SRAM_ADDR) {
+               dev_err(device, "SRAM pool exhausted\n");
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       return cc_init_iv_sram(drvdata);
+
+out:
+       cc_ivgen_fini(drvdata);
+       return rc;
+}
+
+/*!
+ * Acquires 16 Bytes IV from the iv-pool
+ *
+ * \param drvdata Driver private context
+ * \param iv_out_dma Array of physical IV out addresses
+ * \param iv_out_dma_len Length of iv_out_dma array (additional elements
+ *                       of iv_out_dma array are ignore)
+ * \param iv_out_size May be 8 or 16 bytes long
+ * \param iv_seq IN/OUT array to the descriptors sequence
+ * \param iv_seq_len IN/OUT pointer to the sequence length
+ *
+ * \return int Zero for success, negative value otherwise.
+ */
+int cc_get_iv(struct cc_drvdata *drvdata, dma_addr_t iv_out_dma[],
+             unsigned int iv_out_dma_len, unsigned int iv_out_size,
+             struct cc_hw_desc iv_seq[], unsigned int *iv_seq_len)
+{
+       struct cc_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
+       unsigned int idx = *iv_seq_len;
+       struct device *dev = drvdata_to_dev(drvdata);
+       unsigned int t;
+
+       if (iv_out_size != CC_AES_IV_SIZE &&
+           iv_out_size != CTR_RFC3686_IV_SIZE) {
+               return -EINVAL;
+       }
+       if ((iv_out_dma_len + 1) > CC_IVPOOL_SEQ_LEN) {
+               /* The sequence will be longer than allowed */
+               return -EINVAL;
+       }
+
+       /* check that number of generated IV is limited to max dma address
+        * iv buffer size
+        */
+       if (iv_out_dma_len > CC_MAX_IVGEN_DMA_ADDRESSES) {
+               /* The sequence will be longer than allowed */
+               return -EINVAL;
+       }
+
+       for (t = 0; t < iv_out_dma_len; t++) {
+               /* Acquire IV from pool */
+               hw_desc_init(&iv_seq[idx]);
+               set_din_sram(&iv_seq[idx], (ivgen_ctx->pool +
+                                           ivgen_ctx->next_iv_ofs),
+                            iv_out_size);
+               set_dout_dlli(&iv_seq[idx], iv_out_dma[t], iv_out_size,
+                             NS_BIT, 0);
+               set_flow_mode(&iv_seq[idx], BYPASS);
+               idx++;
+       }
+
+       /* Bypass operation is proceeded by crypto sequence, hence must
+        *  assure bypass-write-transaction by a memory barrier
+        */
+       hw_desc_init(&iv_seq[idx]);
+       set_din_no_dma(&iv_seq[idx], 0, 0xfffff0);
+       set_dout_no_dma(&iv_seq[idx], 0, 0, 1);
+       idx++;
+
+       *iv_seq_len = idx; /* update seq length */
+
+       /* Update iv index */
+       ivgen_ctx->next_iv_ofs += iv_out_size;
+
+       if ((CC_IVPOOL_SIZE - ivgen_ctx->next_iv_ofs) < CC_AES_IV_SIZE) {
+               dev_dbg(dev, "Pool exhausted, regenerating iv-pool\n");
+               /* pool is drained -regenerate it! */
+               return cc_gen_iv_pool(ivgen_ctx, iv_seq, iv_seq_len);
+       }
+
+       return 0;
+}
+
diff --git a/drivers/staging/ccree/cc_ivgen.h b/drivers/staging/ccree/cc_ivgen.h
new file mode 100644 (file)
index 0000000..b6ac169
--- /dev/null
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#ifndef __CC_IVGEN_H__
+#define __CC_IVGEN_H__
+
+#include "cc_hw_queue_defs.h"
+
+#define CC_IVPOOL_SEQ_LEN 8
+
+/*!
+ * Allocates iv-pool and maps resources.
+ * This function generates the first IV pool.
+ *
+ * \param drvdata Driver's private context
+ *
+ * \return int Zero for success, negative value otherwise.
+ */
+int cc_ivgen_init(struct cc_drvdata *drvdata);
+
+/*!
+ * Free iv-pool and ivgen context.
+ *
+ * \param drvdata
+ */
+void cc_ivgen_fini(struct cc_drvdata *drvdata);
+
+/*!
+ * Generates the initial pool in SRAM.
+ * This function should be invoked when resuming DX driver.
+ *
+ * \param drvdata
+ *
+ * \return int Zero for success, negative value otherwise.
+ */
+int cc_init_iv_sram(struct cc_drvdata *drvdata);
+
+/*!
+ * Acquires 16 Bytes IV from the iv-pool
+ *
+ * \param drvdata Driver private context
+ * \param iv_out_dma Array of physical IV out addresses
+ * \param iv_out_dma_len Length of iv_out_dma array (additional elements of
+ *                       iv_out_dma array are ignore)
+ * \param iv_out_size May be 8 or 16 bytes long
+ * \param iv_seq IN/OUT array to the descriptors sequence
+ * \param iv_seq_len IN/OUT pointer to the sequence length
+ *
+ * \return int Zero for success, negative value otherwise.
+ */
+int cc_get_iv(struct cc_drvdata *drvdata, dma_addr_t iv_out_dma[],
+             unsigned int iv_out_dma_len, unsigned int iv_out_size,
+             struct cc_hw_desc iv_seq[], unsigned int *iv_seq_len);
+
+#endif /*__CC_IVGEN_H__*/
diff --git a/drivers/staging/ccree/cc_kernel_regs.h b/drivers/staging/ccree/cc_kernel_regs.h
new file mode 100644 (file)
index 0000000..fa99440
--- /dev/null
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#ifndef __CC_CRYS_KERNEL_H__
+#define __CC_CRYS_KERNEL_H__
+
+// --------------------------------------
+// BLOCK: DSCRPTR
+// --------------------------------------
+#define CC_DSCRPTR_COMPLETION_COUNTER_REG_OFFSET       0xE00UL
+#define CC_DSCRPTR_COMPLETION_COUNTER_COMPLETION_COUNTER_BIT_SHIFT     0x0UL
+#define CC_DSCRPTR_COMPLETION_COUNTER_COMPLETION_COUNTER_BIT_SIZE      0x6UL
+#define CC_DSCRPTR_COMPLETION_COUNTER_OVERFLOW_COUNTER_BIT_SHIFT       0x6UL
+#define CC_DSCRPTR_COMPLETION_COUNTER_OVERFLOW_COUNTER_BIT_SIZE        0x1UL
+#define CC_DSCRPTR_SW_RESET_REG_OFFSET 0xE40UL
+#define CC_DSCRPTR_SW_RESET_VALUE_BIT_SHIFT    0x0UL
+#define CC_DSCRPTR_SW_RESET_VALUE_BIT_SIZE     0x1UL
+#define CC_DSCRPTR_QUEUE_SRAM_SIZE_REG_OFFSET  0xE60UL
+#define CC_DSCRPTR_QUEUE_SRAM_SIZE_NUM_OF_DSCRPTR_BIT_SHIFT    0x0UL
+#define CC_DSCRPTR_QUEUE_SRAM_SIZE_NUM_OF_DSCRPTR_BIT_SIZE     0xAUL
+#define CC_DSCRPTR_QUEUE_SRAM_SIZE_DSCRPTR_SRAM_SIZE_BIT_SHIFT 0xAUL
+#define CC_DSCRPTR_QUEUE_SRAM_SIZE_DSCRPTR_SRAM_SIZE_BIT_SIZE  0xCUL
+#define CC_DSCRPTR_QUEUE_SRAM_SIZE_SRAM_SIZE_BIT_SHIFT 0x16UL
+#define CC_DSCRPTR_QUEUE_SRAM_SIZE_SRAM_SIZE_BIT_SIZE  0x3UL
+#define CC_DSCRPTR_SINGLE_ADDR_EN_REG_OFFSET   0xE64UL
+#define CC_DSCRPTR_SINGLE_ADDR_EN_VALUE_BIT_SHIFT      0x0UL
+#define CC_DSCRPTR_SINGLE_ADDR_EN_VALUE_BIT_SIZE       0x1UL
+#define CC_DSCRPTR_MEASURE_CNTR_REG_OFFSET     0xE68UL
+#define CC_DSCRPTR_MEASURE_CNTR_VALUE_BIT_SHIFT        0x0UL
+#define CC_DSCRPTR_MEASURE_CNTR_VALUE_BIT_SIZE 0x20UL
+#define CC_DSCRPTR_QUEUE_WORD0_REG_OFFSET      0xE80UL
+#define CC_DSCRPTR_QUEUE_WORD0_VALUE_BIT_SHIFT 0x0UL
+#define CC_DSCRPTR_QUEUE_WORD0_VALUE_BIT_SIZE  0x20UL
+#define CC_DSCRPTR_QUEUE_WORD1_REG_OFFSET      0xE84UL
+#define CC_DSCRPTR_QUEUE_WORD1_DIN_DMA_MODE_BIT_SHIFT  0x0UL
+#define CC_DSCRPTR_QUEUE_WORD1_DIN_DMA_MODE_BIT_SIZE   0x2UL
+#define CC_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SHIFT      0x2UL
+#define CC_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SIZE       0x18UL
+#define CC_DSCRPTR_QUEUE_WORD1_NS_BIT_BIT_SHIFT        0x1AUL
+#define CC_DSCRPTR_QUEUE_WORD1_NS_BIT_BIT_SIZE 0x1UL
+#define CC_DSCRPTR_QUEUE_WORD1_DIN_CONST_VALUE_BIT_SHIFT       0x1BUL
+#define CC_DSCRPTR_QUEUE_WORD1_DIN_CONST_VALUE_BIT_SIZE        0x1UL
+#define CC_DSCRPTR_QUEUE_WORD1_NOT_LAST_BIT_SHIFT      0x1CUL
+#define CC_DSCRPTR_QUEUE_WORD1_NOT_LAST_BIT_SIZE       0x1UL
+#define CC_DSCRPTR_QUEUE_WORD1_LOCK_QUEUE_BIT_SHIFT    0x1DUL
+#define CC_DSCRPTR_QUEUE_WORD1_LOCK_QUEUE_BIT_SIZE     0x1UL
+#define CC_DSCRPTR_QUEUE_WORD1_NOT_USED_BIT_SHIFT      0x1EUL
+#define CC_DSCRPTR_QUEUE_WORD1_NOT_USED_BIT_SIZE       0x2UL
+#define CC_DSCRPTR_QUEUE_WORD2_REG_OFFSET      0xE88UL
+#define CC_DSCRPTR_QUEUE_WORD2_VALUE_BIT_SHIFT 0x0UL
+#define CC_DSCRPTR_QUEUE_WORD2_VALUE_BIT_SIZE  0x20UL
+#define CC_DSCRPTR_QUEUE_WORD3_REG_OFFSET      0xE8CUL
+#define CC_DSCRPTR_QUEUE_WORD3_DOUT_DMA_MODE_BIT_SHIFT 0x0UL
+#define CC_DSCRPTR_QUEUE_WORD3_DOUT_DMA_MODE_BIT_SIZE  0x2UL
+#define CC_DSCRPTR_QUEUE_WORD3_DOUT_SIZE_BIT_SHIFT     0x2UL
+#define CC_DSCRPTR_QUEUE_WORD3_DOUT_SIZE_BIT_SIZE      0x18UL
+#define CC_DSCRPTR_QUEUE_WORD3_NS_BIT_BIT_SHIFT        0x1AUL
+#define CC_DSCRPTR_QUEUE_WORD3_NS_BIT_BIT_SIZE 0x1UL
+#define CC_DSCRPTR_QUEUE_WORD3_DOUT_LAST_IND_BIT_SHIFT 0x1BUL
+#define CC_DSCRPTR_QUEUE_WORD3_DOUT_LAST_IND_BIT_SIZE  0x1UL
+#define CC_DSCRPTR_QUEUE_WORD3_HASH_XOR_BIT_BIT_SHIFT  0x1DUL
+#define CC_DSCRPTR_QUEUE_WORD3_HASH_XOR_BIT_BIT_SIZE   0x1UL
+#define CC_DSCRPTR_QUEUE_WORD3_NOT_USED_BIT_SHIFT      0x1EUL
+#define CC_DSCRPTR_QUEUE_WORD3_NOT_USED_BIT_SIZE       0x1UL
+#define CC_DSCRPTR_QUEUE_WORD3_QUEUE_LAST_IND_BIT_SHIFT        0x1FUL
+#define CC_DSCRPTR_QUEUE_WORD3_QUEUE_LAST_IND_BIT_SIZE 0x1UL
+#define CC_DSCRPTR_QUEUE_WORD4_REG_OFFSET      0xE90UL
+#define CC_DSCRPTR_QUEUE_WORD4_DATA_FLOW_MODE_BIT_SHIFT        0x0UL
+#define CC_DSCRPTR_QUEUE_WORD4_DATA_FLOW_MODE_BIT_SIZE 0x6UL
+#define CC_DSCRPTR_QUEUE_WORD4_AES_SEL_N_HASH_BIT_SHIFT        0x6UL
+#define CC_DSCRPTR_QUEUE_WORD4_AES_SEL_N_HASH_BIT_SIZE 0x1UL
+#define CC_DSCRPTR_QUEUE_WORD4_AES_XOR_CRYPTO_KEY_BIT_SHIFT    0x7UL
+#define CC_DSCRPTR_QUEUE_WORD4_AES_XOR_CRYPTO_KEY_BIT_SIZE     0x1UL
+#define CC_DSCRPTR_QUEUE_WORD4_ACK_NEEDED_BIT_SHIFT    0x8UL
+#define CC_DSCRPTR_QUEUE_WORD4_ACK_NEEDED_BIT_SIZE     0x2UL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_MODE_BIT_SHIFT   0xAUL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_MODE_BIT_SIZE    0x4UL
+#define CC_DSCRPTR_QUEUE_WORD4_CMAC_SIZE0_BIT_SHIFT    0xEUL
+#define CC_DSCRPTR_QUEUE_WORD4_CMAC_SIZE0_BIT_SIZE     0x1UL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_DO_BIT_SHIFT     0xFUL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_DO_BIT_SIZE      0x2UL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_CONF0_BIT_SHIFT  0x11UL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_CONF0_BIT_SIZE   0x2UL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_CONF1_BIT_SHIFT  0x13UL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_CONF1_BIT_SIZE   0x1UL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_CONF2_BIT_SHIFT  0x14UL
+#define CC_DSCRPTR_QUEUE_WORD4_CIPHER_CONF2_BIT_SIZE   0x2UL
+#define CC_DSCRPTR_QUEUE_WORD4_KEY_SIZE_BIT_SHIFT      0x16UL
+#define CC_DSCRPTR_QUEUE_WORD4_KEY_SIZE_BIT_SIZE       0x2UL
+#define CC_DSCRPTR_QUEUE_WORD4_SETUP_OPERATION_BIT_SHIFT       0x18UL
+#define CC_DSCRPTR_QUEUE_WORD4_SETUP_OPERATION_BIT_SIZE        0x4UL
+#define CC_DSCRPTR_QUEUE_WORD4_DIN_SRAM_ENDIANNESS_BIT_SHIFT   0x1CUL
+#define CC_DSCRPTR_QUEUE_WORD4_DIN_SRAM_ENDIANNESS_BIT_SIZE    0x1UL
+#define CC_DSCRPTR_QUEUE_WORD4_DOUT_SRAM_ENDIANNESS_BIT_SHIFT  0x1DUL
+#define CC_DSCRPTR_QUEUE_WORD4_DOUT_SRAM_ENDIANNESS_BIT_SIZE   0x1UL
+#define CC_DSCRPTR_QUEUE_WORD4_WORD_SWAP_BIT_SHIFT     0x1EUL
+#define CC_DSCRPTR_QUEUE_WORD4_WORD_SWAP_BIT_SIZE      0x1UL
+#define CC_DSCRPTR_QUEUE_WORD4_BYTES_SWAP_BIT_SHIFT    0x1FUL
+#define CC_DSCRPTR_QUEUE_WORD4_BYTES_SWAP_BIT_SIZE     0x1UL
+#define CC_DSCRPTR_QUEUE_WORD5_REG_OFFSET      0xE94UL
+#define CC_DSCRPTR_QUEUE_WORD5_DIN_ADDR_HIGH_BIT_SHIFT 0x0UL
+#define CC_DSCRPTR_QUEUE_WORD5_DIN_ADDR_HIGH_BIT_SIZE  0x10UL
+#define CC_DSCRPTR_QUEUE_WORD5_DOUT_ADDR_HIGH_BIT_SHIFT        0x10UL
+#define CC_DSCRPTR_QUEUE_WORD5_DOUT_ADDR_HIGH_BIT_SIZE 0x10UL
+#define CC_DSCRPTR_QUEUE_WATERMARK_REG_OFFSET  0xE98UL
+#define CC_DSCRPTR_QUEUE_WATERMARK_VALUE_BIT_SHIFT     0x0UL
+#define CC_DSCRPTR_QUEUE_WATERMARK_VALUE_BIT_SIZE      0xAUL
+#define CC_DSCRPTR_QUEUE_CONTENT_REG_OFFSET    0xE9CUL
+#define CC_DSCRPTR_QUEUE_CONTENT_VALUE_BIT_SHIFT       0x0UL
+#define CC_DSCRPTR_QUEUE_CONTENT_VALUE_BIT_SIZE        0xAUL
+// --------------------------------------
+// BLOCK: AXI_P
+// --------------------------------------
+#define CC_AXIM_MON_INFLIGHT_REG_OFFSET        0xB00UL
+#define CC_AXIM_MON_INFLIGHT_VALUE_BIT_SHIFT   0x0UL
+#define CC_AXIM_MON_INFLIGHT_VALUE_BIT_SIZE    0x8UL
+#define CC_AXIM_MON_INFLIGHTLAST_REG_OFFSET    0xB40UL
+#define CC_AXIM_MON_INFLIGHTLAST_VALUE_BIT_SHIFT       0x0UL
+#define CC_AXIM_MON_INFLIGHTLAST_VALUE_BIT_SIZE        0x8UL
+#define CC_AXIM_MON_COMP_REG_OFFSET    0xB80UL
+#define CC_AXIM_MON_COMP_VALUE_BIT_SHIFT       0x0UL
+#define CC_AXIM_MON_COMP_VALUE_BIT_SIZE        0x10UL
+#define CC_AXIM_MON_ERR_REG_OFFSET     0xBC4UL
+#define CC_AXIM_MON_ERR_BRESP_BIT_SHIFT        0x0UL
+#define CC_AXIM_MON_ERR_BRESP_BIT_SIZE 0x2UL
+#define CC_AXIM_MON_ERR_BID_BIT_SHIFT  0x2UL
+#define CC_AXIM_MON_ERR_BID_BIT_SIZE   0x4UL
+#define CC_AXIM_MON_ERR_RRESP_BIT_SHIFT        0x10UL
+#define CC_AXIM_MON_ERR_RRESP_BIT_SIZE 0x2UL
+#define CC_AXIM_MON_ERR_RID_BIT_SHIFT  0x12UL
+#define CC_AXIM_MON_ERR_RID_BIT_SIZE   0x4UL
+#define CC_AXIM_CFG_REG_OFFSET 0xBE8UL
+#define CC_AXIM_CFG_BRESPMASK_BIT_SHIFT        0x4UL
+#define CC_AXIM_CFG_BRESPMASK_BIT_SIZE 0x1UL
+#define CC_AXIM_CFG_RRESPMASK_BIT_SHIFT        0x5UL
+#define CC_AXIM_CFG_RRESPMASK_BIT_SIZE 0x1UL
+#define CC_AXIM_CFG_INFLTMASK_BIT_SHIFT        0x6UL
+#define CC_AXIM_CFG_INFLTMASK_BIT_SIZE 0x1UL
+#define CC_AXIM_CFG_COMPMASK_BIT_SHIFT 0x7UL
+#define CC_AXIM_CFG_COMPMASK_BIT_SIZE  0x1UL
+#define CC_AXIM_ACE_CONST_REG_OFFSET   0xBECUL
+#define CC_AXIM_ACE_CONST_ARDOMAIN_BIT_SHIFT   0x0UL
+#define CC_AXIM_ACE_CONST_ARDOMAIN_BIT_SIZE    0x2UL
+#define CC_AXIM_ACE_CONST_AWDOMAIN_BIT_SHIFT   0x2UL
+#define CC_AXIM_ACE_CONST_AWDOMAIN_BIT_SIZE    0x2UL
+#define CC_AXIM_ACE_CONST_ARBAR_BIT_SHIFT      0x4UL
+#define CC_AXIM_ACE_CONST_ARBAR_BIT_SIZE       0x2UL
+#define CC_AXIM_ACE_CONST_AWBAR_BIT_SHIFT      0x6UL
+#define CC_AXIM_ACE_CONST_AWBAR_BIT_SIZE       0x2UL
+#define CC_AXIM_ACE_CONST_ARSNOOP_BIT_SHIFT    0x8UL
+#define CC_AXIM_ACE_CONST_ARSNOOP_BIT_SIZE     0x4UL
+#define CC_AXIM_ACE_CONST_AWSNOOP_NOT_ALIGNED_BIT_SHIFT        0xCUL
+#define CC_AXIM_ACE_CONST_AWSNOOP_NOT_ALIGNED_BIT_SIZE 0x3UL
+#define CC_AXIM_ACE_CONST_AWSNOOP_ALIGNED_BIT_SHIFT    0xFUL
+#define CC_AXIM_ACE_CONST_AWSNOOP_ALIGNED_BIT_SIZE     0x3UL
+#define CC_AXIM_ACE_CONST_AWADDR_NOT_MASKED_BIT_SHIFT  0x12UL
+#define CC_AXIM_ACE_CONST_AWADDR_NOT_MASKED_BIT_SIZE   0x7UL
+#define CC_AXIM_ACE_CONST_AWLEN_VAL_BIT_SHIFT  0x19UL
+#define CC_AXIM_ACE_CONST_AWLEN_VAL_BIT_SIZE   0x4UL
+#define CC_AXIM_CACHE_PARAMS_REG_OFFSET        0xBF0UL
+#define CC_AXIM_CACHE_PARAMS_AWCACHE_LAST_BIT_SHIFT    0x0UL
+#define CC_AXIM_CACHE_PARAMS_AWCACHE_LAST_BIT_SIZE     0x4UL
+#define CC_AXIM_CACHE_PARAMS_AWCACHE_BIT_SHIFT 0x4UL
+#define CC_AXIM_CACHE_PARAMS_AWCACHE_BIT_SIZE  0x4UL
+#define CC_AXIM_CACHE_PARAMS_ARCACHE_BIT_SHIFT 0x8UL
+#define CC_AXIM_CACHE_PARAMS_ARCACHE_BIT_SIZE  0x4UL
+#endif // __CC_CRYS_KERNEL_H__
index a9c417b07b0429800d58982c67fced9ad0c35267..64b15ac9f1d3bb0fa5370e4d178382ec93f7a0b3 100644 (file)
@@ -1,18 +1,5 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
 
 #ifndef _CC_LLI_DEFS_H_
 #define _CC_LLI_DEFS_H_
@@ -20,7 +7,7 @@
 #include <linux/types.h>
 
 /* Max DLLI size
- *  AKA DX_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SIZE
+ *  AKA CC_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SIZE
  */
 #define DLLI_SIZE_BIT_SIZE     0x18
 
diff --git a/drivers/staging/ccree/cc_pm.c b/drivers/staging/ccree/cc_pm.c
new file mode 100644 (file)
index 0000000..d990f47
--- /dev/null
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include "cc_driver.h"
+#include "cc_buffer_mgr.h"
+#include "cc_request_mgr.h"
+#include "cc_sram_mgr.h"
+#include "cc_ivgen.h"
+#include "cc_hash.h"
+#include "cc_pm.h"
+
+#define POWER_DOWN_ENABLE 0x01
+#define POWER_DOWN_DISABLE 0x00
+
+const struct dev_pm_ops ccree_pm = {
+       SET_RUNTIME_PM_OPS(cc_pm_suspend, cc_pm_resume, NULL)
+};
+
+int cc_pm_suspend(struct device *dev)
+{
+       struct cc_drvdata *drvdata = dev_get_drvdata(dev);
+       int rc;
+
+       dev_dbg(dev, "set HOST_POWER_DOWN_EN\n");
+       cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_ENABLE);
+       rc = cc_suspend_req_queue(drvdata);
+       if (rc) {
+               dev_err(dev, "cc_suspend_req_queue (%x)\n", rc);
+               return rc;
+       }
+       fini_cc_regs(drvdata);
+       cc_clk_off(drvdata);
+       return 0;
+}
+
+int cc_pm_resume(struct device *dev)
+{
+       int rc;
+       struct cc_drvdata *drvdata = dev_get_drvdata(dev);
+
+       dev_dbg(dev, "unset HOST_POWER_DOWN_EN\n");
+       cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE);
+
+       rc = cc_clk_on(drvdata);
+       if (rc) {
+               dev_err(dev, "failed getting clock back on. We're toast.\n");
+               return rc;
+       }
+
+       rc = init_cc_regs(drvdata, false);
+       if (rc) {
+               dev_err(dev, "init_cc_regs (%x)\n", rc);
+               return rc;
+       }
+
+       rc = cc_resume_req_queue(drvdata);
+       if (rc) {
+               dev_err(dev, "cc_resume_req_queue (%x)\n", rc);
+               return rc;
+       }
+
+       /* must be after the queue resuming as it uses the HW queue*/
+       cc_init_hash_sram(drvdata);
+
+       cc_init_iv_sram(drvdata);
+       return 0;
+}
+
+int cc_pm_get(struct device *dev)
+{
+       int rc = 0;
+       struct cc_drvdata *drvdata = dev_get_drvdata(dev);
+
+       if (cc_req_queue_suspended(drvdata))
+               rc = pm_runtime_get_sync(dev);
+       else
+               pm_runtime_get_noresume(dev);
+
+       return rc;
+}
+
+int cc_pm_put_suspend(struct device *dev)
+{
+       int rc = 0;
+       struct cc_drvdata *drvdata = dev_get_drvdata(dev);
+
+       if (!cc_req_queue_suspended(drvdata)) {
+               pm_runtime_mark_last_busy(dev);
+               rc = pm_runtime_put_autosuspend(dev);
+       } else {
+               /* Something wrong happens*/
+               dev_err(dev, "request to suspend already suspended queue");
+               rc = -EBUSY;
+       }
+       return rc;
+}
+
+int cc_pm_init(struct cc_drvdata *drvdata)
+{
+       int rc = 0;
+       struct device *dev = drvdata_to_dev(drvdata);
+
+       /* must be before the enabling to avoid resdundent suspending */
+       pm_runtime_set_autosuspend_delay(dev, CC_SUSPEND_TIMEOUT);
+       pm_runtime_use_autosuspend(dev);
+       /* activate the PM module */
+       rc = pm_runtime_set_active(dev);
+       if (rc)
+               return rc;
+       /* enable the PM module*/
+       pm_runtime_enable(dev);
+
+       return rc;
+}
+
+void cc_pm_fini(struct cc_drvdata *drvdata)
+{
+       pm_runtime_disable(drvdata_to_dev(drvdata));
+}
diff --git a/drivers/staging/ccree/cc_pm.h b/drivers/staging/ccree/cc_pm.h
new file mode 100644 (file)
index 0000000..aac8190
--- /dev/null
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+/* \file cc_pm.h
+ */
+
+#ifndef __CC_POWER_MGR_H__
+#define __CC_POWER_MGR_H__
+
+#include "cc_driver.h"
+
+#define CC_SUSPEND_TIMEOUT 3000
+
+#if defined(CONFIG_PM)
+
+extern const struct dev_pm_ops ccree_pm;
+
+int cc_pm_init(struct cc_drvdata *drvdata);
+void cc_pm_fini(struct cc_drvdata *drvdata);
+int cc_pm_suspend(struct device *dev);
+int cc_pm_resume(struct device *dev);
+int cc_pm_get(struct device *dev);
+int cc_pm_put_suspend(struct device *dev);
+
+#else
+
+static inline int cc_pm_init(struct cc_drvdata *drvdata)
+{
+       return 0;
+}
+
+static inline void cc_pm_fini(struct cc_drvdata *drvdata) {}
+
+static inline int cc_pm_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static inline int cc_pm_resume(struct device *dev)
+{
+       return 0;
+}
+
+static inline int cc_pm_get(struct device *dev)
+{
+       return 0;
+}
+
+static inline int cc_pm_put_suspend(struct device *dev)
+{
+       return 0;
+}
+
+#endif
+
+#endif /*__POWER_MGR_H__*/
+
diff --git a/drivers/staging/ccree/cc_request_mgr.c b/drivers/staging/ccree/cc_request_mgr.c
new file mode 100644 (file)
index 0000000..8a7f834
--- /dev/null
@@ -0,0 +1,713 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include <linux/kernel.h>
+#include "cc_driver.h"
+#include "cc_buffer_mgr.h"
+#include "cc_request_mgr.h"
+#include "cc_ivgen.h"
+#include "cc_pm.h"
+
+#define CC_MAX_POLL_ITER       10
+/* The highest descriptor count in used */
+#define CC_MAX_DESC_SEQ_LEN    23
+
+struct cc_req_mgr_handle {
+       /* Request manager resources */
+       unsigned int hw_queue_size; /* HW capability */
+       unsigned int min_free_hw_slots;
+       unsigned int max_used_sw_slots;
+       struct cc_crypto_req req_queue[MAX_REQUEST_QUEUE_SIZE];
+       u32 req_queue_head;
+       u32 req_queue_tail;
+       u32 axi_completed;
+       u32 q_free_slots;
+       /* This lock protects access to HW register
+        * that must be single request at a time
+        */
+       spinlock_t hw_lock;
+       struct cc_hw_desc compl_desc;
+       u8 *dummy_comp_buff;
+       dma_addr_t dummy_comp_buff_dma;
+
+       /* backlog queue */
+       struct list_head backlog;
+       unsigned int bl_len;
+       spinlock_t bl_lock; /* protect backlog queue */
+
+#ifdef COMP_IN_WQ
+       struct workqueue_struct *workq;
+       struct delayed_work compwork;
+#else
+       struct tasklet_struct comptask;
+#endif
+       bool is_runtime_suspended;
+};
+
+struct cc_bl_item {
+       struct cc_crypto_req creq;
+       struct cc_hw_desc desc[CC_MAX_DESC_SEQ_LEN];
+       unsigned int len;
+       struct list_head list;
+       bool notif;
+};
+
+static void comp_handler(unsigned long devarg);
+#ifdef COMP_IN_WQ
+static void comp_work_handler(struct work_struct *work);
+#endif
+
+void cc_req_mgr_fini(struct cc_drvdata *drvdata)
+{
+       struct cc_req_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
+       struct device *dev = drvdata_to_dev(drvdata);
+
+       if (!req_mgr_h)
+               return; /* Not allocated */
+
+       if (req_mgr_h->dummy_comp_buff_dma) {
+               dma_free_coherent(dev, sizeof(u32), req_mgr_h->dummy_comp_buff,
+                                 req_mgr_h->dummy_comp_buff_dma);
+       }
+
+       dev_dbg(dev, "max_used_hw_slots=%d\n", (req_mgr_h->hw_queue_size -
+                                               req_mgr_h->min_free_hw_slots));
+       dev_dbg(dev, "max_used_sw_slots=%d\n", req_mgr_h->max_used_sw_slots);
+
+#ifdef COMP_IN_WQ
+       flush_workqueue(req_mgr_h->workq);
+       destroy_workqueue(req_mgr_h->workq);
+#else
+       /* Kill tasklet */
+       tasklet_kill(&req_mgr_h->comptask);
+#endif
+       memset(req_mgr_h, 0, sizeof(struct cc_req_mgr_handle));
+       kfree(req_mgr_h);
+       drvdata->request_mgr_handle = NULL;
+}
+
+int cc_req_mgr_init(struct cc_drvdata *drvdata)
+{
+       struct cc_req_mgr_handle *req_mgr_h;
+       struct device *dev = drvdata_to_dev(drvdata);
+       int rc = 0;
+
+       req_mgr_h = kzalloc(sizeof(*req_mgr_h), GFP_KERNEL);
+       if (!req_mgr_h) {
+               rc = -ENOMEM;
+               goto req_mgr_init_err;
+       }
+
+       drvdata->request_mgr_handle = req_mgr_h;
+
+       spin_lock_init(&req_mgr_h->hw_lock);
+       spin_lock_init(&req_mgr_h->bl_lock);
+       INIT_LIST_HEAD(&req_mgr_h->backlog);
+
+#ifdef COMP_IN_WQ
+       dev_dbg(dev, "Initializing completion workqueue\n");
+       req_mgr_h->workq = create_singlethread_workqueue("arm_cc7x_wq");
+       if (!req_mgr_h->workq) {
+               dev_err(dev, "Failed creating work queue\n");
+               rc = -ENOMEM;
+               goto req_mgr_init_err;
+       }
+       INIT_DELAYED_WORK(&req_mgr_h->compwork, comp_work_handler);
+#else
+       dev_dbg(dev, "Initializing completion tasklet\n");
+       tasklet_init(&req_mgr_h->comptask, comp_handler,
+                    (unsigned long)drvdata);
+#endif
+       req_mgr_h->hw_queue_size = cc_ioread(drvdata,
+                                            CC_REG(DSCRPTR_QUEUE_SRAM_SIZE));
+       dev_dbg(dev, "hw_queue_size=0x%08X\n", req_mgr_h->hw_queue_size);
+       if (req_mgr_h->hw_queue_size < MIN_HW_QUEUE_SIZE) {
+               dev_err(dev, "Invalid HW queue size = %u (Min. required is %u)\n",
+                       req_mgr_h->hw_queue_size, MIN_HW_QUEUE_SIZE);
+               rc = -ENOMEM;
+               goto req_mgr_init_err;
+       }
+       req_mgr_h->min_free_hw_slots = req_mgr_h->hw_queue_size;
+       req_mgr_h->max_used_sw_slots = 0;
+
+       /* Allocate DMA word for "dummy" completion descriptor use */
+       req_mgr_h->dummy_comp_buff =
+               dma_alloc_coherent(dev, sizeof(u32),
+                                  &req_mgr_h->dummy_comp_buff_dma,
+                                  GFP_KERNEL);
+       if (!req_mgr_h->dummy_comp_buff) {
+               dev_err(dev, "Not enough memory to allocate DMA (%zu) dropped buffer\n",
+                       sizeof(u32));
+               rc = -ENOMEM;
+               goto req_mgr_init_err;
+       }
+
+       /* Init. "dummy" completion descriptor */
+       hw_desc_init(&req_mgr_h->compl_desc);
+       set_din_const(&req_mgr_h->compl_desc, 0, sizeof(u32));
+       set_dout_dlli(&req_mgr_h->compl_desc, req_mgr_h->dummy_comp_buff_dma,
+                     sizeof(u32), NS_BIT, 1);
+       set_flow_mode(&req_mgr_h->compl_desc, BYPASS);
+       set_queue_last_ind(&req_mgr_h->compl_desc);
+
+       return 0;
+
+req_mgr_init_err:
+       cc_req_mgr_fini(drvdata);
+       return rc;
+}
+
+static void enqueue_seq(struct cc_drvdata *drvdata, struct cc_hw_desc seq[],
+                       unsigned int seq_len)
+{
+       int i, w;
+       void __iomem *reg = drvdata->cc_base + CC_REG(DSCRPTR_QUEUE_WORD0);
+       struct device *dev = drvdata_to_dev(drvdata);
+
+       /*
+        * We do indeed write all 6 command words to the same
+        * register. The HW supports this.
+        */
+
+       for (i = 0; i < seq_len; i++) {
+               for (w = 0; w <= 5; w++)
+                       writel_relaxed(seq[i].word[w], reg);
+
+               if (cc_dump_desc)
+                       dev_dbg(dev, "desc[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n",
+                               i, seq[i].word[0], seq[i].word[1],
+                               seq[i].word[2], seq[i].word[3],
+                               seq[i].word[4], seq[i].word[5]);
+       }
+}
+
+/*!
+ * Completion will take place if and only if user requested completion
+ * by cc_send_sync_request().
+ *
+ * \param dev
+ * \param dx_compl_h The completion event to signal
+ */
+static void request_mgr_complete(struct device *dev, void *dx_compl_h,
+                                int dummy)
+{
+       struct completion *this_compl = dx_compl_h;
+
+       complete(this_compl);
+}
+
+static int cc_queues_status(struct cc_drvdata *drvdata,
+                           struct cc_req_mgr_handle *req_mgr_h,
+                           unsigned int total_seq_len)
+{
+       unsigned long poll_queue;
+       struct device *dev = drvdata_to_dev(drvdata);
+
+       /* SW queue is checked only once as it will not
+        * be chaned during the poll because the spinlock_bh
+        * is held by the thread
+        */
+       if (((req_mgr_h->req_queue_head + 1) & (MAX_REQUEST_QUEUE_SIZE - 1)) ==
+           req_mgr_h->req_queue_tail) {
+               dev_err(dev, "SW FIFO is full. req_queue_head=%d sw_fifo_len=%d\n",
+                       req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE);
+               return -ENOSPC;
+       }
+
+       if (req_mgr_h->q_free_slots >= total_seq_len)
+               return 0;
+
+       /* Wait for space in HW queue. Poll constant num of iterations. */
+       for (poll_queue = 0; poll_queue < CC_MAX_POLL_ITER ; poll_queue++) {
+               req_mgr_h->q_free_slots =
+                       cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT));
+               if (req_mgr_h->q_free_slots < req_mgr_h->min_free_hw_slots)
+                       req_mgr_h->min_free_hw_slots = req_mgr_h->q_free_slots;
+
+               if (req_mgr_h->q_free_slots >= total_seq_len) {
+                       /* If there is enough place return */
+                       return 0;
+               }
+
+               dev_dbg(dev, "HW FIFO is full. q_free_slots=%d total_seq_len=%d\n",
+                       req_mgr_h->q_free_slots, total_seq_len);
+       }
+       /* No room in the HW queue try again later */
+       dev_dbg(dev, "HW FIFO full, timeout. req_queue_head=%d sw_fifo_len=%d q_free_slots=%d total_seq_len=%d\n",
+               req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE,
+               req_mgr_h->q_free_slots, total_seq_len);
+       return -ENOSPC;
+}
+
+/*!
+ * Enqueue caller request to crypto hardware.
+ * Need to be called with HW lock held and PM running
+ *
+ * \param drvdata
+ * \param cc_req The request to enqueue
+ * \param desc The crypto sequence
+ * \param len The crypto sequence length
+ * \param add_comp If "true": add an artificial dout DMA to mark completion
+ *
+ * \return int Returns -EINPROGRESS or error code
+ */
+static int cc_do_send_request(struct cc_drvdata *drvdata,
+                             struct cc_crypto_req *cc_req,
+                             struct cc_hw_desc *desc, unsigned int len,
+                               bool add_comp, bool ivgen)
+{
+       struct cc_req_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
+       unsigned int used_sw_slots;
+       unsigned int iv_seq_len = 0;
+       unsigned int total_seq_len = len; /*initial sequence length*/
+       struct cc_hw_desc iv_seq[CC_IVPOOL_SEQ_LEN];
+       struct device *dev = drvdata_to_dev(drvdata);
+       int rc;
+
+       if (ivgen) {
+               dev_dbg(dev, "Acquire IV from pool into %d DMA addresses %pad, %pad, %pad, IV-size=%u\n",
+                       cc_req->ivgen_dma_addr_len,
+                       &cc_req->ivgen_dma_addr[0],
+                       &cc_req->ivgen_dma_addr[1],
+                       &cc_req->ivgen_dma_addr[2],
+                       cc_req->ivgen_size);
+
+               /* Acquire IV from pool */
+               rc = cc_get_iv(drvdata, cc_req->ivgen_dma_addr,
+                              cc_req->ivgen_dma_addr_len,
+                              cc_req->ivgen_size, iv_seq, &iv_seq_len);
+
+               if (rc) {
+                       dev_err(dev, "Failed to generate IV (rc=%d)\n", rc);
+                       return rc;
+               }
+
+               total_seq_len += iv_seq_len;
+       }
+
+       used_sw_slots = ((req_mgr_h->req_queue_head -
+                         req_mgr_h->req_queue_tail) &
+                        (MAX_REQUEST_QUEUE_SIZE - 1));
+       if (used_sw_slots > req_mgr_h->max_used_sw_slots)
+               req_mgr_h->max_used_sw_slots = used_sw_slots;
+
+       /* Enqueue request - must be locked with HW lock*/
+       req_mgr_h->req_queue[req_mgr_h->req_queue_head] = *cc_req;
+       req_mgr_h->req_queue_head = (req_mgr_h->req_queue_head + 1) &
+                                   (MAX_REQUEST_QUEUE_SIZE - 1);
+       /* TODO: Use circ_buf.h ? */
+
+       dev_dbg(dev, "Enqueue request head=%u\n", req_mgr_h->req_queue_head);
+
+       /*
+        * We are about to push command to the HW via the command registers
+        * that may refernece hsot memory. We need to issue a memory barrier
+        * to make sure there are no outstnading memory writes
+        */
+       wmb();
+
+       /* STAT_PHASE_4: Push sequence */
+       if (ivgen)
+               enqueue_seq(drvdata, iv_seq, iv_seq_len);
+
+       enqueue_seq(drvdata, desc, len);
+
+       if (add_comp) {
+               enqueue_seq(drvdata, &req_mgr_h->compl_desc, 1);
+               total_seq_len++;
+       }
+
+       if (req_mgr_h->q_free_slots < total_seq_len) {
+               /* This situation should never occur. Maybe indicating problem
+                * with resuming power. Set the free slot count to 0 and hope
+                * for the best.
+                */
+               dev_err(dev, "HW free slot count mismatch.");
+               req_mgr_h->q_free_slots = 0;
+       } else {
+               /* Update the free slots in HW queue */
+               req_mgr_h->q_free_slots -= total_seq_len;
+       }
+
+       /* Operation still in process */
+       return -EINPROGRESS;
+}
+
+static void cc_enqueue_backlog(struct cc_drvdata *drvdata,
+                              struct cc_bl_item *bli)
+{
+       struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
+
+       spin_lock_bh(&mgr->bl_lock);
+       list_add_tail(&bli->list, &mgr->backlog);
+       ++mgr->bl_len;
+       spin_unlock_bh(&mgr->bl_lock);
+       tasklet_schedule(&mgr->comptask);
+}
+
+static void cc_proc_backlog(struct cc_drvdata *drvdata)
+{
+       struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
+       struct cc_bl_item *bli;
+       struct cc_crypto_req *creq;
+       struct crypto_async_request *req;
+       bool ivgen;
+       unsigned int total_len;
+       struct device *dev = drvdata_to_dev(drvdata);
+       int rc;
+
+       spin_lock(&mgr->bl_lock);
+
+       while (mgr->bl_len) {
+               bli = list_first_entry(&mgr->backlog, struct cc_bl_item, list);
+               spin_unlock(&mgr->bl_lock);
+
+               creq = &bli->creq;
+               req = (struct crypto_async_request *)creq->user_arg;
+
+               /*
+                * Notify the request we're moving out of the backlog
+                * but only if we haven't done so already.
+                */
+               if (!bli->notif) {
+                       req->complete(req, -EINPROGRESS);
+                       bli->notif = true;
+               }
+
+               ivgen = !!creq->ivgen_dma_addr_len;
+               total_len = bli->len + (ivgen ? CC_IVPOOL_SEQ_LEN : 0);
+
+               spin_lock(&mgr->hw_lock);
+
+               rc = cc_queues_status(drvdata, mgr, total_len);
+               if (rc) {
+                       /*
+                        * There is still not room in the FIFO for
+                        * this request. Bail out. We'll return here
+                        * on the next completion irq.
+                        */
+                       spin_unlock(&mgr->hw_lock);
+                       return;
+               }
+
+               rc = cc_do_send_request(drvdata, &bli->creq, bli->desc,
+                                       bli->len, false, ivgen);
+
+               spin_unlock(&mgr->hw_lock);
+
+               if (rc != -EINPROGRESS) {
+                       cc_pm_put_suspend(dev);
+                       creq->user_cb(dev, req, rc);
+               }
+
+               /* Remove ourselves from the backlog list */
+               spin_lock(&mgr->bl_lock);
+               list_del(&bli->list);
+               --mgr->bl_len;
+       }
+
+       spin_unlock(&mgr->bl_lock);
+}
+
+int cc_send_request(struct cc_drvdata *drvdata, struct cc_crypto_req *cc_req,
+                   struct cc_hw_desc *desc, unsigned int len,
+                   struct crypto_async_request *req)
+{
+       int rc;
+       struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
+       bool ivgen = !!cc_req->ivgen_dma_addr_len;
+       unsigned int total_len = len + (ivgen ? CC_IVPOOL_SEQ_LEN : 0);
+       struct device *dev = drvdata_to_dev(drvdata);
+       bool backlog_ok = req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG;
+       gfp_t flags = cc_gfp_flags(req);
+       struct cc_bl_item *bli;
+
+       rc = cc_pm_get(dev);
+       if (rc) {
+               dev_err(dev, "ssi_power_mgr_runtime_get returned %x\n", rc);
+               return rc;
+       }
+
+       spin_lock_bh(&mgr->hw_lock);
+       rc = cc_queues_status(drvdata, mgr, total_len);
+
+#ifdef CC_DEBUG_FORCE_BACKLOG
+       if (backlog_ok)
+               rc = -ENOSPC;
+#endif /* CC_DEBUG_FORCE_BACKLOG */
+
+       if (rc == -ENOSPC && backlog_ok) {
+               spin_unlock_bh(&mgr->hw_lock);
+
+               bli = kmalloc(sizeof(*bli), flags);
+               if (!bli) {
+                       cc_pm_put_suspend(dev);
+                       return -ENOMEM;
+               }
+
+               memcpy(&bli->creq, cc_req, sizeof(*cc_req));
+               memcpy(&bli->desc, desc, len * sizeof(*desc));
+               bli->len = len;
+               bli->notif = false;
+               cc_enqueue_backlog(drvdata, bli);
+               return -EBUSY;
+       }
+
+       if (!rc)
+               rc = cc_do_send_request(drvdata, cc_req, desc, len, false,
+                                       ivgen);
+
+       spin_unlock_bh(&mgr->hw_lock);
+       return rc;
+}
+
+int cc_send_sync_request(struct cc_drvdata *drvdata,
+                        struct cc_crypto_req *cc_req, struct cc_hw_desc *desc,
+                        unsigned int len)
+{
+       int rc;
+       struct device *dev = drvdata_to_dev(drvdata);
+       struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
+
+       init_completion(&cc_req->seq_compl);
+       cc_req->user_cb = request_mgr_complete;
+       cc_req->user_arg = &cc_req->seq_compl;
+
+       rc = cc_pm_get(dev);
+       if (rc) {
+               dev_err(dev, "ssi_power_mgr_runtime_get returned %x\n", rc);
+               return rc;
+       }
+
+       while (true) {
+               spin_lock_bh(&mgr->hw_lock);
+               rc = cc_queues_status(drvdata, mgr, len + 1);
+
+               if (!rc)
+                       break;
+
+               spin_unlock_bh(&mgr->hw_lock);
+               if (rc != -EAGAIN) {
+                       cc_pm_put_suspend(dev);
+                       return rc;
+               }
+               wait_for_completion_interruptible(&drvdata->hw_queue_avail);
+               reinit_completion(&drvdata->hw_queue_avail);
+       }
+
+       rc = cc_do_send_request(drvdata, cc_req, desc, len, true, false);
+       spin_unlock_bh(&mgr->hw_lock);
+
+       if (rc != -EINPROGRESS) {
+               cc_pm_put_suspend(dev);
+               return rc;
+       }
+
+       wait_for_completion(&cc_req->seq_compl);
+       return 0;
+}
+
+/*!
+ * Enqueue caller request to crypto hardware during init process.
+ * assume this function is not called in middle of a flow,
+ * since we set QUEUE_LAST_IND flag in the last descriptor.
+ *
+ * \param drvdata
+ * \param desc The crypto sequence
+ * \param len The crypto sequence length
+ *
+ * \return int Returns "0" upon success
+ */
+int send_request_init(struct cc_drvdata *drvdata, struct cc_hw_desc *desc,
+                     unsigned int len)
+{
+       struct cc_req_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
+       unsigned int total_seq_len = len; /*initial sequence length*/
+       int rc = 0;
+
+       /* Wait for space in HW and SW FIFO. Poll for as much as FIFO_TIMEOUT.
+        */
+       rc = cc_queues_status(drvdata, req_mgr_h, total_seq_len);
+       if (rc)
+               return rc;
+
+       set_queue_last_ind(&desc[(len - 1)]);
+
+       /*
+        * We are about to push command to the HW via the command registers
+        * that may refernece hsot memory. We need to issue a memory barrier
+        * to make sure there are no outstnading memory writes
+        */
+       wmb();
+       enqueue_seq(drvdata, desc, len);
+
+       /* Update the free slots in HW queue */
+       req_mgr_h->q_free_slots =
+               cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT));
+
+       return 0;
+}
+
+void complete_request(struct cc_drvdata *drvdata)
+{
+       struct cc_req_mgr_handle *request_mgr_handle =
+                                               drvdata->request_mgr_handle;
+
+       complete(&drvdata->hw_queue_avail);
+#ifdef COMP_IN_WQ
+       queue_delayed_work(request_mgr_handle->workq,
+                          &request_mgr_handle->compwork, 0);
+#else
+       tasklet_schedule(&request_mgr_handle->comptask);
+#endif
+}
+
+#ifdef COMP_IN_WQ
+static void comp_work_handler(struct work_struct *work)
+{
+       struct cc_drvdata *drvdata =
+               container_of(work, struct cc_drvdata, compwork.work);
+
+       comp_handler((unsigned long)drvdata);
+}
+#endif
+
+static void proc_completions(struct cc_drvdata *drvdata)
+{
+       struct cc_crypto_req *cc_req;
+       struct device *dev = drvdata_to_dev(drvdata);
+       struct cc_req_mgr_handle *request_mgr_handle =
+                                               drvdata->request_mgr_handle;
+       unsigned int *tail = &request_mgr_handle->req_queue_tail;
+       unsigned int *head = &request_mgr_handle->req_queue_head;
+
+       while (request_mgr_handle->axi_completed) {
+               request_mgr_handle->axi_completed--;
+
+               /* Dequeue request */
+               if (*head == *tail) {
+                       /* We are supposed to handle a completion but our
+                        * queue is empty. This is not normal. Return and
+                        * hope for the best.
+                        */
+                       dev_err(dev, "Request queue is empty head == tail %u\n",
+                               *head);
+                       break;
+               }
+
+               cc_req = &request_mgr_handle->req_queue[*tail];
+
+               if (cc_req->user_cb)
+                       cc_req->user_cb(dev, cc_req->user_arg, 0);
+               *tail = (*tail + 1) & (MAX_REQUEST_QUEUE_SIZE - 1);
+               dev_dbg(dev, "Dequeue request tail=%u\n", *tail);
+               dev_dbg(dev, "Request completed. axi_completed=%d\n",
+                       request_mgr_handle->axi_completed);
+               cc_pm_put_suspend(dev);
+       }
+}
+
+static inline u32 cc_axi_comp_count(struct cc_drvdata *drvdata)
+{
+       return FIELD_GET(AXIM_MON_COMP_VALUE,
+                        cc_ioread(drvdata, CC_REG(AXIM_MON_COMP)));
+}
+
+/* Deferred service handler, run as interrupt-fired tasklet */
+static void comp_handler(unsigned long devarg)
+{
+       struct cc_drvdata *drvdata = (struct cc_drvdata *)devarg;
+       struct cc_req_mgr_handle *request_mgr_handle =
+                                               drvdata->request_mgr_handle;
+
+       u32 irq;
+
+       irq = (drvdata->irq & CC_COMP_IRQ_MASK);
+
+       if (irq & CC_COMP_IRQ_MASK) {
+               /* To avoid the interrupt from firing as we unmask it,
+                * we clear it now
+                */
+               cc_iowrite(drvdata, CC_REG(HOST_ICR), CC_COMP_IRQ_MASK);
+
+               /* Avoid race with above clear: Test completion counter
+                * once more
+                */
+               request_mgr_handle->axi_completed +=
+                               cc_axi_comp_count(drvdata);
+
+               while (request_mgr_handle->axi_completed) {
+                       do {
+                               proc_completions(drvdata);
+                               /* At this point (after proc_completions()),
+                                * request_mgr_handle->axi_completed is 0.
+                                */
+                               request_mgr_handle->axi_completed =
+                                               cc_axi_comp_count(drvdata);
+                       } while (request_mgr_handle->axi_completed > 0);
+
+                       cc_iowrite(drvdata, CC_REG(HOST_ICR),
+                                  CC_COMP_IRQ_MASK);
+
+                       request_mgr_handle->axi_completed +=
+                                       cc_axi_comp_count(drvdata);
+               }
+       }
+       /* after verifing that there is nothing to do,
+        * unmask AXI completion interrupt
+        */
+       cc_iowrite(drvdata, CC_REG(HOST_IMR),
+                  cc_ioread(drvdata, CC_REG(HOST_IMR)) & ~irq);
+
+       cc_proc_backlog(drvdata);
+}
+
+/*
+ * resume the queue configuration - no need to take the lock as this happens
+ * inside the spin lock protection
+ */
+#if defined(CONFIG_PM)
+int cc_resume_req_queue(struct cc_drvdata *drvdata)
+{
+       struct cc_req_mgr_handle *request_mgr_handle =
+               drvdata->request_mgr_handle;
+
+       spin_lock_bh(&request_mgr_handle->hw_lock);
+       request_mgr_handle->is_runtime_suspended = false;
+       spin_unlock_bh(&request_mgr_handle->hw_lock);
+
+       return 0;
+}
+
+/*
+ * suspend the queue configuration. Since it is used for the runtime suspend
+ * only verify that the queue can be suspended.
+ */
+int cc_suspend_req_queue(struct cc_drvdata *drvdata)
+{
+       struct cc_req_mgr_handle *request_mgr_handle =
+                                               drvdata->request_mgr_handle;
+
+       /* lock the send_request */
+       spin_lock_bh(&request_mgr_handle->hw_lock);
+       if (request_mgr_handle->req_queue_head !=
+           request_mgr_handle->req_queue_tail) {
+               spin_unlock_bh(&request_mgr_handle->hw_lock);
+               return -EBUSY;
+       }
+       request_mgr_handle->is_runtime_suspended = true;
+       spin_unlock_bh(&request_mgr_handle->hw_lock);
+
+       return 0;
+}
+
+bool cc_req_queue_suspended(struct cc_drvdata *drvdata)
+{
+       struct cc_req_mgr_handle *request_mgr_handle =
+                                               drvdata->request_mgr_handle;
+
+       return  request_mgr_handle->is_runtime_suspended;
+}
+
+#endif
+
diff --git a/drivers/staging/ccree/cc_request_mgr.h b/drivers/staging/ccree/cc_request_mgr.h
new file mode 100644 (file)
index 0000000..573cb97
--- /dev/null
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+/* \file cc_request_mgr.h
+ * Request Manager
+ */
+
+#ifndef __REQUEST_MGR_H__
+#define __REQUEST_MGR_H__
+
+#include "cc_hw_queue_defs.h"
+
+int cc_req_mgr_init(struct cc_drvdata *drvdata);
+
+/*!
+ * Enqueue caller request to crypto hardware.
+ *
+ * \param drvdata
+ * \param cc_req The request to enqueue
+ * \param desc The crypto sequence
+ * \param len The crypto sequence length
+ * \param is_dout If "true": completion is handled by the caller
+ *       If "false": this function adds a dummy descriptor completion
+ *       and waits upon completion signal.
+ *
+ * \return int Returns -EINPROGRESS or error
+ */
+int cc_send_request(struct cc_drvdata *drvdata, struct cc_crypto_req *cc_req,
+                   struct cc_hw_desc *desc, unsigned int len,
+                   struct crypto_async_request *req);
+
+int cc_send_sync_request(struct cc_drvdata *drvdata,
+                        struct cc_crypto_req *cc_req, struct cc_hw_desc *desc,
+                        unsigned int len);
+
+int send_request_init(struct cc_drvdata *drvdata, struct cc_hw_desc *desc,
+                     unsigned int len);
+
+void complete_request(struct cc_drvdata *drvdata);
+
+void cc_req_mgr_fini(struct cc_drvdata *drvdata);
+
+#if defined(CONFIG_PM)
+int cc_resume_req_queue(struct cc_drvdata *drvdata);
+
+int cc_suspend_req_queue(struct cc_drvdata *drvdata);
+
+bool cc_req_queue_suspended(struct cc_drvdata *drvdata);
+#endif
+
+#endif /*__REQUEST_MGR_H__*/
diff --git a/drivers/staging/ccree/cc_sram_mgr.c b/drivers/staging/ccree/cc_sram_mgr.c
new file mode 100644 (file)
index 0000000..d1f8a9c
--- /dev/null
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#include "cc_driver.h"
+#include "cc_sram_mgr.h"
+
+/**
+ * struct cc_sram_ctx -Internal RAM context manager
+ * @sram_free_offset:   the offset to the non-allocated area
+ */
+struct cc_sram_ctx {
+       cc_sram_addr_t sram_free_offset;
+};
+
+/**
+ * cc_sram_mgr_fini() - Cleanup SRAM pool.
+ *
+ * @drvdata: Associated device driver context
+ */
+void cc_sram_mgr_fini(struct cc_drvdata *drvdata)
+{
+       /* Free "this" context */
+       kfree(drvdata->sram_mgr_handle);
+}
+
+/**
+ * cc_sram_mgr_init() - Initializes SRAM pool.
+ *      The pool starts right at the beginning of SRAM.
+ *      Returns zero for success, negative value otherwise.
+ *
+ * @drvdata: Associated device driver context
+ */
+int cc_sram_mgr_init(struct cc_drvdata *drvdata)
+{
+       struct cc_sram_ctx *ctx;
+
+       /* Allocate "this" context */
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+
+       if (!ctx)
+               return -ENOMEM;
+
+       drvdata->sram_mgr_handle = ctx;
+
+       return 0;
+}
+
+/*!
+ * Allocated buffer from SRAM pool.
+ * Note: Caller is responsible to free the LAST allocated buffer.
+ * This function does not taking care of any fragmentation may occur
+ * by the order of calls to alloc/free.
+ *
+ * \param drvdata
+ * \param size The requested bytes to allocate
+ */
+cc_sram_addr_t cc_sram_alloc(struct cc_drvdata *drvdata, u32 size)
+{
+       struct cc_sram_ctx *smgr_ctx = drvdata->sram_mgr_handle;
+       struct device *dev = drvdata_to_dev(drvdata);
+       cc_sram_addr_t p;
+
+       if ((size & 0x3)) {
+               dev_err(dev, "Requested buffer size (%u) is not multiple of 4",
+                       size);
+               return NULL_SRAM_ADDR;
+       }
+       if (size > (CC_CC_SRAM_SIZE - smgr_ctx->sram_free_offset)) {
+               dev_err(dev, "Not enough space to allocate %u B (at offset %llu)\n",
+                       size, smgr_ctx->sram_free_offset);
+               return NULL_SRAM_ADDR;
+       }
+
+       p = smgr_ctx->sram_free_offset;
+       smgr_ctx->sram_free_offset += size;
+       dev_dbg(dev, "Allocated %u B @ %u\n", size, (unsigned int)p);
+       return p;
+}
+
+/**
+ * cc_set_sram_desc() - Create const descriptors sequence to
+ *     set values in given array into SRAM.
+ * Note: each const value can't exceed word size.
+ *
+ * @src:         A pointer to array of words to set as consts.
+ * @dst:         The target SRAM buffer to set into
+ * @nelements:   The number of words in "src" array
+ * @seq:         A pointer to the given IN/OUT descriptor sequence
+ * @seq_len:     A pointer to the given IN/OUT sequence length
+ */
+void cc_set_sram_desc(const u32 *src, cc_sram_addr_t dst,
+                     unsigned int nelement, struct cc_hw_desc *seq,
+                     unsigned int *seq_len)
+{
+       u32 i;
+       unsigned int idx = *seq_len;
+
+       for (i = 0; i < nelement; i++, idx++) {
+               hw_desc_init(&seq[idx]);
+               set_din_const(&seq[idx], src[i], sizeof(u32));
+               set_dout_sram(&seq[idx], dst + (i * sizeof(u32)), sizeof(u32));
+               set_flow_mode(&seq[idx], BYPASS);
+       }
+
+       *seq_len = idx;
+}
+
diff --git a/drivers/staging/ccree/cc_sram_mgr.h b/drivers/staging/ccree/cc_sram_mgr.h
new file mode 100644 (file)
index 0000000..d48649f
--- /dev/null
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
+
+#ifndef __CC_SRAM_MGR_H__
+#define __CC_SRAM_MGR_H__
+
+#ifndef CC_CC_SRAM_SIZE
+#define CC_CC_SRAM_SIZE 4096
+#endif
+
+struct cc_drvdata;
+
+/**
+ * Address (offset) within CC internal SRAM
+ */
+
+typedef u64 cc_sram_addr_t;
+
+#define NULL_SRAM_ADDR ((cc_sram_addr_t)-1)
+
+/*!
+ * Initializes SRAM pool.
+ * The first X bytes of SRAM are reserved for ROM usage, hence, pool
+ * starts right after X bytes.
+ *
+ * \param drvdata
+ *
+ * \return int Zero for success, negative value otherwise.
+ */
+int cc_sram_mgr_init(struct cc_drvdata *drvdata);
+
+/*!
+ * Uninits SRAM pool.
+ *
+ * \param drvdata
+ */
+void cc_sram_mgr_fini(struct cc_drvdata *drvdata);
+
+/*!
+ * Allocated buffer from SRAM pool.
+ * Note: Caller is responsible to free the LAST allocated buffer.
+ * This function does not taking care of any fragmentation may occur
+ * by the order of calls to alloc/free.
+ *
+ * \param drvdata
+ * \param size The requested bytes to allocate
+ */
+cc_sram_addr_t cc_sram_alloc(struct cc_drvdata *drvdata, u32 size);
+
+/**
+ * cc_set_sram_desc() - Create const descriptors sequence to
+ *     set values in given array into SRAM.
+ * Note: each const value can't exceed word size.
+ *
+ * @src:         A pointer to array of words to set as consts.
+ * @dst:         The target SRAM buffer to set into
+ * @nelements:   The number of words in "src" array
+ * @seq:         A pointer to the given IN/OUT descriptor sequence
+ * @seq_len:     A pointer to the given IN/OUT sequence length
+ */
+void cc_set_sram_desc(const u32 *src, cc_sram_addr_t dst,
+                     unsigned int nelement, struct cc_hw_desc *seq,
+                     unsigned int *seq_len);
+
+#endif /*__CC_SRAM_MGR_H__*/
diff --git a/drivers/staging/ccree/dx_crys_kernel.h b/drivers/staging/ccree/dx_crys_kernel.h
deleted file mode 100644 (file)
index 2196030..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __DX_CRYS_KERNEL_H__
-#define __DX_CRYS_KERNEL_H__
-
-// --------------------------------------
-// BLOCK: DSCRPTR
-// --------------------------------------
-#define DX_DSCRPTR_COMPLETION_COUNTER_REG_OFFSET       0xE00UL
-#define DX_DSCRPTR_COMPLETION_COUNTER_COMPLETION_COUNTER_BIT_SHIFT     0x0UL
-#define DX_DSCRPTR_COMPLETION_COUNTER_COMPLETION_COUNTER_BIT_SIZE      0x6UL
-#define DX_DSCRPTR_COMPLETION_COUNTER_OVERFLOW_COUNTER_BIT_SHIFT       0x6UL
-#define DX_DSCRPTR_COMPLETION_COUNTER_OVERFLOW_COUNTER_BIT_SIZE        0x1UL
-#define DX_DSCRPTR_SW_RESET_REG_OFFSET 0xE40UL
-#define DX_DSCRPTR_SW_RESET_VALUE_BIT_SHIFT    0x0UL
-#define DX_DSCRPTR_SW_RESET_VALUE_BIT_SIZE     0x1UL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_REG_OFFSET  0xE60UL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_NUM_OF_DSCRPTR_BIT_SHIFT    0x0UL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_NUM_OF_DSCRPTR_BIT_SIZE     0xAUL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_DSCRPTR_SRAM_SIZE_BIT_SHIFT 0xAUL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_DSCRPTR_SRAM_SIZE_BIT_SIZE  0xCUL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_SRAM_SIZE_BIT_SHIFT 0x16UL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_SRAM_SIZE_BIT_SIZE  0x3UL
-#define DX_DSCRPTR_SINGLE_ADDR_EN_REG_OFFSET   0xE64UL
-#define DX_DSCRPTR_SINGLE_ADDR_EN_VALUE_BIT_SHIFT      0x0UL
-#define DX_DSCRPTR_SINGLE_ADDR_EN_VALUE_BIT_SIZE       0x1UL
-#define DX_DSCRPTR_MEASURE_CNTR_REG_OFFSET     0xE68UL
-#define DX_DSCRPTR_MEASURE_CNTR_VALUE_BIT_SHIFT        0x0UL
-#define DX_DSCRPTR_MEASURE_CNTR_VALUE_BIT_SIZE 0x20UL
-#define DX_DSCRPTR_QUEUE_WORD0_REG_OFFSET      0xE80UL
-#define DX_DSCRPTR_QUEUE_WORD0_VALUE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD0_VALUE_BIT_SIZE  0x20UL
-#define DX_DSCRPTR_QUEUE_WORD1_REG_OFFSET      0xE84UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_DMA_MODE_BIT_SHIFT  0x0UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_DMA_MODE_BIT_SIZE   0x2UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SHIFT      0x2UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SIZE       0x18UL
-#define DX_DSCRPTR_QUEUE_WORD1_NS_BIT_BIT_SHIFT        0x1AUL
-#define DX_DSCRPTR_QUEUE_WORD1_NS_BIT_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_CONST_VALUE_BIT_SHIFT       0x1BUL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_CONST_VALUE_BIT_SIZE        0x1UL
-#define DX_DSCRPTR_QUEUE_WORD1_NOT_LAST_BIT_SHIFT      0x1CUL
-#define DX_DSCRPTR_QUEUE_WORD1_NOT_LAST_BIT_SIZE       0x1UL
-#define DX_DSCRPTR_QUEUE_WORD1_LOCK_QUEUE_BIT_SHIFT    0x1DUL
-#define DX_DSCRPTR_QUEUE_WORD1_LOCK_QUEUE_BIT_SIZE     0x1UL
-#define DX_DSCRPTR_QUEUE_WORD1_NOT_USED_BIT_SHIFT      0x1EUL
-#define DX_DSCRPTR_QUEUE_WORD1_NOT_USED_BIT_SIZE       0x2UL
-#define DX_DSCRPTR_QUEUE_WORD2_REG_OFFSET      0xE88UL
-#define DX_DSCRPTR_QUEUE_WORD2_VALUE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD2_VALUE_BIT_SIZE  0x20UL
-#define DX_DSCRPTR_QUEUE_WORD3_REG_OFFSET      0xE8CUL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_DMA_MODE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_DMA_MODE_BIT_SIZE  0x2UL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_SIZE_BIT_SHIFT     0x2UL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_SIZE_BIT_SIZE      0x18UL
-#define DX_DSCRPTR_QUEUE_WORD3_NS_BIT_BIT_SHIFT        0x1AUL
-#define DX_DSCRPTR_QUEUE_WORD3_NS_BIT_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_LAST_IND_BIT_SHIFT 0x1BUL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_LAST_IND_BIT_SIZE  0x1UL
-#define DX_DSCRPTR_QUEUE_WORD3_HASH_XOR_BIT_BIT_SHIFT  0x1DUL
-#define DX_DSCRPTR_QUEUE_WORD3_HASH_XOR_BIT_BIT_SIZE   0x1UL
-#define DX_DSCRPTR_QUEUE_WORD3_NOT_USED_BIT_SHIFT      0x1EUL
-#define DX_DSCRPTR_QUEUE_WORD3_NOT_USED_BIT_SIZE       0x1UL
-#define DX_DSCRPTR_QUEUE_WORD3_QUEUE_LAST_IND_BIT_SHIFT        0x1FUL
-#define DX_DSCRPTR_QUEUE_WORD3_QUEUE_LAST_IND_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_REG_OFFSET      0xE90UL
-#define DX_DSCRPTR_QUEUE_WORD4_DATA_FLOW_MODE_BIT_SHIFT        0x0UL
-#define DX_DSCRPTR_QUEUE_WORD4_DATA_FLOW_MODE_BIT_SIZE 0x6UL
-#define DX_DSCRPTR_QUEUE_WORD4_AES_SEL_N_HASH_BIT_SHIFT        0x6UL
-#define DX_DSCRPTR_QUEUE_WORD4_AES_SEL_N_HASH_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_AES_XOR_CRYPTO_KEY_BIT_SHIFT    0x7UL
-#define DX_DSCRPTR_QUEUE_WORD4_AES_XOR_CRYPTO_KEY_BIT_SIZE     0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_ACK_NEEDED_BIT_SHIFT    0x8UL
-#define DX_DSCRPTR_QUEUE_WORD4_ACK_NEEDED_BIT_SIZE     0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_MODE_BIT_SHIFT   0xAUL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_MODE_BIT_SIZE    0x4UL
-#define DX_DSCRPTR_QUEUE_WORD4_CMAC_SIZE0_BIT_SHIFT    0xEUL
-#define DX_DSCRPTR_QUEUE_WORD4_CMAC_SIZE0_BIT_SIZE     0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_DO_BIT_SHIFT     0xFUL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_DO_BIT_SIZE      0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF0_BIT_SHIFT  0x11UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF0_BIT_SIZE   0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF1_BIT_SHIFT  0x13UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF1_BIT_SIZE   0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF2_BIT_SHIFT  0x14UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF2_BIT_SIZE   0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_KEY_SIZE_BIT_SHIFT      0x16UL
-#define DX_DSCRPTR_QUEUE_WORD4_KEY_SIZE_BIT_SIZE       0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_SETUP_OPERATION_BIT_SHIFT       0x18UL
-#define DX_DSCRPTR_QUEUE_WORD4_SETUP_OPERATION_BIT_SIZE        0x4UL
-#define DX_DSCRPTR_QUEUE_WORD4_DIN_SRAM_ENDIANNESS_BIT_SHIFT   0x1CUL
-#define DX_DSCRPTR_QUEUE_WORD4_DIN_SRAM_ENDIANNESS_BIT_SIZE    0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_DOUT_SRAM_ENDIANNESS_BIT_SHIFT  0x1DUL
-#define DX_DSCRPTR_QUEUE_WORD4_DOUT_SRAM_ENDIANNESS_BIT_SIZE   0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_WORD_SWAP_BIT_SHIFT     0x1EUL
-#define DX_DSCRPTR_QUEUE_WORD4_WORD_SWAP_BIT_SIZE      0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_BYTES_SWAP_BIT_SHIFT    0x1FUL
-#define DX_DSCRPTR_QUEUE_WORD4_BYTES_SWAP_BIT_SIZE     0x1UL
-#define DX_DSCRPTR_QUEUE_WORD5_REG_OFFSET      0xE94UL
-#define DX_DSCRPTR_QUEUE_WORD5_DIN_ADDR_HIGH_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD5_DIN_ADDR_HIGH_BIT_SIZE  0x10UL
-#define DX_DSCRPTR_QUEUE_WORD5_DOUT_ADDR_HIGH_BIT_SHIFT        0x10UL
-#define DX_DSCRPTR_QUEUE_WORD5_DOUT_ADDR_HIGH_BIT_SIZE 0x10UL
-#define DX_DSCRPTR_QUEUE_WATERMARK_REG_OFFSET  0xE98UL
-#define DX_DSCRPTR_QUEUE_WATERMARK_VALUE_BIT_SHIFT     0x0UL
-#define DX_DSCRPTR_QUEUE_WATERMARK_VALUE_BIT_SIZE      0xAUL
-#define DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET    0xE9CUL
-#define DX_DSCRPTR_QUEUE_CONTENT_VALUE_BIT_SHIFT       0x0UL
-#define DX_DSCRPTR_QUEUE_CONTENT_VALUE_BIT_SIZE        0xAUL
-// --------------------------------------
-// BLOCK: AXI_P
-// --------------------------------------
-#define DX_AXIM_MON_INFLIGHT_REG_OFFSET        0xB00UL
-#define DX_AXIM_MON_INFLIGHT_VALUE_BIT_SHIFT   0x0UL
-#define DX_AXIM_MON_INFLIGHT_VALUE_BIT_SIZE    0x8UL
-#define DX_AXIM_MON_INFLIGHTLAST_REG_OFFSET    0xB40UL
-#define DX_AXIM_MON_INFLIGHTLAST_VALUE_BIT_SHIFT       0x0UL
-#define DX_AXIM_MON_INFLIGHTLAST_VALUE_BIT_SIZE        0x8UL
-#define DX_AXIM_MON_COMP_REG_OFFSET    0xB80UL
-#define DX_AXIM_MON_COMP_VALUE_BIT_SHIFT       0x0UL
-#define DX_AXIM_MON_COMP_VALUE_BIT_SIZE        0x10UL
-#define DX_AXIM_MON_ERR_REG_OFFSET     0xBC4UL
-#define DX_AXIM_MON_ERR_BRESP_BIT_SHIFT        0x0UL
-#define DX_AXIM_MON_ERR_BRESP_BIT_SIZE 0x2UL
-#define DX_AXIM_MON_ERR_BID_BIT_SHIFT  0x2UL
-#define DX_AXIM_MON_ERR_BID_BIT_SIZE   0x4UL
-#define DX_AXIM_MON_ERR_RRESP_BIT_SHIFT        0x10UL
-#define DX_AXIM_MON_ERR_RRESP_BIT_SIZE 0x2UL
-#define DX_AXIM_MON_ERR_RID_BIT_SHIFT  0x12UL
-#define DX_AXIM_MON_ERR_RID_BIT_SIZE   0x4UL
-#define DX_AXIM_CFG_REG_OFFSET 0xBE8UL
-#define DX_AXIM_CFG_BRESPMASK_BIT_SHIFT        0x4UL
-#define DX_AXIM_CFG_BRESPMASK_BIT_SIZE 0x1UL
-#define DX_AXIM_CFG_RRESPMASK_BIT_SHIFT        0x5UL
-#define DX_AXIM_CFG_RRESPMASK_BIT_SIZE 0x1UL
-#define DX_AXIM_CFG_INFLTMASK_BIT_SHIFT        0x6UL
-#define DX_AXIM_CFG_INFLTMASK_BIT_SIZE 0x1UL
-#define DX_AXIM_CFG_COMPMASK_BIT_SHIFT 0x7UL
-#define DX_AXIM_CFG_COMPMASK_BIT_SIZE  0x1UL
-#define DX_AXIM_ACE_CONST_REG_OFFSET   0xBECUL
-#define DX_AXIM_ACE_CONST_ARDOMAIN_BIT_SHIFT   0x0UL
-#define DX_AXIM_ACE_CONST_ARDOMAIN_BIT_SIZE    0x2UL
-#define DX_AXIM_ACE_CONST_AWDOMAIN_BIT_SHIFT   0x2UL
-#define DX_AXIM_ACE_CONST_AWDOMAIN_BIT_SIZE    0x2UL
-#define DX_AXIM_ACE_CONST_ARBAR_BIT_SHIFT      0x4UL
-#define DX_AXIM_ACE_CONST_ARBAR_BIT_SIZE       0x2UL
-#define DX_AXIM_ACE_CONST_AWBAR_BIT_SHIFT      0x6UL
-#define DX_AXIM_ACE_CONST_AWBAR_BIT_SIZE       0x2UL
-#define DX_AXIM_ACE_CONST_ARSNOOP_BIT_SHIFT    0x8UL
-#define DX_AXIM_ACE_CONST_ARSNOOP_BIT_SIZE     0x4UL
-#define DX_AXIM_ACE_CONST_AWSNOOP_NOT_ALIGNED_BIT_SHIFT        0xCUL
-#define DX_AXIM_ACE_CONST_AWSNOOP_NOT_ALIGNED_BIT_SIZE 0x3UL
-#define DX_AXIM_ACE_CONST_AWSNOOP_ALIGNED_BIT_SHIFT    0xFUL
-#define DX_AXIM_ACE_CONST_AWSNOOP_ALIGNED_BIT_SIZE     0x3UL
-#define DX_AXIM_ACE_CONST_AWADDR_NOT_MASKED_BIT_SHIFT  0x12UL
-#define DX_AXIM_ACE_CONST_AWADDR_NOT_MASKED_BIT_SIZE   0x7UL
-#define DX_AXIM_ACE_CONST_AWLEN_VAL_BIT_SHIFT  0x19UL
-#define DX_AXIM_ACE_CONST_AWLEN_VAL_BIT_SIZE   0x4UL
-#define DX_AXIM_CACHE_PARAMS_REG_OFFSET        0xBF0UL
-#define DX_AXIM_CACHE_PARAMS_AWCACHE_LAST_BIT_SHIFT    0x0UL
-#define DX_AXIM_CACHE_PARAMS_AWCACHE_LAST_BIT_SIZE     0x4UL
-#define DX_AXIM_CACHE_PARAMS_AWCACHE_BIT_SHIFT 0x4UL
-#define DX_AXIM_CACHE_PARAMS_AWCACHE_BIT_SIZE  0x4UL
-#define DX_AXIM_CACHE_PARAMS_ARCACHE_BIT_SHIFT 0x8UL
-#define DX_AXIM_CACHE_PARAMS_ARCACHE_BIT_SIZE  0x4UL
-#endif // __DX_CRYS_KERNEL_H__
diff --git a/drivers/staging/ccree/dx_host.h b/drivers/staging/ccree/dx_host.h
deleted file mode 100644 (file)
index 863c267..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __DX_HOST_H__
-#define __DX_HOST_H__
-
-// --------------------------------------
-// BLOCK: HOST_P
-// --------------------------------------
-#define DX_HOST_IRR_REG_OFFSET 0xA00UL
-#define DX_HOST_IRR_DSCRPTR_COMPLETION_LOW_INT_BIT_SHIFT       0x2UL
-#define DX_HOST_IRR_DSCRPTR_COMPLETION_LOW_INT_BIT_SIZE        0x1UL
-#define DX_HOST_IRR_AXI_ERR_INT_BIT_SHIFT      0x8UL
-#define DX_HOST_IRR_AXI_ERR_INT_BIT_SIZE       0x1UL
-#define DX_HOST_IRR_GPR0_BIT_SHIFT     0xBUL
-#define DX_HOST_IRR_GPR0_BIT_SIZE      0x1UL
-#define DX_HOST_IRR_DSCRPTR_WATERMARK_INT_BIT_SHIFT    0x13UL
-#define DX_HOST_IRR_DSCRPTR_WATERMARK_INT_BIT_SIZE     0x1UL
-#define DX_HOST_IRR_AXIM_COMP_INT_BIT_SHIFT    0x17UL
-#define DX_HOST_IRR_AXIM_COMP_INT_BIT_SIZE     0x1UL
-#define DX_HOST_IMR_REG_OFFSET 0xA04UL
-#define DX_HOST_IMR_NOT_USED_MASK_BIT_SHIFT    0x1UL
-#define DX_HOST_IMR_NOT_USED_MASK_BIT_SIZE     0x1UL
-#define DX_HOST_IMR_DSCRPTR_COMPLETION_MASK_BIT_SHIFT  0x2UL
-#define DX_HOST_IMR_DSCRPTR_COMPLETION_MASK_BIT_SIZE   0x1UL
-#define DX_HOST_IMR_AXI_ERR_MASK_BIT_SHIFT     0x8UL
-#define DX_HOST_IMR_AXI_ERR_MASK_BIT_SIZE      0x1UL
-#define DX_HOST_IMR_GPR0_BIT_SHIFT     0xBUL
-#define DX_HOST_IMR_GPR0_BIT_SIZE      0x1UL
-#define DX_HOST_IMR_DSCRPTR_WATERMARK_MASK0_BIT_SHIFT  0x13UL
-#define DX_HOST_IMR_DSCRPTR_WATERMARK_MASK0_BIT_SIZE   0x1UL
-#define DX_HOST_IMR_AXIM_COMP_INT_MASK_BIT_SHIFT       0x17UL
-#define DX_HOST_IMR_AXIM_COMP_INT_MASK_BIT_SIZE        0x1UL
-#define DX_HOST_ICR_REG_OFFSET 0xA08UL
-#define DX_HOST_ICR_DSCRPTR_COMPLETION_BIT_SHIFT       0x2UL
-#define DX_HOST_ICR_DSCRPTR_COMPLETION_BIT_SIZE        0x1UL
-#define DX_HOST_ICR_AXI_ERR_CLEAR_BIT_SHIFT    0x8UL
-#define DX_HOST_ICR_AXI_ERR_CLEAR_BIT_SIZE     0x1UL
-#define DX_HOST_ICR_GPR_INT_CLEAR_BIT_SHIFT    0xBUL
-#define DX_HOST_ICR_GPR_INT_CLEAR_BIT_SIZE     0x1UL
-#define DX_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SHIFT   0x13UL
-#define DX_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SIZE    0x1UL
-#define DX_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SHIFT      0x17UL
-#define DX_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SIZE       0x1UL
-#define DX_HOST_SIGNATURE_REG_OFFSET   0xA24UL
-#define DX_HOST_SIGNATURE_VALUE_BIT_SHIFT      0x0UL
-#define DX_HOST_SIGNATURE_VALUE_BIT_SIZE       0x20UL
-#define DX_HOST_BOOT_REG_OFFSET        0xA28UL
-#define DX_HOST_BOOT_SYNTHESIS_CONFIG_BIT_SHIFT        0x0UL
-#define DX_HOST_BOOT_SYNTHESIS_CONFIG_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_LARGE_RKEK_LOCAL_BIT_SHIFT        0x1UL
-#define DX_HOST_BOOT_LARGE_RKEK_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_HASH_IN_FUSES_LOCAL_BIT_SHIFT     0x2UL
-#define DX_HOST_BOOT_HASH_IN_FUSES_LOCAL_BIT_SIZE      0x1UL
-#define DX_HOST_BOOT_EXT_MEM_SECURED_LOCAL_BIT_SHIFT   0x3UL
-#define DX_HOST_BOOT_EXT_MEM_SECURED_LOCAL_BIT_SIZE    0x1UL
-#define DX_HOST_BOOT_RKEK_ECC_EXISTS_LOCAL_N_BIT_SHIFT 0x5UL
-#define DX_HOST_BOOT_RKEK_ECC_EXISTS_LOCAL_N_BIT_SIZE  0x1UL
-#define DX_HOST_BOOT_SRAM_SIZE_LOCAL_BIT_SHIFT 0x6UL
-#define DX_HOST_BOOT_SRAM_SIZE_LOCAL_BIT_SIZE  0x3UL
-#define DX_HOST_BOOT_DSCRPTR_EXISTS_LOCAL_BIT_SHIFT    0x9UL
-#define DX_HOST_BOOT_DSCRPTR_EXISTS_LOCAL_BIT_SIZE     0x1UL
-#define DX_HOST_BOOT_PAU_EXISTS_LOCAL_BIT_SHIFT        0xAUL
-#define DX_HOST_BOOT_PAU_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_RNG_EXISTS_LOCAL_BIT_SHIFT        0xBUL
-#define DX_HOST_BOOT_RNG_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_PKA_EXISTS_LOCAL_BIT_SHIFT        0xCUL
-#define DX_HOST_BOOT_PKA_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_RC4_EXISTS_LOCAL_BIT_SHIFT        0xDUL
-#define DX_HOST_BOOT_RC4_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_SHA_512_PRSNT_LOCAL_BIT_SHIFT     0xEUL
-#define DX_HOST_BOOT_SHA_512_PRSNT_LOCAL_BIT_SIZE      0x1UL
-#define DX_HOST_BOOT_SHA_256_PRSNT_LOCAL_BIT_SHIFT     0xFUL
-#define DX_HOST_BOOT_SHA_256_PRSNT_LOCAL_BIT_SIZE      0x1UL
-#define DX_HOST_BOOT_MD5_PRSNT_LOCAL_BIT_SHIFT 0x10UL
-#define DX_HOST_BOOT_MD5_PRSNT_LOCAL_BIT_SIZE  0x1UL
-#define DX_HOST_BOOT_HASH_EXISTS_LOCAL_BIT_SHIFT       0x11UL
-#define DX_HOST_BOOT_HASH_EXISTS_LOCAL_BIT_SIZE        0x1UL
-#define DX_HOST_BOOT_C2_EXISTS_LOCAL_BIT_SHIFT 0x12UL
-#define DX_HOST_BOOT_C2_EXISTS_LOCAL_BIT_SIZE  0x1UL
-#define DX_HOST_BOOT_DES_EXISTS_LOCAL_BIT_SHIFT        0x13UL
-#define DX_HOST_BOOT_DES_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_AES_XCBC_MAC_EXISTS_LOCAL_BIT_SHIFT       0x14UL
-#define DX_HOST_BOOT_AES_XCBC_MAC_EXISTS_LOCAL_BIT_SIZE        0x1UL
-#define DX_HOST_BOOT_AES_CMAC_EXISTS_LOCAL_BIT_SHIFT   0x15UL
-#define DX_HOST_BOOT_AES_CMAC_EXISTS_LOCAL_BIT_SIZE    0x1UL
-#define DX_HOST_BOOT_AES_CCM_EXISTS_LOCAL_BIT_SHIFT    0x16UL
-#define DX_HOST_BOOT_AES_CCM_EXISTS_LOCAL_BIT_SIZE     0x1UL
-#define DX_HOST_BOOT_AES_XEX_HW_T_CALC_LOCAL_BIT_SHIFT 0x17UL
-#define DX_HOST_BOOT_AES_XEX_HW_T_CALC_LOCAL_BIT_SIZE  0x1UL
-#define DX_HOST_BOOT_AES_XEX_EXISTS_LOCAL_BIT_SHIFT    0x18UL
-#define DX_HOST_BOOT_AES_XEX_EXISTS_LOCAL_BIT_SIZE     0x1UL
-#define DX_HOST_BOOT_CTR_EXISTS_LOCAL_BIT_SHIFT        0x19UL
-#define DX_HOST_BOOT_CTR_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_AES_DIN_BYTE_RESOLUTION_LOCAL_BIT_SHIFT   0x1AUL
-#define DX_HOST_BOOT_AES_DIN_BYTE_RESOLUTION_LOCAL_BIT_SIZE    0x1UL
-#define DX_HOST_BOOT_TUNNELING_ENB_LOCAL_BIT_SHIFT     0x1BUL
-#define DX_HOST_BOOT_TUNNELING_ENB_LOCAL_BIT_SIZE      0x1UL
-#define DX_HOST_BOOT_SUPPORT_256_192_KEY_LOCAL_BIT_SHIFT       0x1CUL
-#define DX_HOST_BOOT_SUPPORT_256_192_KEY_LOCAL_BIT_SIZE        0x1UL
-#define DX_HOST_BOOT_ONLY_ENCRYPT_LOCAL_BIT_SHIFT      0x1DUL
-#define DX_HOST_BOOT_ONLY_ENCRYPT_LOCAL_BIT_SIZE       0x1UL
-#define DX_HOST_BOOT_AES_EXISTS_LOCAL_BIT_SHIFT        0x1EUL
-#define DX_HOST_BOOT_AES_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_VERSION_REG_OFFSET     0xA40UL
-#define DX_HOST_VERSION_VALUE_BIT_SHIFT        0x0UL
-#define DX_HOST_VERSION_VALUE_BIT_SIZE 0x20UL
-#define DX_HOST_KFDE0_VALID_REG_OFFSET 0xA60UL
-#define DX_HOST_KFDE0_VALID_VALUE_BIT_SHIFT    0x0UL
-#define DX_HOST_KFDE0_VALID_VALUE_BIT_SIZE     0x1UL
-#define DX_HOST_KFDE1_VALID_REG_OFFSET 0xA64UL
-#define DX_HOST_KFDE1_VALID_VALUE_BIT_SHIFT    0x0UL
-#define DX_HOST_KFDE1_VALID_VALUE_BIT_SIZE     0x1UL
-#define DX_HOST_KFDE2_VALID_REG_OFFSET 0xA68UL
-#define DX_HOST_KFDE2_VALID_VALUE_BIT_SHIFT    0x0UL
-#define DX_HOST_KFDE2_VALID_VALUE_BIT_SIZE     0x1UL
-#define DX_HOST_KFDE3_VALID_REG_OFFSET 0xA6CUL
-#define DX_HOST_KFDE3_VALID_VALUE_BIT_SHIFT    0x0UL
-#define DX_HOST_KFDE3_VALID_VALUE_BIT_SIZE     0x1UL
-#define DX_HOST_GPR0_REG_OFFSET        0xA70UL
-#define DX_HOST_GPR0_VALUE_BIT_SHIFT   0x0UL
-#define DX_HOST_GPR0_VALUE_BIT_SIZE    0x20UL
-#define DX_GPR_HOST_REG_OFFSET 0xA74UL
-#define DX_GPR_HOST_VALUE_BIT_SHIFT    0x0UL
-#define DX_GPR_HOST_VALUE_BIT_SIZE     0x20UL
-#define DX_HOST_POWER_DOWN_EN_REG_OFFSET       0xA78UL
-#define DX_HOST_POWER_DOWN_EN_VALUE_BIT_SHIFT  0x0UL
-#define DX_HOST_POWER_DOWN_EN_VALUE_BIT_SIZE   0x1UL
-// --------------------------------------
-// BLOCK: HOST_SRAM
-// --------------------------------------
-#define DX_SRAM_DATA_REG_OFFSET        0xF00UL
-#define DX_SRAM_DATA_VALUE_BIT_SHIFT   0x0UL
-#define DX_SRAM_DATA_VALUE_BIT_SIZE    0x20UL
-#define DX_SRAM_ADDR_REG_OFFSET        0xF04UL
-#define DX_SRAM_ADDR_VALUE_BIT_SHIFT   0x0UL
-#define DX_SRAM_ADDR_VALUE_BIT_SIZE    0xFUL
-#define DX_SRAM_DATA_READY_REG_OFFSET  0xF08UL
-#define DX_SRAM_DATA_READY_VALUE_BIT_SHIFT     0x0UL
-#define DX_SRAM_DATA_READY_VALUE_BIT_SIZE      0x1UL
-
-#endif //__DX_HOST_H__
diff --git a/drivers/staging/ccree/dx_reg_common.h b/drivers/staging/ccree/dx_reg_common.h
deleted file mode 100644 (file)
index d5132ff..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __DX_REG_COMMON_H__
-#define __DX_REG_COMMON_H__
-
-#define DX_DEV_SIGNATURE 0xDCC71200UL
-
-#define CC_HW_VERSION 0xef840015UL
-
-#define DX_DEV_SHA_MAX 512
-
-#endif /*__DX_REG_COMMON_H__*/
diff --git a/drivers/staging/ccree/hash_defs.h b/drivers/staging/ccree/hash_defs.h
deleted file mode 100644 (file)
index f52656f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _HASH_DEFS_H_
-#define _HASH_DEFS_H_
-
-#include "cc_crypto_ctx.h"
-
-enum cc_hash_conf_pad {
-       HASH_PADDING_DISABLED = 0,
-       HASH_PADDING_ENABLED = 1,
-       HASH_DIGEST_RESULT_LITTLE_ENDIAN = 2,
-       HASH_CONFIG1_PADDING_RESERVE32 = S32_MAX,
-};
-
-enum cc_hash_cipher_pad {
-       DO_NOT_PAD = 0,
-       DO_PAD = 1,
-       HASH_CIPHER_DO_PADDING_RESERVE32 = S32_MAX,
-};
-
-#endif /*_HASH_DEFS_H_*/
-
diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c
deleted file mode 100644 (file)
index ba0954e..0000000
+++ /dev/null
@@ -1,2794 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <crypto/algapi.h>
-#include <crypto/internal/skcipher.h>
-#include <crypto/internal/hash.h>
-#include <crypto/internal/aead.h>
-#include <crypto/sha.h>
-#include <crypto/ctr.h>
-#include <crypto/authenc.h>
-#include <crypto/aes.h>
-#include <crypto/des.h>
-#include <linux/rtnetlink.h>
-#include <linux/version.h>
-#include "ssi_config.h"
-#include "ssi_driver.h"
-#include "ssi_buffer_mgr.h"
-#include "ssi_aead.h"
-#include "ssi_request_mgr.h"
-#include "ssi_hash.h"
-#include "ssi_sysfs.h"
-#include "ssi_sram_mgr.h"
-
-#define template_aead  template_u.aead
-
-#define MAX_AEAD_SETKEY_SEQ 12
-#define MAX_AEAD_PROCESS_SEQ 23
-
-#define MAX_HMAC_DIGEST_SIZE (SHA256_DIGEST_SIZE)
-#define MAX_HMAC_BLOCK_SIZE (SHA256_BLOCK_SIZE)
-
-#define AES_CCM_RFC4309_NONCE_SIZE 3
-#define MAX_NONCE_SIZE CTR_RFC3686_NONCE_SIZE
-
-/* Value of each ICV_CMP byte (of 8) in case of success */
-#define ICV_VERIF_OK 0x01
-
-struct ssi_aead_handle {
-       ssi_sram_addr_t sram_workspace_addr;
-       struct list_head aead_list;
-};
-
-struct cc_hmac_s {
-       u8 *padded_authkey;
-       u8 *ipad_opad; /* IPAD, OPAD*/
-       dma_addr_t padded_authkey_dma_addr;
-       dma_addr_t ipad_opad_dma_addr;
-};
-
-struct cc_xcbc_s {
-       u8 *xcbc_keys; /* K1,K2,K3 */
-       dma_addr_t xcbc_keys_dma_addr;
-};
-
-struct ssi_aead_ctx {
-       struct ssi_drvdata *drvdata;
-       u8 ctr_nonce[MAX_NONCE_SIZE]; /* used for ctr3686 iv and aes ccm */
-       u8 *enckey;
-       dma_addr_t enckey_dma_addr;
-       union {
-               struct cc_hmac_s hmac;
-               struct cc_xcbc_s xcbc;
-       } auth_state;
-       unsigned int enc_keylen;
-       unsigned int auth_keylen;
-       unsigned int authsize; /* Actual (reduced?) size of the MAC/ICv */
-       enum drv_cipher_mode cipher_mode;
-       enum cc_flow_mode flow_mode;
-       enum drv_hash_mode auth_mode;
-};
-
-static inline bool valid_assoclen(struct aead_request *req)
-{
-       return ((req->assoclen == 16) || (req->assoclen == 20));
-}
-
-static void ssi_aead_exit(struct crypto_aead *tfm)
-{
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "Clearing context @%p for %s\n", crypto_aead_ctx(tfm),
-               crypto_tfm_alg_name(&tfm->base));
-
-       /* Unmap enckey buffer */
-       if (ctx->enckey) {
-               dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey, ctx->enckey_dma_addr);
-               dev_dbg(dev, "Freed enckey DMA buffer enckey_dma_addr=%pad\n",
-                       &ctx->enckey_dma_addr);
-               ctx->enckey_dma_addr = 0;
-               ctx->enckey = NULL;
-       }
-
-       if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */
-               struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc;
-
-               if (xcbc->xcbc_keys) {
-                       dma_free_coherent(dev, CC_AES_128_BIT_KEY_SIZE * 3,
-                                         xcbc->xcbc_keys,
-                                         xcbc->xcbc_keys_dma_addr);
-               }
-               dev_dbg(dev, "Freed xcbc_keys DMA buffer xcbc_keys_dma_addr=%pad\n",
-                       &xcbc->xcbc_keys_dma_addr);
-               xcbc->xcbc_keys_dma_addr = 0;
-               xcbc->xcbc_keys = NULL;
-       } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC auth. */
-               struct cc_hmac_s *hmac = &ctx->auth_state.hmac;
-
-               if (hmac->ipad_opad) {
-                       dma_free_coherent(dev, 2 * MAX_HMAC_DIGEST_SIZE,
-                                         hmac->ipad_opad,
-                                         hmac->ipad_opad_dma_addr);
-                       dev_dbg(dev, "Freed ipad_opad DMA buffer ipad_opad_dma_addr=%pad\n",
-                               &hmac->ipad_opad_dma_addr);
-                       hmac->ipad_opad_dma_addr = 0;
-                       hmac->ipad_opad = NULL;
-               }
-               if (hmac->padded_authkey) {
-                       dma_free_coherent(dev, MAX_HMAC_BLOCK_SIZE,
-                                         hmac->padded_authkey,
-                                         hmac->padded_authkey_dma_addr);
-                       dev_dbg(dev, "Freed padded_authkey DMA buffer padded_authkey_dma_addr=%pad\n",
-                               &hmac->padded_authkey_dma_addr);
-                       hmac->padded_authkey_dma_addr = 0;
-                       hmac->padded_authkey = NULL;
-               }
-       }
-}
-
-static int ssi_aead_init(struct crypto_aead *tfm)
-{
-       struct aead_alg *alg = crypto_aead_alg(tfm);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct ssi_crypto_alg *ssi_alg =
-                       container_of(alg, struct ssi_crypto_alg, aead_alg);
-       struct device *dev = drvdata_to_dev(ssi_alg->drvdata);
-
-       dev_dbg(dev, "Initializing context @%p for %s\n", ctx,
-               crypto_tfm_alg_name(&tfm->base));
-
-       /* Initialize modes in instance */
-       ctx->cipher_mode = ssi_alg->cipher_mode;
-       ctx->flow_mode = ssi_alg->flow_mode;
-       ctx->auth_mode = ssi_alg->auth_mode;
-       ctx->drvdata = ssi_alg->drvdata;
-       crypto_aead_set_reqsize(tfm, sizeof(struct aead_req_ctx));
-
-       /* Allocate key buffer, cache line aligned */
-       ctx->enckey = dma_alloc_coherent(dev, AES_MAX_KEY_SIZE,
-                                        &ctx->enckey_dma_addr, GFP_KERNEL);
-       if (!ctx->enckey) {
-               dev_err(dev, "Failed allocating key buffer\n");
-               goto init_failed;
-       }
-       dev_dbg(dev, "Allocated enckey buffer in context ctx->enckey=@%p\n",
-               ctx->enckey);
-
-       /* Set default authlen value */
-
-       if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */
-               struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc;
-               const unsigned int key_size = CC_AES_128_BIT_KEY_SIZE * 3;
-
-               /* Allocate dma-coherent buffer for XCBC's K1+K2+K3 */
-               /* (and temporary for user key - up to 256b) */
-               xcbc->xcbc_keys = dma_alloc_coherent(dev, key_size,
-                                                    &xcbc->xcbc_keys_dma_addr,
-                                                    GFP_KERNEL);
-               if (!xcbc->xcbc_keys) {
-                       dev_err(dev, "Failed allocating buffer for XCBC keys\n");
-                       goto init_failed;
-               }
-       } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC authentication */
-               struct cc_hmac_s *hmac = &ctx->auth_state.hmac;
-               const unsigned int digest_size = 2 * MAX_HMAC_DIGEST_SIZE;
-               dma_addr_t *pkey_dma = &hmac->padded_authkey_dma_addr;
-
-               /* Allocate dma-coherent buffer for IPAD + OPAD */
-               hmac->ipad_opad = dma_alloc_coherent(dev, digest_size,
-                                                    &hmac->ipad_opad_dma_addr,
-                                                    GFP_KERNEL);
-
-               if (!hmac->ipad_opad) {
-                       dev_err(dev, "Failed allocating IPAD/OPAD buffer\n");
-                       goto init_failed;
-               }
-
-               dev_dbg(dev, "Allocated authkey buffer in context ctx->authkey=@%p\n",
-                       hmac->ipad_opad);
-
-               hmac->padded_authkey = dma_alloc_coherent(dev,
-                                                         MAX_HMAC_BLOCK_SIZE,
-                                                         pkey_dma,
-                                                         GFP_KERNEL);
-
-               if (!hmac->padded_authkey) {
-                       dev_err(dev, "failed to allocate padded_authkey\n");
-                       goto init_failed;
-               }
-       } else {
-               ctx->auth_state.hmac.ipad_opad = NULL;
-               ctx->auth_state.hmac.padded_authkey = NULL;
-       }
-
-       return 0;
-
-init_failed:
-       ssi_aead_exit(tfm);
-       return -ENOMEM;
-}
-
-static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *cc_base)
-{
-       struct aead_request *areq = (struct aead_request *)ssi_req;
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(areq);
-       struct crypto_aead *tfm = crypto_aead_reqtfm(ssi_req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       int err = 0;
-
-       ssi_buffer_mgr_unmap_aead_request(dev, areq);
-
-       /* Restore ordinary iv pointer */
-       areq->iv = areq_ctx->backup_iv;
-
-       if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
-               if (memcmp(areq_ctx->mac_buf, areq_ctx->icv_virt_addr,
-                          ctx->authsize) != 0) {
-                       dev_dbg(dev, "Payload authentication failure, (auth-size=%d, cipher=%d)\n",
-                               ctx->authsize, ctx->cipher_mode);
-                       /* In case of payload authentication failure, MUST NOT
-                        * revealed the decrypted message --> zero its memory.
-                        */
-                       ssi_buffer_mgr_zero_sgl(areq->dst, areq_ctx->cryptlen);
-                       err = -EBADMSG;
-               }
-       } else { /*ENCRYPT*/
-               if (unlikely(areq_ctx->is_icv_fragmented))
-                       ssi_buffer_mgr_copy_scatterlist_portion(
-                               dev, areq_ctx->mac_buf, areq_ctx->dst_sgl,
-                               areq->cryptlen + areq_ctx->dst_offset,
-                               (areq->cryptlen + areq_ctx->dst_offset +
-                                ctx->authsize),
-                               SSI_SG_FROM_BUF);
-
-               /* If an IV was generated, copy it back to the user provided buffer. */
-               if (areq_ctx->backup_giv) {
-                       if (ctx->cipher_mode == DRV_CIPHER_CTR)
-                               memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_IV_SIZE);
-                       else if (ctx->cipher_mode == DRV_CIPHER_CCM)
-                               memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, CCM_BLOCK_IV_SIZE);
-               }
-       }
-
-       aead_request_complete(areq, err);
-}
-
-static int xcbc_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx)
-{
-       /* Load the AES key */
-       hw_desc_init(&desc[0]);
-       /* We are using for the source/user key the same buffer as for the output keys,
-        * because after this key loading it is not needed anymore
-        */
-       set_din_type(&desc[0], DMA_DLLI,
-                    ctx->auth_state.xcbc.xcbc_keys_dma_addr, ctx->auth_keylen,
-                    NS_BIT);
-       set_cipher_mode(&desc[0], DRV_CIPHER_ECB);
-       set_cipher_config0(&desc[0], DRV_CRYPTO_DIRECTION_ENCRYPT);
-       set_key_size_aes(&desc[0], ctx->auth_keylen);
-       set_flow_mode(&desc[0], S_DIN_to_AES);
-       set_setup_mode(&desc[0], SETUP_LOAD_KEY0);
-
-       hw_desc_init(&desc[1]);
-       set_din_const(&desc[1], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[1], DIN_AES_DOUT);
-       set_dout_dlli(&desc[1], ctx->auth_state.xcbc.xcbc_keys_dma_addr,
-                     AES_KEYSIZE_128, NS_BIT, 0);
-
-       hw_desc_init(&desc[2]);
-       set_din_const(&desc[2], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[2], DIN_AES_DOUT);
-       set_dout_dlli(&desc[2], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
-                                        + AES_KEYSIZE_128),
-                             AES_KEYSIZE_128, NS_BIT, 0);
-
-       hw_desc_init(&desc[3]);
-       set_din_const(&desc[3], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[3], DIN_AES_DOUT);
-       set_dout_dlli(&desc[3], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
-                                         + 2 * AES_KEYSIZE_128),
-                             AES_KEYSIZE_128, NS_BIT, 0);
-
-       return 4;
-}
-
-static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx)
-{
-       unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST };
-       unsigned int digest_ofs = 0;
-       unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
-                       DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
-       unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
-                       CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
-       struct cc_hmac_s *hmac = &ctx->auth_state.hmac;
-
-       int idx = 0;
-       int i;
-
-       /* calc derived HMAC key */
-       for (i = 0; i < 2; i++) {
-               /* Load hash initial state */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], hash_mode);
-               set_din_sram(&desc[idx],
-                            ssi_ahash_get_larval_digest_sram_addr(
-                               ctx->drvdata, ctx->auth_mode),
-                            digest_size);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-               idx++;
-
-               /* Load the hash current length*/
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], hash_mode);
-               set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-               idx++;
-
-               /* Prepare ipad key */
-               hw_desc_init(&desc[idx]);
-               set_xor_val(&desc[idx], hmac_pad_const[i]);
-               set_cipher_mode(&desc[idx], hash_mode);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
-               idx++;
-
-               /* Perform HASH update */
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI,
-                            hmac->padded_authkey_dma_addr,
-                            SHA256_BLOCK_SIZE, NS_BIT);
-               set_cipher_mode(&desc[idx], hash_mode);
-               set_xor_active(&desc[idx]);
-               set_flow_mode(&desc[idx], DIN_HASH);
-               idx++;
-
-               /* Get the digset */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], hash_mode);
-               set_dout_dlli(&desc[idx],
-                             (hmac->ipad_opad_dma_addr + digest_ofs),
-                             digest_size, NS_BIT, 0);
-               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-               set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
-               idx++;
-
-               digest_ofs += digest_size;
-       }
-
-       return idx;
-}
-
-static int validate_keys_sizes(struct ssi_aead_ctx *ctx)
-{
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "enc_keylen=%u  authkeylen=%u\n",
-               ctx->enc_keylen, ctx->auth_keylen);
-
-       switch (ctx->auth_mode) {
-       case DRV_HASH_SHA1:
-       case DRV_HASH_SHA256:
-               break;
-       case DRV_HASH_XCBC_MAC:
-               if ((ctx->auth_keylen != AES_KEYSIZE_128) &&
-                   (ctx->auth_keylen != AES_KEYSIZE_192) &&
-                   (ctx->auth_keylen != AES_KEYSIZE_256))
-                       return -ENOTSUPP;
-               break;
-       case DRV_HASH_NULL: /* Not authenc (e.g., CCM) - no auth_key) */
-               if (ctx->auth_keylen > 0)
-                       return -EINVAL;
-               break;
-       default:
-               dev_err(dev, "Invalid auth_mode=%d\n", ctx->auth_mode);
-               return -EINVAL;
-       }
-       /* Check cipher key size */
-       if (unlikely(ctx->flow_mode == S_DIN_to_DES)) {
-               if (ctx->enc_keylen != DES3_EDE_KEY_SIZE) {
-                       dev_err(dev, "Invalid cipher(3DES) key size: %u\n",
-                               ctx->enc_keylen);
-                       return -EINVAL;
-               }
-       } else { /* Default assumed to be AES ciphers */
-               if ((ctx->enc_keylen != AES_KEYSIZE_128) &&
-                   (ctx->enc_keylen != AES_KEYSIZE_192) &&
-                   (ctx->enc_keylen != AES_KEYSIZE_256)) {
-                       dev_err(dev, "Invalid cipher(AES) key size: %u\n",
-                               ctx->enc_keylen);
-                       return -EINVAL;
-               }
-       }
-
-       return 0; /* All tests of keys sizes passed */
-}
-
-/* This function prepers the user key so it can pass to the hmac processing
- * (copy to intenral buffer or hash in case of key longer than block
- */
-static int
-ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
-{
-       dma_addr_t key_dma_addr = 0;
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       u32 larval_addr = ssi_ahash_get_larval_digest_sram_addr(
-                                       ctx->drvdata, ctx->auth_mode);
-       struct ssi_crypto_req ssi_req = {};
-       unsigned int blocksize;
-       unsigned int digestsize;
-       unsigned int hashmode;
-       unsigned int idx = 0;
-       int rc = 0;
-       struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
-       dma_addr_t padded_authkey_dma_addr =
-               ctx->auth_state.hmac.padded_authkey_dma_addr;
-
-       switch (ctx->auth_mode) { /* auth_key required and >0 */
-       case DRV_HASH_SHA1:
-               blocksize = SHA1_BLOCK_SIZE;
-               digestsize = SHA1_DIGEST_SIZE;
-               hashmode = DRV_HASH_HW_SHA1;
-               break;
-       case DRV_HASH_SHA256:
-       default:
-               blocksize = SHA256_BLOCK_SIZE;
-               digestsize = SHA256_DIGEST_SIZE;
-               hashmode = DRV_HASH_HW_SHA256;
-       }
-
-       if (likely(keylen != 0)) {
-               key_dma_addr = dma_map_single(dev, (void *)key, keylen, DMA_TO_DEVICE);
-               if (unlikely(dma_mapping_error(dev, key_dma_addr))) {
-                       dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
-                               key, keylen);
-                       return -ENOMEM;
-               }
-               if (keylen > blocksize) {
-                       /* Load hash initial state */
-                       hw_desc_init(&desc[idx]);
-                       set_cipher_mode(&desc[idx], hashmode);
-                       set_din_sram(&desc[idx], larval_addr, digestsize);
-                       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-                       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-                       idx++;
-
-                       /* Load the hash current length*/
-                       hw_desc_init(&desc[idx]);
-                       set_cipher_mode(&desc[idx], hashmode);
-                       set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
-                       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-                       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-                       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-                       idx++;
-
-                       hw_desc_init(&desc[idx]);
-                       set_din_type(&desc[idx], DMA_DLLI,
-                                    key_dma_addr, keylen, NS_BIT);
-                       set_flow_mode(&desc[idx], DIN_HASH);
-                       idx++;
-
-                       /* Get hashed key */
-                       hw_desc_init(&desc[idx]);
-                       set_cipher_mode(&desc[idx], hashmode);
-                       set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
-                                     digestsize, NS_BIT, 0);
-                       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-                       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-                       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
-                       set_cipher_config0(&desc[idx],
-                                          HASH_DIGEST_RESULT_LITTLE_ENDIAN);
-                       idx++;
-
-                       hw_desc_init(&desc[idx]);
-                       set_din_const(&desc[idx], 0, (blocksize - digestsize));
-                       set_flow_mode(&desc[idx], BYPASS);
-                       set_dout_dlli(&desc[idx], (padded_authkey_dma_addr +
-                                     digestsize), (blocksize - digestsize),
-                                     NS_BIT, 0);
-                       idx++;
-               } else {
-                       hw_desc_init(&desc[idx]);
-                       set_din_type(&desc[idx], DMA_DLLI, key_dma_addr,
-                                    keylen, NS_BIT);
-                       set_flow_mode(&desc[idx], BYPASS);
-                       set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
-                                     keylen, NS_BIT, 0);
-                       idx++;
-
-                       if ((blocksize - keylen) != 0) {
-                               hw_desc_init(&desc[idx]);
-                               set_din_const(&desc[idx], 0,
-                                             (blocksize - keylen));
-                               set_flow_mode(&desc[idx], BYPASS);
-                               set_dout_dlli(&desc[idx],
-                                             (padded_authkey_dma_addr +
-                                              keylen),
-                                             (blocksize - keylen), NS_BIT, 0);
-                               idx++;
-                       }
-               }
-       } else {
-               hw_desc_init(&desc[idx]);
-               set_din_const(&desc[idx], 0, (blocksize - keylen));
-               set_flow_mode(&desc[idx], BYPASS);
-               set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
-                             blocksize, NS_BIT, 0);
-               idx++;
-       }
-
-       rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
-       if (unlikely(rc != 0))
-               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-
-       if (likely(key_dma_addr != 0))
-               dma_unmap_single(dev, key_dma_addr, keylen, DMA_TO_DEVICE);
-
-       return rc;
-}
-
-static int
-ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
-{
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct rtattr *rta = (struct rtattr *)key;
-       struct ssi_crypto_req ssi_req = {};
-       struct crypto_authenc_key_param *param;
-       struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
-       int seq_len = 0, rc = -EINVAL;
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "Setting key in context @%p for %s. key=%p keylen=%u\n",
-               ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen);
-
-       /* STAT_PHASE_0: Init and sanity checks */
-
-       if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */
-               if (!RTA_OK(rta, keylen))
-                       goto badkey;
-               if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-                       goto badkey;
-               if (RTA_PAYLOAD(rta) < sizeof(*param))
-                       goto badkey;
-               param = RTA_DATA(rta);
-               ctx->enc_keylen = be32_to_cpu(param->enckeylen);
-               key += RTA_ALIGN(rta->rta_len);
-               keylen -= RTA_ALIGN(rta->rta_len);
-               if (keylen < ctx->enc_keylen)
-                       goto badkey;
-               ctx->auth_keylen = keylen - ctx->enc_keylen;
-
-               if (ctx->cipher_mode == DRV_CIPHER_CTR) {
-                       /* the nonce is stored in bytes at end of key */
-                       if (ctx->enc_keylen <
-                           (AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE))
-                               goto badkey;
-                       /* Copy nonce from last 4 bytes in CTR key to
-                        *  first 4 bytes in CTR IV
-                        */
-                       memcpy(ctx->ctr_nonce, key + ctx->auth_keylen + ctx->enc_keylen -
-                               CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
-                       /* Set CTR key size */
-                       ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE;
-               }
-       } else { /* non-authenc - has just one key */
-               ctx->enc_keylen = keylen;
-               ctx->auth_keylen = 0;
-       }
-
-       rc = validate_keys_sizes(ctx);
-       if (unlikely(rc != 0))
-               goto badkey;
-
-       /* STAT_PHASE_1: Copy key to ctx */
-
-       /* Get key material */
-       memcpy(ctx->enckey, key + ctx->auth_keylen, ctx->enc_keylen);
-       if (ctx->enc_keylen == 24)
-               memset(ctx->enckey + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
-       if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
-               memcpy(ctx->auth_state.xcbc.xcbc_keys, key, ctx->auth_keylen);
-       } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */
-               rc = ssi_get_plain_hmac_key(tfm, key, ctx->auth_keylen);
-               if (rc != 0)
-                       goto badkey;
-       }
-
-       /* STAT_PHASE_2: Create sequence */
-
-       switch (ctx->auth_mode) {
-       case DRV_HASH_SHA1:
-       case DRV_HASH_SHA256:
-               seq_len = hmac_setkey(desc, ctx);
-               break;
-       case DRV_HASH_XCBC_MAC:
-               seq_len = xcbc_setkey(desc, ctx);
-               break;
-       case DRV_HASH_NULL: /* non-authenc modes, e.g., CCM */
-               break; /* No auth. key setup */
-       default:
-               dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode);
-               rc = -ENOTSUPP;
-               goto badkey;
-       }
-
-       /* STAT_PHASE_3: Submit sequence to HW */
-
-       if (seq_len > 0) { /* For CCM there is no sequence to setup the key */
-               rc = send_request(ctx->drvdata, &ssi_req, desc, seq_len, 0);
-               if (unlikely(rc != 0)) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       goto setkey_error;
-               }
-       }
-
-       /* Update STAT_PHASE_3 */
-       return rc;
-
-badkey:
-       crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-
-setkey_error:
-       return rc;
-}
-
-#if SSI_CC_HAS_AES_CCM
-static int ssi_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
-{
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-
-       if (keylen < 3)
-               return -EINVAL;
-
-       keylen -= 3;
-       memcpy(ctx->ctr_nonce, key + keylen, 3);
-
-       return ssi_aead_setkey(tfm, key, keylen);
-}
-#endif /*SSI_CC_HAS_AES_CCM*/
-
-static int ssi_aead_setauthsize(
-       struct crypto_aead *authenc,
-       unsigned int authsize)
-{
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(authenc);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       /* Unsupported auth. sizes */
-       if ((authsize == 0) ||
-           (authsize > crypto_aead_maxauthsize(authenc))) {
-               return -ENOTSUPP;
-       }
-
-       ctx->authsize = authsize;
-       dev_dbg(dev, "authlen=%d\n", ctx->authsize);
-
-       return 0;
-}
-
-#if SSI_CC_HAS_AES_CCM
-static int ssi_rfc4309_ccm_setauthsize(struct crypto_aead *authenc,
-                                      unsigned int authsize)
-{
-       switch (authsize) {
-       case 8:
-       case 12:
-       case 16:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return ssi_aead_setauthsize(authenc, authsize);
-}
-
-static int ssi_ccm_setauthsize(struct crypto_aead *authenc,
-                              unsigned int authsize)
-{
-       switch (authsize) {
-       case 4:
-       case 6:
-       case 8:
-       case 10:
-       case 12:
-       case 14:
-       case 16:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return ssi_aead_setauthsize(authenc, authsize);
-}
-#endif /*SSI_CC_HAS_AES_CCM*/
-
-static inline void
-ssi_aead_create_assoc_desc(
-       struct aead_request *areq,
-       unsigned int flow_mode,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(areq);
-       enum ssi_req_dma_buf_type assoc_dma_type = areq_ctx->assoc_buff_type;
-       unsigned int idx = *seq_size;
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       switch (assoc_dma_type) {
-       case SSI_DMA_BUF_DLLI:
-               dev_dbg(dev, "ASSOC buffer type DLLI\n");
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI, sg_dma_address(areq->src),
-                            areq->assoclen, NS_BIT); set_flow_mode(&desc[idx],
-                            flow_mode);
-               if ((ctx->auth_mode == DRV_HASH_XCBC_MAC) &&
-                   (areq_ctx->cryptlen > 0))
-                       set_din_not_last_indication(&desc[idx]);
-               break;
-       case SSI_DMA_BUF_MLLI:
-               dev_dbg(dev, "ASSOC buffer type MLLI\n");
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_MLLI, areq_ctx->assoc.sram_addr,
-                            areq_ctx->assoc.mlli_nents, NS_BIT);
-               set_flow_mode(&desc[idx], flow_mode);
-               if ((ctx->auth_mode == DRV_HASH_XCBC_MAC) &&
-                   (areq_ctx->cryptlen > 0))
-                       set_din_not_last_indication(&desc[idx]);
-               break;
-       case SSI_DMA_BUF_NULL:
-       default:
-               dev_err(dev, "Invalid ASSOC buffer type\n");
-       }
-
-       *seq_size = (++idx);
-}
-
-static inline void
-ssi_aead_process_authenc_data_desc(
-       struct aead_request *areq,
-       unsigned int flow_mode,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size,
-       int direct)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(areq);
-       enum ssi_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type;
-       unsigned int idx = *seq_size;
-       struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       switch (data_dma_type) {
-       case SSI_DMA_BUF_DLLI:
-       {
-               struct scatterlist *cipher =
-                       (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
-                       areq_ctx->dst_sgl : areq_ctx->src_sgl;
-
-               unsigned int offset =
-                       (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
-                       areq_ctx->dst_offset : areq_ctx->src_offset;
-               dev_dbg(dev, "AUTHENC: SRC/DST buffer type DLLI\n");
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI,
-                            (sg_dma_address(cipher) + offset),
-                            areq_ctx->cryptlen, NS_BIT);
-               set_flow_mode(&desc[idx], flow_mode);
-               break;
-       }
-       case SSI_DMA_BUF_MLLI:
-       {
-               /* DOUBLE-PASS flow (as default)
-                * assoc. + iv + data -compact in one table
-                * if assoclen is ZERO only IV perform
-                */
-               ssi_sram_addr_t mlli_addr = areq_ctx->assoc.sram_addr;
-               u32 mlli_nents = areq_ctx->assoc.mlli_nents;
-
-               if (likely(areq_ctx->is_single_pass)) {
-                       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
-                               mlli_addr = areq_ctx->dst.sram_addr;
-                               mlli_nents = areq_ctx->dst.mlli_nents;
-                       } else {
-                               mlli_addr = areq_ctx->src.sram_addr;
-                               mlli_nents = areq_ctx->src.mlli_nents;
-                       }
-               }
-
-               dev_dbg(dev, "AUTHENC: SRC/DST buffer type MLLI\n");
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_MLLI, mlli_addr, mlli_nents,
-                            NS_BIT);
-               set_flow_mode(&desc[idx], flow_mode);
-               break;
-       }
-       case SSI_DMA_BUF_NULL:
-       default:
-               dev_err(dev, "AUTHENC: Invalid SRC/DST buffer type\n");
-       }
-
-       *seq_size = (++idx);
-}
-
-static inline void
-ssi_aead_process_cipher_data_desc(
-       struct aead_request *areq,
-       unsigned int flow_mode,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       unsigned int idx = *seq_size;
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(areq);
-       enum ssi_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type;
-       struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       if (areq_ctx->cryptlen == 0)
-               return; /*null processing*/
-
-       switch (data_dma_type) {
-       case SSI_DMA_BUF_DLLI:
-               dev_dbg(dev, "CIPHER: SRC/DST buffer type DLLI\n");
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI,
-                            (sg_dma_address(areq_ctx->src_sgl) +
-                             areq_ctx->src_offset), areq_ctx->cryptlen, NS_BIT);
-               set_dout_dlli(&desc[idx],
-                             (sg_dma_address(areq_ctx->dst_sgl) +
-                              areq_ctx->dst_offset),
-                             areq_ctx->cryptlen, NS_BIT, 0);
-               set_flow_mode(&desc[idx], flow_mode);
-               break;
-       case SSI_DMA_BUF_MLLI:
-               dev_dbg(dev, "CIPHER: SRC/DST buffer type MLLI\n");
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_MLLI, areq_ctx->src.sram_addr,
-                            areq_ctx->src.mlli_nents, NS_BIT);
-               set_dout_mlli(&desc[idx], areq_ctx->dst.sram_addr,
-                             areq_ctx->dst.mlli_nents, NS_BIT, 0);
-               set_flow_mode(&desc[idx], flow_mode);
-               break;
-       case SSI_DMA_BUF_NULL:
-       default:
-               dev_err(dev, "CIPHER: Invalid SRC/DST buffer type\n");
-       }
-
-       *seq_size = (++idx);
-}
-
-static inline void ssi_aead_process_digest_result_desc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       unsigned int idx = *seq_size;
-       unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
-                               DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
-       int direct = req_ctx->gen_ctx.op_type;
-
-       /* Get final ICV result */
-       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
-               hw_desc_init(&desc[idx]);
-               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-               set_dout_dlli(&desc[idx], req_ctx->icv_dma_addr, ctx->authsize,
-                             NS_BIT, 1);
-               set_queue_last_ind(&desc[idx]);
-               if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
-                       set_aes_not_hash_mode(&desc[idx]);
-                       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-               } else {
-                       set_cipher_config0(&desc[idx],
-                                          HASH_DIGEST_RESULT_LITTLE_ENDIAN);
-                       set_cipher_mode(&desc[idx], hash_mode);
-               }
-       } else { /*Decrypt*/
-               /* Get ICV out from hardware */
-               hw_desc_init(&desc[idx]);
-               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-               set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr,
-                             ctx->authsize, NS_BIT, 1);
-               set_queue_last_ind(&desc[idx]);
-               set_cipher_config0(&desc[idx],
-                                  HASH_DIGEST_RESULT_LITTLE_ENDIAN);
-               set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
-               if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
-                       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-                       set_aes_not_hash_mode(&desc[idx]);
-               } else {
-                       set_cipher_mode(&desc[idx], hash_mode);
-               }
-       }
-
-       *seq_size = (++idx);
-}
-
-static inline void ssi_aead_setup_cipher_desc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       unsigned int hw_iv_size = req_ctx->hw_iv_size;
-       unsigned int idx = *seq_size;
-       int direct = req_ctx->gen_ctx.op_type;
-
-       /* Setup cipher state */
-       hw_desc_init(&desc[idx]);
-       set_cipher_config0(&desc[idx], direct);
-       set_flow_mode(&desc[idx], ctx->flow_mode);
-       set_din_type(&desc[idx], DMA_DLLI, req_ctx->gen_ctx.iv_dma_addr,
-                    hw_iv_size, NS_BIT);
-       if (ctx->cipher_mode == DRV_CIPHER_CTR)
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
-       else
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       set_cipher_mode(&desc[idx], ctx->cipher_mode);
-       idx++;
-
-       /* Setup enc. key */
-       hw_desc_init(&desc[idx]);
-       set_cipher_config0(&desc[idx], direct);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       set_flow_mode(&desc[idx], ctx->flow_mode);
-       if (ctx->flow_mode == S_DIN_to_AES) {
-               set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
-                            ((ctx->enc_keylen == 24) ? CC_AES_KEY_SIZE_MAX :
-                             ctx->enc_keylen), NS_BIT);
-               set_key_size_aes(&desc[idx], ctx->enc_keylen);
-       } else {
-               set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
-                            ctx->enc_keylen, NS_BIT);
-               set_key_size_des(&desc[idx], ctx->enc_keylen);
-       }
-       set_cipher_mode(&desc[idx], ctx->cipher_mode);
-       idx++;
-
-       *seq_size = idx;
-}
-
-static inline void ssi_aead_process_cipher(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size,
-       unsigned int data_flow_mode)
-{
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       int direct = req_ctx->gen_ctx.op_type;
-       unsigned int idx = *seq_size;
-
-       if (req_ctx->cryptlen == 0)
-               return; /*null processing*/
-
-       ssi_aead_setup_cipher_desc(req, desc, &idx);
-       ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, &idx);
-       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
-               /* We must wait for DMA to write all cipher */
-               hw_desc_init(&desc[idx]);
-               set_din_no_dma(&desc[idx], 0, 0xfffff0);
-               set_dout_no_dma(&desc[idx], 0, 0, 1);
-               idx++;
-       }
-
-       *seq_size = idx;
-}
-
-static inline void ssi_aead_hmac_setup_digest_desc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
-                               DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
-       unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
-                               CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
-       unsigned int idx = *seq_size;
-
-       /* Loading hash ipad xor key state */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], hash_mode);
-       set_din_type(&desc[idx], DMA_DLLI,
-                    ctx->auth_state.hmac.ipad_opad_dma_addr, digest_size,
-                    NS_BIT);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       idx++;
-
-       /* Load init. digest len (64 bytes) */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], hash_mode);
-       set_din_sram(&desc[idx],
-                    ssi_ahash_get_initial_digest_len_sram_addr(ctx->drvdata,
-                                                               hash_mode),
-                                                               HASH_LEN_SIZE);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       idx++;
-
-       *seq_size = idx;
-}
-
-static inline void ssi_aead_xcbc_setup_digest_desc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       unsigned int idx = *seq_size;
-
-       /* Loading MAC state */
-       hw_desc_init(&desc[idx]);
-       set_din_const(&desc[idx], 0, CC_AES_BLOCK_SIZE);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_aes_not_hash_mode(&desc[idx]);
-       idx++;
-
-       /* Setup XCBC MAC K1 */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI,
-                    ctx->auth_state.xcbc.xcbc_keys_dma_addr,
-                    AES_KEYSIZE_128, NS_BIT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_aes_not_hash_mode(&desc[idx]);
-       idx++;
-
-       /* Setup XCBC MAC K2 */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI,
-                    (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
-                     AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_aes_not_hash_mode(&desc[idx]);
-       idx++;
-
-       /* Setup XCBC MAC K3 */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI,
-                    (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
-                     2 * AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE2);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_aes_not_hash_mode(&desc[idx]);
-       idx++;
-
-       *seq_size = idx;
-}
-
-static inline void ssi_aead_process_digest_header_desc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       unsigned int idx = *seq_size;
-       /* Hash associated data */
-       if (req->assoclen > 0)
-               ssi_aead_create_assoc_desc(req, DIN_HASH, desc, &idx);
-
-       /* Hash IV */
-       *seq_size = idx;
-}
-
-static inline void ssi_aead_process_digest_scheme_desc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct ssi_aead_handle *aead_handle = ctx->drvdata->aead_handle;
-       unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
-                               DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
-       unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
-                               CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
-       unsigned int idx = *seq_size;
-
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], hash_mode);
-       set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr,
-                     HASH_LEN_SIZE);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
-       set_cipher_do(&desc[idx], DO_PAD);
-       idx++;
-
-       /* Get final ICV result */
-       hw_desc_init(&desc[idx]);
-       set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr,
-                     digest_size);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
-       set_cipher_mode(&desc[idx], hash_mode);
-       idx++;
-
-       /* Loading hash opad xor key state */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], hash_mode);
-       set_din_type(&desc[idx], DMA_DLLI,
-                    (ctx->auth_state.hmac.ipad_opad_dma_addr + digest_size),
-                    digest_size, NS_BIT);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       idx++;
-
-       /* Load init. digest len (64 bytes) */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], hash_mode);
-       set_din_sram(&desc[idx],
-                    ssi_ahash_get_initial_digest_len_sram_addr(ctx->drvdata,
-                                                               hash_mode),
-                    HASH_LEN_SIZE);
-       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       idx++;
-
-       /* Perform HASH update */
-       hw_desc_init(&desc[idx]);
-       set_din_sram(&desc[idx], aead_handle->sram_workspace_addr,
-                    digest_size);
-       set_flow_mode(&desc[idx], DIN_HASH);
-       idx++;
-
-       *seq_size = idx;
-}
-
-static inline void ssi_aead_load_mlli_to_sram(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       if (unlikely(
-               (req_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) ||
-               (req_ctx->data_buff_type == SSI_DMA_BUF_MLLI) ||
-               !req_ctx->is_single_pass)) {
-               dev_dbg(dev, "Copy-to-sram: mlli_dma=%08x, mlli_size=%u\n",
-                       (unsigned int)ctx->drvdata->mlli_sram_addr,
-                       req_ctx->mlli_params.mlli_len);
-               /* Copy MLLI table host-to-sram */
-               hw_desc_init(&desc[*seq_size]);
-               set_din_type(&desc[*seq_size], DMA_DLLI,
-                            req_ctx->mlli_params.mlli_dma_addr,
-                            req_ctx->mlli_params.mlli_len, NS_BIT);
-               set_dout_sram(&desc[*seq_size],
-                             ctx->drvdata->mlli_sram_addr,
-                             req_ctx->mlli_params.mlli_len);
-               set_flow_mode(&desc[*seq_size], BYPASS);
-               (*seq_size)++;
-       }
-}
-
-static inline enum cc_flow_mode ssi_aead_get_data_flow_mode(
-       enum drv_crypto_direction direct,
-       enum cc_flow_mode setup_flow_mode,
-       bool is_single_pass)
-{
-       enum cc_flow_mode data_flow_mode;
-
-       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
-               if (setup_flow_mode == S_DIN_to_AES)
-                       data_flow_mode = likely(is_single_pass) ?
-                               AES_to_HASH_and_DOUT : DIN_AES_DOUT;
-               else
-                       data_flow_mode = likely(is_single_pass) ?
-                               DES_to_HASH_and_DOUT : DIN_DES_DOUT;
-       } else { /* Decrypt */
-               if (setup_flow_mode == S_DIN_to_AES)
-                       data_flow_mode = likely(is_single_pass) ?
-                                       AES_and_HASH : DIN_AES_DOUT;
-               else
-                       data_flow_mode = likely(is_single_pass) ?
-                                       DES_and_HASH : DIN_DES_DOUT;
-       }
-
-       return data_flow_mode;
-}
-
-static inline void ssi_aead_hmac_authenc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       int direct = req_ctx->gen_ctx.op_type;
-       unsigned int data_flow_mode = ssi_aead_get_data_flow_mode(
-               direct, ctx->flow_mode, req_ctx->is_single_pass);
-
-       if (req_ctx->is_single_pass) {
-               /**
-                * Single-pass flow
-                */
-               ssi_aead_hmac_setup_digest_desc(req, desc, seq_size);
-               ssi_aead_setup_cipher_desc(req, desc, seq_size);
-               ssi_aead_process_digest_header_desc(req, desc, seq_size);
-               ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, seq_size);
-               ssi_aead_process_digest_scheme_desc(req, desc, seq_size);
-               ssi_aead_process_digest_result_desc(req, desc, seq_size);
-               return;
-       }
-
-       /**
-        * Double-pass flow
-        * Fallback for unsupported single-pass modes,
-        * i.e. using assoc. data of non-word-multiple
-        */
-       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
-               /* encrypt first.. */
-               ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode);
-               /* authenc after..*/
-               ssi_aead_hmac_setup_digest_desc(req, desc, seq_size);
-               ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct);
-               ssi_aead_process_digest_scheme_desc(req, desc, seq_size);
-               ssi_aead_process_digest_result_desc(req, desc, seq_size);
-
-       } else { /*DECRYPT*/
-               /* authenc first..*/
-               ssi_aead_hmac_setup_digest_desc(req, desc, seq_size);
-               ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct);
-               ssi_aead_process_digest_scheme_desc(req, desc, seq_size);
-               /* decrypt after.. */
-               ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode);
-               /* read the digest result with setting the completion bit
-                * must be after the cipher operation
-                */
-               ssi_aead_process_digest_result_desc(req, desc, seq_size);
-       }
-}
-
-static inline void
-ssi_aead_xcbc_authenc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       int direct = req_ctx->gen_ctx.op_type;
-       unsigned int data_flow_mode = ssi_aead_get_data_flow_mode(
-               direct, ctx->flow_mode, req_ctx->is_single_pass);
-
-       if (req_ctx->is_single_pass) {
-               /**
-                * Single-pass flow
-                */
-               ssi_aead_xcbc_setup_digest_desc(req, desc, seq_size);
-               ssi_aead_setup_cipher_desc(req, desc, seq_size);
-               ssi_aead_process_digest_header_desc(req, desc, seq_size);
-               ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, seq_size);
-               ssi_aead_process_digest_result_desc(req, desc, seq_size);
-               return;
-       }
-
-       /**
-        * Double-pass flow
-        * Fallback for unsupported single-pass modes,
-        * i.e. using assoc. data of non-word-multiple
-        */
-       if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
-               /* encrypt first.. */
-               ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode);
-               /* authenc after.. */
-               ssi_aead_xcbc_setup_digest_desc(req, desc, seq_size);
-               ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct);
-               ssi_aead_process_digest_result_desc(req, desc, seq_size);
-       } else { /*DECRYPT*/
-               /* authenc first.. */
-               ssi_aead_xcbc_setup_digest_desc(req, desc, seq_size);
-               ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct);
-               /* decrypt after..*/
-               ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode);
-               /* read the digest result with setting the completion bit
-                * must be after the cipher operation
-                */
-               ssi_aead_process_digest_result_desc(req, desc, seq_size);
-       }
-}
-
-static int validate_data_size(struct ssi_aead_ctx *ctx,
-                             enum drv_crypto_direction direct,
-                             struct aead_request *req)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       unsigned int assoclen = req->assoclen;
-       unsigned int cipherlen = (direct == DRV_CRYPTO_DIRECTION_DECRYPT) ?
-                       (req->cryptlen - ctx->authsize) : req->cryptlen;
-
-       if (unlikely((direct == DRV_CRYPTO_DIRECTION_DECRYPT) &&
-                    (req->cryptlen < ctx->authsize)))
-               goto data_size_err;
-
-       areq_ctx->is_single_pass = true; /*defaulted to fast flow*/
-
-       switch (ctx->flow_mode) {
-       case S_DIN_to_AES:
-               if (unlikely((ctx->cipher_mode == DRV_CIPHER_CBC) &&
-                            !IS_ALIGNED(cipherlen, AES_BLOCK_SIZE)))
-                       goto data_size_err;
-               if (ctx->cipher_mode == DRV_CIPHER_CCM)
-                       break;
-               if (ctx->cipher_mode == DRV_CIPHER_GCTR) {
-                       if (areq_ctx->plaintext_authenticate_only)
-                               areq_ctx->is_single_pass = false;
-                       break;
-               }
-
-               if (!IS_ALIGNED(assoclen, sizeof(u32)))
-                       areq_ctx->is_single_pass = false;
-
-               if ((ctx->cipher_mode == DRV_CIPHER_CTR) &&
-                   !IS_ALIGNED(cipherlen, sizeof(u32)))
-                       areq_ctx->is_single_pass = false;
-
-               break;
-       case S_DIN_to_DES:
-               if (unlikely(!IS_ALIGNED(cipherlen, DES_BLOCK_SIZE)))
-                       goto data_size_err;
-               if (unlikely(!IS_ALIGNED(assoclen, DES_BLOCK_SIZE)))
-                       areq_ctx->is_single_pass = false;
-               break;
-       default:
-               dev_err(dev, "Unexpected flow mode (%d)\n", ctx->flow_mode);
-               goto data_size_err;
-       }
-
-       return 0;
-
-data_size_err:
-       return -EINVAL;
-}
-
-#if SSI_CC_HAS_AES_CCM
-static unsigned int format_ccm_a0(u8 *pa0_buff, u32 header_size)
-{
-       unsigned int len = 0;
-
-       if (header_size == 0)
-               return 0;
-
-       if (header_size < ((1UL << 16) - (1UL << 8))) {
-               len = 2;
-
-               pa0_buff[0] = (header_size >> 8) & 0xFF;
-               pa0_buff[1] = header_size & 0xFF;
-       } else {
-               len = 6;
-
-               pa0_buff[0] = 0xFF;
-               pa0_buff[1] = 0xFE;
-               pa0_buff[2] = (header_size >> 24) & 0xFF;
-               pa0_buff[3] = (header_size >> 16) & 0xFF;
-               pa0_buff[4] = (header_size >> 8) & 0xFF;
-               pa0_buff[5] = header_size & 0xFF;
-       }
-
-       return len;
-}
-
-static int set_msg_len(u8 *block, unsigned int msglen, unsigned int csize)
-{
-       __be32 data;
-
-       memset(block, 0, csize);
-       block += csize;
-
-       if (csize >= 4)
-               csize = 4;
-       else if (msglen > (1 << (8 * csize)))
-               return -EOVERFLOW;
-
-       data = cpu_to_be32(msglen);
-       memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
-
-       return 0;
-}
-
-static inline int ssi_aead_ccm(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       unsigned int idx = *seq_size;
-       unsigned int cipher_flow_mode;
-       dma_addr_t mac_result;
-
-       if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
-               cipher_flow_mode = AES_to_HASH_and_DOUT;
-               mac_result = req_ctx->mac_buf_dma_addr;
-       } else { /* Encrypt */
-               cipher_flow_mode = AES_and_HASH;
-               mac_result = req_ctx->icv_dma_addr;
-       }
-
-       /* load key */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
-       set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
-                    ((ctx->enc_keylen == 24) ?  CC_AES_KEY_SIZE_MAX :
-                     ctx->enc_keylen), NS_BIT);
-       set_key_size_aes(&desc[idx], ctx->enc_keylen);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       /* load ctr state */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
-       set_key_size_aes(&desc[idx], ctx->enc_keylen);
-       set_din_type(&desc[idx], DMA_DLLI,
-                    req_ctx->gen_ctx.iv_dma_addr, AES_BLOCK_SIZE, NS_BIT);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       /* load MAC key */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
-       set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
-                    ((ctx->enc_keylen == 24) ?  CC_AES_KEY_SIZE_MAX :
-                     ctx->enc_keylen), NS_BIT);
-       set_key_size_aes(&desc[idx], ctx->enc_keylen);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_aes_not_hash_mode(&desc[idx]);
-       idx++;
-
-       /* load MAC state */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
-       set_key_size_aes(&desc[idx], ctx->enc_keylen);
-       set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
-                    AES_BLOCK_SIZE, NS_BIT);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_aes_not_hash_mode(&desc[idx]);
-       idx++;
-
-       /* process assoc data */
-       if (req->assoclen > 0) {
-               ssi_aead_create_assoc_desc(req, DIN_HASH, desc, &idx);
-       } else {
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI,
-                            sg_dma_address(&req_ctx->ccm_adata_sg),
-                            AES_BLOCK_SIZE + req_ctx->ccm_hdr_size, NS_BIT);
-               set_flow_mode(&desc[idx], DIN_HASH);
-               idx++;
-       }
-
-       /* process the cipher */
-       if (req_ctx->cryptlen != 0)
-               ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, &idx);
-
-       /* Read temporal MAC */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
-       set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, ctx->authsize,
-                     NS_BIT, 0);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       set_aes_not_hash_mode(&desc[idx]);
-       idx++;
-
-       /* load AES-CTR state (for last MAC calculation)*/
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
-       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
-       set_din_type(&desc[idx], DMA_DLLI, req_ctx->ccm_iv0_dma_addr,
-                    AES_BLOCK_SIZE, NS_BIT);
-       set_key_size_aes(&desc[idx], ctx->enc_keylen);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       hw_desc_init(&desc[idx]);
-       set_din_no_dma(&desc[idx], 0, 0xfffff0);
-       set_dout_no_dma(&desc[idx], 0, 0, 1);
-       idx++;
-
-       /* encrypt the "T" value and store MAC in mac_state */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
-                    ctx->authsize, NS_BIT);
-       set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1);
-       set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], DIN_AES_DOUT);
-       idx++;
-
-       *seq_size = idx;
-       return 0;
-}
-
-static int config_ccm_adata(struct aead_request *req)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       //unsigned int size_of_a = 0, rem_a_size = 0;
-       unsigned int lp = req->iv[0];
-       /* Note: The code assume that req->iv[0] already contains the value of L' of RFC3610 */
-       unsigned int l = lp + 1;  /* This is L' of RFC 3610. */
-       unsigned int m = ctx->authsize;  /* This is M' of RFC 3610. */
-       u8 *b0 = req_ctx->ccm_config + CCM_B0_OFFSET;
-       u8 *a0 = req_ctx->ccm_config + CCM_A0_OFFSET;
-       u8 *ctr_count_0 = req_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET;
-       unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
-                                DRV_CRYPTO_DIRECTION_ENCRYPT) ?
-                               req->cryptlen :
-                               (req->cryptlen - ctx->authsize);
-       int rc;
-
-       memset(req_ctx->mac_buf, 0, AES_BLOCK_SIZE);
-       memset(req_ctx->ccm_config, 0, AES_BLOCK_SIZE * 3);
-
-       /* taken from crypto/ccm.c */
-       /* 2 <= L <= 8, so 1 <= L' <= 7. */
-       if (l < 2 || l > 8) {
-               dev_err(dev, "illegal iv value %X\n", req->iv[0]);
-               return -EINVAL;
-       }
-       memcpy(b0, req->iv, AES_BLOCK_SIZE);
-
-       /* format control info per RFC 3610 and
-        * NIST Special Publication 800-38C
-        */
-       *b0 |= (8 * ((m - 2) / 2));
-       if (req->assoclen > 0)
-               *b0 |= 64;  /* Enable bit 6 if Adata exists. */
-
-       rc = set_msg_len(b0 + 16 - l, cryptlen, l);  /* Write L'. */
-       if (rc != 0) {
-               dev_err(dev, "message len overflow detected");
-               return rc;
-       }
-        /* END of "taken from crypto/ccm.c" */
-
-       /* l(a) - size of associated data. */
-       req_ctx->ccm_hdr_size = format_ccm_a0(a0, req->assoclen);
-
-       memset(req->iv + 15 - req->iv[0], 0, req->iv[0] + 1);
-       req->iv[15] = 1;
-
-       memcpy(ctr_count_0, req->iv, AES_BLOCK_SIZE);
-       ctr_count_0[15] = 0;
-
-       return 0;
-}
-
-static void ssi_rfc4309_ccm_process(struct aead_request *req)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-
-       /* L' */
-       memset(areq_ctx->ctr_iv, 0, AES_BLOCK_SIZE);
-       areq_ctx->ctr_iv[0] = 3;  /* For RFC 4309, always use 4 bytes for message length (at most 2^32-1 bytes). */
-
-       /* In RFC 4309 there is an 11-bytes nonce+IV part, that we build here. */
-       memcpy(areq_ctx->ctr_iv + CCM_BLOCK_NONCE_OFFSET, ctx->ctr_nonce, CCM_BLOCK_NONCE_SIZE);
-       memcpy(areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET,    req->iv,        CCM_BLOCK_IV_SIZE);
-       req->iv = areq_ctx->ctr_iv;
-       req->assoclen -= CCM_BLOCK_IV_SIZE;
-}
-#endif /*SSI_CC_HAS_AES_CCM*/
-
-#if SSI_CC_HAS_AES_GCM
-
-static inline void ssi_aead_gcm_setup_ghash_desc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       unsigned int idx = *seq_size;
-
-       /* load key to AES*/
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
-       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
-       set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
-                    ctx->enc_keylen, NS_BIT);
-       set_key_size_aes(&desc[idx], ctx->enc_keylen);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       /* process one zero block to generate hkey */
-       hw_desc_init(&desc[idx]);
-       set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
-       set_dout_dlli(&desc[idx], req_ctx->hkey_dma_addr, AES_BLOCK_SIZE,
-                     NS_BIT, 0);
-       set_flow_mode(&desc[idx], DIN_AES_DOUT);
-       idx++;
-
-       /* Memory Barrier */
-       hw_desc_init(&desc[idx]);
-       set_din_no_dma(&desc[idx], 0, 0xfffff0);
-       set_dout_no_dma(&desc[idx], 0, 0, 1);
-       idx++;
-
-       /* Load GHASH subkey */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, req_ctx->hkey_dma_addr,
-                    AES_BLOCK_SIZE, NS_BIT);
-       set_dout_no_dma(&desc[idx], 0, 0, 1);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_aes_not_hash_mode(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
-       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       idx++;
-
-       /* Configure Hash Engine to work with GHASH.
-        * Since it was not possible to extend HASH submodes to add GHASH,
-        * The following command is necessary in order to
-        * select GHASH (according to HW designers)
-        */
-       hw_desc_init(&desc[idx]);
-       set_din_no_dma(&desc[idx], 0, 0xfffff0);
-       set_dout_no_dma(&desc[idx], 0, 0, 1);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_aes_not_hash_mode(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
-       set_cipher_do(&desc[idx], 1); //1=AES_SK RKEK
-       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
-       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       idx++;
-
-       /* Load GHASH initial STATE (which is 0). (for any hash there is an initial state) */
-       hw_desc_init(&desc[idx]);
-       set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
-       set_dout_no_dma(&desc[idx], 0, 0, 1);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_aes_not_hash_mode(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
-       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       idx++;
-
-       *seq_size = idx;
-}
-
-static inline void ssi_aead_gcm_setup_gctr_desc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       unsigned int idx = *seq_size;
-
-       /* load key to AES*/
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
-       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
-       set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
-                    ctx->enc_keylen, NS_BIT);
-       set_key_size_aes(&desc[idx], ctx->enc_keylen);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       if ((req_ctx->cryptlen != 0) && (!req_ctx->plaintext_authenticate_only)) {
-               /* load AES/CTR initial CTR value inc by 2*/
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
-               set_key_size_aes(&desc[idx], ctx->enc_keylen);
-               set_din_type(&desc[idx], DMA_DLLI,
-                            req_ctx->gcm_iv_inc2_dma_addr, AES_BLOCK_SIZE,
-                            NS_BIT);
-               set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
-               set_flow_mode(&desc[idx], S_DIN_to_AES);
-               idx++;
-       }
-
-       *seq_size = idx;
-}
-
-static inline void ssi_aead_process_gcm_result_desc(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       dma_addr_t mac_result;
-       unsigned int idx = *seq_size;
-
-       if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
-               mac_result = req_ctx->mac_buf_dma_addr;
-       } else { /* Encrypt */
-               mac_result = req_ctx->icv_dma_addr;
-       }
-
-       /* process(ghash) gcm_block_len */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_block_len_dma_addr,
-                    AES_BLOCK_SIZE, NS_BIT);
-       set_flow_mode(&desc[idx], DIN_HASH);
-       idx++;
-
-       /* Store GHASH state after GHASH(Associated Data + Cipher +LenBlock) */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
-       set_din_no_dma(&desc[idx], 0, 0xfffff0);
-       set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, AES_BLOCK_SIZE,
-                     NS_BIT, 0);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       set_aes_not_hash_mode(&desc[idx]);
-
-       idx++;
-
-       /* load AES/CTR initial CTR value inc by 1*/
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
-       set_key_size_aes(&desc[idx], ctx->enc_keylen);
-       set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_iv_inc1_dma_addr,
-                    AES_BLOCK_SIZE, NS_BIT);
-       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       /* Memory Barrier */
-       hw_desc_init(&desc[idx]);
-       set_din_no_dma(&desc[idx], 0, 0xfffff0);
-       set_dout_no_dma(&desc[idx], 0, 0, 1);
-       idx++;
-
-       /* process GCTR on stored GHASH and store MAC in mac_state*/
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
-       set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
-                    AES_BLOCK_SIZE, NS_BIT);
-       set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1);
-       set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], DIN_AES_DOUT);
-       idx++;
-
-       *seq_size = idx;
-}
-
-static inline int ssi_aead_gcm(
-       struct aead_request *req,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       unsigned int cipher_flow_mode;
-
-       if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
-               cipher_flow_mode = AES_and_HASH;
-       } else { /* Encrypt */
-               cipher_flow_mode = AES_to_HASH_and_DOUT;
-       }
-
-       //in RFC4543 no data to encrypt. just copy data from src to dest.
-       if (req_ctx->plaintext_authenticate_only) {
-               ssi_aead_process_cipher_data_desc(req, BYPASS, desc, seq_size);
-               ssi_aead_gcm_setup_ghash_desc(req, desc, seq_size);
-               /* process(ghash) assoc data */
-               ssi_aead_create_assoc_desc(req, DIN_HASH, desc, seq_size);
-               ssi_aead_gcm_setup_gctr_desc(req, desc, seq_size);
-               ssi_aead_process_gcm_result_desc(req, desc, seq_size);
-               return 0;
-       }
-
-       // for gcm and rfc4106.
-       ssi_aead_gcm_setup_ghash_desc(req, desc, seq_size);
-       /* process(ghash) assoc data */
-       if (req->assoclen > 0)
-               ssi_aead_create_assoc_desc(req, DIN_HASH, desc, seq_size);
-       ssi_aead_gcm_setup_gctr_desc(req, desc, seq_size);
-       /* process(gctr+ghash) */
-       if (req_ctx->cryptlen != 0)
-               ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, seq_size);
-       ssi_aead_process_gcm_result_desc(req, desc, seq_size);
-
-       return 0;
-}
-
-#ifdef CC_DEBUG
-static inline void ssi_aead_dump_gcm(
-       const char *title,
-       struct aead_request *req)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-
-       if (ctx->cipher_mode != DRV_CIPHER_GCTR)
-               return;
-
-       if (title) {
-               dev_dbg(dev, "----------------------------------------------------------------------------------");
-               dev_dbg(dev, "%s\n", title);
-       }
-
-       dev_dbg(dev, "cipher_mode %d, authsize %d, enc_keylen %d, assoclen %d, cryptlen %d\n",
-               ctx->cipher_mode, ctx->authsize, ctx->enc_keylen,
-               req->assoclen, req_ctx->cryptlen);
-
-       if (ctx->enckey)
-               dump_byte_array("mac key", ctx->enckey, 16);
-
-       dump_byte_array("req->iv", req->iv, AES_BLOCK_SIZE);
-
-       dump_byte_array("gcm_iv_inc1", req_ctx->gcm_iv_inc1, AES_BLOCK_SIZE);
-
-       dump_byte_array("gcm_iv_inc2", req_ctx->gcm_iv_inc2, AES_BLOCK_SIZE);
-
-       dump_byte_array("hkey", req_ctx->hkey, AES_BLOCK_SIZE);
-
-       dump_byte_array("mac_buf", req_ctx->mac_buf, AES_BLOCK_SIZE);
-
-       dump_byte_array("gcm_len_block", req_ctx->gcm_len_block.len_a, AES_BLOCK_SIZE);
-
-       if (req->src && req->cryptlen)
-               dump_byte_array("req->src", sg_virt(req->src), req->cryptlen + req->assoclen);
-
-       if (req->dst)
-               dump_byte_array("req->dst", sg_virt(req->dst), req->cryptlen + ctx->authsize + req->assoclen);
-}
-#endif
-
-static int config_gcm_context(struct aead_request *req)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
-                                DRV_CRYPTO_DIRECTION_ENCRYPT) ?
-                               req->cryptlen :
-                               (req->cryptlen - ctx->authsize);
-       __be32 counter = cpu_to_be32(2);
-
-       dev_dbg(dev, "%s() cryptlen = %d, req->assoclen = %d ctx->authsize = %d\n",
-               __func__, cryptlen, req->assoclen, ctx->authsize);
-
-       memset(req_ctx->hkey, 0, AES_BLOCK_SIZE);
-
-       memset(req_ctx->mac_buf, 0, AES_BLOCK_SIZE);
-
-       memcpy(req->iv + 12, &counter, 4);
-       memcpy(req_ctx->gcm_iv_inc2, req->iv, 16);
-
-       counter = cpu_to_be32(1);
-       memcpy(req->iv + 12, &counter, 4);
-       memcpy(req_ctx->gcm_iv_inc1, req->iv, 16);
-
-       if (!req_ctx->plaintext_authenticate_only) {
-               __be64 temp64;
-
-               temp64 = cpu_to_be64(req->assoclen * 8);
-               memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64));
-               temp64 = cpu_to_be64(cryptlen * 8);
-               memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8);
-       } else { //rfc4543=>  all data(AAD,IV,Plain) are considered additional data that is nothing is encrypted.
-               __be64 temp64;
-
-               temp64 = cpu_to_be64((req->assoclen + GCM_BLOCK_RFC4_IV_SIZE + cryptlen) * 8);
-               memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64));
-               temp64 = 0;
-               memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8);
-       }
-
-       return 0;
-}
-
-static void ssi_rfc4_gcm_process(struct aead_request *req)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-
-       memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_NONCE_OFFSET, ctx->ctr_nonce, GCM_BLOCK_RFC4_NONCE_SIZE);
-       memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_IV_OFFSET,    req->iv, GCM_BLOCK_RFC4_IV_SIZE);
-       req->iv = areq_ctx->ctr_iv;
-       req->assoclen -= GCM_BLOCK_RFC4_IV_SIZE;
-}
-
-#endif /*SSI_CC_HAS_AES_GCM*/
-
-static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction direct)
-{
-       int rc = 0;
-       int seq_len = 0;
-       struct cc_hw_desc desc[MAX_AEAD_PROCESS_SEQ];
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct ssi_crypto_req ssi_req = {};
-
-       dev_dbg(dev, "%s context=%p req=%p iv=%p src=%p src_ofs=%d dst=%p dst_ofs=%d cryptolen=%d\n",
-               ((direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Enc" : "Dec"),
-               ctx, req, req->iv, sg_virt(req->src), req->src->offset,
-               sg_virt(req->dst), req->dst->offset, req->cryptlen);
-
-       /* STAT_PHASE_0: Init and sanity checks */
-
-       /* Check data length according to mode */
-       if (unlikely(validate_data_size(ctx, direct, req) != 0)) {
-               dev_err(dev, "Unsupported crypt/assoc len %d/%d.\n",
-                       req->cryptlen, req->assoclen);
-               crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_BLOCK_LEN);
-               return -EINVAL;
-       }
-
-       /* Setup DX request structure */
-       ssi_req.user_cb = (void *)ssi_aead_complete;
-       ssi_req.user_arg = (void *)req;
-
-       /* Setup request context */
-       areq_ctx->gen_ctx.op_type = direct;
-       areq_ctx->req_authsize = ctx->authsize;
-       areq_ctx->cipher_mode = ctx->cipher_mode;
-
-       /* STAT_PHASE_1: Map buffers */
-
-       if (ctx->cipher_mode == DRV_CIPHER_CTR) {
-               /* Build CTR IV - Copy nonce from last 4 bytes in
-                * CTR key to first 4 bytes in CTR IV
-                */
-               memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce, CTR_RFC3686_NONCE_SIZE);
-               if (!areq_ctx->backup_giv) /*User none-generated IV*/
-                       memcpy(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE,
-                              req->iv, CTR_RFC3686_IV_SIZE);
-               /* Initialize counter portion of counter block */
-               *(__be32 *)(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE +
-                           CTR_RFC3686_IV_SIZE) = cpu_to_be32(1);
-
-               /* Replace with counter iv */
-               req->iv = areq_ctx->ctr_iv;
-               areq_ctx->hw_iv_size = CTR_RFC3686_BLOCK_SIZE;
-       } else if ((ctx->cipher_mode == DRV_CIPHER_CCM) ||
-                  (ctx->cipher_mode == DRV_CIPHER_GCTR)) {
-               areq_ctx->hw_iv_size = AES_BLOCK_SIZE;
-               if (areq_ctx->ctr_iv != req->iv) {
-                       memcpy(areq_ctx->ctr_iv, req->iv, crypto_aead_ivsize(tfm));
-                       req->iv = areq_ctx->ctr_iv;
-               }
-       }  else {
-               areq_ctx->hw_iv_size = crypto_aead_ivsize(tfm);
-       }
-
-#if SSI_CC_HAS_AES_CCM
-       if (ctx->cipher_mode == DRV_CIPHER_CCM) {
-               rc = config_ccm_adata(req);
-               if (unlikely(rc != 0)) {
-                       dev_dbg(dev, "config_ccm_adata() returned with a failure %d!",
-                               rc);
-                       goto exit;
-               }
-       } else {
-               areq_ctx->ccm_hdr_size = ccm_header_size_null;
-       }
-#else
-       areq_ctx->ccm_hdr_size = ccm_header_size_null;
-#endif /*SSI_CC_HAS_AES_CCM*/
-
-#if SSI_CC_HAS_AES_GCM
-       if (ctx->cipher_mode == DRV_CIPHER_GCTR) {
-               rc = config_gcm_context(req);
-               if (unlikely(rc != 0)) {
-                       dev_dbg(dev, "config_gcm_context() returned with a failure %d!",
-                               rc);
-                       goto exit;
-               }
-       }
-#endif /*SSI_CC_HAS_AES_GCM*/
-
-       rc = ssi_buffer_mgr_map_aead_request(ctx->drvdata, req);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "map_request() failed\n");
-               goto exit;
-       }
-
-       /* do we need to generate IV? */
-       if (areq_ctx->backup_giv) {
-               /* set the DMA mapped IV address*/
-               if (ctx->cipher_mode == DRV_CIPHER_CTR) {
-                       ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr + CTR_RFC3686_NONCE_SIZE;
-                       ssi_req.ivgen_dma_addr_len = 1;
-               } else if (ctx->cipher_mode == DRV_CIPHER_CCM) {
-                       /* In ccm, the IV needs to exist both inside B0 and inside the counter.
-                        * It is also copied to iv_dma_addr for other reasons (like returning
-                        * it to the user).
-                        * So, using 3 (identical) IV outputs.
-                        */
-                       ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr + CCM_BLOCK_IV_OFFSET;
-                       ssi_req.ivgen_dma_addr[1] = sg_dma_address(&areq_ctx->ccm_adata_sg) + CCM_B0_OFFSET          + CCM_BLOCK_IV_OFFSET;
-                       ssi_req.ivgen_dma_addr[2] = sg_dma_address(&areq_ctx->ccm_adata_sg) + CCM_CTR_COUNT_0_OFFSET + CCM_BLOCK_IV_OFFSET;
-                       ssi_req.ivgen_dma_addr_len = 3;
-               } else {
-                       ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr;
-                       ssi_req.ivgen_dma_addr_len = 1;
-               }
-
-               /* set the IV size (8/16 B long)*/
-               ssi_req.ivgen_size = crypto_aead_ivsize(tfm);
-       }
-
-       /* STAT_PHASE_2: Create sequence */
-
-       /* Load MLLI tables to SRAM if necessary */
-       ssi_aead_load_mlli_to_sram(req, desc, &seq_len);
-
-       /*TODO: move seq len by reference */
-       switch (ctx->auth_mode) {
-       case DRV_HASH_SHA1:
-       case DRV_HASH_SHA256:
-               ssi_aead_hmac_authenc(req, desc, &seq_len);
-               break;
-       case DRV_HASH_XCBC_MAC:
-               ssi_aead_xcbc_authenc(req, desc, &seq_len);
-               break;
-#if (SSI_CC_HAS_AES_CCM || SSI_CC_HAS_AES_GCM)
-       case DRV_HASH_NULL:
-#if SSI_CC_HAS_AES_CCM
-               if (ctx->cipher_mode == DRV_CIPHER_CCM)
-                       ssi_aead_ccm(req, desc, &seq_len);
-#endif /*SSI_CC_HAS_AES_CCM*/
-#if SSI_CC_HAS_AES_GCM
-               if (ctx->cipher_mode == DRV_CIPHER_GCTR)
-                       ssi_aead_gcm(req, desc, &seq_len);
-#endif /*SSI_CC_HAS_AES_GCM*/
-                       break;
-#endif
-       default:
-               dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode);
-               ssi_buffer_mgr_unmap_aead_request(dev, req);
-               rc = -ENOTSUPP;
-               goto exit;
-       }
-
-       /* STAT_PHASE_3: Lock HW and push sequence */
-
-       rc = send_request(ctx->drvdata, &ssi_req, desc, seq_len, 1);
-
-       if (unlikely(rc != -EINPROGRESS)) {
-               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-               ssi_buffer_mgr_unmap_aead_request(dev, req);
-       }
-
-exit:
-       return rc;
-}
-
-static int ssi_aead_encrypt(struct aead_request *req)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       int rc;
-
-       /* No generated IV required */
-       areq_ctx->backup_iv = req->iv;
-       areq_ctx->backup_giv = NULL;
-       areq_ctx->is_gcm4543 = false;
-
-       areq_ctx->plaintext_authenticate_only = false;
-
-       rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
-       if (rc != -EINPROGRESS)
-               req->iv = areq_ctx->backup_iv;
-
-       return rc;
-}
-
-#if SSI_CC_HAS_AES_CCM
-static int ssi_rfc4309_ccm_encrypt(struct aead_request *req)
-{
-       /* Very similar to ssi_aead_encrypt() above. */
-
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       int rc = -EINVAL;
-
-       if (!valid_assoclen(req)) {
-               dev_err(dev, "invalid Assoclen:%u\n", req->assoclen);
-               goto out;
-       }
-
-       /* No generated IV required */
-       areq_ctx->backup_iv = req->iv;
-       areq_ctx->backup_giv = NULL;
-       areq_ctx->is_gcm4543 = true;
-
-       ssi_rfc4309_ccm_process(req);
-
-       rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
-       if (rc != -EINPROGRESS)
-               req->iv = areq_ctx->backup_iv;
-out:
-       return rc;
-}
-#endif /* SSI_CC_HAS_AES_CCM */
-
-static int ssi_aead_decrypt(struct aead_request *req)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       int rc;
-
-       /* No generated IV required */
-       areq_ctx->backup_iv = req->iv;
-       areq_ctx->backup_giv = NULL;
-       areq_ctx->is_gcm4543 = false;
-
-       areq_ctx->plaintext_authenticate_only = false;
-
-       rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_DECRYPT);
-       if (rc != -EINPROGRESS)
-               req->iv = areq_ctx->backup_iv;
-
-       return rc;
-}
-
-#if SSI_CC_HAS_AES_CCM
-static int ssi_rfc4309_ccm_decrypt(struct aead_request *req)
-{
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       int rc = -EINVAL;
-
-       if (!valid_assoclen(req)) {
-               dev_err(dev, "invalid Assoclen:%u\n", req->assoclen);
-               goto out;
-       }
-
-       /* No generated IV required */
-       areq_ctx->backup_iv = req->iv;
-       areq_ctx->backup_giv = NULL;
-
-       areq_ctx->is_gcm4543 = true;
-       ssi_rfc4309_ccm_process(req);
-
-       rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_DECRYPT);
-       if (rc != -EINPROGRESS)
-               req->iv = areq_ctx->backup_iv;
-
-out:
-       return rc;
-}
-#endif /* SSI_CC_HAS_AES_CCM */
-
-#if SSI_CC_HAS_AES_GCM
-
-static int ssi_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
-{
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "%s()  keylen %d, key %p\n", __func__, keylen, key);
-
-       if (keylen < 4)
-               return -EINVAL;
-
-       keylen -= 4;
-       memcpy(ctx->ctr_nonce, key + keylen, 4);
-
-       return ssi_aead_setkey(tfm, key, keylen);
-}
-
-static int ssi_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
-{
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "%s()  keylen %d, key %p\n", __func__, keylen, key);
-
-       if (keylen < 4)
-               return -EINVAL;
-
-       keylen -= 4;
-       memcpy(ctx->ctr_nonce, key + keylen, 4);
-
-       return ssi_aead_setkey(tfm, key, keylen);
-}
-
-static int ssi_gcm_setauthsize(struct crypto_aead *authenc,
-                              unsigned int authsize)
-{
-       switch (authsize) {
-       case 4:
-       case 8:
-       case 12:
-       case 13:
-       case 14:
-       case 15:
-       case 16:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return ssi_aead_setauthsize(authenc, authsize);
-}
-
-static int ssi_rfc4106_gcm_setauthsize(struct crypto_aead *authenc,
-                                      unsigned int authsize)
-{
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(authenc);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "authsize %d\n", authsize);
-
-       switch (authsize) {
-       case 8:
-       case 12:
-       case 16:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return ssi_aead_setauthsize(authenc, authsize);
-}
-
-static int ssi_rfc4543_gcm_setauthsize(struct crypto_aead *authenc,
-                                      unsigned int authsize)
-{
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(authenc);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "authsize %d\n", authsize);
-
-       if (authsize != 16)
-               return -EINVAL;
-
-       return ssi_aead_setauthsize(authenc, authsize);
-}
-
-static int ssi_rfc4106_gcm_encrypt(struct aead_request *req)
-{
-       /* Very similar to ssi_aead_encrypt() above. */
-
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       int rc = -EINVAL;
-
-       if (!valid_assoclen(req)) {
-               dev_err(dev, "invalid Assoclen:%u\n", req->assoclen);
-               goto out;
-       }
-
-       /* No generated IV required */
-       areq_ctx->backup_iv = req->iv;
-       areq_ctx->backup_giv = NULL;
-
-       areq_ctx->plaintext_authenticate_only = false;
-
-       ssi_rfc4_gcm_process(req);
-       areq_ctx->is_gcm4543 = true;
-
-       rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
-       if (rc != -EINPROGRESS)
-               req->iv = areq_ctx->backup_iv;
-out:
-       return rc;
-}
-
-static int ssi_rfc4543_gcm_encrypt(struct aead_request *req)
-{
-       /* Very similar to ssi_aead_encrypt() above. */
-
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       int rc;
-
-       //plaintext is not encryped with rfc4543
-       areq_ctx->plaintext_authenticate_only = true;
-
-       /* No generated IV required */
-       areq_ctx->backup_iv = req->iv;
-       areq_ctx->backup_giv = NULL;
-
-       ssi_rfc4_gcm_process(req);
-       areq_ctx->is_gcm4543 = true;
-
-       rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
-       if (rc != -EINPROGRESS)
-               req->iv = areq_ctx->backup_iv;
-
-       return rc;
-}
-
-static int ssi_rfc4106_gcm_decrypt(struct aead_request *req)
-{
-       /* Very similar to ssi_aead_decrypt() above. */
-
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       int rc = -EINVAL;
-
-       if (!valid_assoclen(req)) {
-               dev_err(dev, "invalid Assoclen:%u\n", req->assoclen);
-               goto out;
-       }
-
-       /* No generated IV required */
-       areq_ctx->backup_iv = req->iv;
-       areq_ctx->backup_giv = NULL;
-
-       areq_ctx->plaintext_authenticate_only = false;
-
-       ssi_rfc4_gcm_process(req);
-       areq_ctx->is_gcm4543 = true;
-
-       rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_DECRYPT);
-       if (rc != -EINPROGRESS)
-               req->iv = areq_ctx->backup_iv;
-out:
-       return rc;
-}
-
-static int ssi_rfc4543_gcm_decrypt(struct aead_request *req)
-{
-       /* Very similar to ssi_aead_decrypt() above. */
-
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       int rc;
-
-       //plaintext is not decryped with rfc4543
-       areq_ctx->plaintext_authenticate_only = true;
-
-       /* No generated IV required */
-       areq_ctx->backup_iv = req->iv;
-       areq_ctx->backup_giv = NULL;
-
-       ssi_rfc4_gcm_process(req);
-       areq_ctx->is_gcm4543 = true;
-
-       rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_DECRYPT);
-       if (rc != -EINPROGRESS)
-               req->iv = areq_ctx->backup_iv;
-
-       return rc;
-}
-#endif /* SSI_CC_HAS_AES_GCM */
-
-/* DX Block aead alg */
-static struct ssi_alg_template aead_algs[] = {
-       {
-               .name = "authenc(hmac(sha1),cbc(aes))",
-               .driver_name = "authenc-hmac-sha1-cbc-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_aead_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = AES_BLOCK_SIZE,
-                       .maxauthsize = SHA1_DIGEST_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CBC,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_SHA1,
-       },
-       {
-               .name = "authenc(hmac(sha1),cbc(des3_ede))",
-               .driver_name = "authenc-hmac-sha1-cbc-des3-dx",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_aead_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = DES3_EDE_BLOCK_SIZE,
-                       .maxauthsize = SHA1_DIGEST_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CBC,
-               .flow_mode = S_DIN_to_DES,
-               .auth_mode = DRV_HASH_SHA1,
-       },
-       {
-               .name = "authenc(hmac(sha256),cbc(aes))",
-               .driver_name = "authenc-hmac-sha256-cbc-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_aead_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = AES_BLOCK_SIZE,
-                       .maxauthsize = SHA256_DIGEST_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CBC,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_SHA256,
-       },
-       {
-               .name = "authenc(hmac(sha256),cbc(des3_ede))",
-               .driver_name = "authenc-hmac-sha256-cbc-des3-dx",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_aead_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = DES3_EDE_BLOCK_SIZE,
-                       .maxauthsize = SHA256_DIGEST_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CBC,
-               .flow_mode = S_DIN_to_DES,
-               .auth_mode = DRV_HASH_SHA256,
-       },
-       {
-               .name = "authenc(xcbc(aes),cbc(aes))",
-               .driver_name = "authenc-xcbc-aes-cbc-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_aead_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = AES_BLOCK_SIZE,
-                       .maxauthsize = AES_BLOCK_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CBC,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_XCBC_MAC,
-       },
-       {
-               .name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
-               .driver_name = "authenc-hmac-sha1-rfc3686-ctr-aes-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_aead_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = CTR_RFC3686_IV_SIZE,
-                       .maxauthsize = SHA1_DIGEST_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CTR,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_SHA1,
-       },
-       {
-               .name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
-               .driver_name = "authenc-hmac-sha256-rfc3686-ctr-aes-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_aead_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = CTR_RFC3686_IV_SIZE,
-                       .maxauthsize = SHA256_DIGEST_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CTR,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_SHA256,
-       },
-       {
-               .name = "authenc(xcbc(aes),rfc3686(ctr(aes)))",
-               .driver_name = "authenc-xcbc-aes-rfc3686-ctr-aes-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_aead_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = CTR_RFC3686_IV_SIZE,
-                       .maxauthsize = AES_BLOCK_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CTR,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_XCBC_MAC,
-       },
-#if SSI_CC_HAS_AES_CCM
-       {
-               .name = "ccm(aes)",
-               .driver_name = "ccm-aes-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_ccm_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = AES_BLOCK_SIZE,
-                       .maxauthsize = AES_BLOCK_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CCM,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_NULL,
-       },
-       {
-               .name = "rfc4309(ccm(aes))",
-               .driver_name = "rfc4309-ccm-aes-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_rfc4309_ccm_setkey,
-                       .setauthsize = ssi_rfc4309_ccm_setauthsize,
-                       .encrypt = ssi_rfc4309_ccm_encrypt,
-                       .decrypt = ssi_rfc4309_ccm_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = CCM_BLOCK_IV_SIZE,
-                       .maxauthsize = AES_BLOCK_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CCM,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_NULL,
-       },
-#endif /*SSI_CC_HAS_AES_CCM*/
-#if SSI_CC_HAS_AES_GCM
-       {
-               .name = "gcm(aes)",
-               .driver_name = "gcm-aes-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_aead_setkey,
-                       .setauthsize = ssi_gcm_setauthsize,
-                       .encrypt = ssi_aead_encrypt,
-                       .decrypt = ssi_aead_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = 12,
-                       .maxauthsize = AES_BLOCK_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_GCTR,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_NULL,
-       },
-       {
-               .name = "rfc4106(gcm(aes))",
-               .driver_name = "rfc4106-gcm-aes-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_rfc4106_gcm_setkey,
-                       .setauthsize = ssi_rfc4106_gcm_setauthsize,
-                       .encrypt = ssi_rfc4106_gcm_encrypt,
-                       .decrypt = ssi_rfc4106_gcm_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = GCM_BLOCK_RFC4_IV_SIZE,
-                       .maxauthsize = AES_BLOCK_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_GCTR,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_NULL,
-       },
-       {
-               .name = "rfc4543(gcm(aes))",
-               .driver_name = "rfc4543-gcm-aes-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = ssi_rfc4543_gcm_setkey,
-                       .setauthsize = ssi_rfc4543_gcm_setauthsize,
-                       .encrypt = ssi_rfc4543_gcm_encrypt,
-                       .decrypt = ssi_rfc4543_gcm_decrypt,
-                       .init = ssi_aead_init,
-                       .exit = ssi_aead_exit,
-                       .ivsize = GCM_BLOCK_RFC4_IV_SIZE,
-                       .maxauthsize = AES_BLOCK_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_GCTR,
-               .flow_mode = S_DIN_to_AES,
-               .auth_mode = DRV_HASH_NULL,
-       },
-#endif /*SSI_CC_HAS_AES_GCM*/
-};
-
-static struct ssi_crypto_alg *ssi_aead_create_alg(
-                       struct ssi_alg_template *template,
-                       struct device *dev)
-{
-       struct ssi_crypto_alg *t_alg;
-       struct aead_alg *alg;
-
-       t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
-       if (!t_alg)
-               return ERR_PTR(-ENOMEM);
-
-       alg = &template->template_aead;
-
-       snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", template->name);
-       snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
-                template->driver_name);
-       alg->base.cra_module = THIS_MODULE;
-       alg->base.cra_priority = SSI_CRA_PRIO;
-
-       alg->base.cra_ctxsize = sizeof(struct ssi_aead_ctx);
-       alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
-                        template->type;
-       alg->init = ssi_aead_init;
-       alg->exit = ssi_aead_exit;
-
-       t_alg->aead_alg = *alg;
-
-       t_alg->cipher_mode = template->cipher_mode;
-       t_alg->flow_mode = template->flow_mode;
-       t_alg->auth_mode = template->auth_mode;
-
-       return t_alg;
-}
-
-int ssi_aead_free(struct ssi_drvdata *drvdata)
-{
-       struct ssi_crypto_alg *t_alg, *n;
-       struct ssi_aead_handle *aead_handle =
-               (struct ssi_aead_handle *)drvdata->aead_handle;
-
-       if (aead_handle) {
-               /* Remove registered algs */
-               list_for_each_entry_safe(t_alg, n, &aead_handle->aead_list, entry) {
-                       crypto_unregister_aead(&t_alg->aead_alg);
-                       list_del(&t_alg->entry);
-                       kfree(t_alg);
-               }
-               kfree(aead_handle);
-               drvdata->aead_handle = NULL;
-       }
-
-       return 0;
-}
-
-int ssi_aead_alloc(struct ssi_drvdata *drvdata)
-{
-       struct ssi_aead_handle *aead_handle;
-       struct ssi_crypto_alg *t_alg;
-       int rc = -ENOMEM;
-       int alg;
-       struct device *dev = drvdata_to_dev(drvdata);
-
-       aead_handle = kmalloc(sizeof(*aead_handle), GFP_KERNEL);
-       if (!aead_handle) {
-               rc = -ENOMEM;
-               goto fail0;
-       }
-
-       INIT_LIST_HEAD(&aead_handle->aead_list);
-       drvdata->aead_handle = aead_handle;
-
-       aead_handle->sram_workspace_addr = ssi_sram_mgr_alloc(
-               drvdata, MAX_HMAC_DIGEST_SIZE);
-       if (aead_handle->sram_workspace_addr == NULL_SRAM_ADDR) {
-               dev_err(dev, "SRAM pool exhausted\n");
-               rc = -ENOMEM;
-               goto fail1;
-       }
-
-       /* Linux crypto */
-       for (alg = 0; alg < ARRAY_SIZE(aead_algs); alg++) {
-               t_alg = ssi_aead_create_alg(&aead_algs[alg], dev);
-               if (IS_ERR(t_alg)) {
-                       rc = PTR_ERR(t_alg);
-                       dev_err(dev, "%s alg allocation failed\n",
-                               aead_algs[alg].driver_name);
-                       goto fail1;
-               }
-               t_alg->drvdata = drvdata;
-               rc = crypto_register_aead(&t_alg->aead_alg);
-               if (unlikely(rc != 0)) {
-                       dev_err(dev, "%s alg registration failed\n",
-                               t_alg->aead_alg.base.cra_driver_name);
-                       goto fail2;
-               } else {
-                       list_add_tail(&t_alg->entry, &aead_handle->aead_list);
-                       dev_dbg(dev, "Registered %s\n",
-                               t_alg->aead_alg.base.cra_driver_name);
-               }
-       }
-
-       return 0;
-
-fail2:
-       kfree(t_alg);
-fail1:
-       ssi_aead_free(drvdata);
-fail0:
-       return rc;
-}
diff --git a/drivers/staging/ccree/ssi_aead.h b/drivers/staging/ccree/ssi_aead.h
deleted file mode 100644 (file)
index e85bcd9..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file ssi_aead.h
- * ARM CryptoCell AEAD Crypto API
- */
-
-#ifndef __SSI_AEAD_H__
-#define __SSI_AEAD_H__
-
-#include <linux/kernel.h>
-#include <crypto/algapi.h>
-#include <crypto/ctr.h>
-
-/* mac_cmp - HW writes 8 B but all bytes hold the same value */
-#define ICV_CMP_SIZE 8
-#define CCM_CONFIG_BUF_SIZE (AES_BLOCK_SIZE * 3)
-#define MAX_MAC_SIZE MAX(SHA256_DIGEST_SIZE, AES_BLOCK_SIZE)
-
-/* defines for AES GCM configuration buffer */
-#define GCM_BLOCK_LEN_SIZE 8
-
-#define GCM_BLOCK_RFC4_IV_OFFSET       4
-#define GCM_BLOCK_RFC4_IV_SIZE         8  /* IV size for rfc's */
-#define GCM_BLOCK_RFC4_NONCE_OFFSET    0
-#define GCM_BLOCK_RFC4_NONCE_SIZE      4
-
-/* Offsets into AES CCM configuration buffer */
-#define CCM_B0_OFFSET 0
-#define CCM_A0_OFFSET 16
-#define CCM_CTR_COUNT_0_OFFSET 32
-/* CCM B0 and CTR_COUNT constants. */
-#define CCM_BLOCK_NONCE_OFFSET 1  /* Nonce offset inside B0 and CTR_COUNT */
-#define CCM_BLOCK_NONCE_SIZE   3  /* Nonce size inside B0 and CTR_COUNT */
-#define CCM_BLOCK_IV_OFFSET    4  /* IV offset inside B0 and CTR_COUNT */
-#define CCM_BLOCK_IV_SIZE      8  /* IV size inside B0 and CTR_COUNT */
-
-enum aead_ccm_header_size {
-       ccm_header_size_null = -1,
-       ccm_header_size_zero = 0,
-       ccm_header_size_2 = 2,
-       ccm_header_size_6 = 6,
-       ccm_header_size_max = S32_MAX
-};
-
-struct aead_req_ctx {
-       /* Allocate cache line although only 4 bytes are needed to
-        *  assure next field falls @ cache line
-        *  Used for both: digest HW compare and CCM/GCM MAC value
-        */
-       u8 mac_buf[MAX_MAC_SIZE] ____cacheline_aligned;
-       u8 ctr_iv[AES_BLOCK_SIZE] ____cacheline_aligned;
-
-       //used in gcm
-       u8 gcm_iv_inc1[AES_BLOCK_SIZE] ____cacheline_aligned;
-       u8 gcm_iv_inc2[AES_BLOCK_SIZE] ____cacheline_aligned;
-       u8 hkey[AES_BLOCK_SIZE] ____cacheline_aligned;
-       struct {
-               u8 len_a[GCM_BLOCK_LEN_SIZE] ____cacheline_aligned;
-               u8 len_c[GCM_BLOCK_LEN_SIZE];
-       } gcm_len_block;
-
-       u8 ccm_config[CCM_CONFIG_BUF_SIZE] ____cacheline_aligned;
-       unsigned int hw_iv_size ____cacheline_aligned; /*HW actual size input*/
-       u8 backup_mac[MAX_MAC_SIZE]; /*used to prevent cache coherence problem*/
-       u8 *backup_iv; /*store iv for generated IV flow*/
-       u8 *backup_giv; /*store iv for rfc3686(ctr) flow*/
-       dma_addr_t mac_buf_dma_addr; /* internal ICV DMA buffer */
-       dma_addr_t ccm_iv0_dma_addr; /* buffer for internal ccm configurations */
-       dma_addr_t icv_dma_addr; /* Phys. address of ICV */
-
-       //used in gcm
-       dma_addr_t gcm_iv_inc1_dma_addr; /* buffer for internal gcm configurations */
-       dma_addr_t gcm_iv_inc2_dma_addr; /* buffer for internal gcm configurations */
-       dma_addr_t hkey_dma_addr; /* Phys. address of hkey */
-       dma_addr_t gcm_block_len_dma_addr; /* Phys. address of gcm block len */
-       bool is_gcm4543;
-
-       u8 *icv_virt_addr; /* Virt. address of ICV */
-       struct async_gen_req_ctx gen_ctx;
-       struct ssi_mlli assoc;
-       struct ssi_mlli src;
-       struct ssi_mlli dst;
-       struct scatterlist *src_sgl;
-       struct scatterlist *dst_sgl;
-       unsigned int src_offset;
-       unsigned int dst_offset;
-       enum ssi_req_dma_buf_type assoc_buff_type;
-       enum ssi_req_dma_buf_type data_buff_type;
-       struct mlli_params mlli_params;
-       unsigned int cryptlen;
-       struct scatterlist ccm_adata_sg;
-       enum aead_ccm_header_size ccm_hdr_size;
-       unsigned int req_authsize;
-       enum drv_cipher_mode cipher_mode;
-       bool is_icv_fragmented;
-       bool is_single_pass;
-       bool plaintext_authenticate_only; //for gcm_rfc4543
-};
-
-int ssi_aead_alloc(struct ssi_drvdata *drvdata);
-int ssi_aead_free(struct ssi_drvdata *drvdata);
-
-#endif /*__SSI_AEAD_H__*/
diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c
deleted file mode 100644 (file)
index 1f8a225..0000000
+++ /dev/null
@@ -1,1776 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/crypto.h>
-#include <linux/version.h>
-#include <crypto/algapi.h>
-#include <crypto/internal/aead.h>
-#include <crypto/hash.h>
-#include <crypto/authenc.h>
-#include <crypto/scatterwalk.h>
-#include <linux/dmapool.h>
-#include <linux/dma-mapping.h>
-#include <linux/crypto.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include "ssi_buffer_mgr.h"
-#include "cc_lli_defs.h"
-#include "ssi_cipher.h"
-#include "ssi_hash.h"
-#include "ssi_aead.h"
-
-#define GET_DMA_BUFFER_TYPE(buff_type) ( \
-       ((buff_type) == SSI_DMA_BUF_NULL) ? "BUF_NULL" : \
-       ((buff_type) == SSI_DMA_BUF_DLLI) ? "BUF_DLLI" : \
-       ((buff_type) == SSI_DMA_BUF_MLLI) ? "BUF_MLLI" : "BUF_INVALID")
-
-enum dma_buffer_type {
-       DMA_NULL_TYPE = -1,
-       DMA_SGL_TYPE = 1,
-       DMA_BUFF_TYPE = 2,
-};
-
-struct buff_mgr_handle {
-       struct dma_pool *mlli_buffs_pool;
-};
-
-union buffer_array_entry {
-       struct scatterlist *sgl;
-       dma_addr_t buffer_dma;
-};
-
-struct buffer_array {
-       unsigned int num_of_buffers;
-       union buffer_array_entry entry[MAX_NUM_OF_BUFFERS_IN_MLLI];
-       unsigned int offset[MAX_NUM_OF_BUFFERS_IN_MLLI];
-       int nents[MAX_NUM_OF_BUFFERS_IN_MLLI];
-       int total_data_len[MAX_NUM_OF_BUFFERS_IN_MLLI];
-       enum dma_buffer_type type[MAX_NUM_OF_BUFFERS_IN_MLLI];
-       bool is_last[MAX_NUM_OF_BUFFERS_IN_MLLI];
-       u32 *mlli_nents[MAX_NUM_OF_BUFFERS_IN_MLLI];
-};
-
-/**
- * ssi_buffer_mgr_get_sgl_nents() - Get scatterlist number of entries.
- *
- * @sg_list: SG list
- * @nbytes: [IN] Total SGL data bytes.
- * @lbytes: [OUT] Returns the amount of bytes at the last entry
- */
-static unsigned int ssi_buffer_mgr_get_sgl_nents(
-       struct device *dev, struct scatterlist *sg_list,
-       unsigned int nbytes, u32 *lbytes, bool *is_chained)
-{
-       unsigned int nents = 0;
-
-       while (nbytes != 0) {
-               if (sg_list->length != 0) {
-                       nents++;
-                       /* get the number of bytes in the last entry */
-                       *lbytes = nbytes;
-                       nbytes -= (sg_list->length > nbytes) ? nbytes : sg_list->length;
-                       sg_list = sg_next(sg_list);
-               } else {
-                       sg_list = (struct scatterlist *)sg_page(sg_list);
-                       if (is_chained)
-                               *is_chained = true;
-               }
-       }
-       dev_dbg(dev, "nents %d last bytes %d\n", nents, *lbytes);
-       return nents;
-}
-
-/**
- * ssi_buffer_mgr_zero_sgl() - Zero scatter scatter list data.
- *
- * @sgl:
- */
-void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len)
-{
-       struct scatterlist *current_sg = sgl;
-       int sg_index = 0;
-
-       while (sg_index <= data_len) {
-               if (!current_sg) {
-                       /* reached the end of the sgl --> just return back */
-                       return;
-               }
-               memset(sg_virt(current_sg), 0, current_sg->length);
-               sg_index += current_sg->length;
-               current_sg = sg_next(current_sg);
-       }
-}
-
-/**
- * ssi_buffer_mgr_copy_scatterlist_portion() - Copy scatter list data,
- * from to_skip to end, to dest and vice versa
- *
- * @dest:
- * @sg:
- * @to_skip:
- * @end:
- * @direct:
- */
-void ssi_buffer_mgr_copy_scatterlist_portion(
-       struct device *dev, u8 *dest,
-       struct scatterlist *sg, u32 to_skip,
-       u32 end, enum ssi_sg_cpy_direct direct)
-{
-       u32 nents, lbytes;
-
-       nents = ssi_buffer_mgr_get_sgl_nents(dev, sg, end, &lbytes, NULL);
-       sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip + 1), to_skip,
-                      (direct == SSI_SG_TO_BUF));
-}
-
-static inline int ssi_buffer_mgr_render_buff_to_mlli(
-       struct device *dev, dma_addr_t buff_dma, u32 buff_size,
-       u32 *curr_nents, u32 **mlli_entry_pp)
-{
-       u32 *mlli_entry_p = *mlli_entry_pp;
-       u32 new_nents;
-
-       /* Verify there is no memory overflow*/
-       new_nents = (*curr_nents + buff_size / CC_MAX_MLLI_ENTRY_SIZE + 1);
-       if (new_nents > MAX_NUM_OF_TOTAL_MLLI_ENTRIES)
-               return -ENOMEM;
-
-       /*handle buffer longer than 64 kbytes */
-       while (buff_size > CC_MAX_MLLI_ENTRY_SIZE) {
-               cc_lli_set_addr(mlli_entry_p, buff_dma);
-               cc_lli_set_size(mlli_entry_p, CC_MAX_MLLI_ENTRY_SIZE);
-               dev_dbg(dev, "entry[%d]: single_buff=0x%08X size=%08X\n",
-                       *curr_nents, mlli_entry_p[LLI_WORD0_OFFSET],
-                       mlli_entry_p[LLI_WORD1_OFFSET]);
-               buff_dma += CC_MAX_MLLI_ENTRY_SIZE;
-               buff_size -= CC_MAX_MLLI_ENTRY_SIZE;
-               mlli_entry_p = mlli_entry_p + 2;
-               (*curr_nents)++;
-       }
-       /*Last entry */
-       cc_lli_set_addr(mlli_entry_p, buff_dma);
-       cc_lli_set_size(mlli_entry_p, buff_size);
-       dev_dbg(dev, "entry[%d]: single_buff=0x%08X size=%08X\n",
-               *curr_nents, mlli_entry_p[LLI_WORD0_OFFSET],
-               mlli_entry_p[LLI_WORD1_OFFSET]);
-       mlli_entry_p = mlli_entry_p + 2;
-       *mlli_entry_pp = mlli_entry_p;
-       (*curr_nents)++;
-       return 0;
-}
-
-static inline int ssi_buffer_mgr_render_scatterlist_to_mlli(
-       struct device *dev, struct scatterlist *sgl,
-       u32 sgl_data_len, u32 sgl_offset, u32 *curr_nents,
-       u32 **mlli_entry_pp)
-{
-       struct scatterlist *curr_sgl = sgl;
-       u32 *mlli_entry_p = *mlli_entry_pp;
-       s32 rc = 0;
-
-       for ( ; (curr_sgl) && (sgl_data_len != 0);
-             curr_sgl = sg_next(curr_sgl)) {
-               u32 entry_data_len =
-                       (sgl_data_len > sg_dma_len(curr_sgl) - sgl_offset) ?
-                               sg_dma_len(curr_sgl) - sgl_offset :
-                               sgl_data_len;
-               sgl_data_len -= entry_data_len;
-               rc = ssi_buffer_mgr_render_buff_to_mlli(
-                       dev, sg_dma_address(curr_sgl) + sgl_offset,
-                       entry_data_len, curr_nents, &mlli_entry_p);
-               if (rc != 0)
-                       return rc;
-
-               sgl_offset = 0;
-       }
-       *mlli_entry_pp = mlli_entry_p;
-       return 0;
-}
-
-static int ssi_buffer_mgr_generate_mlli(
-       struct device *dev,
-       struct buffer_array *sg_data,
-       struct mlli_params *mlli_params)
-{
-       u32 *mlli_p;
-       u32 total_nents = 0, prev_total_nents = 0;
-       int rc = 0, i;
-
-       dev_dbg(dev, "NUM of SG's = %d\n", sg_data->num_of_buffers);
-
-       /* Allocate memory from the pointed pool */
-       mlli_params->mlli_virt_addr = dma_pool_alloc(
-                       mlli_params->curr_pool, GFP_KERNEL,
-                       &mlli_params->mlli_dma_addr);
-       if (unlikely(!mlli_params->mlli_virt_addr)) {
-               dev_err(dev, "dma_pool_alloc() failed\n");
-               rc = -ENOMEM;
-               goto build_mlli_exit;
-       }
-       /* Point to start of MLLI */
-       mlli_p = (u32 *)mlli_params->mlli_virt_addr;
-       /* go over all SG's and link it to one MLLI table */
-       for (i = 0; i < sg_data->num_of_buffers; i++) {
-               if (sg_data->type[i] == DMA_SGL_TYPE)
-                       rc = ssi_buffer_mgr_render_scatterlist_to_mlli(
-                               dev, sg_data->entry[i].sgl,
-                               sg_data->total_data_len[i], sg_data->offset[i],
-                               &total_nents, &mlli_p);
-               else /*DMA_BUFF_TYPE*/
-                       rc = ssi_buffer_mgr_render_buff_to_mlli(
-                               dev, sg_data->entry[i].buffer_dma,
-                               sg_data->total_data_len[i], &total_nents,
-                               &mlli_p);
-               if (rc != 0)
-                       return rc;
-
-               /* set last bit in the current table */
-               if (sg_data->mlli_nents[i]) {
-                       /*Calculate the current MLLI table length for the
-                        *length field in the descriptor
-                        */
-                       *sg_data->mlli_nents[i] +=
-                               (total_nents - prev_total_nents);
-                       prev_total_nents = total_nents;
-               }
-       }
-
-       /* Set MLLI size for the bypass operation */
-       mlli_params->mlli_len = (total_nents * LLI_ENTRY_BYTE_SIZE);
-
-       dev_dbg(dev, "MLLI params: virt_addr=%pK dma_addr=%pad mlli_len=0x%X\n",
-               mlli_params->mlli_virt_addr, &mlli_params->mlli_dma_addr,
-               mlli_params->mlli_len);
-
-build_mlli_exit:
-       return rc;
-}
-
-static inline void ssi_buffer_mgr_add_buffer_entry(
-       struct device *dev, struct buffer_array *sgl_data,
-       dma_addr_t buffer_dma, unsigned int buffer_len,
-       bool is_last_entry, u32 *mlli_nents)
-{
-       unsigned int index = sgl_data->num_of_buffers;
-
-       dev_dbg(dev, "index=%u single_buff=%pad buffer_len=0x%08X is_last=%d\n",
-               index, &buffer_dma, buffer_len, is_last_entry);
-       sgl_data->nents[index] = 1;
-       sgl_data->entry[index].buffer_dma = buffer_dma;
-       sgl_data->offset[index] = 0;
-       sgl_data->total_data_len[index] = buffer_len;
-       sgl_data->type[index] = DMA_BUFF_TYPE;
-       sgl_data->is_last[index] = is_last_entry;
-       sgl_data->mlli_nents[index] = mlli_nents;
-       if (sgl_data->mlli_nents[index])
-               *sgl_data->mlli_nents[index] = 0;
-       sgl_data->num_of_buffers++;
-}
-
-static inline void ssi_buffer_mgr_add_scatterlist_entry(
-       struct device *dev,
-       struct buffer_array *sgl_data,
-       unsigned int nents,
-       struct scatterlist *sgl,
-       unsigned int data_len,
-       unsigned int data_offset,
-       bool is_last_table,
-       u32 *mlli_nents)
-{
-       unsigned int index = sgl_data->num_of_buffers;
-
-       dev_dbg(dev, "index=%u nents=%u sgl=%pK data_len=0x%08X is_last=%d\n",
-               index, nents, sgl, data_len, is_last_table);
-       sgl_data->nents[index] = nents;
-       sgl_data->entry[index].sgl = sgl;
-       sgl_data->offset[index] = data_offset;
-       sgl_data->total_data_len[index] = data_len;
-       sgl_data->type[index] = DMA_SGL_TYPE;
-       sgl_data->is_last[index] = is_last_table;
-       sgl_data->mlli_nents[index] = mlli_nents;
-       if (sgl_data->mlli_nents[index])
-               *sgl_data->mlli_nents[index] = 0;
-       sgl_data->num_of_buffers++;
-}
-
-static int
-ssi_buffer_mgr_dma_map_sg(struct device *dev, struct scatterlist *sg, u32 nents,
-                         enum dma_data_direction direction)
-{
-       u32 i, j;
-       struct scatterlist *l_sg = sg;
-
-       for (i = 0; i < nents; i++) {
-               if (!l_sg)
-                       break;
-               if (unlikely(dma_map_sg(dev, l_sg, 1, direction) != 1)) {
-                       dev_err(dev, "dma_map_page() sg buffer failed\n");
-                       goto err;
-               }
-               l_sg = sg_next(l_sg);
-       }
-       return nents;
-
-err:
-       /* Restore mapped parts */
-       for (j = 0; j < i; j++) {
-               if (!sg)
-                       break;
-               dma_unmap_sg(dev, sg, 1, direction);
-               sg = sg_next(sg);
-       }
-       return 0;
-}
-
-static int ssi_buffer_mgr_map_scatterlist(
-       struct device *dev, struct scatterlist *sg,
-       unsigned int nbytes, int direction,
-       u32 *nents, u32 max_sg_nents,
-       u32 *lbytes, u32 *mapped_nents)
-{
-       bool is_chained = false;
-
-       if (sg_is_last(sg)) {
-               /* One entry only case -set to DLLI */
-               if (unlikely(dma_map_sg(dev, sg, 1, direction) != 1)) {
-                       dev_err(dev, "dma_map_sg() single buffer failed\n");
-                       return -ENOMEM;
-               }
-               dev_dbg(dev, "Mapped sg: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n",
-                       &sg_dma_address(sg), sg_page(sg), sg_virt(sg),
-                       sg->offset, sg->length);
-               *lbytes = nbytes;
-               *nents = 1;
-               *mapped_nents = 1;
-       } else {  /*sg_is_last*/
-               *nents = ssi_buffer_mgr_get_sgl_nents(dev, sg, nbytes, lbytes,
-                                                     &is_chained);
-               if (*nents > max_sg_nents) {
-                       *nents = 0;
-                       dev_err(dev, "Too many fragments. current %d max %d\n",
-                               *nents, max_sg_nents);
-                       return -ENOMEM;
-               }
-               if (!is_chained) {
-                       /* In case of mmu the number of mapped nents might
-                        * be changed from the original sgl nents
-                        */
-                       *mapped_nents = dma_map_sg(dev, sg, *nents, direction);
-                       if (unlikely(*mapped_nents == 0)) {
-                               *nents = 0;
-                               dev_err(dev, "dma_map_sg() sg buffer failed\n");
-                               return -ENOMEM;
-                       }
-               } else {
-                       /*In this case the driver maps entry by entry so it
-                        * must have the same nents before and after map
-                        */
-                       *mapped_nents = ssi_buffer_mgr_dma_map_sg(dev,
-                                                                 sg,
-                                                                 *nents,
-                                                                 direction);
-                       if (unlikely(*mapped_nents != *nents)) {
-                               *nents = *mapped_nents;
-                               dev_err(dev, "dma_map_sg() sg buffer failed\n");
-                               return -ENOMEM;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static inline int
-ssi_aead_handle_config_buf(struct device *dev,
-                          struct aead_req_ctx *areq_ctx,
-                          u8 *config_data,
-                          struct buffer_array *sg_data,
-                          unsigned int assoclen)
-{
-       dev_dbg(dev, " handle additional data config set to DLLI\n");
-       /* create sg for the current buffer */
-       sg_init_one(&areq_ctx->ccm_adata_sg, config_data, AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size);
-       if (unlikely(dma_map_sg(dev, &areq_ctx->ccm_adata_sg, 1,
-                               DMA_TO_DEVICE) != 1)) {
-               dev_err(dev, "dma_map_sg() config buffer failed\n");
-               return -ENOMEM;
-       }
-       dev_dbg(dev, "Mapped curr_buff: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n",
-               &sg_dma_address(&areq_ctx->ccm_adata_sg),
-               sg_page(&areq_ctx->ccm_adata_sg),
-               sg_virt(&areq_ctx->ccm_adata_sg),
-               areq_ctx->ccm_adata_sg.offset, areq_ctx->ccm_adata_sg.length);
-       /* prepare for case of MLLI */
-       if (assoclen > 0) {
-               ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, 1,
-                                                    &areq_ctx->ccm_adata_sg,
-                                                    (AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size),
-                                                    0, false, NULL);
-       }
-       return 0;
-}
-
-static inline int ssi_ahash_handle_curr_buf(struct device *dev,
-                                           struct ahash_req_ctx *areq_ctx,
-                                           u8 *curr_buff,
-                                           u32 curr_buff_cnt,
-                                           struct buffer_array *sg_data)
-{
-       dev_dbg(dev, " handle curr buff %x set to   DLLI\n", curr_buff_cnt);
-       /* create sg for the current buffer */
-       sg_init_one(areq_ctx->buff_sg, curr_buff, curr_buff_cnt);
-       if (unlikely(dma_map_sg(dev, areq_ctx->buff_sg, 1,
-                               DMA_TO_DEVICE) != 1)) {
-               dev_err(dev, "dma_map_sg() src buffer failed\n");
-               return -ENOMEM;
-       }
-       dev_dbg(dev, "Mapped curr_buff: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n",
-               &sg_dma_address(areq_ctx->buff_sg), sg_page(areq_ctx->buff_sg),
-               sg_virt(areq_ctx->buff_sg), areq_ctx->buff_sg->offset,
-               areq_ctx->buff_sg->length);
-       areq_ctx->data_dma_buf_type = SSI_DMA_BUF_DLLI;
-       areq_ctx->curr_sg = areq_ctx->buff_sg;
-       areq_ctx->in_nents = 0;
-       /* prepare for case of MLLI */
-       ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, 1, areq_ctx->buff_sg,
-                                            curr_buff_cnt, 0, false, NULL);
-       return 0;
-}
-
-void ssi_buffer_mgr_unmap_blkcipher_request(
-       struct device *dev,
-       void *ctx,
-       unsigned int ivsize,
-       struct scatterlist *src,
-       struct scatterlist *dst)
-{
-       struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx;
-
-       if (likely(req_ctx->gen_ctx.iv_dma_addr != 0)) {
-               dev_dbg(dev, "Unmapped iv: iv_dma_addr=%pad iv_size=%u\n",
-                       &req_ctx->gen_ctx.iv_dma_addr, ivsize);
-               dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr,
-                                ivsize,
-                                req_ctx->is_giv ? DMA_BIDIRECTIONAL :
-                                DMA_TO_DEVICE);
-       }
-       /* Release pool */
-       if (req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI) {
-               dma_pool_free(req_ctx->mlli_params.curr_pool,
-                             req_ctx->mlli_params.mlli_virt_addr,
-                             req_ctx->mlli_params.mlli_dma_addr);
-       }
-
-       dma_unmap_sg(dev, src, req_ctx->in_nents, DMA_BIDIRECTIONAL);
-       dev_dbg(dev, "Unmapped req->src=%pK\n", sg_virt(src));
-
-       if (src != dst) {
-               dma_unmap_sg(dev, dst, req_ctx->out_nents, DMA_BIDIRECTIONAL);
-               dev_dbg(dev, "Unmapped req->dst=%pK\n", sg_virt(dst));
-       }
-}
-
-int ssi_buffer_mgr_map_blkcipher_request(
-       struct ssi_drvdata *drvdata,
-       void *ctx,
-       unsigned int ivsize,
-       unsigned int nbytes,
-       void *info,
-       struct scatterlist *src,
-       struct scatterlist *dst)
-{
-       struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx;
-       struct mlli_params *mlli_params = &req_ctx->mlli_params;
-       struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
-       struct device *dev = drvdata_to_dev(drvdata);
-       struct buffer_array sg_data;
-       u32 dummy = 0;
-       int rc = 0;
-       u32 mapped_nents = 0;
-
-       req_ctx->dma_buf_type = SSI_DMA_BUF_DLLI;
-       mlli_params->curr_pool = NULL;
-       sg_data.num_of_buffers = 0;
-
-       /* Map IV buffer */
-       if (likely(ivsize != 0)) {
-               dump_byte_array("iv", (u8 *)info, ivsize);
-               req_ctx->gen_ctx.iv_dma_addr =
-                       dma_map_single(dev, (void *)info,
-                                      ivsize,
-                                      req_ctx->is_giv ? DMA_BIDIRECTIONAL :
-                                      DMA_TO_DEVICE);
-               if (unlikely(dma_mapping_error(dev,
-                                              req_ctx->gen_ctx.iv_dma_addr))) {
-                       dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n",
-                               ivsize, info);
-                       return -ENOMEM;
-               }
-               dev_dbg(dev, "Mapped iv %u B at va=%pK to dma=%pad\n",
-                       ivsize, info, &req_ctx->gen_ctx.iv_dma_addr);
-       } else {
-               req_ctx->gen_ctx.iv_dma_addr = 0;
-       }
-
-       /* Map the src SGL */
-       rc = ssi_buffer_mgr_map_scatterlist(dev, src,
-                                           nbytes, DMA_BIDIRECTIONAL,
-                                           &req_ctx->in_nents,
-                                           LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy,
-                                           &mapped_nents);
-       if (unlikely(rc != 0)) {
-               rc = -ENOMEM;
-               goto ablkcipher_exit;
-       }
-       if (mapped_nents > 1)
-               req_ctx->dma_buf_type = SSI_DMA_BUF_MLLI;
-
-       if (unlikely(src == dst)) {
-               /* Handle inplace operation */
-               if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) {
-                       req_ctx->out_nents = 0;
-                       ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data,
-                                                            req_ctx->in_nents,
-                                                            src, nbytes, 0,
-                                                            true,
-                                                            &req_ctx->in_mlli_nents);
-               }
-       } else {
-               /* Map the dst sg */
-               if (unlikely(ssi_buffer_mgr_map_scatterlist(
-                       dev, dst, nbytes,
-                       DMA_BIDIRECTIONAL, &req_ctx->out_nents,
-                       LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy,
-                       &mapped_nents))){
-                       rc = -ENOMEM;
-                       goto ablkcipher_exit;
-               }
-               if (mapped_nents > 1)
-                       req_ctx->dma_buf_type = SSI_DMA_BUF_MLLI;
-
-               if (unlikely((req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI))) {
-                       ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data,
-                                                            req_ctx->in_nents,
-                                                            src, nbytes, 0,
-                                                            true,
-                                                            &req_ctx->in_mlli_nents);
-                       ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data,
-                                                            req_ctx->out_nents,
-                                                            dst, nbytes, 0,
-                                                            true,
-                                                            &req_ctx->out_mlli_nents);
-               }
-       }
-
-       if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) {
-               mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
-               rc = ssi_buffer_mgr_generate_mlli(dev, &sg_data, mlli_params);
-               if (unlikely(rc != 0))
-                       goto ablkcipher_exit;
-       }
-
-       dev_dbg(dev, "areq_ctx->dma_buf_type = %s\n",
-               GET_DMA_BUFFER_TYPE(req_ctx->dma_buf_type));
-
-       return 0;
-
-ablkcipher_exit:
-       ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
-       return rc;
-}
-
-void ssi_buffer_mgr_unmap_aead_request(
-       struct device *dev, struct aead_request *req)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       unsigned int hw_iv_size = areq_ctx->hw_iv_size;
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct ssi_drvdata *drvdata = dev_get_drvdata(dev);
-       u32 dummy;
-       bool chained;
-       u32 size_to_unmap = 0;
-
-       if (areq_ctx->mac_buf_dma_addr != 0) {
-               dma_unmap_single(dev, areq_ctx->mac_buf_dma_addr,
-                                MAX_MAC_SIZE, DMA_BIDIRECTIONAL);
-       }
-
-#if SSI_CC_HAS_AES_GCM
-       if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) {
-               if (areq_ctx->hkey_dma_addr != 0) {
-                       dma_unmap_single(dev, areq_ctx->hkey_dma_addr,
-                                        AES_BLOCK_SIZE, DMA_BIDIRECTIONAL);
-               }
-
-               if (areq_ctx->gcm_block_len_dma_addr != 0) {
-                       dma_unmap_single(dev, areq_ctx->gcm_block_len_dma_addr,
-                                        AES_BLOCK_SIZE, DMA_TO_DEVICE);
-               }
-
-               if (areq_ctx->gcm_iv_inc1_dma_addr != 0) {
-                       dma_unmap_single(dev, areq_ctx->gcm_iv_inc1_dma_addr,
-                                        AES_BLOCK_SIZE, DMA_TO_DEVICE);
-               }
-
-               if (areq_ctx->gcm_iv_inc2_dma_addr != 0) {
-                       dma_unmap_single(dev, areq_ctx->gcm_iv_inc2_dma_addr,
-                                        AES_BLOCK_SIZE, DMA_TO_DEVICE);
-               }
-       }
-#endif
-
-       if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
-               if (areq_ctx->ccm_iv0_dma_addr != 0) {
-                       dma_unmap_single(dev, areq_ctx->ccm_iv0_dma_addr,
-                                        AES_BLOCK_SIZE, DMA_TO_DEVICE);
-               }
-
-               dma_unmap_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE);
-       }
-       if (areq_ctx->gen_ctx.iv_dma_addr != 0) {
-               dma_unmap_single(dev, areq_ctx->gen_ctx.iv_dma_addr,
-                                hw_iv_size, DMA_BIDIRECTIONAL);
-       }
-
-       /*In case a pool was set, a table was
-        *allocated and should be released
-        */
-       if (areq_ctx->mlli_params.curr_pool) {
-               dev_dbg(dev, "free MLLI buffer: dma=%pad virt=%pK\n",
-                       &areq_ctx->mlli_params.mlli_dma_addr,
-                       areq_ctx->mlli_params.mlli_virt_addr);
-               dma_pool_free(areq_ctx->mlli_params.curr_pool,
-                             areq_ctx->mlli_params.mlli_virt_addr,
-                             areq_ctx->mlli_params.mlli_dma_addr);
-       }
-
-       dev_dbg(dev, "Unmapping src sgl: req->src=%pK areq_ctx->src.nents=%u areq_ctx->assoc.nents=%u assoclen:%u cryptlen=%u\n",
-               sg_virt(req->src), areq_ctx->src.nents, areq_ctx->assoc.nents,
-               req->assoclen, req->cryptlen);
-       size_to_unmap = req->assoclen + req->cryptlen;
-       if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT)
-               size_to_unmap += areq_ctx->req_authsize;
-       if (areq_ctx->is_gcm4543)
-               size_to_unmap += crypto_aead_ivsize(tfm);
-
-       dma_unmap_sg(dev, req->src,
-                    ssi_buffer_mgr_get_sgl_nents(dev, req->src, size_to_unmap,
-                                                 &dummy, &chained),
-                    DMA_BIDIRECTIONAL);
-       if (unlikely(req->src != req->dst)) {
-               dev_dbg(dev, "Unmapping dst sgl: req->dst=%pK\n",
-                       sg_virt(req->dst));
-               dma_unmap_sg(dev, req->dst,
-                            ssi_buffer_mgr_get_sgl_nents(dev, req->dst,
-                                                         size_to_unmap,
-                                                         &dummy, &chained),
-                            DMA_BIDIRECTIONAL);
-       }
-       if (drvdata->coherent &&
-           (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) &&
-           likely(req->src == req->dst)) {
-               u32 size_to_skip = req->assoclen;
-
-               if (areq_ctx->is_gcm4543)
-                       size_to_skip += crypto_aead_ivsize(tfm);
-
-               /* copy mac to a temporary location to deal with possible
-                * data memory overriding that caused by cache coherence problem.
-                */
-               ssi_buffer_mgr_copy_scatterlist_portion(
-                       dev, areq_ctx->backup_mac, req->src,
-                       size_to_skip + req->cryptlen - areq_ctx->req_authsize,
-                       size_to_skip + req->cryptlen, SSI_SG_FROM_BUF);
-       }
-}
-
-static inline int ssi_buffer_mgr_get_aead_icv_nents(
-       struct device *dev,
-       struct scatterlist *sgl,
-       unsigned int sgl_nents,
-       unsigned int authsize,
-       u32 last_entry_data_size,
-       bool *is_icv_fragmented)
-{
-       unsigned int icv_max_size = 0;
-       unsigned int icv_required_size = authsize > last_entry_data_size ? (authsize - last_entry_data_size) : authsize;
-       unsigned int nents;
-       unsigned int i;
-
-       if (sgl_nents < MAX_ICV_NENTS_SUPPORTED) {
-               *is_icv_fragmented = false;
-               return 0;
-       }
-
-       for (i = 0 ; i < (sgl_nents - MAX_ICV_NENTS_SUPPORTED) ; i++) {
-               if (!sgl)
-                       break;
-               sgl = sg_next(sgl);
-       }
-
-       if (sgl)
-               icv_max_size = sgl->length;
-
-       if (last_entry_data_size > authsize) {
-               nents = 0; /* ICV attached to data in last entry (not fragmented!) */
-               *is_icv_fragmented = false;
-       } else if (last_entry_data_size == authsize) {
-               nents = 1; /* ICV placed in whole last entry (not fragmented!) */
-               *is_icv_fragmented = false;
-       } else if (icv_max_size > icv_required_size) {
-               nents = 1;
-               *is_icv_fragmented = true;
-       } else if (icv_max_size == icv_required_size) {
-               nents = 2;
-               *is_icv_fragmented = true;
-       } else {
-               dev_err(dev, "Unsupported num. of ICV fragments (> %d)\n",
-                       MAX_ICV_NENTS_SUPPORTED);
-               nents = -1; /*unsupported*/
-       }
-       dev_dbg(dev, "is_frag=%s icv_nents=%u\n",
-               (*is_icv_fragmented ? "true" : "false"), nents);
-
-       return nents;
-}
-
-static inline int ssi_buffer_mgr_aead_chain_iv(
-       struct ssi_drvdata *drvdata,
-       struct aead_request *req,
-       struct buffer_array *sg_data,
-       bool is_last, bool do_chain)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       unsigned int hw_iv_size = areq_ctx->hw_iv_size;
-       struct device *dev = drvdata_to_dev(drvdata);
-       int rc = 0;
-
-       if (unlikely(!req->iv)) {
-               areq_ctx->gen_ctx.iv_dma_addr = 0;
-               goto chain_iv_exit;
-       }
-
-       areq_ctx->gen_ctx.iv_dma_addr = dma_map_single(dev, req->iv, hw_iv_size,
-                                                      DMA_BIDIRECTIONAL);
-       if (unlikely(dma_mapping_error(dev, areq_ctx->gen_ctx.iv_dma_addr))) {
-               dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n",
-                       hw_iv_size, req->iv);
-               rc = -ENOMEM;
-               goto chain_iv_exit;
-       }
-
-       dev_dbg(dev, "Mapped iv %u B at va=%pK to dma=%pad\n",
-               hw_iv_size, req->iv, &areq_ctx->gen_ctx.iv_dma_addr);
-       if (do_chain && areq_ctx->plaintext_authenticate_only) {  // TODO: what about CTR?? ask Ron
-               struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-               unsigned int iv_size_to_authenc = crypto_aead_ivsize(tfm);
-               unsigned int iv_ofs = GCM_BLOCK_RFC4_IV_OFFSET;
-               /* Chain to given list */
-               ssi_buffer_mgr_add_buffer_entry(
-                       dev, sg_data,
-                       areq_ctx->gen_ctx.iv_dma_addr + iv_ofs,
-                       iv_size_to_authenc, is_last,
-                       &areq_ctx->assoc.mlli_nents);
-               areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI;
-       }
-
-chain_iv_exit:
-       return rc;
-}
-
-static inline int ssi_buffer_mgr_aead_chain_assoc(
-       struct ssi_drvdata *drvdata,
-       struct aead_request *req,
-       struct buffer_array *sg_data,
-       bool is_last, bool do_chain)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       int rc = 0;
-       u32 mapped_nents = 0;
-       struct scatterlist *current_sg = req->src;
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       unsigned int sg_index = 0;
-       u32 size_of_assoc = req->assoclen;
-       struct device *dev = drvdata_to_dev(drvdata);
-
-       if (areq_ctx->is_gcm4543)
-               size_of_assoc += crypto_aead_ivsize(tfm);
-
-       if (!sg_data) {
-               rc = -EINVAL;
-               goto chain_assoc_exit;
-       }
-
-       if (unlikely(req->assoclen == 0)) {
-               areq_ctx->assoc_buff_type = SSI_DMA_BUF_NULL;
-               areq_ctx->assoc.nents = 0;
-               areq_ctx->assoc.mlli_nents = 0;
-               dev_dbg(dev, "Chain assoc of length 0: buff_type=%s nents=%u\n",
-                       GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type),
-                       areq_ctx->assoc.nents);
-               goto chain_assoc_exit;
-       }
-
-       //iterate over the sgl to see how many entries are for associated data
-       //it is assumed that if we reach here , the sgl is already mapped
-       sg_index = current_sg->length;
-       if (sg_index > size_of_assoc) { //the first entry in the scatter list contains all the associated data
-               mapped_nents++;
-       } else {
-               while (sg_index <= size_of_assoc) {
-                       current_sg = sg_next(current_sg);
-                       //if have reached the end of the sgl, then this is unexpected
-                       if (!current_sg) {
-                               dev_err(dev, "reached end of sg list. unexpected\n");
-                               return -EINVAL;
-                       }
-                       sg_index += current_sg->length;
-                       mapped_nents++;
-               }
-       }
-       if (unlikely(mapped_nents > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES)) {
-               dev_err(dev, "Too many fragments. current %d max %d\n",
-                       mapped_nents, LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES);
-               return -ENOMEM;
-       }
-       areq_ctx->assoc.nents = mapped_nents;
-
-       /* in CCM case we have additional entry for
-        * ccm header configurations
-        */
-       if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
-               if (unlikely((mapped_nents + 1) >
-                       LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES)) {
-                       dev_err(dev, "CCM case.Too many fragments. Current %d max %d\n",
-                               (areq_ctx->assoc.nents + 1),
-                               LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES);
-                       rc = -ENOMEM;
-                       goto chain_assoc_exit;
-               }
-       }
-
-       if (likely(mapped_nents == 1) &&
-           (areq_ctx->ccm_hdr_size == ccm_header_size_null))
-               areq_ctx->assoc_buff_type = SSI_DMA_BUF_DLLI;
-       else
-               areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI;
-
-       if (unlikely((do_chain) ||
-                    (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI))) {
-               dev_dbg(dev, "Chain assoc: buff_type=%s nents=%u\n",
-                       GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type),
-                       areq_ctx->assoc.nents);
-               ssi_buffer_mgr_add_scatterlist_entry(
-                       dev, sg_data, areq_ctx->assoc.nents,
-                       req->src, req->assoclen, 0, is_last,
-                       &areq_ctx->assoc.mlli_nents);
-               areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI;
-       }
-
-chain_assoc_exit:
-       return rc;
-}
-
-static inline void ssi_buffer_mgr_prepare_aead_data_dlli(
-       struct aead_request *req,
-       u32 *src_last_bytes, u32 *dst_last_bytes)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
-       unsigned int authsize = areq_ctx->req_authsize;
-
-       areq_ctx->is_icv_fragmented = false;
-       if (likely(req->src == req->dst)) {
-               /*INPLACE*/
-               areq_ctx->icv_dma_addr = sg_dma_address(
-                       areq_ctx->src_sgl) +
-                       (*src_last_bytes - authsize);
-               areq_ctx->icv_virt_addr = sg_virt(
-                       areq_ctx->src_sgl) +
-                       (*src_last_bytes - authsize);
-       } else if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
-               /*NON-INPLACE and DECRYPT*/
-               areq_ctx->icv_dma_addr = sg_dma_address(
-                       areq_ctx->src_sgl) +
-                       (*src_last_bytes - authsize);
-               areq_ctx->icv_virt_addr = sg_virt(
-                       areq_ctx->src_sgl) +
-                       (*src_last_bytes - authsize);
-       } else {
-               /*NON-INPLACE and ENCRYPT*/
-               areq_ctx->icv_dma_addr = sg_dma_address(
-                       areq_ctx->dst_sgl) +
-                       (*dst_last_bytes - authsize);
-               areq_ctx->icv_virt_addr = sg_virt(
-                       areq_ctx->dst_sgl) +
-                       (*dst_last_bytes - authsize);
-       }
-}
-
-static inline int ssi_buffer_mgr_prepare_aead_data_mlli(
-       struct ssi_drvdata *drvdata,
-       struct aead_request *req,
-       struct buffer_array *sg_data,
-       u32 *src_last_bytes, u32 *dst_last_bytes,
-       bool is_last_table)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
-       unsigned int authsize = areq_ctx->req_authsize;
-       int rc = 0, icv_nents;
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       struct device *dev = drvdata_to_dev(drvdata);
-
-       if (likely(req->src == req->dst)) {
-               /*INPLACE*/
-               ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data,
-                                                    areq_ctx->src.nents,
-                                                    areq_ctx->src_sgl,
-                                                    areq_ctx->cryptlen,
-                                                    areq_ctx->src_offset,
-                                                    is_last_table,
-                                                    &areq_ctx->src.mlli_nents);
-
-               icv_nents = ssi_buffer_mgr_get_aead_icv_nents(dev,
-                                                             areq_ctx->src_sgl,
-                                                             areq_ctx->src.nents,
-                                                             authsize,
-                                                             *src_last_bytes,
-                                                             &areq_ctx->is_icv_fragmented);
-               if (unlikely(icv_nents < 0)) {
-                       rc = -ENOTSUPP;
-                       goto prepare_data_mlli_exit;
-               }
-
-               if (unlikely(areq_ctx->is_icv_fragmented)) {
-                       /* Backup happens only when ICV is fragmented, ICV
-                        * verification is made by CPU compare in order to simplify
-                        * MAC verification upon request completion
-                        */
-                       if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
-                               if (!drvdata->coherent) {
-                               /* In coherent platforms (e.g. ACP)
-                                * already copying ICV for any
-                                * INPLACE-DECRYPT operation, hence
-                                * we must neglect this code.
-                                */
-                                       u32 skip = req->assoclen;
-
-                                       if (areq_ctx->is_gcm4543)
-                                               skip += crypto_aead_ivsize(tfm);
-
-                                       ssi_buffer_mgr_copy_scatterlist_portion(
-                                               dev, areq_ctx->backup_mac,
-                                               req->src,
-                                               (skip + req->cryptlen -
-                                                areq_ctx->req_authsize),
-                                               skip + req->cryptlen,
-                                               SSI_SG_TO_BUF);
-                               }
-                               areq_ctx->icv_virt_addr = areq_ctx->backup_mac;
-                       } else {
-                               areq_ctx->icv_virt_addr = areq_ctx->mac_buf;
-                               areq_ctx->icv_dma_addr = areq_ctx->mac_buf_dma_addr;
-                       }
-               } else { /* Contig. ICV */
-                       /*Should hanlde if the sg is not contig.*/
-                       areq_ctx->icv_dma_addr = sg_dma_address(
-                               &areq_ctx->src_sgl[areq_ctx->src.nents - 1]) +
-                               (*src_last_bytes - authsize);
-                       areq_ctx->icv_virt_addr = sg_virt(
-                               &areq_ctx->src_sgl[areq_ctx->src.nents - 1]) +
-                               (*src_last_bytes - authsize);
-               }
-
-       } else if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
-               /*NON-INPLACE and DECRYPT*/
-               ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data,
-                                                    areq_ctx->src.nents,
-                                                    areq_ctx->src_sgl,
-                                                    areq_ctx->cryptlen,
-                                                    areq_ctx->src_offset,
-                                                    is_last_table,
-                                                    &areq_ctx->src.mlli_nents);
-               ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data,
-                                                    areq_ctx->dst.nents,
-                                                    areq_ctx->dst_sgl,
-                                                    areq_ctx->cryptlen,
-                                                    areq_ctx->dst_offset,
-                                                    is_last_table,
-                                                    &areq_ctx->dst.mlli_nents);
-
-               icv_nents = ssi_buffer_mgr_get_aead_icv_nents(dev,
-                                                             areq_ctx->src_sgl,
-                                                             areq_ctx->src.nents,
-                                                             authsize,
-                                                             *src_last_bytes,
-                                                             &areq_ctx->is_icv_fragmented);
-               if (unlikely(icv_nents < 0)) {
-                       rc = -ENOTSUPP;
-                       goto prepare_data_mlli_exit;
-               }
-
-               if (unlikely(areq_ctx->is_icv_fragmented)) {
-                       /* Backup happens only when ICV is fragmented, ICV
-                        * verification is made by CPU compare in order to simplify
-                        * MAC verification upon request completion
-                        */
-                       u32 size_to_skip = req->assoclen;
-
-                       if (areq_ctx->is_gcm4543)
-                               size_to_skip += crypto_aead_ivsize(tfm);
-
-                       ssi_buffer_mgr_copy_scatterlist_portion(
-                               dev, areq_ctx->backup_mac, req->src,
-                               size_to_skip + req->cryptlen - areq_ctx->req_authsize,
-                               size_to_skip + req->cryptlen, SSI_SG_TO_BUF);
-                       areq_ctx->icv_virt_addr = areq_ctx->backup_mac;
-               } else { /* Contig. ICV */
-                       /*Should hanlde if the sg is not contig.*/
-                       areq_ctx->icv_dma_addr = sg_dma_address(
-                               &areq_ctx->src_sgl[areq_ctx->src.nents - 1]) +
-                               (*src_last_bytes - authsize);
-                       areq_ctx->icv_virt_addr = sg_virt(
-                               &areq_ctx->src_sgl[areq_ctx->src.nents - 1]) +
-                               (*src_last_bytes - authsize);
-               }
-
-       } else {
-               /*NON-INPLACE and ENCRYPT*/
-               ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data,
-                                                    areq_ctx->dst.nents,
-                                                    areq_ctx->dst_sgl,
-                                                    areq_ctx->cryptlen,
-                                                    areq_ctx->dst_offset,
-                                                    is_last_table,
-                                                    &areq_ctx->dst.mlli_nents);
-               ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data,
-                                                    areq_ctx->src.nents,
-                                                    areq_ctx->src_sgl,
-                                                    areq_ctx->cryptlen,
-                                                    areq_ctx->src_offset,
-                                                    is_last_table,
-                                                    &areq_ctx->src.mlli_nents);
-
-               icv_nents = ssi_buffer_mgr_get_aead_icv_nents(dev,
-                                                             areq_ctx->dst_sgl,
-                                                             areq_ctx->dst.nents,
-                                                             authsize,
-                                                             *dst_last_bytes,
-                       &areq_ctx->is_icv_fragmented);
-               if (unlikely(icv_nents < 0)) {
-                       rc = -ENOTSUPP;
-                       goto prepare_data_mlli_exit;
-               }
-
-               if (likely(!areq_ctx->is_icv_fragmented)) {
-                       /* Contig. ICV */
-                       areq_ctx->icv_dma_addr = sg_dma_address(
-                               &areq_ctx->dst_sgl[areq_ctx->dst.nents - 1]) +
-                               (*dst_last_bytes - authsize);
-                       areq_ctx->icv_virt_addr = sg_virt(
-                               &areq_ctx->dst_sgl[areq_ctx->dst.nents - 1]) +
-                               (*dst_last_bytes - authsize);
-               } else {
-                       areq_ctx->icv_dma_addr = areq_ctx->mac_buf_dma_addr;
-                       areq_ctx->icv_virt_addr = areq_ctx->mac_buf;
-               }
-       }
-
-prepare_data_mlli_exit:
-       return rc;
-}
-
-static inline int ssi_buffer_mgr_aead_chain_data(
-       struct ssi_drvdata *drvdata,
-       struct aead_request *req,
-       struct buffer_array *sg_data,
-       bool is_last_table, bool do_chain)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       struct device *dev = drvdata_to_dev(drvdata);
-       enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
-       unsigned int authsize = areq_ctx->req_authsize;
-       int src_last_bytes = 0, dst_last_bytes = 0;
-       int rc = 0;
-       u32 src_mapped_nents = 0, dst_mapped_nents = 0;
-       u32 offset = 0;
-       unsigned int size_for_map = req->assoclen + req->cryptlen; /*non-inplace mode*/
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       u32 sg_index = 0;
-       bool chained = false;
-       bool is_gcm4543 = areq_ctx->is_gcm4543;
-       u32 size_to_skip = req->assoclen;
-
-       if (is_gcm4543)
-               size_to_skip += crypto_aead_ivsize(tfm);
-
-       offset = size_to_skip;
-
-       if (!sg_data)
-               return -EINVAL;
-
-       areq_ctx->src_sgl = req->src;
-       areq_ctx->dst_sgl = req->dst;
-
-       if (is_gcm4543)
-               size_for_map += crypto_aead_ivsize(tfm);
-
-       size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0;
-       src_mapped_nents = ssi_buffer_mgr_get_sgl_nents(dev, req->src,
-                                                       size_for_map,
-                                                       &src_last_bytes,
-                                                       &chained);
-       sg_index = areq_ctx->src_sgl->length;
-       //check where the data starts
-       while (sg_index <= size_to_skip) {
-               offset -= areq_ctx->src_sgl->length;
-               areq_ctx->src_sgl = sg_next(areq_ctx->src_sgl);
-               //if have reached the end of the sgl, then this is unexpected
-               if (!areq_ctx->src_sgl) {
-                       dev_err(dev, "reached end of sg list. unexpected\n");
-                       return -EINVAL;
-               }
-               sg_index += areq_ctx->src_sgl->length;
-               src_mapped_nents--;
-       }
-       if (unlikely(src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) {
-               dev_err(dev, "Too many fragments. current %d max %d\n",
-                       src_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES);
-                       return -ENOMEM;
-       }
-
-       areq_ctx->src.nents = src_mapped_nents;
-
-       areq_ctx->src_offset = offset;
-
-       if (req->src != req->dst) {
-               size_for_map = req->assoclen + req->cryptlen;
-               size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0;
-               if (is_gcm4543)
-                       size_for_map += crypto_aead_ivsize(tfm);
-
-               rc = ssi_buffer_mgr_map_scatterlist(dev, req->dst, size_for_map,
-                                                   DMA_BIDIRECTIONAL,
-                                                   &areq_ctx->dst.nents,
-                                                   LLI_MAX_NUM_OF_DATA_ENTRIES,
-                                                   &dst_last_bytes,
-                                                   &dst_mapped_nents);
-               if (unlikely(rc != 0)) {
-                       rc = -ENOMEM;
-                       goto chain_data_exit;
-               }
-       }
-
-       dst_mapped_nents = ssi_buffer_mgr_get_sgl_nents(dev, req->dst,
-                                                       size_for_map,
-                                                       &dst_last_bytes,
-                                                       &chained);
-       sg_index = areq_ctx->dst_sgl->length;
-       offset = size_to_skip;
-
-       //check where the data starts
-       while (sg_index <= size_to_skip) {
-               offset -= areq_ctx->dst_sgl->length;
-               areq_ctx->dst_sgl = sg_next(areq_ctx->dst_sgl);
-               //if have reached the end of the sgl, then this is unexpected
-               if (!areq_ctx->dst_sgl) {
-                       dev_err(dev, "reached end of sg list. unexpected\n");
-                       return -EINVAL;
-               }
-               sg_index += areq_ctx->dst_sgl->length;
-               dst_mapped_nents--;
-       }
-       if (unlikely(dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) {
-               dev_err(dev, "Too many fragments. current %d max %d\n",
-                       dst_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES);
-               return -ENOMEM;
-       }
-       areq_ctx->dst.nents = dst_mapped_nents;
-       areq_ctx->dst_offset = offset;
-       if ((src_mapped_nents > 1) ||
-           (dst_mapped_nents  > 1) ||
-           do_chain) {
-               areq_ctx->data_buff_type = SSI_DMA_BUF_MLLI;
-               rc = ssi_buffer_mgr_prepare_aead_data_mlli(drvdata, req,
-                                                          sg_data,
-                                                          &src_last_bytes,
-                                                          &dst_last_bytes,
-                                                          is_last_table);
-       } else {
-               areq_ctx->data_buff_type = SSI_DMA_BUF_DLLI;
-               ssi_buffer_mgr_prepare_aead_data_dlli(
-                               req, &src_last_bytes, &dst_last_bytes);
-       }
-
-chain_data_exit:
-       return rc;
-}
-
-static void ssi_buffer_mgr_update_aead_mlli_nents(struct ssi_drvdata *drvdata,
-                                                 struct aead_request *req)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       u32 curr_mlli_size = 0;
-
-       if (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) {
-               areq_ctx->assoc.sram_addr = drvdata->mlli_sram_addr;
-               curr_mlli_size = areq_ctx->assoc.mlli_nents *
-                                               LLI_ENTRY_BYTE_SIZE;
-       }
-
-       if (areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI) {
-               /*Inplace case dst nents equal to src nents*/
-               if (req->src == req->dst) {
-                       areq_ctx->dst.mlli_nents = areq_ctx->src.mlli_nents;
-                       areq_ctx->src.sram_addr = drvdata->mlli_sram_addr +
-                                                               curr_mlli_size;
-                       areq_ctx->dst.sram_addr = areq_ctx->src.sram_addr;
-                       if (!areq_ctx->is_single_pass)
-                               areq_ctx->assoc.mlli_nents +=
-                                       areq_ctx->src.mlli_nents;
-               } else {
-                       if (areq_ctx->gen_ctx.op_type ==
-                                       DRV_CRYPTO_DIRECTION_DECRYPT) {
-                               areq_ctx->src.sram_addr =
-                                               drvdata->mlli_sram_addr +
-                                                               curr_mlli_size;
-                               areq_ctx->dst.sram_addr =
-                                               areq_ctx->src.sram_addr +
-                                               areq_ctx->src.mlli_nents *
-                                               LLI_ENTRY_BYTE_SIZE;
-                               if (!areq_ctx->is_single_pass)
-                                       areq_ctx->assoc.mlli_nents +=
-                                               areq_ctx->src.mlli_nents;
-                       } else {
-                               areq_ctx->dst.sram_addr =
-                                               drvdata->mlli_sram_addr +
-                                                               curr_mlli_size;
-                               areq_ctx->src.sram_addr =
-                                               areq_ctx->dst.sram_addr +
-                                               areq_ctx->dst.mlli_nents *
-                                               LLI_ENTRY_BYTE_SIZE;
-                               if (!areq_ctx->is_single_pass)
-                                       areq_ctx->assoc.mlli_nents +=
-                                               areq_ctx->dst.mlli_nents;
-                       }
-               }
-       }
-}
-
-int ssi_buffer_mgr_map_aead_request(
-       struct ssi_drvdata *drvdata, struct aead_request *req)
-{
-       struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
-       struct mlli_params *mlli_params = &areq_ctx->mlli_params;
-       struct device *dev = drvdata_to_dev(drvdata);
-       struct buffer_array sg_data;
-       unsigned int authsize = areq_ctx->req_authsize;
-       struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
-       int rc = 0;
-       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-       bool is_gcm4543 = areq_ctx->is_gcm4543;
-
-       u32 mapped_nents = 0;
-       u32 dummy = 0; /*used for the assoc data fragments */
-       u32 size_to_map = 0;
-
-       mlli_params->curr_pool = NULL;
-       sg_data.num_of_buffers = 0;
-
-       if (drvdata->coherent &&
-           (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) &&
-           likely(req->src == req->dst)) {
-               u32 size_to_skip = req->assoclen;
-
-               if (is_gcm4543)
-                       size_to_skip += crypto_aead_ivsize(tfm);
-
-               /* copy mac to a temporary location to deal with possible
-                * data memory overriding that caused by cache coherence problem.
-                */
-               ssi_buffer_mgr_copy_scatterlist_portion(
-                       dev, areq_ctx->backup_mac, req->src,
-                       size_to_skip + req->cryptlen - areq_ctx->req_authsize,
-                       size_to_skip + req->cryptlen, SSI_SG_TO_BUF);
-       }
-
-       /* cacluate the size for cipher remove ICV in decrypt*/
-       areq_ctx->cryptlen = (areq_ctx->gen_ctx.op_type ==
-                                DRV_CRYPTO_DIRECTION_ENCRYPT) ?
-                               req->cryptlen :
-                               (req->cryptlen - authsize);
-
-       areq_ctx->mac_buf_dma_addr = dma_map_single(dev, areq_ctx->mac_buf,
-                                                   MAX_MAC_SIZE,
-                                                   DMA_BIDIRECTIONAL);
-       if (unlikely(dma_mapping_error(dev, areq_ctx->mac_buf_dma_addr))) {
-               dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n",
-                       MAX_MAC_SIZE, areq_ctx->mac_buf);
-               rc = -ENOMEM;
-               goto aead_map_failure;
-       }
-
-       if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
-               areq_ctx->ccm_iv0_dma_addr = dma_map_single(dev,
-                                                           (areq_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET),
-                                                           AES_BLOCK_SIZE,
-                                                           DMA_TO_DEVICE);
-
-               if (unlikely(dma_mapping_error(dev, areq_ctx->ccm_iv0_dma_addr))) {
-                       dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n",
-                               AES_BLOCK_SIZE,
-                               (areq_ctx->ccm_config +
-                                CCM_CTR_COUNT_0_OFFSET));
-                       areq_ctx->ccm_iv0_dma_addr = 0;
-                       rc = -ENOMEM;
-                       goto aead_map_failure;
-               }
-               if (ssi_aead_handle_config_buf(dev, areq_ctx,
-                                              areq_ctx->ccm_config, &sg_data,
-                                              req->assoclen) != 0) {
-                       rc = -ENOMEM;
-                       goto aead_map_failure;
-               }
-       }
-
-#if SSI_CC_HAS_AES_GCM
-       if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) {
-               areq_ctx->hkey_dma_addr = dma_map_single(dev,
-                                                        areq_ctx->hkey,
-                                                        AES_BLOCK_SIZE,
-                                                        DMA_BIDIRECTIONAL);
-               if (unlikely(dma_mapping_error(dev, areq_ctx->hkey_dma_addr))) {
-                       dev_err(dev, "Mapping hkey %u B at va=%pK for DMA failed\n",
-                               AES_BLOCK_SIZE, areq_ctx->hkey);
-                       rc = -ENOMEM;
-                       goto aead_map_failure;
-               }
-
-               areq_ctx->gcm_block_len_dma_addr = dma_map_single(dev,
-                                                                 &areq_ctx->gcm_len_block,
-                                                                 AES_BLOCK_SIZE,
-                                                                 DMA_TO_DEVICE);
-               if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_block_len_dma_addr))) {
-                       dev_err(dev, "Mapping gcm_len_block %u B at va=%pK for DMA failed\n",
-                               AES_BLOCK_SIZE, &areq_ctx->gcm_len_block);
-                       rc = -ENOMEM;
-                       goto aead_map_failure;
-               }
-
-               areq_ctx->gcm_iv_inc1_dma_addr = dma_map_single(dev,
-                                                               areq_ctx->gcm_iv_inc1,
-                                                               AES_BLOCK_SIZE,
-                                                               DMA_TO_DEVICE);
-
-               if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_iv_inc1_dma_addr))) {
-                       dev_err(dev, "Mapping gcm_iv_inc1 %u B at va=%pK for DMA failed\n",
-                               AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc1));
-                       areq_ctx->gcm_iv_inc1_dma_addr = 0;
-                       rc = -ENOMEM;
-                       goto aead_map_failure;
-               }
-
-               areq_ctx->gcm_iv_inc2_dma_addr = dma_map_single(dev,
-                                                               areq_ctx->gcm_iv_inc2,
-                                                               AES_BLOCK_SIZE,
-                                                               DMA_TO_DEVICE);
-
-               if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_iv_inc2_dma_addr))) {
-                       dev_err(dev, "Mapping gcm_iv_inc2 %u B at va=%pK for DMA failed\n",
-                               AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc2));
-                       areq_ctx->gcm_iv_inc2_dma_addr = 0;
-                       rc = -ENOMEM;
-                       goto aead_map_failure;
-               }
-       }
-#endif /*SSI_CC_HAS_AES_GCM*/
-
-       size_to_map = req->cryptlen + req->assoclen;
-       if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT)
-               size_to_map += authsize;
-
-       if (is_gcm4543)
-               size_to_map += crypto_aead_ivsize(tfm);
-       rc = ssi_buffer_mgr_map_scatterlist(dev, req->src,
-                                           size_to_map, DMA_BIDIRECTIONAL, &areq_ctx->src.nents,
-                                           LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents);
-       if (unlikely(rc != 0)) {
-               rc = -ENOMEM;
-               goto aead_map_failure;
-       }
-
-       if (likely(areq_ctx->is_single_pass)) {
-               /*
-                * Create MLLI table for:
-                *   (1) Assoc. data
-                *   (2) Src/Dst SGLs
-                *   Note: IV is contg. buffer (not an SGL)
-                */
-               rc = ssi_buffer_mgr_aead_chain_assoc(drvdata, req, &sg_data, true, false);
-               if (unlikely(rc != 0))
-                       goto aead_map_failure;
-               rc = ssi_buffer_mgr_aead_chain_iv(drvdata, req, &sg_data, true, false);
-               if (unlikely(rc != 0))
-                       goto aead_map_failure;
-               rc = ssi_buffer_mgr_aead_chain_data(drvdata, req, &sg_data, true, false);
-               if (unlikely(rc != 0))
-                       goto aead_map_failure;
-       } else { /* DOUBLE-PASS flow */
-               /*
-                * Prepare MLLI table(s) in this order:
-                *
-                * If ENCRYPT/DECRYPT (inplace):
-                *   (1) MLLI table for assoc
-                *   (2) IV entry (chained right after end of assoc)
-                *   (3) MLLI for src/dst (inplace operation)
-                *
-                * If ENCRYPT (non-inplace)
-                *   (1) MLLI table for assoc
-                *   (2) IV entry (chained right after end of assoc)
-                *   (3) MLLI for dst
-                *   (4) MLLI for src
-                *
-                * If DECRYPT (non-inplace)
-                *   (1) MLLI table for assoc
-                *   (2) IV entry (chained right after end of assoc)
-                *   (3) MLLI for src
-                *   (4) MLLI for dst
-                */
-               rc = ssi_buffer_mgr_aead_chain_assoc(drvdata, req, &sg_data, false, true);
-               if (unlikely(rc != 0))
-                       goto aead_map_failure;
-               rc = ssi_buffer_mgr_aead_chain_iv(drvdata, req, &sg_data, false, true);
-               if (unlikely(rc != 0))
-                       goto aead_map_failure;
-               rc = ssi_buffer_mgr_aead_chain_data(drvdata, req, &sg_data, true, true);
-               if (unlikely(rc != 0))
-                       goto aead_map_failure;
-       }
-
-       /* Mlli support -start building the MLLI according to the above results */
-       if (unlikely(
-               (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) ||
-               (areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI))) {
-               mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
-               rc = ssi_buffer_mgr_generate_mlli(dev, &sg_data, mlli_params);
-               if (unlikely(rc != 0))
-                       goto aead_map_failure;
-
-               ssi_buffer_mgr_update_aead_mlli_nents(drvdata, req);
-               dev_dbg(dev, "assoc params mn %d\n",
-                       areq_ctx->assoc.mlli_nents);
-               dev_dbg(dev, "src params mn %d\n", areq_ctx->src.mlli_nents);
-               dev_dbg(dev, "dst params mn %d\n", areq_ctx->dst.mlli_nents);
-       }
-       return 0;
-
-aead_map_failure:
-       ssi_buffer_mgr_unmap_aead_request(dev, req);
-       return rc;
-}
-
-int ssi_buffer_mgr_map_hash_request_final(
-       struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, bool do_update)
-{
-       struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
-       struct device *dev = drvdata_to_dev(drvdata);
-       u8 *curr_buff = areq_ctx->buff_index ? areq_ctx->buff1 :
-                       areq_ctx->buff0;
-       u32 *curr_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff1_cnt :
-                       &areq_ctx->buff0_cnt;
-       struct mlli_params *mlli_params = &areq_ctx->mlli_params;
-       struct buffer_array sg_data;
-       struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
-       u32 dummy = 0;
-       u32 mapped_nents = 0;
-
-       dev_dbg(dev, "final params : curr_buff=%pK curr_buff_cnt=0x%X nbytes = 0x%X src=%pK curr_index=%u\n",
-               curr_buff, *curr_buff_cnt, nbytes, src, areq_ctx->buff_index);
-       /* Init the type of the dma buffer */
-       areq_ctx->data_dma_buf_type = SSI_DMA_BUF_NULL;
-       mlli_params->curr_pool = NULL;
-       sg_data.num_of_buffers = 0;
-       areq_ctx->in_nents = 0;
-
-       if (unlikely(nbytes == 0 && *curr_buff_cnt == 0)) {
-               /* nothing to do */
-               return 0;
-       }
-
-       /*TODO: copy data in case that buffer is enough for operation */
-       /* map the previous buffer */
-       if (*curr_buff_cnt != 0) {
-               if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff,
-                                             *curr_buff_cnt, &sg_data) != 0) {
-                       return -ENOMEM;
-               }
-       }
-
-       if (src && (nbytes > 0) && do_update) {
-               if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src, nbytes,
-                                                           DMA_TO_DEVICE,
-                                                           &areq_ctx->in_nents,
-                                                           LLI_MAX_NUM_OF_DATA_ENTRIES,
-                                                           &dummy,
-                                                           &mapped_nents))){
-                       goto unmap_curr_buff;
-               }
-               if (src && (mapped_nents == 1)
-                    && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL)) {
-                       memcpy(areq_ctx->buff_sg, src,
-                              sizeof(struct scatterlist));
-                       areq_ctx->buff_sg->length = nbytes;
-                       areq_ctx->curr_sg = areq_ctx->buff_sg;
-                       areq_ctx->data_dma_buf_type = SSI_DMA_BUF_DLLI;
-               } else {
-                       areq_ctx->data_dma_buf_type = SSI_DMA_BUF_MLLI;
-               }
-       }
-
-       /*build mlli */
-       if (unlikely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI)) {
-               mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
-               /* add the src data to the sg_data */
-               ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data,
-                                                    areq_ctx->in_nents,
-                                                    src, nbytes, 0, true,
-                                                    &areq_ctx->mlli_nents);
-               if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data,
-                                                         mlli_params) != 0)) {
-                       goto fail_unmap_din;
-               }
-       }
-       /* change the buffer index for the unmap function */
-       areq_ctx->buff_index = (areq_ctx->buff_index ^ 1);
-       dev_dbg(dev, "areq_ctx->data_dma_buf_type = %s\n",
-               GET_DMA_BUFFER_TYPE(areq_ctx->data_dma_buf_type));
-       return 0;
-
-fail_unmap_din:
-       dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);
-
-unmap_curr_buff:
-       if (*curr_buff_cnt != 0)
-               dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
-
-       return -ENOMEM;
-}
-
-int ssi_buffer_mgr_map_hash_request_update(
-       struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, unsigned int block_size)
-{
-       struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
-       struct device *dev = drvdata_to_dev(drvdata);
-       u8 *curr_buff = areq_ctx->buff_index ? areq_ctx->buff1 :
-                       areq_ctx->buff0;
-       u32 *curr_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff1_cnt :
-                       &areq_ctx->buff0_cnt;
-       u8 *next_buff = areq_ctx->buff_index ? areq_ctx->buff0 :
-                       areq_ctx->buff1;
-       u32 *next_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff0_cnt :
-                       &areq_ctx->buff1_cnt;
-       struct mlli_params *mlli_params = &areq_ctx->mlli_params;
-       unsigned int update_data_len;
-       u32 total_in_len = nbytes + *curr_buff_cnt;
-       struct buffer_array sg_data;
-       struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
-       unsigned int swap_index = 0;
-       u32 dummy = 0;
-       u32 mapped_nents = 0;
-
-       dev_dbg(dev, " update params : curr_buff=%pK curr_buff_cnt=0x%X nbytes=0x%X src=%pK curr_index=%u\n",
-               curr_buff, *curr_buff_cnt, nbytes, src, areq_ctx->buff_index);
-       /* Init the type of the dma buffer */
-       areq_ctx->data_dma_buf_type = SSI_DMA_BUF_NULL;
-       mlli_params->curr_pool = NULL;
-       areq_ctx->curr_sg = NULL;
-       sg_data.num_of_buffers = 0;
-       areq_ctx->in_nents = 0;
-
-       if (unlikely(total_in_len < block_size)) {
-               dev_dbg(dev, " less than one block: curr_buff=%pK *curr_buff_cnt=0x%X copy_to=%pK\n",
-                       curr_buff, *curr_buff_cnt, &curr_buff[*curr_buff_cnt]);
-               areq_ctx->in_nents =
-                       ssi_buffer_mgr_get_sgl_nents(dev, src, nbytes, &dummy,
-                                                    NULL);
-               sg_copy_to_buffer(src, areq_ctx->in_nents,
-                                 &curr_buff[*curr_buff_cnt], nbytes);
-               *curr_buff_cnt += nbytes;
-               return 1;
-       }
-
-       /* Calculate the residue size*/
-       *next_buff_cnt = total_in_len & (block_size - 1);
-       /* update data len */
-       update_data_len = total_in_len - *next_buff_cnt;
-
-       dev_dbg(dev, " temp length : *next_buff_cnt=0x%X update_data_len=0x%X\n",
-               *next_buff_cnt, update_data_len);
-
-       /* Copy the new residue to next buffer */
-       if (*next_buff_cnt != 0) {
-               dev_dbg(dev, " handle residue: next buff %pK skip data %u residue %u\n",
-                       next_buff, (update_data_len - *curr_buff_cnt),
-                       *next_buff_cnt);
-               ssi_buffer_mgr_copy_scatterlist_portion(dev, next_buff, src,
-                                                       (update_data_len - *curr_buff_cnt),
-                                                       nbytes, SSI_SG_TO_BUF);
-               /* change the buffer index for next operation */
-               swap_index = 1;
-       }
-
-       if (*curr_buff_cnt != 0) {
-               if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff,
-                                             *curr_buff_cnt, &sg_data) != 0) {
-                       return -ENOMEM;
-               }
-               /* change the buffer index for next operation */
-               swap_index = 1;
-       }
-
-       if (update_data_len > *curr_buff_cnt) {
-               if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src,
-                                                           (update_data_len - *curr_buff_cnt),
-                                                           DMA_TO_DEVICE,
-                                                           &areq_ctx->in_nents,
-                                                           LLI_MAX_NUM_OF_DATA_ENTRIES,
-                                                           &dummy,
-                                                           &mapped_nents))){
-                       goto unmap_curr_buff;
-               }
-               if ((mapped_nents == 1)
-                    && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL)) {
-                       /* only one entry in the SG and no previous data */
-                       memcpy(areq_ctx->buff_sg, src,
-                              sizeof(struct scatterlist));
-                       areq_ctx->buff_sg->length = update_data_len;
-                       areq_ctx->data_dma_buf_type = SSI_DMA_BUF_DLLI;
-                       areq_ctx->curr_sg = areq_ctx->buff_sg;
-               } else {
-                       areq_ctx->data_dma_buf_type = SSI_DMA_BUF_MLLI;
-               }
-       }
-
-       if (unlikely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI)) {
-               mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
-               /* add the src data to the sg_data */
-               ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data,
-                                                    areq_ctx->in_nents,
-                                                    src,
-                                                    (update_data_len - *curr_buff_cnt),
-                                                    0,
-                                                    true,
-                                                    &areq_ctx->mlli_nents);
-               if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data,
-                                                         mlli_params) != 0)) {
-                       goto fail_unmap_din;
-               }
-       }
-       areq_ctx->buff_index = (areq_ctx->buff_index ^ swap_index);
-
-       return 0;
-
-fail_unmap_din:
-       dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);
-
-unmap_curr_buff:
-       if (*curr_buff_cnt != 0)
-               dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
-
-       return -ENOMEM;
-}
-
-void ssi_buffer_mgr_unmap_hash_request(
-       struct device *dev, void *ctx, struct scatterlist *src, bool do_revert)
-{
-       struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
-       u32 *prev_len = areq_ctx->buff_index ?  &areq_ctx->buff0_cnt :
-                                               &areq_ctx->buff1_cnt;
-
-       /*In case a pool was set, a table was
-        *allocated and should be released
-        */
-       if (areq_ctx->mlli_params.curr_pool) {
-               dev_dbg(dev, "free MLLI buffer: dma=%pad virt=%pK\n",
-                       &areq_ctx->mlli_params.mlli_dma_addr,
-                       areq_ctx->mlli_params.mlli_virt_addr);
-               dma_pool_free(areq_ctx->mlli_params.curr_pool,
-                             areq_ctx->mlli_params.mlli_virt_addr,
-                             areq_ctx->mlli_params.mlli_dma_addr);
-       }
-
-       if ((src) && likely(areq_ctx->in_nents != 0)) {
-               dev_dbg(dev, "Unmapped sg src: virt=%pK dma=%pad len=0x%X\n",
-                       sg_virt(src), &sg_dma_address(src), sg_dma_len(src));
-               dma_unmap_sg(dev, src,
-                            areq_ctx->in_nents, DMA_TO_DEVICE);
-       }
-
-       if (*prev_len != 0) {
-               dev_dbg(dev, "Unmapped buffer: areq_ctx->buff_sg=%pK dma=%pad len 0x%X\n",
-                       sg_virt(areq_ctx->buff_sg),
-                       &sg_dma_address(areq_ctx->buff_sg),
-                       sg_dma_len(areq_ctx->buff_sg));
-               dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
-               if (!do_revert) {
-                       /* clean the previous data length for update operation */
-                       *prev_len = 0;
-               } else {
-                       areq_ctx->buff_index ^= 1;
-               }
-       }
-}
-
-int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata)
-{
-       struct buff_mgr_handle *buff_mgr_handle;
-       struct device *dev = drvdata_to_dev(drvdata);
-
-       buff_mgr_handle = kmalloc(sizeof(*buff_mgr_handle), GFP_KERNEL);
-       if (!buff_mgr_handle)
-               return -ENOMEM;
-
-       drvdata->buff_mgr_handle = buff_mgr_handle;
-
-       buff_mgr_handle->mlli_buffs_pool = dma_pool_create(
-                               "dx_single_mlli_tables", dev,
-                               MAX_NUM_OF_TOTAL_MLLI_ENTRIES *
-                               LLI_ENTRY_BYTE_SIZE,
-                               MLLI_TABLE_MIN_ALIGNMENT, 0);
-
-       if (unlikely(!buff_mgr_handle->mlli_buffs_pool))
-               goto error;
-
-       return 0;
-
-error:
-       ssi_buffer_mgr_fini(drvdata);
-       return -ENOMEM;
-}
-
-int ssi_buffer_mgr_fini(struct ssi_drvdata *drvdata)
-{
-       struct buff_mgr_handle *buff_mgr_handle = drvdata->buff_mgr_handle;
-
-       if (buff_mgr_handle) {
-               dma_pool_destroy(buff_mgr_handle->mlli_buffs_pool);
-               kfree(drvdata->buff_mgr_handle);
-               drvdata->buff_mgr_handle = NULL;
-       }
-       return 0;
-}
diff --git a/drivers/staging/ccree/ssi_buffer_mgr.h b/drivers/staging/ccree/ssi_buffer_mgr.h
deleted file mode 100644 (file)
index 1032f25..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file buffer_mgr.h
- * Buffer Manager
- */
-
-#ifndef __SSI_BUFFER_MGR_H__
-#define __SSI_BUFFER_MGR_H__
-
-#include <crypto/algapi.h>
-
-#include "ssi_config.h"
-#include "ssi_driver.h"
-
-enum ssi_req_dma_buf_type {
-       SSI_DMA_BUF_NULL = 0,
-       SSI_DMA_BUF_DLLI,
-       SSI_DMA_BUF_MLLI
-};
-
-enum ssi_sg_cpy_direct {
-       SSI_SG_TO_BUF = 0,
-       SSI_SG_FROM_BUF = 1
-};
-
-struct ssi_mlli {
-       ssi_sram_addr_t sram_addr;
-       unsigned int nents; //sg nents
-       unsigned int mlli_nents; //mlli nents might be different than the above
-};
-
-struct mlli_params {
-       struct dma_pool *curr_pool;
-       u8 *mlli_virt_addr;
-       dma_addr_t mlli_dma_addr;
-       u32 mlli_len;
-};
-
-int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata);
-
-int ssi_buffer_mgr_fini(struct ssi_drvdata *drvdata);
-
-int ssi_buffer_mgr_map_blkcipher_request(
-       struct ssi_drvdata *drvdata,
-       void *ctx,
-       unsigned int ivsize,
-       unsigned int nbytes,
-       void *info,
-       struct scatterlist *src,
-       struct scatterlist *dst);
-
-void ssi_buffer_mgr_unmap_blkcipher_request(
-       struct device *dev,
-       void *ctx,
-       unsigned int ivsize,
-       struct scatterlist *src,
-       struct scatterlist *dst);
-
-int ssi_buffer_mgr_map_aead_request(struct ssi_drvdata *drvdata, struct aead_request *req);
-
-void ssi_buffer_mgr_unmap_aead_request(struct device *dev, struct aead_request *req);
-
-int ssi_buffer_mgr_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, bool do_update);
-
-int ssi_buffer_mgr_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, unsigned int block_size);
-
-void ssi_buffer_mgr_unmap_hash_request(struct device *dev, void *ctx, struct scatterlist *src, bool do_revert);
-
-void ssi_buffer_mgr_copy_scatterlist_portion(struct device *dev, u8 *dest,
-                                            struct scatterlist *sg,
-                                            u32 to_skip, u32 end,
-                                            enum ssi_sg_cpy_direct direct);
-
-void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len);
-
-#endif /*__BUFFER_MGR_H__*/
-
diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c
deleted file mode 100644 (file)
index ee85cbf..0000000
+++ /dev/null
@@ -1,1357 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/semaphore.h>
-#include <crypto/algapi.h>
-#include <crypto/internal/skcipher.h>
-#include <crypto/aes.h>
-#include <crypto/ctr.h>
-#include <crypto/des.h>
-#include <crypto/xts.h>
-#include <crypto/scatterwalk.h>
-
-#include "ssi_config.h"
-#include "ssi_driver.h"
-#include "cc_lli_defs.h"
-#include "ssi_buffer_mgr.h"
-#include "ssi_cipher.h"
-#include "ssi_request_mgr.h"
-#include "ssi_sysfs.h"
-
-#define MAX_ABLKCIPHER_SEQ_LEN 6
-
-#define template_ablkcipher    template_u.ablkcipher
-
-#define SSI_MIN_AES_XTS_SIZE 0x10
-#define SSI_MAX_AES_XTS_SIZE 0x2000
-struct ssi_blkcipher_handle {
-       struct list_head blkcipher_alg_list;
-};
-
-struct cc_user_key_info {
-       u8 *key;
-       dma_addr_t key_dma_addr;
-};
-
-struct cc_hw_key_info {
-       enum cc_hw_crypto_key key1_slot;
-       enum cc_hw_crypto_key key2_slot;
-};
-
-struct ssi_ablkcipher_ctx {
-       struct ssi_drvdata *drvdata;
-       int keylen;
-       int key_round_number;
-       int cipher_mode;
-       int flow_mode;
-       unsigned int flags;
-       struct blkcipher_req_ctx *sync_ctx;
-       struct cc_user_key_info user;
-       struct cc_hw_key_info hw;
-       struct crypto_shash *shash_tfm;
-};
-
-static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __iomem *cc_base);
-
-static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size)
-{
-       switch (ctx_p->flow_mode) {
-       case S_DIN_to_AES:
-               switch (size) {
-               case CC_AES_128_BIT_KEY_SIZE:
-               case CC_AES_192_BIT_KEY_SIZE:
-                       if (likely((ctx_p->cipher_mode != DRV_CIPHER_XTS) &&
-                                  (ctx_p->cipher_mode != DRV_CIPHER_ESSIV) &&
-                                  (ctx_p->cipher_mode != DRV_CIPHER_BITLOCKER)))
-                               return 0;
-                       break;
-               case CC_AES_256_BIT_KEY_SIZE:
-                       return 0;
-               case (CC_AES_192_BIT_KEY_SIZE * 2):
-               case (CC_AES_256_BIT_KEY_SIZE * 2):
-                       if (likely((ctx_p->cipher_mode == DRV_CIPHER_XTS) ||
-                                  (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) ||
-                                  (ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER)))
-                               return 0;
-                       break;
-               default:
-                       break;
-               }
-       case S_DIN_to_DES:
-               if (likely(size == DES3_EDE_KEY_SIZE || size == DES_KEY_SIZE))
-                       return 0;
-               break;
-#if SSI_CC_HAS_MULTI2
-       case S_DIN_to_MULTI2:
-               if (likely(size == CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE))
-                       return 0;
-               break;
-#endif
-       default:
-               break;
-       }
-       return -EINVAL;
-}
-
-static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int size)
-{
-       switch (ctx_p->flow_mode) {
-       case S_DIN_to_AES:
-               switch (ctx_p->cipher_mode) {
-               case DRV_CIPHER_XTS:
-                       if ((size >= SSI_MIN_AES_XTS_SIZE) &&
-                           (size <= SSI_MAX_AES_XTS_SIZE) &&
-                           IS_ALIGNED(size, AES_BLOCK_SIZE))
-                               return 0;
-                       break;
-               case DRV_CIPHER_CBC_CTS:
-                       if (likely(size >= AES_BLOCK_SIZE))
-                               return 0;
-                       break;
-               case DRV_CIPHER_OFB:
-               case DRV_CIPHER_CTR:
-                               return 0;
-               case DRV_CIPHER_ECB:
-               case DRV_CIPHER_CBC:
-               case DRV_CIPHER_ESSIV:
-               case DRV_CIPHER_BITLOCKER:
-                       if (likely(IS_ALIGNED(size, AES_BLOCK_SIZE)))
-                               return 0;
-                       break;
-               default:
-                       break;
-               }
-               break;
-       case S_DIN_to_DES:
-               if (likely(IS_ALIGNED(size, DES_BLOCK_SIZE)))
-                               return 0;
-               break;
-#if SSI_CC_HAS_MULTI2
-       case S_DIN_to_MULTI2:
-               switch (ctx_p->cipher_mode) {
-               case DRV_MULTI2_CBC:
-                       if (likely(IS_ALIGNED(size, CC_MULTI2_BLOCK_SIZE)))
-                               return 0;
-                       break;
-               case DRV_MULTI2_OFB:
-                       return 0;
-               default:
-                       break;
-               }
-               break;
-#endif /*SSI_CC_HAS_MULTI2*/
-       default:
-               break;
-       }
-       return -EINVAL;
-}
-
-static unsigned int get_max_keysize(struct crypto_tfm *tfm)
-{
-       struct ssi_crypto_alg *ssi_alg = container_of(tfm->__crt_alg, struct ssi_crypto_alg, crypto_alg);
-
-       if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_ABLKCIPHER)
-               return ssi_alg->crypto_alg.cra_ablkcipher.max_keysize;
-
-       if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_BLKCIPHER)
-               return ssi_alg->crypto_alg.cra_blkcipher.max_keysize;
-
-       return 0;
-}
-
-static int ssi_blkcipher_init(struct crypto_tfm *tfm)
-{
-       struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-       struct crypto_alg *alg = tfm->__crt_alg;
-       struct ssi_crypto_alg *ssi_alg =
-                       container_of(alg, struct ssi_crypto_alg, crypto_alg);
-       struct device *dev = drvdata_to_dev(ssi_alg->drvdata);
-       int rc = 0;
-       unsigned int max_key_buf_size = get_max_keysize(tfm);
-
-       dev_dbg(dev, "Initializing context @%p for %s\n", ctx_p,
-               crypto_tfm_alg_name(tfm));
-
-       ctx_p->cipher_mode = ssi_alg->cipher_mode;
-       ctx_p->flow_mode = ssi_alg->flow_mode;
-       ctx_p->drvdata = ssi_alg->drvdata;
-
-       /* Allocate key buffer, cache line aligned */
-       ctx_p->user.key = kmalloc(max_key_buf_size, GFP_KERNEL | GFP_DMA);
-       if (!ctx_p->user.key)
-               return -ENOMEM;
-
-       dev_dbg(dev, "Allocated key buffer in context. key=@%p\n",
-               ctx_p->user.key);
-
-       /* Map key buffer */
-       ctx_p->user.key_dma_addr = dma_map_single(dev, (void *)ctx_p->user.key,
-                                                 max_key_buf_size,
-                                                 DMA_TO_DEVICE);
-       if (dma_mapping_error(dev, ctx_p->user.key_dma_addr)) {
-               dev_err(dev, "Mapping Key %u B at va=%pK for DMA failed\n",
-                       max_key_buf_size, ctx_p->user.key);
-               return -ENOMEM;
-       }
-       dev_dbg(dev, "Mapped key %u B at va=%pK to dma=%pad\n",
-               max_key_buf_size, ctx_p->user.key, &ctx_p->user.key_dma_addr);
-
-       if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {
-               /* Alloc hash tfm for essiv */
-               ctx_p->shash_tfm = crypto_alloc_shash("sha256-generic", 0, 0);
-               if (IS_ERR(ctx_p->shash_tfm)) {
-                       dev_err(dev, "Error allocating hash tfm for ESSIV.\n");
-                       return PTR_ERR(ctx_p->shash_tfm);
-               }
-       }
-
-       return rc;
-}
-
-static void ssi_blkcipher_exit(struct crypto_tfm *tfm)
-{
-       struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
-       unsigned int max_key_buf_size = get_max_keysize(tfm);
-
-       dev_dbg(dev, "Clearing context @%p for %s\n",
-               crypto_tfm_ctx(tfm), crypto_tfm_alg_name(tfm));
-
-       if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {
-               /* Free hash tfm for essiv */
-               crypto_free_shash(ctx_p->shash_tfm);
-               ctx_p->shash_tfm = NULL;
-       }
-
-       /* Unmap key buffer */
-       dma_unmap_single(dev, ctx_p->user.key_dma_addr, max_key_buf_size,
-                        DMA_TO_DEVICE);
-       dev_dbg(dev, "Unmapped key buffer key_dma_addr=%pad\n",
-               &ctx_p->user.key_dma_addr);
-
-       /* Free key buffer in context */
-       kfree(ctx_p->user.key);
-       dev_dbg(dev, "Free key buffer in context. key=@%p\n", ctx_p->user.key);
-}
-
-struct tdes_keys {
-       u8      key1[DES_KEY_SIZE];
-       u8      key2[DES_KEY_SIZE];
-       u8      key3[DES_KEY_SIZE];
-};
-
-static const u8 zero_buff[] = {        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-
-/* The function verifies that tdes keys are not weak.*/
-static int ssi_verify_3des_keys(const u8 *key, unsigned int keylen)
-{
-       struct tdes_keys *tdes_key = (struct tdes_keys *)key;
-
-       /* verify key1 != key2 and key3 != key2*/
-       if (unlikely((memcmp((u8 *)tdes_key->key1, (u8 *)tdes_key->key2, sizeof(tdes_key->key1)) == 0) ||
-                    (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2, sizeof(tdes_key->key3)) == 0))) {
-               return -ENOEXEC;
-       }
-
-       return 0;
-}
-
-static enum cc_hw_crypto_key hw_key_to_cc_hw_key(int slot_num)
-{
-       switch (slot_num) {
-       case 0:
-               return KFDE0_KEY;
-       case 1:
-               return KFDE1_KEY;
-       case 2:
-               return KFDE2_KEY;
-       case 3:
-               return KFDE3_KEY;
-       }
-       return END_OF_KEYS;
-}
-
-static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
-                               const u8 *key,
-                               unsigned int keylen)
-{
-       struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
-       u32 tmp[DES_EXPKEY_WORDS];
-       unsigned int max_key_buf_size = get_max_keysize(tfm);
-
-       dev_dbg(dev, "Setting key in context @%p for %s. keylen=%u\n",
-               ctx_p, crypto_tfm_alg_name(tfm), keylen);
-       dump_byte_array("key", (u8 *)key, keylen);
-
-       /* STAT_PHASE_0: Init and sanity checks */
-
-#if SSI_CC_HAS_MULTI2
-       /*last byte of key buffer is round number and should not be a part of key size*/
-       if (ctx_p->flow_mode == S_DIN_to_MULTI2)
-               keylen -= 1;
-#endif /*SSI_CC_HAS_MULTI2*/
-
-       if (unlikely(validate_keys_sizes(ctx_p, keylen) != 0)) {
-               dev_err(dev, "Unsupported key size %d.\n", keylen);
-               crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-               return -EINVAL;
-       }
-
-       if (ssi_is_hw_key(tfm)) {
-               /* setting HW key slots */
-               struct arm_hw_key_info *hki = (struct arm_hw_key_info *)key;
-
-               if (unlikely(ctx_p->flow_mode != S_DIN_to_AES)) {
-                       dev_err(dev, "HW key not supported for non-AES flows\n");
-                       return -EINVAL;
-               }
-
-               ctx_p->hw.key1_slot = hw_key_to_cc_hw_key(hki->hw_key1);
-               if (unlikely(ctx_p->hw.key1_slot == END_OF_KEYS)) {
-                       dev_err(dev, "Unsupported hw key1 number (%d)\n",
-                               hki->hw_key1);
-                       return -EINVAL;
-               }
-
-               if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) ||
-                   (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) ||
-                   (ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER)) {
-                       if (unlikely(hki->hw_key1 == hki->hw_key2)) {
-                               dev_err(dev, "Illegal hw key numbers (%d,%d)\n",
-                                       hki->hw_key1, hki->hw_key2);
-                               return -EINVAL;
-                       }
-                       ctx_p->hw.key2_slot = hw_key_to_cc_hw_key(hki->hw_key2);
-                       if (unlikely(ctx_p->hw.key2_slot == END_OF_KEYS)) {
-                               dev_err(dev, "Unsupported hw key2 number (%d)\n",
-                                       hki->hw_key2);
-                               return -EINVAL;
-                       }
-               }
-
-               ctx_p->keylen = keylen;
-               dev_dbg(dev, "ssi_is_hw_key ret 0");
-
-               return 0;
-       }
-
-       // verify weak keys
-       if (ctx_p->flow_mode == S_DIN_to_DES) {
-               if (unlikely(!des_ekey(tmp, key)) &&
-                   (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_WEAK_KEY)) {
-                       tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
-                       dev_dbg(dev, "weak DES key");
-                       return -EINVAL;
-               }
-       }
-       if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) &&
-           xts_check_key(tfm, key, keylen) != 0) {
-               dev_dbg(dev, "weak XTS key");
-               return -EINVAL;
-       }
-       if ((ctx_p->flow_mode == S_DIN_to_DES) &&
-           (keylen == DES3_EDE_KEY_SIZE) &&
-           ssi_verify_3des_keys(key, keylen) != 0) {
-               dev_dbg(dev, "weak 3DES key");
-               return -EINVAL;
-       }
-
-       /* STAT_PHASE_1: Copy key to ctx */
-       dma_sync_single_for_cpu(dev, ctx_p->user.key_dma_addr,
-                               max_key_buf_size, DMA_TO_DEVICE);
-
-       if (ctx_p->flow_mode == S_DIN_to_MULTI2) {
-#if SSI_CC_HAS_MULTI2
-               memcpy(ctx_p->user.key, key, CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE);
-               ctx_p->key_round_number = key[CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE];
-               if (ctx_p->key_round_number < CC_MULTI2_MIN_NUM_ROUNDS ||
-                   ctx_p->key_round_number > CC_MULTI2_MAX_NUM_ROUNDS) {
-                       crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-                       dev_dbg(dev, "SSI_CC_HAS_MULTI2 einval");
-                       return -EINVAL;
-#endif /*SSI_CC_HAS_MULTI2*/
-       } else {
-               memcpy(ctx_p->user.key, key, keylen);
-               if (keylen == 24)
-                       memset(ctx_p->user.key + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
-
-               if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {
-                       /* sha256 for key2 - use sw implementation */
-                       int key_len = keylen >> 1;
-                       int err;
-                       SHASH_DESC_ON_STACK(desc, ctx_p->shash_tfm);
-
-                       desc->tfm = ctx_p->shash_tfm;
-
-                       err = crypto_shash_digest(desc, ctx_p->user.key, key_len, ctx_p->user.key + key_len);
-                       if (err) {
-                               dev_err(dev, "Failed to hash ESSIV key.\n");
-                               return err;
-                       }
-               }
-       }
-       dma_sync_single_for_device(dev, ctx_p->user.key_dma_addr,
-                                  max_key_buf_size, DMA_TO_DEVICE);
-       ctx_p->keylen = keylen;
-
-        dev_dbg(dev, "return safely");
-       return 0;
-}
-
-static inline void
-ssi_blkcipher_create_setup_desc(
-       struct crypto_tfm *tfm,
-       struct blkcipher_req_ctx *req_ctx,
-       unsigned int ivsize,
-       unsigned int nbytes,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
-       int cipher_mode = ctx_p->cipher_mode;
-       int flow_mode = ctx_p->flow_mode;
-       int direction = req_ctx->gen_ctx.op_type;
-       dma_addr_t key_dma_addr = ctx_p->user.key_dma_addr;
-       unsigned int key_len = ctx_p->keylen;
-       dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr;
-       unsigned int du_size = nbytes;
-
-       struct ssi_crypto_alg *ssi_alg = container_of(tfm->__crt_alg, struct ssi_crypto_alg, crypto_alg);
-
-       if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == CRYPTO_ALG_BULK_DU_512)
-               du_size = 512;
-       if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == CRYPTO_ALG_BULK_DU_4096)
-               du_size = 4096;
-
-       switch (cipher_mode) {
-       case DRV_CIPHER_CBC:
-       case DRV_CIPHER_CBC_CTS:
-       case DRV_CIPHER_CTR:
-       case DRV_CIPHER_OFB:
-               /* Load cipher state */
-               hw_desc_init(&desc[*seq_size]);
-               set_din_type(&desc[*seq_size], DMA_DLLI, iv_dma_addr, ivsize,
-                            NS_BIT);
-               set_cipher_config0(&desc[*seq_size], direction);
-               set_flow_mode(&desc[*seq_size], flow_mode);
-               set_cipher_mode(&desc[*seq_size], cipher_mode);
-               if ((cipher_mode == DRV_CIPHER_CTR) ||
-                   (cipher_mode == DRV_CIPHER_OFB)) {
-                       set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1);
-               } else {
-                       set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE0);
-               }
-               (*seq_size)++;
-               /*FALLTHROUGH*/
-       case DRV_CIPHER_ECB:
-               /* Load key */
-               hw_desc_init(&desc[*seq_size]);
-               set_cipher_mode(&desc[*seq_size], cipher_mode);
-               set_cipher_config0(&desc[*seq_size], direction);
-               if (flow_mode == S_DIN_to_AES) {
-                       if (ssi_is_hw_key(tfm)) {
-                               set_hw_crypto_key(&desc[*seq_size],
-                                                 ctx_p->hw.key1_slot);
-                       } else {
-                               set_din_type(&desc[*seq_size], DMA_DLLI,
-                                            key_dma_addr, ((key_len == 24) ?
-                                                           AES_MAX_KEY_SIZE :
-                                                           key_len), NS_BIT);
-                       }
-                       set_key_size_aes(&desc[*seq_size], key_len);
-               } else {
-                       /*des*/
-                       set_din_type(&desc[*seq_size], DMA_DLLI, key_dma_addr,
-                                    key_len, NS_BIT);
-                       set_key_size_des(&desc[*seq_size], key_len);
-               }
-               set_flow_mode(&desc[*seq_size], flow_mode);
-               set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0);
-               (*seq_size)++;
-               break;
-       case DRV_CIPHER_XTS:
-       case DRV_CIPHER_ESSIV:
-       case DRV_CIPHER_BITLOCKER:
-               /* Load AES key */
-               hw_desc_init(&desc[*seq_size]);
-               set_cipher_mode(&desc[*seq_size], cipher_mode);
-               set_cipher_config0(&desc[*seq_size], direction);
-               if (ssi_is_hw_key(tfm)) {
-                       set_hw_crypto_key(&desc[*seq_size],
-                                         ctx_p->hw.key1_slot);
-               } else {
-                       set_din_type(&desc[*seq_size], DMA_DLLI, key_dma_addr,
-                                    (key_len / 2), NS_BIT);
-               }
-               set_key_size_aes(&desc[*seq_size], (key_len / 2));
-               set_flow_mode(&desc[*seq_size], flow_mode);
-               set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0);
-               (*seq_size)++;
-
-               /* load XEX key */
-               hw_desc_init(&desc[*seq_size]);
-               set_cipher_mode(&desc[*seq_size], cipher_mode);
-               set_cipher_config0(&desc[*seq_size], direction);
-               if (ssi_is_hw_key(tfm)) {
-                       set_hw_crypto_key(&desc[*seq_size],
-                                         ctx_p->hw.key2_slot);
-               } else {
-                       set_din_type(&desc[*seq_size], DMA_DLLI,
-                                    (key_dma_addr + (key_len / 2)),
-                                    (key_len / 2), NS_BIT);
-               }
-               set_xex_data_unit_size(&desc[*seq_size], du_size);
-               set_flow_mode(&desc[*seq_size], S_DIN_to_AES2);
-               set_key_size_aes(&desc[*seq_size], (key_len / 2));
-               set_setup_mode(&desc[*seq_size], SETUP_LOAD_XEX_KEY);
-               (*seq_size)++;
-
-               /* Set state */
-               hw_desc_init(&desc[*seq_size]);
-               set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1);
-               set_cipher_mode(&desc[*seq_size], cipher_mode);
-               set_cipher_config0(&desc[*seq_size], direction);
-               set_key_size_aes(&desc[*seq_size], (key_len / 2));
-               set_flow_mode(&desc[*seq_size], flow_mode);
-               set_din_type(&desc[*seq_size], DMA_DLLI, iv_dma_addr,
-                            CC_AES_BLOCK_SIZE, NS_BIT);
-               (*seq_size)++;
-               break;
-       default:
-               dev_err(dev, "Unsupported cipher mode (%d)\n", cipher_mode);
-       }
-}
-
-#if SSI_CC_HAS_MULTI2
-static inline void ssi_blkcipher_create_multi2_setup_desc(
-       struct crypto_tfm *tfm,
-       struct blkcipher_req_ctx *req_ctx,
-       unsigned int ivsize,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-
-       int direction = req_ctx->gen_ctx.op_type;
-       /* Load system key */
-       hw_desc_init(&desc[*seq_size]);
-       set_cipher_mode(&desc[*seq_size], ctx_p->cipher_mode);
-       set_cipher_config0(&desc[*seq_size], direction);
-       set_din_type(&desc[*seq_size], DMA_DLLI, ctx_p->user.key_dma_addr,
-                    CC_MULTI2_SYSTEM_KEY_SIZE, NS_BIT);
-       set_flow_mode(&desc[*seq_size], ctx_p->flow_mode);
-       set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0);
-       (*seq_size)++;
-
-       /* load data key */
-       hw_desc_init(&desc[*seq_size]);
-       set_din_type(&desc[*seq_size], DMA_DLLI,
-                    (ctx_p->user.key_dma_addr + CC_MULTI2_SYSTEM_KEY_SIZE),
-                    CC_MULTI2_DATA_KEY_SIZE, NS_BIT);
-       set_multi2_num_rounds(&desc[*seq_size], ctx_p->key_round_number);
-       set_flow_mode(&desc[*seq_size], ctx_p->flow_mode);
-       set_cipher_mode(&desc[*seq_size], ctx_p->cipher_mode);
-       set_cipher_config0(&desc[*seq_size], direction);
-       set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE0);
-       (*seq_size)++;
-
-       /* Set state */
-       hw_desc_init(&desc[*seq_size]);
-       set_din_type(&desc[*seq_size], DMA_DLLI, req_ctx->gen_ctx.iv_dma_addr,
-                    ivsize, NS_BIT);
-       set_cipher_config0(&desc[*seq_size], direction);
-       set_flow_mode(&desc[*seq_size], ctx_p->flow_mode);
-       set_cipher_mode(&desc[*seq_size], ctx_p->cipher_mode);
-       set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1);
-       (*seq_size)++;
-}
-#endif /*SSI_CC_HAS_MULTI2*/
-
-static inline void
-ssi_blkcipher_create_data_desc(
-       struct crypto_tfm *tfm,
-       struct blkcipher_req_ctx *req_ctx,
-       struct scatterlist *dst, struct scatterlist *src,
-       unsigned int nbytes,
-       void *areq,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size)
-{
-       struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
-       unsigned int flow_mode = ctx_p->flow_mode;
-
-       switch (ctx_p->flow_mode) {
-       case S_DIN_to_AES:
-               flow_mode = DIN_AES_DOUT;
-               break;
-       case S_DIN_to_DES:
-               flow_mode = DIN_DES_DOUT;
-               break;
-#if SSI_CC_HAS_MULTI2
-       case S_DIN_to_MULTI2:
-               flow_mode = DIN_MULTI2_DOUT;
-               break;
-#endif /*SSI_CC_HAS_MULTI2*/
-       default:
-               dev_err(dev, "invalid flow mode, flow_mode = %d\n", flow_mode);
-               return;
-       }
-       /* Process */
-       if (likely(req_ctx->dma_buf_type == SSI_DMA_BUF_DLLI)) {
-               dev_dbg(dev, " data params addr %pad length 0x%X\n",
-                       &sg_dma_address(src), nbytes);
-               dev_dbg(dev, " data params addr %pad length 0x%X\n",
-                       &sg_dma_address(dst), nbytes);
-               hw_desc_init(&desc[*seq_size]);
-               set_din_type(&desc[*seq_size], DMA_DLLI, sg_dma_address(src),
-                            nbytes, NS_BIT);
-               set_dout_dlli(&desc[*seq_size], sg_dma_address(dst),
-                             nbytes, NS_BIT, (!areq ? 0 : 1));
-               if (areq)
-                       set_queue_last_ind(&desc[*seq_size]);
-
-               set_flow_mode(&desc[*seq_size], flow_mode);
-               (*seq_size)++;
-       } else {
-               /* bypass */
-               dev_dbg(dev, " bypass params addr %pad length 0x%X addr 0x%08X\n",
-                       &req_ctx->mlli_params.mlli_dma_addr,
-                       req_ctx->mlli_params.mlli_len,
-                       (unsigned int)ctx_p->drvdata->mlli_sram_addr);
-               hw_desc_init(&desc[*seq_size]);
-               set_din_type(&desc[*seq_size], DMA_DLLI,
-                            req_ctx->mlli_params.mlli_dma_addr,
-                            req_ctx->mlli_params.mlli_len, NS_BIT);
-               set_dout_sram(&desc[*seq_size],
-                             ctx_p->drvdata->mlli_sram_addr,
-                             req_ctx->mlli_params.mlli_len);
-               set_flow_mode(&desc[*seq_size], BYPASS);
-               (*seq_size)++;
-
-               hw_desc_init(&desc[*seq_size]);
-               set_din_type(&desc[*seq_size], DMA_MLLI,
-                            ctx_p->drvdata->mlli_sram_addr,
-                            req_ctx->in_mlli_nents, NS_BIT);
-               if (req_ctx->out_nents == 0) {
-                       dev_dbg(dev, " din/dout params addr 0x%08X addr 0x%08X\n",
-                               (unsigned int)ctx_p->drvdata->mlli_sram_addr,
-                               (unsigned int)ctx_p->drvdata->mlli_sram_addr);
-                       set_dout_mlli(&desc[*seq_size],
-                                     ctx_p->drvdata->mlli_sram_addr,
-                                     req_ctx->in_mlli_nents, NS_BIT,
-                                     (!areq ? 0 : 1));
-               } else {
-                       dev_dbg(dev, " din/dout params addr 0x%08X addr 0x%08X\n",
-                               (unsigned int)ctx_p->drvdata->mlli_sram_addr,
-                               (unsigned int)ctx_p->drvdata->mlli_sram_addr +
-                               (u32)LLI_ENTRY_BYTE_SIZE * req_ctx->in_nents);
-                       set_dout_mlli(&desc[*seq_size],
-                                     (ctx_p->drvdata->mlli_sram_addr +
-                                      (LLI_ENTRY_BYTE_SIZE *
-                                       req_ctx->in_mlli_nents)),
-                                     req_ctx->out_mlli_nents, NS_BIT,
-                                     (!areq ? 0 : 1));
-               }
-               if (areq)
-                       set_queue_last_ind(&desc[*seq_size]);
-
-               set_flow_mode(&desc[*seq_size], flow_mode);
-               (*seq_size)++;
-       }
-}
-
-static int ssi_blkcipher_complete(struct device *dev,
-                                 struct ssi_ablkcipher_ctx *ctx_p,
-                                 struct blkcipher_req_ctx *req_ctx,
-                                 struct scatterlist *dst,
-                                 struct scatterlist *src,
-                                 unsigned int ivsize,
-                                 void *areq,
-                                 void __iomem *cc_base)
-{
-       int completion_error = 0;
-       struct ablkcipher_request *req = (struct ablkcipher_request *)areq;
-
-       ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
-       kfree(req_ctx->iv);
-
-       if (areq) {
-               /*
-                * The crypto API expects us to set the req->info to the last
-                * ciphertext block. For encrypt, simply copy from the result.
-                * For decrypt, we must copy from a saved buffer since this
-                * could be an in-place decryption operation and the src is
-                * lost by this point.
-                */
-               if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT)  {
-                       memcpy(req->info, req_ctx->backup_info, ivsize);
-                       kfree(req_ctx->backup_info);
-               } else {
-                       scatterwalk_map_and_copy(req->info, req->dst,
-                                                (req->nbytes - ivsize),
-                                                ivsize, 0);
-               }
-
-               ablkcipher_request_complete(areq, completion_error);
-               return 0;
-       }
-       return completion_error;
-}
-
-static int ssi_blkcipher_process(
-       struct crypto_tfm *tfm,
-       struct blkcipher_req_ctx *req_ctx,
-       struct scatterlist *dst, struct scatterlist *src,
-       unsigned int nbytes,
-       void *info, //req info
-       unsigned int ivsize,
-       void *areq,
-       enum drv_crypto_direction direction)
-{
-       struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx_p->drvdata);
-       struct cc_hw_desc desc[MAX_ABLKCIPHER_SEQ_LEN];
-       struct ssi_crypto_req ssi_req = {};
-       int rc, seq_len = 0, cts_restore_flag = 0;
-
-       dev_dbg(dev, "%s areq=%p info=%p nbytes=%d\n",
-               ((direction == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
-               "Encrypt" : "Decrypt"), areq, info, nbytes);
-
-       /* STAT_PHASE_0: Init and sanity checks */
-
-       /* TODO: check data length according to mode */
-       if (unlikely(validate_data_size(ctx_p, nbytes))) {
-               dev_err(dev, "Unsupported data size %d.\n", nbytes);
-               crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_BLOCK_LEN);
-               rc = -EINVAL;
-               goto exit_process;
-       }
-       if (nbytes == 0) {
-               /* No data to process is valid */
-               rc = 0;
-               goto exit_process;
-       }
-
-       /* The IV we are handed may be allocted from the stack so
-        * we must copy it to a DMAable buffer before use.
-        */
-       req_ctx->iv = kmalloc(ivsize, GFP_KERNEL);
-       if (!req_ctx->iv) {
-               rc = -ENOMEM;
-               goto exit_process;
-       }
-       memcpy(req_ctx->iv, info, ivsize);
-
-       /*For CTS in case of data size aligned to 16 use CBC mode*/
-       if (((nbytes % AES_BLOCK_SIZE) == 0) && (ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS)) {
-               ctx_p->cipher_mode = DRV_CIPHER_CBC;
-               cts_restore_flag = 1;
-       }
-
-       /* Setup DX request structure */
-       ssi_req.user_cb = (void *)ssi_ablkcipher_complete;
-       ssi_req.user_arg = (void *)areq;
-
-#ifdef ENABLE_CYCLE_COUNT
-       ssi_req.op_type = (direction == DRV_CRYPTO_DIRECTION_DECRYPT) ?
-               STAT_OP_TYPE_DECODE : STAT_OP_TYPE_ENCODE;
-
-#endif
-
-       /* Setup request context */
-       req_ctx->gen_ctx.op_type = direction;
-
-       /* STAT_PHASE_1: Map buffers */
-
-       rc = ssi_buffer_mgr_map_blkcipher_request(ctx_p->drvdata, req_ctx,
-                                                 ivsize, nbytes, req_ctx->iv,
-                                                 src, dst);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "map_request() failed\n");
-               goto exit_process;
-       }
-
-       /* STAT_PHASE_2: Create sequence */
-
-       /* Setup processing */
-#if SSI_CC_HAS_MULTI2
-       if (ctx_p->flow_mode == S_DIN_to_MULTI2)
-               ssi_blkcipher_create_multi2_setup_desc(tfm, req_ctx, ivsize,
-                                                      desc, &seq_len);
-       else
-#endif /*SSI_CC_HAS_MULTI2*/
-               ssi_blkcipher_create_setup_desc(tfm, req_ctx, ivsize, nbytes,
-                                               desc, &seq_len);
-       /* Data processing */
-       ssi_blkcipher_create_data_desc(tfm, req_ctx, dst, src, nbytes, areq,
-                                      desc, &seq_len);
-
-       /* do we need to generate IV? */
-       if (req_ctx->is_giv) {
-               ssi_req.ivgen_dma_addr[0] = req_ctx->gen_ctx.iv_dma_addr;
-               ssi_req.ivgen_dma_addr_len = 1;
-               /* set the IV size (8/16 B long)*/
-               ssi_req.ivgen_size = ivsize;
-       }
-
-       /* STAT_PHASE_3: Lock HW and push sequence */
-
-       rc = send_request(ctx_p->drvdata, &ssi_req, desc, seq_len, (!areq) ? 0 : 1);
-       if (areq) {
-               if (unlikely(rc != -EINPROGRESS)) {
-                       /* Failed to send the request or request completed synchronously */
-                       ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
-               }
-
-       } else {
-               if (rc != 0) {
-                       ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
-               } else {
-                       rc = ssi_blkcipher_complete(dev, ctx_p, req_ctx, dst,
-                                                   src, ivsize, NULL,
-                                                   ctx_p->drvdata->cc_base);
-               }
-       }
-
-exit_process:
-       if (cts_restore_flag != 0)
-               ctx_p->cipher_mode = DRV_CIPHER_CBC_CTS;
-
-       if (rc != -EINPROGRESS) {
-               kfree(req_ctx->backup_info);
-               kfree(req_ctx->iv);
-       }
-
-       return rc;
-}
-
-static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __iomem *cc_base)
-{
-       struct ablkcipher_request *areq = (struct ablkcipher_request *)ssi_req;
-       struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(areq);
-       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
-       struct ssi_ablkcipher_ctx *ctx_p = crypto_ablkcipher_ctx(tfm);
-       unsigned int ivsize = crypto_ablkcipher_ivsize(tfm);
-
-       ssi_blkcipher_complete(dev, ctx_p, req_ctx, areq->dst, areq->src,
-                              ivsize, areq, cc_base);
-}
-
-/* Async wrap functions */
-
-static int ssi_ablkcipher_init(struct crypto_tfm *tfm)
-{
-       struct ablkcipher_tfm *ablktfm = &tfm->crt_ablkcipher;
-
-       ablktfm->reqsize = sizeof(struct blkcipher_req_ctx);
-
-       return ssi_blkcipher_init(tfm);
-}
-
-static int ssi_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
-                                const u8 *key,
-                                unsigned int keylen)
-{
-       return ssi_blkcipher_setkey(crypto_ablkcipher_tfm(tfm), key, keylen);
-}
-
-static int ssi_ablkcipher_encrypt(struct ablkcipher_request *req)
-{
-       struct crypto_ablkcipher *ablk_tfm = crypto_ablkcipher_reqtfm(req);
-       struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk_tfm);
-       struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(req);
-       unsigned int ivsize = crypto_ablkcipher_ivsize(ablk_tfm);
-
-       req_ctx->is_giv = false;
-
-       return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, req->nbytes, req->info, ivsize, (void *)req, DRV_CRYPTO_DIRECTION_ENCRYPT);
-}
-
-static int ssi_ablkcipher_decrypt(struct ablkcipher_request *req)
-{
-       struct crypto_ablkcipher *ablk_tfm = crypto_ablkcipher_reqtfm(req);
-       struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk_tfm);
-       struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(req);
-       unsigned int ivsize = crypto_ablkcipher_ivsize(ablk_tfm);
-
-       /*
-        * Allocate and save the last IV sized bytes of the source, which will
-        * be lost in case of in-place decryption and might be needed for CTS.
-        */
-       req_ctx->backup_info = kmalloc(ivsize, GFP_KERNEL);
-       if (!req_ctx->backup_info)
-               return -ENOMEM;
-
-       scatterwalk_map_and_copy(req_ctx->backup_info, req->src,
-                                (req->nbytes - ivsize), ivsize, 0);
-       req_ctx->is_giv = false;
-
-       return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, req->nbytes, req->info, ivsize, (void *)req, DRV_CRYPTO_DIRECTION_DECRYPT);
-}
-
-/* DX Block cipher alg */
-static struct ssi_alg_template blkcipher_algs[] = {
-/* Async template */
-#if SSI_CC_HAS_AES_XTS
-       {
-               .name = "xts(aes)",
-               .driver_name = "xts-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE * 2,
-                       .max_keysize = AES_MAX_KEY_SIZE * 2,
-                       .ivsize = AES_BLOCK_SIZE,
-                       .geniv = "eseqiv",
-                       },
-               .cipher_mode = DRV_CIPHER_XTS,
-               .flow_mode = S_DIN_to_AES,
-       },
-       {
-               .name = "xts(aes)",
-               .driver_name = "xts-aes-du512-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_512,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE * 2,
-                       .max_keysize = AES_MAX_KEY_SIZE * 2,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_XTS,
-               .flow_mode = S_DIN_to_AES,
-       },
-       {
-               .name = "xts(aes)",
-               .driver_name = "xts-aes-du4096-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_4096,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE * 2,
-                       .max_keysize = AES_MAX_KEY_SIZE * 2,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_XTS,
-               .flow_mode = S_DIN_to_AES,
-       },
-#endif /*SSI_CC_HAS_AES_XTS*/
-#if SSI_CC_HAS_AES_ESSIV
-       {
-               .name = "essiv(aes)",
-               .driver_name = "essiv-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE * 2,
-                       .max_keysize = AES_MAX_KEY_SIZE * 2,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_ESSIV,
-               .flow_mode = S_DIN_to_AES,
-       },
-       {
-               .name = "essiv(aes)",
-               .driver_name = "essiv-aes-du512-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_512,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE * 2,
-                       .max_keysize = AES_MAX_KEY_SIZE * 2,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_ESSIV,
-               .flow_mode = S_DIN_to_AES,
-       },
-       {
-               .name = "essiv(aes)",
-               .driver_name = "essiv-aes-du4096-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_4096,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE * 2,
-                       .max_keysize = AES_MAX_KEY_SIZE * 2,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_ESSIV,
-               .flow_mode = S_DIN_to_AES,
-       },
-#endif /*SSI_CC_HAS_AES_ESSIV*/
-#if SSI_CC_HAS_AES_BITLOCKER
-       {
-               .name = "bitlocker(aes)",
-               .driver_name = "bitlocker-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE * 2,
-                       .max_keysize = AES_MAX_KEY_SIZE * 2,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_BITLOCKER,
-               .flow_mode = S_DIN_to_AES,
-       },
-       {
-               .name = "bitlocker(aes)",
-               .driver_name = "bitlocker-aes-du512-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_512,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE * 2,
-                       .max_keysize = AES_MAX_KEY_SIZE * 2,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_BITLOCKER,
-               .flow_mode = S_DIN_to_AES,
-       },
-       {
-               .name = "bitlocker(aes)",
-               .driver_name = "bitlocker-aes-du4096-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_BULK_DU_4096,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE * 2,
-                       .max_keysize = AES_MAX_KEY_SIZE * 2,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_BITLOCKER,
-               .flow_mode = S_DIN_to_AES,
-       },
-#endif /*SSI_CC_HAS_AES_BITLOCKER*/
-       {
-               .name = "ecb(aes)",
-               .driver_name = "ecb-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE,
-                       .max_keysize = AES_MAX_KEY_SIZE,
-                       .ivsize = 0,
-                       },
-               .cipher_mode = DRV_CIPHER_ECB,
-               .flow_mode = S_DIN_to_AES,
-       },
-       {
-               .name = "cbc(aes)",
-               .driver_name = "cbc-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE,
-                       .max_keysize = AES_MAX_KEY_SIZE,
-                       .ivsize = AES_BLOCK_SIZE,
-               },
-               .cipher_mode = DRV_CIPHER_CBC,
-               .flow_mode = S_DIN_to_AES,
-       },
-       {
-               .name = "ofb(aes)",
-               .driver_name = "ofb-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE,
-                       .max_keysize = AES_MAX_KEY_SIZE,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_OFB,
-               .flow_mode = S_DIN_to_AES,
-       },
-#if SSI_CC_HAS_AES_CTS
-       {
-               .name = "cts1(cbc(aes))",
-               .driver_name = "cts1-cbc-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE,
-                       .max_keysize = AES_MAX_KEY_SIZE,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_CBC_CTS,
-               .flow_mode = S_DIN_to_AES,
-       },
-#endif
-       {
-               .name = "ctr(aes)",
-               .driver_name = "ctr-aes-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = AES_MIN_KEY_SIZE,
-                       .max_keysize = AES_MAX_KEY_SIZE,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_CTR,
-               .flow_mode = S_DIN_to_AES,
-       },
-       {
-               .name = "cbc(des3_ede)",
-               .driver_name = "cbc-3des-dx",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = DES3_EDE_KEY_SIZE,
-                       .max_keysize = DES3_EDE_KEY_SIZE,
-                       .ivsize = DES3_EDE_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_CBC,
-               .flow_mode = S_DIN_to_DES,
-       },
-       {
-               .name = "ecb(des3_ede)",
-               .driver_name = "ecb-3des-dx",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = DES3_EDE_KEY_SIZE,
-                       .max_keysize = DES3_EDE_KEY_SIZE,
-                       .ivsize = 0,
-                       },
-               .cipher_mode = DRV_CIPHER_ECB,
-               .flow_mode = S_DIN_to_DES,
-       },
-       {
-               .name = "cbc(des)",
-               .driver_name = "cbc-des-dx",
-               .blocksize = DES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = DES_KEY_SIZE,
-                       .max_keysize = DES_KEY_SIZE,
-                       .ivsize = DES_BLOCK_SIZE,
-                       },
-               .cipher_mode = DRV_CIPHER_CBC,
-               .flow_mode = S_DIN_to_DES,
-       },
-       {
-               .name = "ecb(des)",
-               .driver_name = "ecb-des-dx",
-               .blocksize = DES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = DES_KEY_SIZE,
-                       .max_keysize = DES_KEY_SIZE,
-                       .ivsize = 0,
-                       },
-               .cipher_mode = DRV_CIPHER_ECB,
-               .flow_mode = S_DIN_to_DES,
-       },
-#if SSI_CC_HAS_MULTI2
-       {
-               .name = "cbc(multi2)",
-               .driver_name = "cbc-multi2-dx",
-               .blocksize = CC_MULTI2_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_decrypt,
-                       .min_keysize = CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE + 1,
-                       .max_keysize = CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE + 1,
-                       .ivsize = CC_MULTI2_IV_SIZE,
-                       },
-               .cipher_mode = DRV_MULTI2_CBC,
-               .flow_mode = S_DIN_to_MULTI2,
-       },
-       {
-               .name = "ofb(multi2)",
-               .driver_name = "ofb-multi2-dx",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ssi_ablkcipher_setkey,
-                       .encrypt = ssi_ablkcipher_encrypt,
-                       .decrypt = ssi_ablkcipher_encrypt,
-                       .min_keysize = CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE + 1,
-                       .max_keysize = CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE + 1,
-                       .ivsize = CC_MULTI2_IV_SIZE,
-                       },
-               .cipher_mode = DRV_MULTI2_OFB,
-               .flow_mode = S_DIN_to_MULTI2,
-       },
-#endif /*SSI_CC_HAS_MULTI2*/
-};
-
-static
-struct ssi_crypto_alg *ssi_ablkcipher_create_alg(struct ssi_alg_template
-                                                *template, struct device *dev)
-{
-       struct ssi_crypto_alg *t_alg;
-       struct crypto_alg *alg;
-
-       t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
-       if (!t_alg)
-               return ERR_PTR(-ENOMEM);
-
-       alg = &t_alg->crypto_alg;
-
-       snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", template->name);
-       snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
-                template->driver_name);
-       alg->cra_module = THIS_MODULE;
-       alg->cra_priority = SSI_CRA_PRIO;
-       alg->cra_blocksize = template->blocksize;
-       alg->cra_alignmask = 0;
-       alg->cra_ctxsize = sizeof(struct ssi_ablkcipher_ctx);
-
-       alg->cra_init = ssi_ablkcipher_init;
-       alg->cra_exit = ssi_blkcipher_exit;
-       alg->cra_type = &crypto_ablkcipher_type;
-       alg->cra_ablkcipher = template->template_ablkcipher;
-       alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
-                               template->type;
-
-       t_alg->cipher_mode = template->cipher_mode;
-       t_alg->flow_mode = template->flow_mode;
-
-       return t_alg;
-}
-
-int ssi_ablkcipher_free(struct ssi_drvdata *drvdata)
-{
-       struct ssi_crypto_alg *t_alg, *n;
-       struct ssi_blkcipher_handle *blkcipher_handle =
-                                               drvdata->blkcipher_handle;
-       if (blkcipher_handle) {
-               /* Remove registered algs */
-               list_for_each_entry_safe(t_alg, n,
-                                        &blkcipher_handle->blkcipher_alg_list,
-                                        entry) {
-                       crypto_unregister_alg(&t_alg->crypto_alg);
-                       list_del(&t_alg->entry);
-                       kfree(t_alg);
-               }
-               kfree(blkcipher_handle);
-               drvdata->blkcipher_handle = NULL;
-       }
-       return 0;
-}
-
-int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata)
-{
-       struct ssi_blkcipher_handle *ablkcipher_handle;
-       struct ssi_crypto_alg *t_alg;
-       struct device *dev = drvdata_to_dev(drvdata);
-       int rc = -ENOMEM;
-       int alg;
-
-       ablkcipher_handle = kmalloc(sizeof(*ablkcipher_handle), GFP_KERNEL);
-       if (!ablkcipher_handle)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&ablkcipher_handle->blkcipher_alg_list);
-       drvdata->blkcipher_handle = ablkcipher_handle;
-
-       /* Linux crypto */
-       dev_dbg(dev, "Number of algorithms = %zu\n",
-               ARRAY_SIZE(blkcipher_algs));
-       for (alg = 0; alg < ARRAY_SIZE(blkcipher_algs); alg++) {
-               dev_dbg(dev, "creating %s\n", blkcipher_algs[alg].driver_name);
-               t_alg = ssi_ablkcipher_create_alg(&blkcipher_algs[alg], dev);
-               if (IS_ERR(t_alg)) {
-                       rc = PTR_ERR(t_alg);
-                       dev_err(dev, "%s alg allocation failed\n",
-                               blkcipher_algs[alg].driver_name);
-                       goto fail0;
-               }
-               t_alg->drvdata = drvdata;
-
-               dev_dbg(dev, "registering %s\n",
-                       blkcipher_algs[alg].driver_name);
-               rc = crypto_register_alg(&t_alg->crypto_alg);
-               dev_dbg(dev, "%s alg registration rc = %x\n",
-                       t_alg->crypto_alg.cra_driver_name, rc);
-               if (unlikely(rc != 0)) {
-                       dev_err(dev, "%s alg registration failed\n",
-                               t_alg->crypto_alg.cra_driver_name);
-                       kfree(t_alg);
-                       goto fail0;
-               } else {
-                       list_add_tail(&t_alg->entry,
-                                     &ablkcipher_handle->blkcipher_alg_list);
-                       dev_dbg(dev, "Registered %s\n",
-                               t_alg->crypto_alg.cra_driver_name);
-               }
-       }
-       return 0;
-
-fail0:
-       ssi_ablkcipher_free(drvdata);
-       return rc;
-}
diff --git a/drivers/staging/ccree/ssi_cipher.h b/drivers/staging/ccree/ssi_cipher.h
deleted file mode 100644 (file)
index 25e6335..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file ssi_cipher.h
- * ARM CryptoCell Cipher Crypto API
- */
-
-#ifndef __SSI_CIPHER_H__
-#define __SSI_CIPHER_H__
-
-#include <linux/kernel.h>
-#include <crypto/algapi.h>
-#include "ssi_driver.h"
-#include "ssi_buffer_mgr.h"
-
-/* Crypto cipher flags */
-#define CC_CRYPTO_CIPHER_KEY_KFDE0     BIT(0)
-#define CC_CRYPTO_CIPHER_KEY_KFDE1     BIT(1)
-#define CC_CRYPTO_CIPHER_KEY_KFDE2     BIT(2)
-#define CC_CRYPTO_CIPHER_KEY_KFDE3     BIT(3)
-#define CC_CRYPTO_CIPHER_DU_SIZE_512B  BIT(4)
-
-#define CC_CRYPTO_CIPHER_KEY_KFDE_MASK (CC_CRYPTO_CIPHER_KEY_KFDE0 | CC_CRYPTO_CIPHER_KEY_KFDE1 | CC_CRYPTO_CIPHER_KEY_KFDE2 | CC_CRYPTO_CIPHER_KEY_KFDE3)
-
-struct blkcipher_req_ctx {
-       struct async_gen_req_ctx gen_ctx;
-       enum ssi_req_dma_buf_type dma_buf_type;
-       u32 in_nents;
-       u32 in_mlli_nents;
-       u32 out_nents;
-       u32 out_mlli_nents;
-       u8 *backup_info; /*store iv for generated IV flow*/
-       u8 *iv;
-       bool is_giv;
-       struct mlli_params mlli_params;
-};
-
-int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata);
-
-int ssi_ablkcipher_free(struct ssi_drvdata *drvdata);
-
-#ifndef CRYPTO_ALG_BULK_MASK
-
-#define CRYPTO_ALG_BULK_DU_512 0x00002000
-#define CRYPTO_ALG_BULK_DU_4096        0x00004000
-#define CRYPTO_ALG_BULK_MASK   (CRYPTO_ALG_BULK_DU_512 |\
-                               CRYPTO_ALG_BULK_DU_4096)
-#endif /* CRYPTO_ALG_BULK_MASK */
-
-#ifdef CRYPTO_TFM_REQ_HW_KEY
-
-static inline bool ssi_is_hw_key(struct crypto_tfm *tfm)
-{
-       return (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_HW_KEY);
-}
-
-#else
-
-struct arm_hw_key_info {
-       int hw_key1;
-       int hw_key2;
-};
-
-static inline bool ssi_is_hw_key(struct crypto_tfm *tfm)
-{
-       return false;
-}
-
-#endif /* CRYPTO_TFM_REQ_HW_KEY */
-
-#endif /*__SSI_CIPHER_H__*/
diff --git a/drivers/staging/ccree/ssi_config.h b/drivers/staging/ccree/ssi_config.h
deleted file mode 100644 (file)
index ff7597c..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file ssi_config.h
- * Definitions for ARM CryptoCell Linux Crypto Driver
- */
-
-#ifndef __SSI_CONFIG_H__
-#define __SSI_CONFIG_H__
-
-#include <linux/version.h>
-
-//#define FLUSH_CACHE_ALL
-//#define COMPLETION_DELAY
-//#define DX_DUMP_DESCS
-// #define DX_DUMP_BYTES
-// #define CC_DEBUG
-#define ENABLE_CC_SYSFS                /* Enable sysfs interface for debugging REE driver */
-//#define DX_IRQ_DELAY 100000
-#define DMA_BIT_MASK_LEN       48      /* was 32 bit, but for juno's sake it was enlarged to 48 bit */
-
-#endif /*__DX_CONFIG_H__*/
-
diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c
deleted file mode 100644 (file)
index 1a3c481..0000000
+++ /dev/null
@@ -1,538 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <linux/crypto.h>
-#include <crypto/algapi.h>
-#include <crypto/aes.h>
-#include <crypto/sha.h>
-#include <crypto/aead.h>
-#include <crypto/authenc.h>
-#include <crypto/scatterwalk.h>
-#include <crypto/internal/skcipher.h>
-
-#include <linux/init.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/random.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/fcntl.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/mutex.h>
-#include <linux/sysctl.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/platform_device.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/pm.h>
-
-/* cache.h required for L1_CACHE_ALIGN() and cache_line_size() */
-#include <linux/cache.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/pagemap.h>
-#include <linux/sched.h>
-#include <linux/random.h>
-#include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/of_address.h>
-
-#include "ssi_config.h"
-#include "ssi_driver.h"
-#include "ssi_request_mgr.h"
-#include "ssi_buffer_mgr.h"
-#include "ssi_sysfs.h"
-#include "ssi_cipher.h"
-#include "ssi_aead.h"
-#include "ssi_hash.h"
-#include "ssi_ivgen.h"
-#include "ssi_sram_mgr.h"
-#include "ssi_pm.h"
-#include "ssi_fips.h"
-
-#ifdef DX_DUMP_BYTES
-void dump_byte_array(const char *name, const u8 *buf, size_t len)
-{
-       char prefix[NAME_LEN];
-
-       if (!buf)
-               return;
-
-       snprintf(prefix, sizeof(prefix), "%s[%lu]: ", name, len);
-
-       print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_ADDRESS, 16, 1, len,
-                      false);
-}
-#endif
-
-static irqreturn_t cc_isr(int irq, void *dev_id)
-{
-       struct ssi_drvdata *drvdata = (struct ssi_drvdata *)dev_id;
-       struct device *dev = drvdata_to_dev(drvdata);
-       u32 irr;
-       u32 imr;
-
-       /* STAT_OP_TYPE_GENERIC STAT_PHASE_0: Interrupt */
-
-       /* read the interrupt status */
-       irr = cc_ioread(drvdata, CC_REG(HOST_IRR));
-       dev_dbg(dev, "Got IRR=0x%08X\n", irr);
-       if (unlikely(irr == 0)) { /* Probably shared interrupt line */
-               dev_err(dev, "Got interrupt with empty IRR\n");
-               return IRQ_NONE;
-       }
-       imr = cc_ioread(drvdata, CC_REG(HOST_IMR));
-
-       /* clear interrupt - must be before processing events */
-       cc_iowrite(drvdata, CC_REG(HOST_ICR), irr);
-
-       drvdata->irq = irr;
-       /* Completion interrupt - most probable */
-       if (likely((irr & SSI_COMP_IRQ_MASK) != 0)) {
-               /* Mask AXI completion interrupt - will be unmasked in Deferred service handler */
-               cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | SSI_COMP_IRQ_MASK);
-               irr &= ~SSI_COMP_IRQ_MASK;
-               complete_request(drvdata);
-       }
-#ifdef CC_SUPPORT_FIPS
-       /* TEE FIPS interrupt */
-       if (likely((irr & SSI_GPR0_IRQ_MASK) != 0)) {
-               /* Mask interrupt - will be unmasked in Deferred service handler */
-               cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | SSI_GPR0_IRQ_MASK);
-               irr &= ~SSI_GPR0_IRQ_MASK;
-               fips_handler(drvdata);
-       }
-#endif
-       /* AXI error interrupt */
-       if (unlikely((irr & SSI_AXI_ERR_IRQ_MASK) != 0)) {
-               u32 axi_err;
-
-               /* Read the AXI error ID */
-               axi_err = cc_ioread(drvdata, CC_REG(AXIM_MON_ERR));
-               dev_dbg(dev, "AXI completion error: axim_mon_err=0x%08X\n",
-                       axi_err);
-
-               irr &= ~SSI_AXI_ERR_IRQ_MASK;
-       }
-
-       if (unlikely(irr != 0)) {
-               dev_dbg(dev, "IRR includes unknown cause bits (0x%08X)\n",
-                       irr);
-               /* Just warning */
-       }
-
-       return IRQ_HANDLED;
-}
-
-int init_cc_regs(struct ssi_drvdata *drvdata, bool is_probe)
-{
-       unsigned int val, cache_params;
-       struct device *dev = drvdata_to_dev(drvdata);
-
-       /* Unmask all AXI interrupt sources AXI_CFG1 register */
-       val = cc_ioread(drvdata, CC_REG(AXIM_CFG));
-       cc_iowrite(drvdata, CC_REG(AXIM_CFG), val & ~SSI_AXI_IRQ_MASK);
-       dev_dbg(dev, "AXIM_CFG=0x%08X\n",
-               cc_ioread(drvdata, CC_REG(AXIM_CFG)));
-
-       /* Clear all pending interrupts */
-       val = cc_ioread(drvdata, CC_REG(HOST_IRR));
-       dev_dbg(dev, "IRR=0x%08X\n", val);
-       cc_iowrite(drvdata, CC_REG(HOST_ICR), val);
-
-       /* Unmask relevant interrupt cause */
-       val = (unsigned int)(~(SSI_COMP_IRQ_MASK | SSI_AXI_ERR_IRQ_MASK |
-                              SSI_GPR0_IRQ_MASK));
-       cc_iowrite(drvdata, CC_REG(HOST_IMR), val);
-
-#ifdef DX_HOST_IRQ_TIMER_INIT_VAL_REG_OFFSET
-#ifdef DX_IRQ_DELAY
-       /* Set CC IRQ delay */
-       cc_iowrite(drvdata, CC_REG(HOST_IRQ_TIMER_INIT_VAL), DX_IRQ_DELAY);
-#endif
-       if (cc_ioread(drvdata, CC_REG(HOST_IRQ_TIMER_INIT_VAL)) > 0) {
-               dev_dbg(dev, "irq_delay=%d CC cycles\n",
-                       cc_ioread(drvdata, CC_REG(HOST_IRQ_TIMER_INIT_VAL)));
-       }
-#endif
-
-       cache_params = (drvdata->coherent ? CC_COHERENT_CACHE_PARAMS : 0x0);
-
-       val = cc_ioread(drvdata, CC_REG(AXIM_CACHE_PARAMS));
-
-       if (is_probe)
-               dev_info(dev, "Cache params previous: 0x%08X\n", val);
-
-       cc_iowrite(drvdata, CC_REG(AXIM_CACHE_PARAMS), cache_params);
-       val = cc_ioread(drvdata, CC_REG(AXIM_CACHE_PARAMS));
-
-       if (is_probe)
-               dev_info(dev, "Cache params current: 0x%08X (expect: 0x%08X)\n",
-                        val, cache_params);
-
-       return 0;
-}
-
-static int init_cc_resources(struct platform_device *plat_dev)
-{
-       struct resource *req_mem_cc_regs = NULL;
-       void __iomem *cc_base = NULL;
-       struct ssi_drvdata *new_drvdata;
-       struct device *dev = &plat_dev->dev;
-       struct device_node *np = dev->of_node;
-       u32 signature_val;
-       dma_addr_t dma_mask;
-       int rc = 0;
-
-       new_drvdata = devm_kzalloc(dev, sizeof(*new_drvdata), GFP_KERNEL);
-       if (!new_drvdata)
-               return -ENOMEM;
-
-       platform_set_drvdata(plat_dev, new_drvdata);
-       new_drvdata->plat_dev = plat_dev;
-
-       new_drvdata->clk = of_clk_get(np, 0);
-       new_drvdata->coherent = of_dma_is_coherent(np);
-
-       /* Get device resources */
-       /* First CC registers space */
-       req_mem_cc_regs = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
-       /* Map registers space */
-       new_drvdata->cc_base = devm_ioremap_resource(dev, req_mem_cc_regs);
-       if (IS_ERR(new_drvdata->cc_base)) {
-               dev_err(dev, "Failed to ioremap registers");
-               return PTR_ERR(new_drvdata->cc_base);
-       }
-
-       dev_dbg(dev, "Got MEM resource (%s): %pR\n", req_mem_cc_regs->name,
-               req_mem_cc_regs);
-       dev_dbg(dev, "CC registers mapped from %pa to 0x%p\n",
-               &req_mem_cc_regs->start, new_drvdata->cc_base);
-
-       cc_base = new_drvdata->cc_base;
-
-       /* Then IRQ */
-       new_drvdata->irq = platform_get_irq(plat_dev, 0);
-       if (new_drvdata->irq < 0) {
-               dev_err(dev, "Failed getting IRQ resource\n");
-               return new_drvdata->irq;
-       }
-
-       rc = devm_request_irq(dev, new_drvdata->irq, cc_isr,
-                             IRQF_SHARED, "arm_cc7x", new_drvdata);
-       if (rc) {
-               dev_err(dev, "Could not register to interrupt %d\n",
-                       new_drvdata->irq);
-               return rc;
-       }
-       dev_dbg(dev, "Registered to IRQ: %d\n", new_drvdata->irq);
-
-       if (!plat_dev->dev.dma_mask)
-               plat_dev->dev.dma_mask = &plat_dev->dev.coherent_dma_mask;
-
-       dma_mask = (dma_addr_t)(DMA_BIT_MASK(DMA_BIT_MASK_LEN));
-       while (dma_mask > 0x7fffffffUL) {
-               if (dma_supported(&plat_dev->dev, dma_mask)) {
-                       rc = dma_set_coherent_mask(&plat_dev->dev, dma_mask);
-                       if (!rc)
-                               break;
-               }
-               dma_mask >>= 1;
-       }
-
-       if (rc) {
-               dev_err(dev, "Failed in dma_set_mask, mask=%par\n",
-                       &dma_mask);
-               return rc;
-       }
-
-       rc = cc_clk_on(new_drvdata);
-       if (rc) {
-               dev_err(dev, "Failed to enable clock");
-               return rc;
-       }
-
-       /* Verify correct mapping */
-       signature_val = cc_ioread(new_drvdata, CC_REG(HOST_SIGNATURE));
-       if (signature_val != DX_DEV_SIGNATURE) {
-               dev_err(dev, "Invalid CC signature: SIGNATURE=0x%08X != expected=0x%08X\n",
-                       signature_val, (u32)DX_DEV_SIGNATURE);
-               rc = -EINVAL;
-               goto post_clk_err;
-       }
-       dev_dbg(dev, "CC SIGNATURE=0x%08X\n", signature_val);
-
-       /* Display HW versions */
-       dev_info(dev, "ARM CryptoCell %s Driver: HW version 0x%08X, Driver version %s\n",
-                SSI_DEV_NAME_STR,
-                cc_ioread(new_drvdata, CC_REG(HOST_VERSION)),
-                DRV_MODULE_VERSION);
-
-       rc = init_cc_regs(new_drvdata, true);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "init_cc_regs failed\n");
-               goto post_clk_err;
-       }
-
-#ifdef ENABLE_CC_SYSFS
-       rc = ssi_sysfs_init(&dev->kobj, new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "init_stat_db failed\n");
-               goto post_regs_err;
-       }
-#endif
-
-       rc = ssi_fips_init(new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "SSI_FIPS_INIT failed 0x%x\n", rc);
-               goto post_sysfs_err;
-       }
-       rc = ssi_sram_mgr_init(new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "ssi_sram_mgr_init failed\n");
-               goto post_fips_init_err;
-       }
-
-       new_drvdata->mlli_sram_addr =
-               ssi_sram_mgr_alloc(new_drvdata, MAX_MLLI_BUFF_SIZE);
-       if (unlikely(new_drvdata->mlli_sram_addr == NULL_SRAM_ADDR)) {
-               dev_err(dev, "Failed to alloc MLLI Sram buffer\n");
-               rc = -ENOMEM;
-               goto post_sram_mgr_err;
-       }
-
-       rc = request_mgr_init(new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "request_mgr_init failed\n");
-               goto post_sram_mgr_err;
-       }
-
-       rc = ssi_buffer_mgr_init(new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "buffer_mgr_init failed\n");
-               goto post_req_mgr_err;
-       }
-
-       rc = ssi_power_mgr_init(new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "ssi_power_mgr_init failed\n");
-               goto post_buf_mgr_err;
-       }
-
-       rc = ssi_ivgen_init(new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "ssi_ivgen_init failed\n");
-               goto post_power_mgr_err;
-       }
-
-       /* Allocate crypto algs */
-       rc = ssi_ablkcipher_alloc(new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "ssi_ablkcipher_alloc failed\n");
-               goto post_ivgen_err;
-       }
-
-       /* hash must be allocated before aead since hash exports APIs */
-       rc = ssi_hash_alloc(new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "ssi_hash_alloc failed\n");
-               goto post_cipher_err;
-       }
-
-       rc = ssi_aead_alloc(new_drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "ssi_aead_alloc failed\n");
-               goto post_hash_err;
-       }
-
-       /* If we got here and FIPS mode is enabled
-        * it means all FIPS test passed, so let TEE
-        * know we're good.
-        */
-       cc_set_ree_fips_status(new_drvdata, true);
-
-       return 0;
-
-post_hash_err:
-       ssi_hash_free(new_drvdata);
-post_cipher_err:
-       ssi_ablkcipher_free(new_drvdata);
-post_ivgen_err:
-       ssi_ivgen_fini(new_drvdata);
-post_power_mgr_err:
-       ssi_power_mgr_fini(new_drvdata);
-post_buf_mgr_err:
-        ssi_buffer_mgr_fini(new_drvdata);
-post_req_mgr_err:
-       request_mgr_fini(new_drvdata);
-post_sram_mgr_err:
-       ssi_sram_mgr_fini(new_drvdata);
-post_fips_init_err:
-       ssi_fips_fini(new_drvdata);
-post_sysfs_err:
-#ifdef ENABLE_CC_SYSFS
-       ssi_sysfs_fini();
-#endif
-post_regs_err:
-       fini_cc_regs(new_drvdata);
-post_clk_err:
-       cc_clk_off(new_drvdata);
-       return rc;
-}
-
-void fini_cc_regs(struct ssi_drvdata *drvdata)
-{
-       /* Mask all interrupts */
-       cc_iowrite(drvdata, CC_REG(HOST_IMR), 0xFFFFFFFF);
-}
-
-static void cleanup_cc_resources(struct platform_device *plat_dev)
-{
-       struct ssi_drvdata *drvdata =
-               (struct ssi_drvdata *)platform_get_drvdata(plat_dev);
-
-       ssi_aead_free(drvdata);
-       ssi_hash_free(drvdata);
-       ssi_ablkcipher_free(drvdata);
-       ssi_ivgen_fini(drvdata);
-       ssi_power_mgr_fini(drvdata);
-       ssi_buffer_mgr_fini(drvdata);
-       request_mgr_fini(drvdata);
-       ssi_sram_mgr_fini(drvdata);
-       ssi_fips_fini(drvdata);
-#ifdef ENABLE_CC_SYSFS
-       ssi_sysfs_fini();
-#endif
-       fini_cc_regs(drvdata);
-       cc_clk_off(drvdata);
-}
-
-int cc_clk_on(struct ssi_drvdata *drvdata)
-{
-       struct clk *clk = drvdata->clk;
-       int rc;
-
-       if (IS_ERR(clk))
-               /* Not all devices have a clock associated with CCREE  */
-               return 0;
-
-       rc = clk_prepare_enable(clk);
-       if (rc)
-               return rc;
-
-       return 0;
-}
-
-void cc_clk_off(struct ssi_drvdata *drvdata)
-{
-       struct clk *clk = drvdata->clk;
-
-       if (IS_ERR(clk))
-               /* Not all devices have a clock associated with CCREE */
-               return;
-
-       clk_disable_unprepare(clk);
-}
-
-static int cc7x_probe(struct platform_device *plat_dev)
-{
-       int rc;
-       struct device *dev = &plat_dev->dev;
-#if defined(CONFIG_ARM) && defined(CC_DEBUG)
-       u32 ctr, cacheline_size;
-
-       asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
-       cacheline_size =  4 << ((ctr >> 16) & 0xf);
-       dev_dbg(dev, "CP15(L1_CACHE_BYTES) = %u , Kconfig(L1_CACHE_BYTES) = %u\n",
-               cacheline_size, L1_CACHE_BYTES);
-
-       asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (ctr));
-       dev_dbg(dev, "Main ID register (MIDR): Implementer 0x%02X, Arch 0x%01X, Part 0x%03X, Rev r%dp%d\n",
-               (ctr >> 24), (ctr >> 16) & 0xF, (ctr >> 4) & 0xFFF,
-               (ctr >> 20) & 0xF, ctr & 0xF);
-#endif
-
-       /* Map registers space */
-       rc = init_cc_resources(plat_dev);
-       if (rc != 0)
-               return rc;
-
-       dev_info(dev, "ARM ccree device initialized\n");
-
-       return 0;
-}
-
-static int cc7x_remove(struct platform_device *plat_dev)
-{
-       struct device *dev = &plat_dev->dev;
-
-       dev_dbg(dev, "Releasing cc7x resources...\n");
-
-       cleanup_cc_resources(plat_dev);
-
-       dev_info(dev, "ARM ccree device terminated\n");
-
-       return 0;
-}
-
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-static const struct dev_pm_ops arm_cc7x_driver_pm = {
-       SET_RUNTIME_PM_OPS(ssi_power_mgr_runtime_suspend, ssi_power_mgr_runtime_resume, NULL)
-};
-#endif
-
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-#define        DX_DRIVER_RUNTIME_PM    (&arm_cc7x_driver_pm)
-#else
-#define        DX_DRIVER_RUNTIME_PM    NULL
-#endif
-
-#ifdef CONFIG_OF
-static const struct of_device_id arm_cc7x_dev_of_match[] = {
-       {.compatible = "arm,cryptocell-712-ree"},
-       {}
-};
-MODULE_DEVICE_TABLE(of, arm_cc7x_dev_of_match);
-#endif
-
-static struct platform_driver cc7x_driver = {
-       .driver = {
-                  .name = "cc7xree",
-#ifdef CONFIG_OF
-                  .of_match_table = arm_cc7x_dev_of_match,
-#endif
-                  .pm = DX_DRIVER_RUNTIME_PM,
-       },
-       .probe = cc7x_probe,
-       .remove = cc7x_remove,
-};
-module_platform_driver(cc7x_driver);
-
-/* Module description */
-MODULE_DESCRIPTION("ARM TrustZone CryptoCell REE Driver");
-MODULE_VERSION(DRV_MODULE_VERSION);
-MODULE_AUTHOR("ARM");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/ccree/ssi_driver.h b/drivers/staging/ccree/ssi_driver.h
deleted file mode 100644 (file)
index 94c755c..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file ssi_driver.h
- * ARM CryptoCell Linux Crypto Driver
- */
-
-#ifndef __SSI_DRIVER_H__
-#define __SSI_DRIVER_H__
-
-#include "ssi_config.h"
-#ifdef COMP_IN_WQ
-#include <linux/workqueue.h>
-#else
-#include <linux/interrupt.h>
-#endif
-#include <linux/dma-mapping.h>
-#include <crypto/algapi.h>
-#include <crypto/internal/skcipher.h>
-#include <crypto/aes.h>
-#include <crypto/sha.h>
-#include <crypto/aead.h>
-#include <crypto/authenc.h>
-#include <crypto/hash.h>
-#include <linux/version.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-/* Registers definitions from shared/hw/ree_include */
-#include "dx_host.h"
-#include "dx_reg_common.h"
-#define CC_SUPPORT_SHA DX_DEV_SHA_MAX
-#include "cc_crypto_ctx.h"
-#include "ssi_sysfs.h"
-#include "hash_defs.h"
-#include "cc_hw_queue_defs.h"
-#include "ssi_sram_mgr.h"
-
-#define DRV_MODULE_VERSION "3.0"
-
-#define SSI_DEV_NAME_STR "cc715ree"
-#define CC_COHERENT_CACHE_PARAMS 0xEEE
-
-#define SSI_CC_HAS_AES_CCM 1
-#define SSI_CC_HAS_AES_GCM 1
-#define SSI_CC_HAS_AES_XTS 1
-#define SSI_CC_HAS_AES_ESSIV 1
-#define SSI_CC_HAS_AES_BITLOCKER 1
-#define SSI_CC_HAS_AES_CTS 1
-#define SSI_CC_HAS_MULTI2 0
-#define SSI_CC_HAS_CMAC 1
-
-#define SSI_AXI_IRQ_MASK ((1 << DX_AXIM_CFG_BRESPMASK_BIT_SHIFT) | (1 << DX_AXIM_CFG_RRESPMASK_BIT_SHIFT) |    \
-                       (1 << DX_AXIM_CFG_INFLTMASK_BIT_SHIFT) | (1 << DX_AXIM_CFG_COMPMASK_BIT_SHIFT))
-
-#define SSI_AXI_ERR_IRQ_MASK BIT(DX_HOST_IRR_AXI_ERR_INT_BIT_SHIFT)
-
-#define SSI_COMP_IRQ_MASK BIT(DX_HOST_IRR_AXIM_COMP_INT_BIT_SHIFT)
-
-#define AXIM_MON_COMP_VALUE GENMASK(DX_AXIM_MON_COMP_VALUE_BIT_SIZE + \
-                                   DX_AXIM_MON_COMP_VALUE_BIT_SHIFT, \
-                                   DX_AXIM_MON_COMP_VALUE_BIT_SHIFT)
-
-/* Register name mangling macro */
-#define CC_REG(reg_name) DX_ ## reg_name ## _REG_OFFSET
-
-/* TEE FIPS status interrupt */
-#define SSI_GPR0_IRQ_MASK BIT(DX_HOST_IRR_GPR0_BIT_SHIFT)
-
-#define SSI_CRA_PRIO 3000
-
-#define MIN_HW_QUEUE_SIZE 50 /* Minimum size required for proper function */
-
-#define MAX_REQUEST_QUEUE_SIZE 4096
-#define MAX_MLLI_BUFF_SIZE 2080
-#define MAX_ICV_NENTS_SUPPORTED 2
-
-/* Definitions for HW descriptors DIN/DOUT fields */
-#define NS_BIT 1
-#define AXI_ID 0
-/* AXI_ID is not actually the AXI ID of the transaction but the value of AXI_ID
- * field in the HW descriptor. The DMA engine +8 that value.
- */
-
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-
-#define SSI_MAX_IVGEN_DMA_ADDRESSES    3
-struct ssi_crypto_req {
-       void (*user_cb)(struct device *dev, void *req, void __iomem *cc_base);
-       void *user_arg;
-       dma_addr_t ivgen_dma_addr[SSI_MAX_IVGEN_DMA_ADDRESSES];
-       /* For the first 'ivgen_dma_addr_len' addresses of this array,
-        * generated IV would be placed in it by send_request().
-        * Same generated IV for all addresses!
-        */
-       unsigned int ivgen_dma_addr_len; /* Amount of 'ivgen_dma_addr' elements to be filled. */
-       unsigned int ivgen_size; /* The generated IV size required, 8/16 B allowed. */
-       struct completion seq_compl; /* request completion */
-};
-
-/**
- * struct ssi_drvdata - driver private data context
- * @cc_base:   virt address of the CC registers
- * @irq:       device IRQ number
- * @irq_mask:  Interrupt mask shadow (1 for masked interrupts)
- * @fw_ver:    SeP loaded firmware version
- */
-struct ssi_drvdata {
-       void __iomem *cc_base;
-       int irq;
-       u32 irq_mask;
-       u32 fw_ver;
-       /* Calibration time of start/stop
-        * monitor descriptors
-        */
-       u32 monitor_null_cycles;
-       struct platform_device *plat_dev;
-       ssi_sram_addr_t mlli_sram_addr;
-       void *buff_mgr_handle;
-       void *hash_handle;
-       void *aead_handle;
-       void *blkcipher_handle;
-       void *request_mgr_handle;
-       void *fips_handle;
-       void *ivgen_handle;
-       void *sram_mgr_handle;
-       struct clk *clk;
-       bool coherent;
-};
-
-struct ssi_crypto_alg {
-       struct list_head entry;
-       int cipher_mode;
-       int flow_mode; /* Note: currently, refers to the cipher mode only. */
-       int auth_mode;
-       struct ssi_drvdata *drvdata;
-       struct crypto_alg crypto_alg;
-       struct aead_alg aead_alg;
-};
-
-struct ssi_alg_template {
-       char name[CRYPTO_MAX_ALG_NAME];
-       char driver_name[CRYPTO_MAX_ALG_NAME];
-       unsigned int blocksize;
-       u32 type;
-       union {
-               struct ablkcipher_alg ablkcipher;
-               struct aead_alg aead;
-               struct blkcipher_alg blkcipher;
-               struct cipher_alg cipher;
-               struct compress_alg compress;
-       } template_u;
-       int cipher_mode;
-       int flow_mode; /* Note: currently, refers to the cipher mode only. */
-       int auth_mode;
-       struct ssi_drvdata *drvdata;
-};
-
-struct async_gen_req_ctx {
-       dma_addr_t iv_dma_addr;
-       enum drv_crypto_direction op_type;
-};
-
-static inline struct device *drvdata_to_dev(struct ssi_drvdata *drvdata)
-{
-       return &drvdata->plat_dev->dev;
-}
-
-#ifdef DX_DUMP_BYTES
-void dump_byte_array(const char *name, const u8 *the_array, unsigned long size);
-#else
-static inline void dump_byte_array(const char *name, const u8 *the_array,
-                                  unsigned long size) {};
-#endif
-
-int init_cc_regs(struct ssi_drvdata *drvdata, bool is_probe);
-void fini_cc_regs(struct ssi_drvdata *drvdata);
-int cc_clk_on(struct ssi_drvdata *drvdata);
-void cc_clk_off(struct ssi_drvdata *drvdata);
-
-static inline void cc_iowrite(struct ssi_drvdata *drvdata, u32 reg, u32 val)
-{
-       iowrite32(val, (drvdata->cc_base + reg));
-}
-
-static inline u32 cc_ioread(struct ssi_drvdata *drvdata, u32 reg)
-{
-       return ioread32(drvdata->cc_base + reg);
-}
-
-#endif /*__SSI_DRIVER_H__*/
-
diff --git a/drivers/staging/ccree/ssi_fips.c b/drivers/staging/ccree/ssi_fips.c
deleted file mode 100644 (file)
index 4aea99f..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/fips.h>
-
-#include "ssi_config.h"
-#include "ssi_driver.h"
-#include "ssi_fips.h"
-
-static void fips_dsr(unsigned long devarg);
-
-struct ssi_fips_handle {
-       struct tasklet_struct tasklet;
-};
-
-/* The function called once at driver entry point to check
- * whether TEE FIPS error occurred.
- */
-static bool cc_get_tee_fips_status(struct ssi_drvdata *drvdata)
-{
-       u32 reg;
-
-       reg = cc_ioread(drvdata, CC_REG(GPR_HOST));
-       return (reg == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK));
-}
-
-/*
- * This function should push the FIPS REE library status towards the TEE library
- * by writing the error state to HOST_GPR0 register.
- */
-void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, bool status)
-{
-       int val = CC_FIPS_SYNC_REE_STATUS;
-
-       val |= (status ? CC_FIPS_SYNC_MODULE_OK : CC_FIPS_SYNC_MODULE_ERROR);
-
-       cc_iowrite(drvdata, CC_REG(HOST_GPR0), val);
-}
-
-void ssi_fips_fini(struct ssi_drvdata *drvdata)
-{
-       struct ssi_fips_handle *fips_h = drvdata->fips_handle;
-
-       if (!fips_h)
-               return; /* Not allocated */
-
-       /* Kill tasklet */
-       tasklet_kill(&fips_h->tasklet);
-
-       kfree(fips_h);
-       drvdata->fips_handle = NULL;
-}
-
-void fips_handler(struct ssi_drvdata *drvdata)
-{
-       struct ssi_fips_handle *fips_handle_ptr =
-               drvdata->fips_handle;
-
-       tasklet_schedule(&fips_handle_ptr->tasklet);
-}
-
-static inline void tee_fips_error(struct device *dev)
-{
-       if (fips_enabled)
-               panic("ccree: TEE reported cryptographic error in fips mode!\n");
-       else
-               dev_err(dev, "TEE reported error!\n");
-}
-
-/* Deferred service handler, run as interrupt-fired tasklet */
-static void fips_dsr(unsigned long devarg)
-{
-       struct ssi_drvdata *drvdata = (struct ssi_drvdata *)devarg;
-       struct device *dev = drvdata_to_dev(drvdata);
-       u32 irq, state, val;
-
-       irq = (drvdata->irq & (SSI_GPR0_IRQ_MASK));
-
-       if (irq) {
-               state = cc_ioread(drvdata, CC_REG(GPR_HOST));
-
-               if (state != (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK))
-                       tee_fips_error(dev);
-       }
-
-       /* after verifing that there is nothing to do,
-        * unmask AXI completion interrupt.
-        */
-       val = (CC_REG(HOST_IMR) & ~irq);
-       cc_iowrite(drvdata, CC_REG(HOST_IMR), val);
-}
-
-/* The function called once at driver entry point .*/
-int ssi_fips_init(struct ssi_drvdata *p_drvdata)
-{
-       struct ssi_fips_handle *fips_h;
-       struct device *dev = drvdata_to_dev(p_drvdata);
-
-       fips_h = kzalloc(sizeof(*fips_h), GFP_KERNEL);
-       if (!fips_h)
-               return -ENOMEM;
-
-       p_drvdata->fips_handle = fips_h;
-
-       dev_dbg(dev, "Initializing fips tasklet\n");
-       tasklet_init(&fips_h->tasklet, fips_dsr, (unsigned long)p_drvdata);
-
-       if (!cc_get_tee_fips_status(p_drvdata))
-               tee_fips_error(dev);
-
-       return 0;
-}
diff --git a/drivers/staging/ccree/ssi_fips.h b/drivers/staging/ccree/ssi_fips.h
deleted file mode 100644 (file)
index 63bcca7..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __SSI_FIPS_H__
-#define __SSI_FIPS_H__
-
-#ifdef CONFIG_CRYPTO_FIPS
-
-enum cc_fips_status {
-       CC_FIPS_SYNC_MODULE_OK = 0x0,
-       CC_FIPS_SYNC_MODULE_ERROR = 0x1,
-       CC_FIPS_SYNC_REE_STATUS = 0x4,
-       CC_FIPS_SYNC_TEE_STATUS = 0x8,
-       CC_FIPS_SYNC_STATUS_RESERVE32B = S32_MAX
-};
-
-int ssi_fips_init(struct ssi_drvdata *p_drvdata);
-void ssi_fips_fini(struct ssi_drvdata *drvdata);
-void fips_handler(struct ssi_drvdata *drvdata);
-void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, bool ok);
-
-#else  /* CONFIG_CRYPTO_FIPS */
-
-static inline int ssi_fips_init(struct ssi_drvdata *p_drvdata)
-{
-       return 0;
-}
-
-static inline void ssi_fips_fini(struct ssi_drvdata *drvdata) {}
-static inline void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, bool ok) {}
-static inline void fips_handler(struct ssi_drvdata *drvdata) {}
-
-#endif /* CONFIG_CRYPTO_FIPS */
-
-#endif  /*__SSI_FIPS_H__*/
-
diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c
deleted file mode 100644 (file)
index 2035835..0000000
+++ /dev/null
@@ -1,2549 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <crypto/algapi.h>
-#include <crypto/hash.h>
-#include <crypto/sha.h>
-#include <crypto/md5.h>
-#include <crypto/internal/hash.h>
-
-#include "ssi_config.h"
-#include "ssi_driver.h"
-#include "ssi_request_mgr.h"
-#include "ssi_buffer_mgr.h"
-#include "ssi_sysfs.h"
-#include "ssi_hash.h"
-#include "ssi_sram_mgr.h"
-
-#define SSI_MAX_AHASH_SEQ_LEN 12
-#define SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE MAX(SSI_MAX_HASH_BLCK_SIZE, 3 * AES_BLOCK_SIZE)
-
-struct ssi_hash_handle {
-       ssi_sram_addr_t digest_len_sram_addr; /* const value in SRAM*/
-       ssi_sram_addr_t larval_digest_sram_addr;   /* const value in SRAM */
-       struct list_head hash_list;
-       struct completion init_comp;
-};
-
-static const u32 digest_len_init[] = {
-       0x00000040, 0x00000000, 0x00000000, 0x00000000 };
-static const u32 md5_init[] = {
-       SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 };
-static const u32 sha1_init[] = {
-       SHA1_H4, SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 };
-static const u32 sha224_init[] = {
-       SHA224_H7, SHA224_H6, SHA224_H5, SHA224_H4,
-       SHA224_H3, SHA224_H2, SHA224_H1, SHA224_H0 };
-static const u32 sha256_init[] = {
-       SHA256_H7, SHA256_H6, SHA256_H5, SHA256_H4,
-       SHA256_H3, SHA256_H2, SHA256_H1, SHA256_H0 };
-#if (DX_DEV_SHA_MAX > 256)
-static const u32 digest_len_sha512_init[] = {
-       0x00000080, 0x00000000, 0x00000000, 0x00000000 };
-static const u64 sha384_init[] = {
-       SHA384_H7, SHA384_H6, SHA384_H5, SHA384_H4,
-       SHA384_H3, SHA384_H2, SHA384_H1, SHA384_H0 };
-static const u64 sha512_init[] = {
-       SHA512_H7, SHA512_H6, SHA512_H5, SHA512_H4,
-       SHA512_H3, SHA512_H2, SHA512_H1, SHA512_H0 };
-#endif
-
-static void ssi_hash_create_xcbc_setup(
-       struct ahash_request *areq,
-       struct cc_hw_desc desc[],
-       unsigned int *seq_size);
-
-static void ssi_hash_create_cmac_setup(struct ahash_request *areq,
-                                      struct cc_hw_desc desc[],
-                                      unsigned int *seq_size);
-
-struct ssi_hash_alg {
-       struct list_head entry;
-       int hash_mode;
-       int hw_mode;
-       int inter_digestsize;
-       struct ssi_drvdata *drvdata;
-       struct ahash_alg ahash_alg;
-};
-
-struct hash_key_req_ctx {
-       u32 keylen;
-       dma_addr_t key_dma_addr;
-};
-
-/* hash per-session context */
-struct ssi_hash_ctx {
-       struct ssi_drvdata *drvdata;
-       /* holds the origin digest; the digest after "setkey" if HMAC,*
-        * the initial digest if HASH.
-        */
-       u8 digest_buff[SSI_MAX_HASH_DIGEST_SIZE]  ____cacheline_aligned;
-       u8 opad_tmp_keys_buff[SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE]  ____cacheline_aligned;
-
-       dma_addr_t opad_tmp_keys_dma_addr  ____cacheline_aligned;
-       dma_addr_t digest_buff_dma_addr;
-       /* use for hmac with key large then mode block size */
-       struct hash_key_req_ctx key_params;
-       int hash_mode;
-       int hw_mode;
-       int inter_digestsize;
-       struct completion setkey_comp;
-       bool is_hmac;
-};
-
-static void ssi_hash_create_data_desc(
-       struct ahash_req_ctx *areq_ctx,
-       struct ssi_hash_ctx *ctx,
-       unsigned int flow_mode, struct cc_hw_desc desc[],
-       bool is_not_last_data,
-       unsigned int *seq_size);
-
-static inline void ssi_set_hash_endianity(u32 mode, struct cc_hw_desc *desc)
-{
-       if (unlikely((mode == DRV_HASH_MD5) ||
-                    (mode == DRV_HASH_SHA384) ||
-                    (mode == DRV_HASH_SHA512))) {
-               set_bytes_swap(desc, 1);
-       } else {
-               set_cipher_config0(desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN);
-       }
-}
-
-static int ssi_hash_map_result(struct device *dev,
-                              struct ahash_req_ctx *state,
-                              unsigned int digestsize)
-{
-       state->digest_result_dma_addr =
-               dma_map_single(dev, (void *)state->digest_result_buff,
-                              digestsize,
-                              DMA_BIDIRECTIONAL);
-       if (unlikely(dma_mapping_error(dev, state->digest_result_dma_addr))) {
-               dev_err(dev, "Mapping digest result buffer %u B for DMA failed\n",
-                       digestsize);
-               return -ENOMEM;
-       }
-       dev_dbg(dev, "Mapped digest result buffer %u B at va=%pK to dma=%pad\n",
-               digestsize, state->digest_result_buff,
-               &state->digest_result_dma_addr);
-
-       return 0;
-}
-
-static int ssi_hash_map_request(struct device *dev,
-                               struct ahash_req_ctx *state,
-                               struct ssi_hash_ctx *ctx)
-{
-       bool is_hmac = ctx->is_hmac;
-       ssi_sram_addr_t larval_digest_addr = ssi_ahash_get_larval_digest_sram_addr(
-                                       ctx->drvdata, ctx->hash_mode);
-       struct ssi_crypto_req ssi_req = {};
-       struct cc_hw_desc desc;
-       int rc = -ENOMEM;
-
-       state->buff0 = kzalloc(SSI_MAX_HASH_BLCK_SIZE, GFP_KERNEL | GFP_DMA);
-       if (!state->buff0)
-               goto fail0;
-
-       state->buff1 = kzalloc(SSI_MAX_HASH_BLCK_SIZE, GFP_KERNEL | GFP_DMA);
-       if (!state->buff1)
-               goto fail_buff0;
-
-       state->digest_result_buff = kzalloc(SSI_MAX_HASH_DIGEST_SIZE, GFP_KERNEL | GFP_DMA);
-       if (!state->digest_result_buff)
-               goto fail_buff1;
-
-       state->digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL | GFP_DMA);
-       if (!state->digest_buff)
-               goto fail_digest_result_buff;
-
-       dev_dbg(dev, "Allocated digest-buffer in context ctx->digest_buff=@%p\n",
-               state->digest_buff);
-       if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) {
-               state->digest_bytes_len = kzalloc(HASH_LEN_SIZE, GFP_KERNEL | GFP_DMA);
-               if (!state->digest_bytes_len)
-                       goto fail1;
-
-               dev_dbg(dev, "Allocated digest-bytes-len in context state->>digest_bytes_len=@%p\n",
-                       state->digest_bytes_len);
-       } else {
-               state->digest_bytes_len = NULL;
-       }
-
-       state->opad_digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL | GFP_DMA);
-       if (!state->opad_digest_buff)
-               goto fail2;
-
-       dev_dbg(dev, "Allocated opad-digest-buffer in context state->digest_bytes_len=@%p\n",
-               state->opad_digest_buff);
-
-       state->digest_buff_dma_addr = dma_map_single(dev, (void *)state->digest_buff, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(dev, state->digest_buff_dma_addr)) {
-               dev_err(dev, "Mapping digest len %d B at va=%pK for DMA failed\n",
-                       ctx->inter_digestsize, state->digest_buff);
-               goto fail3;
-       }
-       dev_dbg(dev, "Mapped digest %d B at va=%pK to dma=%pad\n",
-               ctx->inter_digestsize, state->digest_buff,
-               &state->digest_buff_dma_addr);
-
-       if (is_hmac) {
-               dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-               if ((ctx->hw_mode == DRV_CIPHER_XCBC_MAC) || (ctx->hw_mode == DRV_CIPHER_CMAC)) {
-                       memset(state->digest_buff, 0, ctx->inter_digestsize);
-               } else { /*sha*/
-                       memcpy(state->digest_buff, ctx->digest_buff, ctx->inter_digestsize);
-#if (DX_DEV_SHA_MAX > 256)
-                       if (unlikely((ctx->hash_mode == DRV_HASH_SHA512) || (ctx->hash_mode == DRV_HASH_SHA384)))
-                               memcpy(state->digest_bytes_len, digest_len_sha512_init, HASH_LEN_SIZE);
-                       else
-                               memcpy(state->digest_bytes_len, digest_len_init, HASH_LEN_SIZE);
-#else
-                       memcpy(state->digest_bytes_len, digest_len_init, HASH_LEN_SIZE);
-#endif
-               }
-               dma_sync_single_for_device(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-
-               if (ctx->hash_mode != DRV_HASH_NULL) {
-                       dma_sync_single_for_cpu(dev, ctx->opad_tmp_keys_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-                       memcpy(state->opad_digest_buff, ctx->opad_tmp_keys_buff, ctx->inter_digestsize);
-               }
-       } else { /*hash*/
-               /* Copy the initial digests if hash flow. The SRAM contains the
-                * initial digests in the expected order for all SHA*
-                */
-               hw_desc_init(&desc);
-               set_din_sram(&desc, larval_digest_addr, ctx->inter_digestsize);
-               set_dout_dlli(&desc, state->digest_buff_dma_addr,
-                             ctx->inter_digestsize, NS_BIT, 0);
-               set_flow_mode(&desc, BYPASS);
-
-               rc = send_request(ctx->drvdata, &ssi_req, &desc, 1, 0);
-               if (unlikely(rc != 0)) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       goto fail4;
-               }
-       }
-
-       if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) {
-               state->digest_bytes_len_dma_addr = dma_map_single(dev, (void *)state->digest_bytes_len, HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
-               if (dma_mapping_error(dev, state->digest_bytes_len_dma_addr)) {
-                       dev_err(dev, "Mapping digest len %u B at va=%pK for DMA failed\n",
-                               HASH_LEN_SIZE, state->digest_bytes_len);
-                       goto fail4;
-               }
-               dev_dbg(dev, "Mapped digest len %u B at va=%pK to dma=%pad\n",
-                       HASH_LEN_SIZE, state->digest_bytes_len,
-                       &state->digest_bytes_len_dma_addr);
-       } else {
-               state->digest_bytes_len_dma_addr = 0;
-       }
-
-       if (is_hmac && ctx->hash_mode != DRV_HASH_NULL) {
-               state->opad_digest_dma_addr = dma_map_single(dev, (void *)state->opad_digest_buff, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-               if (dma_mapping_error(dev, state->opad_digest_dma_addr)) {
-                       dev_err(dev, "Mapping opad digest %d B at va=%pK for DMA failed\n",
-                               ctx->inter_digestsize,
-                               state->opad_digest_buff);
-                       goto fail5;
-               }
-               dev_dbg(dev, "Mapped opad digest %d B at va=%pK to dma=%pad\n",
-                       ctx->inter_digestsize, state->opad_digest_buff,
-                       &state->opad_digest_dma_addr);
-       } else {
-               state->opad_digest_dma_addr = 0;
-       }
-       state->buff0_cnt = 0;
-       state->buff1_cnt = 0;
-       state->buff_index = 0;
-       state->mlli_params.curr_pool = NULL;
-
-       return 0;
-
-fail5:
-       if (state->digest_bytes_len_dma_addr != 0) {
-               dma_unmap_single(dev, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
-               state->digest_bytes_len_dma_addr = 0;
-       }
-fail4:
-       if (state->digest_buff_dma_addr != 0) {
-               dma_unmap_single(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-               state->digest_buff_dma_addr = 0;
-       }
-fail3:
-       kfree(state->opad_digest_buff);
-fail2:
-       kfree(state->digest_bytes_len);
-fail1:
-        kfree(state->digest_buff);
-fail_digest_result_buff:
-       kfree(state->digest_result_buff);
-       state->digest_result_buff = NULL;
-fail_buff1:
-       kfree(state->buff1);
-       state->buff1 = NULL;
-fail_buff0:
-       kfree(state->buff0);
-       state->buff0 = NULL;
-fail0:
-       return rc;
-}
-
-static void ssi_hash_unmap_request(struct device *dev,
-                                  struct ahash_req_ctx *state,
-                                  struct ssi_hash_ctx *ctx)
-{
-       if (state->digest_buff_dma_addr != 0) {
-               dma_unmap_single(dev, state->digest_buff_dma_addr,
-                                ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-               dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n",
-                       &state->digest_buff_dma_addr);
-               state->digest_buff_dma_addr = 0;
-       }
-       if (state->digest_bytes_len_dma_addr != 0) {
-               dma_unmap_single(dev, state->digest_bytes_len_dma_addr,
-                                HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
-               dev_dbg(dev, "Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=%pad\n",
-                       &state->digest_bytes_len_dma_addr);
-               state->digest_bytes_len_dma_addr = 0;
-       }
-       if (state->opad_digest_dma_addr != 0) {
-               dma_unmap_single(dev, state->opad_digest_dma_addr,
-                                ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-               dev_dbg(dev, "Unmapped opad-digest: opad_digest_dma_addr=%pad\n",
-                       &state->opad_digest_dma_addr);
-               state->opad_digest_dma_addr = 0;
-       }
-
-       kfree(state->opad_digest_buff);
-       kfree(state->digest_bytes_len);
-       kfree(state->digest_buff);
-       kfree(state->digest_result_buff);
-       kfree(state->buff1);
-       kfree(state->buff0);
-}
-
-static void ssi_hash_unmap_result(struct device *dev,
-                                 struct ahash_req_ctx *state,
-                                 unsigned int digestsize, u8 *result)
-{
-       if (state->digest_result_dma_addr != 0) {
-               dma_unmap_single(dev,
-                                state->digest_result_dma_addr,
-                                digestsize,
-                                 DMA_BIDIRECTIONAL);
-               dev_dbg(dev, "unmpa digest result buffer va (%pK) pa (%pad) len %u\n",
-                       state->digest_result_buff,
-                       &state->digest_result_dma_addr, digestsize);
-               memcpy(result,
-                      state->digest_result_buff,
-                      digestsize);
-       }
-       state->digest_result_dma_addr = 0;
-}
-
-static void ssi_hash_update_complete(struct device *dev, void *ssi_req, void __iomem *cc_base)
-{
-       struct ahash_request *req = (struct ahash_request *)ssi_req;
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-
-       dev_dbg(dev, "req=%pK\n", req);
-
-       ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false);
-       req->base.complete(&req->base, 0);
-}
-
-static void ssi_hash_digest_complete(struct device *dev, void *ssi_req, void __iomem *cc_base)
-{
-       struct ahash_request *req = (struct ahash_request *)ssi_req;
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       u32 digestsize = crypto_ahash_digestsize(tfm);
-
-       dev_dbg(dev, "req=%pK\n", req);
-
-       ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false);
-       ssi_hash_unmap_result(dev, state, digestsize, req->result);
-       ssi_hash_unmap_request(dev, state, ctx);
-       req->base.complete(&req->base, 0);
-}
-
-static void ssi_hash_complete(struct device *dev, void *ssi_req, void __iomem *cc_base)
-{
-       struct ahash_request *req = (struct ahash_request *)ssi_req;
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       u32 digestsize = crypto_ahash_digestsize(tfm);
-
-       dev_dbg(dev, "req=%pK\n", req);
-
-       ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false);
-       ssi_hash_unmap_result(dev, state, digestsize, req->result);
-       ssi_hash_unmap_request(dev, state, ctx);
-       req->base.complete(&req->base, 0);
-}
-
-static int ssi_hash_digest(struct ahash_req_ctx *state,
-                          struct ssi_hash_ctx *ctx,
-                          unsigned int digestsize,
-                          struct scatterlist *src,
-                          unsigned int nbytes, u8 *result,
-                          void *async_req)
-{
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       bool is_hmac = ctx->is_hmac;
-       struct ssi_crypto_req ssi_req = {};
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-       ssi_sram_addr_t larval_digest_addr = ssi_ahash_get_larval_digest_sram_addr(
-                                       ctx->drvdata, ctx->hash_mode);
-       int idx = 0;
-       int rc = 0;
-
-       dev_dbg(dev, "===== %s-digest (%d) ====\n", is_hmac ? "hmac" : "hash",
-               nbytes);
-
-       if (unlikely(ssi_hash_map_request(dev, state, ctx) != 0)) {
-               dev_err(dev, "map_ahash_source() failed\n");
-               return -ENOMEM;
-       }
-
-       if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) {
-               dev_err(dev, "map_ahash_digest() failed\n");
-               return -ENOMEM;
-       }
-
-       if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1) != 0)) {
-               dev_err(dev, "map_ahash_request_final() failed\n");
-               return -ENOMEM;
-       }
-
-       if (async_req) {
-               /* Setup DX request structure */
-               ssi_req.user_cb = (void *)ssi_hash_digest_complete;
-               ssi_req.user_arg = (void *)async_req;
-       }
-
-       /* If HMAC then load hash IPAD xor key, if HASH then load initial digest */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       if (is_hmac) {
-               set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                            ctx->inter_digestsize, NS_BIT);
-       } else {
-               set_din_sram(&desc[idx], larval_digest_addr,
-                            ctx->inter_digestsize);
-       }
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       idx++;
-
-       /* Load the hash current length */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-
-       if (is_hmac) {
-               set_din_type(&desc[idx], DMA_DLLI,
-                            state->digest_bytes_len_dma_addr, HASH_LEN_SIZE,
-                            NS_BIT);
-       } else {
-               set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
-               if (likely(nbytes != 0))
-                       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-               else
-                       set_cipher_do(&desc[idx], DO_PAD);
-       }
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       idx++;
-
-       ssi_hash_create_data_desc(state, ctx, DIN_HASH, desc, false, &idx);
-
-       if (is_hmac) {
-               /* HW last hash block padding (aka. "DO_PAD") */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
-                             HASH_LEN_SIZE, NS_BIT, 0);
-               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-               set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
-               set_cipher_do(&desc[idx], DO_PAD);
-               idx++;
-
-               /* store the hash digest result in the context */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
-                             digestsize, NS_BIT, 0);
-               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-               ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
-               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-               idx++;
-
-               /* Loading hash opad xor key state */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr,
-                            ctx->inter_digestsize, NS_BIT);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-               idx++;
-
-               /* Load the hash current length */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_din_sram(&desc[idx],
-                            ssi_ahash_get_initial_digest_len_sram_addr(
-ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE);
-               set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-               idx++;
-
-               /* Memory Barrier: wait for IPAD/OPAD axi write to complete */
-               hw_desc_init(&desc[idx]);
-               set_din_no_dma(&desc[idx], 0, 0xfffff0);
-               set_dout_no_dma(&desc[idx], 0, 0, 1);
-               idx++;
-
-               /* Perform HASH update */
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                            digestsize, NS_BIT);
-               set_flow_mode(&desc[idx], DIN_HASH);
-               idx++;
-       }
-
-       /* Get final MAC result */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       /* TODO */
-       set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize,
-                     NS_BIT, (async_req ? 1 : 0));
-       if (async_req)
-               set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
-       ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
-       idx++;
-
-       if (async_req) {
-               rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
-               if (unlikely(rc != -EINPROGRESS)) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, true);
-                       ssi_hash_unmap_result(dev, state, digestsize, result);
-                       ssi_hash_unmap_request(dev, state, ctx);
-               }
-       } else {
-               rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
-               if (rc != 0) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, true);
-               } else {
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, false);
-               }
-               ssi_hash_unmap_result(dev, state, digestsize, result);
-               ssi_hash_unmap_request(dev, state, ctx);
-       }
-       return rc;
-}
-
-static int ssi_hash_update(struct ahash_req_ctx *state,
-                          struct ssi_hash_ctx *ctx,
-                          unsigned int block_size,
-                          struct scatterlist *src,
-                          unsigned int nbytes,
-                          void *async_req)
-{
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct ssi_crypto_req ssi_req = {};
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-       u32 idx = 0;
-       int rc;
-
-       dev_dbg(dev, "===== %s-update (%d) ====\n", ctx->is_hmac ?
-               "hmac" : "hash", nbytes);
-
-       if (nbytes == 0) {
-               /* no real updates required */
-               return 0;
-       }
-
-       rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, src, nbytes, block_size);
-       if (unlikely(rc)) {
-               if (rc == 1) {
-                       dev_dbg(dev, " data size not require HW update %x\n",
-                               nbytes);
-                       /* No hardware updates are required */
-                       return 0;
-               }
-               dev_err(dev, "map_ahash_request_update() failed\n");
-               return -ENOMEM;
-       }
-
-       if (async_req) {
-               /* Setup DX request structure */
-               ssi_req.user_cb = (void *)ssi_hash_update_complete;
-               ssi_req.user_arg = async_req;
-       }
-
-       /* Restore hash digest */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                    ctx->inter_digestsize, NS_BIT);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       idx++;
-       /* Restore hash current length */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr,
-                    HASH_LEN_SIZE, NS_BIT);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       idx++;
-
-       ssi_hash_create_data_desc(state, ctx, DIN_HASH, desc, false, &idx);
-
-       /* store the hash digest result in context */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
-                     ctx->inter_digestsize, NS_BIT, 0);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       idx++;
-
-       /* store current hash length in context */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr,
-                     HASH_LEN_SIZE, NS_BIT, (async_req ? 1 : 0));
-       if (async_req)
-               set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
-       idx++;
-
-       if (async_req) {
-               rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
-               if (unlikely(rc != -EINPROGRESS)) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, true);
-               }
-       } else {
-               rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
-               if (rc != 0) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, true);
-               } else {
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, false);
-               }
-       }
-       return rc;
-}
-
-static int ssi_hash_finup(struct ahash_req_ctx *state,
-                         struct ssi_hash_ctx *ctx,
-                         unsigned int digestsize,
-                         struct scatterlist *src,
-                         unsigned int nbytes,
-                         u8 *result,
-                         void *async_req)
-{
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       bool is_hmac = ctx->is_hmac;
-       struct ssi_crypto_req ssi_req = {};
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-       int idx = 0;
-       int rc;
-
-       dev_dbg(dev, "===== %s-finup (%d) ====\n", is_hmac ? "hmac" : "hash",
-               nbytes);
-
-       if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1) != 0)) {
-               dev_err(dev, "map_ahash_request_final() failed\n");
-               return -ENOMEM;
-       }
-       if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) {
-               dev_err(dev, "map_ahash_digest() failed\n");
-               return -ENOMEM;
-       }
-
-       if (async_req) {
-               /* Setup DX request structure */
-               ssi_req.user_cb = (void *)ssi_hash_complete;
-               ssi_req.user_arg = async_req;
-       }
-
-       /* Restore hash digest */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                    ctx->inter_digestsize, NS_BIT);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       idx++;
-
-       /* Restore hash current length */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-       set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr,
-                    HASH_LEN_SIZE, NS_BIT);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       idx++;
-
-       ssi_hash_create_data_desc(state, ctx, DIN_HASH, desc, false, &idx);
-
-       if (is_hmac) {
-               /* Store the hash digest result in the context */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
-                             digestsize, NS_BIT, 0);
-               ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
-               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-               idx++;
-
-               /* Loading hash OPAD xor key state */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr,
-                            ctx->inter_digestsize, NS_BIT);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-               idx++;
-
-               /* Load the hash current length */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_din_sram(&desc[idx],
-                            ssi_ahash_get_initial_digest_len_sram_addr(
-ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE);
-               set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-               idx++;
-
-               /* Memory Barrier: wait for IPAD/OPAD axi write to complete */
-               hw_desc_init(&desc[idx]);
-               set_din_no_dma(&desc[idx], 0, 0xfffff0);
-               set_dout_no_dma(&desc[idx], 0, 0, 1);
-               idx++;
-
-               /* Perform HASH update on last digest */
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                            digestsize, NS_BIT);
-               set_flow_mode(&desc[idx], DIN_HASH);
-               idx++;
-       }
-
-       /* Get final MAC result */
-       hw_desc_init(&desc[idx]);
-       /* TODO */
-       set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize,
-                     NS_BIT, (async_req ? 1 : 0));
-       if (async_req)
-               set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       idx++;
-
-       if (async_req) {
-               rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
-               if (unlikely(rc != -EINPROGRESS)) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, true);
-                       ssi_hash_unmap_result(dev, state, digestsize, result);
-               }
-       } else {
-               rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
-               if (rc != 0) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, true);
-                       ssi_hash_unmap_result(dev, state, digestsize, result);
-               } else {
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, false);
-                       ssi_hash_unmap_result(dev, state, digestsize, result);
-                       ssi_hash_unmap_request(dev, state, ctx);
-               }
-       }
-       return rc;
-}
-
-static int ssi_hash_final(struct ahash_req_ctx *state,
-                         struct ssi_hash_ctx *ctx,
-                         unsigned int digestsize,
-                         struct scatterlist *src,
-                         unsigned int nbytes,
-                         u8 *result,
-                         void *async_req)
-{
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       bool is_hmac = ctx->is_hmac;
-       struct ssi_crypto_req ssi_req = {};
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-       int idx = 0;
-       int rc;
-
-       dev_dbg(dev, "===== %s-final (%d) ====\n", is_hmac ? "hmac" : "hash",
-               nbytes);
-
-       if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 0) != 0)) {
-               dev_err(dev, "map_ahash_request_final() failed\n");
-               return -ENOMEM;
-       }
-
-       if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) {
-               dev_err(dev, "map_ahash_digest() failed\n");
-               return -ENOMEM;
-       }
-
-       if (async_req) {
-               /* Setup DX request structure */
-               ssi_req.user_cb = (void *)ssi_hash_complete;
-               ssi_req.user_arg = async_req;
-       }
-
-       /* Restore hash digest */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                    ctx->inter_digestsize, NS_BIT);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       idx++;
-
-       /* Restore hash current length */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
-       set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr,
-                    HASH_LEN_SIZE, NS_BIT);
-       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       idx++;
-
-       ssi_hash_create_data_desc(state, ctx, DIN_HASH, desc, false, &idx);
-
-       /* "DO-PAD" must be enabled only when writing current length to HW */
-       hw_desc_init(&desc[idx]);
-       set_cipher_do(&desc[idx], DO_PAD);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr,
-                     HASH_LEN_SIZE, NS_BIT, 0);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       idx++;
-
-       if (is_hmac) {
-               /* Store the hash digest result in the context */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
-                             digestsize, NS_BIT, 0);
-               ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
-               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-               idx++;
-
-               /* Loading hash OPAD xor key state */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr,
-                            ctx->inter_digestsize, NS_BIT);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-               idx++;
-
-               /* Load the hash current length */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_din_sram(&desc[idx],
-                            ssi_ahash_get_initial_digest_len_sram_addr(
-ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE);
-               set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-               idx++;
-
-               /* Memory Barrier: wait for IPAD/OPAD axi write to complete */
-               hw_desc_init(&desc[idx]);
-               set_din_no_dma(&desc[idx], 0, 0xfffff0);
-               set_dout_no_dma(&desc[idx], 0, 0, 1);
-               idx++;
-
-               /* Perform HASH update on last digest */
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                            digestsize, NS_BIT);
-               set_flow_mode(&desc[idx], DIN_HASH);
-               idx++;
-       }
-
-       /* Get final MAC result */
-       hw_desc_init(&desc[idx]);
-       set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize,
-                     NS_BIT, (async_req ? 1 : 0));
-       if (async_req)
-               set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       idx++;
-
-       if (async_req) {
-               rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
-               if (unlikely(rc != -EINPROGRESS)) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, true);
-                       ssi_hash_unmap_result(dev, state, digestsize, result);
-               }
-       } else {
-               rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
-               if (rc != 0) {
-                       dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, true);
-                       ssi_hash_unmap_result(dev, state, digestsize, result);
-               } else {
-                       ssi_buffer_mgr_unmap_hash_request(dev, state, src, false);
-                       ssi_hash_unmap_result(dev, state, digestsize, result);
-                       ssi_hash_unmap_request(dev, state, ctx);
-               }
-       }
-       return rc;
-}
-
-static int ssi_hash_init(struct ahash_req_ctx *state, struct ssi_hash_ctx *ctx)
-{
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       state->xcbc_count = 0;
-
-       ssi_hash_map_request(dev, state, ctx);
-
-       return 0;
-}
-
-static int ssi_hash_setkey(void *hash,
-                          const u8 *key,
-                          unsigned int keylen,
-                          bool synchronize)
-{
-       unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST };
-       struct ssi_crypto_req ssi_req = {};
-       struct ssi_hash_ctx *ctx = NULL;
-       int blocksize = 0;
-       int digestsize = 0;
-       int i, idx = 0, rc = 0;
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-       ssi_sram_addr_t larval_addr;
-       struct device *dev;
-
-       ctx = crypto_ahash_ctx(((struct crypto_ahash *)hash));
-       dev = drvdata_to_dev(ctx->drvdata);
-       dev_dbg(dev, "start keylen: %d", keylen);
-
-       blocksize = crypto_tfm_alg_blocksize(&((struct crypto_ahash *)hash)->base);
-       digestsize = crypto_ahash_digestsize(((struct crypto_ahash *)hash));
-
-       larval_addr = ssi_ahash_get_larval_digest_sram_addr(
-                                       ctx->drvdata, ctx->hash_mode);
-
-       /* The keylen value distinguishes HASH in case keylen is ZERO bytes,
-        * any NON-ZERO value utilizes HMAC flow
-        */
-       ctx->key_params.keylen = keylen;
-       ctx->key_params.key_dma_addr = 0;
-       ctx->is_hmac = true;
-
-       if (keylen != 0) {
-               ctx->key_params.key_dma_addr = dma_map_single(
-                                               dev, (void *)key,
-                                               keylen, DMA_TO_DEVICE);
-               if (unlikely(dma_mapping_error(dev,
-                                              ctx->key_params.key_dma_addr))) {
-                       dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
-                               key, keylen);
-                       return -ENOMEM;
-               }
-               dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n",
-                       &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
-
-               if (keylen > blocksize) {
-                       /* Load hash initial state */
-                       hw_desc_init(&desc[idx]);
-                       set_cipher_mode(&desc[idx], ctx->hw_mode);
-                       set_din_sram(&desc[idx], larval_addr,
-                                    ctx->inter_digestsize);
-                       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-                       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-                       idx++;
-
-                       /* Load the hash current length*/
-                       hw_desc_init(&desc[idx]);
-                       set_cipher_mode(&desc[idx], ctx->hw_mode);
-                       set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
-                       set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
-                       set_flow_mode(&desc[idx], S_DIN_to_HASH);
-                       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-                       idx++;
-
-                       hw_desc_init(&desc[idx]);
-                       set_din_type(&desc[idx], DMA_DLLI,
-                                    ctx->key_params.key_dma_addr, keylen,
-                                    NS_BIT);
-                       set_flow_mode(&desc[idx], DIN_HASH);
-                       idx++;
-
-                       /* Get hashed key */
-                       hw_desc_init(&desc[idx]);
-                       set_cipher_mode(&desc[idx], ctx->hw_mode);
-                       set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
-                                     digestsize, NS_BIT, 0);
-                       set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-                       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-                       set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
-                       ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
-                       idx++;
-
-                       hw_desc_init(&desc[idx]);
-                       set_din_const(&desc[idx], 0, (blocksize - digestsize));
-                       set_flow_mode(&desc[idx], BYPASS);
-                       set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
-                                                  digestsize),
-                                     (blocksize - digestsize), NS_BIT, 0);
-                       idx++;
-               } else {
-                       hw_desc_init(&desc[idx]);
-                       set_din_type(&desc[idx], DMA_DLLI,
-                                    ctx->key_params.key_dma_addr, keylen,
-                                    NS_BIT);
-                       set_flow_mode(&desc[idx], BYPASS);
-                       set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
-                                     keylen, NS_BIT, 0);
-                       idx++;
-
-                       if ((blocksize - keylen) != 0) {
-                               hw_desc_init(&desc[idx]);
-                               set_din_const(&desc[idx], 0,
-                                             (blocksize - keylen));
-                               set_flow_mode(&desc[idx], BYPASS);
-                               set_dout_dlli(&desc[idx],
-                                             (ctx->opad_tmp_keys_dma_addr +
-                                              keylen), (blocksize - keylen),
-                                             NS_BIT, 0);
-                               idx++;
-                       }
-               }
-       } else {
-               hw_desc_init(&desc[idx]);
-               set_din_const(&desc[idx], 0, blocksize);
-               set_flow_mode(&desc[idx], BYPASS);
-               set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr),
-                             blocksize, NS_BIT, 0);
-               idx++;
-       }
-
-       rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-               goto out;
-       }
-
-       /* calc derived HMAC key */
-       for (idx = 0, i = 0; i < 2; i++) {
-               /* Load hash initial state */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_din_sram(&desc[idx], larval_addr, ctx->inter_digestsize);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-               idx++;
-
-               /* Load the hash current length*/
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-               idx++;
-
-               /* Prepare ipad key */
-               hw_desc_init(&desc[idx]);
-               set_xor_val(&desc[idx], hmac_pad_const[i]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_flow_mode(&desc[idx], S_DIN_to_HASH);
-               set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
-               idx++;
-
-               /* Perform HASH update */
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr,
-                            blocksize, NS_BIT);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_xor_active(&desc[idx]);
-               set_flow_mode(&desc[idx], DIN_HASH);
-               idx++;
-
-               /* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest of the first HASH "update" state) */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               if (i > 0) /* Not first iteration */
-                       set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
-                                     ctx->inter_digestsize, NS_BIT, 0);
-               else /* First iteration */
-                       set_dout_dlli(&desc[idx], ctx->digest_buff_dma_addr,
-                                     ctx->inter_digestsize, NS_BIT, 0);
-               set_flow_mode(&desc[idx], S_HASH_to_DOUT);
-               set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-               idx++;
-       }
-
-       rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
-
-out:
-       if (rc)
-               crypto_ahash_set_flags((struct crypto_ahash *)hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
-
-       if (ctx->key_params.key_dma_addr) {
-               dma_unmap_single(dev, ctx->key_params.key_dma_addr,
-                                ctx->key_params.keylen, DMA_TO_DEVICE);
-               dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n",
-                       &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
-       }
-       return rc;
-}
-
-static int ssi_xcbc_setkey(struct crypto_ahash *ahash,
-                          const u8 *key, unsigned int keylen)
-{
-       struct ssi_crypto_req ssi_req = {};
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(ahash);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       int idx = 0, rc = 0;
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-
-       dev_dbg(dev, "===== setkey (%d) ====\n", keylen);
-
-       switch (keylen) {
-       case AES_KEYSIZE_128:
-       case AES_KEYSIZE_192:
-       case AES_KEYSIZE_256:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       ctx->key_params.keylen = keylen;
-
-       ctx->key_params.key_dma_addr = dma_map_single(
-                                       dev, (void *)key,
-                                       keylen, DMA_TO_DEVICE);
-       if (unlikely(dma_mapping_error(dev, ctx->key_params.key_dma_addr))) {
-               dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
-                       key, keylen);
-               return -ENOMEM;
-       }
-       dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n",
-               &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
-
-       ctx->is_hmac = true;
-       /* 1. Load the AES key */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, ctx->key_params.key_dma_addr,
-                    keylen, NS_BIT);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
-       set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
-       set_key_size_aes(&desc[idx], keylen);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       idx++;
-
-       hw_desc_init(&desc[idx]);
-       set_din_const(&desc[idx], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], DIN_AES_DOUT);
-       set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
-                                          XCBC_MAC_K1_OFFSET),
-                             CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
-       idx++;
-
-       hw_desc_init(&desc[idx]);
-       set_din_const(&desc[idx], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], DIN_AES_DOUT);
-       set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
-                                          XCBC_MAC_K2_OFFSET),
-                             CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
-       idx++;
-
-       hw_desc_init(&desc[idx]);
-       set_din_const(&desc[idx], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], DIN_AES_DOUT);
-       set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
-                                          XCBC_MAC_K3_OFFSET),
-                              CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
-       idx++;
-
-       rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
-
-       if (rc != 0)
-               crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN);
-
-       dma_unmap_single(dev, ctx->key_params.key_dma_addr,
-                        ctx->key_params.keylen, DMA_TO_DEVICE);
-       dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n",
-               &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
-
-       return rc;
-}
-
-#if SSI_CC_HAS_CMAC
-static int ssi_cmac_setkey(struct crypto_ahash *ahash,
-                          const u8 *key, unsigned int keylen)
-{
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(ahash);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "===== setkey (%d) ====\n", keylen);
-
-       ctx->is_hmac = true;
-
-       switch (keylen) {
-       case AES_KEYSIZE_128:
-       case AES_KEYSIZE_192:
-       case AES_KEYSIZE_256:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       ctx->key_params.keylen = keylen;
-
-       /* STAT_PHASE_1: Copy key to ctx */
-
-       dma_sync_single_for_cpu(dev, ctx->opad_tmp_keys_dma_addr,
-                               keylen, DMA_TO_DEVICE);
-
-       memcpy(ctx->opad_tmp_keys_buff, key, keylen);
-       if (keylen == 24)
-               memset(ctx->opad_tmp_keys_buff + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
-
-       dma_sync_single_for_device(dev, ctx->opad_tmp_keys_dma_addr,
-                                  keylen, DMA_TO_DEVICE);
-
-       ctx->key_params.keylen = keylen;
-
-       return 0;
-}
-#endif
-
-static void ssi_hash_free_ctx(struct ssi_hash_ctx *ctx)
-{
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       if (ctx->digest_buff_dma_addr != 0) {
-               dma_unmap_single(dev, ctx->digest_buff_dma_addr,
-                                sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL);
-               dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n",
-                       &ctx->digest_buff_dma_addr);
-               ctx->digest_buff_dma_addr = 0;
-       }
-       if (ctx->opad_tmp_keys_dma_addr != 0) {
-               dma_unmap_single(dev, ctx->opad_tmp_keys_dma_addr,
-                                sizeof(ctx->opad_tmp_keys_buff),
-                                DMA_BIDIRECTIONAL);
-               dev_dbg(dev, "Unmapped opad-digest: opad_tmp_keys_dma_addr=%pad\n",
-                       &ctx->opad_tmp_keys_dma_addr);
-               ctx->opad_tmp_keys_dma_addr = 0;
-       }
-
-       ctx->key_params.keylen = 0;
-}
-
-static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx)
-{
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       ctx->key_params.keylen = 0;
-
-       ctx->digest_buff_dma_addr = dma_map_single(dev, (void *)ctx->digest_buff, sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(dev, ctx->digest_buff_dma_addr)) {
-               dev_err(dev, "Mapping digest len %zu B at va=%pK for DMA failed\n",
-                       sizeof(ctx->digest_buff), ctx->digest_buff);
-               goto fail;
-       }
-       dev_dbg(dev, "Mapped digest %zu B at va=%pK to dma=%pad\n",
-               sizeof(ctx->digest_buff), ctx->digest_buff,
-               &ctx->digest_buff_dma_addr);
-
-       ctx->opad_tmp_keys_dma_addr = dma_map_single(dev, (void *)ctx->opad_tmp_keys_buff, sizeof(ctx->opad_tmp_keys_buff), DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(dev, ctx->opad_tmp_keys_dma_addr)) {
-               dev_err(dev, "Mapping opad digest %zu B at va=%pK for DMA failed\n",
-                       sizeof(ctx->opad_tmp_keys_buff),
-                       ctx->opad_tmp_keys_buff);
-               goto fail;
-       }
-       dev_dbg(dev, "Mapped opad_tmp_keys %zu B at va=%pK to dma=%pad\n",
-               sizeof(ctx->opad_tmp_keys_buff), ctx->opad_tmp_keys_buff,
-               &ctx->opad_tmp_keys_dma_addr);
-
-       ctx->is_hmac = false;
-       return 0;
-
-fail:
-       ssi_hash_free_ctx(ctx);
-       return -ENOMEM;
-}
-
-static int ssi_ahash_cra_init(struct crypto_tfm *tfm)
-{
-       struct ssi_hash_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct hash_alg_common *hash_alg_common =
-               container_of(tfm->__crt_alg, struct hash_alg_common, base);
-       struct ahash_alg *ahash_alg =
-               container_of(hash_alg_common, struct ahash_alg, halg);
-       struct ssi_hash_alg *ssi_alg =
-                       container_of(ahash_alg, struct ssi_hash_alg, ahash_alg);
-
-       crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
-                                sizeof(struct ahash_req_ctx));
-
-       ctx->hash_mode = ssi_alg->hash_mode;
-       ctx->hw_mode = ssi_alg->hw_mode;
-       ctx->inter_digestsize = ssi_alg->inter_digestsize;
-       ctx->drvdata = ssi_alg->drvdata;
-
-       return ssi_hash_alloc_ctx(ctx);
-}
-
-static void ssi_hash_cra_exit(struct crypto_tfm *tfm)
-{
-       struct ssi_hash_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "ssi_hash_cra_exit");
-       ssi_hash_free_ctx(ctx);
-}
-
-static int ssi_mac_update(struct ahash_request *req)
-{
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base);
-       struct ssi_crypto_req ssi_req = {};
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-       int rc;
-       u32 idx = 0;
-
-       if (req->nbytes == 0) {
-               /* no real updates required */
-               return 0;
-       }
-
-       state->xcbc_count++;
-
-       rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, req->src, req->nbytes, block_size);
-       if (unlikely(rc)) {
-               if (rc == 1) {
-                       dev_dbg(dev, " data size not require HW update %x\n",
-                               req->nbytes);
-                       /* No hardware updates are required */
-                       return 0;
-               }
-               dev_err(dev, "map_ahash_request_update() failed\n");
-               return -ENOMEM;
-       }
-
-       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC)
-               ssi_hash_create_xcbc_setup(req, desc, &idx);
-       else
-               ssi_hash_create_cmac_setup(req, desc, &idx);
-
-       ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, true, &idx);
-
-       /* store the hash digest result in context */
-       hw_desc_init(&desc[idx]);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
-                     ctx->inter_digestsize, NS_BIT, 1);
-       set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], S_AES_to_DOUT);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       idx++;
-
-       /* Setup DX request structure */
-       ssi_req.user_cb = (void *)ssi_hash_update_complete;
-       ssi_req.user_arg = (void *)req;
-
-       rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
-       if (unlikely(rc != -EINPROGRESS)) {
-               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-               ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true);
-       }
-       return rc;
-}
-
-static int ssi_mac_final(struct ahash_request *req)
-{
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct ssi_crypto_req ssi_req = {};
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-       int idx = 0;
-       int rc = 0;
-       u32 key_size, key_len;
-       u32 digestsize = crypto_ahash_digestsize(tfm);
-
-       u32 rem_cnt = state->buff_index ? state->buff1_cnt :
-                       state->buff0_cnt;
-
-       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
-               key_size = CC_AES_128_BIT_KEY_SIZE;
-               key_len  = CC_AES_128_BIT_KEY_SIZE;
-       } else {
-               key_size = (ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE :
-                       ctx->key_params.keylen;
-               key_len =  ctx->key_params.keylen;
-       }
-
-       dev_dbg(dev, "===== final  xcbc reminder (%d) ====\n", rem_cnt);
-
-       if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 0) != 0)) {
-               dev_err(dev, "map_ahash_request_final() failed\n");
-               return -ENOMEM;
-       }
-
-       if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) {
-               dev_err(dev, "map_ahash_digest() failed\n");
-               return -ENOMEM;
-       }
-
-       /* Setup DX request structure */
-       ssi_req.user_cb = (void *)ssi_hash_complete;
-       ssi_req.user_arg = (void *)req;
-
-       if (state->xcbc_count && (rem_cnt == 0)) {
-               /* Load key for ECB decryption */
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
-               set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_DECRYPT);
-               set_din_type(&desc[idx], DMA_DLLI,
-                            (ctx->opad_tmp_keys_dma_addr +
-                             XCBC_MAC_K1_OFFSET), key_size, NS_BIT);
-               set_key_size_aes(&desc[idx], key_len);
-               set_flow_mode(&desc[idx], S_DIN_to_AES);
-               set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-               idx++;
-
-               /* Initiate decryption of block state to previous block_state-XOR-M[n] */
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                            CC_AES_BLOCK_SIZE, NS_BIT);
-               set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
-                             CC_AES_BLOCK_SIZE, NS_BIT, 0);
-               set_flow_mode(&desc[idx], DIN_AES_DOUT);
-               idx++;
-
-               /* Memory Barrier: wait for axi write to complete */
-               hw_desc_init(&desc[idx]);
-               set_din_no_dma(&desc[idx], 0, 0xfffff0);
-               set_dout_no_dma(&desc[idx], 0, 0, 1);
-               idx++;
-       }
-
-       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC)
-               ssi_hash_create_xcbc_setup(req, desc, &idx);
-       else
-               ssi_hash_create_cmac_setup(req, desc, &idx);
-
-       if (state->xcbc_count == 0) {
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_key_size_aes(&desc[idx], key_len);
-               set_cmac_size0_mode(&desc[idx]);
-               set_flow_mode(&desc[idx], S_DIN_to_AES);
-               idx++;
-       } else if (rem_cnt > 0) {
-               ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
-       } else {
-               hw_desc_init(&desc[idx]);
-               set_din_const(&desc[idx], 0x00, CC_AES_BLOCK_SIZE);
-               set_flow_mode(&desc[idx], DIN_AES_DOUT);
-               idx++;
-       }
-
-       /* Get final MAC result */
-       hw_desc_init(&desc[idx]);
-       /* TODO */
-       set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
-                     digestsize, NS_BIT, 1);
-       set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], S_AES_to_DOUT);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       idx++;
-
-       rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
-       if (unlikely(rc != -EINPROGRESS)) {
-               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-               ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true);
-               ssi_hash_unmap_result(dev, state, digestsize, req->result);
-       }
-       return rc;
-}
-
-static int ssi_mac_finup(struct ahash_request *req)
-{
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct ssi_crypto_req ssi_req = {};
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-       int idx = 0;
-       int rc = 0;
-       u32 key_len = 0;
-       u32 digestsize = crypto_ahash_digestsize(tfm);
-
-       dev_dbg(dev, "===== finup xcbc(%d) ====\n", req->nbytes);
-       if (state->xcbc_count > 0 && req->nbytes == 0) {
-               dev_dbg(dev, "No data to update. Call to fdx_mac_final\n");
-               return ssi_mac_final(req);
-       }
-
-       if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 1) != 0)) {
-               dev_err(dev, "map_ahash_request_final() failed\n");
-               return -ENOMEM;
-       }
-       if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) {
-               dev_err(dev, "map_ahash_digest() failed\n");
-               return -ENOMEM;
-       }
-
-       /* Setup DX request structure */
-       ssi_req.user_cb = (void *)ssi_hash_complete;
-       ssi_req.user_arg = (void *)req;
-
-       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
-               key_len = CC_AES_128_BIT_KEY_SIZE;
-               ssi_hash_create_xcbc_setup(req, desc, &idx);
-       } else {
-               key_len = ctx->key_params.keylen;
-               ssi_hash_create_cmac_setup(req, desc, &idx);
-       }
-
-       if (req->nbytes == 0) {
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_key_size_aes(&desc[idx], key_len);
-               set_cmac_size0_mode(&desc[idx]);
-               set_flow_mode(&desc[idx], S_DIN_to_AES);
-               idx++;
-       } else {
-               ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
-       }
-
-       /* Get final MAC result */
-       hw_desc_init(&desc[idx]);
-       /* TODO */
-       set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
-                     digestsize, NS_BIT, 1);
-       set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], S_AES_to_DOUT);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       idx++;
-
-       rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
-       if (unlikely(rc != -EINPROGRESS)) {
-               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-               ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true);
-               ssi_hash_unmap_result(dev, state, digestsize, req->result);
-       }
-       return rc;
-}
-
-static int ssi_mac_digest(struct ahash_request *req)
-{
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       u32 digestsize = crypto_ahash_digestsize(tfm);
-       struct ssi_crypto_req ssi_req = {};
-       struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
-       u32 key_len;
-       int idx = 0;
-       int rc;
-
-       dev_dbg(dev, "===== -digest mac (%d) ====\n",  req->nbytes);
-
-       if (unlikely(ssi_hash_map_request(dev, state, ctx) != 0)) {
-               dev_err(dev, "map_ahash_source() failed\n");
-               return -ENOMEM;
-       }
-       if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) {
-               dev_err(dev, "map_ahash_digest() failed\n");
-               return -ENOMEM;
-       }
-
-       if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 1) != 0)) {
-               dev_err(dev, "map_ahash_request_final() failed\n");
-               return -ENOMEM;
-       }
-
-       /* Setup DX request structure */
-       ssi_req.user_cb = (void *)ssi_hash_digest_complete;
-       ssi_req.user_arg = (void *)req;
-
-       if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
-               key_len = CC_AES_128_BIT_KEY_SIZE;
-               ssi_hash_create_xcbc_setup(req, desc, &idx);
-       } else {
-               key_len = ctx->key_params.keylen;
-               ssi_hash_create_cmac_setup(req, desc, &idx);
-       }
-
-       if (req->nbytes == 0) {
-               hw_desc_init(&desc[idx]);
-               set_cipher_mode(&desc[idx], ctx->hw_mode);
-               set_key_size_aes(&desc[idx], key_len);
-               set_cmac_size0_mode(&desc[idx]);
-               set_flow_mode(&desc[idx], S_DIN_to_AES);
-               idx++;
-       } else {
-               ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
-       }
-
-       /* Get final MAC result */
-       hw_desc_init(&desc[idx]);
-       set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
-                     CC_AES_BLOCK_SIZE, NS_BIT, 1);
-       set_queue_last_ind(&desc[idx]);
-       set_flow_mode(&desc[idx], S_AES_to_DOUT);
-       set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_cipher_mode(&desc[idx], ctx->hw_mode);
-       idx++;
-
-       rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
-       if (unlikely(rc != -EINPROGRESS)) {
-               dev_err(dev, "send_request() failed (rc=%d)\n", rc);
-               ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true);
-               ssi_hash_unmap_result(dev, state, digestsize, req->result);
-               ssi_hash_unmap_request(dev, state, ctx);
-       }
-       return rc;
-}
-
-//ahash wrap functions
-static int ssi_ahash_digest(struct ahash_request *req)
-{
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       u32 digestsize = crypto_ahash_digestsize(tfm);
-
-       return ssi_hash_digest(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req);
-}
-
-static int ssi_ahash_update(struct ahash_request *req)
-{
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base);
-
-       return ssi_hash_update(state, ctx, block_size, req->src, req->nbytes, (void *)req);
-}
-
-static int ssi_ahash_finup(struct ahash_request *req)
-{
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       u32 digestsize = crypto_ahash_digestsize(tfm);
-
-       return ssi_hash_finup(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req);
-}
-
-static int ssi_ahash_final(struct ahash_request *req)
-{
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       u32 digestsize = crypto_ahash_digestsize(tfm);
-
-       return ssi_hash_final(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req);
-}
-
-static int ssi_ahash_init(struct ahash_request *req)
-{
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       dev_dbg(dev, "===== init (%d) ====\n", req->nbytes);
-
-       return ssi_hash_init(state, ctx);
-}
-
-static int ssi_ahash_export(struct ahash_request *req, void *out)
-{
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(ahash);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       u8 *curr_buff = state->buff_index ? state->buff1 : state->buff0;
-       u32 curr_buff_cnt = state->buff_index ? state->buff1_cnt :
-                               state->buff0_cnt;
-       const u32 tmp = CC_EXPORT_MAGIC;
-
-       memcpy(out, &tmp, sizeof(u32));
-       out += sizeof(u32);
-
-       dma_sync_single_for_cpu(dev, state->digest_buff_dma_addr,
-                               ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-       memcpy(out, state->digest_buff, ctx->inter_digestsize);
-       out += ctx->inter_digestsize;
-
-       if (state->digest_bytes_len_dma_addr) {
-               dma_sync_single_for_cpu(dev, state->digest_bytes_len_dma_addr,
-                                       HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
-               memcpy(out, state->digest_bytes_len, HASH_LEN_SIZE);
-       } else {
-               /* Poison the unused exported digest len field. */
-               memset(out, 0x5F, HASH_LEN_SIZE);
-       }
-       out += HASH_LEN_SIZE;
-
-       memcpy(out, &curr_buff_cnt, sizeof(u32));
-       out += sizeof(u32);
-
-       memcpy(out, curr_buff, curr_buff_cnt);
-
-       /* No sync for device ineeded since we did not change the data,
-        * we only copy it
-        */
-
-       return 0;
-}
-
-static int ssi_ahash_import(struct ahash_request *req, const void *in)
-{
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(ahash);
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-       struct ahash_req_ctx *state = ahash_request_ctx(req);
-       u32 tmp;
-       int rc = 0;
-
-       memcpy(&tmp, in, sizeof(u32));
-       if (tmp != CC_EXPORT_MAGIC) {
-               rc = -EINVAL;
-               goto out;
-       }
-       in += sizeof(u32);
-
-       /* call init() to allocate bufs if the user hasn't */
-       if (!state->digest_buff) {
-               rc = ssi_hash_init(state, ctx);
-               if (rc)
-                       goto out;
-       }
-
-       dma_sync_single_for_cpu(dev, state->digest_buff_dma_addr,
-                               ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-       memcpy(state->digest_buff, in, ctx->inter_digestsize);
-       in += ctx->inter_digestsize;
-
-       if (state->digest_bytes_len_dma_addr) {
-               dma_sync_single_for_cpu(dev, state->digest_bytes_len_dma_addr,
-                                       HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
-               memcpy(state->digest_bytes_len, in, HASH_LEN_SIZE);
-       }
-       in += HASH_LEN_SIZE;
-
-       dma_sync_single_for_device(dev, state->digest_buff_dma_addr,
-                                  ctx->inter_digestsize, DMA_BIDIRECTIONAL);
-
-       if (state->digest_bytes_len_dma_addr)
-               dma_sync_single_for_device(dev,
-                                          state->digest_bytes_len_dma_addr,
-                                          HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
-
-       state->buff_index = 0;
-
-       /* Sanity check the data as much as possible */
-       memcpy(&tmp, in, sizeof(u32));
-       if (tmp > SSI_MAX_HASH_BLCK_SIZE) {
-               rc = -EINVAL;
-               goto out;
-       }
-       in += sizeof(u32);
-
-       state->buff0_cnt = tmp;
-       memcpy(state->buff0, in, state->buff0_cnt);
-
-out:
-       return rc;
-}
-
-static int ssi_ahash_setkey(struct crypto_ahash *ahash,
-                           const u8 *key, unsigned int keylen)
-{
-       return ssi_hash_setkey((void *)ahash, key, keylen, false);
-}
-
-struct ssi_hash_template {
-       char name[CRYPTO_MAX_ALG_NAME];
-       char driver_name[CRYPTO_MAX_ALG_NAME];
-       char mac_name[CRYPTO_MAX_ALG_NAME];
-       char mac_driver_name[CRYPTO_MAX_ALG_NAME];
-       unsigned int blocksize;
-       bool synchronize;
-       struct ahash_alg template_ahash;
-       int hash_mode;
-       int hw_mode;
-       int inter_digestsize;
-       struct ssi_drvdata *drvdata;
-};
-
-#define CC_STATE_SIZE(_x) \
-       ((_x) + HASH_LEN_SIZE + SSI_MAX_HASH_BLCK_SIZE + (2 * sizeof(u32)))
-
-/* hash descriptors */
-static struct ssi_hash_template driver_hash[] = {
-       //Asynchronize hash template
-       {
-               .name = "sha1",
-               .driver_name = "sha1-dx",
-               .mac_name = "hmac(sha1)",
-               .mac_driver_name = "hmac-sha1-dx",
-               .blocksize = SHA1_BLOCK_SIZE,
-               .synchronize = false,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA1_DIGEST_SIZE,
-                               .statesize = CC_STATE_SIZE(SHA1_DIGEST_SIZE),
-                       },
-               },
-               .hash_mode = DRV_HASH_SHA1,
-               .hw_mode = DRV_HASH_HW_SHA1,
-               .inter_digestsize = SHA1_DIGEST_SIZE,
-       },
-       {
-               .name = "sha256",
-               .driver_name = "sha256-dx",
-               .mac_name = "hmac(sha256)",
-               .mac_driver_name = "hmac-sha256-dx",
-               .blocksize = SHA256_BLOCK_SIZE,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA256_DIGEST_SIZE,
-                               .statesize = CC_STATE_SIZE(SHA256_DIGEST_SIZE)
-                       },
-               },
-               .hash_mode = DRV_HASH_SHA256,
-               .hw_mode = DRV_HASH_HW_SHA256,
-               .inter_digestsize = SHA256_DIGEST_SIZE,
-       },
-       {
-               .name = "sha224",
-               .driver_name = "sha224-dx",
-               .mac_name = "hmac(sha224)",
-               .mac_driver_name = "hmac-sha224-dx",
-               .blocksize = SHA224_BLOCK_SIZE,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA224_DIGEST_SIZE,
-                               .statesize = CC_STATE_SIZE(SHA224_DIGEST_SIZE),
-                       },
-               },
-               .hash_mode = DRV_HASH_SHA224,
-               .hw_mode = DRV_HASH_HW_SHA256,
-               .inter_digestsize = SHA256_DIGEST_SIZE,
-       },
-#if (DX_DEV_SHA_MAX > 256)
-       {
-               .name = "sha384",
-               .driver_name = "sha384-dx",
-               .mac_name = "hmac(sha384)",
-               .mac_driver_name = "hmac-sha384-dx",
-               .blocksize = SHA384_BLOCK_SIZE,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA384_DIGEST_SIZE,
-                               .statesize = CC_STATE_SIZE(SHA384_DIGEST_SIZE),
-                       },
-               },
-               .hash_mode = DRV_HASH_SHA384,
-               .hw_mode = DRV_HASH_HW_SHA512,
-               .inter_digestsize = SHA512_DIGEST_SIZE,
-       },
-       {
-               .name = "sha512",
-               .driver_name = "sha512-dx",
-               .mac_name = "hmac(sha512)",
-               .mac_driver_name = "hmac-sha512-dx",
-               .blocksize = SHA512_BLOCK_SIZE,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA512_DIGEST_SIZE,
-                               .statesize = CC_STATE_SIZE(SHA512_DIGEST_SIZE),
-                       },
-               },
-               .hash_mode = DRV_HASH_SHA512,
-               .hw_mode = DRV_HASH_HW_SHA512,
-               .inter_digestsize = SHA512_DIGEST_SIZE,
-       },
-#endif
-       {
-               .name = "md5",
-               .driver_name = "md5-dx",
-               .mac_name = "hmac(md5)",
-               .mac_driver_name = "hmac-md5-dx",
-               .blocksize = MD5_HMAC_BLOCK_SIZE,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = MD5_DIGEST_SIZE,
-                               .statesize = CC_STATE_SIZE(MD5_DIGEST_SIZE),
-                       },
-               },
-               .hash_mode = DRV_HASH_MD5,
-               .hw_mode = DRV_HASH_HW_MD5,
-               .inter_digestsize = MD5_DIGEST_SIZE,
-       },
-       {
-               .mac_name = "xcbc(aes)",
-               .mac_driver_name = "xcbc-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_mac_update,
-                       .final = ssi_mac_final,
-                       .finup = ssi_mac_finup,
-                       .digest = ssi_mac_digest,
-                       .setkey = ssi_xcbc_setkey,
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
-                       .halg = {
-                               .digestsize = AES_BLOCK_SIZE,
-                               .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE),
-                       },
-               },
-               .hash_mode = DRV_HASH_NULL,
-               .hw_mode = DRV_CIPHER_XCBC_MAC,
-               .inter_digestsize = AES_BLOCK_SIZE,
-       },
-#if SSI_CC_HAS_CMAC
-       {
-               .mac_name = "cmac(aes)",
-               .mac_driver_name = "cmac-aes-dx",
-               .blocksize = AES_BLOCK_SIZE,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_mac_update,
-                       .final = ssi_mac_final,
-                       .finup = ssi_mac_finup,
-                       .digest = ssi_mac_digest,
-                       .setkey = ssi_cmac_setkey,
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
-                       .halg = {
-                               .digestsize = AES_BLOCK_SIZE,
-                               .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE),
-                       },
-               },
-               .hash_mode = DRV_HASH_NULL,
-               .hw_mode = DRV_CIPHER_CMAC,
-               .inter_digestsize = AES_BLOCK_SIZE,
-       },
-#endif
-
-};
-
-static struct ssi_hash_alg *
-ssi_hash_create_alg(struct ssi_hash_template *template, struct device *dev,
-                   bool keyed)
-{
-       struct ssi_hash_alg *t_crypto_alg;
-       struct crypto_alg *alg;
-       struct ahash_alg *halg;
-
-       t_crypto_alg = kzalloc(sizeof(*t_crypto_alg), GFP_KERNEL);
-       if (!t_crypto_alg)
-               return ERR_PTR(-ENOMEM);
-
-
-       t_crypto_alg->ahash_alg = template->template_ahash;
-       halg = &t_crypto_alg->ahash_alg;
-       alg = &halg->halg.base;
-
-       if (keyed) {
-               snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
-                        template->mac_name);
-               snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
-                        template->mac_driver_name);
-       } else {
-               halg->setkey = NULL;
-               snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
-                        template->name);
-               snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
-                        template->driver_name);
-       }
-       alg->cra_module = THIS_MODULE;
-       alg->cra_ctxsize = sizeof(struct ssi_hash_ctx);
-       alg->cra_priority = SSI_CRA_PRIO;
-       alg->cra_blocksize = template->blocksize;
-       alg->cra_alignmask = 0;
-       alg->cra_exit = ssi_hash_cra_exit;
-
-       alg->cra_init = ssi_ahash_cra_init;
-       alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_TYPE_AHASH |
-                       CRYPTO_ALG_KERN_DRIVER_ONLY;
-       alg->cra_type = &crypto_ahash_type;
-
-       t_crypto_alg->hash_mode = template->hash_mode;
-       t_crypto_alg->hw_mode = template->hw_mode;
-       t_crypto_alg->inter_digestsize = template->inter_digestsize;
-
-       return t_crypto_alg;
-}
-
-int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata)
-{
-       struct ssi_hash_handle *hash_handle = drvdata->hash_handle;
-       ssi_sram_addr_t sram_buff_ofs = hash_handle->digest_len_sram_addr;
-       unsigned int larval_seq_len = 0;
-       struct cc_hw_desc larval_seq[CC_DIGEST_SIZE_MAX / sizeof(u32)];
-       struct device *dev = drvdata_to_dev(drvdata);
-       int rc = 0;
-#if (DX_DEV_SHA_MAX > 256)
-       int i;
-#endif
-
-       /* Copy-to-sram digest-len */
-       ssi_sram_mgr_const2sram_desc(digest_len_init, sram_buff_ofs,
-                                    ARRAY_SIZE(digest_len_init),
-                                    larval_seq, &larval_seq_len);
-       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
-       if (unlikely(rc != 0))
-               goto init_digest_const_err;
-
-       sram_buff_ofs += sizeof(digest_len_init);
-       larval_seq_len = 0;
-
-#if (DX_DEV_SHA_MAX > 256)
-       /* Copy-to-sram digest-len for sha384/512 */
-       ssi_sram_mgr_const2sram_desc(digest_len_sha512_init, sram_buff_ofs,
-                                    ARRAY_SIZE(digest_len_sha512_init),
-                                    larval_seq, &larval_seq_len);
-       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
-       if (unlikely(rc != 0))
-               goto init_digest_const_err;
-
-       sram_buff_ofs += sizeof(digest_len_sha512_init);
-       larval_seq_len = 0;
-#endif
-
-       /* The initial digests offset */
-       hash_handle->larval_digest_sram_addr = sram_buff_ofs;
-
-       /* Copy-to-sram initial SHA* digests */
-       ssi_sram_mgr_const2sram_desc(md5_init, sram_buff_ofs,
-                                    ARRAY_SIZE(md5_init), larval_seq,
-                                    &larval_seq_len);
-       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
-       if (unlikely(rc != 0))
-               goto init_digest_const_err;
-       sram_buff_ofs += sizeof(md5_init);
-       larval_seq_len = 0;
-
-       ssi_sram_mgr_const2sram_desc(sha1_init, sram_buff_ofs,
-                                    ARRAY_SIZE(sha1_init), larval_seq,
-                                    &larval_seq_len);
-       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
-       if (unlikely(rc != 0))
-               goto init_digest_const_err;
-       sram_buff_ofs += sizeof(sha1_init);
-       larval_seq_len = 0;
-
-       ssi_sram_mgr_const2sram_desc(sha224_init, sram_buff_ofs,
-                                    ARRAY_SIZE(sha224_init), larval_seq,
-                                    &larval_seq_len);
-       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
-       if (unlikely(rc != 0))
-               goto init_digest_const_err;
-       sram_buff_ofs += sizeof(sha224_init);
-       larval_seq_len = 0;
-
-       ssi_sram_mgr_const2sram_desc(sha256_init, sram_buff_ofs,
-                                    ARRAY_SIZE(sha256_init), larval_seq,
-                                    &larval_seq_len);
-       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
-       if (unlikely(rc != 0))
-               goto init_digest_const_err;
-       sram_buff_ofs += sizeof(sha256_init);
-       larval_seq_len = 0;
-
-#if (DX_DEV_SHA_MAX > 256)
-       /* We are forced to swap each double-word larval before copying to sram */
-       for (i = 0; i < ARRAY_SIZE(sha384_init); i++) {
-               const u32 const0 = ((u32 *)((u64 *)&sha384_init[i]))[1];
-               const u32 const1 = ((u32 *)((u64 *)&sha384_init[i]))[0];
-
-               ssi_sram_mgr_const2sram_desc(&const0, sram_buff_ofs, 1,
-                                            larval_seq, &larval_seq_len);
-               sram_buff_ofs += sizeof(u32);
-               ssi_sram_mgr_const2sram_desc(&const1, sram_buff_ofs, 1,
-                                            larval_seq, &larval_seq_len);
-               sram_buff_ofs += sizeof(u32);
-       }
-       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "send_request() failed (rc = %d)\n", rc);
-               goto init_digest_const_err;
-       }
-       larval_seq_len = 0;
-
-       for (i = 0; i < ARRAY_SIZE(sha512_init); i++) {
-               const u32 const0 = ((u32 *)((u64 *)&sha512_init[i]))[1];
-               const u32 const1 = ((u32 *)((u64 *)&sha512_init[i]))[0];
-
-               ssi_sram_mgr_const2sram_desc(&const0, sram_buff_ofs, 1,
-                                            larval_seq, &larval_seq_len);
-               sram_buff_ofs += sizeof(u32);
-               ssi_sram_mgr_const2sram_desc(&const1, sram_buff_ofs, 1,
-                                            larval_seq, &larval_seq_len);
-               sram_buff_ofs += sizeof(u32);
-       }
-       rc = send_request_init(drvdata, larval_seq, larval_seq_len);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "send_request() failed (rc = %d)\n", rc);
-               goto init_digest_const_err;
-       }
-#endif
-
-init_digest_const_err:
-       return rc;
-}
-
-int ssi_hash_alloc(struct ssi_drvdata *drvdata)
-{
-       struct ssi_hash_handle *hash_handle;
-       ssi_sram_addr_t sram_buff;
-       u32 sram_size_to_alloc;
-       struct device *dev = drvdata_to_dev(drvdata);
-       int rc = 0;
-       int alg;
-
-       hash_handle = kzalloc(sizeof(*hash_handle), GFP_KERNEL);
-       if (!hash_handle)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&hash_handle->hash_list);
-       drvdata->hash_handle = hash_handle;
-
-       sram_size_to_alloc = sizeof(digest_len_init) +
-#if (DX_DEV_SHA_MAX > 256)
-                       sizeof(digest_len_sha512_init) +
-                       sizeof(sha384_init) +
-                       sizeof(sha512_init) +
-#endif
-                       sizeof(md5_init) +
-                       sizeof(sha1_init) +
-                       sizeof(sha224_init) +
-                       sizeof(sha256_init);
-
-       sram_buff = ssi_sram_mgr_alloc(drvdata, sram_size_to_alloc);
-       if (sram_buff == NULL_SRAM_ADDR) {
-               dev_err(dev, "SRAM pool exhausted\n");
-               rc = -ENOMEM;
-               goto fail;
-       }
-
-       /* The initial digest-len offset */
-       hash_handle->digest_len_sram_addr = sram_buff;
-
-       /*must be set before the alg registration as it is being used there*/
-       rc = ssi_hash_init_sram_digest_consts(drvdata);
-       if (unlikely(rc != 0)) {
-               dev_err(dev, "Init digest CONST failed (rc=%d)\n", rc);
-               goto fail;
-       }
-
-       /* ahash registration */
-       for (alg = 0; alg < ARRAY_SIZE(driver_hash); alg++) {
-               struct ssi_hash_alg *t_alg;
-               int hw_mode = driver_hash[alg].hw_mode;
-
-               /* register hmac version */
-               t_alg = ssi_hash_create_alg(&driver_hash[alg], dev, true);
-               if (IS_ERR(t_alg)) {
-                       rc = PTR_ERR(t_alg);
-                       dev_err(dev, "%s alg allocation failed\n",
-                               driver_hash[alg].driver_name);
-                       goto fail;
-               }
-               t_alg->drvdata = drvdata;
-
-               rc = crypto_register_ahash(&t_alg->ahash_alg);
-               if (unlikely(rc)) {
-                       dev_err(dev, "%s alg registration failed\n",
-                               driver_hash[alg].driver_name);
-                       kfree(t_alg);
-                       goto fail;
-               } else {
-                       list_add_tail(&t_alg->entry,
-                                     &hash_handle->hash_list);
-               }
-
-               if ((hw_mode == DRV_CIPHER_XCBC_MAC) ||
-                   (hw_mode == DRV_CIPHER_CMAC))
-                       continue;
-
-               /* register hash version */
-               t_alg = ssi_hash_create_alg(&driver_hash[alg], dev, false);
-               if (IS_ERR(t_alg)) {
-                       rc = PTR_ERR(t_alg);
-                       dev_err(dev, "%s alg allocation failed\n",
-                               driver_hash[alg].driver_name);
-                       goto fail;
-               }
-               t_alg->drvdata = drvdata;
-
-               rc = crypto_register_ahash(&t_alg->ahash_alg);
-               if (unlikely(rc)) {
-                       dev_err(dev, "%s alg registration failed\n",
-                               driver_hash[alg].driver_name);
-                       kfree(t_alg);
-                       goto fail;
-               } else {
-                       list_add_tail(&t_alg->entry, &hash_handle->hash_list);
-               }
-       }
-
-       return 0;
-
-fail:
-       kfree(drvdata->hash_handle);
-       drvdata->hash_handle = NULL;
-       return rc;
-}
-
-int ssi_hash_free(struct ssi_drvdata *drvdata)
-{
-       struct ssi_hash_alg *t_hash_alg, *hash_n;
-       struct ssi_hash_handle *hash_handle = drvdata->hash_handle;
-
-       if (hash_handle) {
-               list_for_each_entry_safe(t_hash_alg, hash_n, &hash_handle->hash_list, entry) {
-                       crypto_unregister_ahash(&t_hash_alg->ahash_alg);
-                       list_del(&t_hash_alg->entry);
-                       kfree(t_hash_alg);
-               }
-
-               kfree(hash_handle);
-               drvdata->hash_handle = NULL;
-       }
-       return 0;
-}
-
-static void ssi_hash_create_xcbc_setup(struct ahash_request *areq,
-                                      struct cc_hw_desc desc[],
-                                      unsigned int *seq_size)
-{
-       unsigned int idx = *seq_size;
-       struct ahash_req_ctx *state = ahash_request_ctx(areq);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-
-       /* Setup XCBC MAC K1 */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr +
-                                           XCBC_MAC_K1_OFFSET),
-                    CC_AES_128_BIT_KEY_SIZE, NS_BIT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       /* Setup XCBC MAC K2 */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr +
-                                           XCBC_MAC_K2_OFFSET),
-                    CC_AES_128_BIT_KEY_SIZE, NS_BIT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       /* Setup XCBC MAC K3 */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr +
-                                           XCBC_MAC_K3_OFFSET),
-                    CC_AES_128_BIT_KEY_SIZE, NS_BIT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE2);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       /* Loading MAC state */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                    CC_AES_BLOCK_SIZE, NS_BIT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-       *seq_size = idx;
-}
-
-static void ssi_hash_create_cmac_setup(struct ahash_request *areq,
-                                      struct cc_hw_desc desc[],
-                                      unsigned int *seq_size)
-{
-       unsigned int idx = *seq_size;
-       struct ahash_req_ctx *state = ahash_request_ctx(areq);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
-       struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-
-       /* Setup CMAC Key */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr,
-                    ((ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE :
-                     ctx->key_params.keylen), NS_BIT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], ctx->key_params.keylen);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-
-       /* Load MAC state */
-       hw_desc_init(&desc[idx]);
-       set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
-                    CC_AES_BLOCK_SIZE, NS_BIT);
-       set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
-       set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
-       set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_key_size_aes(&desc[idx], ctx->key_params.keylen);
-       set_flow_mode(&desc[idx], S_DIN_to_AES);
-       idx++;
-       *seq_size = idx;
-}
-
-static void ssi_hash_create_data_desc(struct ahash_req_ctx *areq_ctx,
-                                     struct ssi_hash_ctx *ctx,
-                                     unsigned int flow_mode,
-                                     struct cc_hw_desc desc[],
-                                     bool is_not_last_data,
-                                     unsigned int *seq_size)
-{
-       unsigned int idx = *seq_size;
-       struct device *dev = drvdata_to_dev(ctx->drvdata);
-
-       if (likely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_DLLI)) {
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI,
-                            sg_dma_address(areq_ctx->curr_sg),
-                            areq_ctx->curr_sg->length, NS_BIT);
-               set_flow_mode(&desc[idx], flow_mode);
-               idx++;
-       } else {
-               if (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) {
-                       dev_dbg(dev, " NULL mode\n");
-                       /* nothing to build */
-                       return;
-               }
-               /* bypass */
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_DLLI,
-                            areq_ctx->mlli_params.mlli_dma_addr,
-                            areq_ctx->mlli_params.mlli_len, NS_BIT);
-               set_dout_sram(&desc[idx], ctx->drvdata->mlli_sram_addr,
-                             areq_ctx->mlli_params.mlli_len);
-               set_flow_mode(&desc[idx], BYPASS);
-               idx++;
-               /* process */
-               hw_desc_init(&desc[idx]);
-               set_din_type(&desc[idx], DMA_MLLI,
-                            ctx->drvdata->mlli_sram_addr,
-                            areq_ctx->mlli_nents, NS_BIT);
-               set_flow_mode(&desc[idx], flow_mode);
-               idx++;
-       }
-       if (is_not_last_data)
-               set_din_not_last_indication(&desc[(idx - 1)]);
-       /* return updated desc sequence size */
-       *seq_size = idx;
-}
-
-/*!
- * Gets the address of the initial digest in SRAM
- * according to the given hash mode
- *
- * \param drvdata
- * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256
- *
- * \return u32 The address of the inital digest in SRAM
- */
-ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode)
-{
-       struct ssi_drvdata *_drvdata = (struct ssi_drvdata *)drvdata;
-       struct ssi_hash_handle *hash_handle = _drvdata->hash_handle;
-       struct device *dev = drvdata_to_dev(_drvdata);
-
-       switch (mode) {
-       case DRV_HASH_NULL:
-               break; /*Ignore*/
-       case DRV_HASH_MD5:
-               return (hash_handle->larval_digest_sram_addr);
-       case DRV_HASH_SHA1:
-               return (hash_handle->larval_digest_sram_addr +
-                       sizeof(md5_init));
-       case DRV_HASH_SHA224:
-               return (hash_handle->larval_digest_sram_addr +
-                       sizeof(md5_init) +
-                       sizeof(sha1_init));
-       case DRV_HASH_SHA256:
-               return (hash_handle->larval_digest_sram_addr +
-                       sizeof(md5_init) +
-                       sizeof(sha1_init) +
-                       sizeof(sha224_init));
-#if (DX_DEV_SHA_MAX > 256)
-       case DRV_HASH_SHA384:
-               return (hash_handle->larval_digest_sram_addr +
-                       sizeof(md5_init) +
-                       sizeof(sha1_init) +
-                       sizeof(sha224_init) +
-                       sizeof(sha256_init));
-       case DRV_HASH_SHA512:
-               return (hash_handle->larval_digest_sram_addr +
-                       sizeof(md5_init) +
-                       sizeof(sha1_init) +
-                       sizeof(sha224_init) +
-                       sizeof(sha256_init) +
-                       sizeof(sha384_init));
-#endif
-       default:
-               dev_err(dev, "Invalid hash mode (%d)\n", mode);
-       }
-
-       /*This is valid wrong value to avoid kernel crash*/
-       return hash_handle->larval_digest_sram_addr;
-}
-
-ssi_sram_addr_t
-ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, u32 mode)
-{
-       struct ssi_drvdata *_drvdata = (struct ssi_drvdata *)drvdata;
-       struct ssi_hash_handle *hash_handle = _drvdata->hash_handle;
-       ssi_sram_addr_t digest_len_addr = hash_handle->digest_len_sram_addr;
-
-       switch (mode) {
-       case DRV_HASH_SHA1:
-       case DRV_HASH_SHA224:
-       case DRV_HASH_SHA256:
-       case DRV_HASH_MD5:
-               return digest_len_addr;
-#if (DX_DEV_SHA_MAX > 256)
-       case DRV_HASH_SHA384:
-       case DRV_HASH_SHA512:
-               return  digest_len_addr + sizeof(digest_len_init);
-#endif
-       default:
-               return digest_len_addr; /*to avoid kernel crash*/
-       }
-}
-
diff --git a/drivers/staging/ccree/ssi_hash.h b/drivers/staging/ccree/ssi_hash.h
deleted file mode 100644 (file)
index 2400e38..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file ssi_hash.h
- * ARM CryptoCell Hash Crypto API
- */
-
-#ifndef __SSI_HASH_H__
-#define __SSI_HASH_H__
-
-#include "ssi_buffer_mgr.h"
-
-#define HMAC_IPAD_CONST        0x36363636
-#define HMAC_OPAD_CONST        0x5C5C5C5C
-#if (DX_DEV_SHA_MAX > 256)
-#define HASH_LEN_SIZE 16
-#define SSI_MAX_HASH_DIGEST_SIZE       SHA512_DIGEST_SIZE
-#define SSI_MAX_HASH_BLCK_SIZE SHA512_BLOCK_SIZE
-#else
-#define HASH_LEN_SIZE 8
-#define SSI_MAX_HASH_DIGEST_SIZE       SHA256_DIGEST_SIZE
-#define SSI_MAX_HASH_BLCK_SIZE SHA256_BLOCK_SIZE
-#endif
-
-#define XCBC_MAC_K1_OFFSET 0
-#define XCBC_MAC_K2_OFFSET 16
-#define XCBC_MAC_K3_OFFSET 32
-
-#define CC_EXPORT_MAGIC 0xC2EE1070U
-
-// this struct was taken from drivers/crypto/nx/nx-aes-xcbc.c and it is used for xcbc/cmac statesize
-struct aeshash_state {
-       u8 state[AES_BLOCK_SIZE];
-       unsigned int count;
-       u8 buffer[AES_BLOCK_SIZE];
-};
-
-/* ahash state */
-struct ahash_req_ctx {
-       u8 *buff0;
-       u8 *buff1;
-       u8 *digest_result_buff;
-       struct async_gen_req_ctx gen_ctx;
-       enum ssi_req_dma_buf_type data_dma_buf_type;
-       u8 *digest_buff;
-       u8 *opad_digest_buff;
-       u8 *digest_bytes_len;
-       dma_addr_t opad_digest_dma_addr;
-       dma_addr_t digest_buff_dma_addr;
-       dma_addr_t digest_bytes_len_dma_addr;
-       dma_addr_t digest_result_dma_addr;
-       u32 buff0_cnt;
-       u32 buff1_cnt;
-       u32 buff_index;
-       u32 xcbc_count; /* count xcbc update operatations */
-       struct scatterlist buff_sg[2];
-       struct scatterlist *curr_sg;
-       u32 in_nents;
-       u32 mlli_nents;
-       struct mlli_params mlli_params;
-};
-
-int ssi_hash_alloc(struct ssi_drvdata *drvdata);
-int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata);
-int ssi_hash_free(struct ssi_drvdata *drvdata);
-
-/*!
- * Gets the initial digest length
- *
- * \param drvdata
- * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256/SHA384/SHA512
- *
- * \return u32 returns the address of the initial digest length in SRAM
- */
-ssi_sram_addr_t
-ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, u32 mode);
-
-/*!
- * Gets the address of the initial digest in SRAM
- * according to the given hash mode
- *
- * \param drvdata
- * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256/SHA384/SHA512
- *
- * \return u32 The address of the inital digest in SRAM
- */
-ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode);
-
-#endif /*__SSI_HASH_H__*/
-
diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c
deleted file mode 100644 (file)
index 3f082f4..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/platform_device.h>
-#include <crypto/ctr.h>
-#include "ssi_config.h"
-#include "ssi_driver.h"
-#include "ssi_ivgen.h"
-#include "ssi_request_mgr.h"
-#include "ssi_sram_mgr.h"
-#include "ssi_buffer_mgr.h"
-
-/* The max. size of pool *MUST* be <= SRAM total size */
-#define SSI_IVPOOL_SIZE 1024
-/* The first 32B fraction of pool are dedicated to the
- * next encryption "key" & "IV" for pool regeneration
- */
-#define SSI_IVPOOL_META_SIZE (CC_AES_IV_SIZE + AES_KEYSIZE_128)
-#define SSI_IVPOOL_GEN_SEQ_LEN 4
-
-/**
- * struct ssi_ivgen_ctx -IV pool generation context
- * @pool:          the start address of the iv-pool resides in internal RAM
- * @ctr_key_dma:   address of pool's encryption key material in internal RAM
- * @ctr_iv_dma:    address of pool's counter iv in internal RAM
- * @next_iv_ofs:   the offset to the next available IV in pool
- * @pool_meta:     virt. address of the initial enc. key/IV
- * @pool_meta_dma: phys. address of the initial enc. key/IV
- */
-struct ssi_ivgen_ctx {
-       ssi_sram_addr_t pool;
-       ssi_sram_addr_t ctr_key;
-       ssi_sram_addr_t ctr_iv;
-       u32 next_iv_ofs;
-       u8 *pool_meta;
-       dma_addr_t pool_meta_dma;
-};
-
-/*!
- * Generates SSI_IVPOOL_SIZE of random bytes by
- * encrypting 0's using AES128-CTR.
- *
- * \param ivgen iv-pool context
- * \param iv_seq IN/OUT array to the descriptors sequence
- * \param iv_seq_len IN/OUT pointer to the sequence length
- */
-static int ssi_ivgen_generate_pool(
-       struct ssi_ivgen_ctx *ivgen_ctx,
-       struct cc_hw_desc iv_seq[],
-       unsigned int *iv_seq_len)
-{
-       unsigned int idx = *iv_seq_len;
-
-       if ((*iv_seq_len + SSI_IVPOOL_GEN_SEQ_LEN) > SSI_IVPOOL_SEQ_LEN) {
-               /* The sequence will be longer than allowed */
-               return -EINVAL;
-       }
-       /* Setup key */
-       hw_desc_init(&iv_seq[idx]);
-       set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_key, AES_KEYSIZE_128);
-       set_setup_mode(&iv_seq[idx], SETUP_LOAD_KEY0);
-       set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_flow_mode(&iv_seq[idx], S_DIN_to_AES);
-       set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR);
-       idx++;
-
-       /* Setup cipher state */
-       hw_desc_init(&iv_seq[idx]);
-       set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_iv, CC_AES_IV_SIZE);
-       set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
-       set_flow_mode(&iv_seq[idx], S_DIN_to_AES);
-       set_setup_mode(&iv_seq[idx], SETUP_LOAD_STATE1);
-       set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
-       set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR);
-       idx++;
-
-       /* Perform dummy encrypt to skip first block */
-       hw_desc_init(&iv_seq[idx]);
-       set_din_const(&iv_seq[idx], 0, CC_AES_IV_SIZE);
-       set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, CC_AES_IV_SIZE);
-       set_flow_mode(&iv_seq[idx], DIN_AES_DOUT);
-       idx++;
-
-       /* Generate IV pool */
-       hw_desc_init(&iv_seq[idx]);
-       set_din_const(&iv_seq[idx], 0, SSI_IVPOOL_SIZE);
-       set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, SSI_IVPOOL_SIZE);
-       set_flow_mode(&iv_seq[idx], DIN_AES_DOUT);
-       idx++;
-
-       *iv_seq_len = idx; /* Update sequence length */
-
-       /* queue ordering assures pool readiness */
-       ivgen_ctx->next_iv_ofs = SSI_IVPOOL_META_SIZE;
-
-       return 0;
-}
-
-/*!
- * Generates the initial pool in SRAM.
- * This function should be invoked when resuming DX driver.
- *
- * \param drvdata
- *
- * \return int Zero for success, negative value otherwise.
- */
-int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata)
-{
-       struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
-       struct cc_hw_desc iv_seq[SSI_IVPOOL_SEQ_LEN];
-       unsigned int iv_seq_len = 0;
-       int rc;
-
-       /* Generate initial enc. key/iv */
-       get_random_bytes(ivgen_ctx->pool_meta, SSI_IVPOOL_META_SIZE);
-
-       /* The first 32B reserved for the enc. Key/IV */
-       ivgen_ctx->ctr_key = ivgen_ctx->pool;
-       ivgen_ctx->ctr_iv = ivgen_ctx->pool + AES_KEYSIZE_128;
-
-       /* Copy initial enc. key and IV to SRAM at a single descriptor */
-       hw_desc_init(&iv_seq[iv_seq_len]);
-       set_din_type(&iv_seq[iv_seq_len], DMA_DLLI, ivgen_ctx->pool_meta_dma,
-                    SSI_IVPOOL_META_SIZE, NS_BIT);
-       set_dout_sram(&iv_seq[iv_seq_len], ivgen_ctx->pool,
-                     SSI_IVPOOL_META_SIZE);
-       set_flow_mode(&iv_seq[iv_seq_len], BYPASS);
-       iv_seq_len++;
-
-       /* Generate initial pool */
-       rc = ssi_ivgen_generate_pool(ivgen_ctx, iv_seq, &iv_seq_len);
-       if (unlikely(rc != 0))
-               return rc;
-
-       /* Fire-and-forget */
-       return send_request_init(drvdata, iv_seq, iv_seq_len);
-}
-
-/*!
- * Free iv-pool and ivgen context.
- *
- * \param drvdata
- */
-void ssi_ivgen_fini(struct ssi_drvdata *drvdata)
-{
-       struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
-       struct device *device = &drvdata->plat_dev->dev;
-
-       if (!ivgen_ctx)
-               return;
-
-       if (ivgen_ctx->pool_meta) {
-               memset(ivgen_ctx->pool_meta, 0, SSI_IVPOOL_META_SIZE);
-               dma_free_coherent(device, SSI_IVPOOL_META_SIZE,
-                                 ivgen_ctx->pool_meta,
-                                 ivgen_ctx->pool_meta_dma);
-       }
-
-       ivgen_ctx->pool = NULL_SRAM_ADDR;
-
-       /* release "this" context */
-       kfree(ivgen_ctx);
-}
-
-/*!
- * Allocates iv-pool and maps resources.
- * This function generates the first IV pool.
- *
- * \param drvdata Driver's private context
- *
- * \return int Zero for success, negative value otherwise.
- */
-int ssi_ivgen_init(struct ssi_drvdata *drvdata)
-{
-       struct ssi_ivgen_ctx *ivgen_ctx;
-       struct device *device = &drvdata->plat_dev->dev;
-       int rc;
-
-       /* Allocate "this" context */
-       drvdata->ivgen_handle = kzalloc(sizeof(*drvdata->ivgen_handle),
-                                       GFP_KERNEL);
-       if (!drvdata->ivgen_handle)
-               return -ENOMEM;
-
-       ivgen_ctx = drvdata->ivgen_handle;
-
-       /* Allocate pool's header for intial enc. key/IV */
-       ivgen_ctx->pool_meta = dma_alloc_coherent(device, SSI_IVPOOL_META_SIZE,
-                                                 &ivgen_ctx->pool_meta_dma,
-                                                 GFP_KERNEL);
-       if (!ivgen_ctx->pool_meta) {
-               dev_err(device, "Not enough memory to allocate DMA of pool_meta (%u B)\n",
-                       SSI_IVPOOL_META_SIZE);
-               rc = -ENOMEM;
-               goto out;
-       }
-       /* Allocate IV pool in SRAM */
-       ivgen_ctx->pool = ssi_sram_mgr_alloc(drvdata, SSI_IVPOOL_SIZE);
-       if (ivgen_ctx->pool == NULL_SRAM_ADDR) {
-               dev_err(device, "SRAM pool exhausted\n");
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       return ssi_ivgen_init_sram_pool(drvdata);
-
-out:
-       ssi_ivgen_fini(drvdata);
-       return rc;
-}
-
-/*!
- * Acquires 16 Bytes IV from the iv-pool
- *
- * \param drvdata Driver private context
- * \param iv_out_dma Array of physical IV out addresses
- * \param iv_out_dma_len Length of iv_out_dma array (additional elements of iv_out_dma array are ignore)
- * \param iv_out_size May be 8 or 16 bytes long
- * \param iv_seq IN/OUT array to the descriptors sequence
- * \param iv_seq_len IN/OUT pointer to the sequence length
- *
- * \return int Zero for success, negative value otherwise.
- */
-int ssi_ivgen_getiv(
-       struct ssi_drvdata *drvdata,
-       dma_addr_t iv_out_dma[],
-       unsigned int iv_out_dma_len,
-       unsigned int iv_out_size,
-       struct cc_hw_desc iv_seq[],
-       unsigned int *iv_seq_len)
-{
-       struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
-       unsigned int idx = *iv_seq_len;
-       struct device *dev = drvdata_to_dev(drvdata);
-       unsigned int t;
-
-       if ((iv_out_size != CC_AES_IV_SIZE) &&
-           (iv_out_size != CTR_RFC3686_IV_SIZE)) {
-               return -EINVAL;
-       }
-       if ((iv_out_dma_len + 1) > SSI_IVPOOL_SEQ_LEN) {
-               /* The sequence will be longer than allowed */
-               return -EINVAL;
-       }
-
-       //check that number of generated IV is limited to max dma address iv buffer size
-       if (iv_out_dma_len > SSI_MAX_IVGEN_DMA_ADDRESSES) {
-               /* The sequence will be longer than allowed */
-               return -EINVAL;
-       }
-
-       for (t = 0; t < iv_out_dma_len; t++) {
-               /* Acquire IV from pool */
-               hw_desc_init(&iv_seq[idx]);
-               set_din_sram(&iv_seq[idx], (ivgen_ctx->pool +
-                                           ivgen_ctx->next_iv_ofs),
-                            iv_out_size);
-               set_dout_dlli(&iv_seq[idx], iv_out_dma[t], iv_out_size,
-                             NS_BIT, 0);
-               set_flow_mode(&iv_seq[idx], BYPASS);
-               idx++;
-       }
-
-       /* Bypass operation is proceeded by crypto sequence, hence must
-        *  assure bypass-write-transaction by a memory barrier
-        */
-       hw_desc_init(&iv_seq[idx]);
-       set_din_no_dma(&iv_seq[idx], 0, 0xfffff0);
-       set_dout_no_dma(&iv_seq[idx], 0, 0, 1);
-       idx++;
-
-       *iv_seq_len = idx; /* update seq length */
-
-       /* Update iv index */
-       ivgen_ctx->next_iv_ofs += iv_out_size;
-
-       if ((SSI_IVPOOL_SIZE - ivgen_ctx->next_iv_ofs) < CC_AES_IV_SIZE) {
-               dev_dbg(dev, "Pool exhausted, regenerating iv-pool\n");
-               /* pool is drained -regenerate it! */
-               return ssi_ivgen_generate_pool(ivgen_ctx, iv_seq, iv_seq_len);
-       }
-
-       return 0;
-}
-
diff --git a/drivers/staging/ccree/ssi_ivgen.h b/drivers/staging/ccree/ssi_ivgen.h
deleted file mode 100644 (file)
index 961aea4..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __SSI_IVGEN_H__
-#define __SSI_IVGEN_H__
-
-#include "cc_hw_queue_defs.h"
-
-#define SSI_IVPOOL_SEQ_LEN 8
-
-/*!
- * Allocates iv-pool and maps resources.
- * This function generates the first IV pool.
- *
- * \param drvdata Driver's private context
- *
- * \return int Zero for success, negative value otherwise.
- */
-int ssi_ivgen_init(struct ssi_drvdata *drvdata);
-
-/*!
- * Free iv-pool and ivgen context.
- *
- * \param drvdata
- */
-void ssi_ivgen_fini(struct ssi_drvdata *drvdata);
-
-/*!
- * Generates the initial pool in SRAM.
- * This function should be invoked when resuming DX driver.
- *
- * \param drvdata
- *
- * \return int Zero for success, negative value otherwise.
- */
-int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata);
-
-/*!
- * Acquires 16 Bytes IV from the iv-pool
- *
- * \param drvdata Driver private context
- * \param iv_out_dma Array of physical IV out addresses
- * \param iv_out_dma_len Length of iv_out_dma array (additional elements of iv_out_dma array are ignore)
- * \param iv_out_size May be 8 or 16 bytes long
- * \param iv_seq IN/OUT array to the descriptors sequence
- * \param iv_seq_len IN/OUT pointer to the sequence length
- *
- * \return int Zero for success, negative value otherwise.
- */
-int ssi_ivgen_getiv(
-       struct ssi_drvdata *drvdata,
-       dma_addr_t iv_out_dma[],
-       unsigned int iv_out_dma_len,
-       unsigned int iv_out_size,
-       struct cc_hw_desc iv_seq[],
-       unsigned int *iv_seq_len);
-
-#endif /*__SSI_IVGEN_H__*/
diff --git a/drivers/staging/ccree/ssi_pm.c b/drivers/staging/ccree/ssi_pm.c
deleted file mode 100644 (file)
index 36a4980..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "ssi_config.h"
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <crypto/ctr.h>
-#include <linux/pm_runtime.h>
-#include "ssi_driver.h"
-#include "ssi_buffer_mgr.h"
-#include "ssi_request_mgr.h"
-#include "ssi_sram_mgr.h"
-#include "ssi_sysfs.h"
-#include "ssi_ivgen.h"
-#include "ssi_hash.h"
-#include "ssi_pm.h"
-
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-
-#define POWER_DOWN_ENABLE 0x01
-#define POWER_DOWN_DISABLE 0x00
-
-int ssi_power_mgr_runtime_suspend(struct device *dev)
-{
-       struct ssi_drvdata *drvdata =
-               (struct ssi_drvdata *)dev_get_drvdata(dev);
-       int rc;
-
-       dev_dbg(dev, "set HOST_POWER_DOWN_EN\n");
-       cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_ENABLE);
-       rc = ssi_request_mgr_runtime_suspend_queue(drvdata);
-       if (rc != 0) {
-               dev_err(dev, "ssi_request_mgr_runtime_suspend_queue (%x)\n",
-                       rc);
-               return rc;
-       }
-       fini_cc_regs(drvdata);
-       cc_clk_off(drvdata);
-       return 0;
-}
-
-int ssi_power_mgr_runtime_resume(struct device *dev)
-{
-       int rc;
-       struct ssi_drvdata *drvdata =
-               (struct ssi_drvdata *)dev_get_drvdata(dev);
-
-       dev_dbg(dev, "unset HOST_POWER_DOWN_EN\n");
-       cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE);
-
-       rc = cc_clk_on(drvdata);
-       if (rc) {
-               dev_err(dev, "failed getting clock back on. We're toast.\n");
-               return rc;
-       }
-
-       rc = init_cc_regs(drvdata, false);
-       if (rc != 0) {
-               dev_err(dev, "init_cc_regs (%x)\n", rc);
-               return rc;
-       }
-
-       rc = ssi_request_mgr_runtime_resume_queue(drvdata);
-       if (rc != 0) {
-               dev_err(dev, "ssi_request_mgr_runtime_resume_queue (%x)\n", rc);
-               return rc;
-       }
-
-       /* must be after the queue resuming as it uses the HW queue*/
-       ssi_hash_init_sram_digest_consts(drvdata);
-
-       ssi_ivgen_init_sram_pool(drvdata);
-       return 0;
-}
-
-int ssi_power_mgr_runtime_get(struct device *dev)
-{
-       int rc = 0;
-
-       if (ssi_request_mgr_is_queue_runtime_suspend(
-                               (struct ssi_drvdata *)dev_get_drvdata(dev))) {
-               rc = pm_runtime_get_sync(dev);
-       } else {
-               pm_runtime_get_noresume(dev);
-       }
-       return rc;
-}
-
-int ssi_power_mgr_runtime_put_suspend(struct device *dev)
-{
-       int rc = 0;
-
-       if (!ssi_request_mgr_is_queue_runtime_suspend(
-                               (struct ssi_drvdata *)dev_get_drvdata(dev))) {
-               pm_runtime_mark_last_busy(dev);
-               rc = pm_runtime_put_autosuspend(dev);
-       } else {
-               /* Something wrong happens*/
-               dev_err(dev, "request to suspend already suspended queue");
-               rc = -EBUSY;
-       }
-       return rc;
-}
-
-#endif
-
-int ssi_power_mgr_init(struct ssi_drvdata *drvdata)
-{
-       int rc = 0;
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-       struct device *dev = drvdata_to_dev(drvdata);
-
-       /* must be before the enabling to avoid resdundent suspending */
-       pm_runtime_set_autosuspend_delay(dev, SSI_SUSPEND_TIMEOUT);
-       pm_runtime_use_autosuspend(dev);
-       /* activate the PM module */
-       rc = pm_runtime_set_active(dev);
-       if (rc != 0)
-               return rc;
-       /* enable the PM module*/
-       pm_runtime_enable(dev);
-#endif
-       return rc;
-}
-
-void ssi_power_mgr_fini(struct ssi_drvdata *drvdata)
-{
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-       pm_runtime_disable(drvdata_to_dev(drvdata));
-#endif
-}
diff --git a/drivers/staging/ccree/ssi_pm.h b/drivers/staging/ccree/ssi_pm.h
deleted file mode 100644 (file)
index 63673f6..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file ssi_pm.h
- */
-
-#ifndef __SSI_POWER_MGR_H__
-#define __SSI_POWER_MGR_H__
-
-#include "ssi_config.h"
-#include "ssi_driver.h"
-
-#define SSI_SUSPEND_TIMEOUT 3000
-
-int ssi_power_mgr_init(struct ssi_drvdata *drvdata);
-
-void ssi_power_mgr_fini(struct ssi_drvdata *drvdata);
-
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-int ssi_power_mgr_runtime_suspend(struct device *dev);
-
-int ssi_power_mgr_runtime_resume(struct device *dev);
-
-int ssi_power_mgr_runtime_get(struct device *dev);
-
-int ssi_power_mgr_runtime_put_suspend(struct device *dev);
-#endif
-
-#endif /*__POWER_MGR_H__*/
-
diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c
deleted file mode 100644 (file)
index a8a7dc6..0000000
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "ssi_config.h"
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <crypto/ctr.h>
-#ifdef FLUSH_CACHE_ALL
-#include <asm/cacheflush.h>
-#endif
-#include <linux/pm_runtime.h>
-#include "ssi_driver.h"
-#include "ssi_buffer_mgr.h"
-#include "ssi_request_mgr.h"
-#include "ssi_sysfs.h"
-#include "ssi_ivgen.h"
-#include "ssi_pm.h"
-
-#define SSI_MAX_POLL_ITER      10
-
-struct ssi_request_mgr_handle {
-       /* Request manager resources */
-       unsigned int hw_queue_size; /* HW capability */
-       unsigned int min_free_hw_slots;
-       unsigned int max_used_sw_slots;
-       struct ssi_crypto_req req_queue[MAX_REQUEST_QUEUE_SIZE];
-       u32 req_queue_head;
-       u32 req_queue_tail;
-       u32 axi_completed;
-       u32 q_free_slots;
-       spinlock_t hw_lock;
-       struct cc_hw_desc compl_desc;
-       u8 *dummy_comp_buff;
-       dma_addr_t dummy_comp_buff_dma;
-       struct cc_hw_desc monitor_desc;
-
-#ifdef COMP_IN_WQ
-       struct workqueue_struct *workq;
-       struct delayed_work compwork;
-#else
-       struct tasklet_struct comptask;
-#endif
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-       bool is_runtime_suspended;
-#endif
-};
-
-static void comp_handler(unsigned long devarg);
-#ifdef COMP_IN_WQ
-static void comp_work_handler(struct work_struct *work);
-#endif
-
-void request_mgr_fini(struct ssi_drvdata *drvdata)
-{
-       struct ssi_request_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
-       struct device *dev = drvdata_to_dev(drvdata);
-
-       if (!req_mgr_h)
-               return; /* Not allocated */
-
-       if (req_mgr_h->dummy_comp_buff_dma != 0) {
-               dma_free_coherent(dev, sizeof(u32), req_mgr_h->dummy_comp_buff,
-                                 req_mgr_h->dummy_comp_buff_dma);
-       }
-
-       dev_dbg(dev, "max_used_hw_slots=%d\n", (req_mgr_h->hw_queue_size -
-                                               req_mgr_h->min_free_hw_slots));
-       dev_dbg(dev, "max_used_sw_slots=%d\n", req_mgr_h->max_used_sw_slots);
-
-#ifdef COMP_IN_WQ
-       flush_workqueue(req_mgr_h->workq);
-       destroy_workqueue(req_mgr_h->workq);
-#else
-       /* Kill tasklet */
-       tasklet_kill(&req_mgr_h->comptask);
-#endif
-       memset(req_mgr_h, 0, sizeof(struct ssi_request_mgr_handle));
-       kfree(req_mgr_h);
-       drvdata->request_mgr_handle = NULL;
-}
-
-int request_mgr_init(struct ssi_drvdata *drvdata)
-{
-       struct ssi_request_mgr_handle *req_mgr_h;
-       struct device *dev = drvdata_to_dev(drvdata);
-       int rc = 0;
-
-       req_mgr_h = kzalloc(sizeof(*req_mgr_h), GFP_KERNEL);
-       if (!req_mgr_h) {
-               rc = -ENOMEM;
-               goto req_mgr_init_err;
-       }
-
-       drvdata->request_mgr_handle = req_mgr_h;
-
-       spin_lock_init(&req_mgr_h->hw_lock);
-#ifdef COMP_IN_WQ
-       dev_dbg(dev, "Initializing completion workqueue\n");
-       req_mgr_h->workq = create_singlethread_workqueue("arm_cc7x_wq");
-       if (unlikely(!req_mgr_h->workq)) {
-               dev_err(dev, "Failed creating work queue\n");
-               rc = -ENOMEM;
-               goto req_mgr_init_err;
-       }
-       INIT_DELAYED_WORK(&req_mgr_h->compwork, comp_work_handler);
-#else
-       dev_dbg(dev, "Initializing completion tasklet\n");
-       tasklet_init(&req_mgr_h->comptask, comp_handler, (unsigned long)drvdata);
-#endif
-       req_mgr_h->hw_queue_size = cc_ioread(drvdata,
-                                            CC_REG(DSCRPTR_QUEUE_SRAM_SIZE));
-       dev_dbg(dev, "hw_queue_size=0x%08X\n", req_mgr_h->hw_queue_size);
-       if (req_mgr_h->hw_queue_size < MIN_HW_QUEUE_SIZE) {
-               dev_err(dev, "Invalid HW queue size = %u (Min. required is %u)\n",
-                       req_mgr_h->hw_queue_size, MIN_HW_QUEUE_SIZE);
-               rc = -ENOMEM;
-               goto req_mgr_init_err;
-       }
-       req_mgr_h->min_free_hw_slots = req_mgr_h->hw_queue_size;
-       req_mgr_h->max_used_sw_slots = 0;
-
-       /* Allocate DMA word for "dummy" completion descriptor use */
-       req_mgr_h->dummy_comp_buff = dma_alloc_coherent(dev, sizeof(u32),
-                                                       &req_mgr_h->dummy_comp_buff_dma,
-                                                       GFP_KERNEL);
-       if (!req_mgr_h->dummy_comp_buff) {
-               dev_err(dev, "Not enough memory to allocate DMA (%zu) dropped buffer\n",
-                       sizeof(u32));
-               rc = -ENOMEM;
-               goto req_mgr_init_err;
-       }
-
-       /* Init. "dummy" completion descriptor */
-       hw_desc_init(&req_mgr_h->compl_desc);
-       set_din_const(&req_mgr_h->compl_desc, 0, sizeof(u32));
-       set_dout_dlli(&req_mgr_h->compl_desc, req_mgr_h->dummy_comp_buff_dma,
-                     sizeof(u32), NS_BIT, 1);
-       set_flow_mode(&req_mgr_h->compl_desc, BYPASS);
-       set_queue_last_ind(&req_mgr_h->compl_desc);
-
-       return 0;
-
-req_mgr_init_err:
-       request_mgr_fini(drvdata);
-       return rc;
-}
-
-static inline void enqueue_seq(
-       void __iomem *cc_base,
-       struct cc_hw_desc seq[], unsigned int seq_len)
-{
-       int i;
-
-       for (i = 0; i < seq_len; i++) {
-               writel_relaxed(seq[i].word[0], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0)));
-               writel_relaxed(seq[i].word[1], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0)));
-               writel_relaxed(seq[i].word[2], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0)));
-               writel_relaxed(seq[i].word[3], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0)));
-               writel_relaxed(seq[i].word[4], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0)));
-               wmb();
-               writel_relaxed(seq[i].word[5], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0)));
-#ifdef DX_DUMP_DESCS
-               dev_dbg(dev, "desc[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n",
-                       i, seq[i].word[0], seq[i].word[1], seq[i].word[2],
-                       seq[i].word[3], seq[i].word[4], seq[i].word[5]);
-#endif
-       }
-}
-
-/*!
- * Completion will take place if and only if user requested completion
- * by setting "is_dout = 0" in send_request().
- *
- * \param dev
- * \param dx_compl_h The completion event to signal
- */
-static void request_mgr_complete(struct device *dev, void *dx_compl_h, void __iomem *cc_base)
-{
-       struct completion *this_compl = dx_compl_h;
-
-       complete(this_compl);
-}
-
-static inline int request_mgr_queues_status_check(
-               struct ssi_drvdata *drvdata,
-               struct ssi_request_mgr_handle *req_mgr_h,
-               unsigned int total_seq_len)
-{
-       unsigned long poll_queue;
-       struct device *dev = drvdata_to_dev(drvdata);
-
-       /* SW queue is checked only once as it will not
-        * be chaned during the poll becasue the spinlock_bh
-        * is held by the thread
-        */
-       if (unlikely(((req_mgr_h->req_queue_head + 1) &
-                     (MAX_REQUEST_QUEUE_SIZE - 1)) ==
-                    req_mgr_h->req_queue_tail)) {
-               dev_err(dev, "SW FIFO is full. req_queue_head=%d sw_fifo_len=%d\n",
-                       req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE);
-               return -EBUSY;
-       }
-
-       if ((likely(req_mgr_h->q_free_slots >= total_seq_len)))
-               return 0;
-
-       /* Wait for space in HW queue. Poll constant num of iterations. */
-       for (poll_queue = 0; poll_queue < SSI_MAX_POLL_ITER ; poll_queue++) {
-               req_mgr_h->q_free_slots =
-                       cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT));
-               if (unlikely(req_mgr_h->q_free_slots <
-                                               req_mgr_h->min_free_hw_slots)) {
-                       req_mgr_h->min_free_hw_slots = req_mgr_h->q_free_slots;
-               }
-
-               if (likely(req_mgr_h->q_free_slots >= total_seq_len)) {
-                       /* If there is enough place return */
-                       return 0;
-               }
-
-               dev_dbg(dev, "HW FIFO is full. q_free_slots=%d total_seq_len=%d\n",
-                       req_mgr_h->q_free_slots, total_seq_len);
-       }
-       /* No room in the HW queue try again later */
-       dev_dbg(dev, "HW FIFO full, timeout. req_queue_head=%d sw_fifo_len=%d q_free_slots=%d total_seq_len=%d\n",
-               req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE,
-               req_mgr_h->q_free_slots, total_seq_len);
-       return -EAGAIN;
-}
-
-/*!
- * Enqueue caller request to crypto hardware.
- *
- * \param drvdata
- * \param ssi_req The request to enqueue
- * \param desc The crypto sequence
- * \param len The crypto sequence length
- * \param is_dout If "true": completion is handled by the caller
- *       If "false": this function adds a dummy descriptor completion
- *       and waits upon completion signal.
- *
- * \return int Returns -EINPROGRESS if "is_dout=true"; "0" if "is_dout=false"
- */
-int send_request(
-       struct ssi_drvdata *drvdata, struct ssi_crypto_req *ssi_req,
-       struct cc_hw_desc *desc, unsigned int len, bool is_dout)
-{
-       void __iomem *cc_base = drvdata->cc_base;
-       struct ssi_request_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
-       unsigned int used_sw_slots;
-       unsigned int iv_seq_len = 0;
-       unsigned int total_seq_len = len; /*initial sequence length*/
-       struct cc_hw_desc iv_seq[SSI_IVPOOL_SEQ_LEN];
-       struct device *dev = drvdata_to_dev(drvdata);
-       int rc;
-       unsigned int max_required_seq_len = (total_seq_len +
-                                       ((ssi_req->ivgen_dma_addr_len == 0) ? 0 :
-                                       SSI_IVPOOL_SEQ_LEN) +
-                                       (!is_dout ? 1 : 0));
-
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-       rc = ssi_power_mgr_runtime_get(dev);
-       if (rc != 0) {
-               dev_err(dev, "ssi_power_mgr_runtime_get returned %x\n", rc);
-               return rc;
-       }
-#endif
-
-       do {
-               spin_lock_bh(&req_mgr_h->hw_lock);
-
-               /* Check if there is enough place in the SW/HW queues
-                * in case iv gen add the max size and in case of no dout add 1
-                * for the internal completion descriptor
-                */
-               rc = request_mgr_queues_status_check(drvdata, req_mgr_h,
-                                                    max_required_seq_len);
-               if (likely(rc == 0))
-                       /* There is enough place in the queue */
-                       break;
-               /* something wrong release the spinlock*/
-               spin_unlock_bh(&req_mgr_h->hw_lock);
-
-               if (rc != -EAGAIN) {
-                       /* Any error other than HW queue full
-                        * (SW queue is full)
-                        */
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-                       ssi_power_mgr_runtime_put_suspend(dev);
-#endif
-                       return rc;
-               }
-
-               /* HW queue is full - short sleep */
-               msleep(1);
-       } while (1);
-
-       /* Additional completion descriptor is needed incase caller did not
-        * enabled any DLLI/MLLI DOUT bit in the given sequence
-        */
-       if (!is_dout) {
-               init_completion(&ssi_req->seq_compl);
-               ssi_req->user_cb = request_mgr_complete;
-               ssi_req->user_arg = &ssi_req->seq_compl;
-               total_seq_len++;
-       }
-
-       if (ssi_req->ivgen_dma_addr_len > 0) {
-               dev_dbg(dev, "Acquire IV from pool into %d DMA addresses %pad, %pad, %pad, IV-size=%u\n",
-                       ssi_req->ivgen_dma_addr_len,
-                       &ssi_req->ivgen_dma_addr[0],
-                       &ssi_req->ivgen_dma_addr[1],
-                       &ssi_req->ivgen_dma_addr[2],
-                       ssi_req->ivgen_size);
-
-               /* Acquire IV from pool */
-               rc = ssi_ivgen_getiv(drvdata, ssi_req->ivgen_dma_addr,
-                                    ssi_req->ivgen_dma_addr_len,
-                                    ssi_req->ivgen_size, iv_seq, &iv_seq_len);
-
-               if (unlikely(rc != 0)) {
-                       dev_err(dev, "Failed to generate IV (rc=%d)\n", rc);
-                       spin_unlock_bh(&req_mgr_h->hw_lock);
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-                       ssi_power_mgr_runtime_put_suspend(dev);
-#endif
-                       return rc;
-               }
-
-               total_seq_len += iv_seq_len;
-       }
-
-       used_sw_slots = ((req_mgr_h->req_queue_head - req_mgr_h->req_queue_tail) & (MAX_REQUEST_QUEUE_SIZE - 1));
-       if (unlikely(used_sw_slots > req_mgr_h->max_used_sw_slots))
-               req_mgr_h->max_used_sw_slots = used_sw_slots;
-
-       /* Enqueue request - must be locked with HW lock*/
-       req_mgr_h->req_queue[req_mgr_h->req_queue_head] = *ssi_req;
-       req_mgr_h->req_queue_head = (req_mgr_h->req_queue_head + 1) & (MAX_REQUEST_QUEUE_SIZE - 1);
-       /* TODO: Use circ_buf.h ? */
-
-       dev_dbg(dev, "Enqueue request head=%u\n", req_mgr_h->req_queue_head);
-
-#ifdef FLUSH_CACHE_ALL
-       flush_cache_all();
-#endif
-
-       /* STAT_PHASE_4: Push sequence */
-       enqueue_seq(cc_base, iv_seq, iv_seq_len);
-       enqueue_seq(cc_base, desc, len);
-       enqueue_seq(cc_base, &req_mgr_h->compl_desc, (is_dout ? 0 : 1));
-
-       if (unlikely(req_mgr_h->q_free_slots < total_seq_len)) {
-               /* This situation should never occur. Maybe indicating problem
-                * with resuming power. Set the free slot count to 0 and hope
-                * for the best.
-                */
-               dev_err(dev, "HW free slot count mismatch.");
-               req_mgr_h->q_free_slots = 0;
-       } else {
-               /* Update the free slots in HW queue */
-               req_mgr_h->q_free_slots -= total_seq_len;
-       }
-
-       spin_unlock_bh(&req_mgr_h->hw_lock);
-
-       if (!is_dout) {
-               /* Wait upon sequence completion.
-                *  Return "0" -Operation done successfully.
-                */
-               wait_for_completion(&ssi_req->seq_compl);
-               return 0;
-       }
-       /* Operation still in process */
-       return -EINPROGRESS;
-}
-
-/*!
- * Enqueue caller request to crypto hardware during init process.
- * assume this function is not called in middle of a flow,
- * since we set QUEUE_LAST_IND flag in the last descriptor.
- *
- * \param drvdata
- * \param desc The crypto sequence
- * \param len The crypto sequence length
- *
- * \return int Returns "0" upon success
- */
-int send_request_init(
-       struct ssi_drvdata *drvdata, struct cc_hw_desc *desc, unsigned int len)
-{
-       void __iomem *cc_base = drvdata->cc_base;
-       struct ssi_request_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
-       unsigned int total_seq_len = len; /*initial sequence length*/
-       int rc = 0;
-
-       /* Wait for space in HW and SW FIFO. Poll for as much as FIFO_TIMEOUT. */
-       rc = request_mgr_queues_status_check(drvdata, req_mgr_h,
-                                            total_seq_len);
-       if (unlikely(rc != 0))
-               return rc;
-
-       set_queue_last_ind(&desc[(len - 1)]);
-
-       enqueue_seq(cc_base, desc, len);
-
-       /* Update the free slots in HW queue */
-       req_mgr_h->q_free_slots =
-               cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT));
-
-       return 0;
-}
-
-void complete_request(struct ssi_drvdata *drvdata)
-{
-       struct ssi_request_mgr_handle *request_mgr_handle =
-                                               drvdata->request_mgr_handle;
-#ifdef COMP_IN_WQ
-       queue_delayed_work(request_mgr_handle->workq, &request_mgr_handle->compwork, 0);
-#else
-       tasklet_schedule(&request_mgr_handle->comptask);
-#endif
-}
-
-#ifdef COMP_IN_WQ
-static void comp_work_handler(struct work_struct *work)
-{
-       struct ssi_drvdata *drvdata =
-               container_of(work, struct ssi_drvdata, compwork.work);
-
-       comp_handler((unsigned long)drvdata);
-}
-#endif
-
-static void proc_completions(struct ssi_drvdata *drvdata)
-{
-       struct ssi_crypto_req *ssi_req;
-       struct device *dev = drvdata_to_dev(drvdata);
-       struct ssi_request_mgr_handle *request_mgr_handle =
-                                               drvdata->request_mgr_handle;
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-       int rc = 0;
-#endif
-
-       while (request_mgr_handle->axi_completed) {
-               request_mgr_handle->axi_completed--;
-
-               /* Dequeue request */
-               if (unlikely(request_mgr_handle->req_queue_head == request_mgr_handle->req_queue_tail)) {
-                       /* We are supposed to handle a completion but our
-                        * queue is empty. This is not normal. Return and
-                        * hope for the best.
-                        */
-                       dev_err(dev, "Request queue is empty head == tail %u\n",
-                               request_mgr_handle->req_queue_head);
-                       break;
-               }
-
-               ssi_req = &request_mgr_handle->req_queue[request_mgr_handle->req_queue_tail];
-
-#ifdef FLUSH_CACHE_ALL
-               flush_cache_all();
-#endif
-
-#ifdef COMPLETION_DELAY
-               /* Delay */
-               {
-                       u32 axi_err;
-                       int i;
-
-                       dev_info(dev, "Delay\n");
-                       for (i = 0; i < 1000000; i++)
-                               axi_err = cc_ioread(drvdata,
-                                                   CC_REG(AXIM_MON_ERR));
-               }
-#endif /* COMPLETION_DELAY */
-
-               if (likely(ssi_req->user_cb))
-                       ssi_req->user_cb(dev, ssi_req->user_arg,
-                                        drvdata->cc_base);
-               request_mgr_handle->req_queue_tail = (request_mgr_handle->req_queue_tail + 1) & (MAX_REQUEST_QUEUE_SIZE - 1);
-               dev_dbg(dev, "Dequeue request tail=%u\n",
-                       request_mgr_handle->req_queue_tail);
-               dev_dbg(dev, "Request completed. axi_completed=%d\n",
-                       request_mgr_handle->axi_completed);
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-               rc = ssi_power_mgr_runtime_put_suspend(dev);
-               if (rc != 0)
-                       dev_err(dev, "Failed to set runtime suspension %d\n",
-                               rc);
-#endif
-       }
-}
-
-static inline u32 cc_axi_comp_count(struct ssi_drvdata *drvdata)
-{
-       return FIELD_GET(AXIM_MON_COMP_VALUE,
-                        cc_ioread(drvdata, CC_REG(AXIM_MON_COMP)));
-}
-
-/* Deferred service handler, run as interrupt-fired tasklet */
-static void comp_handler(unsigned long devarg)
-{
-       struct ssi_drvdata *drvdata = (struct ssi_drvdata *)devarg;
-       struct ssi_request_mgr_handle *request_mgr_handle =
-                                               drvdata->request_mgr_handle;
-
-       u32 irq;
-
-       irq = (drvdata->irq & SSI_COMP_IRQ_MASK);
-
-       if (irq & SSI_COMP_IRQ_MASK) {
-               /* To avoid the interrupt from firing as we unmask it,
-                * we clear it now
-                */
-               cc_iowrite(drvdata, CC_REG(HOST_ICR), SSI_COMP_IRQ_MASK);
-
-               /* Avoid race with above clear: Test completion counter
-                * once more
-                */
-               request_mgr_handle->axi_completed +=
-                               cc_axi_comp_count(drvdata);
-
-               while (request_mgr_handle->axi_completed) {
-                       do {
-                               proc_completions(drvdata);
-                               /* At this point (after proc_completions()),
-                                * request_mgr_handle->axi_completed is 0.
-                                */
-                               request_mgr_handle->axi_completed =
-                                               cc_axi_comp_count(drvdata);
-                       } while (request_mgr_handle->axi_completed > 0);
-
-                       cc_iowrite(drvdata, CC_REG(HOST_ICR),
-                                  SSI_COMP_IRQ_MASK);
-
-                       request_mgr_handle->axi_completed +=
-                                       cc_axi_comp_count(drvdata);
-               }
-       }
-       /* after verifing that there is nothing to do,
-        * unmask AXI completion interrupt
-        */
-       cc_iowrite(drvdata, CC_REG(HOST_IMR),
-                  cc_ioread(drvdata, CC_REG(HOST_IMR)) & ~irq);
-}
-
-/*
- * resume the queue configuration - no need to take the lock as this happens inside
- * the spin lock protection
- */
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata)
-{
-       struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle;
-
-       spin_lock_bh(&request_mgr_handle->hw_lock);
-       request_mgr_handle->is_runtime_suspended = false;
-       spin_unlock_bh(&request_mgr_handle->hw_lock);
-
-       return 0;
-}
-
-/*
- * suspend the queue configuration. Since it is used for the runtime suspend
- * only verify that the queue can be suspended.
- */
-int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata)
-{
-       struct ssi_request_mgr_handle *request_mgr_handle =
-                                               drvdata->request_mgr_handle;
-
-       /* lock the send_request */
-       spin_lock_bh(&request_mgr_handle->hw_lock);
-       if (request_mgr_handle->req_queue_head !=
-           request_mgr_handle->req_queue_tail) {
-               spin_unlock_bh(&request_mgr_handle->hw_lock);
-               return -EBUSY;
-       }
-       request_mgr_handle->is_runtime_suspended = true;
-       spin_unlock_bh(&request_mgr_handle->hw_lock);
-
-       return 0;
-}
-
-bool ssi_request_mgr_is_queue_runtime_suspend(struct ssi_drvdata *drvdata)
-{
-       struct ssi_request_mgr_handle *request_mgr_handle =
-                                               drvdata->request_mgr_handle;
-
-       return  request_mgr_handle->is_runtime_suspended;
-}
-
-#endif
-
diff --git a/drivers/staging/ccree/ssi_request_mgr.h b/drivers/staging/ccree/ssi_request_mgr.h
deleted file mode 100644 (file)
index bdbbf89..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file request_mgr.h
- * Request Manager
- */
-
-#ifndef __REQUEST_MGR_H__
-#define __REQUEST_MGR_H__
-
-#include "cc_hw_queue_defs.h"
-
-int request_mgr_init(struct ssi_drvdata *drvdata);
-
-/*!
- * Enqueue caller request to crypto hardware.
- *
- * \param drvdata
- * \param ssi_req The request to enqueue
- * \param desc The crypto sequence
- * \param len The crypto sequence length
- * \param is_dout If "true": completion is handled by the caller
- *       If "false": this function adds a dummy descriptor completion
- *       and waits upon completion signal.
- *
- * \return int Returns -EINPROGRESS if "is_dout=ture"; "0" if "is_dout=false"
- */
-int send_request(
-       struct ssi_drvdata *drvdata, struct ssi_crypto_req *ssi_req,
-       struct cc_hw_desc *desc, unsigned int len, bool is_dout);
-
-int send_request_init(
-       struct ssi_drvdata *drvdata, struct cc_hw_desc *desc, unsigned int len);
-
-void complete_request(struct ssi_drvdata *drvdata);
-
-void request_mgr_fini(struct ssi_drvdata *drvdata);
-
-#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
-int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata);
-
-int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata);
-
-bool ssi_request_mgr_is_queue_runtime_suspend(struct ssi_drvdata *drvdata);
-#endif
-
-#endif /*__REQUEST_MGR_H__*/
diff --git a/drivers/staging/ccree/ssi_sram_mgr.c b/drivers/staging/ccree/ssi_sram_mgr.c
deleted file mode 100644 (file)
index 07260d1..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "ssi_driver.h"
-#include "ssi_sram_mgr.h"
-
-/**
- * struct ssi_sram_mgr_ctx -Internal RAM context manager
- * @sram_free_offset:   the offset to the non-allocated area
- */
-struct ssi_sram_mgr_ctx {
-       ssi_sram_addr_t sram_free_offset;
-};
-
-/**
- * ssi_sram_mgr_fini() - Cleanup SRAM pool.
- *
- * @drvdata: Associated device driver context
- */
-void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata)
-{
-       struct ssi_sram_mgr_ctx *smgr_ctx = drvdata->sram_mgr_handle;
-
-       /* Free "this" context */
-       if (smgr_ctx) {
-               memset(smgr_ctx, 0, sizeof(struct ssi_sram_mgr_ctx));
-               kfree(smgr_ctx);
-       }
-}
-
-/**
- * ssi_sram_mgr_init() - Initializes SRAM pool.
- *      The pool starts right at the beginning of SRAM.
- *      Returns zero for success, negative value otherwise.
- *
- * @drvdata: Associated device driver context
- */
-int ssi_sram_mgr_init(struct ssi_drvdata *drvdata)
-{
-       /* Allocate "this" context */
-       drvdata->sram_mgr_handle = kzalloc(sizeof(struct ssi_sram_mgr_ctx),
-                                          GFP_KERNEL);
-
-       if (!drvdata->sram_mgr_handle)
-               return -ENOMEM;
-
-       return 0;
-}
-
-/*!
- * Allocated buffer from SRAM pool.
- * Note: Caller is responsible to free the LAST allocated buffer.
- * This function does not taking care of any fragmentation may occur
- * by the order of calls to alloc/free.
- *
- * \param drvdata
- * \param size The requested bytes to allocate
- */
-ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size)
-{
-       struct ssi_sram_mgr_ctx *smgr_ctx = drvdata->sram_mgr_handle;
-       struct device *dev = drvdata_to_dev(drvdata);
-       ssi_sram_addr_t p;
-
-       if (unlikely((size & 0x3) != 0)) {
-               dev_err(dev, "Requested buffer size (%u) is not multiple of 4",
-                       size);
-               return NULL_SRAM_ADDR;
-       }
-       if (unlikely(size > (SSI_CC_SRAM_SIZE - smgr_ctx->sram_free_offset))) {
-               dev_err(dev, "Not enough space to allocate %u B (at offset %llu)\n",
-                       size, smgr_ctx->sram_free_offset);
-               return NULL_SRAM_ADDR;
-       }
-
-       p = smgr_ctx->sram_free_offset;
-       smgr_ctx->sram_free_offset += size;
-       dev_dbg(dev, "Allocated %u B @ %u\n", size, (unsigned int)p);
-       return p;
-}
-
-/**
- * ssi_sram_mgr_const2sram_desc() - Create const descriptors sequence to
- *     set values in given array into SRAM.
- * Note: each const value can't exceed word size.
- *
- * @src:         A pointer to array of words to set as consts.
- * @dst:         The target SRAM buffer to set into
- * @nelements:   The number of words in "src" array
- * @seq:         A pointer to the given IN/OUT descriptor sequence
- * @seq_len:     A pointer to the given IN/OUT sequence length
- */
-void ssi_sram_mgr_const2sram_desc(
-       const u32 *src, ssi_sram_addr_t dst,
-       unsigned int nelement,
-       struct cc_hw_desc *seq, unsigned int *seq_len)
-{
-       u32 i;
-       unsigned int idx = *seq_len;
-
-       for (i = 0; i < nelement; i++, idx++) {
-               hw_desc_init(&seq[idx]);
-               set_din_const(&seq[idx], src[i], sizeof(u32));
-               set_dout_sram(&seq[idx], dst + (i * sizeof(u32)), sizeof(u32));
-               set_flow_mode(&seq[idx], BYPASS);
-       }
-
-       *seq_len = idx;
-}
-
diff --git a/drivers/staging/ccree/ssi_sram_mgr.h b/drivers/staging/ccree/ssi_sram_mgr.h
deleted file mode 100644 (file)
index 9ba1d59..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __SSI_SRAM_MGR_H__
-#define __SSI_SRAM_MGR_H__
-
-#ifndef SSI_CC_SRAM_SIZE
-#define SSI_CC_SRAM_SIZE 4096
-#endif
-
-struct ssi_drvdata;
-
-/**
- * Address (offset) within CC internal SRAM
- */
-
-typedef u64 ssi_sram_addr_t;
-
-#define NULL_SRAM_ADDR ((ssi_sram_addr_t)-1)
-
-/*!
- * Initializes SRAM pool.
- * The first X bytes of SRAM are reserved for ROM usage, hence, pool
- * starts right after X bytes.
- *
- * \param drvdata
- *
- * \return int Zero for success, negative value otherwise.
- */
-int ssi_sram_mgr_init(struct ssi_drvdata *drvdata);
-
-/*!
- * Uninits SRAM pool.
- *
- * \param drvdata
- */
-void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata);
-
-/*!
- * Allocated buffer from SRAM pool.
- * Note: Caller is responsible to free the LAST allocated buffer.
- * This function does not taking care of any fragmentation may occur
- * by the order of calls to alloc/free.
- *
- * \param drvdata
- * \param size The requested bytes to allocate
- */
-ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size);
-
-/**
- * ssi_sram_mgr_const2sram_desc() - Create const descriptors sequence to
- *     set values in given array into SRAM.
- * Note: each const value can't exceed word size.
- *
- * @src:         A pointer to array of words to set as consts.
- * @dst:         The target SRAM buffer to set into
- * @nelements:   The number of words in "src" array
- * @seq:         A pointer to the given IN/OUT descriptor sequence
- * @seq_len:     A pointer to the given IN/OUT sequence length
- */
-void ssi_sram_mgr_const2sram_desc(
-       const u32 *src, ssi_sram_addr_t dst,
-       unsigned int nelement,
-       struct cc_hw_desc *seq, unsigned int *seq_len);
-
-#endif /*__SSI_SRAM_MGR_H__*/
diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c
deleted file mode 100644 (file)
index 5d39f15..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include "ssi_config.h"
-#include "ssi_driver.h"
-#include "cc_crypto_ctx.h"
-#include "ssi_sysfs.h"
-
-#ifdef ENABLE_CC_SYSFS
-
-static struct ssi_drvdata *sys_get_drvdata(void);
-
-static ssize_t ssi_sys_regdump_show(struct kobject *kobj,
-                                   struct kobj_attribute *attr, char *buf)
-{
-       struct ssi_drvdata *drvdata = sys_get_drvdata();
-       u32 register_value;
-       int offset = 0;
-
-       register_value = cc_ioread(drvdata, CC_REG(HOST_SIGNATURE));
-       offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_SIGNATURE       ", DX_HOST_SIGNATURE_REG_OFFSET, register_value);
-       register_value = cc_ioread(drvdata, CC_REG(HOST_IRR));
-       offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_IRR             ", DX_HOST_IRR_REG_OFFSET, register_value);
-       register_value = cc_ioread(drvdata, CC_REG(HOST_POWER_DOWN_EN));
-       offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_POWER_DOWN_EN   ", DX_HOST_POWER_DOWN_EN_REG_OFFSET, register_value);
-       register_value =  cc_ioread(drvdata, CC_REG(AXIM_MON_ERR));
-       offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "AXIM_MON_ERR         ", DX_AXIM_MON_ERR_REG_OFFSET, register_value);
-       register_value = cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT));
-       offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "DSCRPTR_QUEUE_CONTENT", DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET, register_value);
-       return offset;
-}
-
-static ssize_t ssi_sys_help_show(struct kobject *kobj,
-                                struct kobj_attribute *attr, char *buf)
-{
-       char *help_str[] = {
-                               "cat reg_dump              ", "Print several of CC register values",
-                               };
-       int i = 0, offset = 0;
-
-       offset += scnprintf(buf + offset, PAGE_SIZE - offset, "Usage:\n");
-       for (i = 0; i < ARRAY_SIZE(help_str); i += 2)
-          offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s\t\t%s\n", help_str[i], help_str[i + 1]);
-
-       return offset;
-}
-
-/********************************************************
- *             SYSFS objects                           *
- ********************************************************/
-/*
- * Structure used to create a directory
- * and its attributes in sysfs.
- */
-struct sys_dir {
-       struct kobject *sys_dir_kobj;
-       struct attribute_group sys_dir_attr_group;
-       struct attribute **sys_dir_attr_list;
-       u32 num_of_attrs;
-       struct ssi_drvdata *drvdata; /* Associated driver context */
-};
-
-/* top level directory structures */
-static struct sys_dir sys_top_dir;
-
-/* TOP LEVEL ATTRIBUTES */
-static struct kobj_attribute ssi_sys_top_level_attrs[] = {
-       __ATTR(dump_regs, 0444, ssi_sys_regdump_show, NULL),
-       __ATTR(help, 0444, ssi_sys_help_show, NULL),
-#if defined CC_CYCLE_COUNT
-       __ATTR(stats_host, 0664, ssi_sys_stat_host_db_show, ssi_sys_stats_host_db_clear),
-       __ATTR(stats_cc, 0664, ssi_sys_stat_cc_db_show, ssi_sys_stats_cc_db_clear),
-#endif
-
-};
-
-static struct ssi_drvdata *sys_get_drvdata(void)
-{
-       /* TODO: supporting multiple SeP devices would require avoiding
-        * global "top_dir" and finding associated "top_dir" by traversing
-        * up the tree to the kobject which matches one of the top_dir's
-        */
-       return sys_top_dir.drvdata;
-}
-
-static int sys_init_dir(struct sys_dir *sys_dir, struct ssi_drvdata *drvdata,
-                       struct kobject *parent_dir_kobj, const char *dir_name,
-                       struct kobj_attribute *attrs, u32 num_of_attrs)
-{
-       int i;
-
-       memset(sys_dir, 0, sizeof(struct sys_dir));
-
-       sys_dir->drvdata = drvdata;
-
-       /* initialize directory kobject */
-       sys_dir->sys_dir_kobj =
-               kobject_create_and_add(dir_name, parent_dir_kobj);
-
-       if (!(sys_dir->sys_dir_kobj))
-               return -ENOMEM;
-       /* allocate memory for directory's attributes list */
-       sys_dir->sys_dir_attr_list =
-               kcalloc(num_of_attrs + 1, sizeof(struct attribute *),
-                       GFP_KERNEL);
-
-       if (!(sys_dir->sys_dir_attr_list)) {
-               kobject_put(sys_dir->sys_dir_kobj);
-               return -ENOMEM;
-       }
-
-       sys_dir->num_of_attrs = num_of_attrs;
-
-       /* initialize attributes list */
-       for (i = 0; i < num_of_attrs; ++i)
-               sys_dir->sys_dir_attr_list[i] = &attrs[i].attr;
-
-       /* last list entry should be NULL */
-       sys_dir->sys_dir_attr_list[num_of_attrs] = NULL;
-
-       sys_dir->sys_dir_attr_group.attrs = sys_dir->sys_dir_attr_list;
-
-       return sysfs_create_group(sys_dir->sys_dir_kobj,
-                       &sys_dir->sys_dir_attr_group);
-}
-
-static void sys_free_dir(struct sys_dir *sys_dir)
-{
-       if (!sys_dir)
-               return;
-
-       kfree(sys_dir->sys_dir_attr_list);
-
-       if (sys_dir->sys_dir_kobj)
-               kobject_put(sys_dir->sys_dir_kobj);
-}
-
-int ssi_sysfs_init(struct kobject *sys_dev_obj, struct ssi_drvdata *drvdata)
-{
-       int retval;
-       struct device *dev = drvdata_to_dev(drvdata);
-
-       dev_info(dev, "setup sysfs under %s\n", sys_dev_obj->name);
-
-       /* Initialize top directory */
-       retval = sys_init_dir(&sys_top_dir, drvdata, sys_dev_obj, "cc_info",
-                             ssi_sys_top_level_attrs,
-                             ARRAY_SIZE(ssi_sys_top_level_attrs));
-       return retval;
-}
-
-void ssi_sysfs_fini(void)
-{
-       sys_free_dir(&sys_top_dir);
-}
-
-#endif /*ENABLE_CC_SYSFS*/
-
diff --git a/drivers/staging/ccree/ssi_sysfs.h b/drivers/staging/ccree/ssi_sysfs.h
deleted file mode 100644 (file)
index 44ae3d4..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file ssi_sysfs.h
- * ARM CryptoCell sysfs APIs
- */
-
-#ifndef __SSI_SYSFS_H__
-#define __SSI_SYSFS_H__
-
-#include <asm/timex.h>
-
-/* forward declaration */
-struct ssi_drvdata;
-
-enum stat_phase {
-       STAT_PHASE_0 = 0,
-       STAT_PHASE_1,
-       STAT_PHASE_2,
-       STAT_PHASE_3,
-       STAT_PHASE_4,
-       STAT_PHASE_5,
-       STAT_PHASE_6,
-       MAX_STAT_PHASES,
-};
-
-enum stat_op {
-       STAT_OP_TYPE_NULL = 0,
-       STAT_OP_TYPE_ENCODE,
-       STAT_OP_TYPE_DECODE,
-       STAT_OP_TYPE_SETKEY,
-       STAT_OP_TYPE_GENERIC,
-       MAX_STAT_OP_TYPES,
-};
-
-int ssi_sysfs_init(struct kobject *sys_dev_obj, struct ssi_drvdata *drvdata);
-void ssi_sysfs_fini(void);
-void update_host_stat(unsigned int op_type, unsigned int phase, cycles_t result);
-void update_cc_stat(unsigned int op_type, unsigned int phase, unsigned int elapsed_cycles);
-void display_all_stat_db(void);
-
-#endif /*__SSI_SYSFS_H__*/
index bf3fe7c61be578380225f666b7981b623517383c..cae7e6e695b0ca623797ffc989a8999c101d7e22 100644 (file)
@@ -1,21 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Xilinx 'Clocking Wizard' driver
  *
  *  Copyright (C) 2013 - 2014 Xilinx
  *
  *  Sören Brinkmann <soren.brinkmann@xilinx.com>
- *
- * 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, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/platform_device.h>
index a1c1081906c5523dd3976112b7c9a0cf18012a6f..c0bc413f7fe078a24ee69972095faa2c58833fc8 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: LGPL-2.0+
 /*
  * comedi.h
  * header file for COMEDI user API
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 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 _COMEDI_H
index b455ff6714eb23e08e68afa18f4bfa2aa2e9ef81..f693c2c0bec3cc6843072ff714bfb8ef0b3e2fbb 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_buf.c
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
  * Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/vmalloc.h>
index f356386d833a1fe80c83b9a492634d295991688a..97fb9388bc22d673544e28f35998afc264276898 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/comedi_compat32.c
  * 32-bit ioctl compatibility for 64-bit comedi kernel module.
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/uaccess.h>
index 0127c1f98bbfd426ddb018c97b684fc3d2342f5f..3980e6e1bd0d98ed47f0cea4704c35d138ea81ba 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/comedi_compat32.h
  * 32-bit ioctl compatibility for 64-bit comedi kernel module.
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _COMEDI_COMPAT32_H
index 491b54d986ebdefa27dd61b12f9c72a690daea61..ef733847eebedac08410511c3aa6790e98656e3a 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/comedi_fops.c
  * comedi kernel module
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 51e023a1c0eecf16bb7da1c235a2a2119157b57b..126048b03f43e1cd6a1c6285fcfff96d1c4df587 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_pci.c
  * Comedi PCI driver specific functions.
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index 7dfd892c74b015a983c2aade96cdbb3b4fa4ba44..647a72441b8ab03528c5096d3365a0742ec6ffeb 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_pci.h
  * header file for Comedi PCI drivers
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _COMEDI_PCI_H
index cd4742851c088b3274eddf83fbc7840a79312a65..e16f35eae343b42d6f96565a7ff3c378e43c236c 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_pcmcia.c
  * Comedi PCMCIA driver specific functions.
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index 9e45c7c9327896b02642d7da6f64715b44644ade..c7d37b38e7306f59b7a7dbc62fc873cbdfdfcfc0 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_pcmcia.h
  * header file for Comedi PCMCIA drivers
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _COMEDI_PCMCIA_H
index 9c946d40b8944b56ae3ba7d99e16492623934ee0..c632c2bae72248f11d08a4c6a5748554a08509d8 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_usb.c
  * Comedi USB driver specific functions.
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index 132154ec792fa8b44c1b979cf51ed544683bb0a9..50287de7a239b5b23e0bdcbdbb48146b55f847fb 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_usb.h
  * header file for USB Comedi drivers
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _COMEDI_USB_H
index 1bb9986f865e0151cbb1dde498f4b4e447778d80..f3474a4ba69ee8cc20f4e75758ad5ab17eec0ddb 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedidev.h
  * header file for kernel-only structures, variables, and constants
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _COMEDIDEV_H
@@ -186,23 +177,27 @@ struct comedi_subdevice {
 
        unsigned int *chanlist; /* driver-owned chanlist (not used) */
 
-       int (*insn_read)(struct comedi_device *, struct comedi_subdevice *,
-                        struct comedi_insn *, unsigned int *);
-       int (*insn_write)(struct comedi_device *, struct comedi_subdevice *,
-                         struct comedi_insn *, unsigned int *);
-       int (*insn_bits)(struct comedi_device *, struct comedi_subdevice *,
-                        struct comedi_insn *, unsigned int *);
-       int (*insn_config)(struct comedi_device *, struct comedi_subdevice *,
-                          struct comedi_insn *, unsigned int *);
-
-       int (*do_cmd)(struct comedi_device *, struct comedi_subdevice *);
-       int (*do_cmdtest)(struct comedi_device *, struct comedi_subdevice *,
-                         struct comedi_cmd *);
-       int (*poll)(struct comedi_device *, struct comedi_subdevice *);
-       int (*cancel)(struct comedi_device *, struct comedi_subdevice *);
+       int (*insn_read)(struct comedi_device *dev, struct comedi_subdevice *s,
+                        struct comedi_insn *insn, unsigned int *data);
+       int (*insn_write)(struct comedi_device *dev, struct comedi_subdevice *s,
+                         struct comedi_insn *insn, unsigned int *data);
+       int (*insn_bits)(struct comedi_device *dev, struct comedi_subdevice *s,
+                        struct comedi_insn *insn, unsigned int *data);
+       int (*insn_config)(struct comedi_device *dev,
+                          struct comedi_subdevice *s,
+                          struct comedi_insn *insn,
+                          unsigned int *data);
+
+       int (*do_cmd)(struct comedi_device *dev, struct comedi_subdevice *s);
+       int (*do_cmdtest)(struct comedi_device *dev,
+                         struct comedi_subdevice *s,
+                         struct comedi_cmd *cmd);
+       int (*poll)(struct comedi_device *dev, struct comedi_subdevice *s);
+       int (*cancel)(struct comedi_device *dev, struct comedi_subdevice *s);
 
        /* called when the buffer changes */
-       int (*buf_change)(struct comedi_device *, struct comedi_subdevice *);
+       int (*buf_change)(struct comedi_device *dev,
+                         struct comedi_subdevice *s);
 
        void (*munge)(struct comedi_device *dev, struct comedi_subdevice *s,
                      void *data, unsigned int num_bytes,
@@ -445,9 +440,9 @@ struct comedi_driver {
        /* public: */
        const char *driver_name;
        struct module *module;
-       int (*attach)(struct comedi_device *, struct comedi_devconfig *);
-       void (*detach)(struct comedi_device *);
-       int (*auto_attach)(struct comedi_device *, unsigned long);
+       int (*attach)(struct comedi_device *dev, struct comedi_devconfig *it);
+       void (*detach)(struct comedi_device *dev);
+       int (*auto_attach)(struct comedi_device *dev, unsigned long context);
        unsigned int num_names;
        const char *const *board_name;
        int offset;
index f9b56396e161cccd3c0f42fe016abd6438ff6278..e98cb9752dbce44d41cc47a36c8a76600a798085 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedilib.h
  * Header file for kcomedilib
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _LINUX_COMEDILIB_H
index 0b43db6371c68ae9f3730a5789dcf1d7eb218ece..e618a87521a35606cb97cae84d50fbcdfe13f688 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  module/drivers.c
  *  functions for manipulating drivers
@@ -5,16 +6,6 @@
  *  COMEDI - Linux Control and Measurement Device Interface
  *  Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
  *  Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
  */
 
 #include <linux/device.h>
index b79d3764a8a0a7514084df1d22428b1045246586..3d6105b5a11b13abc7123aefc8d536f9ed706c74 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/8255.c
  * Driver for 8255
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 55a67af5152d1368e3d0500615519e15e39d8356..6cd1339ab83e65d6a795b5290524b020b0a581a8 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * module/8255.h
  * Header file for 8255
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _8255_H
index 38c05d1ec6475a742cbac8b6e4c5a61353e4afdb..9ed05f962fdba6f3399e296006bd5704f0ee4bc3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * COMEDI driver for generic PCI based 8255 digital i/o boards
  * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
@@ -9,16 +10,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index ccd1a91290bf9a27cc4471d5efdc6d1cebb6a22f..560649be9d1309479d959e20c57e68b34f39abb2 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_1032.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 /*
index 63991c49ff2309e8a00bdd1bf28e4ad16eefcce4..45ad4ba92f94f2cbba62aa844a6bf1229de7ae5b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_1500.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
@@ -9,16 +10,6 @@
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 #include <linux/module.h>
index f1f8b1c422a785174d4e769f09b1f606e49dad11..6c8213ee1a748e0ac9a418492c94d90a29b300f3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_1516.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 #include <linux/module.h>
index 9bfb79c2e5c8795e366d94c6650b634104e780ca..10501fe6bb25363fc88cd1d1b194ee511e45e2c1 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_1564.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
@@ -9,16 +10,6 @@
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 /*
index c63133a12a4e12aa3a63c57cc42e307bd9ac614a..050d0b4b32099d0c1a3b03d5587b153131aa7b3c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_16xx.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 #include <linux/module.h>
index 50f9eb25d7cbd55d6dee07b73392c5ca7ba8ebd9..a122f3f3f5ec557636b28c57dae3b38974093622 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_2032.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 #include <linux/module.h>
index 2b382a52d80d41c0679857eef6fb03e3df12e986..140d1514a10660b38518da85363eeb85c71834cc 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_2200.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 #include <linux/module.h>
index 3630d75e36e85255a33c877b8eb647c548ed4a40..d2810fdd5e63050bd84df5a5b29a129bd15a2764 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_3120.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
@@ -9,16 +10,6 @@
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 #include <linux/module.h>
index 1fdc0f8d7e1a7cc441e0a832600c0ee2b1bfff4c..a38267928e5eed0bb1983c8237a6bf3cc3fa46ae 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_3501.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 /*
index be1f6133ff1c8a08f78130810970a515fc01d20f..55784f24e2a748936c1a1be4992867ee22ea84d3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * addi_apci_3xxx.c
  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
  *     Fax: +49(0)7223/9493-92
  *     http://www.addi-data.com
  *     info@addi-data.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.
  */
 
 #include <linux/module.h>
index 9d9853fe54a006cd8316ea20e4fb6cbfae090c33..69b323fb869f96275b35dc69eb530680c153ef1e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * COMEDI driver for the watchdog subdevice found on some addi-data boards
  * Copyright (c) 2013 H Hartley Sweeten <hsweeten@visionengravers.com>
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index ad7e7c4a5232fb6eeb4aa03dd5ca368c95c53e27..d39b4eabce8d17b4f6bd8802ee084f868d673754 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * adl_pci6208.c
  * Comedi driver for ADLink 6208 series cards
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index b0fc027cf485d11cebdb6d495bbce59e239c9996..d0081897fe4719eedc48d7a2a101fe22acd23e5c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * COMEDI driver for the ADLINK PCI-723x/743x series boards.
  * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
@@ -9,16 +10,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index da901c8dec0e2ade20d736136a30d48f8821822b..3022793b1bc54f60000c0c08feede73797c1d67f 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/adl_pci8164.c
  *
  * Hardware comedi driver for PCI-8164 Adlink card
  * Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca>
- *
- * 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.
  */
 
 /*
index 01d2ee931b28eedb9a1c4aa073b71720d88cbfae..f4dba6271d0d736edb23a121d72bbc0dd5c28ad8 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * adl_pci9111.c
  * Hardware driver for PCI9111 ADLink cards: PCI-9111HR
  * Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
- *
- * 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.
  */
 
 /*
index 1cc9b7ef1ff9e18be79233d11a482c5af898f99f..2528ca0ede6df5651b471a5a43f431200a27aadb 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *  comedi/drivers/adl_pci9118.c
  *
index 315050454c26cb7a1337a2e94ab709c8c367780d..5d431573bcca92599f204f083a6b85e8b5a8c6db 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * adq12b.c
  * Driver for MicroAxial ADQ12-B data acquisition and control card
@@ -9,16 +10,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 2c1b6de30da8c4d74e085aaeac64d1c376c53a9f..6a93b04f1fdfd7dd53d47f70d675cb1e3158a88e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * adv_pci1710.c
  * Comedi driver for Advantech PCI-1710 series boards
index 4830a1c93d158fecdb95c47af3130d841ac8f025..2fcd7e8e7d85a90df63bef85b6a950a7d0f89fa7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * COMEDI driver for Advantech PCI-1720U
  * Copyright (c) 2015 H Hartley Sweeten <hsweeten@visionengravers.com>
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index f82afd94731017442494a688e70d00a9fb02e9aa..771d61f87427dfd99c83f708f6050d541e254b67 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * adv_pci1723.c
  * Comedi driver for the Advantech PCI-1723 card.
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index bf6a8f10118c9e9aef2f6454cbcb54d638a45450..e8ab573c839fb7397fda11016f026b35e1ff7a80 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * adv_pci1724.c
  * Comedi driver for the Advantech PCI-1724U card.
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 9f525ff7290c69b764503a232fcd9d7a7de338b3..f460f21efb90c52ec9abc065c7efd90934679878 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * COMEDI driver for the Advantech PCI-1760
  * Copyright (C) 2015 H Hartley Sweeten <hsweeten@visionengravers.com>
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
@@ -69,7 +60,7 @@
 #define PCI1760_CMD_SET_DO             0x01    /* Set output state */
 #define PCI1760_CMD_GET_DO             0x02    /* Read output status */
 #define PCI1760_CMD_GET_STATUS         0x03    /* Read current status */
-#define PCI1760_CMD_GET_FW_VER         0x0e    /* Read firware version */
+#define PCI1760_CMD_GET_FW_VER         0x0e    /* Read firmware version */
 #define PCI1760_CMD_GET_HW_VER         0x0f    /* Read hardware version */
 #define PCI1760_CMD_SET_PWM_HI(x)      (0x10 + (x) * 2) /* Set "hi" period */
 #define PCI1760_CMD_SET_PWM_LO(x)      (0x11 + (x) * 2) /* Set "lo" period */
index a8186687ca2c08064272faa81a759aa849f55e85..5fef2aef7e0350ddeae65dcb38b1b5eba7717a71 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * comedi/drivers/adv_pci_dio.c
  *
index 43a0ce5721d3a3e6a8f7cf943848b567b46ed6e4..f4beda1ed64090a03defb987f3158cf0d8a18093 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * aio_aio12_8.c
  * Driver for Access I/O Products PC-104 AIO12-8 Analog I/O Board
  * Copyright (C) 2006 C&C Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
  */
 
 /*
index 35b2f98f0de951a93b069cf450c8cac4e7dfc517..41c9c56816ef50aa555e2d07bbbd4eca90e3b7c7 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * aio_iiro_16.c
  * Comedi driver for Access I/O Products 104-IIRO-16 board
  * Copyright (C) 2006 C&C Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
  */
 
 /*
index f5cfa71a90c6c50a08a913063574e58692b706fc..26e63d64ffc6d2116a6bac2b84c1c3545631ea49 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/amplc_dio200.c
  *
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 53fb86d59fc3a04cab2d4d3f077e627c6df582b9..88c1d1063d5dfb89766b0427186fe4cb9356a5ad 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/amplc_dio.h
  *
@@ -8,16 +9,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef AMPLC_DIO200_H_INCLUDED
index f6e4e984235d8061a2a2d242338c3ba0bb00d8f8..82bd41d925093bc434cbf317aaf3bc446e829d8e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/amplc_dio200_common.c
  *
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index 2598e6e7d47d3032182ec3caef15538719aefa49..30d239731e0bf69cfd682c14e038a98e41eed2d1 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /* comedi/drivers/amplc_dio200_pci.c
  *
  * Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296.
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 875cc19cb96913ef87949d6758aa8fc69bb13fd3..b7dd15f5ec63c04b6843a857395ff9b6edd8ff98 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/amplc_pc236.c
  * Driver for Amplicon PC36AT DIO boards.
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 /*
  * Driver: amplc_pc236
index 91d6d9c065b59d3c3e2832d189e60b2a04e060ed..4b67090aab540347ead0ead45155a1a1e324dab5 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/amplc_pc236.h
  * Header for "amplc_pc236", "amplc_pci236" and "amplc_pc236_common".
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef AMPLC_PC236_H_INCLUDED
index 0c02d3245679cc8348a4dfb594431d53620baf68..01b90e4eca8a01f14aba117677c24c6bc0baca52 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/amplc_pc236_common.c
  * Common support code for "amplc_pc236" and "amplc_pci236".
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index 58b0b6b1a693c1d7422d69dd53717e70dc1780e5..84c989f12faf5fc725f0376016e971c02b67e870 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Driver for Amplicon PC263 relay board.
  *
@@ -5,16 +6,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 4e554944bc718dc43d4c277ed06aeea75f01b0c2..657b736ef46d3b2f6ff811c3daceb23f8456a513 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/amplc_pci224.c
  * Driver for Amplicon PCI224 and PCI234 AO boards.
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 48c7890c30071ea62b615d596d2d3ab1917ef498..15fc7f19051a307c612ea8bc72aedf6abf14fe98 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/amplc_pci230.c
  * Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 31cc38b4bcadf6154445e4a951074f05123991db..86ea876a11be9babe0463a305400dfa5f50d43bb 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/amplc_pci236.c
  * Driver for Amplicon PCI236 DIO boards.
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 /*
  * Driver: amplc_pci236
index 8d4069bc5716cfc49b510e6e8f38a7fcfc9a3dae..c3efe14020a84f5e8295f59800dc4d3d64662857 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Driver for Amplicon PCI263 relay board.
  *
@@ -5,16 +6,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 8ee732571588a5fa0c3772935c67c1fee6908f0a..41cc784320a940072764c9cbd5030477943858d3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * c6xdigio.c
  * Hardware driver for Mechatronic Systems Inc. C6x_DIGIO DSP daughter card.
@@ -5,16 +6,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999 Dan Block
- *
- * 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.
  */
 
 /*
index 78d098f9e1f2540ca300b3d44d7d4c6d00c4d78d..a5d171e71c330da822a1523b52cc982d0b758ef9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * cb_das16_cs.c
  * Driver for Computer Boards PC-CARD DAS16/16.
@@ -5,16 +6,6 @@
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000, 2001, 2002 David A. Schleef <ds@schleef.org>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * PCMCIA support code for this driver is adapted from the dummy_cs.c
  * driver of the Linux PCMCIA Card Services package.
  *
index 3cd008acb657a5d735628fd49614f5c742a93564..8429d57087fd5a66bc24fac138c4ca8b7aa02baa 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * cb_pcidas.c
  * Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
@@ -8,16 +9,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index b761f000c1dc2ff158eb6586a2dca7ad870e879e..b657beedd5fff751289a0f23a841adb6caf39bd3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/cb_pcidas64.c
  * This is a driver for the ComputerBoards/MeasurementComputing PCI-DAS
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 98741474160514edd39a11132c3d88a648eab16e..807a31e75883ca2703331d4f5c925b0792d1936d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/cb_pcidda.c
  * Driver for the ComputerBoards / MeasurementComputing PCI-DDA series.
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 47e38398921ed26588f1409217f1aafe5bf5c277..4e72a0778086632ed97a2f7b0cc90efcde1680c2 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/cb_pcimdas.c
  * Comedi driver for Computer Boards PCIM-DAS1602/16 and PCIe-DAS1602/16
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 84ef45457c6045714555bd2ec2216dc414170136..b33203f6a99075e483a863e10a4b9e1666c2c4ec 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/cb_pcimdda.c
  * Computer Boards PCIM-DDA06-16 Comedi driver
@@ -5,16 +6,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 /*
  * Driver: cb_pcimdda
index 0d5d56b61f600b37385aa7404cb93626f9bf666f..d1d509e9add94b10c4e16d6def970e43c72a68ed 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_8254.c
  * Generic 8254 timer/counter support
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 326bd44b063e735ce3c37e370cd526346ffa6dca..7faa2185282ef52cf65a054db84627628b40ca07 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_8254.h
  * Generic 8254 timer/counter support
@@ -5,16 +6,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _COMEDI_8254_H
index b2441efc61ccc789c1047087519c9b3dadfdf0de..62baa0d79302359e25218dd95ec6456718cfaa11 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_8255.c
  * Generic 8255 digital I/O support
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 64a5ea3810d4f7b38a4871fea3f0ee5df78c1aa6..4392b5927a9944667ce7a0e1e7f9c0f5e8328c48 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_bond.c
  * A Comedi driver to 'bond' or merge multiple drivers and devices as one.
@@ -5,16 +6,6 @@
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
  * Copyright (C) 2005 Calin A. Culianu <calin@ajvar.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 68ef9b1750be8adefc21d148d949588969fda6c5..b77dc8d5d3ffdf0dc8f72975bc6722c89f226201 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * COMEDI ISA DMA support functions
  * Copyright (c) 2014 H Hartley Sweeten <hsweeten@visionengravers.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.
  */
 
 #include <linux/module.h>
index a193d3e8d185305dd4ca122d470c574bb77cc3cd..ccef7c9c0a4da1da5286a8f3d74d16d9cf817800 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * COMEDI ISA DMA support functions
  * Copyright (c) 2014 H Hartley Sweeten <hsweeten@visionengravers.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 _COMEDI_ISADMA_H
index 1bf8ddc6f07cb6e3155f7e22ed891a352a2b54e5..efaa57372aeb0c3cc24911879142a2ef4c07a784 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi_parport.c
  * Comedi driver for standard parallel port
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998,2001 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index c7e8194984e508d4785053aeba385e43660edd21..d437af721bd81e5c0c6f31d8c5206401bf606068 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/comedi_test.c
  *
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 5f848396c2f7cf7be25bc64c95881a48e3d8ceb8..49be795b4971458884e5fdc0f9bef5eed259f986 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/contec_pci_dio.c
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index a562df498b017e278f266f7ff8a07160991a2f61..5ef8114c2c853f6c381b5770add4c69a1568b193 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * dac02.c
  * Comedi driver for DAC02 compatible boards
@@ -9,16 +10,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 32dd8a857b6b4268486044f58a875fb4bada0753..03f98b0287c89a87abae0c293a0834875e973f02 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/daqboard2000.c
  * hardware driver for IOtech DAQboard/2000
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se>
- *
- * 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.
  */
 /*
  * Driver: daqboard2000
index 3d8fc6ad44df2891b5d12336cde17107c2a04da9..327ecf9aea3080cd82ab9242441deb4f33a02697 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/das08.c
  * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers)
@@ -6,16 +7,6 @@
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
  * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
  * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index d27044cb7158175f55063dfb71449f6c4d8540e6..235d32f7c817c6249012b32732a78062b88976ff 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * das08.h
  *
  * Header for common DAS08 support (used by ISA/PCI/PCMCIA drivers)
  *
  * Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _DAS08_H
index 317a9b5e4a3b16537bd460cbb0c6e0dfc2b09b52..223479f9ea3cffe67aaf3c69f5bf61996b6a4a74 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for DAS008 PCMCIA boards
  *
@@ -5,16 +6,6 @@
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
  * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * PCMCIA support code for this driver is adapted from the dummy_cs.c
  * driver of the Linux PCMCIA Card Services package.
  *
index cdefc99b6db30e183e69d6b5b8c87cc3694ab7f8..b22a45bd21d1042d72c6c6a2dd2f4a949b8431c9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  das08_isa.c
  *  comedi driver for DAS08 ISA/PC-104 boards
@@ -6,16 +7,6 @@
  *  Copyright (C) 2000 David A. Schleef <ds@schleef.org>
  *  Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
  *  Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
  */
 
 /*
index d8d27fa4449133720189cf1e681877d571f9b968..7856fc13466a181ad84a21623d638c4d4b199679 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  das08_pci.c
  *  comedi driver for DAS08 PCI boards
@@ -6,16 +7,6 @@
  *  Copyright (C) 2000 David A. Schleef <ds@schleef.org>
  *  Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
  *  Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
  */
 
 /*
index ddd4aeab63650f1d610f794c1d7cc310bf655b43..74ff204b585d413a5cbb03d4c33dc638f1fa47c4 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * das16.c
  * DAS16 driver
@@ -6,16 +7,6 @@
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
  * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
  * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index bb8d6ec0632ef7043845417d975b273a2bd5c227..72f8ed2c5008a5f1fd435f62fe8023b8137d0cf9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for CIO-DAS16/M1
  * Author: Frank Mori Hess, based on code from the das16 driver.
@@ -5,16 +6,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index e0a34c2687a8becd8bd6531f2c98cd7f24419e24..f16aa7e9f4f3ad00ccd9d410e6165ca662ec584b 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for Keithley DAS-1700/DAS-1800 series boards
  * Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 0fdf5e02182fb3459f3eea3bbbce50ff4c1419c3..f99211ec46debd7476c2c1cdffac11f64f9f72be 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * das6402.c
  * Comedi driver for DAS6402 compatible boards
@@ -5,16 +6,6 @@
  *
  * Rewrite of an experimental driver by:
  * Copyright (C) 1999 Oystein Svendsen <svendsen@pvv.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index fd4cb4911671ce1fa145a57473d3b0ba90bea34d..8cf09ef3012fa5923c9978fbce0fcae6a094b7a0 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/das800.c
  * Driver for Keitley das800 series boards and compatibles
@@ -5,16 +6,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 /*
  * Driver: das800
index 771cceb710697ab105c14f94b50d11a8d8e1ae34..75693cdde31384ea9aeab58bc289cd73865dd9d6 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * dmm32at.c
  * Diamond Systems Diamond-MM-32-AT Comedi driver
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 30805797a957ebbc323737368c7573581ec130c7..a29880981d81d1ef47d408c4f8888308aec25067 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * comedi/drivers/dt2801.c
  * Device Driver for DataTranslation DT2801
index fcd85475e4294a6c49e96d93a6738a1408407fbf..05207a519755d8576742bcd878ab713ffa7b4c40 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for Data Translation DT2811
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
@@ -316,7 +307,7 @@ static int dt2811_ai_cmd(struct comedi_device *dev,
 static unsigned int dt2811_ns_to_timer(unsigned int *nanosec,
                                       unsigned int flags)
 {
-       unsigned long long ns = *nanosec;
+       unsigned long long ns;
        unsigned int ns_lo = COMEDI_MIN_SPEED;
        unsigned int ns_hi = 0;
        unsigned int divisor_hi = 0;
index 09984a66dba3a40cdb2580003ef008a3de5264ca..d2c71573736144ea1cec4745041de66833d68277 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/dt2814.c
  * Hardware driver for Data Translation DT2814
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 /*
  * Driver: dt2814
index ce557197119454f41bf2005f4731edda3d59cdb4..83026ba63d1cc57a5fb0c727b72c22b2791e4f08 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/dt2815.c
  * Hardware driver for Data Translation DT2815
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se>
- *
- * 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.
  */
 /*
  * Driver: dt2815
index 39d2566e49bf1b05123f958f1a377c88437e0c81..9babb2a5196a393cbfeec09091ea0d589cf98e26 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/dt2817.c
  * Hardware driver for Data Translation DT2817
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 /*
  * Driver: dt2817
index 217a4b884689c436e883fafcd96512a730fa6b89..3be927f1d3a92694faf94dc664f3c8bb829ba804 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * dt282x.c
  * Comedi driver for Data Translation DT2821 series
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 19e0b7be8495fe7d6c70fe3ce616abcf938caa69..2edf3ee91300007c4dff503774bca1f2fe04b57b 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * dt3000.c
  * Data Translation DT3000 series driver
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 7ebca862ecaa3204224b678a47ddf613806b4786..75cc9e8e5b94b1f4b14bc86ba310579668278c22 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/dt9812.c
  *   COMEDI driver for DataTranslation DT9812 USB module
@@ -5,16 +6,6 @@
  * Copyright (C) 2005 Anders Blomdell <anders.blomdell@control.lth.se>
  *
  * COMEDI - Linux Control and Measurement Device Interface
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; 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.
  */
 
 /*
index bab7ac9e62370cd2da331f7f4826696bd316fe37..e50536731d11d71bb71d66e0d34d5b1ae1d2b4d2 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/dyna_pci10xx.c
  * Copyright (C) 2011 Prashant Shah, pshah.mumbai@gmail.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
  */
 
 /*
index 0f278ffdad76b70294d91089b7aebc5db3c733ee..41c50c7a8f59b355f1e40585047f35ec808a4dc7 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * fl512.c
  * Anders Gnistrup <ex18@kalman.iau.dtu.dk>
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index e5b948405fd9c78ddf47f7f62b087dc802dbef25..4bdf44d8287996fb9a07af330316744078cb0eb0 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * gsc_hpdi.c
  * Comedi driver the General Standards Corporation
@@ -8,16 +9,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 28cf53e48b8d88a68b610f002dab6009a6ef3100..b14aaed6b5254b48fe6e3594832bece4bf53c141 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * icp_multi.c
  * Comedi driver for Inova ICP_MULTI board
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 77e1d891f23218fc53615c41df221c714dee8905..3eaf7c59de75f8a74d44df34f40c18b534536a88 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * ii_pci20kc.c
  * Driver for Intelligent Instruments PCI-20001C carrier board and modules.
index cbff3b41bb45914150079feb2f6f5aed3d73cda9..201f4f96c182b8ed58c38c41dc51bdc5a726a17f 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/jr3_pci.c
  * hardware driver for JR3/PCI force sensor board
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2007 Anders Blomdell <anders.blomdell@control.lth.se>
- *
- * 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.
  */
 /*
  * Driver: jr3_pci
index 93198abf0ee54293ca3098948cb5d64324ae6ef0..e612cf605700776c066dbf9d74eab0f72b7e1788 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * ke_counter.c
  * Comedi driver for Kolter-Electronic PCI Counter 1 Card
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 15a53204a36a5a579745e2ea78c5339289911f05..ee53571a89698857579daadef13dcce1465fc0c1 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * me4000.c
  * Source code for the Meilhaus ME-4000 board family.
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index c0b7a300e4288940c692eb2f96f56e073f190e19..169742be17b86f345afb3e4a5af8dce34937dfe1 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/me_daq.c
  * Hardware driver for Meilhaus data acquisition cards:
  *   ME-2000i, ME-2600i, ME-3000vm1
  *
  * Copyright (C) 2002 Michael Hillmann <hillmann@syscongroup.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index fbdf181d8ccccc228c131346a9e9ec9dc403d11b..ea430237efa7f6a1233ff589b0e03ef466e1c40d 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  comedi/drivers/mf6x4.c
  *  Driver for Humusoft MF634 and MF624 Data acquisition cards
  *
  *  COMEDI - Linux Control and Measurement Device Interface
  *  Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
  */
 /*
  * Driver: mf6x4
index 05126ba4ba51bd804fc5f91413acbe8c7c6fd590..61e03ad8412300ddbcf762f86bc9db1288d09402 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/mite.c
  * Hardware driver for NI Mite PCI interface chip
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 02a627d3969dc6003701c5594ede1de236950a5c..d5e27ac25df848f873603e5420fc81fcb6803a1e 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * module/mite.h
  * Hardware driver for NI Mite PCI interface chip
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _MITE_H_
index 9bda761433c2b5065850af066bb6b8014433ce83..bf3a3a08c7ab89fc581afeac5c5064b58768cefc 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * mpc624.c
  * Hardware driver for a Micro/sys inc. MPC-624 PC/104 board
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index b5a26f7b4332857513e599164e018bf0e13ef08a..c85c9ab3655fd55ad752b40a0438ee4eacba3d45 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * multiq3.c
  * Hardware driver for Quanser Consulting MultiQ-3 board
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se>
- *
- * 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.
  */
 
 /*
index 84c62e25609435493838b85139b45867e5c7aaca..4d1eccb5041dc45a04f9179e5a47e8e5364e4eae 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * ni_6527.c
  * Comedi driver for National Instruments PCI-6527
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 07f38e38546911c06981745120d980213eec3a83..996074e471d3648106723a0b69682523f87f3217 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * ni_65xx.c
  * Comedi driver for National Instruments PCI-65xx static dio boards
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 6aa755ad395399ed659a5cbe9f60a3362d2e52e8..e521ed9d0887043bc5e4711e02c1c1f0b0d8d29f 100644 (file)
@@ -1,15 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Hardware driver for NI 660x devices
- *
- * 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.
  */
 
 /*
index 1d3ff60efcb8c614930e493d95e5891e4e2b78bd..4e4ae31c8d0b8b43e9c56ea0022971148a92f7f3 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for NI 670x devices
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index c69cd676f357c790d689a070cc91111c905cd818..76e8d047f71eacdbd7225fde107927b1440fa974 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for National Instruments AT-A2150 boards
  * Copyright (C) 2001, 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 158fa29374fc56f872366fbeb1c6dc74c71cd39d..aad0b295ee2b2e1fbdd20986f033eca41a58c714 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * ni_at_ao.c
  * Driver for NI AT-AO-6/10 boards
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000,2002 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index ae6ed96d7874c4ce34d7ce3574b9eded74dbb625..b9e9ab548c4b48d79bec52d28f2d89297f00b50b 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for NI AT-MIO E series cards
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index fb59b0ffbba6660bb7922fb00bbbe4ba80114174..68ad9676f9623a8c8b6d07bba8373378ca173b47 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for National Instruments AT-MIO16D board
  * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.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.
  */
 
 /*
index 8f6396edd21ce04cb06b8d8dc79a0a86bd10c691..b9e525b9beb9478bd0701a79a3d7fe3b5807a89d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *     comedi/drivers/ni_daq_700.c
  *     Driver for DAQCard-700 DIO/AI
@@ -5,16 +6,6 @@
  *
  *     COMEDI - Linux Control and Measurement Device Interface
  *     Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
  */
 
 /*
index 733d3fbafa4d83f6dcf70ddd7d8d7c5abd73a3e0..44fb65afc218b92b750a6f5cacee059ffa72f474 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for National Instruments PCMCIA DAQ-Card DIO-24
  * Copyright (C) 2002 Daniel Vecino Castel <dvecino@able.es>
@@ -7,16 +8,6 @@
  * The initial developer of the pcmcia dummy_cs.c code is David A. Hinds
  * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 51e5e942b442975daf4abcb33956289672207a47..c6cf37ccbc920a171222de00dfe418f57b0643a4 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/ni_labpc.c
  * Driver for National Instruments Lab-PC series boards and compatibles
  * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index c2edadc7b3c6d7210d9ec9856232d77542fa8886..f685047efb6764d6755ce72af7177bfddb8b11f5 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Header for ni_labpc ISA/PCMCIA/PCI drivers
  *
  * Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _NI_LABPC_H
index b0dfb8eed16dcc0211cfb135737f760fc2be8ebd..7fa2d39562dbf7ec6ffe04d7e93e405a26eb433a 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/ni_labpc_common.c
  *
  * Common support code for "ni_labpc", "ni_labpc_pci" and "ni_labpc_cs".
  *
  * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index 3d4d0b9ad4e157485de8a6d165a3d648051fb4eb..4f7e2fe212548c548d3205bf7ea5e2f17176c58a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Driver for National Instruments daqcard-1200 boards
  * Copyright (C) 2001, 2002, 2003 Frank Mori Hess <fmhess@users.sourceforge.net>
@@ -7,16 +8,6 @@
  * The initial developer of the pcmcia dummy_cs.c code is David A. Hinds
  * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.
- *
- * 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
- * General Public License for more details.
  */
 
 /*
index 29dbdf5ec25dfb37d4de072946d8d6d878543af8..5657736a94082b9c585b66e20720f57b7d821a0a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/ni_labpc_isadma.c
  * ISA DMA support for National Instruments Lab-PC series boards and
@@ -5,16 +6,6 @@
  *
  * Extracted from ni_labpc.c:
  * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index cac089193121c922b72fc8c119c93025bf0cb814..d7d5a797355826929a5630c2cc31eee0e0d85660 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/ni_labpc_pci.c
  * Driver for National Instruments Lab-PC PCI-1200
  * Copyright (C) 2001, 2002, 2003 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 398347fedc476b3f186cbc38f4eb76271874b216..5d610af6799f6d64a1516c2d942b4b80cb9282a6 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Hardware driver for DAQ-STC based boards
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
  * Copyright (C) 2002-2006 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 21f82317935627dadcb7c7e658ab878be5a9b1bb..4f37b4e58f09e83bc887ec5fb06d19d0821e5549 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for NI PCMCIA MIO E series cards
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index b27345abebe1b75ba21f2236c5a84f4e0f1fc548..6692af5ff79bf1b5f3119c7d2111da96517bdca9 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for National Instruments PCI-DIO-32HS
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 3a96913c025e78972dbdeae5e192a79c3748a88b..f9e466d18b3fcb14d4ed7f58742c887f17b01752 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Comedi driver for NI PCI-MIO E series cards
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 61138e86a455ff657acd554023351b58545fbcbd..cb9d4c3a1926606de04455c7855ce380e158cb0e 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Register descriptions for NI DAQ-STC chip
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998-9 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 15cb4088467bc782e505dbf2723819f699698c9f..ef919b21b7d98bd6282dfc32517e9d54b8f946cd 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Support for NI general purpose counters
  *
  * Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 2012033414d3f7b0005e2e50e5db84ad431f1192..23221cead8ca0cca92bc8912d74b3aa2b9961730 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Header file for NI general purpose counter support code (ni_tio.c)
  *
  * COMEDI - Linux Control and Measurement Device Interface
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; 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 _COMEDI_NI_TIO_H
index 4e024eb5656b38e734c1c12be2108236f4d5d6b1..f4d99d78208ad0850b6c03a8d5b9c1019edc47f7 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Header file for NI general purpose counter support code (ni_tio.c and
  * ni_tiocmd.c)
  *
  * COMEDI - Linux Control and Measurement Device Interface
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; 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 _COMEDI_NI_TIO_INTERNAL_H
index 9007c57544bf4f69d92c8dac8abfc0a0df4aedd6..050bee0b9515672ae4d5daec15dd155ab22e0b8e 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Command support for NI general purpose counters
  *
  * Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 9a0a96329a55083f158b59110fb2244272400dd3..808ed92ed66fe4bedfbbba500452d86771e8162e 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/ni_usb6501.c
  * Comedi driver for National Instruments USB-6501
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2014 Luca Ellero <luca.ellero@brickedbrain.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.
  */
 
 /*
index 3774daa9d6615f6f2d70a079b1877d25497e3028..a5937206bf1cd914116af7aad9f9a8cdbd4dafae 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * pcl711.c
  * Comedi driver for PC-LabCard PCL-711 and AdSys ACL-8112 and compatibles
@@ -7,16 +8,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 74b07e1744c72c115a6350ddbb927655e33bc1b8..9c174f1f2fcf56487d982122cc40a311732cce52 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * pcl724.c
  * Comedi driver for 8255 based ISA and PC/104 DIO boards
index 256850ccb6fa21d09389ed3ae341171716fb633c..0963d85873a9e3f61fc109b4316464c6eb3019ce 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * pcl726.c
  * Comedi driver for 6/12-Channel D/A Output and DIO cards
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index ce958eef2a6197c97ea2cebc9bd19aab04cffa89..3d1e9150e5b53188a85a9b4f49b49a1123d37c8b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * comedi/drivers/pcl730.c
  * Driver for Advantech PCL-730 and clones
index 9c75065dd26a34ca4e4cce0fd8ba899a2fb58222..aefc1b849cf79db883753f2e0efc9e9cb171d0f2 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * comedi/drivers/pcl812.c
  *
index c00a71f538efc14364ddb757c67f816580f4a694..d722079f3327cc691250ca623976cb7f974b7d39 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * pcl816.c
  * Comedi driver for Advantech PCL-816 cards
index 5b5df0596ad982c9077100b436fcb143cba60982..eebb49751713bc0bf3b74063d1bcec5b42b1fc48 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * comedi/drivers/pcl818.c
  *
index 588ae5ecec66e08067aa4bb4fe7308ccd68a6feb..5779e005c0cb063a49c4ba43956828e07562f6cd 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * pcm3724.c
  * Comedi driver for Advantech PCM-3724 Digital I/O board
index 12f94fe82f5b53272c30e1d8ea10f5df45c072cf..fe5449bb17160e88810be7c20a317fb2718887b8 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * pcmad.c
  * Hardware driver for Winsystems PCM-A/D12 and PCM-A/D16
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000,2001 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index d86c5e2cd0c7e1920f29905e96bffe4a0563cef1..33e463b193a164465f60715967ae34520b88fc17 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * pcmda12.c
  * Driver for Winsystems PC-104 based PCM-D/A-12 8-channel AO board.
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2006 Calin A. Culianu <calin@ajvar.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 70ad497dd20b8ce7bd08d88d5e56e5f2cf37b215..72af1776f785de0d8916a5354c7d125f142b9592 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * pcmmio.c
  * Driver for Winsystems PC-104 based multifunction IO board.
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2007 Calin A. Culianu <calin@ajvar.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 8ad64f2625fe48eb6642143956501657ba00e9ac..743fb226e2e4ba3303981f1e23215bfeb14d3f1e 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * pcmuio.c
  * Comedi driver for Winsystems PC-104 based 48/96-channel DIO boards.
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2006 Calin A. Culianu <calin@ajvar.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 2892e65289678c20252daefdd69bf5ac00a0bb27..7950d1f57db6d304f4b0e60cde98828f8925ccc2 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Definitions for the PLX-9052 PCI interface chip
  *
@@ -5,16 +6,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _PLX9052_H_
index e23e63a097b512582d8f5225f0911de221c91ff3..469a9573acdc4c012fd99b06a9c9af8af7a972c4 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * plx9080.h
  *
@@ -9,11 +10,6 @@
  * Written by Krzysztof Halasa <khc@rgstudio.com.pl>
  *
  * Portions (C) SBE Inc., used by permission.
- *
- * 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 __COMEDI_PLX9080_H
index e00e9c6268aef7d3d2999cc91259c3a849a1814f..bb400e08f0bc7337a8d27f43f4ef04a528d042a7 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/rtd520.c
  * Comedi driver for Real Time Devices (RTD) PCI4520/DM7520
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2001 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
  */
 
 /*
index cd61d2645af452f31e314c8232554499bed189ab..f7c320c89ee6ab4fcf068deb24349bb697a25bd4 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/rti800.c
  * Hardware driver for Analog Devices RTI-800/815 board
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 6db58fcfd496bbf2b53958d687a2fa2d7180c03b..c6cf92bfff73f8abfece791192c8dfc80fb5ce46 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * rti802.c
  * Comedi driver for Analog Devices RTI-802 board
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se>
- *
- * 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.
  */
 
 /*
index e226275972c0d5cf4a467dbadb65854c0d6b26bf..5d567ae78f28e86943ea49efc7cb78ef119542ce 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * s526.c
  * Sensoray s526 Comedi driver
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index c906c9a5d944cc9bf2175fa3dab859a7b799283e..0b3cfe934e14a679d64d2d96da03063074378341 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/s626.c
  * Sensoray s626 Comedi driver
@@ -7,16 +8,6 @@
  *
  * Based on Sensoray Model 626 Linux driver Version 0.2
  * Copyright (C) 2002-2004 Sensoray Co., Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
  */
 
 /*
@@ -1385,8 +1376,7 @@ static void s626_reset_adc(struct comedi_device *dev, u8 *ppl)
                jmp_adrs =
                        (u32)devpriv->rps_buf.physical_base +
                        (u32)((unsigned long)rps -
-                                  (unsigned long)devpriv->
-                                                 rps_buf.logical_base);
+                             (unsigned long)devpriv->rps_buf.logical_base);
                for (i = 0; i < (10 * S626_RPSCLK_PER_US / 2); i++) {
                        jmp_adrs += 8;  /* Repeat to implement time delay: */
                        /* Jump to next RPS instruction. */
@@ -1903,9 +1893,9 @@ static int s626_ai_cmdtest(struct comedi_device *dev,
 
                if (cmd->scan_begin_src == TRIG_TIMER) {
                        arg = cmd->convert_arg * cmd->scan_end_arg;
-                       err |= comedi_check_trigger_arg_min(&cmd->
-                                                           scan_begin_arg,
-                                                           arg);
+                       err |= comedi_check_trigger_arg_min(
+                               &cmd->scan_begin_arg,
+                               arg);
                }
        }
 
index 4cef4526326712c22694809ac8b8326ce70f1b87..4bdc4fba736f831cd3197168803ff90d7d13792a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/drivers/s626.h
  * Sensoray s626 Comedi driver, header file
@@ -7,16 +8,6 @@
  *
  * Based on Sensoray Model 626 Linux driver Version 0.2
  * Copyright (C) 2002-2004 Sensoray Co., Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 S626_H_INCLUDED
index a557be8a507631619ff8ab571e4f5e7cdf9dd4e9..ab69eeb2c1f18d5eded92a1e956c5a449922d34f 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * serial2002.c
  * Comedi driver for serial connected hardware
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2002 Anders Blomdell <anders.blomdell@control.lth.se>
- *
- * 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.
  */
 
 /*
@@ -107,6 +98,7 @@ static long serial2002_tty_ioctl(struct file *f, unsigned int op,
 static int serial2002_tty_write(struct file *f, unsigned char *buf, int count)
 {
        loff_t pos = 0;
+
        return kernel_write(f, buf, count, &pos);
 }
 
index f9f634fd53cf86fce12ee2fbece4481cdbd74bdd..0628060e42cafa777af3ccc2b7b9e43d20b463ee 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * ssv_dnp.c
  * generic comedi driver for SSV Embedded Systems' DIL/Net-PCs
@@ -5,16 +6,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index f4f05d29d30d6de689892e9e6e449952bfc675ee..de177418190f54b1b7c8679ab3d60884be62a6fe 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * usbdux.c
  * Copyright (C) 2003-2014 Bernd Porr, mail@berndporr.me.uk
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This 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.
  */
 
 /*
@@ -809,7 +800,6 @@ static int usbdux_ao_insn_write(struct comedi_device *dev,
 {
        struct usbdux_private *devpriv = dev->private;
        unsigned int chan = CR_CHAN(insn->chanspec);
-       unsigned int val = s->readback[chan];
        __le16 *p = (__le16 *)&devpriv->dux_commands[2];
        int ret = -EBUSY;
        int i;
@@ -825,7 +815,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev,
        devpriv->dux_commands[4] = chan << 6;
 
        for (i = 0; i < insn->n; i++) {
-               val = data[i];
+               unsigned int val = data[i];
 
                /* one 16 bit value */
                *p = cpu_to_le16(val);
index 608403c7586b767e4bb264300dc216d1fa0d785a..e18c0723b760c80763e235489c32e1c98c4639fb 100644 (file)
@@ -1,15 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Copyright (C) 2004-2014 Bernd Porr, mail@berndporr.me.uk
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This 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.
  */
 
 /*
index 456e9f13becb828a5da171d318d7cf466d20fa77..af5605a875e2c3aeeafe1a32fdfc01b83043ee9b 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * usbduxsigma.c
  * Copyright (C) 2011-2015 Bernd Porr, mail@berndporr.me.uk
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This 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.
  */
 
 /*
index a004aed0147a526fa3732d1d8718be3e2957ef10..6234b649d887ccb3abac4c73dcb38aa095768600 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * vmk80xx.c
  * Velleman USB Board Low-Level Driver
@@ -6,16 +7,6 @@
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index 55d43c076b1cc581cca3776b5d41a60e328dad27..df9bba1b69eded250eaea794e7a2bb4d0e6547ed 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * kcomedilib/kcomedilib.c
  * a comedlib interface for kernel modules
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
index 2644dd4d6143bb65ac5c55031f000946f847dadc..50d38938ac6f2e112ed53065259e8ed021270b51 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * /proc interface for comedi
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
index ce3a58a7a1713b7d32c43fc50ce7c0045980ccbf..89d599877445b498946789a3afed6ecc09d18910 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * comedi/range.c
  * comedi routines for voltage ranges
  *
  * COMEDI - Linux Control and Measurement Device Interface
  * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/uaccess.h>
index 40ff0d0076957c89350106302e02fae3f3a6c31b..49633042fcc9967672124c8a372690c386c7b656 100644 (file)
@@ -1,5 +1,4 @@
 obj-$(CONFIG_DGNC) += dgnc.o
 
 dgnc-objs :=   dgnc_cls.o dgnc_driver.o\
-               dgnc_mgmt.o dgnc_neo.o\
-               dgnc_tty.o dgnc_utils.o
+               dgnc_tty.o
index 9639035fddd169ae3377ab877163269baf11f3c2..7e6cbfe4e4ee10f66134952037ceaa50b966418f 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2003 Digi International (www.digi.com)
  *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
@@ -397,7 +388,7 @@ static void cls_assert_modem_signals(struct channel_t *ch)
        writeb(out, &ch->ch_cls_uart->mcr);
 
        /* Give time for the UART to actually drop the signals */
-       udelay(10);
+       usleep_range(10, 20);
 }
 
 static void cls_copy_data_from_queue_to_uart(struct channel_t *ch)
@@ -1123,30 +1114,6 @@ static void cls_send_immediate_char(struct channel_t *ch, unsigned char c)
        writeb(c, &ch->ch_cls_uart->txrx);
 }
 
-static void cls_vpd(struct dgnc_board *brd)
-{
-       ulong           vpdbase;        /* Start of io base of the card */
-       u8 __iomem           *re_map_vpdbase;/* Remapped memory of the card */
-       int i = 0;
-
-       vpdbase = pci_resource_start(brd->pdev, 3);
-       if (!vpdbase)
-               return;
-
-       re_map_vpdbase = ioremap(vpdbase, 0x400);
-
-       if (!re_map_vpdbase)
-               return;
-
-       for (i = 0; i < 0x40; i++) {
-               brd->vpd[i] = readb(re_map_vpdbase + i);
-               pr_info("%x ", brd->vpd[i]);
-       }
-       pr_info("\n");
-
-       iounmap(re_map_vpdbase);
-}
-
 struct board_ops dgnc_cls_ops = {
        .tasklet =                      cls_tasklet,
        .intr =                         cls_intr,
@@ -1154,7 +1121,6 @@ struct board_ops dgnc_cls_ops = {
        .uart_off =                     cls_uart_off,
        .drain =                        cls_drain,
        .param =                        cls_param,
-       .vpd =                          cls_vpd,
        .assert_modem_signals =         cls_assert_modem_signals,
        .flush_uart_write =             cls_flush_uart_write,
        .flush_uart_read =              cls_flush_uart_read,
index 9dfa9682a8973ef72e5443363b2b354098a911ff..d31508542261667877b54f18d0be3c6408c0807b 100644 (file)
@@ -1,16 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright 2003 Digi International (www.digi.com)
  *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
  */
 
 #ifndef _DGNC_CLS_H
index d9bf5da1b8e58ef25f1a007392022fd0ff8a2ecb..5d8c2d995dccebea55d96d9fa39ae067d2f78ddb 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2003 Digi International (www.digi.com)
  *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include "dgnc_driver.h"
-#include "dgnc_pci.h"
-#include "dgnc_mgmt.h"
 #include "dgnc_tty.h"
 #include "dgnc_cls.h"
-#include "dgnc_neo.h"
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Digi International, http://www.digi.com");
 MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line");
 MODULE_SUPPORTED_DEVICE("dgnc");
 
-static const struct file_operations dgnc_board_fops = {
-       .owner          =       THIS_MODULE,
-       .unlocked_ioctl =       dgnc_mgmt_ioctl,
-       .open           =       dgnc_mgmt_open,
-       .release        =       dgnc_mgmt_close
-};
-
-uint                   dgnc_num_boards;
+static unsigned int dgnc_num_boards;
 struct dgnc_board              *dgnc_board[MAXBOARDS];
-DEFINE_SPINLOCK(dgnc_global_lock);
-DEFINE_SPINLOCK(dgnc_poll_lock); /* Poll scheduling lock */
-uint                   dgnc_major;
-int                    dgnc_poll_tick = 20;    /* Poll interval - 20 ms */
-
-static struct class *dgnc_class;
+static DEFINE_SPINLOCK(dgnc_poll_lock); /* Poll scheduling lock */
 
+static int             dgnc_poll_tick = 20;    /* Poll interval - 20 ms */
 static ulong           dgnc_poll_time; /* Time of next poll */
 static uint            dgnc_poll_stop; /* Used to tell poller to stop */
 static struct timer_list dgnc_poll_timer;
 
+#define DIGI_VID                               0x114F
+#define PCI_DEVICE_CLASSIC_4_DID               0x0028
+#define PCI_DEVICE_CLASSIC_8_DID               0x0029
+#define PCI_DEVICE_CLASSIC_4_422_DID           0x00D0
+#define PCI_DEVICE_CLASSIC_8_422_DID           0x00D1
+
+#define PCI_DEVICE_CLASSIC_4_PCI_NAME          "ClassicBoard 4 PCI"
+#define PCI_DEVICE_CLASSIC_8_PCI_NAME          "ClassicBoard 8 PCI"
+#define PCI_DEVICE_CLASSIC_4_422_PCI_NAME      "ClassicBoard 4 422 PCI"
+#define PCI_DEVICE_CLASSIC_8_422_PCI_NAME      "ClassicBoard 8 422 PCI"
+
 static const struct pci_device_id dgnc_pci_tbl[] = {
        {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_4_DID),     .driver_data = 0},
        {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_4_422_DID), .driver_data = 1},
@@ -70,19 +58,6 @@ static const struct board_id dgnc_ids[] = {
        {       PCI_DEVICE_CLASSIC_4_422_PCI_NAME,      4,      0       },
        {       PCI_DEVICE_CLASSIC_8_PCI_NAME,          8,      0       },
        {       PCI_DEVICE_CLASSIC_8_422_PCI_NAME,      8,      0       },
-       {       PCI_DEVICE_NEO_4_PCI_NAME,              4,      0       },
-       {       PCI_DEVICE_NEO_8_PCI_NAME,              8,      0       },
-       {       PCI_DEVICE_NEO_2DB9_PCI_NAME,           2,      0       },
-       {       PCI_DEVICE_NEO_2DB9PRI_PCI_NAME,        2,      0       },
-       {       PCI_DEVICE_NEO_2RJ45_PCI_NAME,          2,      0       },
-       {       PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME,       2,      0       },
-       {       PCI_DEVICE_NEO_1_422_PCI_NAME,          1,      0       },
-       {       PCI_DEVICE_NEO_1_422_485_PCI_NAME,      1,      0       },
-       {       PCI_DEVICE_NEO_2_422_485_PCI_NAME,      2,      0       },
-       {       PCI_DEVICE_NEO_EXPRESS_8_PCI_NAME,      8,      1       },
-       {       PCI_DEVICE_NEO_EXPRESS_4_PCI_NAME,      4,      1       },
-       {       PCI_DEVICE_NEO_EXPRESS_4RJ45_PCI_NAME,  4,      1       },
-       {       PCI_DEVICE_NEO_EXPRESS_8RJ45_PCI_NAME,  8,      1       },
        {       NULL,                                   0,      0       }
 };
 
@@ -101,7 +76,6 @@ static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id)
 {
        struct dgnc_board *brd;
        unsigned int pci_irq;
-       int i = 0;
        int rc = 0;
 
        brd = kzalloc(sizeof(*brd), GFP_KERNEL);
@@ -110,16 +84,10 @@ static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id)
 
        /* store the info for the board we've found */
        brd->boardnum = dgnc_num_boards;
-       brd->vendor = dgnc_pci_tbl[id].vendor;
        brd->device = dgnc_pci_tbl[id].device;
        brd->pdev = pdev;
-       brd->pci_bus = pdev->bus->number;
-       brd->pci_slot = PCI_SLOT(pdev->devfn);
        brd->name = dgnc_ids[id].name;
        brd->maxports = dgnc_ids[id].maxports;
-       if (dgnc_ids[i].is_pci_express)
-               brd->bd_flags |= BD_IS_PCI_EXPRESS;
-       brd->dpastatus = BD_NOFEP;
        init_waitqueue_head(&brd->state_wait);
 
        spin_lock_init(&brd->bd_lock);
@@ -127,11 +95,6 @@ static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id)
 
        brd->state              = BOARD_FOUND;
 
-       /* store which card & revision we have */
-       pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
-       pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
-
        pci_irq = pdev->irq;
        brd->irq = pci_irq;
 
@@ -140,9 +103,6 @@ static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id)
        case PCI_DEVICE_CLASSIC_8_DID:
        case PCI_DEVICE_CLASSIC_4_422_DID:
        case PCI_DEVICE_CLASSIC_8_422_DID:
-
-               brd->dpatype = T_CLASSIC | T_PCIBUS;
-
                /*
                 * For PCI ClassicBoards
                 * PCI Local Address (i.e. "resource" number) space
@@ -182,9 +142,6 @@ static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id)
                if (rc < 0)
                        goto failed;
 
-               /* Get and store the board VPD, if it exists */
-               brd->bd_ops->vpd(brd);
-
                /*
                 * Enable Local Interrupt 1               (0x1),
                 * Local Interrupt 1 Polarity Active high (0x2),
@@ -194,55 +151,6 @@ static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id)
 
                break;
 
-       case PCI_DEVICE_NEO_4_DID:
-       case PCI_DEVICE_NEO_8_DID:
-       case PCI_DEVICE_NEO_2DB9_DID:
-       case PCI_DEVICE_NEO_2DB9PRI_DID:
-       case PCI_DEVICE_NEO_2RJ45_DID:
-       case PCI_DEVICE_NEO_2RJ45PRI_DID:
-       case PCI_DEVICE_NEO_1_422_DID:
-       case PCI_DEVICE_NEO_1_422_485_DID:
-       case PCI_DEVICE_NEO_2_422_485_DID:
-       case PCI_DEVICE_NEO_EXPRESS_8_DID:
-       case PCI_DEVICE_NEO_EXPRESS_4_DID:
-       case PCI_DEVICE_NEO_EXPRESS_4RJ45_DID:
-       case PCI_DEVICE_NEO_EXPRESS_8RJ45_DID:
-
-               /*
-                * This chip is set up 100% when we get to it.
-                * No need to enable global interrupts or anything.
-                */
-               if (brd->bd_flags & BD_IS_PCI_EXPRESS)
-                       brd->dpatype = T_NEO_EXPRESS | T_PCIBUS;
-               else
-                       brd->dpatype = T_NEO | T_PCIBUS;
-
-               brd->membase     = pci_resource_start(pdev, 0);
-               brd->membase_end = pci_resource_end(pdev, 0);
-
-               if (brd->membase & 1)
-                       brd->membase &= ~3;
-               else
-                       brd->membase &= ~15;
-
-               brd->bd_ops = &dgnc_neo_ops;
-
-               brd->bd_uart_offset = 0x200;
-               brd->bd_dividend = 921600;
-
-               rc = dgnc_do_remap(brd);
-
-               if (rc < 0)
-                       goto failed;
-
-               /* Read and store the dvid after remapping */
-               brd->dvid = readb(brd->re_map_membase + 0x8D);
-
-               /* Get and store the board VPD, if it exists */
-               brd->bd_ops->vpd(brd);
-
-               break;
-
        default:
                dev_err(&brd->pdev->dev,
                        "Didn't find any compatible Neo/Classic PCI boards.\n");
@@ -273,7 +181,6 @@ static int dgnc_request_irq(struct dgnc_board *brd)
                        dev_err(&brd->pdev->dev,
                                "Failed to hook IRQ %d\n", brd->irq);
                        brd->state = BOARD_FAILED;
-                       brd->dpastatus = BD_NOFEP;
                        return -ENODEV;
                }
        }
@@ -364,7 +271,6 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        brd->state = BOARD_READY;
-       brd->dpastatus = BD_RUNNING;
 
        dgnc_board[dgnc_num_boards++] = brd;
 
@@ -388,32 +294,7 @@ static struct pci_driver dgnc_driver = {
 
 static int dgnc_start(void)
 {
-       int rc = 0;
        unsigned long flags;
-       struct device *dev;
-
-       rc = register_chrdev(0, "dgnc", &dgnc_board_fops);
-       if (rc < 0) {
-               pr_err(DRVSTR ": Can't register dgnc driver device (%d)\n", rc);
-               return rc;
-       }
-       dgnc_major = rc;
-
-       dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt");
-       if (IS_ERR(dgnc_class)) {
-               rc = PTR_ERR(dgnc_class);
-               pr_err(DRVSTR ": Can't create dgnc_mgmt class (%d)\n", rc);
-               goto failed_class;
-       }
-
-       dev = device_create(dgnc_class, NULL,
-                           MKDEV(dgnc_major, 0),
-                       NULL, "dgnc_mgmt");
-       if (IS_ERR(dev)) {
-               rc = PTR_ERR(dev);
-               pr_err(DRVSTR ": Can't create device (%d)\n", rc);
-               goto failed_device;
-       }
 
        /* Start the poller */
        spin_lock_irqsave(&dgnc_poll_lock, flags);
@@ -425,13 +306,6 @@ static int dgnc_start(void)
        add_timer(&dgnc_poll_timer);
 
        return 0;
-
-failed_device:
-       class_destroy(dgnc_class);
-failed_class:
-       unregister_chrdev(dgnc_major, "dgnc");
-
-       return rc;
 }
 
 /* Free all the memory associated with a board */
@@ -495,10 +369,6 @@ static void cleanup(void)
        /* Turn off poller right away. */
        del_timer_sync(&dgnc_poll_timer);
 
-       device_destroy(dgnc_class, MKDEV(dgnc_major, 0));
-       class_destroy(dgnc_class);
-       unregister_chrdev(dgnc_major, "dgnc");
-
        for (i = 0; i < dgnc_num_boards; ++i) {
                dgnc_cleanup_tty(dgnc_board[i]);
                dgnc_cleanup_board(dgnc_board[i]);
index efdb11a5e27fb361a369ddb36441d713f0391ea1..b4d9f714c60a3580c2ee41bc2fb2199bb6a48234 100644 (file)
@@ -1,16 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright 2003 Digi International (www.digi.com)
  *      Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
  */
 
 #ifndef _DGNC_DRIVER_H
@@ -82,42 +73,27 @@ struct board_ops {
        void (*uart_off)(struct channel_t *ch);
        int  (*drain)(struct tty_struct *tty, uint seconds);
        void (*param)(struct tty_struct *tty);
-       void (*vpd)(struct dgnc_board *brd);
        void (*assert_modem_signals)(struct channel_t *ch);
        void (*flush_uart_write)(struct channel_t *ch);
        void (*flush_uart_read)(struct channel_t *ch);
        void (*disable_receiver)(struct channel_t *ch);
        void (*enable_receiver)(struct channel_t *ch);
-       void (*send_break)(struct channel_t *ch, int);
+       void (*send_break)(struct channel_t *ch, int msec);
        void (*send_start_character)(struct channel_t *ch);
        void (*send_stop_character)(struct channel_t *ch);
        void (*copy_data_from_queue_to_uart)(struct channel_t *ch);
        uint (*get_uart_bytes_left)(struct channel_t *ch);
-       void (*send_immediate_char)(struct channel_t *ch, unsigned char);
+       void (*send_immediate_char)(struct channel_t *ch, unsigned char c);
 };
 
-/* Device flag definitions for bd_flags. */
-
-#define BD_IS_PCI_EXPRESS     0x0001     /* Is a PCI Express board */
-
 /**
  * struct dgnc_board - Per board information.
  * @boardnum: Board number (0 - 32).
  *
  * @name: Product name.
  * @pdev: Pointer to the pci_dev structure.
- * @bd_flags: Board flags.
- * @vendor: PCI vendor ID.
  * @device: PCI device ID.
- * @subvendor: PCI subsystem vendor ID.
- * @subdevice: PCI subsystem device ID.
- * @rev: PCI revision ID.
- * @pci_bus: PCI bus value.
- * @pci_slot: PCI slot value.
  * @maxports: Maximum ports this board can handle.
- * @dvid: Board specific device ID.
- * @vpd: VPD of this board, if found.
- * @serial_num: Serial number of this board, if found in VPD.
  * @bd_lock: Used to protect board.
  * @bd_intr_lock: Protect poller tasklet and interrupt routine from each other.
  * @state: State of the card.
@@ -135,8 +111,6 @@ struct board_ops {
  * @serial_name: Serial driver name.
  * @print_dirver: Pointer to the print driver.
  * @print_name: Print driver name.
- * @dpatype: Board type as defined by DPA.
- * @dpastatus: Board status as defined by DPA.
  * @bd_dividend: Board/UART's specific dividend.
  * @bd_ops: Pointer to board operations structure.
  */
@@ -144,18 +118,8 @@ struct dgnc_board {
        int             boardnum;
        char            *name;
        struct pci_dev  *pdev;
-       unsigned long   bd_flags;
-       u16             vendor;
        u16             device;
-       u16             subvendor;
-       u16             subdevice;
-       unsigned char   rev;
-       uint            pci_bus;
-       uint            pci_slot;
        uint            maxports;
-       unsigned char   dvid;
-       unsigned char   vpd[128];
-       unsigned char   serial_num[20];
 
        /* used to protect the board */
        spinlock_t      bd_lock;
@@ -189,9 +153,6 @@ struct dgnc_board {
        struct tty_driver *print_driver;
        char            print_name[200];
 
-       u16             dpatype;
-       u16             dpastatus;
-
        uint            bd_dividend;
 
        struct board_ops *bd_ops;
@@ -285,7 +246,6 @@ struct un_t {
  * @ch_wopen: Waiting for open process count.
  * @ch_mostat: FEP output modem status.
  * @ch_mistat: FEP input modem status.
- * @chc_neo_uart: Pointer to the mapped neo UART struct
  * @ch_cls_uart:  Pointer to the mapped cls UART struct
  * @ch_cached_lsr: Cached value of the LSR register.
  * @ch_rqueue: Read queue buffer, malloc'ed.
@@ -344,7 +304,6 @@ struct channel_t {
        unsigned char   ch_mostat;
        unsigned char   ch_mistat;
 
-       struct neo_uart_struct __iomem *ch_neo_uart;
        struct cls_uart_struct __iomem *ch_cls_uart;
 
        unsigned char   ch_cached_lsr;
@@ -381,11 +340,6 @@ struct channel_t {
        ulong           ch_xoff_sends;
 };
 
-extern uint            dgnc_major;             /* Our driver/mgmt major */
-extern int             dgnc_poll_tick;         /* Poll interval - 20 ms */
-extern spinlock_t      dgnc_global_lock;       /* Driver global spinlock */
-extern spinlock_t      dgnc_poll_lock;         /* Poll scheduling lock */
-extern uint            dgnc_num_boards;        /* Total number of boards */
 extern struct dgnc_board *dgnc_board[MAXBOARDS];/* Array of boards */
 
 #endif /* _DGNC_DRIVER_H */
diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c
deleted file mode 100644 (file)
index 3ca473b..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
- */
-
-/*
- * This file implements the mgmt functionality for the
- * Neo and ClassicBoard based product lines.
- */
-
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/serial_reg.h>
-#include <linux/termios.h>
-#include <linux/uaccess.h>
-
-#include "dgnc_driver.h"
-#include "dgnc_pci.h"
-#include "dgnc_mgmt.h"
-
-/* Our "in use" variables, to enforce 1 open only */
-static int dgnc_mgmt_in_use[MAXMGMTDEVICES];
-
-/**
- * dgnc_mgmt_open() - Open the mgmt/downld/dpa device.
- */
-int dgnc_mgmt_open(struct inode *inode, struct file *file)
-{
-       unsigned long flags;
-       unsigned int minor = iminor(inode);
-       int rc = 0;
-
-       spin_lock_irqsave(&dgnc_global_lock, flags);
-
-       if (minor >= MAXMGMTDEVICES) {
-               rc = -ENXIO;
-               goto out;
-       }
-       /* Only allow 1 open at a time on mgmt device */
-       if (dgnc_mgmt_in_use[minor]) {
-               rc = -EBUSY;
-               goto out;
-       }
-       dgnc_mgmt_in_use[minor]++;
-
-out:
-       spin_unlock_irqrestore(&dgnc_global_lock, flags);
-
-       return rc;
-}
-
-/**
- * dgnc_mgmt_close() - Close the mgmt/dpa device
- */
-int dgnc_mgmt_close(struct inode *inode, struct file *file)
-{
-       unsigned long flags;
-       unsigned int minor = iminor(inode);
-       int rc = 0;
-
-       spin_lock_irqsave(&dgnc_global_lock, flags);
-
-       if (minor >= MAXMGMTDEVICES) {
-               rc = -ENXIO;
-               goto out;
-       }
-       dgnc_mgmt_in_use[minor] = 0;
-
-out:
-       spin_unlock_irqrestore(&dgnc_global_lock, flags);
-
-       return rc;
-}
-
-/**
- * dgnc_mgmt_ioctl() - Ioctl the mgmt/dpa device.
- */
-long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       unsigned long flags;
-       void __user *uarg = (void __user *)arg;
-
-       switch (cmd) {
-       case DIGI_GETDD:
-       {
-               /*
-                * This returns the total number of boards
-                * in the system, as well as driver version
-                * and has space for a reserved entry
-                */
-               struct digi_dinfo ddi;
-
-               spin_lock_irqsave(&dgnc_global_lock, flags);
-
-               memset(&ddi, 0, sizeof(ddi));
-               ddi.dinfo_nboards = dgnc_num_boards;
-               sprintf(ddi.dinfo_version, "%s", DG_PART);
-
-               spin_unlock_irqrestore(&dgnc_global_lock, flags);
-
-               if (copy_to_user(uarg, &ddi, sizeof(ddi)))
-                       return -EFAULT;
-
-               break;
-       }
-
-       case DIGI_GETBD:
-       {
-               int brd;
-
-               struct digi_info di;
-
-               if (copy_from_user(&brd, uarg, sizeof(int)))
-                       return -EFAULT;
-
-               if (brd < 0 || brd >= dgnc_num_boards)
-                       return -ENODEV;
-
-               memset(&di, 0, sizeof(di));
-
-               di.info_bdnum = brd;
-
-               spin_lock_irqsave(&dgnc_board[brd]->bd_lock, flags);
-
-               di.info_bdtype = dgnc_board[brd]->dpatype;
-               di.info_bdstate = dgnc_board[brd]->dpastatus;
-               di.info_ioport = 0;
-               di.info_physaddr = (ulong)dgnc_board[brd]->membase;
-               di.info_physsize = (ulong)dgnc_board[brd]->membase
-                       - dgnc_board[brd]->membase_end;
-               if (dgnc_board[brd]->state != BOARD_FAILED)
-                       di.info_nports = dgnc_board[brd]->nasync;
-               else
-                       di.info_nports = 0;
-
-               spin_unlock_irqrestore(&dgnc_board[brd]->bd_lock, flags);
-
-               if (copy_to_user(uarg, &di, sizeof(di)))
-                       return -EFAULT;
-
-               break;
-       }
-
-       case DIGI_GET_NI_INFO:
-       {
-               struct channel_t *ch;
-               struct ni_info ni;
-               unsigned char mstat = 0;
-               uint board = 0;
-               uint channel = 0;
-
-               if (copy_from_user(&ni, uarg, sizeof(ni)))
-                       return -EFAULT;
-
-               board = ni.board;
-               channel = ni.channel;
-
-               if (board >= dgnc_num_boards)
-                       return -ENODEV;
-
-               if (channel >= dgnc_board[board]->nasync)
-                       return -ENODEV;
-
-               ch = dgnc_board[board]->channels[channel];
-
-               if (!ch)
-                       return -ENODEV;
-
-               memset(&ni, 0, sizeof(ni));
-               ni.board = board;
-               ni.channel = channel;
-
-               spin_lock_irqsave(&ch->ch_lock, flags);
-
-               mstat = ch->ch_mostat | ch->ch_mistat;
-
-               if (mstat & UART_MCR_DTR) {
-                       ni.mstat |= TIOCM_DTR;
-                       ni.dtr = TIOCM_DTR;
-               }
-               if (mstat & UART_MCR_RTS) {
-                       ni.mstat |= TIOCM_RTS;
-                       ni.rts = TIOCM_RTS;
-               }
-               if (mstat & UART_MSR_CTS) {
-                       ni.mstat |= TIOCM_CTS;
-                       ni.cts = TIOCM_CTS;
-               }
-               if (mstat & UART_MSR_RI) {
-                       ni.mstat |= TIOCM_RI;
-                       ni.ri = TIOCM_RI;
-               }
-               if (mstat & UART_MSR_DCD) {
-                       ni.mstat |= TIOCM_CD;
-                       ni.dcd = TIOCM_CD;
-               }
-               if (mstat & UART_MSR_DSR)
-                       ni.mstat |= TIOCM_DSR;
-
-               ni.iflag = ch->ch_c_iflag;
-               ni.oflag = ch->ch_c_oflag;
-               ni.cflag = ch->ch_c_cflag;
-               ni.lflag = ch->ch_c_lflag;
-
-               if (ch->ch_digi.digi_flags & CTSPACE ||
-                   ch->ch_c_cflag & CRTSCTS)
-                       ni.hflow = 1;
-               else
-                       ni.hflow = 0;
-
-               if ((ch->ch_flags & CH_STOPI) ||
-                   (ch->ch_flags & CH_FORCED_STOPI))
-                       ni.recv_stopped = 1;
-               else
-                       ni.recv_stopped = 0;
-
-               if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_FORCED_STOP))
-                       ni.xmit_stopped = 1;
-               else
-                       ni.xmit_stopped = 0;
-
-               ni.curtx = ch->ch_txcount;
-               ni.currx = ch->ch_rxcount;
-
-               ni.baud = ch->ch_old_baud;
-
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-
-               if (copy_to_user(uarg, &ni, sizeof(ni)))
-                       return -EFAULT;
-
-               break;
-       }
-       }
-       return 0;
-}
diff --git a/drivers/staging/dgnc/dgnc_mgmt.h b/drivers/staging/dgnc/dgnc_mgmt.h
deleted file mode 100644 (file)
index a7a5770..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- */
-
-#ifndef _DGNC_MGMT_H
-#define _DGNC_MGMT_H
-
-#define MAXMGMTDEVICES 8
-
-int dgnc_mgmt_open(struct inode *inode, struct file *file);
-int dgnc_mgmt_close(struct inode *inode, struct file *file);
-long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-
-#endif /* _DGNC_MGMT_H */
-
diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c
deleted file mode 100644 (file)
index 0ae229c..0000000
+++ /dev/null
@@ -1,1690 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-
-#include "dgnc_driver.h"
-#include "dgnc_neo.h"
-#include "dgnc_tty.h"
-
-static inline void neo_parse_lsr(struct dgnc_board *brd, uint port);
-static inline void neo_parse_isr(struct dgnc_board *brd, uint port);
-static void neo_copy_data_from_uart_to_queue(struct channel_t *ch);
-static inline void neo_clear_break(struct channel_t *ch, int force);
-static inline void neo_set_cts_flow_control(struct channel_t *ch);
-static inline void neo_set_rts_flow_control(struct channel_t *ch);
-static inline void neo_set_ixon_flow_control(struct channel_t *ch);
-static inline void neo_set_ixoff_flow_control(struct channel_t *ch);
-static inline void neo_set_no_output_flow_control(struct channel_t *ch);
-static inline void neo_set_no_input_flow_control(struct channel_t *ch);
-static inline void neo_set_new_start_stop_chars(struct channel_t *ch);
-static void neo_parse_modem(struct channel_t *ch, unsigned char signals);
-static void neo_tasklet(unsigned long data);
-static void neo_vpd(struct dgnc_board *brd);
-static void neo_uart_init(struct channel_t *ch);
-static void neo_uart_off(struct channel_t *ch);
-static int neo_drain(struct tty_struct *tty, uint seconds);
-static void neo_param(struct tty_struct *tty);
-static void neo_assert_modem_signals(struct channel_t *ch);
-static void neo_flush_uart_write(struct channel_t *ch);
-static void neo_flush_uart_read(struct channel_t *ch);
-static void neo_disable_receiver(struct channel_t *ch);
-static void neo_enable_receiver(struct channel_t *ch);
-static void neo_send_break(struct channel_t *ch, int msecs);
-static void neo_send_start_character(struct channel_t *ch);
-static void neo_send_stop_character(struct channel_t *ch);
-static void neo_copy_data_from_queue_to_uart(struct channel_t *ch);
-static uint neo_get_uart_bytes_left(struct channel_t *ch);
-static void neo_send_immediate_char(struct channel_t *ch, unsigned char c);
-static irqreturn_t neo_intr(int irq, void *voidbrd);
-
-struct board_ops dgnc_neo_ops = {
-       .tasklet =                      neo_tasklet,
-       .intr =                         neo_intr,
-       .uart_init =                    neo_uart_init,
-       .uart_off =                     neo_uart_off,
-       .drain =                        neo_drain,
-       .param =                        neo_param,
-       .vpd =                          neo_vpd,
-       .assert_modem_signals =         neo_assert_modem_signals,
-       .flush_uart_write =             neo_flush_uart_write,
-       .flush_uart_read =              neo_flush_uart_read,
-       .disable_receiver =             neo_disable_receiver,
-       .enable_receiver =              neo_enable_receiver,
-       .send_break =                   neo_send_break,
-       .send_start_character =         neo_send_start_character,
-       .send_stop_character =          neo_send_stop_character,
-       .copy_data_from_queue_to_uart = neo_copy_data_from_queue_to_uart,
-       .get_uart_bytes_left =          neo_get_uart_bytes_left,
-       .send_immediate_char =          neo_send_immediate_char
-};
-
-/*
- * This function allows calls to ensure that all outstanding
- * PCI writes have been completed, by doing a PCI read against
- * a non-destructive, read-only location on the Neo card.
- *
- * In this case, we are reading the DVID (Read-only Device Identification)
- * value of the Neo card.
- */
-static inline void neo_pci_posting_flush(struct dgnc_board *bd)
-{
-       readb(bd->re_map_membase + 0x8D);
-}
-
-static inline void neo_set_cts_flow_control(struct channel_t *ch)
-{
-       unsigned char ier = readb(&ch->ch_neo_uart->ier);
-       unsigned char efr = readb(&ch->ch_neo_uart->efr);
-
-       /* Turn on auto CTS flow control */
-       ier |= UART_17158_IER_CTSDSR;
-       efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR);
-
-       /* Turn off auto Xon flow control */
-       efr &= ~UART_17158_EFR_IXON;
-
-       /*
-        * Why? Because Exar's spec says we have to zero it
-        * out before setting it
-        */
-       writeb(0, &ch->ch_neo_uart->efr);
-
-       /* Turn on UART enhanced bits */
-       writeb(efr, &ch->ch_neo_uart->efr);
-
-       /* Turn on table D, with 8 char hi/low watermarks */
-       writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY,
-              &ch->ch_neo_uart->fctr);
-
-       /* Feed the UART our trigger levels */
-       writeb(8, &ch->ch_neo_uart->tfifo);
-       ch->ch_t_tlevel = 8;
-
-       writeb(ier, &ch->ch_neo_uart->ier);
-
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-static inline void neo_set_rts_flow_control(struct channel_t *ch)
-{
-       unsigned char ier = readb(&ch->ch_neo_uart->ier);
-       unsigned char efr = readb(&ch->ch_neo_uart->efr);
-
-       /* Turn on auto RTS flow control */
-       ier |= UART_17158_IER_RTSDTR;
-       efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR);
-
-       /* Turn off auto Xoff flow control */
-       ier &= ~UART_17158_IER_XOFF;
-       efr &= ~UART_17158_EFR_IXOFF;
-
-       /*
-        * Why? Because Exar's spec says we have to zero it
-        * out before setting it
-        */
-       writeb(0, &ch->ch_neo_uart->efr);
-
-       /* Turn on UART enhanced bits */
-       writeb(efr, &ch->ch_neo_uart->efr);
-
-       writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY,
-              &ch->ch_neo_uart->fctr);
-       ch->ch_r_watermark = 4;
-
-       writeb(32, &ch->ch_neo_uart->rfifo);
-       ch->ch_r_tlevel = 32;
-
-       writeb(ier, &ch->ch_neo_uart->ier);
-
-       /*
-        * From the Neo UART spec sheet:
-        * The auto RTS/DTR function must be started by asserting
-        * RTS/DTR# output pin (MCR bit-0 or 1 to logic 1 after
-        * it is enabled.
-        */
-       ch->ch_mostat |= UART_MCR_RTS;
-
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-static inline void neo_set_ixon_flow_control(struct channel_t *ch)
-{
-       unsigned char ier = readb(&ch->ch_neo_uart->ier);
-       unsigned char efr = readb(&ch->ch_neo_uart->efr);
-
-       /* Turn off auto CTS flow control */
-       ier &= ~UART_17158_IER_CTSDSR;
-       efr &= ~UART_17158_EFR_CTSDSR;
-
-       /* Turn on auto Xon flow control */
-       efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON);
-
-       /*
-        * Why? Because Exar's spec says we have to zero it
-        * out before setting it
-        */
-       writeb(0, &ch->ch_neo_uart->efr);
-
-       /* Turn on UART enhanced bits */
-       writeb(efr, &ch->ch_neo_uart->efr);
-
-       writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY,
-              &ch->ch_neo_uart->fctr);
-       ch->ch_r_watermark = 4;
-
-       writeb(32, &ch->ch_neo_uart->rfifo);
-       ch->ch_r_tlevel = 32;
-
-       /* Tell UART what start/stop chars it should be looking for */
-       writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
-       writeb(0, &ch->ch_neo_uart->xonchar2);
-
-       writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
-       writeb(0, &ch->ch_neo_uart->xoffchar2);
-
-       writeb(ier, &ch->ch_neo_uart->ier);
-
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-static inline void neo_set_ixoff_flow_control(struct channel_t *ch)
-{
-       unsigned char ier = readb(&ch->ch_neo_uart->ier);
-       unsigned char efr = readb(&ch->ch_neo_uart->efr);
-
-       /* Turn off auto RTS flow control */
-       ier &= ~UART_17158_IER_RTSDTR;
-       efr &= ~UART_17158_EFR_RTSDTR;
-
-       /* Turn on auto Xoff flow control */
-       ier |= UART_17158_IER_XOFF;
-       efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
-
-       /*
-        * Why? Because Exar's spec says we have to zero it
-        * out before setting it
-        */
-       writeb(0, &ch->ch_neo_uart->efr);
-
-       /* Turn on UART enhanced bits */
-       writeb(efr, &ch->ch_neo_uart->efr);
-
-       /* Turn on table D, with 8 char hi/low watermarks */
-       writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY,
-              &ch->ch_neo_uart->fctr);
-
-       writeb(8, &ch->ch_neo_uart->tfifo);
-       ch->ch_t_tlevel = 8;
-
-       /* Tell UART what start/stop chars it should be looking for */
-       writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
-       writeb(0, &ch->ch_neo_uart->xonchar2);
-
-       writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
-       writeb(0, &ch->ch_neo_uart->xoffchar2);
-
-       writeb(ier, &ch->ch_neo_uart->ier);
-
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-static inline void neo_set_no_input_flow_control(struct channel_t *ch)
-{
-       unsigned char ier = readb(&ch->ch_neo_uart->ier);
-       unsigned char efr = readb(&ch->ch_neo_uart->efr);
-
-       /* Turn off auto RTS flow control */
-       ier &= ~UART_17158_IER_RTSDTR;
-       efr &= ~UART_17158_EFR_RTSDTR;
-
-       /* Turn off auto Xoff flow control */
-       ier &= ~UART_17158_IER_XOFF;
-       if (ch->ch_c_iflag & IXON)
-               efr &= ~(UART_17158_EFR_IXOFF);
-       else
-               efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
-
-       /*
-        * Why? Because Exar's spec says we have to zero
-        * it out before setting it
-        */
-       writeb(0, &ch->ch_neo_uart->efr);
-
-       /* Turn on UART enhanced bits */
-       writeb(efr, &ch->ch_neo_uart->efr);
-
-       /* Turn on table D, with 8 char hi/low watermarks */
-       writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY,
-              &ch->ch_neo_uart->fctr);
-
-       ch->ch_r_watermark = 0;
-
-       writeb(16, &ch->ch_neo_uart->tfifo);
-       ch->ch_t_tlevel = 16;
-
-       writeb(16, &ch->ch_neo_uart->rfifo);
-       ch->ch_r_tlevel = 16;
-
-       writeb(ier, &ch->ch_neo_uart->ier);
-
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-static inline void neo_set_no_output_flow_control(struct channel_t *ch)
-{
-       unsigned char ier = readb(&ch->ch_neo_uart->ier);
-       unsigned char efr = readb(&ch->ch_neo_uart->efr);
-
-       /* Turn off auto CTS flow control */
-       ier &= ~UART_17158_IER_CTSDSR;
-       efr &= ~UART_17158_EFR_CTSDSR;
-
-       /* Turn off auto Xon flow control */
-       if (ch->ch_c_iflag & IXOFF)
-               efr &= ~UART_17158_EFR_IXON;
-       else
-               efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON);
-
-       /*
-        * Why? Because Exar's spec says we have to zero it
-        * out before setting it
-        */
-       writeb(0, &ch->ch_neo_uart->efr);
-
-       /* Turn on UART enhanced bits */
-       writeb(efr, &ch->ch_neo_uart->efr);
-
-       /* Turn on table D, with 8 char hi/low watermarks */
-       writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY,
-              &ch->ch_neo_uart->fctr);
-
-       ch->ch_r_watermark = 0;
-
-       writeb(16, &ch->ch_neo_uart->tfifo);
-       ch->ch_t_tlevel = 16;
-
-       writeb(16, &ch->ch_neo_uart->rfifo);
-       ch->ch_r_tlevel = 16;
-
-       writeb(ier, &ch->ch_neo_uart->ier);
-
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-/* change UARTs start/stop chars */
-static inline void neo_set_new_start_stop_chars(struct channel_t *ch)
-{
-       /* if hardware flow control is set, then skip this whole thing */
-       if (ch->ch_digi.digi_flags & (CTSPACE | RTSPACE) ||
-           ch->ch_c_cflag & CRTSCTS)
-               return;
-
-       /* Tell UART what start/stop chars it should be looking for */
-       writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
-       writeb(0, &ch->ch_neo_uart->xonchar2);
-
-       writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
-       writeb(0, &ch->ch_neo_uart->xoffchar2);
-
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-/* No locks are assumed to be held when calling this function. */
-static inline void neo_clear_break(struct channel_t *ch, int force)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&ch->ch_lock, flags);
-
-       if (!ch->ch_stop_sending_break) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
-       }
-
-       if (ch->ch_flags & CH_BREAK_SENDING) {
-               if (force ||
-                   time_after_eq(jiffies, ch->ch_stop_sending_break)) {
-                       unsigned char temp = readb(&ch->ch_neo_uart->lcr);
-
-                       writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
-                       neo_pci_posting_flush(ch->ch_bd);
-                       ch->ch_flags &= ~(CH_BREAK_SENDING);
-                       ch->ch_stop_sending_break = 0;
-               }
-       }
-       spin_unlock_irqrestore(&ch->ch_lock, flags);
-}
-
-/* Parse the ISR register. */
-static inline void neo_parse_isr(struct dgnc_board *brd, uint port)
-{
-       struct channel_t *ch;
-       unsigned char isr;
-       unsigned char cause;
-       unsigned long flags;
-
-       ch = brd->channels[port];
-       if (!ch)
-               return;
-
-       /* Here we try to figure out what caused the interrupt to happen */
-       while (1) {
-               isr = readb(&ch->ch_neo_uart->isr_fcr);
-
-               if (isr & UART_IIR_NO_INT)
-                       break;
-
-               /*
-                * Yank off the upper 2 bits,
-                * which just show that the FIFO's are enabled.
-                */
-               isr &= ~(UART_17158_IIR_FIFO_ENABLED);
-
-               if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
-                       /* Read data from uart -> queue */
-                       neo_copy_data_from_uart_to_queue(ch);
-                       /*
-                        * Call our tty layer to enforce queue
-                        * flow control if needed.
-                        */
-                       spin_lock_irqsave(&ch->ch_lock, flags);
-                       dgnc_check_queue_flow_control(ch);
-                       spin_unlock_irqrestore(&ch->ch_lock, flags);
-               }
-
-               if (isr & UART_IIR_THRI) {
-                       spin_lock_irqsave(&ch->ch_lock, flags);
-                       ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-                       spin_unlock_irqrestore(&ch->ch_lock, flags);
-                       neo_copy_data_from_queue_to_uart(ch);
-               }
-
-               if (isr & UART_17158_IIR_XONXOFF) {
-                       cause = readb(&ch->ch_neo_uart->xoffchar1);
-
-                       /*
-                        * Since the UART detected either an XON or
-                        * XOFF match, we need to figure out which
-                        * one it was, so we can suspend or resume data flow.
-                        */
-                       if (cause == UART_17158_XON_DETECT) {
-                               /* resume output if stopped */
-                               if (brd->channels[port]->ch_flags & CH_STOP) {
-                                       spin_lock_irqsave(&ch->ch_lock,
-                                                         flags);
-                                       ch->ch_flags &= ~(CH_STOP);
-                                       spin_unlock_irqrestore(&ch->ch_lock,
-                                                              flags);
-                               }
-                       } else if (cause == UART_17158_XOFF_DETECT) {
-                               if (!(brd->channels[port]->ch_flags &
-                                     CH_STOP)) {
-                                       spin_lock_irqsave(&ch->ch_lock,
-                                                         flags);
-                                       ch->ch_flags |= CH_STOP;
-                                       spin_unlock_irqrestore(&ch->ch_lock,
-                                                              flags);
-                               }
-                       }
-               }
-
-               if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) {
-                       /*
-                        * If we get here, this means the hardware is
-                        * doing auto flow control. Check to see whether
-                        * RTS/DTR or CTS/DSR caused this interrupt.
-                        */
-                       cause = readb(&ch->ch_neo_uart->mcr);
-                       /* Which pin is doing auto flow? RTS or DTR? */
-                       if ((cause & 0x4) == 0) {
-                               if (cause & UART_MCR_RTS) {
-                                       spin_lock_irqsave(&ch->ch_lock,
-                                                         flags);
-                                       ch->ch_mostat |= UART_MCR_RTS;
-                                       spin_unlock_irqrestore(&ch->ch_lock,
-                                                              flags);
-                               } else {
-                                       spin_lock_irqsave(&ch->ch_lock,
-                                                         flags);
-                                       ch->ch_mostat &= ~(UART_MCR_RTS);
-                                       spin_unlock_irqrestore(&ch->ch_lock,
-                                                              flags);
-                               }
-                       } else {
-                               if (cause & UART_MCR_DTR) {
-                                       spin_lock_irqsave(&ch->ch_lock,
-                                                         flags);
-                                       ch->ch_mostat |= UART_MCR_DTR;
-                                       spin_unlock_irqrestore(&ch->ch_lock,
-                                                              flags);
-                               } else {
-                                       spin_lock_irqsave(&ch->ch_lock,
-                                                         flags);
-                                       ch->ch_mostat &= ~(UART_MCR_DTR);
-                                       spin_unlock_irqrestore(&ch->ch_lock,
-                                                              flags);
-                               }
-                       }
-               }
-
-               neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
-       }
-}
-
-static inline void neo_parse_lsr(struct dgnc_board *brd, uint port)
-{
-       struct channel_t *ch;
-       int linestatus;
-       unsigned long flags;
-
-       if (!brd)
-               return;
-
-       if (port >= brd->maxports)
-               return;
-
-       ch = brd->channels[port];
-       if (!ch)
-               return;
-
-       linestatus = readb(&ch->ch_neo_uart->lsr);
-
-       ch->ch_cached_lsr |= linestatus;
-
-       if (ch->ch_cached_lsr & UART_LSR_DR) {
-               neo_copy_data_from_uart_to_queue(ch);
-               spin_lock_irqsave(&ch->ch_lock, flags);
-               dgnc_check_queue_flow_control(ch);
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-       }
-
-       /*
-        * The next 3 tests should *NOT* happen, as the above test
-        * should encapsulate all 3... At least, thats what Exar says.
-        */
-
-       if (linestatus & UART_LSR_PE)
-               ch->ch_err_parity++;
-
-       if (linestatus & UART_LSR_FE)
-               ch->ch_err_frame++;
-
-       if (linestatus & UART_LSR_BI)
-               ch->ch_err_break++;
-
-       if (linestatus & UART_LSR_OE) {
-               /*
-                * Rx Oruns. Exar says that an orun will NOT corrupt
-                * the FIFO. It will just replace the holding register
-                * with this new data byte. So basically just ignore this.
-                * Probably we should eventually have an orun stat in our
-                * driver...
-                */
-               ch->ch_err_overrun++;
-       }
-
-       if (linestatus & UART_LSR_THRE) {
-               spin_lock_irqsave(&ch->ch_lock, flags);
-               ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-
-               neo_copy_data_from_queue_to_uart(ch);
-       } else if (linestatus & UART_17158_TX_AND_FIFO_CLR) {
-               spin_lock_irqsave(&ch->ch_lock, flags);
-               ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-
-               neo_copy_data_from_queue_to_uart(ch);
-       }
-}
-
-/* Send any/all changes to the line to the UART. */
-static void neo_param(struct tty_struct *tty)
-{
-       unsigned char lcr = 0;
-       unsigned char uart_lcr = 0;
-       unsigned char ier = 0;
-       unsigned char uart_ier = 0;
-       uint baud = 9600;
-       int quot = 0;
-       struct dgnc_board *bd;
-       struct channel_t *ch;
-       struct un_t   *un;
-
-       if (!tty)
-               return;
-
-       un = (struct un_t *)tty->driver_data;
-       if (!un)
-               return;
-
-       ch = un->un_ch;
-       if (!ch)
-               return;
-
-       bd = ch->ch_bd;
-       if (!bd)
-               return;
-
-       /* If baud rate is zero, flush queues, and set mval to drop DTR. */
-       if ((ch->ch_c_cflag & (CBAUD)) == 0) {
-               ch->ch_r_head = 0;
-               ch->ch_r_tail = 0;
-               ch->ch_e_head = 0;
-               ch->ch_e_tail = 0;
-               ch->ch_w_head = 0;
-               ch->ch_w_tail = 0;
-
-               neo_flush_uart_write(ch);
-               neo_flush_uart_read(ch);
-
-               /* The baudrate is B0 so all modem lines are to be dropped. */
-               ch->ch_flags |= (CH_BAUD0);
-               ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
-               neo_assert_modem_signals(ch);
-               ch->ch_old_baud = 0;
-               return;
-
-       } else if (ch->ch_custom_speed) {
-               baud = ch->ch_custom_speed;
-               /* Handle transition from B0 */
-               if (ch->ch_flags & CH_BAUD0) {
-                       ch->ch_flags &= ~(CH_BAUD0);
-
-                       /*
-                        * Bring back up RTS and DTR...
-                        * Also handle RTS or DTR toggle if set.
-                        */
-                       if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
-                               ch->ch_mostat |= (UART_MCR_RTS);
-                       if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
-                               ch->ch_mostat |= (UART_MCR_DTR);
-               }
-       } else {
-               int iindex = 0;
-               int jindex = 0;
-
-               ulong bauds[4][16] = {
-                       { /* slowbaud */
-                               0,      50,     75,     110,
-                               134,    150,    200,    300,
-                               600,    1200,   1800,   2400,
-                               4800,   9600,   19200,  38400 },
-                       { /* slowbaud & CBAUDEX */
-                               0,      57600,  115200, 230400,
-                               460800, 150,    200,    921600,
-                               600,    1200,   1800,   2400,
-                               4800,   9600,   19200,  38400 },
-                       { /* fastbaud */
-                               0,      57600,   76800, 115200,
-                               131657, 153600, 230400, 460800,
-                               921600, 1200,   1800,   2400,
-                               4800,   9600,   19200,  38400 },
-                       { /* fastbaud & CBAUDEX */
-                               0,      57600,  115200, 230400,
-                               460800, 150,    200,    921600,
-                               600,    1200,   1800,   2400,
-                               4800,   9600,   19200,  38400 }
-               };
-
-               /*
-                * Only use the TXPrint baud rate if the terminal unit
-                * is NOT open
-                */
-               if (!(ch->ch_tun.un_flags & UN_ISOPEN) &&
-                   (un->un_type == DGNC_PRINT))
-                       baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
-               else
-                       baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
-
-               if (ch->ch_c_cflag & CBAUDEX)
-                       iindex = 1;
-
-               if (ch->ch_digi.digi_flags & DIGI_FAST)
-                       iindex += 2;
-
-               jindex = baud;
-
-               if ((iindex >= 0) && (iindex < 4) &&
-                   (jindex >= 0) && (jindex < 16))
-                       baud = bauds[iindex][jindex];
-               else
-                       baud = 0;
-
-               if (baud == 0)
-                       baud = 9600;
-
-               /* Handle transition from B0 */
-               if (ch->ch_flags & CH_BAUD0) {
-                       ch->ch_flags &= ~(CH_BAUD0);
-
-                       /*
-                        * Bring back up RTS and DTR...
-                        * Also handle RTS or DTR toggle if set.
-                        */
-                       if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
-                               ch->ch_mostat |= (UART_MCR_RTS);
-                       if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
-                               ch->ch_mostat |= (UART_MCR_DTR);
-               }
-       }
-
-       if (ch->ch_c_cflag & PARENB)
-               lcr |= UART_LCR_PARITY;
-
-       if (!(ch->ch_c_cflag & PARODD))
-               lcr |= UART_LCR_EPAR;
-
-#ifdef CMSPAR
-       if (ch->ch_c_cflag & CMSPAR)
-               lcr |= UART_LCR_SPAR;
-#endif
-
-       if (ch->ch_c_cflag & CSTOPB)
-               lcr |= UART_LCR_STOP;
-
-       switch (ch->ch_c_cflag & CSIZE) {
-       case CS5:
-               lcr |= UART_LCR_WLEN5;
-               break;
-       case CS6:
-               lcr |= UART_LCR_WLEN6;
-               break;
-       case CS7:
-               lcr |= UART_LCR_WLEN7;
-               break;
-       case CS8:
-       default:
-               lcr |= UART_LCR_WLEN8;
-               break;
-       }
-
-       uart_ier = readb(&ch->ch_neo_uart->ier);
-       ier = uart_ier;
-
-       uart_lcr = readb(&ch->ch_neo_uart->lcr);
-
-       if (baud == 0)
-               baud = 9600;
-
-       quot = ch->ch_bd->bd_dividend / baud;
-
-       if (quot != 0 && ch->ch_old_baud != baud) {
-               ch->ch_old_baud = baud;
-               writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr);
-               writeb((quot & 0xff), &ch->ch_neo_uart->txrx);
-               writeb((quot >> 8), &ch->ch_neo_uart->ier);
-               writeb(lcr, &ch->ch_neo_uart->lcr);
-       }
-
-       if (uart_lcr != lcr)
-               writeb(lcr, &ch->ch_neo_uart->lcr);
-
-       if (ch->ch_c_cflag & CREAD)
-               ier |= (UART_IER_RDI | UART_IER_RLSI);
-       else
-               ier &= ~(UART_IER_RDI | UART_IER_RLSI);
-
-       /*
-        * Have the UART interrupt on modem signal changes ONLY when
-        * we are in hardware flow control mode, or CLOCAL/FORCEDCD is not set.
-        */
-       if ((ch->ch_digi.digi_flags & CTSPACE) ||
-           (ch->ch_digi.digi_flags & RTSPACE) ||
-           (ch->ch_c_cflag & CRTSCTS) ||
-           !(ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
-           !(ch->ch_c_cflag & CLOCAL))
-               ier |= UART_IER_MSI;
-       else
-               ier &= ~UART_IER_MSI;
-
-       ier |= UART_IER_THRI;
-
-       if (ier != uart_ier)
-               writeb(ier, &ch->ch_neo_uart->ier);
-
-       neo_set_new_start_stop_chars(ch);
-
-       if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) {
-               neo_set_cts_flow_control(ch);
-       } else if (ch->ch_c_iflag & IXON) {
-               if ((ch->ch_startc == _POSIX_VDISABLE) ||
-                   (ch->ch_stopc == _POSIX_VDISABLE))
-                       neo_set_no_output_flow_control(ch);
-               else
-                       neo_set_ixon_flow_control(ch);
-       } else {
-               neo_set_no_output_flow_control(ch);
-       }
-
-       if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) {
-               neo_set_rts_flow_control(ch);
-       } else if (ch->ch_c_iflag & IXOFF) {
-               if ((ch->ch_startc == _POSIX_VDISABLE) ||
-                   (ch->ch_stopc == _POSIX_VDISABLE))
-                       neo_set_no_input_flow_control(ch);
-               else
-                       neo_set_ixoff_flow_control(ch);
-       } else {
-               neo_set_no_input_flow_control(ch);
-       }
-
-       /*
-        * Adjust the RX FIFO Trigger level if baud is less than 9600.
-        * Not exactly elegant, but this is needed because of the Exar chip's
-        * delay on firing off the RX FIFO interrupt on slower baud rates.
-        */
-       if (baud < 9600) {
-               writeb(1, &ch->ch_neo_uart->rfifo);
-               ch->ch_r_tlevel = 1;
-       }
-
-       neo_assert_modem_signals(ch);
-
-       neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
-}
-
-/* Board poller function. */
-static void neo_tasklet(unsigned long data)
-{
-       struct dgnc_board *bd = (struct dgnc_board *)data;
-       struct channel_t *ch;
-       unsigned long flags;
-       int i;
-       int state = 0;
-       int ports = 0;
-
-       if (!bd)
-               return;
-
-       spin_lock_irqsave(&bd->bd_lock, flags);
-       state = bd->state;
-       ports = bd->nasync;
-       spin_unlock_irqrestore(&bd->bd_lock, flags);
-
-       /*
-        * Do NOT allow the interrupt routine to read the intr registers
-        * Until we release this lock.
-        */
-       spin_lock_irqsave(&bd->bd_intr_lock, flags);
-
-       if ((state == BOARD_READY) && (ports > 0)) {
-               for (i = 0; i < ports; i++) {
-                       ch = bd->channels[i];
-                       if (!ch)
-                               continue;
-
-                       /*
-                        * NOTE: Remember you CANNOT hold any channel
-                        * locks when calling the input routine.
-                        *
-                        * During input processing, its possible we
-                        * will call the Linux ld, which might in turn,
-                        * do a callback right back into us, resulting
-                        * in us trying to grab the channel lock twice!
-                        */
-                       dgnc_input(ch);
-
-                       /*
-                        * Channel lock is grabbed and then released
-                        * inside both of these routines, but neither
-                        * call anything else that could call back into us.
-                        */
-                       neo_copy_data_from_queue_to_uart(ch);
-                       dgnc_wakeup_writes(ch);
-
-                       dgnc_carrier(ch);
-
-                       /*
-                        * Check to see if we need to turn off a sending break.
-                        * The timing check is done inside clear_break()
-                        */
-                       if (ch->ch_stop_sending_break)
-                               neo_clear_break(ch, 0);
-               }
-       }
-
-       spin_unlock_irqrestore(&bd->bd_intr_lock, flags);
-}
-
-/* Neo specific interrupt handler. */
-static irqreturn_t neo_intr(int irq, void *voidbrd)
-{
-       struct dgnc_board *brd = voidbrd;
-       struct channel_t *ch;
-       int port = 0;
-       int type;
-       u32 uart_poll;
-       unsigned long flags;
-       unsigned long flags2;
-
-       if (!brd)
-               return IRQ_NONE;
-
-       /* Lock out the slow poller from running on this board. */
-       spin_lock_irqsave(&brd->bd_intr_lock, flags);
-
-       /*
-        * Read in "extended" IRQ information from the 32bit Neo register.
-        * Bits 0-7: What port triggered the interrupt.
-        * Bits 8-31: Each 3bits indicate what type of interrupt occurred.
-        */
-       uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
-
-       /*
-        * If 0, no interrupts pending.
-        * This can happen if the IRQ is shared among a couple Neo/Classic
-        * boards.
-        */
-       if (!uart_poll) {
-               spin_unlock_irqrestore(&brd->bd_intr_lock, flags);
-               return IRQ_NONE;
-       }
-
-       while ((uart_poll & 0xff) != 0) {
-               type = uart_poll >> (8 + (port * 3));
-               type &= 0x7;
-
-               uart_poll &= ~(0x01 << port);
-
-               switch (type) {
-               case UART_17158_RXRDY_TIMEOUT:
-                       /*
-                        * RXRDY Time-out is cleared by reading data in the
-                        * RX FIFO until it falls below the trigger level.
-                        */
-
-                       if (port >= brd->nasync)
-                               break;
-
-                       ch = brd->channels[port];
-                       neo_copy_data_from_uart_to_queue(ch);
-
-                       /*
-                        * Call our tty layer to enforce queue flow control if
-                        * needed.
-                        */
-                       spin_lock_irqsave(&ch->ch_lock, flags2);
-                       dgnc_check_queue_flow_control(ch);
-                       spin_unlock_irqrestore(&ch->ch_lock, flags2);
-
-                       break;
-
-               case UART_17158_RX_LINE_STATUS:
-
-                       /* RXRDY and RX LINE Status (logic OR of LSR[4:1]) */
-
-                       neo_parse_lsr(brd, port);
-                       break;
-
-               case UART_17158_TXRDY:
-                       /*
-                        * TXRDY interrupt clears after reading ISR register
-                        * for the UART channel.
-                        */
-
-                       /*
-                        * Yes, this is odd...
-                        * Why would I check EVERY possibility of type of
-                        * interrupt, when we know its TXRDY???
-                        * Becuz for some reason, even tho we got triggered for
-                        * TXRDY, it seems to be occasionally wrong. Instead of
-                        * TX, which it should be, I was getting things like
-                        * RXDY too. Weird.
-                        */
-                       neo_parse_isr(brd, port);
-                       break;
-
-               case UART_17158_MSR:
-                       /* MSR or flow control was seen. */
-                       neo_parse_isr(brd, port);
-                       break;
-
-               default:
-                       break;
-               }
-
-               port++;
-       }
-
-       tasklet_schedule(&brd->helper_tasklet);
-
-       spin_unlock_irqrestore(&brd->bd_intr_lock, flags);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * Neo specific way of turning off the receiver.
- * Used as a way to enforce queue flow control when in
- * hardware flow control mode.
- */
-static void neo_disable_receiver(struct channel_t *ch)
-{
-       unsigned char tmp = readb(&ch->ch_neo_uart->ier);
-
-       tmp &= ~(UART_IER_RDI);
-       writeb(tmp, &ch->ch_neo_uart->ier);
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-/*
- * Neo specific way of turning on the receiver.
- * Used as a way to un-enforce queue flow control when in
- * hardware flow control mode.
- */
-static void neo_enable_receiver(struct channel_t *ch)
-{
-       unsigned char tmp = readb(&ch->ch_neo_uart->ier);
-
-       tmp |= (UART_IER_RDI);
-       writeb(tmp, &ch->ch_neo_uart->ier);
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-static void neo_copy_data_from_uart_to_queue(struct channel_t *ch)
-{
-       int qleft = 0;
-       unsigned char linestatus = 0;
-       unsigned char error_mask = 0;
-       int n = 0;
-       int total = 0;
-       ushort head;
-       ushort tail;
-       unsigned long flags;
-
-       if (!ch)
-               return;
-
-       spin_lock_irqsave(&ch->ch_lock, flags);
-
-       head = ch->ch_r_head & RQUEUEMASK;
-       tail = ch->ch_r_tail & RQUEUEMASK;
-
-       linestatus = ch->ch_cached_lsr;
-       ch->ch_cached_lsr = 0;
-
-       qleft = tail - head - 1;
-       if (qleft < 0)
-               qleft += RQUEUEMASK + 1;
-
-       if (!(ch->ch_flags & CH_FIFO_ENABLED)) {
-               /* force the FIFO copy to NOT be run */
-               total = 0;
-       } else {
-               total = readb(&ch->ch_neo_uart->rfifo);
-
-               /*
-                * EXAR chip bug - RX FIFO COUNT - Fudge factor.
-                *
-                * This resolves a problem/bug with the Exar chip that sometimes
-                * returns a bogus value in the rfifo register.
-                * The count can be any where from 0-3 bytes "off".
-                * Bizarre, but true.
-                */
-               if ((ch->ch_bd->dvid & 0xf0) >= UART_XR17E158_DVID)
-                       total -= 1;
-               else
-                       total -= 3;
-       }
-
-       total = min(total, qleft);
-
-       while (total > 0) {
-               linestatus = readb(&ch->ch_neo_uart->lsr);
-
-               if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
-                       break;
-
-               /* Make sure we don't go over the end of our queue */
-               n = min(((uint)total), (RQUEUESIZE - (uint)head));
-
-               /*
-                * Cut down n even further if needed, this is to fix
-                * a problem with memcpy_fromio() with the Neo on the
-                * IBM pSeries platform.
-                * 15 bytes max appears to be the magic number.
-                */
-               n = min_t(uint, n, 12);
-
-               /*
-                * Since we are grabbing the linestatus register, which
-                * will reset some bits after our read, we need to ensure
-                * we don't miss our TX FIFO emptys.
-                */
-               if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR))
-                       ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-
-               linestatus = 0;
-
-               memcpy_fromio(ch->ch_rqueue + head,
-                             &ch->ch_neo_uart->txrxburst, n);
-
-               /*
-                * Since RX_FIFO_DATA_ERROR was 0, we are guaranteed
-                * that all the data currently in the FIFO is free of
-                * breaks and parity/frame/orun errors.
-                */
-               memset(ch->ch_equeue + head, 0, n);
-
-               head = (head + n) & RQUEUEMASK;
-               total -= n;
-               qleft -= n;
-               ch->ch_rxcount += n;
-       }
-
-       /*
-        * Create a mask to determine whether we should
-        * insert the character (if any) into our queue.
-        */
-       if (ch->ch_c_iflag & IGNBRK)
-               error_mask |= UART_LSR_BI;
-
-       /*
-        * Now cleanup any leftover bytes still in the UART.
-        * Also deal with any possible queue overflow here as well.
-        */
-       while (1) {
-               /*
-                * Its possible we have a linestatus from the loop above
-                * this, so we "OR" on any extra bits.
-                */
-               linestatus |= readb(&ch->ch_neo_uart->lsr);
-
-               /*
-                * If the chip tells us there is no more data pending to
-                * be read, we can then leave.
-                * But before we do, cache the linestatus, just in case.
-                */
-               if (!(linestatus & UART_LSR_DR)) {
-                       ch->ch_cached_lsr = linestatus;
-                       break;
-               }
-
-               /* No need to store this bit */
-               linestatus &= ~UART_LSR_DR;
-
-               /*
-                * Since we are grabbing the linestatus register, which
-                * will reset some bits after our read, we need to ensure
-                * we don't miss our TX FIFO emptys.
-                */
-               if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) {
-                       linestatus &= ~(UART_LSR_THRE |
-                                       UART_17158_TX_AND_FIFO_CLR);
-                       ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-               }
-
-               if (linestatus & error_mask)  {
-                       unsigned char discard;
-
-                       linestatus = 0;
-                       memcpy_fromio(&discard, &ch->ch_neo_uart->txrxburst, 1);
-                       continue;
-               }
-
-               /*
-                * If our queue is full, we have no choice but to drop
-                * some data. The assumption is that HWFLOW or SWFLOW
-                * should have stopped things way way before we got to
-                * this point.
-                */
-               while (qleft < 1) {
-                       tail = (tail + 1) & RQUEUEMASK;
-                       ch->ch_r_tail = tail;
-                       ch->ch_err_overrun++;
-                       qleft++;
-               }
-
-               memcpy_fromio(ch->ch_rqueue + head,
-                             &ch->ch_neo_uart->txrxburst, 1);
-               ch->ch_equeue[head] = (unsigned char)linestatus;
-
-               linestatus = 0;
-
-               head = (head + 1) & RQUEUEMASK;
-
-               qleft--;
-               ch->ch_rxcount++;
-       }
-
-       ch->ch_r_head = head & RQUEUEMASK;
-       ch->ch_e_head = head & EQUEUEMASK;
-
-       spin_unlock_irqrestore(&ch->ch_lock, flags);
-}
-
-/*
- * This function basically goes to sleep for secs, or until
- * it gets signalled that the port has fully drained.
- */
-static int neo_drain(struct tty_struct *tty, uint seconds)
-{
-       unsigned long flags;
-       struct channel_t *ch;
-       struct un_t *un;
-
-       if (!tty)
-               return -ENXIO;
-
-       un = (struct un_t *)tty->driver_data;
-       if (!un)
-               return -ENXIO;
-
-       ch = un->un_ch;
-       if (!ch)
-               return -ENXIO;
-
-       spin_lock_irqsave(&ch->ch_lock, flags);
-       un->un_flags |= UN_EMPTY;
-       spin_unlock_irqrestore(&ch->ch_lock, flags);
-
-       /* If returned value is non-zero, user ctrl-c'ed us */
-       return wait_event_interruptible_timeout(un->un_flags_wait,
-                                       ((un->un_flags & UN_EMPTY) == 0),
-                                       msecs_to_jiffies(seconds * 1000));
-}
-
-/*
- * Flush the WRITE FIFO on the Neo.
- * Channel lock MUST be held before calling this function!
- */
-static void neo_flush_uart_write(struct channel_t *ch)
-{
-       unsigned char tmp = 0;
-       int i = 0;
-
-       if (!ch)
-               return;
-
-       writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT),
-              &ch->ch_neo_uart->isr_fcr);
-       neo_pci_posting_flush(ch->ch_bd);
-
-       for (i = 0; i < 10; i++) {
-               /*
-                * Check to see if the UART completely flushed the FIFO
-                * FIFO.
-                */
-               tmp = readb(&ch->ch_neo_uart->isr_fcr);
-               if (tmp & 4)
-                       udelay(10);
-               else
-                       break;
-       }
-
-       ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-}
-
-/*
- * Flush the READ FIFO on the Neo.
- * Channel lock MUST be held before calling this function!
- */
-static void neo_flush_uart_read(struct channel_t *ch)
-{
-       unsigned char tmp = 0;
-       int i = 0;
-
-       if (!ch)
-               return;
-
-       writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
-              &ch->ch_neo_uart->isr_fcr);
-       neo_pci_posting_flush(ch->ch_bd);
-
-       for (i = 0; i < 10; i++) {
-               /*
-                * Check to see if the UART feels it completely flushed the
-                * FIFO.
-                */
-               tmp = readb(&ch->ch_neo_uart->isr_fcr);
-               if (tmp & 2)
-                       udelay(10);
-               else
-                       break;
-       }
-}
-
-static void neo_copy_data_from_queue_to_uart(struct channel_t *ch)
-{
-       ushort head;
-       ushort tail;
-       int n;
-       int s;
-       int qlen;
-       uint len_written = 0;
-       unsigned long flags;
-
-       if (!ch)
-               return;
-
-       spin_lock_irqsave(&ch->ch_lock, flags);
-
-       if (ch->ch_w_tail == ch->ch_w_head)
-               goto exit_unlock;
-
-       /* If port is "stopped", don't send any data to the UART */
-       if ((ch->ch_flags & CH_FORCED_STOP) ||
-           (ch->ch_flags & CH_BREAK_SENDING))
-               goto exit_unlock;
-
-       if (!(ch->ch_flags & CH_FIFO_ENABLED)) {
-               /* Send data directly to txrx register */
-               unsigned char lsrbits = readb(&ch->ch_neo_uart->lsr);
-
-               ch->ch_cached_lsr |= lsrbits;
-               if (ch->ch_cached_lsr & UART_LSR_THRE) {
-                       ch->ch_cached_lsr &= ~(UART_LSR_THRE);
-
-                       /*
-                        * If RTS Toggle mode is on, turn on RTS now if not
-                        * already set, and make sure we get an event when the
-                        * data transfer has completed.
-                        */
-                       if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
-                               if (!(ch->ch_mostat & UART_MCR_RTS)) {
-                                       ch->ch_mostat |= (UART_MCR_RTS);
-                                       neo_assert_modem_signals(ch);
-                               }
-                               ch->ch_tun.un_flags |= (UN_EMPTY);
-                       }
-                       /*
-                        * If DTR Toggle mode is on, turn on DTR now if not
-                        * already set, and make sure we get an event when the
-                        * data transfer has completed.
-                        */
-                       if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
-                               if (!(ch->ch_mostat & UART_MCR_DTR)) {
-                                       ch->ch_mostat |= (UART_MCR_DTR);
-                                       neo_assert_modem_signals(ch);
-                               }
-                               ch->ch_tun.un_flags |= (UN_EMPTY);
-                       }
-
-                       writeb(ch->ch_wqueue[ch->ch_w_tail],
-                              &ch->ch_neo_uart->txrx);
-                       ch->ch_w_tail++;
-                       ch->ch_w_tail &= WQUEUEMASK;
-                       ch->ch_txcount++;
-               }
-
-               goto exit_unlock;
-       }
-
-       /* We have to do it this way, because of the EXAR TXFIFO count bug. */
-
-       if ((ch->ch_bd->dvid & 0xf0) < UART_XR17E158_DVID) {
-               if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
-                       goto exit_unlock;
-
-               len_written = 0;
-
-               n = readb(&ch->ch_neo_uart->tfifo);
-
-               if ((unsigned int)n > ch->ch_t_tlevel)
-                       goto exit_unlock;
-
-               n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
-       } else {
-               n = UART_17158_TX_FIFOSIZE - readb(&ch->ch_neo_uart->tfifo);
-       }
-
-       head = ch->ch_w_head & WQUEUEMASK;
-       tail = ch->ch_w_tail & WQUEUEMASK;
-       qlen = (head - tail) & WQUEUEMASK;
-
-       n = min(n, qlen);
-
-       while (n > 0) {
-               s = ((head >= tail) ? head : WQUEUESIZE) - tail;
-               s = min(s, n);
-
-               if (s <= 0)
-                       break;
-
-               /*
-                * If RTS Toggle mode is on, turn on RTS now if not already set,
-                * and make sure we get an event when the data transfer has
-                * completed.
-                */
-               if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
-                       if (!(ch->ch_mostat & UART_MCR_RTS)) {
-                               ch->ch_mostat |= (UART_MCR_RTS);
-                               neo_assert_modem_signals(ch);
-                       }
-                       ch->ch_tun.un_flags |= (UN_EMPTY);
-               }
-
-               /*
-                * If DTR Toggle mode is on, turn on DTR now if not already set,
-                * and make sure we get an event when the data transfer has
-                * completed.
-                */
-               if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
-                       if (!(ch->ch_mostat & UART_MCR_DTR)) {
-                               ch->ch_mostat |= (UART_MCR_DTR);
-                               neo_assert_modem_signals(ch);
-                       }
-                       ch->ch_tun.un_flags |= (UN_EMPTY);
-               }
-
-               memcpy_toio(&ch->ch_neo_uart->txrxburst,
-                           ch->ch_wqueue + tail, s);
-
-               tail = (tail + s) & WQUEUEMASK;
-               n -= s;
-               ch->ch_txcount += s;
-               len_written += s;
-       }
-
-       ch->ch_w_tail = tail & WQUEUEMASK;
-
-       if (len_written > 0) {
-               neo_pci_posting_flush(ch->ch_bd);
-               ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-       }
-
-exit_unlock:
-       spin_unlock_irqrestore(&ch->ch_lock, flags);
-}
-
-static void neo_parse_modem(struct channel_t *ch, unsigned char signals)
-{
-       unsigned char msignals = signals;
-
-       if (!ch)
-               return;
-
-       /*
-        * Do altpin switching. Altpin switches DCD and DSR.
-        * This prolly breaks DSRPACE, so we should be more clever here.
-        */
-       if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
-               unsigned char mswap = msignals;
-
-               if (mswap & UART_MSR_DDCD) {
-                       msignals &= ~UART_MSR_DDCD;
-                       msignals |= UART_MSR_DDSR;
-               }
-               if (mswap & UART_MSR_DDSR) {
-                       msignals &= ~UART_MSR_DDSR;
-                       msignals |= UART_MSR_DDCD;
-               }
-               if (mswap & UART_MSR_DCD) {
-                       msignals &= ~UART_MSR_DCD;
-                       msignals |= UART_MSR_DSR;
-               }
-               if (mswap & UART_MSR_DSR) {
-                       msignals &= ~UART_MSR_DSR;
-                       msignals |= UART_MSR_DCD;
-               }
-       }
-
-       /* Scrub off lower bits. They signify delta's */
-       msignals &= 0xf0;
-
-       if (msignals & UART_MSR_DCD)
-               ch->ch_mistat |= UART_MSR_DCD;
-       else
-               ch->ch_mistat &= ~UART_MSR_DCD;
-
-       if (msignals & UART_MSR_DSR)
-               ch->ch_mistat |= UART_MSR_DSR;
-       else
-               ch->ch_mistat &= ~UART_MSR_DSR;
-
-       if (msignals & UART_MSR_RI)
-               ch->ch_mistat |= UART_MSR_RI;
-       else
-               ch->ch_mistat &= ~UART_MSR_RI;
-
-       if (msignals & UART_MSR_CTS)
-               ch->ch_mistat |= UART_MSR_CTS;
-       else
-               ch->ch_mistat &= ~UART_MSR_CTS;
-}
-
-/* Make the UART raise any of the output signals we want up */
-static void neo_assert_modem_signals(struct channel_t *ch)
-{
-       unsigned char out;
-
-       if (!ch)
-               return;
-
-       out = ch->ch_mostat;
-
-       if (ch->ch_flags & CH_LOOPBACK)
-               out |= UART_MCR_LOOP;
-
-       writeb(out, &ch->ch_neo_uart->mcr);
-       neo_pci_posting_flush(ch->ch_bd);
-
-       /* Give time for the UART to actually raise/drop the signals */
-       udelay(10);
-}
-
-static void neo_send_start_character(struct channel_t *ch)
-{
-       if (!ch)
-               return;
-
-       if (ch->ch_startc != _POSIX_VDISABLE) {
-               ch->ch_xon_sends++;
-               writeb(ch->ch_startc, &ch->ch_neo_uart->txrx);
-               neo_pci_posting_flush(ch->ch_bd);
-               udelay(10);
-       }
-}
-
-static void neo_send_stop_character(struct channel_t *ch)
-{
-       if (!ch)
-               return;
-
-       if (ch->ch_stopc != _POSIX_VDISABLE) {
-               ch->ch_xoff_sends++;
-               writeb(ch->ch_stopc, &ch->ch_neo_uart->txrx);
-               neo_pci_posting_flush(ch->ch_bd);
-               udelay(10);
-       }
-}
-
-/* neo_uart_init */
-
-static void neo_uart_init(struct channel_t *ch)
-{
-       writeb(0, &ch->ch_neo_uart->ier);
-       writeb(0, &ch->ch_neo_uart->efr);
-       writeb(UART_EFR_ECB, &ch->ch_neo_uart->efr);
-
-       /* Clear out UART and FIFO */
-       readb(&ch->ch_neo_uart->txrx);
-       writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
-              &ch->ch_neo_uart->isr_fcr);
-       readb(&ch->ch_neo_uart->lsr);
-       readb(&ch->ch_neo_uart->msr);
-
-       ch->ch_flags |= CH_FIFO_ENABLED;
-
-       /* Assert any signals we want up */
-       writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr);
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-/* Make the UART completely turn off. */
-static void neo_uart_off(struct channel_t *ch)
-{
-       /* Turn off UART enhanced bits */
-       writeb(0, &ch->ch_neo_uart->efr);
-
-       /* Stop all interrupts from occurring. */
-       writeb(0, &ch->ch_neo_uart->ier);
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-static uint neo_get_uart_bytes_left(struct channel_t *ch)
-{
-       unsigned char left = 0;
-       unsigned char lsr = readb(&ch->ch_neo_uart->lsr);
-
-       /* We must cache the LSR as some of the bits get reset once read... */
-       ch->ch_cached_lsr |= lsr;
-
-       /* Determine whether the Transmitter is empty or not */
-       if (!(lsr & UART_LSR_TEMT)) {
-               if (ch->ch_flags & CH_TX_FIFO_EMPTY)
-                       tasklet_schedule(&ch->ch_bd->helper_tasklet);
-               left = 1;
-       } else {
-               ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
-               left = 0;
-       }
-
-       return left;
-}
-
-/* Channel lock MUST be held by the calling function! */
-static void neo_send_break(struct channel_t *ch, int msecs)
-{
-       /* If we receive a time of 0, this means turn off the break. */
-
-       if (msecs == 0) {
-               if (ch->ch_flags & CH_BREAK_SENDING) {
-                       unsigned char temp = readb(&ch->ch_neo_uart->lcr);
-
-                       writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
-                       neo_pci_posting_flush(ch->ch_bd);
-                       ch->ch_flags &= ~(CH_BREAK_SENDING);
-                       ch->ch_stop_sending_break = 0;
-               }
-               return;
-       }
-
-       /*
-        * Set the time we should stop sending the break.
-        * If we are already sending a break, toss away the existing
-        * time to stop, and use this new value instead.
-        */
-       ch->ch_stop_sending_break = jiffies + dgnc_jiffies_from_ms(msecs);
-
-       /* Tell the UART to start sending the break */
-       if (!(ch->ch_flags & CH_BREAK_SENDING)) {
-               unsigned char temp = readb(&ch->ch_neo_uart->lcr);
-
-               writeb((temp | UART_LCR_SBC), &ch->ch_neo_uart->lcr);
-               neo_pci_posting_flush(ch->ch_bd);
-               ch->ch_flags |= (CH_BREAK_SENDING);
-       }
-}
-
-/*
- * Sends a specific character as soon as possible to the UART,
- * jumping over any bytes that might be in the write queue.
- *
- * The channel lock MUST be held by the calling function.
- */
-static void neo_send_immediate_char(struct channel_t *ch, unsigned char c)
-{
-       if (!ch)
-               return;
-
-       writeb(c, &ch->ch_neo_uart->txrx);
-       neo_pci_posting_flush(ch->ch_bd);
-}
-
-static unsigned int neo_read_eeprom(unsigned char __iomem *base,
-                                   unsigned int address)
-{
-       unsigned int enable;
-       unsigned int bits;
-       unsigned int databit;
-       unsigned int val;
-
-       /* enable chip select */
-       writeb(NEO_EECS, base + NEO_EEREG);
-       /* READ */
-       enable = address | 0x180;
-
-       for (bits = 9; bits--; ) {
-               databit = (enable & (1 << bits)) ? NEO_EEDI : 0;
-               /* Set read address */
-               writeb(databit | NEO_EECS, base + NEO_EEREG);
-               writeb(databit | NEO_EECS | NEO_EECK, base + NEO_EEREG);
-       }
-
-       val = 0;
-
-       for (bits = 17; bits--; ) {
-               /* clock to EEPROM */
-               writeb(NEO_EECS, base + NEO_EEREG);
-               writeb(NEO_EECS | NEO_EECK, base + NEO_EEREG);
-               val <<= 1;
-               /* read EEPROM */
-               if (readb(base + NEO_EEREG) & NEO_EEDO)
-                       val |= 1;
-       }
-
-       /* clock falling edge */
-       writeb(NEO_EECS, base + NEO_EEREG);
-
-       /* drop chip select */
-       writeb(0x00, base + NEO_EEREG);
-
-       return val;
-}
-
-static void neo_vpd(struct dgnc_board *brd)
-{
-       unsigned int i = 0;
-       unsigned int a;
-
-       if (!brd)
-               return;
-
-       if (!brd->re_map_membase)
-               return;
-
-       /* Store the VPD into our buffer */
-       for (i = 0; i < NEO_VPD_IMAGESIZE; i++) {
-               a = neo_read_eeprom(brd->re_map_membase, i);
-               brd->vpd[i * 2] = a & 0xff;
-               brd->vpd[(i * 2) + 1] = (a >> 8) & 0xff;
-       }
-
-       /*
-        * brd->vpd has different name tags by below index.
-        * 0x08 : long resource name tag
-        * 0x10 : long resource name tage (PCI-66 files)
-        * 0x7F : small resource end tag
-        */
-       if  (((brd->vpd[0x08] != 0x82) &&
-             (brd->vpd[0x10] != 0x82)) ||
-            (brd->vpd[0x7F] != 0x78)) {
-               memset(brd->vpd, '\0', NEO_VPD_IMAGESIZE);
-       } else {
-               /* Search for the serial number */
-               for (i = 0; i < NEO_VPD_IMAGEBYTES - 3; i++)
-                       if (brd->vpd[i] == 'S' && brd->vpd[i + 1] == 'N')
-                               strncpy(brd->serial_num, &brd->vpd[i + 3], 9);
-       }
-}
diff --git a/drivers/staging/dgnc/dgnc_neo.h b/drivers/staging/dgnc/dgnc_neo.h
deleted file mode 100644 (file)
index c30a2c2..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- */
-
-#ifndef _DGNC_NEO_H
-#define _DGNC_NEO_H
-
-#include "dgnc_driver.h"
-
-/**
- * struct neo_uart_struct - Per channel/port NEO UART structure
- *
- * key - W = read write
- *     - R = read only
- *     - U = unused
- *
- * @txrx: (RW) Holding Register.
- * @ier: (RW) Interrupt Enable Register.
- * @isr_fcr: (RW) Interrupt Status Reg/Fifo Control Register.
- * @lcr: (RW) Line Control Register.
- * @mcr: (RW) Modem Control Register.
- * @lsr: (RW) Line Status Register.
- * @msr: (RW) Modem Status Register.
- * @spr: (RW) Scratch Pad Register.
- * @fctr: (RW) Feature Control Register.
- * @efr: (RW) Enhanced Function Register.
- * @tfifo: (RW) Transmit FIFO Register.
- * @rfifo: (RW) Receive  FIFO Register.
- * @xoffchar1: (RW) XOff Character 1 Register.
- * @xoffchar2: (RW) XOff Character 2 Register.
- * @xonchar1: (RW) Xon Character 1 Register.
- * @xonchar2: (RW) XOn Character 2 Register.
- * @reserved1: (U) Reserved by Exar.
- * @txrxburst: (RW)  64 bytes of RX/TX FIFO Data.
- * @reserved2: (U) Reserved by Exar.
- * @rxburst_with_errors: (R) bytes of RX FIFO Data + LSR.
- */
-struct neo_uart_struct {
-       u8 txrx;
-       u8 ier;
-       u8 isr_fcr;
-
-       u8 lcr;
-       u8 mcr;
-       u8 lsr;
-       u8 msr;
-       u8 spr;
-       u8 fctr;
-       u8 efr;
-       u8 tfifo;
-       u8 rfifo;
-       u8 xoffchar1;
-       u8 xoffchar2;
-       u8 xonchar1;
-       u8 xonchar2;
-
-       u8 reserved1[0x2ff - 0x200];
-       u8 txrxburst[64];
-       u8 reserved2[0x37f - 0x340];
-       u8 rxburst_with_errors[64];
-};
-
-/* Where to read the extended interrupt register (32bits instead of 8bits) */
-#define        UART_17158_POLL_ADDR_OFFSET     0x80
-
-/* These are the current dvid's of the Neo boards */
-#define UART_XR17C158_DVID 0x20
-#define UART_XR17D158_DVID 0x20
-#define UART_XR17E158_DVID 0x40
-
-#define NEO_EECK  0x10         /* Clock */
-#define NEO_EECS  0x20         /* Chip Select */
-#define NEO_EEDI  0x40         /* Data In  is an Output Pin */
-#define NEO_EEDO  0x80         /* Data Out is an Input Pin */
-#define NEO_EEREG 0x8E         /* offset to EEPROM control reg */
-
-#define NEO_VPD_IMAGESIZE 0x40 /* size of image to read from EEPROM in words */
-#define NEO_VPD_IMAGEBYTES (NEO_VPD_IMAGESIZE * 2)
-
-/*
- * These are the redefinitions for the FCTR on the XR17C158, since
- * Exar made them different than their earlier design. (XR16C854)
- */
-
-/* These are only applicable when table D is selected */
-#define UART_17158_FCTR_RTS_NODELAY    0x00
-#define UART_17158_FCTR_RTS_4DELAY     0x01
-#define UART_17158_FCTR_RTS_6DELAY     0x02
-#define UART_17158_FCTR_RTS_8DELAY     0x03
-#define UART_17158_FCTR_RTS_12DELAY    0x12
-#define UART_17158_FCTR_RTS_16DELAY    0x05
-#define UART_17158_FCTR_RTS_20DELAY    0x13
-#define UART_17158_FCTR_RTS_24DELAY    0x06
-#define UART_17158_FCTR_RTS_28DELAY    0x14
-#define UART_17158_FCTR_RTS_32DELAY    0x07
-#define UART_17158_FCTR_RTS_36DELAY    0x16
-#define UART_17158_FCTR_RTS_40DELAY    0x08
-#define UART_17158_FCTR_RTS_44DELAY    0x09
-#define UART_17158_FCTR_RTS_48DELAY    0x10
-#define UART_17158_FCTR_RTS_52DELAY    0x11
-
-#define UART_17158_FCTR_RTS_IRDA       0x10
-#define UART_17158_FCTR_RS485          0x20
-#define UART_17158_FCTR_TRGA           0x00
-#define UART_17158_FCTR_TRGB           0x40
-#define UART_17158_FCTR_TRGC           0x80
-#define UART_17158_FCTR_TRGD           0xC0
-
-/* 17158 trigger table selects.. */
-#define UART_17158_FCTR_BIT6           0x40
-#define UART_17158_FCTR_BIT7           0x80
-
-/* 17158 TX/RX memmapped buffer offsets */
-#define UART_17158_RX_FIFOSIZE         64
-#define UART_17158_TX_FIFOSIZE         64
-
-/* 17158 Extended IIR's */
-#define UART_17158_IIR_RDI_TIMEOUT     0x0C    /* Receiver data TIMEOUT */
-#define UART_17158_IIR_XONXOFF         0x10    /* Received an XON/XOFF char */
-#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20        /* CTS/DSR or RTS/DTR
-                                                * state change
-                                                */
-#define UART_17158_IIR_FIFO_ENABLED    0xC0    /* 16550 FIFOs are Enabled */
-
-/*
- * These are the extended interrupts that get sent
- * back to us from the UART's 32bit interrupt register
- */
-#define UART_17158_RX_LINE_STATUS      0x1     /* RX Ready */
-#define UART_17158_RXRDY_TIMEOUT       0x2     /* RX Ready Timeout */
-#define UART_17158_TXRDY               0x3     /* TX Ready */
-#define UART_17158_MSR                 0x4     /* Modem State Change */
-#define UART_17158_TX_AND_FIFO_CLR     0x40    /* Transmitter Holding
-                                                * Reg Empty
-                                                */
-#define UART_17158_RX_FIFO_DATA_ERROR  0x80    /* UART detected an RX FIFO
-                                                * Data error
-                                                */
-
-/*
- * These are the EXTENDED definitions for the 17C158's Interrupt
- * Enable Register.
- */
-#define UART_17158_EFR_ECB     0x10    /* Enhanced control bit */
-#define UART_17158_EFR_IXON    0x2     /* Receiver compares Xon1/Xoff1 */
-#define UART_17158_EFR_IXOFF   0x8     /* Transmit Xon1/Xoff1 */
-#define UART_17158_EFR_RTSDTR  0x40    /* Auto RTS/DTR Flow Control Enable */
-#define UART_17158_EFR_CTSDSR  0x80    /* Auto CTS/DSR Flow Control Enable */
-
-#define UART_17158_XOFF_DETECT 0x1     /* Indicates whether chip saw an
-                                        * incoming XOFF char
-                                        */
-#define UART_17158_XON_DETECT  0x2     /* Indicates whether chip saw an
-                                        * incoming XON char
-                                        */
-
-#define UART_17158_IER_RSVD1   0x10    /* Reserved by Exar */
-#define UART_17158_IER_XOFF    0x20    /* Xoff Interrupt Enable */
-#define UART_17158_IER_RTSDTR  0x40    /* Output Interrupt Enable */
-#define UART_17158_IER_CTSDSR  0x80    /* Input Interrupt Enable */
-
-extern struct board_ops dgnc_neo_ops;
-
-#endif /* _DGNC_NEO_H */
diff --git a/drivers/staging/dgnc/dgnc_pci.h b/drivers/staging/dgnc/dgnc_pci.h
deleted file mode 100644 (file)
index 5984591..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- */
-
-#ifndef _DGNC_PCI_H
-#define _DGNC_PCI_H
-
-/* Maximum number of PCI boards */
-#define PCIMAX 32
-
-#define DIGI_VID                               0x114F
-
-#define PCI_DEVICE_CLASSIC_4_DID               0x0028
-#define PCI_DEVICE_CLASSIC_8_DID               0x0029
-#define PCI_DEVICE_CLASSIC_4_422_DID           0x00D0
-#define PCI_DEVICE_CLASSIC_8_422_DID           0x00D1
-#define PCI_DEVICE_NEO_4_DID                   0x00B0
-#define PCI_DEVICE_NEO_8_DID                   0x00B1
-#define PCI_DEVICE_NEO_2DB9_DID                        0x00C8
-#define PCI_DEVICE_NEO_2DB9PRI_DID             0x00C9
-#define PCI_DEVICE_NEO_2RJ45_DID               0x00CA
-#define PCI_DEVICE_NEO_2RJ45PRI_DID            0x00CB
-#define PCI_DEVICE_NEO_1_422_DID               0x00CC
-#define PCI_DEVICE_NEO_1_422_485_DID           0x00CD
-#define PCI_DEVICE_NEO_2_422_485_DID           0x00CE
-#define PCI_DEVICE_NEO_EXPRESS_8_DID           0x00F0
-#define PCI_DEVICE_NEO_EXPRESS_4_DID           0x00F1
-#define PCI_DEVICE_NEO_EXPRESS_4RJ45_DID       0x00F2
-#define PCI_DEVICE_NEO_EXPRESS_8RJ45_DID       0x00F3
-#define PCI_DEVICE_NEO_EXPRESS_4_IBM_DID       0x00F4
-
-#define PCI_DEVICE_CLASSIC_4_PCI_NAME          "ClassicBoard 4 PCI"
-#define PCI_DEVICE_CLASSIC_8_PCI_NAME          "ClassicBoard 8 PCI"
-#define PCI_DEVICE_CLASSIC_4_422_PCI_NAME      "ClassicBoard 4 422 PCI"
-#define PCI_DEVICE_CLASSIC_8_422_PCI_NAME      "ClassicBoard 8 422 PCI"
-#define PCI_DEVICE_NEO_4_PCI_NAME              "Neo 4 PCI"
-#define PCI_DEVICE_NEO_8_PCI_NAME              "Neo 8 PCI"
-#define PCI_DEVICE_NEO_2DB9_PCI_NAME           "Neo 2 - DB9 Universal PCI"
-#define PCI_DEVICE_NEO_2DB9PRI_PCI_NAME                "Neo 2 - DB9 Universal PCI - Powered Ring Indicator"
-#define PCI_DEVICE_NEO_2RJ45_PCI_NAME          "Neo 2 - RJ45 Universal PCI"
-#define PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME       "Neo 2 - RJ45 Universal PCI - Powered Ring Indicator"
-#define PCI_DEVICE_NEO_1_422_PCI_NAME          "Neo 1 422 PCI"
-#define PCI_DEVICE_NEO_1_422_485_PCI_NAME      "Neo 1 422/485 PCI"
-#define PCI_DEVICE_NEO_2_422_485_PCI_NAME      "Neo 2 422/485 PCI"
-
-#define PCI_DEVICE_NEO_EXPRESS_8_PCI_NAME      "Neo 8 PCI Express"
-#define PCI_DEVICE_NEO_EXPRESS_4_PCI_NAME      "Neo 4 PCI Express"
-#define PCI_DEVICE_NEO_EXPRESS_4RJ45_PCI_NAME  "Neo 4 PCI Express RJ45"
-#define PCI_DEVICE_NEO_EXPRESS_8RJ45_PCI_NAME  "Neo 8 PCI Express RJ45"
-#define PCI_DEVICE_NEO_EXPRESS_4_IBM_PCI_NAME  "Neo 4 PCI Express IBM"
-
-/* Size of memory and I/O for PCI (4 K) */
-#define PCI_RAM_SIZE                           0x1000
-
-/* Size of memory (2MB) */
-#define PCI_MEM_SIZE                           0x1000
-
-#endif /* _DGNC_PCI_H */
index d3736daf8cf2ef039fce857d7cfb829be55e15fc..9f9b9a5b4b27b4b63e75d32544c7dcb6bf23ab48 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2003 Digi International (www.digi.com)
  *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, 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.
  */
 
 /*
@@ -33,9 +24,7 @@
 #include <linux/pci.h>
 #include "dgnc_driver.h"
 #include "dgnc_tty.h"
-#include "dgnc_neo.h"
 #include "dgnc_cls.h"
-#include "dgnc_utils.h"
 
 /* Default transparent print information. */
 
@@ -240,10 +229,7 @@ int dgnc_tty_init(struct dgnc_board *brd)
                ch->ch_pun.un_type = DGNC_PRINT;
                ch->ch_pun.un_dev = i + 128;
 
-               if (brd->bd_uart_offset == 0x200)
-                       ch->ch_neo_uart = vaddr + (brd->bd_uart_offset * i);
-               else
-                       ch->ch_cls_uart = vaddr + (brd->bd_uart_offset * i);
+               ch->ch_cls_uart = vaddr + (brd->bd_uart_offset * i);
 
                ch->ch_bd = brd;
                ch->ch_portnum = i;
@@ -1238,7 +1224,7 @@ static void dgnc_tty_close(struct tty_struct *tty, struct file *file)
                        if (ch->ch_close_delay) {
                                spin_unlock_irqrestore(&ch->ch_lock,
                                                       flags);
-                               dgnc_ms_sleep(ch->ch_close_delay);
+                               msleep_interruptible(ch->ch_close_delay);
                                spin_lock_irqsave(&ch->ch_lock, flags);
                        }
                }
index 6c58f1b3461a99b5fa937c50d21fa157b7c577e0..00e31035b83de1a1968429d992376a3f4cebf721 100644 (file)
@@ -1,16 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright 2003 Digi International (www.digi.com)
  *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
  */
 
 #ifndef _DGNC_TTY_H
diff --git a/drivers/staging/dgnc/dgnc_utils.c b/drivers/staging/dgnc/dgnc_utils.c
deleted file mode 100644 (file)
index 620f574..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/tty.h>
-#include <linux/sched/signal.h>
-#include "dgnc_utils.h"
-
-/**
- * dgnc_ms_sleep - Put the driver to sleep
- * @ms - milliseconds to sleep
- *
- * Return: 0 if timed out, if interrupted by a signal return signal.
- */
-int dgnc_ms_sleep(ulong ms)
-{
-       __set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout((ms * HZ) / 1000);
-       return signal_pending(current);
-}
diff --git a/drivers/staging/dgnc/dgnc_utils.h b/drivers/staging/dgnc/dgnc_utils.h
deleted file mode 100644 (file)
index b30527f..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _DGNC_UTILS_H
-#define _DGNC_UTILS_H
-
-int dgnc_ms_sleep(ulong ms);
-
-#endif /* _DGNC_UTILS_H */
index 46b06b07bbf2a026b68b526eb96ca6bafbd88f4f..b414ee80db88604b0ea2022f5594a9dcca136064 100644 (file)
@@ -1,50 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright 2003 Digi International (www.digi.com)
  *     Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
  */
 
 #ifndef _DIGI_H
 #define _DIGI_H
 
-#ifndef TIOCM_LE
-#define                TIOCM_LE        0x01            /* line enable */
-#define                TIOCM_DTR       0x02            /* data terminal ready */
-#define                TIOCM_RTS       0x04            /* request to send */
-#define                TIOCM_ST        0x08            /* secondary transmit */
-#define                TIOCM_SR        0x10            /* secondary receive */
-#define                TIOCM_CTS       0x20            /* clear to send */
-#define                TIOCM_CAR       0x40            /* carrier detect */
-#define                TIOCM_RNG       0x80            /* ring indicator */
-#define                TIOCM_DSR       0x100           /* data set ready */
-#define                TIOCM_RI        TIOCM_RNG       /* ring (alternate) */
-#define                TIOCM_CD        TIOCM_CAR       /* carrier detect (alt) */
-#endif
-
-#if !defined(TIOCMSET)
-#define        TIOCMSET        (('d' << 8) | 252)      /* set modem ctrl state */
-#define        TIOCMGET        (('d' << 8) | 253)      /* set modem ctrl state */
-#endif
-
-#if !defined(TIOCMBIC)
-#define        TIOCMBIC        (('d' << 8) | 254)      /* set modem ctrl state */
-#define        TIOCMBIS        (('d' << 8) | 255)      /* set modem ctrl state */
-#endif
-
 #define DIGI_GETA      (('e' << 8) | 94)       /* Read params */
 #define DIGI_SETA      (('e' << 8) | 95)       /* Set params */
 #define DIGI_SETAW     (('e' << 8) | 96)       /* Drain & set params */
 #define DIGI_SETAF     (('e' << 8) | 97)       /* Drain, flush & set params */
-#define DIGI_GET_NI_INFO (('d' << 8) | 250)    /* Non-intelligent state info */
 #define DIGI_LOOPBACK (('d' << 8) | 252)       /* Enable/disable UART
                                                 * internal loopback
                                                 */
@@ -87,49 +53,6 @@ struct digi_t {
        char            digi_term[DIGI_TSIZ];
 };
 
-/**
- * struct digi_dinfo - Driver status information.
- * @dinfo_nboards: Number of boards configured.
- * @dinfo_reserved: Not used, for future expansion.
- * @dinfio_version: Driver version.
- */
-struct digi_dinfo {
-       unsigned int    dinfo_nboards;
-       char            dinfo_reserved[12];
-       char            dinfo_version[16];
-};
-
-#define        DIGI_GETDD      (('d' << 8) | 248)      /* get driver info */
-
-/**
- * struct digi_info - Ioctl commands for per board information.
- *
- * Physsize and memsize differ when board has "windowed" memory.
- *
- * @info_bdnum: Board number (0 based).
- * @info_ioport: IO port address.
- * @indo_physaddr: Memory address.
- * @info_physize: Size of host memory window.
- * @info_memsize: Amount of dual-port memory on board.
- * @info_bdtype: Board type.
- * @info_nports: Number of ports.
- * @info_bdstate: Board state.
- * @info_reserved: Not used, for future expansion.
- */
-struct digi_info {
-       unsigned int    info_bdnum;
-       unsigned int    info_ioport;
-       unsigned int    info_physaddr;
-       unsigned int    info_physsize;
-       unsigned int    info_memsize;
-       unsigned short  info_bdtype;
-       unsigned short  info_nports;
-       char            info_bdstate;
-       char            info_reserved[7];
-};
-
-#define        DIGI_GETBD      (('d' << 8) | 249)      /* get board info */
-
 /**
  * struct digi_getbuffer - Holds buffer use counts.
  */
@@ -161,10 +84,6 @@ struct digi_getcounter {
        unsigned long tbytes;
 };
 
-/* Board State Definitions */
-#define        BD_RUNNING      0x0
-#define        BD_NOFEP        0x5
-
 #define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) /* Set integer baud rate */
 #define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) /* Get integer baud rate */
 
@@ -204,11 +123,6 @@ struct ni_info {
        unsigned int baud;
 };
 
-#define T_CLASSIC 0002
-#define T_PCIBUS 0400
-#define T_NEO_EXPRESS 0001
-#define T_NEO 0000
-
 #define TTY_FLIPBUF_SIZE 512
 
 #endif /* _DIGI_H */
index bb010cb98a1cc1c66146a197e9f4aaa15fd8c5ca..7517001fb8f09f70796cd99439996aa266ca8f18 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *  drivers/usb/gadget/emxx_udc.c
  *     EMXX FCD (Function Controller Driver) for USB.
  *
  *  Copyright (C) 2010 Renesas Electronics Corporation
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *  GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
index 928d531a5115e9719cac9b3af8ecd9cc4e2fa117..8337e38c238a271a25e2f4d6b920e15b018d65d2 100644 (file)
@@ -1,16 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  *  EMXX FCD (Function Controller Driver) for USB.
  *
  *  Copyright (C) 2010 Renesas Electronics Corporation
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *  GNU General Public License for more details.
  */
 
 #ifndef _LINUX_EMXX_H
index dba676761d721cfc82e586983195a88dbafe8f27..84b2e7ebc0240fb8d80fbc605e88a15669c90666 100644 (file)
@@ -135,12 +135,6 @@ config FB_TFT_SSD1306
        help
          Framebuffer support for SSD1306
 
-config FB_TFT_SSD1325
-        tristate "FB driver for the SSD1325 OLED Controller"
-        depends on FB_TFT
-        help
-          Framebuffer support for SSD1305
-
 config FB_TFT_SSD1331
        tristate "FB driver for the SSD1331 LCD Controller"
        depends on FB_TFT
index 456a8dd65cafc02bfe6a55b051c595d44361543f..f6f30f5bf15a59807ca99b56858605aaacd92375 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for Two KS0108 LCD controllers in AGM1264K-FL display
  *
  * Copyright (C) 2014 ololoshka2871
- *
- * 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/module.h>
index 6010e6cbbd723d05eab2868d8906b226e17381d5..a58c514f47210c4c542eca8ecf78c6eb585f63e1 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the uPD161704 LCD Controller
  *
@@ -6,16 +7,6 @@
  * Based on fb_ili9325.c by Noralf Tronnes
  * Based on ili9325.c by Jeroen Domburg
  * Init code from UTFT library by Henning Karlsen
- *
- * 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/module.h>
index fbd5ef5252438f67e78ac7931708c349c2651fec..d47dcf31fffb1558573799855fcb5aac7f3caa1d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the HX8340BN LCD Controller
  *
@@ -7,16 +8,6 @@
  * This is done by transferring eight 9-bit words in 9 bytes.
  *
  * Copyright (C) 2013 Noralf Tronnes
- *
- * 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/module.h>
index bbf78f8644a87341a491d5cca603f5820ee13357..0b605303813e99a0dabedda47a3f85b063865cec 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the HX8347D LCD Controller
  *
  * Copyright (C) 2013 Christian Vogelgsang
  *
  * Based on driver code found here: https://github.com/watterott/r61505u-Adapter
- *
- * 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/module.h>
index 2c18051a44b32802a5879318b3ae044799d2c8f3..3e73b69b6a27627833e9f19d83b63c32bb1ac4b7 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the HX8353D LCD Controller
  *
  * Copyright (c) 2014 Petr Olivka
  * Copyright (c) 2013 Noralf Tronnes
- *
- * 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/module.h>
index 32e6efe1d0a79c8df97a14e2dbc8614549b0a944..94a357e8fdf6a60903ea9f5a0cc597b1eb10e773 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the HX8357D LCD Controller
  * Copyright (C) 2015 Adafruit Industries
@@ -6,16 +7,6 @@
  * Copyright (C) 2013 Christian Vogelgsang
  *
  * Based on driver code found here: https://github.com/watterott/r61505u-Adapter
- *
- * 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/module.h>
index e281921d4a975a4e01778d722abfae0979c2355f..6180b093f94ffae2f83b197e2846d939300c48a7 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: MIT */
 /*
  * This is our library for the Adafruit  ILI9341 Breakout and Shield
  * ----> http://www.adafruit.com/products/1651
index 045cadc3bc65466274e16e6484c65f25865c941b..fd3dd671509ffcd1b80c9cf0ec5a73e4de930fe3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the ILI9163 LCD Controller
  *
@@ -5,16 +6,6 @@
  *
  * Based on ili9325.c by Noralf Tronnes and
  * .S.U.M.O.T.O.Y. by Max MC Costa (https://github.com/sumotoy/TFT_ILI9163C).
- *
- * 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/module.h>
index 20ba86da028ba4dc2eb39dde0e0c5bf0892d42f8..501eee7dce4cc14792db6375e6a0a03168778fb3 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the ILI9320 LCD Controller
  *
  * Copyright (C) 2013 Noralf Tronnes
- *
- * 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/module.h>
index 7f9e9b25490e1e155497efc1c8e1e9aeb43e299d..d6b1d4be9ff4f68860a77a8670482110db6858ba 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the ILI9325 LCD Controller
  *
  * Copyright (C) 2013 Noralf Tronnes
  *
  * Based on ili9325.c by Jeroen Domburg
- *
- * 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/module.h>
index 0711121c303c8cee6416170b580ff5c36b8af27c..430f21e50f4db473af50d369decce47018a67a37 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the ILI9340 LCD Controller
  *
  * Copyright (C) 2013 Noralf Tronnes
- *
- * 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/module.h>
index 21a98e9e1a1477271614487468f31dc6a8fe129d..a10e8c9de438a5a53cb9870bf222bd14f6ebb74f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the ILI9341 LCD display controller
  *
@@ -8,16 +9,6 @@
  *
  * Copyright (C) 2013 Christian Vogelgsang
  * Based on adafruit22fb.c by Noralf Tronnes
- *
- * 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/module.h>
index 7f182a1c084c2ac11def004e60d9187e8e4e48c7..19eba085ea53ee2e132c9572c148b8fac8d15352 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the ILI9481 LCD Controller
  *
  * Copyright (c) 2014 Petr Olivka
  * Copyright (c) 2013 Noralf Tronnes
- *
- * 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/module.h>
index ddd07a64c48aa757bc49d619427594e12943407f..66210a7137fccc8778409181887e8a41b8ad8882 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the ILI9486 LCD Controller
  *
  * Copyright (C) 2014 Noralf Tronnes
- *
- * 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/module.h>
index 87f678a314ccf5591ecbf1434848f281f8b951ec..32172f8f79f03bd02fd41b4def06488c0c6f07dc 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the PCD8544 LCD Controller
  *
@@ -5,16 +6,6 @@
  * Any pixel value except 0 turns the pixel on.
  *
  * Copyright (C) 2013 Noralf Tronnes
- *
- * 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/module.h>
index 6d1cad85957bcb2128a2f2ddc97f8d5c30fc291c..5d3b76ca74d8153bb54e8214c26821ac561b69ae 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FBTFT driver for the RA8875 LCD Controller
  * Copyright by Pf@nne & NOTRO
- *
- * 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/module.h>
index c12855bb689108a5418f626ae7485a6d2795d15e..75295760f49173fd7b9adc58e6413d8492ee8815 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the S6D02A1 LCD Controller
  *
  * Based on fb_st7735r.c by Noralf Tronnes
  * Init code from UTFT library by Henning Karlsen
- *
- * 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/module.h>
index 3b36ed50d491a58961cd0580ae906c8017c03f4c..b90244259d4376a71ee53de96cbfd002a96f6e49 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the S6D1121 LCD Controller
  *
@@ -6,16 +7,6 @@
  * Based on fb_ili9325.c by Noralf Tronnes
  * Based on ili9325.c by Jeroen Domburg
  * Init code from UTFT library by Henning Karlsen
- *
- * 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/module.h>
index 89c27a440305dbf08fc79b9938ef6829890d99f9..3fc18c0a6f11d03762b050c9f0d150073b8af04f 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the SH1106 OLED Controller
  * Based on the SSD1306 driver by Noralf Tronnes
  *
  * Copyright (C) 2017 Heiner Kallweit
- *
- * 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/module.h>
index 129e175fcd7eabb6b0f8f9c0a4b014d9ff3aa708..cbf22e1f4b617f4a7bc800c21830ff6d836fb2d8 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the SSD1289 LCD Controller
  *
  * Copyright (C) 2013 Noralf Tronnes
  *
  * Init sequence taken from ITDB02_Graph16.cpp - (C)2010-2011 Henning Karlsen
- *
- * 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/module.h>
index 33c03872ca849ff6d82826191eca556df33fd42e..3515888d94c98073a691a97a772b0c0cb2cb3e85 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the SSD1305 OLED Controller
  *
  * based on SSD1306 driver by Noralf Tronnes
- *
- * 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/module.h>
index 96c58de85288ed7342e647f63a907311bc348ee8..9276be499303b014e70b8ca6fd29c90ca2305ccb 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the SSD1306 OLED Controller
  *
  * Copyright (C) 2013 Noralf Tronnes
- *
- * 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/module.h>
index b7e40c24f58ed70569a084902377060d24351127..1a469b3c92d49ef6d601b4ff69c10af513016c50 100644 (file)
@@ -1,15 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the SSD1325 OLED Controller
- *
- * 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/module.h>
index e4a759b54ba031e4659ad878ff6cf7088433e38b..383e197cf56ad244f492ca59ce9190b09f542a5c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
index e62235d4d9e7ea0466ce5d19c041a97974b88294..b8ef75f5e8568fb41cb1936a0bcbc6b42b61b255 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
index d98522a393447aa4ab7243c905394cc76c259464..631208bd3a17f6ad946ae9e39a1f9c972ce78b91 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the ST7735R LCD Controller
  *
  * Copyright (C) 2013 Noralf Tronnes
- *
- * 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/module.h>
index a5d7c87557f854024c30095629856f1e62f3bbe7..7d7573a7b615ab5fd46f0854bbf28ef326366f55 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the ST7789V LCD Controller
  *
  * Copyright (C) 2015 Dennis Menschel
- *
- * 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/bitops.h>
index 097e71cfef62ea36679fa05eeee4ac4f7dc40efc..e463b0ddf16d53cdf35e6665bda903eb118c07f8 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Custom FB driver for tinylcd.com display
  *
  * Copyright (C) 2013 Noralf Tronnes
- *
- * 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/module.h>
index 4302e822de3b90e54581f4495ffc44118ec1e9a0..277b6ed9c725bd73adfe432446b9b00e9c491491 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the TLS8204 LCD Controller
  *
@@ -6,16 +7,6 @@
  *
  * Copyright (C) 2013 Noralf Tronnes
  * Copyright (C) 2014 Michael Hope (adapted for the TLS8204)
- *
- * 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/module.h>
index 8eb5e7f10fb50d3b908200bc82323d8a6e35f01a..4d65567eefe29a560ae70ffcc698fd46075eb032 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the UltraChip UC1611 LCD controller
  *
  * The display is 4-bit grayscale (16 shades) 240x160.
  *
  * Copyright (C) 2015 Henri Chain
- *
- * 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/module.h>
index 78899a172c7e37d47eb05ad6da1569e06fcd581b..0a3531d6eb3960f2ef22372bb0bc8b968328c3ee 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the UC1701 LCD Controller
  *
@@ -5,16 +6,6 @@
  * Any pixel value except 0 turns the pixel on.
  *
  * Copyright (C) 2014 Juergen Holzmann
- *
- * 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/module.h>
index 970b8430eccf7d00327793674f7cbce19b70e209..acc425fdf34e03a0d04be8929e976edafd5b5028 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the uPD161704 LCD Controller
  *
@@ -6,16 +7,6 @@
  * Based on fb_ili9325.c by Noralf Tronnes
  * Based on ili9325.c by Jeroen Domburg
  * Init code from UTFT library by Henning Karlsen
- *
- * 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/module.h>
index 180e5be6fa4f730ba0ad2c4d2a09381b9db7f306..bfd1527f20f717db1a7d85d4a4cc73b32f4d7007 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FB driver for the Watterott LCD Controller
  *
  * Copyright (C) 2013 Noralf Tronnes
- *
- * 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/module.h>
index 6d0363deba6193528342bf3306a84e83979b6c24..0e36b66ae5f75d58a9216569d7f86a3da991fbbf 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2013 Noralf Tronnes
  *
  * This driver is inspired by:
  *   st7735fb.c, Copyright (C) 2011, Matt Porter
  *   broadsheetfb.c, Copyright (C) 2008, Jaya Kumar
- *
- * 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/module.h>
@@ -1367,20 +1358,18 @@ int fbtft_probe_common(struct fbtft_display *display,
        }
 
        /* write register functions */
-       if (display->regwidth == 8 && display->buswidth == 8) {
+       if (display->regwidth == 8 && display->buswidth == 8)
                par->fbtftops.write_register = fbtft_write_reg8_bus8;
-       } else
-       if (display->regwidth == 8 && display->buswidth == 9 && par->spi) {
+       else if (display->regwidth == 8 && display->buswidth == 9 && par->spi)
                par->fbtftops.write_register = fbtft_write_reg8_bus9;
-       } else if (display->regwidth == 16 && display->buswidth == 8) {
+       else if (display->regwidth == 16 && display->buswidth == 8)
                par->fbtftops.write_register = fbtft_write_reg16_bus8;
-       } else if (display->regwidth == 16 && display->buswidth == 16) {
+       else if (display->regwidth == 16 && display->buswidth == 16)
                par->fbtftops.write_register = fbtft_write_reg16_bus16;
-       } else {
+       else
                dev_warn(dev,
-                       "no default functions for regwidth=%d and buswidth=%d\n",
-                       display->regwidth, display->buswidth);
-       }
+                        "no default functions for regwidth=%d and buswidth=%d\n",
+                        display->regwidth, display->buswidth);
 
        /* write_vmem() functions */
        if (display->buswidth == 8)
index 488ab788138e1805529f33367a59de57a3a8b462..e19e64e0d094c26078c45b1ff7df924a62962a3c 100644 (file)
@@ -1,16 +1,5 @@
-/*
- * Copyright (C) 2013 Noralf Tronnes
- *
- * 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.
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2013 Noralf Tronnes */
 
 #ifndef __LINUX_FBTFT_H
 #define __LINUX_FBTFT_H
index 0d974738c1c4e9332e74b3f7adcb8721d0b1d080..ec8477674b7d770964b3c3019893c01e4119697e 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *
  * Copyright (C) 2013, Noralf Tronnes
- *
- * 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) "fbtft_device: " fmt
index 7134624a16c2da9397e178c28fb8869e1d7002e6..f676c9b853f10f8253decf4063e67df6ef9d7dd8 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Generic FB driver for TFT LCD displays
  *
  * Copyright (C) 2013 Noralf Tronnes
- *
- * 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/module.h>
index 25b9bf6f54bbdc7cd07b6a163a9dd01a0364f617..ae2ff4a4a472890933134c6853ea679da70a137c 100644 (file)
@@ -1,17 +1,5 @@
-/*
- * Copyright (C) 2013 Noralf Tronnes
- *
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2013 Noralf Tronnes */
 
 #ifndef __LINUX_FBTFT_INTERNAL_H
 #define __LINUX_FBTFT_INTERNAL_H
index 0d8ed002adcbab4b764ef949d4eaec1f621c5e07..2817e67df3d5f0b0c225d5247c11ff00102e8669 100644 (file)
@@ -230,7 +230,8 @@ static struct sk_buff *build_frag_skb(struct dpaa2_eth_priv *priv,
 static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
                         struct dpaa2_eth_channel *ch,
                         const struct dpaa2_fd *fd,
-                        struct napi_struct *napi)
+                        struct napi_struct *napi,
+                        u16 queue_id)
 {
        dma_addr_t addr = dpaa2_fd_get_addr(fd);
        u8 fd_format = dpaa2_fd_get_format(fd);
@@ -249,7 +250,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
        vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
        dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, DMA_FROM_DEVICE);
 
-       fas = dpaa2_get_fas(vaddr);
+       fas = dpaa2_get_fas(vaddr, false);
        prefetch(fas);
        buf_data = vaddr + dpaa2_fd_get_offset(fd);
        prefetch(buf_data);
@@ -281,6 +282,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
        }
 
        skb->protocol = eth_type_trans(skb, priv->net_dev);
+       skb_record_rx_queue(skb, queue_id);
 
        percpu_stats->rx_packets++;
        percpu_stats->rx_bytes += dpaa2_fd_get_len(fd);
@@ -325,7 +327,7 @@ static int consume_frames(struct dpaa2_eth_channel *ch)
                fq = (struct dpaa2_eth_fq *)dpaa2_dq_fqd_ctx(dq);
                fq->stats.frames++;
 
-               fq->consume(priv, ch, fd, &ch->napi);
+               fq->consume(priv, ch, fd, &ch->napi, fq->flowid);
                cleaned++;
        } while (!is_last);
 
@@ -348,7 +350,6 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
        int num_sg;
        int num_dma_bufs;
        struct dpaa2_eth_swa *swa;
-       struct dpaa2_fas *fas;
 
        /* Create and map scatterlist.
         * We don't advertise NETIF_F_FRAGLIST, so skb_to_sgvec() will not have
@@ -379,15 +380,6 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
                goto sgt_buf_alloc_failed;
        }
        sgt_buf = PTR_ALIGN(sgt_buf, DPAA2_ETH_TX_BUF_ALIGN);
-
-       /* PTA from egress side is passed as is to the confirmation side so
-        * we need to clear some fields here in order to find consistent values
-        * on TX confirmation. We are clearing FAS (Frame Annotation Status)
-        * field from the hardware annotation area
-        */
-       fas = dpaa2_get_fas(sgt_buf);
-       memset(fas, 0, DPAA2_FAS_SIZE);
-
        sgt = (struct dpaa2_sg_entry *)(sgt_buf + priv->tx_data_offset);
 
        /* Fill in the HW SGT structure.
@@ -424,8 +416,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
        dpaa2_fd_set_format(fd, dpaa2_fd_sg);
        dpaa2_fd_set_addr(fd, addr);
        dpaa2_fd_set_len(fd, skb->len);
-       dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_ASAL | DPAA2_FD_CTRL_PTA |
-                         DPAA2_FD_CTRL_PTV1);
+       dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
 
        return 0;
 
@@ -444,22 +435,19 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
                           struct dpaa2_fd *fd)
 {
        struct device *dev = priv->net_dev->dev.parent;
-       u8 *buffer_start;
-       struct dpaa2_fas *fas;
+       u8 *buffer_start, *aligned_start;
        struct sk_buff **skbh;
        dma_addr_t addr;
 
-       buffer_start = PTR_ALIGN(skb->data - priv->tx_data_offset -
-                                DPAA2_ETH_TX_BUF_ALIGN,
-                                DPAA2_ETH_TX_BUF_ALIGN);
+       buffer_start = skb->data - dpaa2_eth_needed_headroom(priv, skb);
 
-       /* PTA from egress side is passed as is to the confirmation side so
-        * we need to clear some fields here in order to find consistent values
-        * on TX confirmation. We are clearing FAS (Frame Annotation Status)
-        * field from the hardware annotation area
+       /* If there's enough room to align the FD address, do it.
+        * It will help hardware optimize accesses.
         */
-       fas = dpaa2_get_fas(buffer_start);
-       memset(fas, 0, DPAA2_FAS_SIZE);
+       aligned_start = PTR_ALIGN(buffer_start - DPAA2_ETH_TX_BUF_ALIGN,
+                                 DPAA2_ETH_TX_BUF_ALIGN);
+       if (aligned_start >= skb->head)
+               buffer_start = aligned_start;
 
        /* Store a backpointer to the skb at the beginning of the buffer
         * (in the private data area) such that we can release it
@@ -478,8 +466,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
        dpaa2_fd_set_offset(fd, (u16)(skb->data - buffer_start));
        dpaa2_fd_set_len(fd, skb->len);
        dpaa2_fd_set_format(fd, dpaa2_fd_single);
-       dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_ASAL | DPAA2_FD_CTRL_PTA |
-                         DPAA2_FD_CTRL_PTV1);
+       dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
 
        return 0;
 }
@@ -494,8 +481,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
  * to be checked if we're on the confirmation path.
  */
 static void free_tx_fd(const struct dpaa2_eth_priv *priv,
-                      const struct dpaa2_fd *fd,
-                      u32 *status)
+                      const struct dpaa2_fd *fd)
 {
        struct device *dev = priv->net_dev->dev.parent;
        dma_addr_t fd_addr;
@@ -506,11 +492,9 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
        int num_sg, num_dma_bufs;
        struct dpaa2_eth_swa *swa;
        u8 fd_format = dpaa2_fd_get_format(fd);
-       struct dpaa2_fas *fas;
 
        fd_addr = dpaa2_fd_get_addr(fd);
        skbh = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
-       fas = dpaa2_get_fas(skbh);
 
        if (fd_format == dpaa2_fd_single) {
                skb = *skbh;
@@ -537,19 +521,10 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
                       sizeof(struct dpaa2_sg_entry) * (1 + num_dma_bufs);
                dma_unmap_single(dev, fd_addr, unmap_size, DMA_BIDIRECTIONAL);
        } else {
-               /* Unsupported format, mark it as errored and give up */
-               if (status)
-                       *status = ~0;
+               netdev_dbg(priv->net_dev, "Invalid FD format\n");
                return;
        }
 
-       /* Read the status from the Frame Annotation after we unmap the first
-        * buffer but before we free it. The caller function is responsible
-        * for checking the status value.
-        */
-       if (status)
-               *status = le32_to_cpu(fas->status);
-
        /* Free SGT buffer kmalloc'ed on tx */
        if (fd_format != dpaa2_fd_single)
                kfree(skbh);
@@ -566,19 +541,22 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
        struct dpaa2_eth_drv_stats *percpu_extras;
        struct dpaa2_eth_fq *fq;
        u16 queue_mapping;
+       unsigned int needed_headroom;
        int err, i;
 
        percpu_stats = this_cpu_ptr(priv->percpu_stats);
        percpu_extras = this_cpu_ptr(priv->percpu_extras);
 
-       if (unlikely(skb_headroom(skb) < dpaa2_eth_needed_headroom(priv))) {
+       needed_headroom = dpaa2_eth_needed_headroom(priv, skb);
+       if (skb_headroom(skb) < needed_headroom) {
                struct sk_buff *ns;
 
-               ns = skb_realloc_headroom(skb, dpaa2_eth_needed_headroom(priv));
+               ns = skb_realloc_headroom(skb, needed_headroom);
                if (unlikely(!ns)) {
                        percpu_stats->tx_dropped++;
                        goto err_alloc_headroom;
                }
+               percpu_extras->tx_reallocs++;
                dev_kfree_skb(skb);
                skb = ns;
        }
@@ -612,13 +590,15 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
        /* Tracing point */
        trace_dpaa2_tx_fd(net_dev, &fd);
 
-       /* TxConf FQ selection primarily based on cpu affinity; this is
-        * non-migratable context, so it's safe to call smp_processor_id().
+       /* TxConf FQ selection relies on queue id from the stack.
+        * In case of a forwarded frame from another DPNI interface, we choose
+        * a queue affined to the same core that processed the Rx frame
         */
-       queue_mapping = smp_processor_id() % dpaa2_eth_queue_count(priv);
+       queue_mapping = skb_get_queue_mapping(skb);
        fq = &priv->fq[queue_mapping];
        for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
-               err = dpaa2_io_service_enqueue_qd(NULL, priv->tx_qdid, 0,
+               err = dpaa2_io_service_enqueue_qd(fq->channel->dpio,
+                                                 priv->tx_qdid, 0,
                                                  fq->tx_qdbin, &fd);
                if (err != -EBUSY)
                        break;
@@ -627,7 +607,7 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
        if (unlikely(err < 0)) {
                percpu_stats->tx_errors++;
                /* Clean up everything, including freeing the skb */
-               free_tx_fd(priv, &fd, NULL);
+               free_tx_fd(priv, &fd);
        } else {
                percpu_stats->tx_packets++;
                percpu_stats->tx_bytes += dpaa2_fd_get_len(&fd);
@@ -646,13 +626,12 @@ err_alloc_headroom:
 static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
                              struct dpaa2_eth_channel *ch,
                              const struct dpaa2_fd *fd,
-                             struct napi_struct *napi __always_unused)
+                             struct napi_struct *napi __always_unused,
+                             u16 queue_id __always_unused)
 {
        struct rtnl_link_stats64 *percpu_stats;
        struct dpaa2_eth_drv_stats *percpu_extras;
-       u32 status = 0;
        u32 fd_errors;
-       bool has_fas_errors = false;
 
        /* Tracing point */
        trace_dpaa2_tx_conf_fd(priv->net_dev, fd);
@@ -663,29 +642,18 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
 
        /* Check frame errors in the FD field */
        fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK;
-       if (unlikely(fd_errors)) {
-               /* We only check error bits in the FAS field if corresponding
-                * FAERR bit is set in FD and the FAS field is marked as valid
-                */
-               has_fas_errors = (fd_errors & DPAA2_FD_CTRL_FAERR) &&
-                                !!(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV);
-               if (net_ratelimit())
-                       netdev_dbg(priv->net_dev, "TX frame FD error: 0x%08x\n",
-                                  fd_errors);
-       }
-
-       free_tx_fd(priv, fd, has_fas_errors ? &status : NULL);
+       free_tx_fd(priv, fd);
 
        if (likely(!fd_errors))
                return;
 
+       if (net_ratelimit())
+               netdev_dbg(priv->net_dev, "TX frame FD error: 0x%08x\n",
+                          fd_errors);
+
        percpu_stats = this_cpu_ptr(priv->percpu_stats);
        /* Tx-conf logically pertains to the egress path. */
        percpu_stats->tx_errors++;
-
-       if (has_fas_errors && net_ratelimit())
-               netdev_dbg(priv->net_dev, "TX frame FAS error: 0x%08x\n",
-                          status & DPAA2_FAS_TX_ERR_MASK);
 }
 
 static int set_rx_csum(struct dpaa2_eth_priv *priv, bool enable)
@@ -752,7 +720,8 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count)
 /* Perform a single release command to add buffers
  * to the specified buffer pool
  */
-static int add_bufs(struct dpaa2_eth_priv *priv, u16 bpid)
+static int add_bufs(struct dpaa2_eth_priv *priv,
+                   struct dpaa2_eth_channel *ch, u16 bpid)
 {
        struct device *dev = priv->net_dev->dev.parent;
        u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
@@ -786,7 +755,7 @@ static int add_bufs(struct dpaa2_eth_priv *priv, u16 bpid)
 
 release_bufs:
        /* In case the portal is busy, retry until successful */
-       while ((err = dpaa2_io_service_release(NULL, bpid,
+       while ((err = dpaa2_io_service_release(ch->dpio, bpid,
                                               buf_array, i)) == -EBUSY)
                cpu_relax();
 
@@ -827,7 +796,7 @@ static int seed_pool(struct dpaa2_eth_priv *priv, u16 bpid)
        for (j = 0; j < priv->num_channels; j++) {
                for (i = 0; i < DPAA2_ETH_NUM_BUFS;
                     i += DPAA2_ETH_BUFS_PER_CMD) {
-                       new_count = add_bufs(priv, bpid);
+                       new_count = add_bufs(priv, priv->channel[j], bpid);
                        priv->channel[j]->buf_count += new_count;
 
                        if (new_count < DPAA2_ETH_BUFS_PER_CMD) {
@@ -885,7 +854,7 @@ static int refill_pool(struct dpaa2_eth_priv *priv,
                return 0;
 
        do {
-               new_count = add_bufs(priv, bpid);
+               new_count = add_bufs(priv, ch, bpid);
                if (unlikely(!new_count)) {
                        /* Out of memory; abort for now, we'll try later on */
                        break;
@@ -906,7 +875,8 @@ static int pull_channel(struct dpaa2_eth_channel *ch)
 
        /* Retry while portal is busy */
        do {
-               err = dpaa2_io_service_pull_channel(NULL, ch->ch_id, ch->store);
+               err = dpaa2_io_service_pull_channel(ch->dpio, ch->ch_id,
+                                                   ch->store);
                dequeues++;
                cpu_relax();
        } while (err == -EBUSY);
@@ -956,7 +926,7 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
        if (cleaned < budget && napi_complete_done(napi, cleaned)) {
                /* Re-enable data available notifications */
                do {
-                       err = dpaa2_io_service_rearm(NULL, &ch->nctx);
+                       err = dpaa2_io_service_rearm(ch->dpio, &ch->nctx);
                        cpu_relax();
                } while (err == -EBUSY);
                WARN_ONCE(err, "CDAN notifications rearm failed on core %d",
@@ -1564,7 +1534,8 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
                nctx->desired_cpu = i;
 
                /* Register the new context */
-               err = dpaa2_io_service_register(NULL, nctx);
+               channel->dpio = dpaa2_io_service_select(i);
+               err = dpaa2_io_service_register(channel->dpio, nctx);
                if (err) {
                        dev_dbg(dev, "No affine DPIO for cpu %d\n", i);
                        /* If no affine DPIO for this core, there's probably
@@ -1604,7 +1575,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
        return 0;
 
 err_set_cdan:
-       dpaa2_io_service_deregister(NULL, nctx);
+       dpaa2_io_service_deregister(channel->dpio, nctx);
 err_service_reg:
        free_channel(priv, channel);
 err_alloc_ch:
@@ -1627,7 +1598,7 @@ static void free_dpio(struct dpaa2_eth_priv *priv)
        /* deregister CDAN notifications and free channels */
        for (i = 0; i < priv->num_channels; i++) {
                ch = priv->channel[i];
-               dpaa2_io_service_deregister(NULL, &ch->nctx);
+               dpaa2_io_service_deregister(ch->dpio, &ch->nctx);
                free_channel(priv, ch);
        }
 }
@@ -1653,9 +1624,10 @@ static struct dpaa2_eth_channel *get_affine_channel(struct dpaa2_eth_priv *priv,
 static void set_fq_affinity(struct dpaa2_eth_priv *priv)
 {
        struct device *dev = priv->net_dev->dev.parent;
+       struct cpumask xps_mask;
        struct dpaa2_eth_fq *fq;
        int rx_cpu, txc_cpu;
-       int i;
+       int i, err;
 
        /* For each FQ, pick one channel/CPU to deliver frames to.
         * This may well change at runtime, either through irqbalance or
@@ -1674,6 +1646,17 @@ static void set_fq_affinity(struct dpaa2_eth_priv *priv)
                        break;
                case DPAA2_TX_CONF_FQ:
                        fq->target_cpu = txc_cpu;
+
+                       /* Tell the stack to affine to txc_cpu the Tx queue
+                        * associated with the confirmation one
+                        */
+                       cpumask_clear(&xps_mask);
+                       cpumask_set_cpu(txc_cpu, &xps_mask);
+                       err = netif_set_xps_queue(priv->net_dev, &xps_mask,
+                                                 fq->flowid);
+                       if (err)
+                               dev_err(dev, "Error setting XPS queue\n");
+
                        txc_cpu = cpumask_next(txc_cpu, &priv->dpio_cpumask);
                        if (txc_cpu >= nr_cpu_ids)
                                txc_cpu = cpumask_first(&priv->dpio_cpumask);
@@ -1791,10 +1774,8 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
                priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN;
 
        /* tx buffer */
-       buf_layout.pass_frame_status = true;
        buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
-       buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
-                            DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
+       buf_layout.options = DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
        err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
                                     DPNI_QUEUE_TX, &buf_layout);
        if (err) {
@@ -1803,7 +1784,7 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
        }
 
        /* tx-confirm buffer */
-       buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS;
+       buf_layout.options = 0;
        err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
                                     DPNI_QUEUE_TX_CONFIRM, &buf_layout);
        if (err) {
@@ -1826,6 +1807,7 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
                         priv->tx_data_offset);
 
        /* rx buffer */
+       buf_layout.pass_frame_status = true;
        buf_layout.pass_parser_result = true;
        buf_layout.data_align = priv->rx_buf_align;
        buf_layout.data_head_room = dpaa2_eth_rx_head_room(priv);
@@ -2273,7 +2255,6 @@ static int netdev_init(struct net_device *net_dev)
 {
        struct device *dev = net_dev->dev.parent;
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-       u16 rx_headroom, req_headroom;
        u8 bcast_addr[ETH_ALEN];
        u8 num_queues;
        int err;
@@ -2292,24 +2273,6 @@ static int netdev_init(struct net_device *net_dev)
                return err;
        }
 
-       /* Reserve enough space to align buffer as per hardware requirement;
-        * NOTE: priv->tx_data_offset MUST be initialized at this point.
-        */
-       net_dev->needed_headroom = dpaa2_eth_needed_headroom(priv);
-
-       /* If headroom guaranteed by hardware in the Rx frame buffer is
-        * smaller than the Tx headroom required by the stack, issue a
-        * one time warning. This will most likely mean skbs forwarded to
-        * another DPAA2 network interface will get reallocated, with a
-        * significant performance impact.
-        */
-       req_headroom = LL_RESERVED_SPACE(net_dev) - ETH_HLEN;
-       rx_headroom = ALIGN(DPAA2_ETH_RX_HWA_SIZE +
-                           dpaa2_eth_rx_head_room(priv), priv->rx_buf_align);
-       if (req_headroom > rx_headroom)
-               dev_info_once(dev, "Required headroom (%d) greater than available (%d)\n",
-                             req_headroom, rx_headroom);
-
        /* Set MTU limits */
        net_dev->min_mtu = 68;
        net_dev->max_mtu = DPAA2_ETH_MAX_MTU;
index 5b3ab9f62d5eea8ecf964b2e9059035b395f5d38..e577410fdf4fbcffb3b58b9bc8e1c3803d2dbf7a 100644 (file)
@@ -134,7 +134,6 @@ struct dpaa2_eth_swa {
                                         DPAA2_FD_CTRL_FAERR)
 
 /* Annotation bits in FD CTRL */
-#define DPAA2_FD_CTRL_ASAL             0x00010000      /* ASAL = 64 */
 #define DPAA2_FD_CTRL_PTA              0x00800000
 #define DPAA2_FD_CTRL_PTV1             0x00400000
 
@@ -153,10 +152,15 @@ struct dpaa2_fas {
 #define DPAA2_FAS_SIZE                 (sizeof(struct dpaa2_fas))
 
 /* Accessors for the hardware annotation fields that we use */
-#define dpaa2_get_hwa(buf_addr) \
-       ((void *)(buf_addr) + DPAA2_ETH_SWA_SIZE)
-#define dpaa2_get_fas(buf_addr) \
-       (struct dpaa2_fas *)(dpaa2_get_hwa(buf_addr) + DPAA2_FAS_OFFSET)
+static inline void *dpaa2_get_hwa(void *buf_addr, bool swa)
+{
+       return buf_addr + (swa ? DPAA2_ETH_SWA_SIZE : 0);
+}
+
+static inline struct dpaa2_fas *dpaa2_get_fas(void *buf_addr, bool swa)
+{
+       return dpaa2_get_hwa(buf_addr, swa) + DPAA2_FAS_OFFSET;
+}
 
 /* Error and status bits in the frame annotation status word */
 /* Debug frame, otherwise supposed to be discarded */
@@ -203,11 +207,6 @@ struct dpaa2_fas {
                                         DPAA2_FAS_BLE          | \
                                         DPAA2_FAS_L3CE         | \
                                         DPAA2_FAS_L4CE)
-/* Tx errors */
-#define DPAA2_FAS_TX_ERR_MASK          (DPAA2_FAS_KSE          | \
-                                        DPAA2_FAS_EOFHE        | \
-                                        DPAA2_FAS_MNLE         | \
-                                        DPAA2_FAS_TIDE)
 
 /* Time in milliseconds between link state updates */
 #define DPAA2_ETH_LINK_STATE_REFRESH   1000
@@ -226,6 +225,7 @@ struct dpaa2_eth_drv_stats {
        __u64   tx_conf_bytes;
        __u64   tx_sg_frames;
        __u64   tx_sg_bytes;
+       __u64   tx_reallocs;
        __u64   rx_sg_frames;
        __u64   rx_sg_bytes;
        /* Enqueues retried due to portal busy */
@@ -276,7 +276,8 @@ struct dpaa2_eth_fq {
        void (*consume)(struct dpaa2_eth_priv *,
                        struct dpaa2_eth_channel *,
                        const struct dpaa2_fd *,
-                       struct napi_struct *);
+                       struct napi_struct *,
+                       u16 queue_id);
        struct dpaa2_eth_fq_stats stats;
 };
 
@@ -287,6 +288,7 @@ struct dpaa2_eth_channel {
        int ch_id;
        int dpio_id;
        struct napi_struct napi;
+       struct dpaa2_io *dpio;
        struct dpaa2_io_store *store;
        struct dpaa2_eth_priv *priv;
        int buf_count;
@@ -364,9 +366,13 @@ static inline unsigned int dpaa2_eth_buf_raw_size(struct dpaa2_eth_priv *priv)
 }
 
 static inline
-unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv)
+unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv,
+                                      struct sk_buff *skb)
 {
-       return priv->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN - HH_DATA_MOD;
+       if (skb_is_nonlinear(skb))
+               return 0;
+
+       return DPAA2_ETH_SWA_SIZE;
 }
 
 /* Extra headroom space requested to hardware, in order to make sure there's
@@ -374,7 +380,8 @@ unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv)
  */
 static inline unsigned int dpaa2_eth_rx_head_room(struct dpaa2_eth_priv *priv)
 {
-       return dpaa2_eth_needed_headroom(priv) - DPAA2_ETH_RX_HWA_SIZE;
+       return priv->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN -
+              DPAA2_ETH_RX_HWA_SIZE;
 }
 
 static int dpaa2_eth_queue_count(struct dpaa2_eth_priv *priv)
index ebe8fd6ccf2cc526e1d50b69b70b9cf08311c10f..070a3f2a0523868668f3c6d0e8e24f8158c81a06 100644 (file)
@@ -62,6 +62,7 @@ static char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
        "[drv] tx conf bytes",
        "[drv] tx sg frames",
        "[drv] tx sg bytes",
+       "[drv] tx realloc frames",
        "[drv] rx sg frames",
        "[drv] rx sg bytes",
        "[drv] enqueue portal busy",
index 32df07b15e09452aa8fde5971ed2725122eb55a4..3002229bec1bb0ef9a94167dec671bb38269ea20 100644 (file)
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
 source "drivers/staging/fsl-mc/bus/Kconfig"
index 9c6a00128c65f4e83645ad673bc8510b3757fee8..14683889dabd7baca930d514b83eadd96861d170 100644 (file)
@@ -1,2 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
 # Freescale Management Complex (MC) bus drivers
 obj-$(CONFIG_FSL_MC_BUS)       += bus/
diff --git a/drivers/staging/fsl-mc/README.txt b/drivers/staging/fsl-mc/README.txt
deleted file mode 100644 (file)
index 524eda1..0000000
+++ /dev/null
@@ -1,386 +0,0 @@
-Copyright (C) 2015 Freescale Semiconductor Inc.
-
-DPAA2 (Data Path Acceleration Architecture Gen2)
-------------------------------------------------
-
-This document provides an overview of the Freescale DPAA2 architecture
-and how it is integrated into the Linux kernel.
-
-Contents summary
-   -DPAA2 overview
-   -Overview of DPAA2 objects
-   -DPAA2 Linux driver architecture overview
-        -bus driver
-        -DPRC driver
-        -allocator
-        -DPIO driver
-        -Ethernet
-        -MAC
-
-DPAA2 Overview
---------------
-
-DPAA2 is a hardware architecture designed for high-speeed network
-packet processing.  DPAA2 consists of sophisticated mechanisms for
-processing Ethernet packets, queue management, buffer management,
-autonomous L2 switching, virtual Ethernet bridging, and accelerator
-(e.g. crypto) sharing.
-
-A DPAA2 hardware component called the Management Complex (or MC) manages the
-DPAA2 hardware resources.  The MC provides an object-based abstraction for
-software drivers to use the DPAA2 hardware.
-
-The MC uses DPAA2 hardware resources such as queues, buffer pools, and
-network ports to create functional objects/devices such as network
-interfaces, an L2 switch, or accelerator instances.
-
-The MC provides memory-mapped I/O command interfaces (MC portals)
-which DPAA2 software drivers use to operate on DPAA2 objects:
-
-The diagram below shows an overview of the DPAA2 resource management
-architecture:
-
-         +--------------------------------------+
-         |                  OS                  |
-         |                        DPAA2 drivers |
-         |                             |        |
-         +-----------------------------|--------+
-                                       |
-                                       | (create,discover,connect
-                                       |  config,use,destroy)
-                                       |
-                         DPAA2         |
-         +------------------------| mc portal |-+
-         |                             |        |
-         |   +- - - - - - - - - - - - -V- - -+  |
-         |   |                               |  |
-         |   |   Management Complex (MC)     |  |
-         |   |                               |  |
-         |   +- - - - - - - - - - - - - - - -+  |
-         |                                      |
-         | Hardware                  Hardware   |
-         | Resources                 Objects    |
-         | ---------                 -------    |
-         | -queues                   -DPRC      |
-         | -buffer pools             -DPMCP     |
-         | -Eth MACs/ports           -DPIO      |
-         | -network interface        -DPNI      |
-         |  profiles                 -DPMAC     |
-         | -queue portals            -DPBP      |
-         | -MC portals                ...       |
-         |  ...                                 |
-         |                                      |
-         +--------------------------------------+
-
-The MC mediates operations such as create, discover,
-connect, configuration, and destroy.  Fast-path operations
-on data, such as packet transmit/receive, are not mediated by
-the MC and are done directly using memory mapped regions in
-DPIO objects.
-
-Overview of DPAA2 Objects
--------------------------
-The section provides a brief overview of some key DPAA2 objects.
-A simple scenario is described illustrating the objects involved
-in creating a network interfaces.
-
--DPRC (Datapath Resource Container)
-
-    A DPRC is a container object that holds all the other
-    types of DPAA2 objects.  In the example diagram below there
-    are 8 objects of 5 types (DPMCP, DPIO, DPBP, DPNI, and DPMAC)
-    in the container.
-
-    +---------------------------------------------------------+
-    | DPRC                                                    |
-    |                                                         |
-    |  +-------+  +-------+  +-------+  +-------+  +-------+  |
-    |  | DPMCP |  | DPIO  |  | DPBP  |  | DPNI  |  | DPMAC |  |
-    |  +-------+  +-------+  +-------+  +---+---+  +---+---+  |
-    |  | DPMCP |  | DPIO  |                                   |
-    |  +-------+  +-------+                                   |
-    |  | DPMCP |                                              |
-    |  +-------+                                              |
-    |                                                         |
-    +---------------------------------------------------------+
-
-    From the point of view of an OS, a DPRC behaves similar to a plug and
-    play bus, like PCI.  DPRC commands can be used to enumerate the contents
-    of the DPRC, discover the hardware objects present (including mappable
-    regions and interrupts).
-
-     DPRC.1 (bus)
-       |
-       +--+--------+-------+-------+-------+
-          |        |       |       |       |
-        DPMCP.1  DPIO.1  DPBP.1  DPNI.1  DPMAC.1
-        DPMCP.2  DPIO.2
-        DPMCP.3
-
-    Hardware objects can be created and destroyed dynamically, providing
-    the ability to hot plug/unplug objects in and out of the DPRC.
-
-    A DPRC has a mappable MMIO region (an MC portal) that can be used
-    to send MC commands.  It has an interrupt for status events (like
-    hotplug).
-
-    All objects in a container share the same hardware "isolation context".
-    This means that with respect to an IOMMU the isolation granularity
-    is at the DPRC (container) level, not at the individual object
-    level.
-
-    DPRCs can be defined statically and populated with objects
-    via a config file passed to the MC when firmware starts
-    it.
-
--DPAA2 Objects for an Ethernet Network Interface
-
-    A typical Ethernet NIC is monolithic-- the NIC device contains TX/RX
-    queuing mechanisms, configuration mechanisms, buffer management,
-    physical ports, and interrupts.  DPAA2 uses a more granular approach
-    utilizing multiple hardware objects.  Each object provides specialized
-    functions. Groups of these objects are used by software to provide
-    Ethernet network interface functionality.  This approach provides
-    efficient use of finite hardware resources, flexibility, and
-    performance advantages.
-
-    The diagram below shows the objects needed for a simple
-    network interface configuration on a system with 2 CPUs.
-
-              +---+---+ +---+---+
-                 CPU0     CPU1
-              +---+---+ +---+---+
-                  |         |
-              +---+---+ +---+---+
-                 DPIO     DPIO
-              +---+---+ +---+---+
-                    \     /
-                     \   /
-                      \ /
-                   +---+---+
-                      DPNI  --- DPBP,DPMCP
-                   +---+---+
-                       |
-                       |
-                   +---+---+
-                     DPMAC
-                   +---+---+
-                       |
-                    port/PHY
-
-    Below the objects are described.  For each object a brief description
-    is provided along with a summary of the kinds of operations the object
-    supports and a summary of key resources of the object (MMIO regions
-    and IRQs).
-
-       -DPMAC (Datapath Ethernet MAC): represents an Ethernet MAC, a
-        hardware device that connects to an Ethernet PHY and allows
-        physical transmission and reception of Ethernet frames.
-           -MMIO regions: none
-           -IRQs: DPNI link change
-           -commands: set link up/down, link config, get stats,
-            IRQ config, enable, reset
-
-       -DPNI (Datapath Network Interface): contains TX/RX queues,
-        network interface configuration, and RX buffer pool configuration
-        mechanisms.  The TX/RX queues are in memory and are identified by
-        queue number.
-           -MMIO regions: none
-           -IRQs: link state
-           -commands: port config, offload config, queue config,
-            parse/classify config, IRQ config, enable, reset
-
-       -DPIO (Datapath I/O): provides interfaces to enqueue and dequeue
-        packets and do hardware buffer pool management operations.  The DPAA2
-        architecture separates the mechanism to access queues (the DPIO object)
-        from the queues themselves.  The DPIO provides an MMIO interface to
-        enqueue/dequeue packets.  To enqueue something a descriptor is written
-        to the DPIO MMIO region, which includes the target queue number.
-        There will typically be one DPIO assigned to each CPU.  This allows all
-        CPUs to simultaneously perform enqueue/dequeued operations.  DPIOs are
-        expected to be shared by different DPAA2 drivers.
-           -MMIO regions: queue operations, buffer management
-           -IRQs: data availability, congestion notification, buffer
-                  pool depletion
-           -commands: IRQ config, enable, reset
-
-       -DPBP (Datapath Buffer Pool): represents a hardware buffer
-        pool.
-           -MMIO regions: none
-           -IRQs: none
-           -commands: enable, reset
-
-       -DPMCP (Datapath MC Portal): provides an MC command portal.
-        Used by drivers to send commands to the MC to manage
-        objects.
-           -MMIO regions: MC command portal
-           -IRQs: command completion
-           -commands: IRQ config, enable, reset
-
-    Object Connections
-    ------------------
-    Some objects have explicit relationships that must
-    be configured:
-
-       -DPNI <--> DPMAC
-       -DPNI <--> DPNI
-       -DPNI <--> L2-switch-port
-          A DPNI must be connected to something such as a DPMAC,
-          another DPNI, or L2 switch port.  The DPNI connection
-          is made via a DPRC command.
-
-              +-------+  +-------+
-              | DPNI  |  | DPMAC |
-              +---+---+  +---+---+
-                  |          |
-                  +==========+
-
-       -DPNI <--> DPBP
-          A network interface requires a 'buffer pool' (DPBP
-          object) which provides a list of pointers to memory
-          where received Ethernet data is to be copied.  The
-          Ethernet driver configures the DPBPs associated with
-          the network interface.
-
-    Interrupts
-    ----------
-    All interrupts generated by DPAA2 objects are message
-    interrupts.  At the hardware level message interrupts
-    generated by devices will normally have 3 components--
-    1) a non-spoofable 'device-id' expressed on the hardware
-    bus, 2) an address, 3) a data value.
-
-    In the case of DPAA2 devices/objects, all objects in the
-    same container/DPRC share the same 'device-id'.
-    For ARM-based SoC this is the same as the stream ID.
-
-
-DPAA2 Linux Driver Overview
----------------------------
-
-This section provides an overview of the Linux kernel drivers for
-DPAA2-- 1) the bus driver and associated "DPAA2 infrastructure"
-drivers and 2) functional object drivers (such as Ethernet).
-
-As described previously, a DPRC is a container that holds the other
-types of DPAA2 objects.  It is functionally similar to a plug-and-play
-bus controller.
-
-Each object in the DPRC is a Linux "device" and is bound to a driver.
-The diagram below shows the Linux drivers involved in a networking
-scenario and the objects bound to each driver.  A brief description
-of each driver follows.
-
-                                             +------------+
-                                             | OS Network |
-                                             |   Stack    |
-                 +------------+              +------------+
-                 | Allocator  |. . . . . . . |  Ethernet  |
-                 |(DPMCP,DPBP)|              |   (DPNI)   |
-                 +-.----------+              +---+---+----+
-                  .          .                   ^   |
-                 .            .     <data avail, |   |<enqueue,
-                .              .     tx confirm> |   | dequeue>
-    +-------------+             .                |   |
-    | DPRC driver |              .           +---+---V----+     +---------+
-    |   (DPRC)    |               . . . . . .| DPIO driver|     |   MAC   |
-    +----------+--+                          |  (DPIO)    |     | (DPMAC) |
-               |                             +------+-----+     +-----+---+
-               |<dev add/remove>                    |                 |
-               |                                    |                 |
-          +----+--------------+                     |              +--+---+
-          |   MC-bus driver   |                     |              | PHY  |
-          |                   |                     |              |driver|
-          | /soc/fsl-mc       |                     |              +--+---+
-          +-------------------+                     |                 |
-                                                    |                 |
- ================================ HARDWARE =========|=================|======
-                                                  DPIO                |
-                                                    |                 |
-                                                  DPNI---DPBP         |
-                                                    |                 |
-                                                  DPMAC               |
-                                                    |                 |
-                                                   PHY ---------------+
- ===================================================|========================
-
-A brief description of each driver is provided below.
-
-    MC-bus driver
-    -------------
-    The MC-bus driver is a platform driver and is probed from a
-    node in the device tree (compatible "fsl,qoriq-mc") passed in by boot
-    firmware.  It is responsible for bootstrapping the DPAA2 kernel
-    infrastructure.
-    Key functions include:
-       -registering a new bus type named "fsl-mc" with the kernel,
-        and implementing bus call-backs (e.g. match/uevent/dev_groups)
-       -implementing APIs for DPAA2 driver registration and for device
-        add/remove
-       -creates an MSI IRQ domain
-       -doing a 'device add' to expose the 'root' DPRC, in turn triggering
-        a bind of the root DPRC to the DPRC driver
-    The binding for the MC-bus device-tree node can be consulted here:
-        Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
-
-    DPRC driver
-    -----------
-    The DPRC driver is bound to DPRC objects and does runtime management
-    of a bus instance.  It performs the initial bus scan of the DPRC
-    and handles interrupts for container events such as hot plug by
-    re-scanning the DPRC.
-
-    Allocator
-    ----------
-    Certain objects such as DPMCP and DPBP are generic and fungible,
-    and are intended to be used by other drivers.  For example,
-    the DPAA2 Ethernet driver needs:
-       -DPMCPs to send MC commands, to configure network interfaces
-       -DPBPs for network buffer pools
-
-    The allocator driver registers for these allocatable object types
-    and those objects are bound to the allocator when the bus is probed.
-    The allocator maintains a pool of objects that are available for
-    allocation by other DPAA2 drivers.
-
-    DPIO driver
-    -----------
-    The DPIO driver is bound to DPIO objects and provides services that allow
-    other drivers such as the Ethernet driver to enqueue and dequeue data for
-    their respective objects.
-    Key services include:
-        -data availability notifications
-        -hardware queuing operations (enqueue and dequeue of data)
-        -hardware buffer pool management
-
-    To transmit a packet the Ethernet driver puts data on a queue and
-    invokes a DPIO API.  For receive, the Ethernet driver registers
-    a data availability notification callback.  To dequeue a packet
-    a DPIO API is used.
-
-    There is typically one DPIO object per physical CPU for optimum
-    performance, allowing different CPUs to simultaneously enqueue
-    and dequeue data.
-
-    The DPIO driver operates on behalf of all DPAA2 drivers
-    active in the kernel--  Ethernet, crypto, compression,
-    etc.
-
-    Ethernet
-    --------
-    The Ethernet driver is bound to a DPNI and implements the kernel
-    interfaces needed to connect the DPAA2 network interface to
-    the network stack.
-
-    Each DPNI corresponds to a Linux network interface.
-
-    MAC driver
-    ----------
-    An Ethernet PHY is an off-chip, board specific component and is managed
-    by the appropriate PHY driver via an mdio bus.  The MAC driver
-    plays a role of being a proxy between the PHY driver and the
-    MC.  It does this proxy via the MC commands to a DPMAC object.
-    If the PHY driver signals a link change, the MAC driver notifies
-    the MC via a DPMAC command.  If a network interface is brought
-    up or down, the MC notifies the DPMAC driver via an interrupt and
-    the driver can take appropriate action.
index 504c987447f2674e23e4a7c9448d05e5fda838ef..1f91000491767a9c049a27b3f27edf4c3c39b4fe 100644 (file)
@@ -1,10 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # DPAA2 fsl-mc bus
 #
 # Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
 #
-# This file is released under the GPLv2
-#
 
 config FSL_MC_BUS
        bool "QorIQ DPAA2 fsl-mc bus driver"
index 6df407edfade8f62e4439e5d9597445cea244756..29059db95ecc82dc54ff1d124647868a9704b73b 100644 (file)
@@ -1,10 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Freescale Management Complex (MC) bus drivers
 #
 # Copyright (C) 2014 Freescale Semiconductor, Inc.
 #
-# This file is released under the GPLv2
-#
 obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
 
 mc-bus-driver-objs := fsl-mc-bus.o \
index 5904836fd741ff80616c6d1ff1b9ae0763dd8dd9..0b7f5c041f1968a133c1f4a401a344e39923872b 100644 (file)
@@ -1,33 +1,7 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef _FSL_DPBP_CMD_H
 #define _FSL_DPBP_CMD_H
index 363730a80cbbbb64d76357eef13239c7c6f99b90..a4df84668d5b20087b168c8d53876df271350bf0 100644 (file)
@@ -1,33 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS 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/kernel.h>
 #include "../include/mc.h"
@@ -77,7 +51,7 @@ int dpbp_open(struct fsl_mc_io *mc_io,
 
        return err;
 }
-EXPORT_SYMBOL(dpbp_open);
+EXPORT_SYMBOL_GPL(dpbp_open);
 
 /**
  * dpbp_close() - Close the control session of the object
@@ -103,7 +77,7 @@ int dpbp_close(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dpbp_close);
+EXPORT_SYMBOL_GPL(dpbp_close);
 
 /**
  * dpbp_enable() - Enable the DPBP.
@@ -126,7 +100,7 @@ int dpbp_enable(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dpbp_enable);
+EXPORT_SYMBOL_GPL(dpbp_enable);
 
 /**
  * dpbp_disable() - Disable the DPBP.
@@ -149,7 +123,7 @@ int dpbp_disable(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dpbp_disable);
+EXPORT_SYMBOL_GPL(dpbp_disable);
 
 /**
  * dpbp_is_enabled() - Check if the DPBP is enabled.
@@ -183,7 +157,7 @@ int dpbp_is_enabled(struct fsl_mc_io *mc_io,
 
        return 0;
 }
-EXPORT_SYMBOL(dpbp_is_enabled);
+EXPORT_SYMBOL_GPL(dpbp_is_enabled);
 
 /**
  * dpbp_reset() - Reset the DPBP, returns the object to initial state.
@@ -206,7 +180,7 @@ int dpbp_reset(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dpbp_reset);
+EXPORT_SYMBOL_GPL(dpbp_reset);
 
 /**
  * dpbp_get_attributes - Retrieve DPBP attributes.
@@ -243,7 +217,7 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io,
 
        return 0;
 }
-EXPORT_SYMBOL(dpbp_get_attributes);
+EXPORT_SYMBOL_GPL(dpbp_get_attributes);
 
 /**
  * dpbp_get_api_version - Get Data Path Buffer Pool API version
@@ -276,4 +250,4 @@ int dpbp_get_api_version(struct fsl_mc_io *mc_io,
 
        return 0;
 }
-EXPORT_SYMBOL(dpbp_get_api_version);
+EXPORT_SYMBOL_GPL(dpbp_get_api_version);
index 2bb66988ecf618f6d0a2b3f668ce57f385674cd1..27fa09877970d35cfca48b596194540117b88904 100644 (file)
@@ -1,33 +1,7 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef _FSL_DPCON_CMD_H
 #define _FSL_DPCON_CMD_H
 /* Command IDs */
 #define DPCON_CMDID_CLOSE                      DPCON_CMD(0x800)
 #define DPCON_CMDID_OPEN                       DPCON_CMD(0x808)
-#define DPCON_CMDID_GET_API_VERSION            DPCON_CMD(0xa08)
 
 #define DPCON_CMDID_ENABLE                     DPCON_CMD(0x002)
 #define DPCON_CMDID_DISABLE                    DPCON_CMD(0x003)
 #define DPCON_CMDID_GET_ATTR                   DPCON_CMD(0x004)
 #define DPCON_CMDID_RESET                      DPCON_CMD(0x005)
-#define DPCON_CMDID_IS_ENABLED                 DPCON_CMD(0x006)
 
 #define DPCON_CMDID_SET_NOTIFICATION           DPCON_CMD(0x100)
 
@@ -61,10 +33,6 @@ struct dpcon_cmd_open {
 
 #define DPCON_ENABLE                   1
 
-struct dpcon_rsp_is_enabled {
-       u8 enabled;
-};
-
 struct dpcon_rsp_get_attr {
        /* response word 0 */
        __le32 id;
index ca1da85c6dda159a859d651d9dae65e0549d146b..8f84d7b5465ca3a516832f48443ae1f7e56b0bc4 100644 (file)
@@ -1,33 +1,7 @@
-/* Copyright 2013-2016 Freescale Semiconductor Inc.
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS 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/kernel.h>
 #include "../include/mc.h"
@@ -78,7 +52,7 @@ int dpcon_open(struct fsl_mc_io *mc_io,
 
        return 0;
 }
-EXPORT_SYMBOL(dpcon_open);
+EXPORT_SYMBOL_GPL(dpcon_open);
 
 /**
  * dpcon_close() - Close the control session of the object
@@ -105,7 +79,7 @@ int dpcon_close(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dpcon_close);
+EXPORT_SYMBOL_GPL(dpcon_close);
 
 /**
  * dpcon_enable() - Enable the DPCON
@@ -129,7 +103,7 @@ int dpcon_enable(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dpcon_enable);
+EXPORT_SYMBOL_GPL(dpcon_enable);
 
 /**
  * dpcon_disable() - Disable the DPCON
@@ -153,43 +127,7 @@ int dpcon_disable(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dpcon_disable);
-
-/**
- * dpcon_is_enabled() -        Check if the DPCON is enabled.
- * @mc_io:     Pointer to MC portal's I/O object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @token:     Token of DPCON object
- * @en:                Returns '1' if object is enabled; '0' otherwise
- *
- * Return:     '0' on Success; Error code otherwise.
- */
-int dpcon_is_enabled(struct fsl_mc_io *mc_io,
-                    u32 cmd_flags,
-                    u16 token,
-                    int *en)
-{
-       struct mc_command cmd = { 0 };
-       struct dpcon_rsp_is_enabled *dpcon_rsp;
-       int err;
-
-       /* prepare command */
-       cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED,
-                                         cmd_flags,
-                                         token);
-
-       /* send command to mc*/
-       err = mc_send_command(mc_io, &cmd);
-       if (err)
-               return err;
-
-       /* retrieve response parameters */
-       dpcon_rsp = (struct dpcon_rsp_is_enabled *)cmd.params;
-       *en = dpcon_rsp->enabled & DPCON_ENABLE;
-
-       return 0;
-}
-EXPORT_SYMBOL(dpcon_is_enabled);
+EXPORT_SYMBOL_GPL(dpcon_disable);
 
 /**
  * dpcon_reset() - Reset the DPCON, returns the object to initial state.
@@ -212,7 +150,7 @@ int dpcon_reset(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dpcon_reset);
+EXPORT_SYMBOL_GPL(dpcon_reset);
 
 /**
  * dpcon_get_attributes() - Retrieve DPCON attributes.
@@ -250,7 +188,7 @@ int dpcon_get_attributes(struct fsl_mc_io *mc_io,
 
        return 0;
 }
-EXPORT_SYMBOL(dpcon_get_attributes);
+EXPORT_SYMBOL_GPL(dpcon_get_attributes);
 
 /**
  * dpcon_set_notification() - Set DPCON notification destination
@@ -281,37 +219,4 @@ int dpcon_set_notification(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dpcon_set_notification);
-
-/**
- * dpcon_get_api_version - Get Data Path Concentrator API version
- * @mc_io:     Pointer to MC portal's DPCON object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @major_ver: Major version of DPCON API
- * @minor_ver: Minor version of DPCON API
- *
- * Return:     '0' on Success; Error code otherwise
- */
-int dpcon_get_api_version(struct fsl_mc_io *mc_io,
-                         u32 cmd_flags,
-                         u16 *major_ver,
-                         u16 *minor_ver)
-{
-       struct mc_command cmd = { 0 };
-       int err;
-
-       /* prepare command */
-       cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_API_VERSION,
-                                         cmd_flags, 0);
-
-       /* send command to mc */
-       err = mc_send_command(mc_io, &cmd);
-       if (err)
-               return err;
-
-       /* retrieve response parameters */
-       mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
-
-       return 0;
-}
-EXPORT_SYMBOL(dpcon_get_api_version);
+EXPORT_SYMBOL_GPL(dpcon_set_notification);
index 837d3303e11d05c5af03eee7114777c0349accce..53ba84d7b884f4f55ae1b249110c7d3806fb124f 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # QorIQ DPAA2 DPIO driver
 #
index b2dc6e766f092b4e54b2723cf22476ee3b43c8c7..ab8f82ee7ee58a0b67ff4174d9344f6fc707ac38 100644 (file)
@@ -1,34 +1,8 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  * Copyright 2016 NXP
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef _FSL_DPIO_CMD_H
 #define _FSL_DPIO_CMD_H
index e36da20a2796b2277a7c699df13472465b89ea46..b8479ef64c71a3c676939fb1f856464aa060a420 100644 (file)
@@ -1,33 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright 2014-2016 Freescale Semiconductor Inc.
  * Copyright NXP 2016
  *
- * 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 Freescale Semiconductor nor the
- *      names of its contributors may be used to endorse or promote products
- *      derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/types.h>
index a609ec82daf34e7170c45e9636175d5781ddf70d..d3c8462d43e8704d33d2d1bc308069544e56f900 100644 (file)
@@ -1,33 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright 2014-2016 Freescale Semiconductor Inc.
  * Copyright 2016 NXP
  *
- * 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 Freescale Semiconductor nor the
- *      names of its contributors may be used to endorse or promote products
- *      derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/types.h>
 #include "../../include/mc.h"
@@ -43,7 +18,6 @@
 #include "qbman-portal.h"
 
 struct dpaa2_io {
-       atomic_t refs;
        struct dpaa2_io_desc dpio_desc;
        struct qbman_swp_desc swp_desc;
        struct qbman_swp *swp;
@@ -104,6 +78,23 @@ static inline struct dpaa2_io *service_select(struct dpaa2_io *d)
        return d;
 }
 
+/**
+ * dpaa2_io_service_select() - return a dpaa2_io service affined to this cpu
+ * @cpu: the cpu id
+ *
+ * Return the affine dpaa2_io service, or NULL if there is no service affined
+ * to the specified cpu. If DPAA2_IO_ANY_CPU is used, return the next available
+ * service.
+ */
+struct dpaa2_io *dpaa2_io_service_select(int cpu)
+{
+       if (cpu == DPAA2_IO_ANY_CPU)
+               return service_select(NULL);
+
+       return service_select_by_cpu(NULL, cpu);
+}
+EXPORT_SYMBOL_GPL(dpaa2_io_service_select);
+
 /**
  * dpaa2_io_create() - create a dpaa2_io object.
  * @desc: the dpaa2_io descriptor
@@ -126,7 +117,6 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc)
                return NULL;
        }
 
-       atomic_set(&obj->refs, 1);
        obj->dpio_desc = *desc;
        obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena;
        obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh;
@@ -158,7 +148,6 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc)
 
        return obj;
 }
-EXPORT_SYMBOL(dpaa2_io_create);
 
 /**
  * dpaa2_io_down() - release the dpaa2_io object.
@@ -171,11 +160,8 @@ EXPORT_SYMBOL(dpaa2_io_create);
  */
 void dpaa2_io_down(struct dpaa2_io *d)
 {
-       if (!atomic_dec_and_test(&d->refs))
-               return;
        kfree(d);
 }
-EXPORT_SYMBOL(dpaa2_io_down);
 
 #define DPAA_POLL_MAX 32
 
@@ -222,7 +208,6 @@ done:
        qbman_swp_interrupt_set_inhibit(swp, 0);
        return IRQ_HANDLED;
 }
-EXPORT_SYMBOL(dpaa2_io_irq);
 
 /**
  * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN
@@ -265,7 +250,7 @@ int dpaa2_io_service_register(struct dpaa2_io *d,
                                                         ctx->qman64);
        return 0;
 }
-EXPORT_SYMBOL(dpaa2_io_service_register);
+EXPORT_SYMBOL_GPL(dpaa2_io_service_register);
 
 /**
  * dpaa2_io_service_deregister - The opposite of 'register'.
@@ -288,7 +273,7 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service,
        list_del(&ctx->node);
        spin_unlock_irqrestore(&d->lock_notifications, irqflags);
 }
-EXPORT_SYMBOL(dpaa2_io_service_deregister);
+EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister);
 
 /**
  * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO service.
@@ -322,38 +307,7 @@ int dpaa2_io_service_rearm(struct dpaa2_io *d,
 
        return err;
 }
-EXPORT_SYMBOL(dpaa2_io_service_rearm);
-
-/**
- * dpaa2_io_service_pull_fq() - pull dequeue functions from a fq.
- * @d: the given DPIO service.
- * @fqid: the given frame queue id.
- * @s: the dpaa2_io_store object for the result.
- *
- * Return 0 for success, or error code for failure.
- */
-int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid,
-                            struct dpaa2_io_store *s)
-{
-       struct qbman_pull_desc pd;
-       int err;
-
-       qbman_pull_desc_clear(&pd);
-       qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1);
-       qbman_pull_desc_set_numframes(&pd, (u8)s->max);
-       qbman_pull_desc_set_fq(&pd, fqid);
-
-       d = service_select(d);
-       if (!d)
-               return -ENODEV;
-       s->swp = d->swp;
-       err = qbman_swp_pull(d->swp, &pd);
-       if (err)
-               s->swp = NULL;
-
-       return err;
-}
-EXPORT_SYMBOL(dpaa2_io_service_pull_fq);
+EXPORT_SYMBOL_GPL(dpaa2_io_service_rearm);
 
 /**
  * dpaa2_io_service_pull_channel() - pull dequeue functions from a channel.
@@ -385,34 +339,7 @@ int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,
 
        return err;
 }
-EXPORT_SYMBOL(dpaa2_io_service_pull_channel);
-
-/**
- * dpaa2_io_service_enqueue_fq() - Enqueue a frame to a frame queue.
- * @d: the given DPIO service.
- * @fqid: the given frame queue id.
- * @fd: the frame descriptor which is enqueued.
- *
- * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready,
- * or -ENODEV if there is no dpio service.
- */
-int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d,
-                               u32 fqid,
-                               const struct dpaa2_fd *fd)
-{
-       struct qbman_eq_desc ed;
-
-       d = service_select(d);
-       if (!d)
-               return -ENODEV;
-
-       qbman_eq_desc_clear(&ed);
-       qbman_eq_desc_set_no_orp(&ed, 0);
-       qbman_eq_desc_set_fq(&ed, fqid);
-
-       return qbman_swp_enqueue(d->swp, &ed, fd);
-}
-EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq);
+EXPORT_SYMBOL_GPL(dpaa2_io_service_pull_channel);
 
 /**
  * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD.
@@ -441,7 +368,7 @@ int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d,
 
        return qbman_swp_enqueue(d->swp, &ed, fd);
 }
-EXPORT_SYMBOL(dpaa2_io_service_enqueue_qd);
+EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd);
 
 /**
  * dpaa2_io_service_release() - Release buffers to a buffer pool.
@@ -468,7 +395,7 @@ int dpaa2_io_service_release(struct dpaa2_io *d,
 
        return qbman_swp_release(d->swp, &rd, buffers, num_buffers);
 }
-EXPORT_SYMBOL(dpaa2_io_service_release);
+EXPORT_SYMBOL_GPL(dpaa2_io_service_release);
 
 /**
  * dpaa2_io_service_acquire() - Acquire buffers from a buffer pool.
@@ -499,7 +426,7 @@ int dpaa2_io_service_acquire(struct dpaa2_io *d,
 
        return err;
 }
-EXPORT_SYMBOL(dpaa2_io_service_acquire);
+EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire);
 
 /*
  * 'Stores' are reusable memory blocks for holding dequeue results, and to
@@ -553,7 +480,7 @@ struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
 
        return ret;
 }
-EXPORT_SYMBOL(dpaa2_io_store_create);
+EXPORT_SYMBOL_GPL(dpaa2_io_store_create);
 
 /**
  * dpaa2_io_store_destroy() - Frees the dma memory storage for dequeue
@@ -567,7 +494,7 @@ void dpaa2_io_store_destroy(struct dpaa2_io_store *s)
        kfree(s->alloced_addr);
        kfree(s);
 }
-EXPORT_SYMBOL(dpaa2_io_store_destroy);
+EXPORT_SYMBOL_GPL(dpaa2_io_store_destroy);
 
 /**
  * dpaa2_io_store_next() - Determine when the next dequeue result is available.
@@ -615,4 +542,4 @@ struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last)
 
        return ret;
 }
-EXPORT_SYMBOL(dpaa2_io_store_next);
+EXPORT_SYMBOL_GPL(dpaa2_io_store_next);
index 00eb22186f42ffc7aa3c056da0e5b0cd8e612ba1..20cdeae54a74f7bfde80271c961bdda9b1ac124b 100644 (file)
@@ -1,34 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  * Copyright 2016 NXP
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS 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/kernel.h>
 #include "../../include/mc.h"
index ced1103d157c116c08af37d2795f32c640a8f5d8..49194c8e45f124acdc6063bde89d724e80b489c8 100644 (file)
@@ -1,34 +1,8 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  * Copyright 2016 NXP
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef __FSL_DPIO_H
 #define __FSL_DPIO_H
index 163bdac6b05116ae4a0a297d80bfc1665992d92a..376e9ed0297adbe6f853df23bf63c3a6992ea299 100644 (file)
@@ -1,33 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
  * Copyright 2016 NXP
  *
- * 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 Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 <asm/cacheflush.h>
index 842855971f343943e9d08db4c8728569c15a2570..fb8b9d35a3ebfccfb5429d31c07d9795cfc2c365 100644 (file)
@@ -1,33 +1,8 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
  * Copyright 2016 NXP
  *
- * 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 Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef __FSL_QBMAN_PORTAL_H
 #define __FSL_QBMAN_PORTAL_H
diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
deleted file mode 100644 (file)
index 861b2a7..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2013-2016 Freescale Semiconductor Inc.
- *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _FSL_DPMCP_CMD_H
-#define _FSL_DPMCP_CMD_H
-
-/* Minimal supported DPMCP Version */
-#define DPMCP_MIN_VER_MAJOR            3
-#define DPMCP_MIN_VER_MINOR            0
-
-/* Command versioning */
-#define DPMCP_CMD_BASE_VERSION         1
-#define DPMCP_CMD_ID_OFFSET            4
-
-#define DPMCP_CMD(id)  (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
-
-/* Command IDs */
-#define DPMCP_CMDID_CLOSE              DPMCP_CMD(0x800)
-#define DPMCP_CMDID_OPEN               DPMCP_CMD(0x80b)
-#define DPMCP_CMDID_GET_API_VERSION    DPMCP_CMD(0xa0b)
-
-#define DPMCP_CMDID_RESET              DPMCP_CMD(0x005)
-
-struct dpmcp_cmd_open {
-       __le32 dpmcp_id;
-};
-
-#endif /* _FSL_DPMCP_CMD_H */
index eea42f61af867d7be256b1bc4d956d943fc5439b..be07c77520af92d69ef674adc3941cb4c62e958f 100644 (file)
@@ -1,39 +1,12 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS 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/kernel.h>
 #include "../include/mc.h"
 
-#include "dpmcp.h"
-#include "dpmcp-cmd.h"
+#include "fsl-mc-private.h"
 
 /**
  * dpmcp_open() - Open a control session for the specified object.
@@ -124,35 +97,3 @@ int dpmcp_reset(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-
-/**
- * dpmcp_get_api_version - Get Data Path Management Command Portal API version
- * @mc_io:     Pointer to Mc portal's I/O object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @major_ver: Major version of Data Path Management Command Portal API
- * @minor_ver: Minor version of Data Path Management Command Portal API
- *
- * Return:     '0' on Success; Error code otherwise.
- */
-int dpmcp_get_api_version(struct fsl_mc_io *mc_io,
-                         u32 cmd_flags,
-                         u16 *major_ver,
-                         u16 *minor_ver)
-{
-       struct mc_command cmd = { 0 };
-       int err;
-
-       /* prepare command */
-       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_API_VERSION,
-                                         cmd_flags, 0);
-
-       /* send command to mc */
-       err = mc_send_command(mc_io, &cmd);
-       if (err)
-               return err;
-
-       /* retrieve response parameters */
-       mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
-
-       return 0;
-}
diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h
deleted file mode 100644 (file)
index f616031..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2013-2016 Freescale Semiconductor Inc.
- *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef __FSL_DPMCP_H
-#define __FSL_DPMCP_H
-
-/*
- * Data Path Management Command Portal API
- * Contains initialization APIs and runtime control APIs for DPMCP
- */
-
-struct fsl_mc_io;
-
-int dpmcp_open(struct fsl_mc_io *mc_io,
-              u32 cmd_flags,
-              int dpmcp_id,
-              u16 *token);
-
-int dpmcp_close(struct fsl_mc_io *mc_io,
-               u32 cmd_flags,
-               u16 token);
-
-int dpmcp_get_api_version(struct fsl_mc_io *mc_io,
-                         u32 cmd_flags,
-                         u16 *major_ver,
-                         u16 *minor_ver);
-
-int dpmcp_reset(struct fsl_mc_io *mc_io,
-               u32 cmd_flags,
-               u16 token);
-
-#endif /* __FSL_DPMCP_H */
diff --git a/drivers/staging/fsl-mc/bus/dpmng-cmd.h b/drivers/staging/fsl-mc/bus/dpmng-cmd.h
deleted file mode 100644 (file)
index d1f04ac..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2013-2016 Freescale Semiconductor Inc.
- *
- * 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 the above-listed copyright holders nor the
- *       names of any contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS 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.
- */
-
-/*
- * dpmng-cmd.h
- *
- * defines portal commands
- *
- */
-
-#ifndef __FSL_DPMNG_CMD_H
-#define __FSL_DPMNG_CMD_H
-
-/* Command versioning */
-#define DPMNG_CMD_BASE_VERSION         1
-#define DPMNG_CMD_ID_OFFSET            4
-
-#define DPMNG_CMD(id)  (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
-
-/* Command IDs */
-#define DPMNG_CMDID_GET_VERSION                DPMNG_CMD(0x831)
-
-struct dpmng_rsp_get_version {
-       __le32 revision;
-       __le32 version_major;
-       __le32 version_minor;
-};
-
-#endif /* __FSL_DPMNG_CMD_H */
diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h
deleted file mode 100644 (file)
index d9b2dcd..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright 2013-2016 Freescale Semiconductor Inc.
- *
- * 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 the above-listed copyright holders nor the
- *       names of any contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS 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.
- */
-
-/*
- * dprc-cmd.h
- *
- * defines dprc portal commands
- *
- */
-
-#ifndef _FSL_DPRC_CMD_H
-#define _FSL_DPRC_CMD_H
-
-/* Minimal supported DPRC Version */
-#define DPRC_MIN_VER_MAJOR                     6
-#define DPRC_MIN_VER_MINOR                     0
-
-/* Command versioning */
-#define DPRC_CMD_BASE_VERSION                  1
-#define DPRC_CMD_ID_OFFSET                     4
-
-#define DPRC_CMD(id)   (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
-
-/* Command IDs */
-#define DPRC_CMDID_CLOSE                        DPRC_CMD(0x800)
-#define DPRC_CMDID_OPEN                         DPRC_CMD(0x805)
-#define DPRC_CMDID_GET_API_VERSION              DPRC_CMD(0xa05)
-
-#define DPRC_CMDID_GET_ATTR                     DPRC_CMD(0x004)
-
-#define DPRC_CMDID_SET_IRQ                      DPRC_CMD(0x010)
-#define DPRC_CMDID_GET_IRQ                      DPRC_CMD(0x011)
-#define DPRC_CMDID_SET_IRQ_ENABLE               DPRC_CMD(0x012)
-#define DPRC_CMDID_GET_IRQ_ENABLE               DPRC_CMD(0x013)
-#define DPRC_CMDID_SET_IRQ_MASK                 DPRC_CMD(0x014)
-#define DPRC_CMDID_GET_IRQ_MASK                 DPRC_CMD(0x015)
-#define DPRC_CMDID_GET_IRQ_STATUS               DPRC_CMD(0x016)
-#define DPRC_CMDID_CLEAR_IRQ_STATUS             DPRC_CMD(0x017)
-
-#define DPRC_CMDID_GET_CONT_ID                  DPRC_CMD(0x830)
-#define DPRC_CMDID_GET_OBJ_COUNT                DPRC_CMD(0x159)
-#define DPRC_CMDID_GET_OBJ                      DPRC_CMD(0x15A)
-#define DPRC_CMDID_GET_RES_COUNT                DPRC_CMD(0x15B)
-#define DPRC_CMDID_GET_OBJ_REG                  DPRC_CMD(0x15E)
-#define DPRC_CMDID_SET_OBJ_IRQ                  DPRC_CMD(0x15F)
-#define DPRC_CMDID_GET_OBJ_IRQ                  DPRC_CMD(0x160)
-
-struct dprc_cmd_open {
-       __le32 container_id;
-};
-
-struct dprc_cmd_create_container {
-       /* cmd word 0 */
-       __le32 options;
-       __le16 icid;
-       __le16 pad0;
-       /* cmd word 1 */
-       __le32 pad1;
-       __le32 portal_id;
-       /* cmd words 2-3 */
-       u8 label[16];
-};
-
-struct dprc_rsp_create_container {
-       /* response word 0 */
-       __le64 pad0;
-       /* response word 1 */
-       __le32 child_container_id;
-       __le32 pad1;
-       /* response word 2 */
-       __le64 child_portal_addr;
-};
-
-struct dprc_cmd_destroy_container {
-       __le32 child_container_id;
-};
-
-struct dprc_cmd_reset_container {
-       __le32 child_container_id;
-};
-
-struct dprc_cmd_set_irq {
-       /* cmd word 0 */
-       __le32 irq_val;
-       u8 irq_index;
-       u8 pad[3];
-       /* cmd word 1 */
-       __le64 irq_addr;
-       /* cmd word 2 */
-       __le32 irq_num;
-};
-
-struct dprc_cmd_get_irq {
-       __le32 pad;
-       u8 irq_index;
-};
-
-struct dprc_rsp_get_irq {
-       /* response word 0 */
-       __le32 irq_val;
-       __le32 pad;
-       /* response word 1 */
-       __le64 irq_addr;
-       /* response word 2 */
-       __le32 irq_num;
-       __le32 type;
-};
-
-#define DPRC_ENABLE            0x1
-
-struct dprc_cmd_set_irq_enable {
-       u8 enable;
-       u8 pad[3];
-       u8 irq_index;
-};
-
-struct dprc_cmd_get_irq_enable {
-       __le32 pad;
-       u8 irq_index;
-};
-
-struct dprc_rsp_get_irq_enable {
-       u8 enabled;
-};
-
-struct dprc_cmd_set_irq_mask {
-       __le32 mask;
-       u8 irq_index;
-};
-
-struct dprc_cmd_get_irq_mask {
-       __le32 pad;
-       u8 irq_index;
-};
-
-struct dprc_rsp_get_irq_mask {
-       __le32 mask;
-};
-
-struct dprc_cmd_get_irq_status {
-       __le32 status;
-       u8 irq_index;
-};
-
-struct dprc_rsp_get_irq_status {
-       __le32 status;
-};
-
-struct dprc_cmd_clear_irq_status {
-       __le32 status;
-       u8 irq_index;
-};
-
-struct dprc_rsp_get_attributes {
-       /* response word 0 */
-       __le32 container_id;
-       __le16 icid;
-       __le16 pad;
-       /* response word 1 */
-       __le32 options;
-       __le32 portal_id;
-};
-
-struct dprc_cmd_set_res_quota {
-       /* cmd word 0 */
-       __le32 child_container_id;
-       __le16 quota;
-       __le16 pad;
-       /* cmd words 1-2 */
-       u8 type[16];
-};
-
-struct dprc_cmd_get_res_quota {
-       /* cmd word 0 */
-       __le32 child_container_id;
-       __le32 pad;
-       /* cmd word 1-2 */
-       u8 type[16];
-};
-
-struct dprc_rsp_get_res_quota {
-       __le32 pad;
-       __le16 quota;
-};
-
-struct dprc_cmd_assign {
-       /* cmd word 0 */
-       __le32 container_id;
-       __le32 options;
-       /* cmd word 1 */
-       __le32 num;
-       __le32 id_base_align;
-       /* cmd word 2-3 */
-       u8 type[16];
-};
-
-struct dprc_cmd_unassign {
-       /* cmd word 0 */
-       __le32 child_container_id;
-       __le32 options;
-       /* cmd word 1 */
-       __le32 num;
-       __le32 id_base_align;
-       /* cmd word 2-3 */
-       u8 type[16];
-};
-
-struct dprc_rsp_get_pool_count {
-       __le32 pool_count;
-};
-
-struct dprc_cmd_get_pool {
-       __le32 pool_index;
-};
-
-struct dprc_rsp_get_pool {
-       /* response word 0 */
-       __le64 pad;
-       /* response word 1-2 */
-       u8 type[16];
-};
-
-struct dprc_rsp_get_obj_count {
-       __le32 pad;
-       __le32 obj_count;
-};
-
-struct dprc_cmd_get_obj {
-       __le32 obj_index;
-};
-
-struct dprc_rsp_get_obj {
-       /* response word 0 */
-       __le32 pad0;
-       __le32 id;
-       /* response word 1 */
-       __le16 vendor;
-       u8 irq_count;
-       u8 region_count;
-       __le32 state;
-       /* response word 2 */
-       __le16 version_major;
-       __le16 version_minor;
-       __le16 flags;
-       __le16 pad1;
-       /* response word 3-4 */
-       u8 type[16];
-       /* response word 5-6 */
-       u8 label[16];
-};
-
-struct dprc_cmd_get_obj_desc {
-       /* cmd word 0 */
-       __le32 obj_id;
-       __le32 pad;
-       /* cmd word 1-2 */
-       u8 type[16];
-};
-
-struct dprc_rsp_get_obj_desc {
-       /* response word 0 */
-       __le32 pad0;
-       __le32 id;
-       /* response word 1 */
-       __le16 vendor;
-       u8 irq_count;
-       u8 region_count;
-       __le32 state;
-       /* response word 2 */
-       __le16 version_major;
-       __le16 version_minor;
-       __le16 flags;
-       __le16 pad1;
-       /* response word 3-4 */
-       u8 type[16];
-       /* response word 5-6 */
-       u8 label[16];
-};
-
-struct dprc_cmd_get_res_count {
-       /* cmd word 0 */
-       __le64 pad;
-       /* cmd word 1-2 */
-       u8 type[16];
-};
-
-struct dprc_rsp_get_res_count {
-       __le32 res_count;
-};
-
-struct dprc_cmd_get_res_ids {
-       /* cmd word 0 */
-       u8 pad0[5];
-       u8 iter_status;
-       __le16 pad1;
-       /* cmd word 1 */
-       __le32 base_id;
-       __le32 last_id;
-       /* cmd word 2-3 */
-       u8 type[16];
-};
-
-struct dprc_rsp_get_res_ids {
-       /* response word 0 */
-       u8 pad0[5];
-       u8 iter_status;
-       __le16 pad1;
-       /* response word 1 */
-       __le32 base_id;
-       __le32 last_id;
-};
-
-struct dprc_cmd_get_obj_region {
-       /* cmd word 0 */
-       __le32 obj_id;
-       __le16 pad0;
-       u8 region_index;
-       u8 pad1;
-       /* cmd word 1-2 */
-       __le64 pad2[2];
-       /* cmd word 3-4 */
-       u8 obj_type[16];
-};
-
-struct dprc_rsp_get_obj_region {
-       /* response word 0 */
-       __le64 pad;
-       /* response word 1 */
-       __le64 base_addr;
-       /* response word 2 */
-       __le32 size;
-};
-
-struct dprc_cmd_set_obj_label {
-       /* cmd word 0 */
-       __le32 obj_id;
-       __le32 pad;
-       /* cmd word 1-2 */
-       u8 label[16];
-       /* cmd word 3-4 */
-       u8 obj_type[16];
-};
-
-struct dprc_cmd_set_obj_irq {
-       /* cmd word 0 */
-       __le32 irq_val;
-       u8 irq_index;
-       u8 pad[3];
-       /* cmd word 1 */
-       __le64 irq_addr;
-       /* cmd word 2 */
-       __le32 irq_num;
-       __le32 obj_id;
-       /* cmd word 3-4 */
-       u8 obj_type[16];
-};
-
-struct dprc_cmd_get_obj_irq {
-       /* cmd word 0 */
-       __le32 obj_id;
-       u8 irq_index;
-       u8 pad[3];
-       /* cmd word 1-2 */
-       u8 obj_type[16];
-};
-
-struct dprc_rsp_get_obj_irq {
-       /* response word 0 */
-       __le32 irq_val;
-       __le32 pad;
-       /* response word 1 */
-       __le64 irq_addr;
-       /* response word 2 */
-       __le32 irq_num;
-       __le32 type;
-};
-
-struct dprc_cmd_connect {
-       /* cmd word 0 */
-       __le32 ep1_id;
-       __le32 ep1_interface_id;
-       /* cmd word 1 */
-       __le32 ep2_id;
-       __le32 ep2_interface_id;
-       /* cmd word 2-3 */
-       u8 ep1_type[16];
-       /* cmd word 4 */
-       __le32 max_rate;
-       __le32 committed_rate;
-       /* cmd word 5-6 */
-       u8 ep2_type[16];
-};
-
-struct dprc_cmd_disconnect {
-       /* cmd word 0 */
-       __le32 id;
-       __le32 interface_id;
-       /* cmd word 1-2 */
-       u8 type[16];
-};
-
-struct dprc_cmd_get_connection {
-       /* cmd word 0 */
-       __le32 ep1_id;
-       __le32 ep1_interface_id;
-       /* cmd word 1-2 */
-       u8 ep1_type[16];
-};
-
-struct dprc_rsp_get_connection {
-       /* response word 0-2 */
-       __le64 pad[3];
-       /* response word 3 */
-       __le32 ep2_id;
-       __le32 ep2_interface_id;
-       /* response word 4-5 */
-       u8 ep2_type[16];
-       /* response word 6 */
-       __le32 state;
-};
-
-#endif /* _FSL_DPRC_CMD_H */
index 06df528f4cfc20815c76f459b94e1208ff546c9c..b09075731e62cf62f765f77d2ef9d377b96dd662 100644 (file)
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Freescale data path resource container (DPRC) driver
  *
  * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
  * Author: German Rivera <German.Rivera@freescale.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
  */
 
 #include <linux/module.h>
@@ -15,7 +13,6 @@
 #include <linux/msi.h>
 #include "../include/mc.h"
 
-#include "dprc-cmd.h"
 #include "fsl-mc-private.h"
 
 #define FSL_MC_DPRC_DRIVER_NAME    "fsl_mc_dprc"
@@ -39,8 +36,6 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
        struct fsl_mc_child_objs *objs;
        struct fsl_mc_device *mc_dev;
 
-       WARN_ON(!dev);
-       WARN_ON(!data);
        mc_dev = to_fsl_mc_device(dev);
        objs = data;
 
@@ -60,8 +55,6 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
 
 static int __fsl_mc_device_remove(struct device *dev, void *data)
 {
-       WARN_ON(!dev);
-       WARN_ON(data);
        fsl_mc_device_remove(to_fsl_mc_device(dev));
        return 0;
 }
@@ -206,7 +199,8 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
  * dprc_scan_objects - Discover objects in a DPRC
  *
  * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
- * @total_irq_count: total number of IRQs needed by objects in the DPRC.
+ * @total_irq_count: If argument is provided the function populates the
+ * total number of IRQs created by objects in the DPRC.
  *
  * Detects objects added and removed from a DPRC and synchronizes the
  * state of the Linux bus driver, MC by adding and removing
@@ -228,6 +222,7 @@ static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
        int error;
        unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
        struct fsl_mc_obj_desc *child_obj_desc_array = NULL;
+       struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
 
        error = dprc_get_obj_count(mc_bus_dev->mc_io,
                                   0,
@@ -297,7 +292,26 @@ static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
                }
        }
 
-       *total_irq_count = irq_count;
+       /*
+        * Allocate IRQ's before binding the scanned devices with their
+        * respective drivers.
+        */
+       if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
+               if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
+                       dev_warn(&mc_bus_dev->dev,
+                                "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
+                                irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
+               }
+
+               error = fsl_mc_populate_irq_pool(mc_bus,
+                               FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
+               if (error < 0)
+                       return error;
+       }
+
+       if (total_irq_count)
+               *total_irq_count = irq_count;
+
        dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
                            num_child_objects);
 
@@ -322,7 +336,6 @@ static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
 static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
 {
        int error;
-       unsigned int irq_count;
        struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
 
        fsl_mc_init_all_resource_pools(mc_bus_dev);
@@ -331,29 +344,14 @@ static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
         * Discover objects in the DPRC:
         */
        mutex_lock(&mc_bus->scan_mutex);
-       error = dprc_scan_objects(mc_bus_dev, &irq_count);
+       error = dprc_scan_objects(mc_bus_dev, NULL);
        mutex_unlock(&mc_bus->scan_mutex);
-       if (error < 0)
-               goto error;
-
-       if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
-               if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
-                       dev_warn(&mc_bus_dev->dev,
-                                "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
-                                irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
-               }
-
-               error = fsl_mc_populate_irq_pool(
-                               mc_bus,
-                               FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
-               if (error < 0)
-                       goto error;
+       if (error < 0) {
+               fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
+               return error;
        }
 
        return 0;
-error:
-       fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
-       return error;
 }
 
 /**
@@ -386,11 +384,11 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
        dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
                irq_num, smp_processor_id());
 
-       if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC)))
+       if (!(mc_dev->flags & FSL_MC_IS_DPRC))
                return IRQ_HANDLED;
 
        mutex_lock(&mc_bus->scan_mutex);
-       if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num))
+       if (!msi_desc || msi_desc->irq != (u32)irq_num)
                goto out;
 
        status = 0;
@@ -453,8 +451,6 @@ static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
        int error;
        struct fsl_mc_io *mc_io = mc_dev->mc_io;
 
-       WARN_ON(mc_dev->obj_desc.irq_count != 1);
-
        /*
         * Disable generation of interrupt, while we configure it:
         */
@@ -496,8 +492,6 @@ static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
        int error;
        struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
 
-       WARN_ON(mc_dev->obj_desc.irq_count != 1);
-
        /*
         * NOTE: devm_request_threaded_irq() invokes the device-specific
         * function that programs the MSI physically in the device
@@ -601,20 +595,20 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
        bool msi_domain_set = false;
        u16 major_ver, minor_ver;
 
-       if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
+       if (!is_fsl_mc_bus_dprc(mc_dev))
                return -EINVAL;
 
-       if (WARN_ON(dev_get_msi_domain(&mc_dev->dev)))
+       if (dev_get_msi_domain(&mc_dev->dev))
                return -EINVAL;
 
        if (!mc_dev->mc_io) {
                /*
                 * This is a child DPRC:
                 */
-               if (WARN_ON(!dev_is_fsl_mc(parent_dev)))
+               if (!dev_is_fsl_mc(parent_dev))
                        return -EINVAL;
 
-               if (WARN_ON(mc_dev->obj_desc.region_count == 0))
+               if (mc_dev->obj_desc.region_count == 0)
                        return -EINVAL;
 
                region_size = resource_size(mc_dev->regions);
@@ -642,7 +636,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
                 */
                struct irq_domain *mc_msi_domain;
 
-               if (WARN_ON(dev_is_fsl_mc(parent_dev)))
+               if (dev_is_fsl_mc(parent_dev))
                        return -EINVAL;
 
                error = fsl_mc_find_msi_domain(parent_dev,
@@ -753,12 +747,12 @@ static int dprc_remove(struct fsl_mc_device *mc_dev)
        int error;
        struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
 
-       if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
+       if (!is_fsl_mc_bus_dprc(mc_dev))
                return -EINVAL;
-       if (WARN_ON(!mc_dev->mc_io))
+       if (!mc_dev->mc_io)
                return -EINVAL;
 
-       if (WARN_ON(!mc_bus->irq_resources))
+       if (!mc_bus->irq_resources)
                return -EINVAL;
 
        if (dev_get_msi_domain(&mc_dev->dev))
index 6f6c65a4216699803c5f71f583f42c01877c6757..97f51726fa7e28604fc6a37ae0ab50d3755f3d18 100644 (file)
@@ -1,39 +1,11 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS 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/kernel.h>
 #include "../include/mc.h"
-#include "dprc.h"
-
-#include "dprc-cmd.h"
+#include "fsl-mc-private.h"
 
 /**
  * dprc_open() - Open DPRC object for use
@@ -71,7 +43,7 @@ int dprc_open(struct fsl_mc_io *mc_io,
 
        return 0;
 }
-EXPORT_SYMBOL(dprc_open);
+EXPORT_SYMBOL_GPL(dprc_open);
 
 /**
  * dprc_close() - Close the control session of the object
@@ -97,53 +69,7 @@ int dprc_close(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dprc_close);
-
-/**
- * dprc_get_irq() - Get IRQ information from the DPRC.
- * @mc_io:     Pointer to MC portal's I/O object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @token:     Token of DPRC object
- * @irq_index: The interrupt index to configure
- * @type:      Interrupt type: 0 represents message interrupt
- *             type (both irq_addr and irq_val are valid)
- * @irq_cfg:   IRQ attributes
- *
- * Return:     '0' on Success; Error code otherwise.
- */
-int dprc_get_irq(struct fsl_mc_io *mc_io,
-                u32 cmd_flags,
-                u16 token,
-                u8 irq_index,
-                int *type,
-                struct dprc_irq_cfg *irq_cfg)
-{
-       struct mc_command cmd = { 0 };
-       struct dprc_cmd_get_irq *cmd_params;
-       struct dprc_rsp_get_irq *rsp_params;
-       int err;
-
-       /* prepare command */
-       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ,
-                                         cmd_flags,
-                                         token);
-       cmd_params = (struct dprc_cmd_get_irq *)cmd.params;
-       cmd_params->irq_index = irq_index;
-
-       /* send command to mc*/
-       err = mc_send_command(mc_io, &cmd);
-       if (err)
-               return err;
-
-       /* retrieve response parameters */
-       rsp_params = (struct dprc_rsp_get_irq *)cmd.params;
-       irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
-       irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr);
-       irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
-       *type = le32_to_cpu(rsp_params->type);
-
-       return 0;
-}
+EXPORT_SYMBOL_GPL(dprc_close);
 
 /**
  * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
@@ -178,45 +104,6 @@ int dprc_set_irq(struct fsl_mc_io *mc_io,
        return mc_send_command(mc_io, &cmd);
 }
 
-/**
- * dprc_get_irq_enable() - Get overall interrupt state.
- * @mc_io:     Pointer to MC portal's I/O object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @token:     Token of DPRC object
- * @irq_index:  The interrupt index to configure
- * @en:                Returned interrupt state - enable = 1, disable = 0
- *
- * Return:     '0' on Success; Error code otherwise.
- */
-int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
-                       u32 cmd_flags,
-                       u16 token,
-                       u8 irq_index,
-                       u8 *en)
-{
-       struct mc_command cmd = { 0 };
-       struct dprc_cmd_get_irq_enable *cmd_params;
-       struct dprc_rsp_get_irq_enable *rsp_params;
-       int err;
-
-       /* prepare command */
-       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE,
-                                         cmd_flags, token);
-       cmd_params = (struct dprc_cmd_get_irq_enable *)cmd.params;
-       cmd_params->irq_index = irq_index;
-
-       /* send command to mc*/
-       err = mc_send_command(mc_io, &cmd);
-       if (err)
-               return err;
-
-       /* retrieve response parameters */
-       rsp_params = (struct dprc_rsp_get_irq_enable *)cmd.params;
-       *en = rsp_params->enabled & DPRC_ENABLE;
-
-       return 0;
-}
-
 /**
  * dprc_set_irq_enable() - Set overall interrupt state.
  * @mc_io:     Pointer to MC portal's I/O object
@@ -252,48 +139,6 @@ int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
        return mc_send_command(mc_io, &cmd);
 }
 
-/**
- * dprc_get_irq_mask() - Get interrupt mask.
- * @mc_io:     Pointer to MC portal's I/O object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @token:     Token of DPRC object
- * @irq_index: The interrupt index to configure
- * @mask:      Returned event mask to trigger interrupt
- *
- * Every interrupt can have up to 32 causes and the interrupt model supports
- * masking/unmasking each cause independently
- *
- * Return:     '0' on Success; Error code otherwise.
- */
-int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
-                     u32 cmd_flags,
-                     u16 token,
-                     u8 irq_index,
-                     u32 *mask)
-{
-       struct mc_command cmd = { 0 };
-       struct dprc_cmd_get_irq_mask *cmd_params;
-       struct dprc_rsp_get_irq_mask *rsp_params;
-       int err;
-
-       /* prepare command */
-       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK,
-                                         cmd_flags, token);
-       cmd_params = (struct dprc_cmd_get_irq_mask *)cmd.params;
-       cmd_params->irq_index = irq_index;
-
-       /* send command to mc*/
-       err = mc_send_command(mc_io, &cmd);
-       if (err)
-               return err;
-
-       /* retrieve response parameters */
-       rsp_params = (struct dprc_rsp_get_irq_mask *)cmd.params;
-       *mask = le32_to_cpu(rsp_params->mask);
-
-       return 0;
-}
-
 /**
  * dprc_set_irq_mask() - Set interrupt mask.
  * @mc_io:     Pointer to MC portal's I/O object
@@ -475,7 +320,7 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io,
 
        return 0;
 }
-EXPORT_SYMBOL(dprc_get_obj_count);
+EXPORT_SYMBOL_GPL(dprc_get_obj_count);
 
 /**
  * dprc_get_obj() - Get general information on an object
@@ -531,7 +376,7 @@ int dprc_get_obj(struct fsl_mc_io *mc_io,
        obj_desc->label[15] = '\0';
        return 0;
 }
-EXPORT_SYMBOL(dprc_get_obj);
+EXPORT_SYMBOL_GPL(dprc_get_obj);
 
 /**
  * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt.
@@ -572,104 +417,7 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
        /* send command to mc*/
        return mc_send_command(mc_io, &cmd);
 }
-EXPORT_SYMBOL(dprc_set_obj_irq);
-
-/**
- * dprc_get_obj_irq() - Get IRQ information from object.
- * @mc_io:     Pointer to MC portal's I/O object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @token:     Token of DPRC object
- * @obj_type:  Type od the object to get its IRQ
- * @obj_id:    ID of the object to get its IRQ
- * @irq_index: The interrupt index to configure
- * @type:      Interrupt type: 0 represents message interrupt
- *             type (both irq_addr and irq_val are valid)
- * @irq_cfg:   The returned IRQ attributes
- *
- * Return:     '0' on Success; Error code otherwise.
- */
-int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
-                    u32 cmd_flags,
-                    u16 token,
-                    char *obj_type,
-                    int obj_id,
-                    u8 irq_index,
-                    int *type,
-                    struct dprc_irq_cfg *irq_cfg)
-{
-       struct mc_command cmd = { 0 };
-       struct dprc_cmd_get_obj_irq *cmd_params;
-       struct dprc_rsp_get_obj_irq *rsp_params;
-       int err;
-
-       /* prepare command */
-       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ,
-                                         cmd_flags,
-                                         token);
-       cmd_params = (struct dprc_cmd_get_obj_irq *)cmd.params;
-       cmd_params->obj_id = cpu_to_le32(obj_id);
-       cmd_params->irq_index = irq_index;
-       strncpy(cmd_params->obj_type, obj_type, 16);
-       cmd_params->obj_type[15] = '\0';
-
-       /* send command to mc*/
-       err = mc_send_command(mc_io, &cmd);
-       if (err)
-               return err;
-
-       /* retrieve response parameters */
-       rsp_params = (struct dprc_rsp_get_obj_irq *)cmd.params;
-       irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
-       irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr);
-       irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
-       *type = le32_to_cpu(rsp_params->type);
-
-       return 0;
-}
-EXPORT_SYMBOL(dprc_get_obj_irq);
-
-/**
- * dprc_get_res_count() - Obtains the number of free resources that are assigned
- *             to this container, by pool type
- * @mc_io:     Pointer to MC portal's I/O object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @token:     Token of DPRC object
- * @type:      pool type
- * @res_count: Returned number of free resources of the given
- *                     resource type that are assigned to this DPRC
- *
- * Return:     '0' on Success; Error code otherwise.
- */
-int dprc_get_res_count(struct fsl_mc_io *mc_io,
-                      u32 cmd_flags,
-                      u16 token,
-                      char *type,
-                      int *res_count)
-{
-       struct mc_command cmd = { 0 };
-       struct dprc_cmd_get_res_count *cmd_params;
-       struct dprc_rsp_get_res_count *rsp_params;
-       int err;
-
-       /* prepare command */
-       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT,
-                                         cmd_flags, token);
-       cmd_params = (struct dprc_cmd_get_res_count *)cmd.params;
-       strncpy(cmd_params->type, type, 16);
-       cmd_params->type[15] = '\0';
-
-       /* send command to mc*/
-       err = mc_send_command(mc_io, &cmd);
-       if (err)
-               return err;
-
-       /* retrieve response parameters */
-       rsp_params = (struct dprc_rsp_get_res_count *)cmd.params;
-       *res_count = le32_to_cpu(rsp_params->res_count);
-
-       return 0;
-}
-EXPORT_SYMBOL(dprc_get_res_count);
+EXPORT_SYMBOL_GPL(dprc_set_obj_irq);
 
 /**
  * dprc_get_obj_region() - Get region information for a specified object.
@@ -717,7 +465,7 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io,
 
        return 0;
 }
-EXPORT_SYMBOL(dprc_get_obj_region);
+EXPORT_SYMBOL_GPL(dprc_get_obj_region);
 
 /**
  * dprc_get_api_version - Get Data Path Resource Container API version
diff --git a/drivers/staging/fsl-mc/bus/dprc.h b/drivers/staging/fsl-mc/bus/dprc.h
deleted file mode 100644 (file)
index 21295e4..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright 2013-2016 Freescale Semiconductor Inc.
- *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _FSL_DPRC_H
-#define _FSL_DPRC_H
-
-/*
- * Data Path Resource Container API
- * Contains DPRC API for managing and querying DPAA resources
- */
-
-struct fsl_mc_io;
-struct fsl_mc_obj_desc;
-
-int dprc_open(struct fsl_mc_io *mc_io,
-             u32 cmd_flags,
-             int container_id,
-             u16 *token);
-
-int dprc_close(struct fsl_mc_io *mc_io,
-              u32 cmd_flags,
-              u16 token);
-
-/* IRQ */
-
-/* IRQ index */
-#define DPRC_IRQ_INDEX          0
-
-/* Number of dprc's IRQs */
-#define DPRC_NUM_OF_IRQS       1
-
-/* DPRC IRQ events */
-
-/* IRQ event - Indicates that a new object added to the container */
-#define DPRC_IRQ_EVENT_OBJ_ADDED               0x00000001
-/* IRQ event - Indicates that an object was removed from the container */
-#define DPRC_IRQ_EVENT_OBJ_REMOVED             0x00000002
-/* IRQ event - Indicates that resources added to the container */
-#define DPRC_IRQ_EVENT_RES_ADDED               0x00000004
-/* IRQ event - Indicates that resources removed from the container */
-#define DPRC_IRQ_EVENT_RES_REMOVED             0x00000008
-/*
- * IRQ event - Indicates that one of the descendant containers that opened by
- * this container is destroyed
- */
-#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED     0x00000010
-
-/*
- * IRQ event - Indicates that on one of the container's opened object is
- * destroyed
- */
-#define DPRC_IRQ_EVENT_OBJ_DESTROYED           0x00000020
-
-/* Irq event - Indicates that object is created at the container */
-#define DPRC_IRQ_EVENT_OBJ_CREATED             0x00000040
-
-/**
- * struct dprc_irq_cfg - IRQ configuration
- * @paddr:     Address that must be written to signal a message-based interrupt
- * @val:       Value to write into irq_addr address
- * @irq_num:   A user defined number associated with this IRQ
- */
-struct dprc_irq_cfg {
-            phys_addr_t paddr;
-            u32 val;
-            int irq_num;
-};
-
-int dprc_set_irq(struct fsl_mc_io *mc_io,
-                u32 cmd_flags,
-                u16 token,
-                u8 irq_index,
-                struct dprc_irq_cfg *irq_cfg);
-
-int dprc_get_irq(struct fsl_mc_io *mc_io,
-                u32 cmd_flags,
-                u16 token,
-                u8 irq_index,
-                int *type,
-                struct dprc_irq_cfg *irq_cfg);
-
-int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
-                       u32 cmd_flags,
-                       u16 token,
-                       u8 irq_index,
-                       u8 en);
-
-int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
-                       u32 cmd_flags,
-                       u16 token,
-                       u8 irq_index,
-                       u8 *en);
-
-int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
-                     u32 cmd_flags,
-                     u16 token,
-                     u8 irq_index,
-                     u32 mask);
-
-int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
-                     u32 cmd_flags,
-                     u16 token,
-                     u8 irq_index,
-                     u32 *mask);
-
-int dprc_get_irq_status(struct fsl_mc_io *mc_io,
-                       u32 cmd_flags,
-                       u16 token,
-                       u8 irq_index,
-                       u32 *status);
-
-int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
-                         u32 cmd_flags,
-                         u16 token,
-                         u8 irq_index,
-                         u32 status);
-
-/**
- * struct dprc_attributes - Container attributes
- * @container_id: Container's ID
- * @icid: Container's ICID
- * @portal_id: Container's portal ID
- * @options: Container's options as set at container's creation
- */
-struct dprc_attributes {
-       int container_id;
-       u16 icid;
-       int portal_id;
-       u64 options;
-};
-
-int dprc_get_attributes(struct fsl_mc_io *mc_io,
-                       u32 cmd_flags,
-                       u16 token,
-                       struct dprc_attributes *attributes);
-
-int dprc_get_obj_count(struct fsl_mc_io *mc_io,
-                      u32 cmd_flags,
-                      u16 token,
-                      int *obj_count);
-
-int dprc_get_obj(struct fsl_mc_io *mc_io,
-                u32 cmd_flags,
-                u16 token,
-                int obj_index,
-                struct fsl_mc_obj_desc *obj_desc);
-
-int dprc_get_obj_desc(struct fsl_mc_io *mc_io,
-                     u32 cmd_flags,
-                     u16 token,
-                     char *obj_type,
-                     int obj_id,
-                     struct fsl_mc_obj_desc *obj_desc);
-
-int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
-                    u32 cmd_flags,
-                    u16 token,
-                    char *obj_type,
-                    int obj_id,
-                    u8 irq_index,
-                    struct dprc_irq_cfg *irq_cfg);
-
-int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
-                    u32 cmd_flags,
-                    u16 token,
-                    char *obj_type,
-                    int obj_id,
-                    u8 irq_index,
-                    int *type,
-                    struct dprc_irq_cfg *irq_cfg);
-
-int dprc_get_res_count(struct fsl_mc_io *mc_io,
-                      u32 cmd_flags,
-                      u16 token,
-                      char *type,
-                      int *res_count);
-
-/**
- * enum dprc_iter_status - Iteration status
- * @DPRC_ITER_STATUS_FIRST: Perform first iteration
- * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed
- * @DPRC_ITER_STATUS_LAST: Indicates last iteration
- */
-enum dprc_iter_status {
-       DPRC_ITER_STATUS_FIRST = 0,
-       DPRC_ITER_STATUS_MORE = 1,
-       DPRC_ITER_STATUS_LAST = 2
-};
-
-/* Region flags */
-/* Cacheable - Indicates that region should be mapped as cacheable */
-#define DPRC_REGION_CACHEABLE  0x00000001
-
-/**
- * enum dprc_region_type - Region type
- * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region
- * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region
- */
-enum dprc_region_type {
-       DPRC_REGION_TYPE_MC_PORTAL,
-       DPRC_REGION_TYPE_QBMAN_PORTAL
-};
-
-/**
- * struct dprc_region_desc - Mappable region descriptor
- * @base_offset: Region offset from region's base address.
- *     For DPMCP and DPRC objects, region base is offset from SoC MC portals
- *     base address; For DPIO, region base is offset from SoC QMan portals
- *     base address
- * @size: Region size (in bytes)
- * @flags: Region attributes
- * @type: Portal region type
- */
-struct dprc_region_desc {
-       u32 base_offset;
-       u32 size;
-       u32 flags;
-       enum dprc_region_type type;
-};
-
-int dprc_get_obj_region(struct fsl_mc_io *mc_io,
-                       u32 cmd_flags,
-                       u16 token,
-                       char *obj_type,
-                       int obj_id,
-                       u8 region_index,
-                       struct dprc_region_desc *region_desc);
-
-int dprc_get_api_version(struct fsl_mc_io *mc_io,
-                        u32 cmd_flags,
-                        u16 *major_ver,
-                        u16 *minor_ver);
-
-int dprc_get_container_id(struct fsl_mc_io *mc_io,
-                         u32 cmd_flags,
-                         int *container_id);
-
-#endif /* _FSL_DPRC_H */
-
index 8ea3920400a06b6a43e8456375fb6fae2b20577f..8f313a41240b34efd4fbb5196cbb1f2718f41f2c 100644 (file)
@@ -1,11 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * fsl-mc object allocator driver
  *
  * Copyright (C) 2013-2016 Freescale Semiconductor, 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.
  */
 
 #include <linux/module.h>
 
 #include "fsl-mc-private.h"
 
-static bool __must_check fsl_mc_is_allocatable(const char *obj_type)
+static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev)
 {
-       return strcmp(obj_type, "dpbp") == 0 ||
-              strcmp(obj_type, "dpmcp") == 0 ||
-              strcmp(obj_type, "dpcon") == 0;
+       return is_fsl_mc_bus_dpbp(mc_dev) ||
+              is_fsl_mc_bus_dpmcp(mc_dev) ||
+              is_fsl_mc_bus_dpcon(mc_dev);
 }
 
 /**
@@ -41,25 +39,25 @@ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
        struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
        int error = -EINVAL;
 
-       if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
+       if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
                goto out;
-       if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
+       if (!fsl_mc_is_allocatable(mc_dev))
                goto out;
-       if (WARN_ON(mc_dev->resource))
+       if (mc_dev->resource)
                goto out;
 
        res_pool = &mc_bus->resource_pools[pool_type];
-       if (WARN_ON(res_pool->type != pool_type))
+       if (res_pool->type != pool_type)
                goto out;
-       if (WARN_ON(res_pool->mc_bus != mc_bus))
+       if (res_pool->mc_bus != mc_bus)
                goto out;
 
        mutex_lock(&res_pool->mutex);
 
-       if (WARN_ON(res_pool->max_count < 0))
+       if (res_pool->max_count < 0)
                goto out_unlock;
-       if (WARN_ON(res_pool->free_count < 0 ||
-                   res_pool->free_count > res_pool->max_count))
+       if (res_pool->free_count < 0 ||
+           res_pool->free_count > res_pool->max_count)
                goto out_unlock;
 
        resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
@@ -105,25 +103,25 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
        struct fsl_mc_resource *resource;
        int error = -EINVAL;
 
-       if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
+       if (!fsl_mc_is_allocatable(mc_dev))
                goto out;
 
        resource = mc_dev->resource;
-       if (WARN_ON(!resource || resource->data != mc_dev))
+       if (!resource || resource->data != mc_dev)
                goto out;
 
        mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
        mc_bus = to_fsl_mc_bus(mc_bus_dev);
        res_pool = resource->parent_pool;
-       if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type]))
+       if (res_pool != &mc_bus->resource_pools[resource->type])
                goto out;
 
        mutex_lock(&res_pool->mutex);
 
-       if (WARN_ON(res_pool->max_count <= 0))
+       if (res_pool->max_count <= 0)
                goto out_unlock;
-       if (WARN_ON(res_pool->free_count <= 0 ||
-                   res_pool->free_count > res_pool->max_count))
+       if (res_pool->free_count <= 0 ||
+           res_pool->free_count > res_pool->max_count)
                goto out_unlock;
 
        /*
@@ -187,11 +185,11 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
                     FSL_MC_NUM_POOL_TYPES);
 
        *new_resource = NULL;
-       if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
+       if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
                goto out;
 
        res_pool = &mc_bus->resource_pools[pool_type];
-       if (WARN_ON(res_pool->mc_bus != mc_bus))
+       if (res_pool->mc_bus != mc_bus)
                goto out;
 
        mutex_lock(&res_pool->mutex);
@@ -199,7 +197,6 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
                                            struct fsl_mc_resource, node);
 
        if (!resource) {
-               WARN_ON(res_pool->free_count != 0);
                error = -ENXIO;
                dev_err(&mc_bus_dev->dev,
                        "No more resources of type %s left\n",
@@ -207,12 +204,12 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
                goto out_unlock;
        }
 
-       if (WARN_ON(resource->type != pool_type))
+       if (resource->type != pool_type)
                goto out_unlock;
-       if (WARN_ON(resource->parent_pool != res_pool))
+       if (resource->parent_pool != res_pool)
                goto out_unlock;
-       if (WARN_ON(res_pool->free_count <= 0 ||
-                   res_pool->free_count > res_pool->max_count))
+       if (res_pool->free_count <= 0 ||
+           res_pool->free_count > res_pool->max_count)
                goto out_unlock;
 
        list_del_init(&resource->node);
@@ -232,15 +229,15 @@ void fsl_mc_resource_free(struct fsl_mc_resource *resource)
        struct fsl_mc_resource_pool *res_pool;
 
        res_pool = resource->parent_pool;
-       if (WARN_ON(resource->type != res_pool->type))
+       if (resource->type != res_pool->type)
                return;
 
        mutex_lock(&res_pool->mutex);
-       if (WARN_ON(res_pool->free_count < 0 ||
-                   res_pool->free_count >= res_pool->max_count))
+       if (res_pool->free_count < 0 ||
+           res_pool->free_count >= res_pool->max_count)
                goto out_unlock;
 
-       if (WARN_ON(!list_empty(&resource->node)))
+       if (!list_empty(&resource->node))
                goto out_unlock;
 
        list_add_tail(&resource->node, &res_pool->free_list);
@@ -279,13 +276,13 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
        struct fsl_mc_resource *resource = NULL;
 
        *new_mc_adev = NULL;
-       if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC))
+       if (mc_dev->flags & FSL_MC_IS_DPRC)
                goto error;
 
-       if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
+       if (!dev_is_fsl_mc(mc_dev->dev.parent))
                goto error;
 
-       if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP))
+       if (pool_type == FSL_MC_POOL_DPMCP)
                goto error;
 
        mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
@@ -295,7 +292,7 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
                goto error;
 
        mc_adev = resource->data;
-       if (WARN_ON(!mc_adev))
+       if (!mc_adev)
                goto error;
 
        *new_mc_adev = mc_adev;
@@ -318,9 +315,9 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
        struct fsl_mc_resource *resource;
 
        resource = mc_adev->resource;
-       if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP))
+       if (resource->type == FSL_MC_POOL_DPMCP)
                return;
-       if (WARN_ON(resource->data != mc_adev))
+       if (resource->data != mc_adev)
                return;
 
        fsl_mc_resource_free(resource);
@@ -349,8 +346,8 @@ int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
        struct fsl_mc_resource_pool *res_pool =
                        &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
 
-       if (WARN_ON(irq_count == 0 ||
-                   irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS))
+       if (irq_count == 0 ||
+           irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
                return -EINVAL;
 
        error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
@@ -406,13 +403,13 @@ void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
        struct fsl_mc_resource_pool *res_pool =
                        &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
 
-       if (WARN_ON(!mc_bus->irq_resources))
+       if (!mc_bus->irq_resources)
                return;
 
-       if (WARN_ON(res_pool->max_count == 0))
+       if (res_pool->max_count == 0)
                return;
 
-       if (WARN_ON(res_pool->free_count != res_pool->max_count))
+       if (res_pool->free_count != res_pool->max_count)
                return;
 
        INIT_LIST_HEAD(&res_pool->free_list);
@@ -436,19 +433,19 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
        struct fsl_mc_bus *mc_bus;
        struct fsl_mc_resource_pool *res_pool;
 
-       if (WARN_ON(mc_dev->irqs))
+       if (mc_dev->irqs)
                return -EINVAL;
 
        irq_count = mc_dev->obj_desc.irq_count;
-       if (WARN_ON(irq_count == 0))
+       if (irq_count == 0)
                return -EINVAL;
 
-       if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
+       if (is_fsl_mc_bus_dprc(mc_dev))
                mc_bus = to_fsl_mc_bus(mc_dev);
        else
                mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
 
-       if (WARN_ON(!mc_bus->irq_resources))
+       if (!mc_bus->irq_resources)
                return -EINVAL;
 
        res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
@@ -474,7 +471,6 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
                irqs[i] = to_fsl_mc_irq(resource);
                res_allocated_count++;
 
-               WARN_ON(irqs[i]->mc_dev);
                irqs[i]->mc_dev = mc_dev;
                irqs[i]->dev_irq_index = i;
        }
@@ -502,21 +498,20 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
        struct fsl_mc_bus *mc_bus;
        struct fsl_mc_device_irq **irqs = mc_dev->irqs;
 
-       if (WARN_ON(!irqs))
+       if (!irqs)
                return;
 
        irq_count = mc_dev->obj_desc.irq_count;
 
-       if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
+       if (is_fsl_mc_bus_dprc(mc_dev))
                mc_bus = to_fsl_mc_bus(mc_dev);
        else
                mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
 
-       if (WARN_ON(!mc_bus->irq_resources))
+       if (!mc_bus->irq_resources)
                return;
 
        for (i = 0; i < irq_count; i++) {
-               WARN_ON(!irqs[i]->mc_dev);
                irqs[i]->mc_dev = NULL;
                fsl_mc_resource_free(&irqs[i]->resource);
        }
@@ -553,17 +548,10 @@ static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
                                        &mc_bus->resource_pools[pool_type];
        int free_count = 0;
 
-       WARN_ON(res_pool->type != pool_type);
-       WARN_ON(res_pool->free_count != res_pool->max_count);
-
        list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
                free_count++;
-               WARN_ON(resource->type != res_pool->type);
-               WARN_ON(resource->parent_pool != res_pool);
                devm_kfree(&mc_bus_dev->dev, resource);
        }
-
-       WARN_ON(free_count != res_pool->free_count);
 }
 
 void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
@@ -585,11 +573,11 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
        struct fsl_mc_bus *mc_bus;
        int error;
 
-       if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
+       if (!fsl_mc_is_allocatable(mc_dev))
                return -EINVAL;
 
        mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
-       if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev)))
+       if (!dev_is_fsl_mc(&mc_bus_dev->dev))
                return -EINVAL;
 
        mc_bus = to_fsl_mc_bus(mc_bus_dev);
@@ -614,7 +602,7 @@ static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
 {
        int error;
 
-       if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
+       if (!fsl_mc_is_allocatable(mc_dev))
                return -EINVAL;
 
        if (mc_dev->resource) {
@@ -658,8 +646,3 @@ int __init fsl_mc_allocator_driver_init(void)
 {
        return fsl_mc_driver_register(&fsl_mc_allocator_driver);
 }
-
-void fsl_mc_allocator_driver_exit(void)
-{
-       fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
-}
index 409f2b9e70ff6a786378dbc3f3878dbe92b4e736..1b333c43aae9b7606847552cd157c6f76634d8f2 100644 (file)
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Freescale Management Complex (MC) bus driver
  *
  * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
  * Author: German Rivera <German.Rivera@freescale.com>
  *
- * 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.
  */
 
 #define pr_fmt(fmt) "fsl-mc: " fmt
@@ -22,8 +20,6 @@
 #include <linux/dma-mapping.h>
 
 #include "fsl-mc-private.h"
-#include "dprc-cmd.h"
-#include "dpmng-cmd.h"
 
 /**
  * Default DMA mask for devices on a fsl-mc bus
@@ -156,22 +152,80 @@ struct bus_type fsl_mc_bus_type = {
 };
 EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
 
+struct device_type fsl_mc_bus_dprc_type = {
+       .name = "fsl_mc_bus_dprc"
+};
+
+struct device_type fsl_mc_bus_dpni_type = {
+       .name = "fsl_mc_bus_dpni"
+};
+
+struct device_type fsl_mc_bus_dpio_type = {
+       .name = "fsl_mc_bus_dpio"
+};
+
+struct device_type fsl_mc_bus_dpsw_type = {
+       .name = "fsl_mc_bus_dpsw"
+};
+
+struct device_type fsl_mc_bus_dpbp_type = {
+       .name = "fsl_mc_bus_dpbp"
+};
+
+struct device_type fsl_mc_bus_dpcon_type = {
+       .name = "fsl_mc_bus_dpcon"
+};
+
+struct device_type fsl_mc_bus_dpmcp_type = {
+       .name = "fsl_mc_bus_dpmcp"
+};
+
+struct device_type fsl_mc_bus_dpmac_type = {
+       .name = "fsl_mc_bus_dpmac"
+};
+
+struct device_type fsl_mc_bus_dprtc_type = {
+       .name = "fsl_mc_bus_dprtc"
+};
+
+static struct device_type *fsl_mc_get_device_type(const char *type)
+{
+       static const struct {
+               struct device_type *dev_type;
+               const char *type;
+       } dev_types[] = {
+               { &fsl_mc_bus_dprc_type, "dprc" },
+               { &fsl_mc_bus_dpni_type, "dpni" },
+               { &fsl_mc_bus_dpio_type, "dpio" },
+               { &fsl_mc_bus_dpsw_type, "dpsw" },
+               { &fsl_mc_bus_dpbp_type, "dpbp" },
+               { &fsl_mc_bus_dpcon_type, "dpcon" },
+               { &fsl_mc_bus_dpmcp_type, "dpmcp" },
+               { &fsl_mc_bus_dpmac_type, "dpmac" },
+               { &fsl_mc_bus_dprtc_type, "dprtc" },
+               { NULL, NULL }
+       };
+       int i;
+
+       for (i = 0; dev_types[i].dev_type; i++)
+               if (!strcmp(dev_types[i].type, type))
+                       return dev_types[i].dev_type;
+
+       return NULL;
+}
+
 static int fsl_mc_driver_probe(struct device *dev)
 {
        struct fsl_mc_driver *mc_drv;
        struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
        int error;
 
-       if (WARN_ON(!dev->driver))
-               return -EINVAL;
-
        mc_drv = to_fsl_mc_driver(dev->driver);
-       if (WARN_ON(!mc_drv->probe))
-               return -EINVAL;
 
        error = mc_drv->probe(mc_dev);
        if (error < 0) {
-               dev_err(dev, "%s failed: %d\n", __func__, error);
+               if (error != -EPROBE_DEFER)
+                       dev_err(dev, "%s failed: %d\n", __func__, error);
                return error;
        }
 
@@ -184,9 +238,6 @@ static int fsl_mc_driver_remove(struct device *dev)
        struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
        int error;
 
-       if (WARN_ON(!dev->driver))
-               return -EINVAL;
-
        error = mc_drv->remove(mc_dev);
        if (error < 0) {
                dev_err(dev, "%s failed: %d\n", __func__, error);
@@ -292,9 +343,9 @@ static int mc_get_version(struct fsl_mc_io *mc_io,
 static void fsl_mc_get_root_dprc(struct device *dev,
                                 struct device **root_dprc_dev)
 {
-       if (WARN_ON(!dev)) {
+       if (!dev) {
                *root_dprc_dev = NULL;
-       } else if (WARN_ON(!dev_is_fsl_mc(dev))) {
+       } else if (!dev_is_fsl_mc(dev)) {
                *root_dprc_dev = NULL;
        } else {
                *root_dprc_dev = dev;
@@ -352,8 +403,6 @@ static int translate_mc_addr(struct fsl_mc_device *mc_dev,
        struct fsl_mc *mc;
 
        fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
-       if (WARN_ON(!root_dprc_dev))
-               return -EINVAL;
        mc = dev_get_drvdata(root_dprc_dev->parent);
 
        if (mc->num_translation_ranges == 0) {
@@ -390,10 +439,10 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
        struct device *parent_dev = mc_dev->dev.parent;
        enum dprc_region_type mc_region_type;
 
-       if (strcmp(obj_desc->type, "dprc") == 0 ||
-           strcmp(obj_desc->type, "dpmcp") == 0) {
+       if (is_fsl_mc_bus_dprc(mc_dev) ||
+           is_fsl_mc_bus_dpmcp(mc_dev)) {
                mc_region_type = DPRC_REGION_TYPE_MC_PORTAL;
-       } else if (strcmp(obj_desc->type, "dpio") == 0) {
+       } else if (is_fsl_mc_bus_dpio(mc_dev)) {
                mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL;
        } else {
                /*
@@ -401,7 +450,6 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
                 * type, as this object type is not supposed to have MMIO
                 * regions
                 */
-               WARN_ON(true);
                return -EINVAL;
        }
 
@@ -424,7 +472,6 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
                        goto error_cleanup_regions;
                }
 
-               WARN_ON(region_desc.size == 0);
                error = translate_mc_addr(mc_dev, mc_region_type,
                                          region_desc.base_offset,
                                          &regions[i].start);
@@ -470,7 +517,7 @@ static void fsl_mc_device_release(struct device *dev)
 
        kfree(mc_dev->regions);
 
-       if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
+       if (is_fsl_mc_bus_dprc(mc_dev))
                kfree(to_fsl_mc_bus(mc_dev));
        else
                kfree(mc_dev);
@@ -518,6 +565,12 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
        mc_dev->dev.parent = parent_dev;
        mc_dev->dev.bus = &fsl_mc_bus_type;
        mc_dev->dev.release = fsl_mc_device_release;
+       mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type);
+       if (!mc_dev->dev.type) {
+               error = -ENODEV;
+               dev_err(parent_dev, "unknown device type %s\n", obj_desc->type);
+               goto error_cleanup_dev;
+       }
        dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
 
        if (strcmp(obj_desc->type, "dprc") == 0) {
@@ -544,7 +597,7 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
                        /*
                         * device being added is the root DPRC device
                         */
-                       if (WARN_ON(!mc_io)) {
+                       if (!mc_io) {
                                error = -EINVAL;
                                goto error_cleanup_dev;
                        }
@@ -826,7 +879,7 @@ static int fsl_mc_bus_remove(struct platform_device *pdev)
 {
        struct fsl_mc *mc = platform_get_drvdata(pdev);
 
-       if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)))
+       if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))
                return -EINVAL;
 
        fsl_mc_device_remove(mc->root_mc_bus_dev);
@@ -878,15 +931,8 @@ static int __init fsl_mc_bus_driver_init(void)
        if (error < 0)
                goto error_cleanup_dprc_driver;
 
-       error = its_fsl_mc_msi_init();
-       if (error < 0)
-               goto error_cleanup_mc_allocator;
-
        return 0;
 
-error_cleanup_mc_allocator:
-       fsl_mc_allocator_driver_exit();
-
 error_cleanup_dprc_driver:
        dprc_driver_exit();
 
index f74a6f1764bbc775828cffb6ad29d28cc71df4d0..971ad87c584c38b197bdd71d7c71cb1114c87f90 100644 (file)
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Freescale Management Complex (MC) bus driver MSI support
  *
  * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
  * Author: German Rivera <German.Rivera@freescale.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
  */
 
 #include <linux/of_device.h>
@@ -47,7 +45,7 @@ static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
 {
        struct msi_domain_ops *ops = info->ops;
 
-       if (WARN_ON(!ops))
+       if (!ops)
                return;
 
        /*
@@ -73,7 +71,7 @@ static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
        if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
                return;
 
-       if (WARN_ON(!owner_mc_dev))
+       if (!owner_mc_dev)
                return;
 
        irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
@@ -124,7 +122,6 @@ static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
        struct fsl_mc_device_irq *mc_dev_irq =
                &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
 
-       WARN_ON(mc_dev_irq->msi_desc != msi_desc);
        msi_desc->msg = *msg;
 
        /*
@@ -137,7 +134,7 @@ static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
 {
        struct irq_chip *chip = info->chip;
 
-       if (WARN_ON(!chip))
+       if (!chip)
                return;
 
        /*
@@ -239,7 +236,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
        struct irq_domain *msi_domain;
        int error;
 
-       if (WARN_ON(!list_empty(dev_to_msi_list(dev))))
+       if (!list_empty(dev_to_msi_list(dev)))
                return -EINVAL;
 
        error = fsl_mc_msi_alloc_descs(dev, irq_count);
@@ -247,7 +244,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
                return error;
 
        msi_domain = dev_get_msi_domain(dev);
-       if (WARN_ON(!msi_domain)) {
+       if (!msi_domain) {
                error = -EINVAL;
                goto cleanup_msi_descs;
        }
@@ -275,12 +272,12 @@ void fsl_mc_msi_domain_free_irqs(struct device *dev)
        struct irq_domain *msi_domain;
 
        msi_domain = dev_get_msi_domain(dev);
-       if (WARN_ON(!msi_domain))
+       if (!msi_domain)
                return;
 
        msi_domain_free_irqs(msi_domain, dev);
 
-       if (WARN_ON(list_empty(dev_to_msi_list(dev))))
+       if (list_empty(dev_to_msi_list(dev)))
                return;
 
        fsl_mc_msi_free_descs(dev);
index 62d3989476059aca83a9f479522abd1e2a1c7adf..83b89d6241f2f838eafb33bcfce61ecbc7c84362 100644 (file)
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Freescale Management Complex (MC) bus private declarations
  *
  * Copyright (C) 2016 Freescale Semiconductor, 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.
  */
 #ifndef _FSL_MC_PRIVATE_H_
 #define _FSL_MC_PRIVATE_H_
 
 #include "../include/mc.h"
-#include "dprc.h"
 #include <linux/mutex.h>
 
+/*
+ * Data Path Management Complex (DPMNG) General API
+ */
+
+/* DPMNG command versioning */
+#define DPMNG_CMD_BASE_VERSION         1
+#define DPMNG_CMD_ID_OFFSET            4
+
+#define DPMNG_CMD(id)  (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
+
+/* DPMNG command IDs */
+#define DPMNG_CMDID_GET_VERSION                DPMNG_CMD(0x831)
+
+struct dpmng_rsp_get_version {
+       __le32 revision;
+       __le32 version_major;
+       __le32 version_minor;
+};
+
+/*
+ * Data Path Management Command Portal (DPMCP) API
+ */
+
+/* Minimal supported DPMCP Version */
+#define DPMCP_MIN_VER_MAJOR            3
+#define DPMCP_MIN_VER_MINOR            0
+
+/* DPMCP command versioning */
+#define DPMCP_CMD_BASE_VERSION         1
+#define DPMCP_CMD_ID_OFFSET            4
+
+#define DPMCP_CMD(id)  (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
+
+/* DPMCP command IDs */
+#define DPMCP_CMDID_CLOSE              DPMCP_CMD(0x800)
+#define DPMCP_CMDID_OPEN               DPMCP_CMD(0x80b)
+#define DPMCP_CMDID_RESET              DPMCP_CMD(0x005)
+
+struct dpmcp_cmd_open {
+       __le32 dpmcp_id;
+};
+
+/*
+ * Initialization and runtime control APIs for DPMCP
+ */
+int dpmcp_open(struct fsl_mc_io *mc_io,
+              u32 cmd_flags,
+              int dpmcp_id,
+              u16 *token);
+
+int dpmcp_close(struct fsl_mc_io *mc_io,
+               u32 cmd_flags,
+               u16 token);
+
+int dpmcp_reset(struct fsl_mc_io *mc_io,
+               u32 cmd_flags,
+               u16 token);
+
+/*
+ * Data Path Resource Container (DPRC) API
+ */
+
+/* Minimal supported DPRC Version */
+#define DPRC_MIN_VER_MAJOR                     6
+#define DPRC_MIN_VER_MINOR                     0
+
+/* DPRC command versioning */
+#define DPRC_CMD_BASE_VERSION                  1
+#define DPRC_CMD_ID_OFFSET                     4
+
+#define DPRC_CMD(id)   (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
+
+/* DPRC command IDs */
+#define DPRC_CMDID_CLOSE                        DPRC_CMD(0x800)
+#define DPRC_CMDID_OPEN                         DPRC_CMD(0x805)
+#define DPRC_CMDID_GET_API_VERSION              DPRC_CMD(0xa05)
+
+#define DPRC_CMDID_GET_ATTR                     DPRC_CMD(0x004)
+
+#define DPRC_CMDID_SET_IRQ                      DPRC_CMD(0x010)
+#define DPRC_CMDID_SET_IRQ_ENABLE               DPRC_CMD(0x012)
+#define DPRC_CMDID_SET_IRQ_MASK                 DPRC_CMD(0x014)
+#define DPRC_CMDID_GET_IRQ_STATUS               DPRC_CMD(0x016)
+#define DPRC_CMDID_CLEAR_IRQ_STATUS             DPRC_CMD(0x017)
+
+#define DPRC_CMDID_GET_CONT_ID                  DPRC_CMD(0x830)
+#define DPRC_CMDID_GET_OBJ_COUNT                DPRC_CMD(0x159)
+#define DPRC_CMDID_GET_OBJ                      DPRC_CMD(0x15A)
+#define DPRC_CMDID_GET_OBJ_REG                  DPRC_CMD(0x15E)
+#define DPRC_CMDID_SET_OBJ_IRQ                  DPRC_CMD(0x15F)
+
+struct dprc_cmd_open {
+       __le32 container_id;
+};
+
+struct dprc_cmd_set_irq {
+       /* cmd word 0 */
+       __le32 irq_val;
+       u8 irq_index;
+       u8 pad[3];
+       /* cmd word 1 */
+       __le64 irq_addr;
+       /* cmd word 2 */
+       __le32 irq_num;
+};
+
+#define DPRC_ENABLE            0x1
+
+struct dprc_cmd_set_irq_enable {
+       u8 enable;
+       u8 pad[3];
+       u8 irq_index;
+};
+
+struct dprc_cmd_set_irq_mask {
+       __le32 mask;
+       u8 irq_index;
+};
+
+struct dprc_cmd_get_irq_status {
+       __le32 status;
+       u8 irq_index;
+};
+
+struct dprc_rsp_get_irq_status {
+       __le32 status;
+};
+
+struct dprc_cmd_clear_irq_status {
+       __le32 status;
+       u8 irq_index;
+};
+
+struct dprc_rsp_get_attributes {
+       /* response word 0 */
+       __le32 container_id;
+       __le16 icid;
+       __le16 pad;
+       /* response word 1 */
+       __le32 options;
+       __le32 portal_id;
+};
+
+struct dprc_rsp_get_obj_count {
+       __le32 pad;
+       __le32 obj_count;
+};
+
+struct dprc_cmd_get_obj {
+       __le32 obj_index;
+};
+
+struct dprc_rsp_get_obj {
+       /* response word 0 */
+       __le32 pad0;
+       __le32 id;
+       /* response word 1 */
+       __le16 vendor;
+       u8 irq_count;
+       u8 region_count;
+       __le32 state;
+       /* response word 2 */
+       __le16 version_major;
+       __le16 version_minor;
+       __le16 flags;
+       __le16 pad1;
+       /* response word 3-4 */
+       u8 type[16];
+       /* response word 5-6 */
+       u8 label[16];
+};
+
+struct dprc_cmd_get_obj_region {
+       /* cmd word 0 */
+       __le32 obj_id;
+       __le16 pad0;
+       u8 region_index;
+       u8 pad1;
+       /* cmd word 1-2 */
+       __le64 pad2[2];
+       /* cmd word 3-4 */
+       u8 obj_type[16];
+};
+
+struct dprc_rsp_get_obj_region {
+       /* response word 0 */
+       __le64 pad;
+       /* response word 1 */
+       __le64 base_addr;
+       /* response word 2 */
+       __le32 size;
+};
+
+struct dprc_cmd_set_obj_irq {
+       /* cmd word 0 */
+       __le32 irq_val;
+       u8 irq_index;
+       u8 pad[3];
+       /* cmd word 1 */
+       __le64 irq_addr;
+       /* cmd word 2 */
+       __le32 irq_num;
+       __le32 obj_id;
+       /* cmd word 3-4 */
+       u8 obj_type[16];
+};
+
+/*
+ * DPRC API for managing and querying DPAA resources
+ */
+int dprc_open(struct fsl_mc_io *mc_io,
+             u32 cmd_flags,
+             int container_id,
+             u16 *token);
+
+int dprc_close(struct fsl_mc_io *mc_io,
+              u32 cmd_flags,
+              u16 token);
+
+/* DPRC IRQ events */
+
+/* IRQ event - Indicates that a new object added to the container */
+#define DPRC_IRQ_EVENT_OBJ_ADDED               0x00000001
+/* IRQ event - Indicates that an object was removed from the container */
+#define DPRC_IRQ_EVENT_OBJ_REMOVED             0x00000002
+/*
+ * IRQ event - Indicates that one of the descendant containers that opened by
+ * this container is destroyed
+ */
+#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED     0x00000010
+
+/*
+ * IRQ event - Indicates that on one of the container's opened object is
+ * destroyed
+ */
+#define DPRC_IRQ_EVENT_OBJ_DESTROYED           0x00000020
+
+/* Irq event - Indicates that object is created at the container */
+#define DPRC_IRQ_EVENT_OBJ_CREATED             0x00000040
+
+/**
+ * struct dprc_irq_cfg - IRQ configuration
+ * @paddr:     Address that must be written to signal a message-based interrupt
+ * @val:       Value to write into irq_addr address
+ * @irq_num:   A user defined number associated with this IRQ
+ */
+struct dprc_irq_cfg {
+            phys_addr_t paddr;
+            u32 val;
+            int irq_num;
+};
+
+int dprc_set_irq(struct fsl_mc_io *mc_io,
+                u32 cmd_flags,
+                u16 token,
+                u8 irq_index,
+                struct dprc_irq_cfg *irq_cfg);
+
+int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
+                       u32 cmd_flags,
+                       u16 token,
+                       u8 irq_index,
+                       u8 en);
+
+int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
+                     u32 cmd_flags,
+                     u16 token,
+                     u8 irq_index,
+                     u32 mask);
+
+int dprc_get_irq_status(struct fsl_mc_io *mc_io,
+                       u32 cmd_flags,
+                       u16 token,
+                       u8 irq_index,
+                       u32 *status);
+
+int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
+                         u32 cmd_flags,
+                         u16 token,
+                         u8 irq_index,
+                         u32 status);
+
+/**
+ * struct dprc_attributes - Container attributes
+ * @container_id: Container's ID
+ * @icid: Container's ICID
+ * @portal_id: Container's portal ID
+ * @options: Container's options as set at container's creation
+ */
+struct dprc_attributes {
+       int container_id;
+       u16 icid;
+       int portal_id;
+       u64 options;
+};
+
+int dprc_get_attributes(struct fsl_mc_io *mc_io,
+                       u32 cmd_flags,
+                       u16 token,
+                       struct dprc_attributes *attributes);
+
+int dprc_get_obj_count(struct fsl_mc_io *mc_io,
+                      u32 cmd_flags,
+                      u16 token,
+                      int *obj_count);
+
+int dprc_get_obj(struct fsl_mc_io *mc_io,
+                u32 cmd_flags,
+                u16 token,
+                int obj_index,
+                struct fsl_mc_obj_desc *obj_desc);
+
+int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
+                    u32 cmd_flags,
+                    u16 token,
+                    char *obj_type,
+                    int obj_id,
+                    u8 irq_index,
+                    struct dprc_irq_cfg *irq_cfg);
+
+/* Region flags */
+/* Cacheable - Indicates that region should be mapped as cacheable */
+#define DPRC_REGION_CACHEABLE  0x00000001
+
+/**
+ * enum dprc_region_type - Region type
+ * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region
+ * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region
+ */
+enum dprc_region_type {
+       DPRC_REGION_TYPE_MC_PORTAL,
+       DPRC_REGION_TYPE_QBMAN_PORTAL
+};
+
+/**
+ * struct dprc_region_desc - Mappable region descriptor
+ * @base_offset: Region offset from region's base address.
+ *     For DPMCP and DPRC objects, region base is offset from SoC MC portals
+ *     base address; For DPIO, region base is offset from SoC QMan portals
+ *     base address
+ * @size: Region size (in bytes)
+ * @flags: Region attributes
+ * @type: Portal region type
+ */
+struct dprc_region_desc {
+       u32 base_offset;
+       u32 size;
+       u32 flags;
+       enum dprc_region_type type;
+};
+
+int dprc_get_obj_region(struct fsl_mc_io *mc_io,
+                       u32 cmd_flags,
+                       u16 token,
+                       char *obj_type,
+                       int obj_id,
+                       u8 region_index,
+                       struct dprc_region_desc *region_desc);
+
+int dprc_get_api_version(struct fsl_mc_io *mc_io,
+                        u32 cmd_flags,
+                        u16 *major_ver,
+                        u16 *minor_ver);
+
+int dprc_get_container_id(struct fsl_mc_io *mc_io,
+                         u32 cmd_flags,
+                         int *container_id);
+
 /**
  * Maximum number of total IRQs that can be pre-allocated for an MC bus'
  * IRQ pool
@@ -73,8 +438,6 @@ void dprc_driver_exit(void);
 
 int __init fsl_mc_allocator_driver_init(void);
 
-void fsl_mc_allocator_driver_exit(void);
-
 void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
 
 void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
@@ -91,10 +454,6 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
 
 void fsl_mc_msi_domain_free_irqs(struct device *dev);
 
-int __init its_fsl_mc_msi_init(void);
-
-void its_fsl_mc_msi_cleanup(void);
-
 int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
                           struct irq_domain **mc_msi_domain);
 
index 123e4af584081115bec627e49c57c3e315cb4e43..5064d5ddf581c2282eba49ab87a668da83a5aeee 100644 (file)
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Freescale Management Complex (MC) bus driver MSI support
  *
  * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
  * Author: German Rivera <German.Rivera@freescale.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
  */
 
 #include <linux/of_device.h>
@@ -15,7 +13,7 @@
 #include <linux/msi.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
-#include "fsl-mc-private.h"
+#include "../include/mc.h"
 
 static struct irq_chip its_msi_irq_chip = {
        .name = "ITS-fMSI",
@@ -32,11 +30,11 @@ static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
        struct fsl_mc_device *mc_bus_dev;
        struct msi_domain_info *msi_info;
 
-       if (WARN_ON(!dev_is_fsl_mc(dev)))
+       if (!dev_is_fsl_mc(dev))
                return -EINVAL;
 
        mc_bus_dev = to_fsl_mc_device(dev);
-       if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC)))
+       if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC))
                return -EINVAL;
 
        /*
@@ -67,7 +65,7 @@ static const struct of_device_id its_device_id[] = {
        {},
 };
 
-int __init its_fsl_mc_msi_init(void)
+static int __init its_fsl_mc_msi_init(void)
 {
        struct device_node *np;
        struct irq_domain *parent;
@@ -93,30 +91,10 @@ int __init its_fsl_mc_msi_init(void)
                        continue;
                }
 
-               WARN_ON(mc_msi_domain->host_data !=
-                       &its_fsl_mc_msi_domain_info);
-
                pr_info("fsl-mc MSI: %pOF domain created\n", np);
        }
 
        return 0;
 }
 
-void its_fsl_mc_msi_cleanup(void)
-{
-       struct device_node *np;
-
-       for (np = of_find_matching_node(NULL, its_device_id); np;
-            np = of_find_matching_node(np, its_device_id)) {
-               struct irq_domain *mc_msi_domain = irq_find_matching_host(
-                                                       np,
-                                                       DOMAIN_BUS_FSL_MC_MSI);
-
-               if (!of_property_read_bool(np, "msi-controller"))
-                       continue;
-
-               if (mc_msi_domain &&
-                   mc_msi_domain->host_data == &its_fsl_mc_msi_domain_info)
-                       irq_domain_remove(mc_msi_domain);
-       }
-}
+early_initcall(its_fsl_mc_msi_init);
index f65c23ce83f169bbc160df503e8dcf94a8f67c59..7e6fb360ef12fe2cb342a299c1a0fa9cf88bd62c 100644 (file)
@@ -1,54 +1,23 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
- * 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 the above-listed copyright holders nor the
- *       names of any contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS 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/io.h>
 #include "../include/mc.h"
 
 #include "fsl-mc-private.h"
-#include "dpmcp.h"
-#include "dpmcp-cmd.h"
 
 static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
                               struct fsl_mc_device *dpmcp_dev)
 {
        int error;
 
-       if (WARN_ON(!dpmcp_dev))
-               return -EINVAL;
-
-       if (WARN_ON(mc_io->dpmcp_dev))
+       if (mc_io->dpmcp_dev)
                return -EINVAL;
 
-       if (WARN_ON(dpmcp_dev->mc_io))
+       if (dpmcp_dev->mc_io)
                return -EINVAL;
 
        error = dpmcp_open(mc_io,
@@ -68,12 +37,6 @@ static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
        int error;
        struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
 
-       if (WARN_ON(!dpmcp_dev))
-               return;
-
-       if (WARN_ON(dpmcp_dev->mc_io != mc_io))
-               return;
-
        error = dpmcp_close(mc_io,
                            0,
                            dpmcp_dev->mc_handle);
@@ -210,7 +173,7 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
        if (mc_dev->flags & FSL_MC_IS_DPRC) {
                mc_bus_dev = mc_dev;
        } else {
-               if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
+               if (!dev_is_fsl_mc(mc_dev->dev.parent))
                        return error;
 
                mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
@@ -224,8 +187,6 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
 
        error = -EINVAL;
        dpmcp_dev = resource->data;
-       if (WARN_ON(!dpmcp_dev))
-               goto error_cleanup_resource;
 
        if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
            (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
@@ -238,15 +199,9 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
                goto error_cleanup_resource;
        }
 
-       if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0))
-               goto error_cleanup_resource;
-
        mc_portal_phys_addr = dpmcp_dev->regions[0].start;
        mc_portal_size = resource_size(dpmcp_dev->regions);
 
-       if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size))
-               goto error_cleanup_resource;
-
        error = fsl_create_mc_io(&mc_bus_dev->dev,
                                 mc_portal_phys_addr,
                                 mc_portal_size, dpmcp_dev,
@@ -279,14 +234,12 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
         * to have a DPMCP object associated with.
         */
        dpmcp_dev = mc_io->dpmcp_dev;
-       if (WARN_ON(!dpmcp_dev))
-               return;
 
        resource = dpmcp_dev->resource;
-       if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP))
+       if (!resource || resource->type != FSL_MC_POOL_DPMCP)
                return;
 
-       if (WARN_ON(resource->data != dpmcp_dev))
+       if (resource->data != dpmcp_dev)
                return;
 
        fsl_destroy_mc_io(mc_io);
@@ -304,9 +257,6 @@ int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
        int error;
        struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
 
-       if (WARN_ON(!dpmcp_dev))
-               return -EINVAL;
-
        error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
        if (error < 0) {
                dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
index 7ce105bd397782ce38e39da044aa07bf1f3c74a9..f09d75d9a9761a2a2abae1d8165889fcd5c4d219 100644 (file)
@@ -1,35 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
  * I/O services to send MC commands to the MC hardware
  *
- * 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 the above-listed copyright holders nor the
- *       names of any contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS 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>
@@ -40,7 +14,7 @@
 #include <linux/io-64-nonatomic-hi-lo.h>
 #include "../include/mc.h"
 
-#include "dpmcp.h"
+#include "fsl-mc-private.h"
 
 /**
  * Timeout in milliseconds to wait for the completion of an MC command
@@ -85,7 +59,7 @@ static int mc_status_to_error(enum mc_cmd_status status)
                [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
        };
 
-       if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map)))
+       if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map))
                return -EINVAL;
 
        return mc_status_to_error_map[status];
@@ -273,8 +247,7 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
        enum mc_cmd_status status;
        unsigned long irq_flags = 0;
 
-       if (WARN_ON(in_irq() &&
-                   !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)))
+       if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
                return -EINVAL;
 
        if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
@@ -320,4 +293,4 @@ common_exit:
 
        return error;
 }
-EXPORT_SYMBOL(mc_send_command);
+EXPORT_SYMBOL_GPL(mc_send_command);
index cf7857f00a5c2f7a77d1b769315362862eb5dd8f..3e022001f0b1e2df39e6e69635a8132df9f11e69 100644 (file)
@@ -1,33 +1,8 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright 2014-2016 Freescale Semiconductor Inc.
  * Copyright 2016 NXP
  *
- * 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 Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef __FSL_DPAA2_FD_H
 #define __FSL_DPAA2_FD_H
index 0326447fde4e76f93cb01de5808eb56856fa1783..9bc0713346a8fc7b51f2059528fa1c1ad2a4a56c 100644 (file)
@@ -1,33 +1,8 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright 2014-2016 Freescale Semiconductor Inc.
  * Copyright 2016 NXP
  *
- * 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 Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef __FSL_DPAA2_GLOBAL_H
 #define __FSL_DPAA2_GLOBAL_H
index afc2d060d077cffd29d9f503323770befb211d66..9cb1eec87a9c67955791e9c9727879082f0b0a84 100644 (file)
@@ -1,33 +1,8 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright 2014-2016 Freescale Semiconductor Inc.
  * Copyright NXP
  *
- * 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 Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef __FSL_DPAA2_IO_H
 #define __FSL_DPAA2_IO_H
@@ -88,6 +63,8 @@ void dpaa2_io_down(struct dpaa2_io *d);
 
 irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj);
 
+struct dpaa2_io *dpaa2_io_service_select(int cpu);
+
 /**
  * struct dpaa2_io_notification_ctx - The DPIO notification context structure
  * @cb:           The callback to be invoked when the notification arrives
@@ -120,13 +97,9 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service,
 int dpaa2_io_service_rearm(struct dpaa2_io *service,
                           struct dpaa2_io_notification_ctx *ctx);
 
-int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid,
-                            struct dpaa2_io_store *s);
 int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,
                                  struct dpaa2_io_store *s);
 
-int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid,
-                               const struct dpaa2_fd *fd);
 int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
                                u16 qdbin, const struct dpaa2_fd *fd);
 int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid,
index e9e04ccea82b9c773f30cb82d893dd1ddbf6ad75..4a18096043198cca5dec2fe4781a4d5560c4ff5d 100644 (file)
@@ -1,34 +1,7 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef __FSL_DPBP_H
 #define __FSL_DPBP_H
index efa23906b36402d2874c7a3a18f48ad6f632bfd5..062e90ad929bebad02fcec20a471beba6caf50f7 100644 (file)
@@ -1,33 +1,7 @@
-/* Copyright 2013-2016 Freescale Semiconductor Inc.
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright 2013-2016 Freescale Semiconductor Inc.
  *
- * 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 the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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 HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef __FSL_DPCON_H
 #define __FSL_DPCON_H
@@ -62,11 +36,6 @@ int dpcon_disable(struct fsl_mc_io *mc_io,
                  u32 cmd_flags,
                  u16 token);
 
-int dpcon_is_enabled(struct fsl_mc_io *mc_io,
-                    u32 cmd_flags,
-                    u16 token,
-                    int *en);
-
 int dpcon_reset(struct fsl_mc_io *mc_io,
                u32 cmd_flags,
                u16 token);
@@ -107,9 +76,4 @@ int dpcon_set_notification(struct fsl_mc_io *mc_io,
                           u16 token,
                           struct dpcon_notification_cfg *cfg);
 
-int dpcon_get_api_version(struct fsl_mc_io *mc_io,
-                         u32 cmd_flags,
-                         u16 *major_ver,
-                         u16 *minor_ver);
-
 #endif /* __FSL_DPCON_H */
index aafe63a21f4958cf895426a787b694ae0ecd18dd..765ba41f5987fb1303c34fbaaaf72eaed121c8f0 100644 (file)
@@ -1,12 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Freescale Management Complex (MC) bus public interface
  *
  * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
  * Author: German Rivera <German.Rivera@freescale.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
  */
 #ifndef _FSL_MC_H_
 #define _FSL_MC_H_
@@ -325,7 +323,7 @@ static inline void mc_cmd_read_api_version(struct mc_command *cmd,
 struct fsl_mc_io {
        struct device *dev;
        u16 flags;
-       u16 portal_size;
+       u32 portal_size;
        phys_addr_t portal_phys_addr;
        void __iomem *portal_virt_addr;
        struct fsl_mc_device *dpmcp_dev;
@@ -398,4 +396,59 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
 
 extern struct bus_type fsl_mc_bus_type;
 
+extern struct device_type fsl_mc_bus_dprc_type;
+extern struct device_type fsl_mc_bus_dpni_type;
+extern struct device_type fsl_mc_bus_dpio_type;
+extern struct device_type fsl_mc_bus_dpsw_type;
+extern struct device_type fsl_mc_bus_dpbp_type;
+extern struct device_type fsl_mc_bus_dpcon_type;
+extern struct device_type fsl_mc_bus_dpmcp_type;
+extern struct device_type fsl_mc_bus_dpmac_type;
+extern struct device_type fsl_mc_bus_dprtc_type;
+
+static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev)
+{
+       return mc_dev->dev.type == &fsl_mc_bus_dprc_type;
+}
+
+static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev)
+{
+       return mc_dev->dev.type == &fsl_mc_bus_dpni_type;
+}
+
+static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev)
+{
+       return mc_dev->dev.type == &fsl_mc_bus_dpio_type;
+}
+
+static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev)
+{
+       return mc_dev->dev.type == &fsl_mc_bus_dpsw_type;
+}
+
+static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev)
+{
+       return mc_dev->dev.type == &fsl_mc_bus_dpbp_type;
+}
+
+static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev)
+{
+       return mc_dev->dev.type == &fsl_mc_bus_dpcon_type;
+}
+
+static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev)
+{
+       return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type;
+}
+
+static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev)
+{
+       return mc_dev->dev.type == &fsl_mc_bus_dpmac_type;
+}
+
+static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev)
+{
+       return mc_dev->dev.type == &fsl_mc_bus_dprtc_type;
+}
+
 #endif /* _FSL_MC_H_ */
diff --git a/drivers/staging/fsl-mc/overview.rst b/drivers/staging/fsl-mc/overview.rst
new file mode 100644 (file)
index 0000000..79fede4
--- /dev/null
@@ -0,0 +1,404 @@
+.. include:: <isonum.txt>
+
+DPAA2 (Data Path Acceleration Architecture Gen2) Overview
+=========================================================
+
+:Copyright: |copy| 2015 Freescale Semiconductor Inc.
+:Copyright: |copy| 2018 NXP
+
+This document provides an overview of the Freescale DPAA2 architecture
+and how it is integrated into the Linux kernel.
+
+Introduction
+============
+
+DPAA2 is a hardware architecture designed for high-speeed network
+packet processing.  DPAA2 consists of sophisticated mechanisms for
+processing Ethernet packets, queue management, buffer management,
+autonomous L2 switching, virtual Ethernet bridging, and accelerator
+(e.g. crypto) sharing.
+
+A DPAA2 hardware component called the Management Complex (or MC) manages the
+DPAA2 hardware resources.  The MC provides an object-based abstraction for
+software drivers to use the DPAA2 hardware.
+The MC uses DPAA2 hardware resources such as queues, buffer pools, and
+network ports to create functional objects/devices such as network
+interfaces, an L2 switch, or accelerator instances.
+The MC provides memory-mapped I/O command interfaces (MC portals)
+which DPAA2 software drivers use to operate on DPAA2 objects.
+
+The diagram below shows an overview of the DPAA2 resource management
+architecture::
+
+       +--------------------------------------+
+       |                  OS                  |
+       |                        DPAA2 drivers |
+       |                             |        |
+       +-----------------------------|--------+
+                                     |
+                                     | (create,discover,connect
+                                     |  config,use,destroy)
+                                     |
+                        DPAA2        |
+       +------------------------| mc portal |-+
+       |                             |        |
+       |   +- - - - - - - - - - - - -V- - -+  |
+       |   |                               |  |
+       |   |   Management Complex (MC)     |  |
+       |   |                               |  |
+       |   +- - - - - - - - - - - - - - - -+  |
+       |                                      |
+       | Hardware                  Hardware   |
+       | Resources                 Objects    |
+       | ---------                 -------    |
+       | -queues                   -DPRC      |
+       | -buffer pools             -DPMCP     |
+       | -Eth MACs/ports           -DPIO      |
+       | -network interface        -DPNI      |
+       |  profiles                 -DPMAC     |
+       | -queue portals            -DPBP      |
+       | -MC portals                ...       |
+       |  ...                                 |
+       |                                      |
+       +--------------------------------------+
+
+
+The MC mediates operations such as create, discover,
+connect, configuration, and destroy.  Fast-path operations
+on data, such as packet transmit/receive, are not mediated by
+the MC and are done directly using memory mapped regions in
+DPIO objects.
+
+Overview of DPAA2 Objects
+=========================
+
+The section provides a brief overview of some key DPAA2 objects.
+A simple scenario is described illustrating the objects involved
+in creating a network interfaces.
+
+DPRC (Datapath Resource Container)
+----------------------------------
+
+A DPRC is a container object that holds all the other
+types of DPAA2 objects.  In the example diagram below there
+are 8 objects of 5 types (DPMCP, DPIO, DPBP, DPNI, and DPMAC)
+in the container.
+
+::
+
+       +---------------------------------------------------------+
+       | DPRC                                                    |
+       |                                                         |
+       |  +-------+  +-------+  +-------+  +-------+  +-------+  |
+       |  | DPMCP |  | DPIO  |  | DPBP  |  | DPNI  |  | DPMAC |  |
+       |  +-------+  +-------+  +-------+  +---+---+  +---+---+  |
+       |  | DPMCP |  | DPIO  |                                   |
+       |  +-------+  +-------+                                   |
+       |  | DPMCP |                                              |
+       |  +-------+                                              |
+       |                                                         |
+       +---------------------------------------------------------+
+
+From the point of view of an OS, a DPRC behaves similar to a plug and
+play bus, like PCI.  DPRC commands can be used to enumerate the contents
+of the DPRC, discover the hardware objects present (including mappable
+regions and interrupts).
+
+::
+
+       DPRC.1 (bus)
+          |
+          +--+--------+-------+-------+-------+
+             |        |       |       |       |
+           DPMCP.1  DPIO.1  DPBP.1  DPNI.1  DPMAC.1
+           DPMCP.2  DPIO.2
+           DPMCP.3
+
+Hardware objects can be created and destroyed dynamically, providing
+the ability to hot plug/unplug objects in and out of the DPRC.
+
+A DPRC has a mappable MMIO region (an MC portal) that can be used
+to send MC commands.  It has an interrupt for status events (like
+hotplug).
+All objects in a container share the same hardware "isolation context".
+This means that with respect to an IOMMU the isolation granularity
+is at the DPRC (container) level, not at the individual object
+level.
+
+DPRCs can be defined statically and populated with objects
+via a config file passed to the MC when firmware starts it.
+
+DPAA2 Objects for an Ethernet Network Interface
+-----------------------------------------------
+
+A typical Ethernet NIC is monolithic-- the NIC device contains TX/RX
+queuing mechanisms, configuration mechanisms, buffer management,
+physical ports, and interrupts.  DPAA2 uses a more granular approach
+utilizing multiple hardware objects.  Each object provides specialized
+functions. Groups of these objects are used by software to provide
+Ethernet network interface functionality.  This approach provides
+efficient use of finite hardware resources, flexibility, and
+performance advantages.
+
+The diagram below shows the objects needed for a simple
+network interface configuration on a system with 2 CPUs.
+
+::
+
+       +---+---+ +---+---+
+          CPU0     CPU1
+       +---+---+ +---+---+
+           |         |
+       +---+---+ +---+---+
+          DPIO     DPIO
+       +---+---+ +---+---+
+           \     /
+            \   /
+             \ /
+          +---+---+
+             DPNI  --- DPBP,DPMCP
+          +---+---+
+              |
+              |
+          +---+---+
+            DPMAC
+          +---+---+
+              |
+          port/PHY
+
+Below the objects are described.  For each object a brief description
+is provided along with a summary of the kinds of operations the object
+supports and a summary of key resources of the object (MMIO regions
+and IRQs).
+
+DPMAC (Datapath Ethernet MAC)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Represents an Ethernet MAC, a hardware device that connects to an Ethernet
+PHY and allows physical transmission and reception of Ethernet frames.
+
+- MMIO regions: none
+- IRQs: DPNI link change
+- commands: set link up/down, link config, get stats,
+  IRQ config, enable, reset
+
+DPNI (Datapath Network Interface)
+Contains TX/RX queues, network interface configuration, and RX buffer pool
+configuration mechanisms.  The TX/RX queues are in memory and are identified
+by queue number.
+
+- MMIO regions: none
+- IRQs: link state
+- commands: port config, offload config, queue config,
+  parse/classify config, IRQ config, enable, reset
+
+DPIO (Datapath I/O)
+~~~~~~~~~~~~~~~~~~~
+Provides interfaces to enqueue and dequeue
+packets and do hardware buffer pool management operations.  The DPAA2
+architecture separates the mechanism to access queues (the DPIO object)
+from the queues themselves.  The DPIO provides an MMIO interface to
+enqueue/dequeue packets.  To enqueue something a descriptor is written
+to the DPIO MMIO region, which includes the target queue number.
+There will typically be one DPIO assigned to each CPU.  This allows all
+CPUs to simultaneously perform enqueue/dequeued operations.  DPIOs are
+expected to be shared by different DPAA2 drivers.
+
+- MMIO regions: queue operations, buffer management
+- IRQs: data availability, congestion notification, buffer
+  pool depletion
+- commands: IRQ config, enable, reset
+
+DPBP (Datapath Buffer Pool)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Represents a hardware buffer pool.
+
+- MMIO regions: none
+- IRQs: none
+- commands: enable, reset
+
+DPMCP (Datapath MC Portal)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+Provides an MC command portal.
+Used by drivers to send commands to the MC to manage
+objects.
+
+- MMIO regions: MC command portal
+- IRQs: command completion
+- commands: IRQ config, enable, reset
+
+Object Connections
+==================
+Some objects have explicit relationships that must
+be configured:
+
+- DPNI <--> DPMAC
+- DPNI <--> DPNI
+- DPNI <--> L2-switch-port
+
+    A DPNI must be connected to something such as a DPMAC,
+    another DPNI, or L2 switch port.  The DPNI connection
+    is made via a DPRC command.
+
+::
+
+              +-------+  +-------+
+              | DPNI  |  | DPMAC |
+              +---+---+  +---+---+
+                  |          |
+                  +==========+
+
+- DPNI <--> DPBP
+
+    A network interface requires a 'buffer pool' (DPBP
+    object) which provides a list of pointers to memory
+    where received Ethernet data is to be copied.  The
+    Ethernet driver configures the DPBPs associated with
+    the network interface.
+
+Interrupts
+==========
+All interrupts generated by DPAA2 objects are message
+interrupts.  At the hardware level message interrupts
+generated by devices will normally have 3 components--
+1) a non-spoofable 'device-id' expressed on the hardware
+bus, 2) an address, 3) a data value.
+
+In the case of DPAA2 devices/objects, all objects in the
+same container/DPRC share the same 'device-id'.
+For ARM-based SoC this is the same as the stream ID.
+
+
+DPAA2 Linux Drivers Overview
+============================
+
+This section provides an overview of the Linux kernel drivers for
+DPAA2-- 1) the bus driver and associated "DPAA2 infrastructure"
+drivers and 2) functional object drivers (such as Ethernet).
+
+As described previously, a DPRC is a container that holds the other
+types of DPAA2 objects.  It is functionally similar to a plug-and-play
+bus controller.
+Each object in the DPRC is a Linux "device" and is bound to a driver.
+The diagram below shows the Linux drivers involved in a networking
+scenario and the objects bound to each driver.  A brief description
+of each driver follows.
+
+::
+
+                                            +------------+
+                                            | OS Network |
+                                            |   Stack    |
+                +------------+              +------------+
+                | Allocator  |. . . . . . . |  Ethernet  |
+                |(DPMCP,DPBP)|              |   (DPNI)   |
+                +-.----------+              +---+---+----+
+                 .          .                   ^   |
+                .            .     <data avail, |   | <enqueue,
+               .              .     tx confirm> |   | dequeue>
+       +-------------+         .                |   |
+       | DPRC driver |          .           +---+---V----+     +---------+
+       |   (DPRC)    |           . . . . . .| DPIO driver|     |   MAC   |
+       +----------+--+                      |  (DPIO)    |     | (DPMAC) |
+                  |                         +------+-----+     +-----+---+
+                  |<dev add/remove>                |                 |
+                  |                                |                 |
+         +--------+----------+                     |              +--+---+
+         |   MC-bus driver   |                     |              | PHY  |
+         |                   |                     |              |driver|
+         |   /bus/fsl-mc     |                     |              +--+---+
+         +-------------------+                     |                 |
+                                                   |                 |
+       ========================= HARDWARE =========|=================|======
+                                                 DPIO                |
+                                                   |                 |
+                                                 DPNI---DPBP         |
+                                                   |                 |
+                                                 DPMAC               |
+                                                   |                 |
+                                                  PHY ---------------+
+       ============================================|========================
+
+A brief description of each driver is provided below.
+
+MC-bus driver
+-------------
+The MC-bus driver is a platform driver and is probed from a
+node in the device tree (compatible "fsl,qoriq-mc") passed in by boot
+firmware.  It is responsible for bootstrapping the DPAA2 kernel
+infrastructure.
+Key functions include:
+
+- registering a new bus type named "fsl-mc" with the kernel,
+  and implementing bus call-backs (e.g. match/uevent/dev_groups)
+- implementing APIs for DPAA2 driver registration and for device
+  add/remove
+- creates an MSI IRQ domain
+- doing a 'device add' to expose the 'root' DPRC, in turn triggering
+  a bind of the root DPRC to the DPRC driver
+
+The binding for the MC-bus device-tree node can be consulted at
+*Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt*.
+The sysfs bind/unbind interfaces for the MC-bus can be consulted at
+*Documentation/ABI/testing/sysfs-bus-fsl-mc*.
+
+DPRC driver
+-----------
+The DPRC driver is bound to DPRC objects and does runtime management
+of a bus instance.  It performs the initial bus scan of the DPRC
+and handles interrupts for container events such as hot plug by
+re-scanning the DPRC.
+
+Allocator
+---------
+Certain objects such as DPMCP and DPBP are generic and fungible,
+and are intended to be used by other drivers.  For example,
+the DPAA2 Ethernet driver needs:
+
+- DPMCPs to send MC commands, to configure network interfaces
+- DPBPs for network buffer pools
+
+The allocator driver registers for these allocatable object types
+and those objects are bound to the allocator when the bus is probed.
+The allocator maintains a pool of objects that are available for
+allocation by other DPAA2 drivers.
+
+DPIO driver
+-----------
+The DPIO driver is bound to DPIO objects and provides services that allow
+other drivers such as the Ethernet driver to enqueue and dequeue data for
+their respective objects.
+Key services include:
+
+- data availability notifications
+- hardware queuing operations (enqueue and dequeue of data)
+- hardware buffer pool management
+
+To transmit a packet the Ethernet driver puts data on a queue and
+invokes a DPIO API.  For receive, the Ethernet driver registers
+a data availability notification callback.  To dequeue a packet
+a DPIO API is used.
+There is typically one DPIO object per physical CPU for optimum
+performance, allowing different CPUs to simultaneously enqueue
+and dequeue data.
+
+The DPIO driver operates on behalf of all DPAA2 drivers
+active in the kernel--  Ethernet, crypto, compression,
+etc.
+
+Ethernet driver
+---------------
+The Ethernet driver is bound to a DPNI and implements the kernel
+interfaces needed to connect the DPAA2 network interface to
+the network stack.
+Each DPNI corresponds to a Linux network interface.
+
+MAC driver
+----------
+An Ethernet PHY is an off-chip, board specific component and is managed
+by the appropriate PHY driver via an mdio bus.  The MAC driver
+plays a role of being a proxy between the PHY driver and the
+MC.  It does this proxy via the MC commands to a DPMAC object.
+If the PHY driver signals a link change, the MAC driver notifies
+the MC via a DPMAC command.  If a network interface is brought
+up or down, the MC notifies the DPMAC driver via an interrupt and
+the driver can take appropriate action.
index 8b23a553fd4a8e01af31cbe81e4e44b68c8316a3..5dcbab6fd6224c2f8822e0fcb56aa5fb4585c897 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * DMA-able FIFO implementation
  *
  * Copyright (C) 2012 Peter Hurley <peter@hurleysoftware.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.
  */
 
 #include <linux/kernel.h>
index 37a91c6a17098a1bcc4e2e690faf47fc204819f2..c46a06336975617ba2e166ce6a3cc052d3cf9d18 100644 (file)
@@ -1,17 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * DMA-able FIFO interface
  *
  * Copyright (C) 2012 Peter Hurley <peter@hurleysoftware.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 _DMA_FIFO_H_
index bba7e9c888b37617f55662246e8bfbdfef894a75..1993b03a6f2d6fdc40540a00959d65670aa41aca 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * FireWire Serial driver
  *
  * Copyright (C) 2012 Peter Hurley <peter@hurleysoftware.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
index b0c66112eb18f4a3b0f31ef3f828abd6270143da..cc8d6fc831b41673a6b231e32e7f26f82978a139 100644 (file)
@@ -72,14 +72,14 @@ static int coldboot_seq(struct platform_device *pdev)
        int ret;
 
        if (apb->init_disabled ||
-                       apb->state == ARCHE_PLATFORM_STATE_ACTIVE)
+           apb->state == ARCHE_PLATFORM_STATE_ACTIVE)
                return 0;
 
        /* Hold APB in reset state */
        assert_reset(apb->resetn_gpio);
 
        if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
-                       gpio_is_valid(apb->spi_en_gpio))
+           gpio_is_valid(apb->spi_en_gpio))
                devm_gpio_free(dev, apb->spi_en_gpio);
 
        /* Enable power to APB */
@@ -122,7 +122,7 @@ static int fw_flashing_seq(struct platform_device *pdev)
        int ret;
 
        if (apb->init_disabled ||
-                       apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
+           apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
                return 0;
 
        ret = regulator_enable(apb->vcore);
@@ -146,7 +146,7 @@ static int fw_flashing_seq(struct platform_device *pdev)
                        flags = GPIOF_OUT_INIT_LOW;
 
                ret = devm_gpio_request_one(dev, apb->spi_en_gpio,
-                               flags, "apb_spi_en");
+                                           flags, "apb_spi_en");
                if (ret) {
                        dev_err(dev, "Failed requesting SPI bus en gpio %d\n",
                                apb->spi_en_gpio);
@@ -174,11 +174,11 @@ static int standby_boot_seq(struct platform_device *pdev)
         * then we do not want to change the state
         */
        if (apb->state == ARCHE_PLATFORM_STATE_STANDBY ||
-                       apb->state == ARCHE_PLATFORM_STATE_OFF)
+           apb->state == ARCHE_PLATFORM_STATE_OFF)
                return 0;
 
        if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
-                       gpio_is_valid(apb->spi_en_gpio))
+           gpio_is_valid(apb->spi_en_gpio))
                devm_gpio_free(dev, apb->spi_en_gpio);
 
        /*
@@ -203,7 +203,7 @@ static void poweroff_seq(struct platform_device *pdev)
                return;
 
        if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
-                       gpio_is_valid(apb->spi_en_gpio))
+           gpio_is_valid(apb->spi_en_gpio))
                devm_gpio_free(dev, apb->spi_en_gpio);
 
        /* disable the clock */
@@ -251,7 +251,8 @@ void apb_ctrl_poweroff(struct device *dev)
 }
 
 static ssize_t state_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
@@ -297,7 +298,7 @@ static ssize_t state_store(struct device *dev,
 }
 
 static ssize_t state_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
+                         struct device_attribute *attr, char *buf)
 {
        struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev);
 
@@ -319,7 +320,7 @@ static ssize_t state_show(struct device *dev,
 static DEVICE_ATTR_RW(state);
 
 static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
-               struct arche_apb_ctrl_drvdata *apb)
+                                    struct arche_apb_ctrl_drvdata *apb)
 {
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
@@ -331,10 +332,10 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
                return apb->resetn_gpio;
        }
        ret = devm_gpio_request_one(dev, apb->resetn_gpio,
-                       GPIOF_OUT_INIT_LOW, "apb-reset");
+                                   GPIOF_OUT_INIT_LOW, "apb-reset");
        if (ret) {
                dev_err(dev, "Failed requesting reset gpio %d\n",
-                               apb->resetn_gpio);
+                       apb->resetn_gpio);
                return ret;
        }
 
@@ -344,10 +345,10 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
                return apb->boot_ret_gpio;
        }
        ret = devm_gpio_request_one(dev, apb->boot_ret_gpio,
-                       GPIOF_OUT_INIT_LOW, "boot retention");
+                                   GPIOF_OUT_INIT_LOW, "boot retention");
        if (ret) {
                dev_err(dev, "Failed requesting bootret gpio %d\n",
-                               apb->boot_ret_gpio);
+                       apb->boot_ret_gpio);
                return ret;
        }
 
@@ -358,10 +359,10 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
                return apb->pwroff_gpio;
        }
        ret = devm_gpio_request_one(dev, apb->pwroff_gpio,
-                       GPIOF_IN, "pwroff_n");
+                                   GPIOF_IN, "pwroff_n");
        if (ret) {
                dev_err(dev, "Failed requesting pwroff_n gpio %d\n",
-                               apb->pwroff_gpio);
+                       apb->pwroff_gpio);
                return ret;
        }
 
@@ -371,10 +372,10 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
                dev_warn(dev, "failed to get clock en gpio\n");
        } else if (gpio_is_valid(apb->clk_en_gpio)) {
                ret = devm_gpio_request_one(dev, apb->clk_en_gpio,
-                               GPIOF_OUT_INIT_LOW, "apb_clk_en");
+                                           GPIOF_OUT_INIT_LOW, "apb_clk_en");
                if (ret) {
                        dev_warn(dev, "Failed requesting APB clock en gpio %d\n",
-                                       apb->clk_en_gpio);
+                                apb->clk_en_gpio);
                        return ret;
                }
        }
@@ -407,7 +408,7 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
        apb->spi_en_gpio = of_get_named_gpio(np, "spi-en-gpio", 0);
        if (apb->spi_en_gpio >= 0) {
                if (of_property_read_bool(pdev->dev.of_node,
-                                       "spi-en-active-high"))
+                                         "spi-en-active-high"))
                        apb->spi_en_polarity_high = true;
        }
 
index ace4eb365c0e422e2f076e1f956cc2ba5f5783b3..83254a72a7bbbd34ea12167ae480e8620d37130a 100644 (file)
@@ -233,7 +233,7 @@ arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata)
        ret = clk_prepare_enable(arche_pdata->svc_ref_clk);
        if (ret) {
                dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n",
-                               ret);
+                       ret);
                return ret;
        }
 
@@ -269,7 +269,7 @@ arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata)
        ret = clk_prepare_enable(arche_pdata->svc_ref_clk);
        if (ret) {
                dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n",
-                               ret);
+                       ret);
                return ret;
        }
 
@@ -312,7 +312,8 @@ arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata)
 }
 
 static ssize_t state_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
@@ -376,7 +377,7 @@ exit:
 }
 
 static ssize_t state_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
+                         struct device_attribute *attr, char *buf)
 {
        struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev);
 
@@ -443,7 +444,7 @@ static int arche_platform_probe(struct platform_device *pdev)
 
        /* setup svc reset gpio */
        arche_pdata->is_reset_act_hi = of_property_read_bool(np,
-                                       "svc,reset-active-high");
+                                                            "svc,reset-active-high");
        arche_pdata->svc_reset_gpio = of_get_named_gpio(np,
                                                        "svc,reset-gpio",
                                                        0);
@@ -457,7 +458,7 @@ static int arche_platform_probe(struct platform_device *pdev)
                return ret;
        }
        ret = gpio_direction_output(arche_pdata->svc_reset_gpio,
-                                       arche_pdata->is_reset_act_hi);
+                                   arche_pdata->is_reset_act_hi);
        if (ret) {
                dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret);
                return ret;
@@ -465,7 +466,8 @@ static int arche_platform_probe(struct platform_device *pdev)
        arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
 
        arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np,
-                                       "svc,sysboot-gpio", 0);
+                                                         "svc,sysboot-gpio",
+                                                         0);
        if (arche_pdata->svc_sysboot_gpio < 0) {
                dev_err(dev, "failed to get sysboot gpio\n");
                return arche_pdata->svc_sysboot_gpio;
@@ -483,7 +485,8 @@ static int arche_platform_probe(struct platform_device *pdev)
 
        /* setup the clock request gpio first */
        arche_pdata->svc_refclk_req = of_get_named_gpio(np,
-                                       "svc,refclk-req-gpio", 0);
+                                                       "svc,refclk-req-gpio",
+                                                       0);
        if (arche_pdata->svc_refclk_req < 0) {
                dev_err(dev, "failed to get svc clock-req gpio\n");
                return arche_pdata->svc_refclk_req;
@@ -525,7 +528,7 @@ static int arche_platform_probe(struct platform_device *pdev)
                                "wake detect");
        if (ret) {
                dev_err(dev, "Failed requesting wake_detect gpio %d\n",
-                               arche_pdata->wake_detect_gpio);
+                       arche_pdata->wake_detect_gpio);
                return ret;
        }
 
index fdb9e83cc34b31561404088fa89bf68719f6b54f..35acd55ca5ab7bd80682386d4f6b0beb9d851014 100644 (file)
@@ -47,7 +47,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec,
        int module_state, ret = 0;
        u16 data_cport, i2s_port, cportid;
        u8 sig_bits, channels;
-       uint32_t format, rate;
+       u32 format, rate;
        struct gbaudio_data_connection *data;
        struct gbaudio_stream_params *params;
 
@@ -182,7 +182,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec,
        int module_state, ret = 0;
        u16 data_cport, i2s_port, cportid;
        u8 sig_bits, channels;
-       uint32_t format, rate;
+       u32 format, rate;
        struct gbaudio_data_connection *data;
        struct gbaudio_stream_params *params;
 
@@ -319,7 +319,7 @@ int gbaudio_module_update(struct gbaudio_codec_info *codec,
        char intf_name[NAME_SIZE], dir[NAME_SIZE];
 
        dev_dbg(module->dev, "%s:Module update %s sequence\n", w->name,
-               enable ? "Enable":"Disable");
+               enable ? "Enable" : "Disable");
 
        if ((w->id != snd_soc_dapm_aif_in) && (w->id != snd_soc_dapm_aif_out)) {
                dev_dbg(codec->dev, "No action required for %s\n", w->name);
@@ -412,7 +412,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream,
 {
        int ret;
        u8 sig_bits, channels;
-       uint32_t format, rate;
+       u32 format, rate;
        struct gbaudio_module_info *module;
        struct gbaudio_data_connection *data;
        struct gb_bundle *bundle;
@@ -567,7 +567,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream,
        if (ret) {
                mutex_unlock(&codec->lock);
                dev_err_ratelimited(dai->dev, "set_data_size failed:%d\n",
-                                    ret);
+                                   ret);
                return ret;
        }
 
@@ -587,9 +587,8 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
        struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
        struct gbaudio_stream_params *params;
 
-
        dev_dbg(dai->dev, "Mute:%d, Direction:%s\n", mute,
-               stream ? "CAPTURE":"PLAYBACK");
+               stream ? "CAPTURE" : "PLAYBACK");
 
        mutex_lock(&codec->lock);
 
@@ -827,7 +826,7 @@ int gbaudio_register_module(struct gbaudio_module_info *module)
                                          module->num_dapm_widgets);
        if (module->controls)
                snd_soc_add_codec_controls(codec, module->controls,
-                                    module->num_controls);
+                                          module->num_controls);
        if (module->dapm_routes)
                snd_soc_dapm_add_routes(&codec->dapm, module->dapm_routes,
                                        module->num_dapm_routes);
@@ -842,8 +841,8 @@ int gbaudio_register_module(struct gbaudio_module_info *module)
                 * from codec->jack_list
                 */
                list_for_each_entry(jack, &codec->jack_list, list) {
-                       if ((jack == &module->headset_jack)
-                           || (jack == &module->button_jack))
+                       if ((jack == &module->headset_jack) ||
+                           (jack == &module->button_jack))
                                snd_device_register(codec->card->snd_card,
                                                    jack->jack);
                }
@@ -907,7 +906,6 @@ static void gbaudio_codec_clean_data_rx(struct gbaudio_data_connection *data)
        data->state[1] = GBAUDIO_CODEC_SHUTDOWN;
 }
 
-
 static void gbaudio_codec_cleanup(struct gbaudio_module_info *module)
 {
        struct gbaudio_data_connection *data;
@@ -923,7 +921,6 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module)
 
                if (cap_state > GBAUDIO_CODEC_SHUTDOWN)
                        gbaudio_codec_clean_data_rx(data);
-
        }
 }
 
@@ -972,7 +969,7 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module)
                dev_dbg(codec->dev, "Removing %d controls\n",
                        module->num_controls);
                snd_soc_remove_codec_controls(codec, module->controls,
-                                         module->num_controls);
+                                             module->num_controls);
        }
        if (module->dapm_widgets) {
                dev_dbg(codec->dev, "Removing %d widgets\n",
index 161b37c8ef171edbbdbf570a7a4328e3ca38c2a9..a1d5440552d405a72060959e809192768ec0fbdb 100644 (file)
@@ -53,7 +53,7 @@ enum gbaudio_codec_state {
 struct gbaudio_stream_params {
        int state;
        u8 sig_bits, channels;
-       uint32_t format, rate;
+       u32 format, rate;
 };
 
 struct gbaudio_codec_dai {
@@ -159,7 +159,7 @@ struct gbaudio_module_info {
 };
 
 int gbaudio_tplg_parse_data(struct gbaudio_module_info *module,
-                              struct gb_audio_topology *tplg_data);
+                           struct gb_audio_topology *tplg_data);
 void gbaudio_tplg_release(struct gbaudio_module_info *module);
 
 int gbaudio_module_update(struct gbaudio_codec_info *codec,
@@ -183,12 +183,12 @@ extern int gb_audio_gb_enable_widget(struct gb_connection *connection,
 extern int gb_audio_gb_disable_widget(struct gb_connection *connection,
                                      u8 widget_id);
 extern int gb_audio_gb_get_pcm(struct gb_connection *connection,
-                              u16 data_cport, uint32_t *format,
-                              uint32_t *rate, u8 *channels,
+                              u16 data_cport, u32 *format,
+                              u32 *rate, u8 *channels,
                               u8 *sig_bits);
 extern int gb_audio_gb_set_pcm(struct gb_connection *connection,
-                              u16 data_cport, uint32_t format,
-                              uint32_t rate, u8 channels,
+                              u16 data_cport, u32 format,
+                              u32 rate, u8 channels,
                               u8 sig_bits);
 extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection,
                                        u16 data_cport, u16 size);
index 16cc65e1472b59a5b851706e39260ab6774cb0e0..a5d7c53df987b4a3bba1c8c6c47c49f57c9b30c8 100644 (file)
@@ -202,7 +202,7 @@ static int cap_release(struct inode *inode, struct file *file)
 }
 
 static int cap_ioctl(struct gb_cap *cap, unsigned int cmd,
-                        void __user *buf)
+                    void __user *buf)
 {
        struct cap_ioc_get_endpoint_uid endpoint_uid;
        struct cap_ioc_get_ims_certificate *ims_cert;
index f13f16b63d7eda31fa389093b826a6ad51cf2bd7..07ebfb88db9bc66a98c429ed0c0b44e7847a2df3 100644 (file)
@@ -918,7 +918,7 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam,
 
        /* Retrieve number of streams to configure */
        token = strsep(&buf, ";");
-       if (token == NULL)
+       if (!token)
                return -EINVAL;
 
        ret = kstrtouint(token, 10, &nstreams);
@@ -929,7 +929,7 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam,
                return -EINVAL;
 
        token = strsep(&buf, ";");
-       if (token == NULL)
+       if (!token)
                return -EINVAL;
 
        ret = kstrtouint(token, 10, &flags);
@@ -946,7 +946,7 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam,
 
                /* width */
                token = strsep(&buf, ";");
-               if (token == NULL) {
+               if (!token) {
                        ret = -EINVAL;
                        goto done;
                }
@@ -956,7 +956,7 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam,
 
                /* height */
                token = strsep(&buf, ";");
-               if (token == NULL)
+               if (!token)
                        goto done;
 
                ret = kstrtouint(token, 10, &stream->height);
@@ -965,7 +965,7 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam,
 
                /* Image format code */
                token = strsep(&buf, ";");
-               if (token == NULL)
+               if (!token)
                        goto done;
 
                ret = kstrtouint(token, 16, &stream->format);
@@ -1009,7 +1009,7 @@ static ssize_t gb_camera_debugfs_capture(struct gb_camera *gcam,
 
        /* Request id */
        token = strsep(&buf, ";");
-       if (token == NULL)
+       if (!token)
                return -EINVAL;
        ret = kstrtouint(token, 10, &request_id);
        if (ret < 0)
@@ -1017,7 +1017,7 @@ static ssize_t gb_camera_debugfs_capture(struct gb_camera *gcam,
 
        /* Stream mask */
        token = strsep(&buf, ";");
-       if (token == NULL)
+       if (!token)
                return -EINVAL;
        ret = kstrtouint(token, 16, &streams_mask);
        if (ret < 0)
@@ -1025,7 +1025,7 @@ static ssize_t gb_camera_debugfs_capture(struct gb_camera *gcam,
 
        /* number of frames */
        token = strsep(&buf, ";");
-       if (token == NULL)
+       if (!token)
                return -EINVAL;
        ret = kstrtouint(token, 10, &num_frames);
        if (ret < 0)
index 5e839b1fc8849a336967d6fcc3f3d62be115489d..bc5d99cbda8fc65143e845b5921c760f025247ab 100644 (file)
@@ -7,12 +7,7 @@
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #define GPDIR  0
index cadfb96734edc638bd9114f7f0bed83c004e9b32..f01595593ce2d25558a51d47ec2eece33767f002 100644 (file)
@@ -271,7 +271,7 @@ static int ad7192_setup(struct ad7192_state *st,
        if (pdata->sinc3_en)
                st->mode |= AD7192_MODE_SINC3;
 
-       if (pdata->refin2_en && (st->devid != ID_AD7195))
+       if (pdata->refin2_en && st->devid != ID_AD7195)
                st->conf |= AD7192_CONF_REFSEL;
 
        if (pdata->chop_en) {
index 61377ca444dec30c37b26c6d80c29a46539916e3..19dc896603a1a70c1319073ff534ed4b2577a62d 100644 (file)
@@ -47,7 +47,7 @@
 #define AD7152_STATUS_PWDN             BIT(7)
 
 /* Setup Register Bit Designations (AD7152_REG_CHx_SETUP) */
-#define AD7152_SETUP_CAPDIFF           (1 << 5)
+#define AD7152_SETUP_CAPDIFF           BIT(5)
 #define AD7152_SETUP_RANGE_2pF         (0 << 6)
 #define AD7152_SETUP_RANGE_0_5pF       (1 << 6)
 #define AD7152_SETUP_RANGE_1pF         (2 << 6)
@@ -55,8 +55,8 @@
 #define AD7152_SETUP_RANGE(x)          ((x) << 6)
 
 /* Config Register Bit Designations (AD7152_REG_CFG) */
-#define AD7152_CONF_CH2EN              (1 << 3)
-#define AD7152_CONF_CH1EN              (1 << 4)
+#define AD7152_CONF_CH2EN              BIT(3)
+#define AD7152_CONF_CH1EN              BIT(4)
 #define AD7152_CONF_MODE_IDLE          (0 << 0)
 #define AD7152_CONF_MODE_CONT_CONV     (1 << 0)
 #define AD7152_CONF_MODE_SINGLE_CONV   (2 << 0)
@@ -64,7 +64,7 @@
 #define AD7152_CONF_MODE_GAIN_CAL      (6 << 0)
 
 /* Capdac Register Bit Designations (AD7152_REG_CAPDAC_XXX) */
-#define AD7152_CAPDAC_DACEN            (1 << 7)
+#define AD7152_CAPDAC_DACEN            BIT(7)
 #define AD7152_CAPDAC_DACP(x)          ((x) & 0x1F)
 
 /* CFG2 Register Bit Designations (AD7152_REG_CFG2) */
@@ -118,22 +118,23 @@ static inline ssize_t ad7152_start_calib(struct device *dev,
 
        mutex_lock(&chip->state_lock);
        ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG, regval);
-       if (ret < 0) {
-               mutex_unlock(&chip->state_lock);
-               return ret;
-       }
+       if (ret < 0)
+               goto unlock;
 
        do {
                mdelay(20);
                ret = i2c_smbus_read_byte_data(chip->client, AD7152_REG_CFG);
-               if (ret < 0) {
-                       mutex_unlock(&chip->state_lock);
-                       return ret;
-               }
+               if (ret < 0)
+                       goto unlock;
+
        } while ((ret == regval) && timeout--);
 
        mutex_unlock(&chip->state_lock);
        return len;
+
+unlock:
+       mutex_unlock(&chip->state_lock);
+       return ret;
 }
 
 static ssize_t ad7152_start_offset_calib(struct device *dev,
index a124853a05f0e9c6395377af4b47abb28033fc7a..c4a8647253764d188535db73077cf45aa6d79eed 100644 (file)
@@ -302,23 +302,24 @@ static inline ssize_t ad7746_start_calib(struct device *dev,
        mutex_lock(&chip->lock);
        regval |= chip->config;
        ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval);
-       if (ret < 0) {
-               mutex_unlock(&chip->lock);
-               return ret;
-       }
+       if (ret < 0)
+               goto unlock;
 
        do {
                msleep(20);
                ret = i2c_smbus_read_byte_data(chip->client, AD7746_REG_CFG);
-               if (ret < 0) {
-                       mutex_unlock(&chip->lock);
-                       return ret;
-               }
+               if (ret < 0)
+                       goto unlock;
+
        } while ((ret == regval) && timeout--);
 
        mutex_unlock(&chip->lock);
 
        return len;
+
+unlock:
+       mutex_unlock(&chip->lock);
+       return ret;
 }
 
 static ssize_t ad7746_start_offset_calib(struct device *dev,
index 42ed9c015aaf3f188b7c2d3a58efbbdd68f09aad..126e11530ce0dc9373cd78c561be7666485f8774 100644 (file)
@@ -1441,7 +1441,8 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private)
 
 static struct attribute *tsl2x7x_ALS_device_attrs[] = {
        &dev_attr_in_illuminance0_calibscale_available.attr,
-       &iio_const_attr_in_illuminance0_integration_time_available.dev_attr.attr,
+       &iio_const_attr_in_illuminance0_integration_time_available
+               .dev_attr.attr,
        &dev_attr_in_illuminance0_target_input.attr,
        &dev_attr_in_illuminance0_calibrate.attr,
        &dev_attr_in_illuminance0_lux_table.attr,
@@ -1455,7 +1456,8 @@ static struct attribute *tsl2x7x_PRX_device_attrs[] = {
 
 static struct attribute *tsl2x7x_ALSPRX_device_attrs[] = {
        &dev_attr_in_illuminance0_calibscale_available.attr,
-       &iio_const_attr_in_illuminance0_integration_time_available.dev_attr.attr,
+       &iio_const_attr_in_illuminance0_integration_time_available
+               .dev_attr.attr,
        &dev_attr_in_illuminance0_target_input.attr,
        &dev_attr_in_illuminance0_calibrate.attr,
        &dev_attr_in_illuminance0_lux_table.attr,
@@ -1471,7 +1473,8 @@ static struct attribute *tsl2x7x_PRX2_device_attrs[] = {
 
 static struct attribute *tsl2x7x_ALSPRX2_device_attrs[] = {
        &dev_attr_in_illuminance0_calibscale_available.attr,
-       &iio_const_attr_in_illuminance0_integration_time_available.dev_attr.attr,
+       &iio_const_attr_in_illuminance0_integration_time_available
+               .dev_attr.attr,
        &dev_attr_in_illuminance0_target_input.attr,
        &dev_attr_in_illuminance0_calibrate.attr,
        &dev_attr_in_illuminance0_lux_table.attr,
index d80dcf82eba92c32a98e7e777694aa10090772ab..71f11d7472c0824176e1cdb5c0f473097bef73f2 100644 (file)
@@ -78,9 +78,9 @@ static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state)
        return 0;
 }
 
-static ssize_t iio_bfin_tmr_frequency_store(struct device *dev,
-                                           struct device_attribute *attr,
-                                           const char *buf, size_t count)
+static ssize_t frequency_store(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t count)
 {
        struct iio_trigger *trig = to_iio_trigger(dev);
        struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
@@ -116,9 +116,9 @@ static ssize_t iio_bfin_tmr_frequency_store(struct device *dev,
        return count;
 }
 
-static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
-                                          struct device_attribute *attr,
-                                          char *buf)
+static ssize_t frequency_show(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
 {
        struct iio_trigger *trig = to_iio_trigger(dev);
        struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
@@ -133,8 +133,7 @@ static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
        return sprintf(buf, "%lu\n", val);
 }
 
-static DEVICE_ATTR(frequency, 0644, iio_bfin_tmr_frequency_show,
-                  iio_bfin_tmr_frequency_store);
+static DEVICE_ATTR_RW(frequency);
 
 static struct attribute *iio_bfin_tmr_trigger_attrs[] = {
        &dev_attr_frequency.attr,
@@ -187,9 +186,9 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        st->irq = platform_get_irq(pdev, 0);
-       if (!st->irq) {
+       if (st->irq < 0) {
                dev_err(&pdev->dev, "No IRQs specified");
-               return -ENODEV;
+               return st->irq;
        }
 
        ret = iio_bfin_tmr_get_number(st->irq);
diff --git a/drivers/staging/ipx/Kconfig b/drivers/staging/ipx/Kconfig
new file mode 100644 (file)
index 0000000..cdff083
--- /dev/null
@@ -0,0 +1,61 @@
+#
+# IPX configuration
+#
+config IPX
+       tristate "The IPX protocol"
+       depends on NET
+       select LLC
+       ---help---
+         This is support for the Novell networking protocol, IPX, commonly
+         used for local networks of Windows machines.  You need it if you
+         want to access Novell NetWare file or print servers using the Linux
+         Novell client ncpfs (available from
+         <ftp://platan.vc.cvut.cz/pub/linux/ncpfs/>) or from
+         within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO,
+         available from <http://www.tldp.org/docs.html#howto>).  In order
+         to do the former, you'll also have to say Y to "NCP file system
+         support", below.
+
+         IPX is similar in scope to IP, while SPX, which runs on top of IPX,
+         is similar to TCP.
+
+         To turn your Linux box into a fully featured NetWare file server and
+         IPX router, say Y here and fetch either lwared from
+         <ftp://ibiblio.org/pub/Linux/system/network/daemons/> or
+         mars_nwe from <ftp://www.compu-art.de/mars_nwe/>. For more
+         information, read the IPX-HOWTO available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         The IPX driver would enlarge your kernel by about 16 KB. To compile
+         this driver as a module, choose M here: the module will be called ipx.
+         Unless you want to integrate your Linux box with a local Novell
+         network, say N.
+
+config IPX_INTERN
+       bool "IPX: Full internal IPX network"
+       depends on IPX
+       ---help---
+         Every IPX network has an address that identifies it. Sometimes it is
+         useful to give an IPX "network" address to your Linux box as well
+         (for example if your box is acting as a file server for different
+         IPX networks: it will then be accessible from everywhere using the
+         same address). The way this is done is to create a virtual internal
+         "network" inside your box and to assign an IPX address to this
+         network. Say Y here if you want to do this; read the IPX-HOWTO at
+         <http://www.tldp.org/docs.html#howto> for details.
+
+         The full internal IPX network enables you to allocate sockets on
+         different virtual nodes of the internal network. This is done by
+         evaluating the field sipx_node of the socket address given to the
+         bind call. So applications should always initialize the node field
+         to 0 when binding a socket on the primary network. In this case the
+         socket is assigned the default node that has been given to the
+         kernel when the internal network was created. By enabling the full
+         internal IPX network the cross-forwarding of packets targeted at
+         'special' sockets to sockets listening on the primary network is
+         disabled. This might break existing applications, especially RIP/SAP
+         daemons. A RIP/SAP daemon that works well with the full internal net
+         can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/>.
+
+         If you don't know what you are doing, say N.
+
diff --git a/drivers/staging/ipx/Makefile b/drivers/staging/ipx/Makefile
new file mode 100644 (file)
index 0000000..440fafa
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the Linux IPX layer.
+#
+
+obj-$(CONFIG_IPX) += ipx.o
+
+ipx-y                  := af_ipx.o ipx_route.o ipx_proc.o pe2.o
+ipx-$(CONFIG_SYSCTL)   += sysctl_net_ipx.o
diff --git a/drivers/staging/ipx/TODO b/drivers/staging/ipx/TODO
new file mode 100644 (file)
index 0000000..80db5d9
--- /dev/null
@@ -0,0 +1,4 @@
+The ipx code will be removed soon from the kernel tree as it is old and
+obsolete and broken.
+
+Don't worry about fixing up anything here, it's not needed.
diff --git a/drivers/staging/ipx/af_ipx.c b/drivers/staging/ipx/af_ipx.c
new file mode 100644 (file)
index 0000000..d21a9d1
--- /dev/null
@@ -0,0 +1,2084 @@
+/*
+ *     Implements an IPX socket layer.
+ *
+ *     This code is derived from work by
+ *             Ross Biro       :       Writing the original IP stack
+ *             Fred Van Kempen :       Tidying up the TCP/IP
+ *
+ *     Many thanks go to Keith Baker, Institute For Industrial Information
+ *     Technology Ltd, Swansea University for allowing me to work on this
+ *     in my own time even though it was in some ways related to commercial
+ *     work I am currently employed to do there.
+ *
+ *     All the material in this file is subject to the Gnu license version 2.
+ *     Neither Alan Cox nor the Swansea University Computer Society admit
+ *     liability nor provide warranty for any of this software. This material
+ *     is provided as is and at no charge.
+ *
+ *     Portions Copyright (c) 2000-2003 Conectiva, Inc. <acme@conectiva.com.br>
+ *     Neither Arnaldo Carvalho de Melo nor Conectiva, Inc. admit liability nor
+ *     provide warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     Portions Copyright (c) 1995 Caldera, Inc. <greg@caldera.com>
+ *     Neither Greg Page nor Caldera, Inc. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     See net/ipx/ChangeLog.
+ */
+
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/init.h>
+#include <linux/ipx.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/uio.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/termios.h>
+
+#include <net/ipx.h>
+#include <net/p8022.h>
+#include <net/psnap.h>
+#include <net/sock.h>
+#include <net/datalink.h>
+#include <net/tcp_states.h>
+#include <net/net_namespace.h>
+
+#include <linux/uaccess.h>
+
+/* Configuration Variables */
+static unsigned char ipxcfg_max_hops = 16;
+static char ipxcfg_auto_select_primary;
+static char ipxcfg_auto_create_interfaces;
+int sysctl_ipx_pprop_broadcasting = 1;
+
+/* Global Variables */
+static struct datalink_proto *p8022_datalink;
+static struct datalink_proto *pEII_datalink;
+static struct datalink_proto *p8023_datalink;
+static struct datalink_proto *pSNAP_datalink;
+
+static const struct proto_ops ipx_dgram_ops;
+
+LIST_HEAD(ipx_interfaces);
+DEFINE_SPINLOCK(ipx_interfaces_lock);
+
+struct ipx_interface *ipx_primary_net;
+struct ipx_interface *ipx_internal_net;
+
+struct ipx_interface *ipx_interfaces_head(void)
+{
+       struct ipx_interface *rc = NULL;
+
+       if (!list_empty(&ipx_interfaces))
+               rc = list_entry(ipx_interfaces.next,
+                               struct ipx_interface, node);
+       return rc;
+}
+
+static void ipxcfg_set_auto_select(char val)
+{
+       ipxcfg_auto_select_primary = val;
+       if (val && !ipx_primary_net)
+               ipx_primary_net = ipx_interfaces_head();
+}
+
+static int ipxcfg_get_config_data(struct ipx_config_data __user *arg)
+{
+       struct ipx_config_data vals;
+
+       vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
+       vals.ipxcfg_auto_select_primary    = ipxcfg_auto_select_primary;
+
+       return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0;
+}
+
+/*
+ * Note: Sockets may not be removed _during_ an interrupt or inet_bh
+ * handler using this technique. They can be added although we do not
+ * use this facility.
+ */
+
+static void ipx_remove_socket(struct sock *sk)
+{
+       /* Determine interface with which socket is associated */
+       struct ipx_interface *intrfc = ipx_sk(sk)->intrfc;
+
+       if (!intrfc)
+               goto out;
+
+       ipxitf_hold(intrfc);
+       spin_lock_bh(&intrfc->if_sklist_lock);
+       sk_del_node_init(sk);
+       spin_unlock_bh(&intrfc->if_sklist_lock);
+       ipxitf_put(intrfc);
+out:
+       return;
+}
+
+static void ipx_destroy_socket(struct sock *sk)
+{
+       ipx_remove_socket(sk);
+       skb_queue_purge(&sk->sk_receive_queue);
+       sk_refcnt_debug_dec(sk);
+}
+
+/*
+ * The following code is used to support IPX Interfaces (IPXITF).  An
+ * IPX interface is defined by a physical device and a frame type.
+ */
+
+/* ipxitf_clear_primary_net has to be called with ipx_interfaces_lock held */
+
+static void ipxitf_clear_primary_net(void)
+{
+       ipx_primary_net = NULL;
+       if (ipxcfg_auto_select_primary)
+               ipx_primary_net = ipx_interfaces_head();
+}
+
+static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
+                                                     __be16 datalink)
+{
+       struct ipx_interface *i;
+
+       list_for_each_entry(i, &ipx_interfaces, node)
+               if (i->if_dev == dev && i->if_dlink_type == datalink)
+                       goto out;
+       i = NULL;
+out:
+       return i;
+}
+
+static struct ipx_interface *ipxitf_find_using_phys(struct net_device *dev,
+                                                   __be16 datalink)
+{
+       struct ipx_interface *i;
+
+       spin_lock_bh(&ipx_interfaces_lock);
+       i = __ipxitf_find_using_phys(dev, datalink);
+       if (i)
+               ipxitf_hold(i);
+       spin_unlock_bh(&ipx_interfaces_lock);
+       return i;
+}
+
+struct ipx_interface *ipxitf_find_using_net(__be32 net)
+{
+       struct ipx_interface *i;
+
+       spin_lock_bh(&ipx_interfaces_lock);
+       if (net) {
+               list_for_each_entry(i, &ipx_interfaces, node)
+                       if (i->if_netnum == net)
+                               goto hold;
+               i = NULL;
+               goto unlock;
+       }
+
+       i = ipx_primary_net;
+       if (i)
+hold:
+               ipxitf_hold(i);
+unlock:
+       spin_unlock_bh(&ipx_interfaces_lock);
+       return i;
+}
+
+/* Sockets are bound to a particular IPX interface. */
+static void ipxitf_insert_socket(struct ipx_interface *intrfc, struct sock *sk)
+{
+       ipxitf_hold(intrfc);
+       spin_lock_bh(&intrfc->if_sklist_lock);
+       ipx_sk(sk)->intrfc = intrfc;
+       sk_add_node(sk, &intrfc->if_sklist);
+       spin_unlock_bh(&intrfc->if_sklist_lock);
+       ipxitf_put(intrfc);
+}
+
+/* caller must hold intrfc->if_sklist_lock */
+static struct sock *__ipxitf_find_socket(struct ipx_interface *intrfc,
+                                        __be16 port)
+{
+       struct sock *s;
+
+       sk_for_each(s, &intrfc->if_sklist)
+               if (ipx_sk(s)->port == port)
+                       goto found;
+       s = NULL;
+found:
+       return s;
+}
+
+/* caller must hold a reference to intrfc */
+static struct sock *ipxitf_find_socket(struct ipx_interface *intrfc,
+                                       __be16 port)
+{
+       struct sock *s;
+
+       spin_lock_bh(&intrfc->if_sklist_lock);
+       s = __ipxitf_find_socket(intrfc, port);
+       if (s)
+               sock_hold(s);
+       spin_unlock_bh(&intrfc->if_sklist_lock);
+
+       return s;
+}
+
+#ifdef CONFIG_IPX_INTERN
+static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc,
+                                               unsigned char *ipx_node,
+                                               __be16 port)
+{
+       struct sock *s;
+
+       ipxitf_hold(intrfc);
+       spin_lock_bh(&intrfc->if_sklist_lock);
+
+       sk_for_each(s, &intrfc->if_sklist) {
+               struct ipx_sock *ipxs = ipx_sk(s);
+
+               if (ipxs->port == port &&
+                   !memcmp(ipx_node, ipxs->node, IPX_NODE_LEN))
+                       goto found;
+       }
+       s = NULL;
+found:
+       spin_unlock_bh(&intrfc->if_sklist_lock);
+       ipxitf_put(intrfc);
+       return s;
+}
+#endif
+
+static void __ipxitf_down(struct ipx_interface *intrfc)
+{
+       struct sock *s;
+       struct hlist_node *t;
+
+       /* Delete all routes associated with this interface */
+       ipxrtr_del_routes(intrfc);
+
+       spin_lock_bh(&intrfc->if_sklist_lock);
+       /* error sockets */
+       sk_for_each_safe(s, t, &intrfc->if_sklist) {
+               struct ipx_sock *ipxs = ipx_sk(s);
+
+               s->sk_err = ENOLINK;
+               s->sk_error_report(s);
+               ipxs->intrfc = NULL;
+               ipxs->port   = 0;
+               sock_set_flag(s, SOCK_ZAPPED); /* Indicates it is no longer bound */
+               sk_del_node_init(s);
+       }
+       INIT_HLIST_HEAD(&intrfc->if_sklist);
+       spin_unlock_bh(&intrfc->if_sklist_lock);
+
+       /* remove this interface from list */
+       list_del(&intrfc->node);
+
+       /* remove this interface from *special* networks */
+       if (intrfc == ipx_primary_net)
+               ipxitf_clear_primary_net();
+       if (intrfc == ipx_internal_net)
+               ipx_internal_net = NULL;
+
+       if (intrfc->if_dev)
+               dev_put(intrfc->if_dev);
+       kfree(intrfc);
+}
+
+void ipxitf_down(struct ipx_interface *intrfc)
+{
+       spin_lock_bh(&ipx_interfaces_lock);
+       __ipxitf_down(intrfc);
+       spin_unlock_bh(&ipx_interfaces_lock);
+}
+
+static void __ipxitf_put(struct ipx_interface *intrfc)
+{
+       if (refcount_dec_and_test(&intrfc->refcnt))
+               __ipxitf_down(intrfc);
+}
+
+static int ipxitf_device_event(struct notifier_block *notifier,
+                               unsigned long event, void *ptr)
+{
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct ipx_interface *i, *tmp;
+
+       if (!net_eq(dev_net(dev), &init_net))
+               return NOTIFY_DONE;
+
+       if (event != NETDEV_DOWN && event != NETDEV_UP)
+               goto out;
+
+       spin_lock_bh(&ipx_interfaces_lock);
+       list_for_each_entry_safe(i, tmp, &ipx_interfaces, node)
+               if (i->if_dev == dev) {
+                       if (event == NETDEV_UP)
+                               ipxitf_hold(i);
+                       else
+                               __ipxitf_put(i);
+               }
+       spin_unlock_bh(&ipx_interfaces_lock);
+out:
+       return NOTIFY_DONE;
+}
+
+
+static __exit void ipxitf_cleanup(void)
+{
+       struct ipx_interface *i, *tmp;
+
+       spin_lock_bh(&ipx_interfaces_lock);
+       list_for_each_entry_safe(i, tmp, &ipx_interfaces, node)
+               __ipxitf_put(i);
+       spin_unlock_bh(&ipx_interfaces_lock);
+}
+
+static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
+{
+       if (sock_queue_rcv_skb(sock, skb) < 0)
+               kfree_skb(skb);
+}
+
+/*
+ * On input skb->sk is NULL. Nobody is charged for the memory.
+ */
+
+/* caller must hold a reference to intrfc */
+
+#ifdef CONFIG_IPX_INTERN
+static int ipxitf_demux_socket(struct ipx_interface *intrfc,
+                              struct sk_buff *skb, int copy)
+{
+       struct ipxhdr *ipx = ipx_hdr(skb);
+       int is_broadcast = !memcmp(ipx->ipx_dest.node, ipx_broadcast_node,
+                                  IPX_NODE_LEN);
+       struct sock *s;
+       int rc;
+
+       spin_lock_bh(&intrfc->if_sklist_lock);
+
+       sk_for_each(s, &intrfc->if_sklist) {
+               struct ipx_sock *ipxs = ipx_sk(s);
+
+               if (ipxs->port == ipx->ipx_dest.sock &&
+                   (is_broadcast || !memcmp(ipx->ipx_dest.node,
+                                            ipxs->node, IPX_NODE_LEN))) {
+                       /* We found a socket to which to send */
+                       struct sk_buff *skb1;
+
+                       if (copy) {
+                               skb1 = skb_clone(skb, GFP_ATOMIC);
+                               rc = -ENOMEM;
+                               if (!skb1)
+                                       goto out;
+                       } else {
+                               skb1 = skb;
+                               copy = 1; /* skb may only be used once */
+                       }
+                       ipxitf_def_skb_handler(s, skb1);
+
+                       /* On an external interface, one socket can listen */
+                       if (intrfc != ipx_internal_net)
+                               break;
+               }
+       }
+
+       /* skb was solely for us, and we did not make a copy, so free it. */
+       if (!copy)
+               kfree_skb(skb);
+
+       rc = 0;
+out:
+       spin_unlock_bh(&intrfc->if_sklist_lock);
+       return rc;
+}
+#else
+static struct sock *ncp_connection_hack(struct ipx_interface *intrfc,
+                                       struct ipxhdr *ipx)
+{
+       /* The packet's target is a NCP connection handler. We want to hand it
+        * to the correct socket directly within the kernel, so that the
+        * mars_nwe packet distribution process does not have to do it. Here we
+        * only care about NCP and BURST packets.
+        *
+        * You might call this a hack, but believe me, you do not want a
+        * complete NCP layer in the kernel, and this is VERY fast as well. */
+       struct sock *sk = NULL;
+       int connection = 0;
+       u8 *ncphdr = (u8 *)(ipx + 1);
+
+       if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */
+               connection = (((int) *(ncphdr + 5)) << 8) | (int) *(ncphdr + 3);
+       else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77) /* BURST packet */
+               connection = (((int) *(ncphdr + 9)) << 8) | (int) *(ncphdr + 8);
+
+       if (connection) {
+               /* Now we have to look for a special NCP connection handling
+                * socket. Only these sockets have ipx_ncp_conn != 0, set by
+                * SIOCIPXNCPCONN. */
+               spin_lock_bh(&intrfc->if_sklist_lock);
+               sk_for_each(sk, &intrfc->if_sklist)
+                       if (ipx_sk(sk)->ipx_ncp_conn == connection) {
+                               sock_hold(sk);
+                               goto found;
+                       }
+               sk = NULL;
+       found:
+               spin_unlock_bh(&intrfc->if_sklist_lock);
+       }
+       return sk;
+}
+
+static int ipxitf_demux_socket(struct ipx_interface *intrfc,
+                              struct sk_buff *skb, int copy)
+{
+       struct ipxhdr *ipx = ipx_hdr(skb);
+       struct sock *sock1 = NULL, *sock2 = NULL;
+       struct sk_buff *skb1 = NULL, *skb2 = NULL;
+       int rc;
+
+       if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451)
+               sock1 = ncp_connection_hack(intrfc, ipx);
+       if (!sock1)
+               /* No special socket found, forward the packet the normal way */
+               sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
+
+       /*
+        * We need to check if there is a primary net and if
+        * this is addressed to one of the *SPECIAL* sockets because
+        * these need to be propagated to the primary net.
+        * The *SPECIAL* socket list contains: 0x452(SAP), 0x453(RIP) and
+        * 0x456(Diagnostic).
+        */
+
+       if (ipx_primary_net && intrfc != ipx_primary_net) {
+               const int dsock = ntohs(ipx->ipx_dest.sock);
+
+               if (dsock == 0x452 || dsock == 0x453 || dsock == 0x456)
+                       /* The appropriate thing to do here is to dup the
+                        * packet and route to the primary net interface via
+                        * ipxitf_send; however, we'll cheat and just demux it
+                        * here. */
+                       sock2 = ipxitf_find_socket(ipx_primary_net,
+                                                       ipx->ipx_dest.sock);
+       }
+
+       /*
+        * If there is nothing to do return. The kfree will cancel any charging.
+        */
+       rc = 0;
+       if (!sock1 && !sock2) {
+               if (!copy)
+                       kfree_skb(skb);
+               goto out;
+       }
+
+       /*
+        * This next segment of code is a little awkward, but it sets it up
+        * so that the appropriate number of copies of the SKB are made and
+        * that skb1 and skb2 point to it (them) so that it (they) can be
+        * demuxed to sock1 and/or sock2.  If we are unable to make enough
+        * copies, we do as much as is possible.
+        */
+
+       if (copy)
+               skb1 = skb_clone(skb, GFP_ATOMIC);
+       else
+               skb1 = skb;
+
+       rc = -ENOMEM;
+       if (!skb1)
+               goto out_put;
+
+       /* Do we need 2 SKBs? */
+       if (sock1 && sock2)
+               skb2 = skb_clone(skb1, GFP_ATOMIC);
+       else
+               skb2 = skb1;
+
+       if (sock1)
+               ipxitf_def_skb_handler(sock1, skb1);
+
+       if (!skb2)
+               goto out_put;
+
+       if (sock2)
+               ipxitf_def_skb_handler(sock2, skb2);
+
+       rc = 0;
+out_put:
+       if (sock1)
+               sock_put(sock1);
+       if (sock2)
+               sock_put(sock2);
+out:
+       return rc;
+}
+#endif /* CONFIG_IPX_INTERN */
+
+static struct sk_buff *ipxitf_adjust_skbuff(struct ipx_interface *intrfc,
+                                           struct sk_buff *skb)
+{
+       struct sk_buff *skb2;
+       int in_offset = (unsigned char *)ipx_hdr(skb) - skb->head;
+       int out_offset = intrfc->if_ipx_offset;
+       int len;
+
+       /* Hopefully, most cases */
+       if (in_offset >= out_offset)
+               return skb;
+
+       /* Need new SKB */
+       len  = skb->len + out_offset;
+       skb2 = alloc_skb(len, GFP_ATOMIC);
+       if (skb2) {
+               skb_reserve(skb2, out_offset);
+               skb_reset_network_header(skb2);
+               skb_reset_transport_header(skb2);
+               skb_put(skb2, skb->len);
+               memcpy(ipx_hdr(skb2), ipx_hdr(skb), skb->len);
+               memcpy(skb2->cb, skb->cb, sizeof(skb->cb));
+       }
+       kfree_skb(skb);
+       return skb2;
+}
+
+/* caller must hold a reference to intrfc and the skb has to be unshared */
+int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node)
+{
+       struct ipxhdr *ipx = ipx_hdr(skb);
+       struct net_device *dev = intrfc->if_dev;
+       struct datalink_proto *dl = intrfc->if_dlink;
+       char dest_node[IPX_NODE_LEN];
+       int send_to_wire = 1;
+       int addr_len;
+
+       ipx->ipx_tctrl = IPX_SKB_CB(skb)->ipx_tctrl;
+       ipx->ipx_dest.net = IPX_SKB_CB(skb)->ipx_dest_net;
+       ipx->ipx_source.net = IPX_SKB_CB(skb)->ipx_source_net;
+
+       /* see if we need to include the netnum in the route list */
+       if (IPX_SKB_CB(skb)->last_hop.index >= 0) {
+               __be32 *last_hop = (__be32 *)(((u8 *) skb->data) +
+                               sizeof(struct ipxhdr) +
+                               IPX_SKB_CB(skb)->last_hop.index *
+                               sizeof(__be32));
+               *last_hop = IPX_SKB_CB(skb)->last_hop.netnum;
+               IPX_SKB_CB(skb)->last_hop.index = -1;
+       }
+
+       /*
+        * We need to know how many skbuffs it will take to send out this
+        * packet to avoid unnecessary copies.
+        */
+
+       if (!dl || !dev || dev->flags & IFF_LOOPBACK)
+               send_to_wire = 0;       /* No non looped */
+
+       /*
+        * See if this should be demuxed to sockets on this interface
+        *
+        * We want to ensure the original was eaten or that we only use
+        * up clones.
+        */
+
+       if (ipx->ipx_dest.net == intrfc->if_netnum) {
+               /*
+                * To our own node, loop and free the original.
+                * The internal net will receive on all node address.
+                */
+               if (intrfc == ipx_internal_net ||
+                   !memcmp(intrfc->if_node, node, IPX_NODE_LEN)) {
+                       /* Don't charge sender */
+                       skb_orphan(skb);
+
+                       /* Will charge receiver */
+                       return ipxitf_demux_socket(intrfc, skb, 0);
+               }
+
+               /* Broadcast, loop and possibly keep to send on. */
+               if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN)) {
+                       if (!send_to_wire)
+                               skb_orphan(skb);
+                       ipxitf_demux_socket(intrfc, skb, send_to_wire);
+                       if (!send_to_wire)
+                               goto out;
+               }
+       }
+
+       /*
+        * If the originating net is not equal to our net; this is routed
+        * We are still charging the sender. Which is right - the driver
+        * free will handle this fairly.
+        */
+       if (ipx->ipx_source.net != intrfc->if_netnum) {
+               /*
+                * Unshare the buffer before modifying the count in
+                * case it's a flood or tcpdump
+                */
+               skb = skb_unshare(skb, GFP_ATOMIC);
+               if (!skb)
+                       goto out;
+               if (++ipx->ipx_tctrl > ipxcfg_max_hops)
+                       send_to_wire = 0;
+       }
+
+       if (!send_to_wire) {
+               kfree_skb(skb);
+               goto out;
+       }
+
+       /* Determine the appropriate hardware address */
+       addr_len = dev->addr_len;
+       if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN))
+               memcpy(dest_node, dev->broadcast, addr_len);
+       else
+               memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len);
+
+       /* Make any compensation for differing physical/data link size */
+       skb = ipxitf_adjust_skbuff(intrfc, skb);
+       if (!skb)
+               goto out;
+
+       /* set up data link and physical headers */
+       skb->dev        = dev;
+       skb->protocol   = htons(ETH_P_IPX);
+
+       /* Send it out */
+       dl->request(dl, skb, dest_node);
+out:
+       return 0;
+}
+
+static int ipxitf_add_local_route(struct ipx_interface *intrfc)
+{
+       return ipxrtr_add_route(intrfc->if_netnum, intrfc, NULL);
+}
+
+static void ipxitf_discover_netnum(struct ipx_interface *intrfc,
+                                  struct sk_buff *skb);
+static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb);
+
+static int ipxitf_rcv(struct ipx_interface *intrfc, struct sk_buff *skb)
+{
+       struct ipxhdr *ipx = ipx_hdr(skb);
+       int rc = 0;
+
+       ipxitf_hold(intrfc);
+
+       /* See if we should update our network number */
+       if (!intrfc->if_netnum) /* net number of intrfc not known yet */
+               ipxitf_discover_netnum(intrfc, skb);
+
+       IPX_SKB_CB(skb)->last_hop.index = -1;
+       if (ipx->ipx_type == IPX_TYPE_PPROP) {
+               rc = ipxitf_pprop(intrfc, skb);
+               if (rc)
+                       goto out_free_skb;
+       }
+
+       /* local processing follows */
+       if (!IPX_SKB_CB(skb)->ipx_dest_net)
+               IPX_SKB_CB(skb)->ipx_dest_net = intrfc->if_netnum;
+       if (!IPX_SKB_CB(skb)->ipx_source_net)
+               IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum;
+
+       /* it doesn't make sense to route a pprop packet, there's no meaning
+        * in the ipx_dest_net for such packets */
+       if (ipx->ipx_type != IPX_TYPE_PPROP &&
+           intrfc->if_netnum != IPX_SKB_CB(skb)->ipx_dest_net) {
+               /* We only route point-to-point packets. */
+               if (skb->pkt_type == PACKET_HOST) {
+                       skb = skb_unshare(skb, GFP_ATOMIC);
+                       if (skb)
+                               rc = ipxrtr_route_skb(skb);
+                       goto out_intrfc;
+               }
+
+               goto out_free_skb;
+       }
+
+       /* see if we should keep it */
+       if (!memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) ||
+           !memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN)) {
+               rc = ipxitf_demux_socket(intrfc, skb, 0);
+               goto out_intrfc;
+       }
+
+       /* we couldn't pawn it off so unload it */
+out_free_skb:
+       kfree_skb(skb);
+out_intrfc:
+       ipxitf_put(intrfc);
+       return rc;
+}
+
+static void ipxitf_discover_netnum(struct ipx_interface *intrfc,
+                                  struct sk_buff *skb)
+{
+       const struct ipx_cb *cb = IPX_SKB_CB(skb);
+
+       /* see if this is an intra packet: source_net == dest_net */
+       if (cb->ipx_source_net == cb->ipx_dest_net && cb->ipx_source_net) {
+               struct ipx_interface *i =
+                               ipxitf_find_using_net(cb->ipx_source_net);
+               /* NB: NetWare servers lie about their hop count so we
+                * dropped the test based on it. This is the best way
+                * to determine this is a 0 hop count packet. */
+               if (!i) {
+                       intrfc->if_netnum = cb->ipx_source_net;
+                       ipxitf_add_local_route(intrfc);
+               } else {
+                       printk(KERN_WARNING "IPX: Network number collision "
+                               "%lx\n        %s %s and %s %s\n",
+                               (unsigned long) ntohl(cb->ipx_source_net),
+                               ipx_device_name(i),
+                               ipx_frame_name(i->if_dlink_type),
+                               ipx_device_name(intrfc),
+                               ipx_frame_name(intrfc->if_dlink_type));
+                       ipxitf_put(i);
+               }
+       }
+}
+
+/**
+ * ipxitf_pprop - Process packet propagation IPX packet type 0x14, used for
+ *               NetBIOS broadcasts
+ * @intrfc: IPX interface receiving this packet
+ * @skb: Received packet
+ *
+ * Checks if packet is valid: if its more than %IPX_MAX_PPROP_HOPS hops or if it
+ * is smaller than a IPX header + the room for %IPX_MAX_PPROP_HOPS hops we drop
+ * it, not even processing it locally, if it has exact %IPX_MAX_PPROP_HOPS we
+ * don't broadcast it, but process it locally. See chapter 5 of Novell's "IPX
+ * RIP and SAP Router Specification", Part Number 107-000029-001.
+ *
+ * If it is valid, check if we have pprop broadcasting enabled by the user,
+ * if not, just return zero for local processing.
+ *
+ * If it is enabled check the packet and don't broadcast it if we have already
+ * seen this packet.
+ *
+ * Broadcast: send it to the interfaces that aren't on the packet visited nets
+ * array, just after the IPX header.
+ *
+ * Returns -EINVAL for invalid packets, so that the calling function drops
+ * the packet without local processing. 0 if packet is to be locally processed.
+ */
+static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
+{
+       struct ipxhdr *ipx = ipx_hdr(skb);
+       int i, rc = -EINVAL;
+       struct ipx_interface *ifcs;
+       char *c;
+       __be32 *l;
+
+       /* Illegal packet - too many hops or too short */
+       /* We decide to throw it away: no broadcasting, no local processing.
+        * NetBIOS unaware implementations route them as normal packets -
+        * tctrl <= 15, any data payload... */
+       if (IPX_SKB_CB(skb)->ipx_tctrl > IPX_MAX_PPROP_HOPS ||
+           ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr) +
+                                       IPX_MAX_PPROP_HOPS * sizeof(u32))
+               goto out;
+       /* are we broadcasting this damn thing? */
+       rc = 0;
+       if (!sysctl_ipx_pprop_broadcasting)
+               goto out;
+       /* We do broadcast packet on the IPX_MAX_PPROP_HOPS hop, but we
+        * process it locally. All previous hops broadcasted it, and process it
+        * locally. */
+       if (IPX_SKB_CB(skb)->ipx_tctrl == IPX_MAX_PPROP_HOPS)
+               goto out;
+
+       c = ((u8 *) ipx) + sizeof(struct ipxhdr);
+       l = (__be32 *) c;
+
+       /* Don't broadcast packet if already seen this net */
+       for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++)
+               if (*l++ == intrfc->if_netnum)
+                       goto out;
+
+       /* < IPX_MAX_PPROP_HOPS hops && input interface not in list. Save the
+        * position where we will insert recvd netnum into list, later on,
+        * in ipxitf_send */
+       IPX_SKB_CB(skb)->last_hop.index = i;
+       IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum;
+       /* xmit on all other interfaces... */
+       spin_lock_bh(&ipx_interfaces_lock);
+       list_for_each_entry(ifcs, &ipx_interfaces, node) {
+               /* Except unconfigured interfaces */
+               if (!ifcs->if_netnum)
+                       continue;
+
+               /* That aren't in the list */
+               if (ifcs == intrfc)
+                       continue;
+               l = (__be32 *) c;
+               /* don't consider the last entry in the packet list,
+                * it is our netnum, and it is not there yet */
+               for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++)
+                       if (ifcs->if_netnum == *l++)
+                               break;
+               if (i == IPX_SKB_CB(skb)->ipx_tctrl) {
+                       struct sk_buff *s = skb_copy(skb, GFP_ATOMIC);
+
+                       if (s) {
+                               IPX_SKB_CB(s)->ipx_dest_net = ifcs->if_netnum;
+                               ipxrtr_route_skb(s);
+                       }
+               }
+       }
+       spin_unlock_bh(&ipx_interfaces_lock);
+out:
+       return rc;
+}
+
+static void ipxitf_insert(struct ipx_interface *intrfc)
+{
+       spin_lock_bh(&ipx_interfaces_lock);
+       list_add_tail(&intrfc->node, &ipx_interfaces);
+       spin_unlock_bh(&ipx_interfaces_lock);
+
+       if (ipxcfg_auto_select_primary && !ipx_primary_net)
+               ipx_primary_net = intrfc;
+}
+
+static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __be32 netnum,
+                                         __be16 dlink_type,
+                                         struct datalink_proto *dlink,
+                                         unsigned char internal,
+                                         int ipx_offset)
+{
+       struct ipx_interface *intrfc = kmalloc(sizeof(*intrfc), GFP_ATOMIC);
+
+       if (intrfc) {
+               intrfc->if_dev          = dev;
+               intrfc->if_netnum       = netnum;
+               intrfc->if_dlink_type   = dlink_type;
+               intrfc->if_dlink        = dlink;
+               intrfc->if_internal     = internal;
+               intrfc->if_ipx_offset   = ipx_offset;
+               intrfc->if_sknum        = IPX_MIN_EPHEMERAL_SOCKET;
+               INIT_HLIST_HEAD(&intrfc->if_sklist);
+               refcount_set(&intrfc->refcnt, 1);
+               spin_lock_init(&intrfc->if_sklist_lock);
+       }
+
+       return intrfc;
+}
+
+static int ipxitf_create_internal(struct ipx_interface_definition *idef)
+{
+       struct ipx_interface *intrfc;
+       int rc = -EEXIST;
+
+       /* Only one primary network allowed */
+       if (ipx_primary_net)
+               goto out;
+
+       /* Must have a valid network number */
+       rc = -EADDRNOTAVAIL;
+       if (!idef->ipx_network)
+               goto out;
+       intrfc = ipxitf_find_using_net(idef->ipx_network);
+       rc = -EADDRINUSE;
+       if (intrfc) {
+               ipxitf_put(intrfc);
+               goto out;
+       }
+       intrfc = ipxitf_alloc(NULL, idef->ipx_network, 0, NULL, 1, 0);
+       rc = -EAGAIN;
+       if (!intrfc)
+               goto out;
+       memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN);
+       ipx_internal_net = ipx_primary_net = intrfc;
+       ipxitf_hold(intrfc);
+       ipxitf_insert(intrfc);
+
+       rc = ipxitf_add_local_route(intrfc);
+       ipxitf_put(intrfc);
+out:
+       return rc;
+}
+
+static __be16 ipx_map_frame_type(unsigned char type)
+{
+       __be16 rc = 0;
+
+       switch (type) {
+       case IPX_FRAME_ETHERII: rc = htons(ETH_P_IPX);          break;
+       case IPX_FRAME_8022:    rc = htons(ETH_P_802_2);        break;
+       case IPX_FRAME_SNAP:    rc = htons(ETH_P_SNAP);         break;
+       case IPX_FRAME_8023:    rc = htons(ETH_P_802_3);        break;
+       }
+
+       return rc;
+}
+
+static int ipxitf_create(struct ipx_interface_definition *idef)
+{
+       struct net_device *dev;
+       __be16 dlink_type = 0;
+       struct datalink_proto *datalink = NULL;
+       struct ipx_interface *intrfc;
+       int rc;
+
+       if (idef->ipx_special == IPX_INTERNAL) {
+               rc = ipxitf_create_internal(idef);
+               goto out;
+       }
+
+       rc = -EEXIST;
+       if (idef->ipx_special == IPX_PRIMARY && ipx_primary_net)
+               goto out;
+
+       intrfc = ipxitf_find_using_net(idef->ipx_network);
+       rc = -EADDRINUSE;
+       if (idef->ipx_network && intrfc) {
+               ipxitf_put(intrfc);
+               goto out;
+       }
+
+       if (intrfc)
+               ipxitf_put(intrfc);
+
+       dev = dev_get_by_name(&init_net, idef->ipx_device);
+       rc = -ENODEV;
+       if (!dev)
+               goto out;
+
+       switch (idef->ipx_dlink_type) {
+       case IPX_FRAME_8022:
+               dlink_type      = htons(ETH_P_802_2);
+               datalink        = p8022_datalink;
+               break;
+       case IPX_FRAME_ETHERII:
+               if (dev->type != ARPHRD_IEEE802) {
+                       dlink_type      = htons(ETH_P_IPX);
+                       datalink        = pEII_datalink;
+                       break;
+               }
+               /* fall through */
+       case IPX_FRAME_SNAP:
+               dlink_type      = htons(ETH_P_SNAP);
+               datalink        = pSNAP_datalink;
+               break;
+       case IPX_FRAME_8023:
+               dlink_type      = htons(ETH_P_802_3);
+               datalink        = p8023_datalink;
+               break;
+       case IPX_FRAME_NONE:
+       default:
+               rc = -EPROTONOSUPPORT;
+               goto out_dev;
+       }
+
+       rc = -ENETDOWN;
+       if (!(dev->flags & IFF_UP))
+               goto out_dev;
+
+       /* Check addresses are suitable */
+       rc = -EINVAL;
+       if (dev->addr_len > IPX_NODE_LEN)
+               goto out_dev;
+
+       intrfc = ipxitf_find_using_phys(dev, dlink_type);
+       if (!intrfc) {
+               /* Ok now create */
+               intrfc = ipxitf_alloc(dev, idef->ipx_network, dlink_type,
+                                     datalink, 0, dev->hard_header_len +
+                                       datalink->header_length);
+               rc = -EAGAIN;
+               if (!intrfc)
+                       goto out_dev;
+               /* Setup primary if necessary */
+               if (idef->ipx_special == IPX_PRIMARY)
+                       ipx_primary_net = intrfc;
+               if (!memcmp(idef->ipx_node, "\000\000\000\000\000\000",
+                           IPX_NODE_LEN)) {
+                       memset(intrfc->if_node, 0, IPX_NODE_LEN);
+                       memcpy(intrfc->if_node + IPX_NODE_LEN - dev->addr_len,
+                               dev->dev_addr, dev->addr_len);
+               } else
+                       memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN);
+               ipxitf_hold(intrfc);
+               ipxitf_insert(intrfc);
+       }
+
+
+       /* If the network number is known, add a route */
+       rc = 0;
+       if (!intrfc->if_netnum)
+               goto out_intrfc;
+
+       rc = ipxitf_add_local_route(intrfc);
+out_intrfc:
+       ipxitf_put(intrfc);
+       goto out;
+out_dev:
+       dev_put(dev);
+out:
+       return rc;
+}
+
+static int ipxitf_delete(struct ipx_interface_definition *idef)
+{
+       struct net_device *dev = NULL;
+       __be16 dlink_type = 0;
+       struct ipx_interface *intrfc;
+       int rc = 0;
+
+       spin_lock_bh(&ipx_interfaces_lock);
+       if (idef->ipx_special == IPX_INTERNAL) {
+               if (ipx_internal_net) {
+                       __ipxitf_put(ipx_internal_net);
+                       goto out;
+               }
+               rc = -ENOENT;
+               goto out;
+       }
+
+       dlink_type = ipx_map_frame_type(idef->ipx_dlink_type);
+       rc = -EPROTONOSUPPORT;
+       if (!dlink_type)
+               goto out;
+
+       dev = __dev_get_by_name(&init_net, idef->ipx_device);
+       rc = -ENODEV;
+       if (!dev)
+               goto out;
+
+       intrfc = __ipxitf_find_using_phys(dev, dlink_type);
+       rc = -EINVAL;
+       if (!intrfc)
+               goto out;
+       __ipxitf_put(intrfc);
+
+       rc = 0;
+out:
+       spin_unlock_bh(&ipx_interfaces_lock);
+       return rc;
+}
+
+static struct ipx_interface *ipxitf_auto_create(struct net_device *dev,
+                                               __be16 dlink_type)
+{
+       struct ipx_interface *intrfc = NULL;
+       struct datalink_proto *datalink;
+
+       if (!dev)
+               goto out;
+
+       /* Check addresses are suitable */
+       if (dev->addr_len > IPX_NODE_LEN)
+               goto out;
+
+       switch (ntohs(dlink_type)) {
+       case ETH_P_IPX:         datalink = pEII_datalink;       break;
+       case ETH_P_802_2:       datalink = p8022_datalink;      break;
+       case ETH_P_SNAP:        datalink = pSNAP_datalink;      break;
+       case ETH_P_802_3:       datalink = p8023_datalink;      break;
+       default:                goto out;
+       }
+
+       intrfc = ipxitf_alloc(dev, 0, dlink_type, datalink, 0,
+                               dev->hard_header_len + datalink->header_length);
+
+       if (intrfc) {
+               memset(intrfc->if_node, 0, IPX_NODE_LEN);
+               memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
+                       dev->dev_addr, dev->addr_len);
+               spin_lock_init(&intrfc->if_sklist_lock);
+               refcount_set(&intrfc->refcnt, 1);
+               ipxitf_insert(intrfc);
+               dev_hold(dev);
+       }
+
+out:
+       return intrfc;
+}
+
+static int ipxitf_ioctl(unsigned int cmd, void __user *arg)
+{
+       int rc = -EINVAL;
+       struct ifreq ifr;
+       int val;
+
+       switch (cmd) {
+       case SIOCSIFADDR: {
+               struct sockaddr_ipx *sipx;
+               struct ipx_interface_definition f;
+
+               rc = -EFAULT;
+               if (copy_from_user(&ifr, arg, sizeof(ifr)))
+                       break;
+               sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
+               rc = -EINVAL;
+               if (sipx->sipx_family != AF_IPX)
+                       break;
+               f.ipx_network = sipx->sipx_network;
+               memcpy(f.ipx_device, ifr.ifr_name,
+                       sizeof(f.ipx_device));
+               memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN);
+               f.ipx_dlink_type = sipx->sipx_type;
+               f.ipx_special = sipx->sipx_special;
+
+               if (sipx->sipx_action == IPX_DLTITF)
+                       rc = ipxitf_delete(&f);
+               else
+                       rc = ipxitf_create(&f);
+               break;
+       }
+       case SIOCGIFADDR: {
+               struct sockaddr_ipx *sipx;
+               struct ipx_interface *ipxif;
+               struct net_device *dev;
+
+               rc = -EFAULT;
+               if (copy_from_user(&ifr, arg, sizeof(ifr)))
+                       break;
+               sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
+               dev  = __dev_get_by_name(&init_net, ifr.ifr_name);
+               rc   = -ENODEV;
+               if (!dev)
+                       break;
+               ipxif = ipxitf_find_using_phys(dev,
+                                          ipx_map_frame_type(sipx->sipx_type));
+               rc = -EADDRNOTAVAIL;
+               if (!ipxif)
+                       break;
+
+               sipx->sipx_family       = AF_IPX;
+               sipx->sipx_network      = ipxif->if_netnum;
+               memcpy(sipx->sipx_node, ipxif->if_node,
+                       sizeof(sipx->sipx_node));
+               rc = 0;
+               if (copy_to_user(arg, &ifr, sizeof(ifr)))
+                       rc = -EFAULT;
+               ipxitf_put(ipxif);
+               break;
+       }
+       case SIOCAIPXITFCRT:
+               rc = -EFAULT;
+               if (get_user(val, (unsigned char __user *) arg))
+                       break;
+               rc = 0;
+               ipxcfg_auto_create_interfaces = val;
+               break;
+       case SIOCAIPXPRISLT:
+               rc = -EFAULT;
+               if (get_user(val, (unsigned char __user *) arg))
+                       break;
+               rc = 0;
+               ipxcfg_set_auto_select(val);
+               break;
+       }
+
+       return rc;
+}
+
+/*
+ *     Checksum routine for IPX
+ */
+
+/* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
+/* This functions should *not* mess with packet contents */
+
+__be16 ipx_cksum(struct ipxhdr *packet, int length)
+{
+       /*
+        *      NOTE: sum is a net byte order quantity, which optimizes the
+        *      loop. This only works on big and little endian machines. (I
+        *      don't know of a machine that isn't.)
+        */
+       /* handle the first 3 words separately; checksum should be skipped
+        * and ipx_tctrl masked out */
+       __u16 *p = (__u16 *)packet;
+       __u32 sum = p[1] + (p[2] & (__force u16)htons(0x00ff));
+       __u32 i = (length >> 1) - 3; /* Number of remaining complete words */
+
+       /* Loop through them */
+       p += 3;
+       while (i--)
+               sum += *p++;
+
+       /* Add on the last part word if it exists */
+       if (packet->ipx_pktsize & htons(1))
+               sum += (__force u16)htons(0xff00) & *p;
+
+       /* Do final fixup */
+       sum = (sum & 0xffff) + (sum >> 16);
+
+       /* It's a pity there's no concept of carry in C */
+       if (sum >= 0x10000)
+               sum++;
+
+       /*
+        * Leave 0 alone; we don't want 0xffff here.  Note that we can't get
+        * here with 0x10000, so this check is the same as ((__u16)sum)
+        */
+       if (sum)
+               sum = ~sum;
+
+       return (__force __be16)sum;
+}
+
+const char *ipx_frame_name(__be16 frame)
+{
+       char* rc = "None";
+
+       switch (ntohs(frame)) {
+       case ETH_P_IPX:         rc = "EtherII"; break;
+       case ETH_P_802_2:       rc = "802.2";   break;
+       case ETH_P_SNAP:        rc = "SNAP";    break;
+       case ETH_P_802_3:       rc = "802.3";   break;
+       }
+
+       return rc;
+}
+
+const char *ipx_device_name(struct ipx_interface *intrfc)
+{
+       return intrfc->if_internal ? "Internal" :
+               intrfc->if_dev ? intrfc->if_dev->name : "Unknown";
+}
+
+/* Handling for system calls applied via the various interfaces to an IPX
+ * socket object. */
+
+static int ipx_setsockopt(struct socket *sock, int level, int optname,
+                         char __user *optval, unsigned int optlen)
+{
+       struct sock *sk = sock->sk;
+       int opt;
+       int rc = -EINVAL;
+
+       lock_sock(sk);
+       if (optlen != sizeof(int))
+               goto out;
+
+       rc = -EFAULT;
+       if (get_user(opt, (unsigned int __user *)optval))
+               goto out;
+
+       rc = -ENOPROTOOPT;
+       if (!(level == SOL_IPX && optname == IPX_TYPE))
+               goto out;
+
+       ipx_sk(sk)->type = opt;
+       rc = 0;
+out:
+       release_sock(sk);
+       return rc;
+}
+
+static int ipx_getsockopt(struct socket *sock, int level, int optname,
+       char __user *optval, int __user *optlen)
+{
+       struct sock *sk = sock->sk;
+       int val = 0;
+       int len;
+       int rc = -ENOPROTOOPT;
+
+       lock_sock(sk);
+       if (!(level == SOL_IPX && optname == IPX_TYPE))
+               goto out;
+
+       val = ipx_sk(sk)->type;
+
+       rc = -EFAULT;
+       if (get_user(len, optlen))
+               goto out;
+
+       len = min_t(unsigned int, len, sizeof(int));
+       rc = -EINVAL;
+       if(len < 0)
+               goto out;
+
+       rc = -EFAULT;
+       if (put_user(len, optlen) || copy_to_user(optval, &val, len))
+               goto out;
+
+       rc = 0;
+out:
+       release_sock(sk);
+       return rc;
+}
+
+static struct proto ipx_proto = {
+       .name     = "IPX",
+       .owner    = THIS_MODULE,
+       .obj_size = sizeof(struct ipx_sock),
+};
+
+static int ipx_create(struct net *net, struct socket *sock, int protocol,
+                     int kern)
+{
+       int rc = -ESOCKTNOSUPPORT;
+       struct sock *sk;
+
+       if (!net_eq(net, &init_net))
+               return -EAFNOSUPPORT;
+
+       /*
+        * SPX support is not anymore in the kernel sources. If you want to
+        * ressurrect it, completing it and making it understand shared skbs,
+        * be fully multithreaded, etc, grab the sources in an early 2.5 kernel
+        * tree.
+        */
+       if (sock->type != SOCK_DGRAM)
+               goto out;
+
+       rc = -ENOMEM;
+       sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto, kern);
+       if (!sk)
+               goto out;
+
+       sk_refcnt_debug_inc(sk);
+       sock_init_data(sock, sk);
+       sk->sk_no_check_tx = 1;         /* Checksum off by default */
+       sock->ops = &ipx_dgram_ops;
+       rc = 0;
+out:
+       return rc;
+}
+
+static int ipx_release(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+
+       if (!sk)
+               goto out;
+
+       lock_sock(sk);
+       sk->sk_shutdown = SHUTDOWN_MASK;
+       if (!sock_flag(sk, SOCK_DEAD))
+               sk->sk_state_change(sk);
+
+       sock_set_flag(sk, SOCK_DEAD);
+       sock->sk = NULL;
+       sk_refcnt_debug_release(sk);
+       ipx_destroy_socket(sk);
+       release_sock(sk);
+       sock_put(sk);
+out:
+       return 0;
+}
+
+/* caller must hold a reference to intrfc */
+
+static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc)
+{
+       unsigned short socketNum = intrfc->if_sknum;
+
+       spin_lock_bh(&intrfc->if_sklist_lock);
+
+       if (socketNum < IPX_MIN_EPHEMERAL_SOCKET)
+               socketNum = IPX_MIN_EPHEMERAL_SOCKET;
+
+       while (__ipxitf_find_socket(intrfc, htons(socketNum)))
+               if (socketNum > IPX_MAX_EPHEMERAL_SOCKET)
+                       socketNum = IPX_MIN_EPHEMERAL_SOCKET;
+               else
+                       socketNum++;
+
+       spin_unlock_bh(&intrfc->if_sklist_lock);
+       intrfc->if_sknum = socketNum;
+
+       return htons(socketNum);
+}
+
+static int __ipx_bind(struct socket *sock,
+                       struct sockaddr *uaddr, int addr_len)
+{
+       struct sock *sk = sock->sk;
+       struct ipx_sock *ipxs = ipx_sk(sk);
+       struct ipx_interface *intrfc;
+       struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr;
+       int rc = -EINVAL;
+
+       if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_ipx))
+               goto out;
+
+       intrfc = ipxitf_find_using_net(addr->sipx_network);
+       rc = -EADDRNOTAVAIL;
+       if (!intrfc)
+               goto out;
+
+       if (!addr->sipx_port) {
+               addr->sipx_port = ipx_first_free_socketnum(intrfc);
+               rc = -EINVAL;
+               if (!addr->sipx_port)
+                       goto out_put;
+       }
+
+       /* protect IPX system stuff like routing/sap */
+       rc = -EACCES;
+       if (ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET &&
+           !capable(CAP_NET_ADMIN))
+               goto out_put;
+
+       ipxs->port = addr->sipx_port;
+
+#ifdef CONFIG_IPX_INTERN
+       if (intrfc == ipx_internal_net) {
+               /* The source address is to be set explicitly if the
+                * socket is to be bound on the internal network. If a
+                * node number 0 was specified, the default is used.
+                */
+
+               rc = -EINVAL;
+               if (!memcmp(addr->sipx_node, ipx_broadcast_node, IPX_NODE_LEN))
+                       goto out_put;
+               if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN))
+                       memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN);
+               else
+                       memcpy(ipxs->node, addr->sipx_node, IPX_NODE_LEN);
+
+               rc = -EADDRINUSE;
+               if (ipxitf_find_internal_socket(intrfc, ipxs->node,
+                                               ipxs->port)) {
+                       SOCK_DEBUG(sk,
+                               "IPX: bind failed because port %X in use.\n",
+                               ntohs(addr->sipx_port));
+                       goto out_put;
+               }
+       } else {
+               /* Source addresses are easy. It must be our
+                * network:node pair for an interface routed to IPX
+                * with the ipx routing ioctl()
+                */
+
+               memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN);
+
+               rc = -EADDRINUSE;
+               if (ipxitf_find_socket(intrfc, addr->sipx_port)) {
+                       SOCK_DEBUG(sk,
+                               "IPX: bind failed because port %X in use.\n",
+                               ntohs(addr->sipx_port));
+                       goto out_put;
+               }
+       }
+
+#else  /* !def CONFIG_IPX_INTERN */
+
+       /* Source addresses are easy. It must be our network:node pair for
+          an interface routed to IPX with the ipx routing ioctl() */
+
+       rc = -EADDRINUSE;
+       if (ipxitf_find_socket(intrfc, addr->sipx_port)) {
+               SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n",
+                               ntohs((int)addr->sipx_port));
+               goto out_put;
+       }
+
+#endif /* CONFIG_IPX_INTERN */
+
+       ipxitf_insert_socket(intrfc, sk);
+       sock_reset_flag(sk, SOCK_ZAPPED);
+
+       rc = 0;
+out_put:
+       ipxitf_put(intrfc);
+out:
+       return rc;
+}
+
+static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+       struct sock *sk = sock->sk;
+       int rc;
+
+       lock_sock(sk);
+       rc = __ipx_bind(sock, uaddr, addr_len);
+       release_sock(sk);
+
+       return rc;
+}
+
+static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
+       int addr_len, int flags)
+{
+       struct sock *sk = sock->sk;
+       struct ipx_sock *ipxs = ipx_sk(sk);
+       struct sockaddr_ipx *addr;
+       int rc = -EINVAL;
+       struct ipx_route *rt;
+
+       sk->sk_state    = TCP_CLOSE;
+       sock->state     = SS_UNCONNECTED;
+
+       lock_sock(sk);
+       if (addr_len != sizeof(*addr))
+               goto out;
+       addr = (struct sockaddr_ipx *)uaddr;
+
+       /* put the autobinding in */
+       if (!ipxs->port) {
+               struct sockaddr_ipx uaddr;
+
+               uaddr.sipx_port         = 0;
+               uaddr.sipx_network      = 0;
+
+#ifdef CONFIG_IPX_INTERN
+               rc = -ENETDOWN;
+               if (!ipxs->intrfc)
+                       goto out; /* Someone zonked the iface */
+               memcpy(uaddr.sipx_node, ipxs->intrfc->if_node,
+                       IPX_NODE_LEN);
+#endif /* CONFIG_IPX_INTERN */
+
+               rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
+                             sizeof(struct sockaddr_ipx));
+               if (rc)
+                       goto out;
+       }
+
+       /* We can either connect to primary network or somewhere
+        * we can route to */
+       rt = ipxrtr_lookup(addr->sipx_network);
+       rc = -ENETUNREACH;
+       if (!rt && !(!addr->sipx_network && ipx_primary_net))
+               goto out;
+
+       ipxs->dest_addr.net  = addr->sipx_network;
+       ipxs->dest_addr.sock = addr->sipx_port;
+       memcpy(ipxs->dest_addr.node, addr->sipx_node, IPX_NODE_LEN);
+       ipxs->type = addr->sipx_type;
+
+       if (sock->type == SOCK_DGRAM) {
+               sock->state     = SS_CONNECTED;
+               sk->sk_state    = TCP_ESTABLISHED;
+       }
+
+       if (rt)
+               ipxrtr_put(rt);
+       rc = 0;
+out:
+       release_sock(sk);
+       return rc;
+}
+
+
+static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
+                       int *uaddr_len, int peer)
+{
+       struct ipx_address *addr;
+       struct sockaddr_ipx sipx;
+       struct sock *sk = sock->sk;
+       struct ipx_sock *ipxs = ipx_sk(sk);
+       int rc;
+
+       *uaddr_len = sizeof(struct sockaddr_ipx);
+
+       lock_sock(sk);
+       if (peer) {
+               rc = -ENOTCONN;
+               if (sk->sk_state != TCP_ESTABLISHED)
+                       goto out;
+
+               addr = &ipxs->dest_addr;
+               sipx.sipx_network       = addr->net;
+               sipx.sipx_port          = addr->sock;
+               memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN);
+       } else {
+               if (ipxs->intrfc) {
+                       sipx.sipx_network = ipxs->intrfc->if_netnum;
+#ifdef CONFIG_IPX_INTERN
+                       memcpy(sipx.sipx_node, ipxs->node, IPX_NODE_LEN);
+#else
+                       memcpy(sipx.sipx_node, ipxs->intrfc->if_node,
+                               IPX_NODE_LEN);
+#endif /* CONFIG_IPX_INTERN */
+
+               } else {
+                       sipx.sipx_network = 0;
+                       memset(sipx.sipx_node, '\0', IPX_NODE_LEN);
+               }
+
+               sipx.sipx_port = ipxs->port;
+       }
+
+       sipx.sipx_family = AF_IPX;
+       sipx.sipx_type   = ipxs->type;
+       sipx.sipx_zero   = 0;
+       memcpy(uaddr, &sipx, sizeof(sipx));
+
+       rc = 0;
+out:
+       release_sock(sk);
+       return rc;
+}
+
+static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+{
+       /* NULL here for pt means the packet was looped back */
+       struct ipx_interface *intrfc;
+       struct ipxhdr *ipx;
+       u16 ipx_pktsize;
+       int rc = 0;
+
+       if (!net_eq(dev_net(dev), &init_net))
+               goto drop;
+
+       /* Not ours */
+       if (skb->pkt_type == PACKET_OTHERHOST)
+               goto drop;
+
+       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+               goto out;
+
+       if (!pskb_may_pull(skb, sizeof(struct ipxhdr)))
+               goto drop;
+
+       ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize);
+
+       /* Too small or invalid header? */
+       if (ipx_pktsize < sizeof(struct ipxhdr) ||
+           !pskb_may_pull(skb, ipx_pktsize))
+               goto drop;
+
+       ipx = ipx_hdr(skb);
+       if (ipx->ipx_checksum != IPX_NO_CHECKSUM &&
+          ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))
+               goto drop;
+
+       IPX_SKB_CB(skb)->ipx_tctrl      = ipx->ipx_tctrl;
+       IPX_SKB_CB(skb)->ipx_dest_net   = ipx->ipx_dest.net;
+       IPX_SKB_CB(skb)->ipx_source_net = ipx->ipx_source.net;
+
+       /* Determine what local ipx endpoint this is */
+       intrfc = ipxitf_find_using_phys(dev, pt->type);
+       if (!intrfc) {
+               if (ipxcfg_auto_create_interfaces &&
+                  IPX_SKB_CB(skb)->ipx_dest_net) {
+                       intrfc = ipxitf_auto_create(dev, pt->type);
+                       if (intrfc)
+                               ipxitf_hold(intrfc);
+               }
+
+               if (!intrfc)    /* Not one of ours */
+                               /* or invalid packet for auto creation */
+                       goto drop;
+       }
+
+       rc = ipxitf_rcv(intrfc, skb);
+       ipxitf_put(intrfc);
+       goto out;
+drop:
+       kfree_skb(skb);
+out:
+       return rc;
+}
+
+static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
+{
+       struct sock *sk = sock->sk;
+       struct ipx_sock *ipxs = ipx_sk(sk);
+       DECLARE_SOCKADDR(struct sockaddr_ipx *, usipx, msg->msg_name);
+       struct sockaddr_ipx local_sipx;
+       int rc = -EINVAL;
+       int flags = msg->msg_flags;
+
+       lock_sock(sk);
+       /* Socket gets bound below anyway */
+/*     if (sk->sk_zapped)
+               return -EIO; */ /* Socket not bound */
+       if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
+               goto out;
+
+       /* Max possible packet size limited by 16 bit pktsize in header */
+       if (len >= 65535 - sizeof(struct ipxhdr))
+               goto out;
+
+       if (usipx) {
+               if (!ipxs->port) {
+                       struct sockaddr_ipx uaddr;
+
+                       uaddr.sipx_port         = 0;
+                       uaddr.sipx_network      = 0;
+#ifdef CONFIG_IPX_INTERN
+                       rc = -ENETDOWN;
+                       if (!ipxs->intrfc)
+                               goto out; /* Someone zonked the iface */
+                       memcpy(uaddr.sipx_node, ipxs->intrfc->if_node,
+                               IPX_NODE_LEN);
+#endif
+                       rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
+                                       sizeof(struct sockaddr_ipx));
+                       if (rc)
+                               goto out;
+               }
+
+               rc = -EINVAL;
+               if (msg->msg_namelen < sizeof(*usipx) ||
+                   usipx->sipx_family != AF_IPX)
+                       goto out;
+       } else {
+               rc = -ENOTCONN;
+               if (sk->sk_state != TCP_ESTABLISHED)
+                       goto out;
+
+               usipx = &local_sipx;
+               usipx->sipx_family      = AF_IPX;
+               usipx->sipx_type        = ipxs->type;
+               usipx->sipx_port        = ipxs->dest_addr.sock;
+               usipx->sipx_network     = ipxs->dest_addr.net;
+               memcpy(usipx->sipx_node, ipxs->dest_addr.node, IPX_NODE_LEN);
+       }
+
+       rc = ipxrtr_route_packet(sk, usipx, msg, len, flags & MSG_DONTWAIT);
+       if (rc >= 0)
+               rc = len;
+out:
+       release_sock(sk);
+       return rc;
+}
+
+
+static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
+                      int flags)
+{
+       struct sock *sk = sock->sk;
+       struct ipx_sock *ipxs = ipx_sk(sk);
+       DECLARE_SOCKADDR(struct sockaddr_ipx *, sipx, msg->msg_name);
+       struct ipxhdr *ipx = NULL;
+       struct sk_buff *skb;
+       int copied, rc;
+       bool locked = true;
+
+       lock_sock(sk);
+       /* put the autobinding in */
+       if (!ipxs->port) {
+               struct sockaddr_ipx uaddr;
+
+               uaddr.sipx_port         = 0;
+               uaddr.sipx_network      = 0;
+
+#ifdef CONFIG_IPX_INTERN
+               rc = -ENETDOWN;
+               if (!ipxs->intrfc)
+                       goto out; /* Someone zonked the iface */
+               memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN);
+#endif /* CONFIG_IPX_INTERN */
+
+               rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
+                             sizeof(struct sockaddr_ipx));
+               if (rc)
+                       goto out;
+       }
+
+       rc = -ENOTCONN;
+       if (sock_flag(sk, SOCK_ZAPPED))
+               goto out;
+
+       release_sock(sk);
+       locked = false;
+       skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+                               flags & MSG_DONTWAIT, &rc);
+       if (!skb) {
+               if (rc == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN))
+                       rc = 0;
+               goto out;
+       }
+
+       ipx     = ipx_hdr(skb);
+       copied  = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);
+       if (copied > size) {
+               copied = size;
+               msg->msg_flags |= MSG_TRUNC;
+       }
+
+       rc = skb_copy_datagram_msg(skb, sizeof(struct ipxhdr), msg, copied);
+       if (rc)
+               goto out_free;
+       if (skb->tstamp)
+               sk->sk_stamp = skb->tstamp;
+
+       if (sipx) {
+               sipx->sipx_family       = AF_IPX;
+               sipx->sipx_port         = ipx->ipx_source.sock;
+               memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN);
+               sipx->sipx_network      = IPX_SKB_CB(skb)->ipx_source_net;
+               sipx->sipx_type         = ipx->ipx_type;
+               sipx->sipx_zero         = 0;
+               msg->msg_namelen        = sizeof(*sipx);
+       }
+       rc = copied;
+
+out_free:
+       skb_free_datagram(sk, skb);
+out:
+       if (locked)
+               release_sock(sk);
+       return rc;
+}
+
+
+static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       int rc = 0;
+       long amount = 0;
+       struct sock *sk = sock->sk;
+       void __user *argp = (void __user *)arg;
+
+       lock_sock(sk);
+       switch (cmd) {
+       case TIOCOUTQ:
+               amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
+               if (amount < 0)
+                       amount = 0;
+               rc = put_user(amount, (int __user *)argp);
+               break;
+       case TIOCINQ: {
+               struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
+               /* These two are safe on a single CPU system as only
+                * user tasks fiddle here */
+               if (skb)
+                       amount = skb->len - sizeof(struct ipxhdr);
+               rc = put_user(amount, (int __user *)argp);
+               break;
+       }
+       case SIOCADDRT:
+       case SIOCDELRT:
+               rc = -EPERM;
+               if (capable(CAP_NET_ADMIN))
+                       rc = ipxrtr_ioctl(cmd, argp);
+               break;
+       case SIOCSIFADDR:
+       case SIOCAIPXITFCRT:
+       case SIOCAIPXPRISLT:
+               rc = -EPERM;
+               if (!capable(CAP_NET_ADMIN))
+                       break;
+               /* fall through */
+       case SIOCGIFADDR:
+               rc = ipxitf_ioctl(cmd, argp);
+               break;
+       case SIOCIPXCFGDATA:
+               rc = ipxcfg_get_config_data(argp);
+               break;
+       case SIOCIPXNCPCONN:
+               /*
+                * This socket wants to take care of the NCP connection
+                * handed to us in arg.
+                */
+               rc = -EPERM;
+               if (!capable(CAP_NET_ADMIN))
+                       break;
+               rc = get_user(ipx_sk(sk)->ipx_ncp_conn,
+                             (const unsigned short __user *)argp);
+               break;
+       case SIOCGSTAMP:
+               rc = sock_get_timestamp(sk, argp);
+               break;
+       case SIOCGIFDSTADDR:
+       case SIOCSIFDSTADDR:
+       case SIOCGIFBRDADDR:
+       case SIOCSIFBRDADDR:
+       case SIOCGIFNETMASK:
+       case SIOCSIFNETMASK:
+               rc = -EINVAL;
+               break;
+       default:
+               rc = -ENOIOCTLCMD;
+               break;
+       }
+       release_sock(sk);
+
+       return rc;
+}
+
+
+#ifdef CONFIG_COMPAT
+static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       /*
+        * These 4 commands use same structure on 32bit and 64bit.  Rest of IPX
+        * commands is handled by generic ioctl code.  As these commands are
+        * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic
+        * code.
+        */
+       switch (cmd) {
+       case SIOCAIPXITFCRT:
+       case SIOCAIPXPRISLT:
+       case SIOCIPXCFGDATA:
+       case SIOCIPXNCPCONN:
+               return ipx_ioctl(sock, cmd, arg);
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+#endif
+
+static int ipx_shutdown(struct socket *sock, int mode)
+{
+       struct sock *sk = sock->sk;
+
+       if (mode < SHUT_RD || mode > SHUT_RDWR)
+               return -EINVAL;
+       /* This maps:
+        * SHUT_RD   (0) -> RCV_SHUTDOWN  (1)
+        * SHUT_WR   (1) -> SEND_SHUTDOWN (2)
+        * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
+        */
+       ++mode;
+
+       lock_sock(sk);
+       sk->sk_shutdown |= mode;
+       release_sock(sk);
+       sk->sk_state_change(sk);
+
+       return 0;
+}
+
+/*
+ * Socket family declarations
+ */
+
+static const struct net_proto_family ipx_family_ops = {
+       .family         = PF_IPX,
+       .create         = ipx_create,
+       .owner          = THIS_MODULE,
+};
+
+static const struct proto_ops ipx_dgram_ops = {
+       .family         = PF_IPX,
+       .owner          = THIS_MODULE,
+       .release        = ipx_release,
+       .bind           = ipx_bind,
+       .connect        = ipx_connect,
+       .socketpair     = sock_no_socketpair,
+       .accept         = sock_no_accept,
+       .getname        = ipx_getname,
+       .poll           = datagram_poll,
+       .ioctl          = ipx_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ipx_compat_ioctl,
+#endif
+       .listen         = sock_no_listen,
+       .shutdown       = ipx_shutdown,
+       .setsockopt     = ipx_setsockopt,
+       .getsockopt     = ipx_getsockopt,
+       .sendmsg        = ipx_sendmsg,
+       .recvmsg        = ipx_recvmsg,
+       .mmap           = sock_no_mmap,
+       .sendpage       = sock_no_sendpage,
+};
+
+static struct packet_type ipx_8023_packet_type __read_mostly = {
+       .type           = cpu_to_be16(ETH_P_802_3),
+       .func           = ipx_rcv,
+};
+
+static struct packet_type ipx_dix_packet_type __read_mostly = {
+       .type           = cpu_to_be16(ETH_P_IPX),
+       .func           = ipx_rcv,
+};
+
+static struct notifier_block ipx_dev_notifier = {
+       .notifier_call  = ipxitf_device_event,
+};
+
+static const unsigned char ipx_8022_type = 0xE0;
+static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
+static const char ipx_EII_err_msg[] __initconst =
+       KERN_CRIT "IPX: Unable to register with Ethernet II\n";
+static const char ipx_8023_err_msg[] __initconst =
+       KERN_CRIT "IPX: Unable to register with 802.3\n";
+static const char ipx_llc_err_msg[] __initconst =
+       KERN_CRIT "IPX: Unable to register with 802.2\n";
+static const char ipx_snap_err_msg[] __initconst =
+       KERN_CRIT "IPX: Unable to register with SNAP\n";
+
+static int __init ipx_init(void)
+{
+       int rc = proto_register(&ipx_proto, 1);
+
+       if (rc != 0)
+               goto out;
+
+       sock_register(&ipx_family_ops);
+
+       pEII_datalink = make_EII_client();
+       if (pEII_datalink)
+               dev_add_pack(&ipx_dix_packet_type);
+       else
+               printk(ipx_EII_err_msg);
+
+       p8023_datalink = make_8023_client();
+       if (p8023_datalink)
+               dev_add_pack(&ipx_8023_packet_type);
+       else
+               printk(ipx_8023_err_msg);
+
+       p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv);
+       if (!p8022_datalink)
+               printk(ipx_llc_err_msg);
+
+       pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv);
+       if (!pSNAP_datalink)
+               printk(ipx_snap_err_msg);
+
+       register_netdevice_notifier(&ipx_dev_notifier);
+       ipx_register_sysctl();
+       ipx_proc_init();
+out:
+       return rc;
+}
+
+static void __exit ipx_proto_finito(void)
+{
+       ipx_proc_exit();
+       ipx_unregister_sysctl();
+
+       unregister_netdevice_notifier(&ipx_dev_notifier);
+
+       ipxitf_cleanup();
+
+       if (pSNAP_datalink) {
+               unregister_snap_client(pSNAP_datalink);
+               pSNAP_datalink = NULL;
+       }
+
+       if (p8022_datalink) {
+               unregister_8022_client(p8022_datalink);
+               p8022_datalink = NULL;
+       }
+
+       dev_remove_pack(&ipx_8023_packet_type);
+       if (p8023_datalink) {
+               destroy_8023_client(p8023_datalink);
+               p8023_datalink = NULL;
+       }
+
+       dev_remove_pack(&ipx_dix_packet_type);
+       if (pEII_datalink) {
+               destroy_EII_client(pEII_datalink);
+               pEII_datalink = NULL;
+       }
+
+       proto_unregister(&ipx_proto);
+       sock_unregister(ipx_family_ops.family);
+}
+
+module_init(ipx_init);
+module_exit(ipx_proto_finito);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(PF_IPX);
diff --git a/drivers/staging/ipx/ipx_proc.c b/drivers/staging/ipx/ipx_proc.c
new file mode 100644 (file)
index 0000000..b9232e4
--- /dev/null
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *     IPX proc routines
+ *
+ *     Copyright(C) Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2002
+ */
+
+#include <linux/init.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/seq_file.h>
+#include <linux/export.h>
+#include <net/net_namespace.h>
+#include <net/tcp_states.h>
+#include <net/ipx.h>
+
+static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos)
+{
+       spin_lock_bh(&ipx_interfaces_lock);
+       return seq_list_start_head(&ipx_interfaces, *pos);
+}
+
+static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       return seq_list_next(v, &ipx_interfaces, pos);
+}
+
+static void ipx_seq_interface_stop(struct seq_file *seq, void *v)
+{
+       spin_unlock_bh(&ipx_interfaces_lock);
+}
+
+static int ipx_seq_interface_show(struct seq_file *seq, void *v)
+{
+       struct ipx_interface *i;
+
+       if (v == &ipx_interfaces) {
+               seq_puts(seq, "Network    Node_Address   Primary  Device     "
+                             "Frame_Type");
+#ifdef IPX_REFCNT_DEBUG
+               seq_puts(seq, "  refcnt");
+#endif
+               seq_puts(seq, "\n");
+               goto out;
+       }
+
+       i = list_entry(v, struct ipx_interface, node);
+       seq_printf(seq, "%08X   ", ntohl(i->if_netnum));
+       seq_printf(seq, "%02X%02X%02X%02X%02X%02X   ",
+                       i->if_node[0], i->if_node[1], i->if_node[2],
+                       i->if_node[3], i->if_node[4], i->if_node[5]);
+       seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No");
+       seq_printf(seq, "%-11s", ipx_device_name(i));
+       seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type));
+#ifdef IPX_REFCNT_DEBUG
+       seq_printf(seq, "%6d", refcount_read(&i->refcnt));
+#endif
+       seq_puts(seq, "\n");
+out:
+       return 0;
+}
+
+static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos)
+{
+       read_lock_bh(&ipx_routes_lock);
+       return seq_list_start_head(&ipx_routes, *pos);
+}
+
+static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       return seq_list_next(v, &ipx_routes, pos);
+}
+
+static void ipx_seq_route_stop(struct seq_file *seq, void *v)
+{
+       read_unlock_bh(&ipx_routes_lock);
+}
+
+static int ipx_seq_route_show(struct seq_file *seq, void *v)
+{
+       struct ipx_route *rt;
+
+       if (v == &ipx_routes) {
+               seq_puts(seq, "Network    Router_Net   Router_Node\n");
+               goto out;
+       }
+
+       rt = list_entry(v, struct ipx_route, node);
+
+       seq_printf(seq, "%08X   ", ntohl(rt->ir_net));
+       if (rt->ir_routed)
+               seq_printf(seq, "%08X     %02X%02X%02X%02X%02X%02X\n",
+                          ntohl(rt->ir_intrfc->if_netnum),
+                          rt->ir_router_node[0], rt->ir_router_node[1],
+                          rt->ir_router_node[2], rt->ir_router_node[3],
+                          rt->ir_router_node[4], rt->ir_router_node[5]);
+       else
+               seq_puts(seq, "Directly     Connected\n");
+out:
+       return 0;
+}
+
+static __inline__ struct sock *ipx_get_socket_idx(loff_t pos)
+{
+       struct sock *s = NULL;
+       struct ipx_interface *i;
+
+       list_for_each_entry(i, &ipx_interfaces, node) {
+               spin_lock_bh(&i->if_sklist_lock);
+               sk_for_each(s, &i->if_sklist) {
+                       if (!pos)
+                               break;
+                       --pos;
+               }
+               spin_unlock_bh(&i->if_sklist_lock);
+               if (!pos) {
+                       if (s)
+                               goto found;
+                       break;
+               }
+       }
+       s = NULL;
+found:
+       return s;
+}
+
+static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos)
+{
+       loff_t l = *pos;
+
+       spin_lock_bh(&ipx_interfaces_lock);
+       return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN;
+}
+
+static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       struct sock* sk, *next;
+       struct ipx_interface *i;
+       struct ipx_sock *ipxs;
+
+       ++*pos;
+       if (v == SEQ_START_TOKEN) {
+               sk = NULL;
+               i = ipx_interfaces_head();
+               if (!i)
+                       goto out;
+               sk = sk_head(&i->if_sklist);
+               if (sk)
+                       spin_lock_bh(&i->if_sklist_lock);
+               goto out;
+       }
+       sk = v;
+       next = sk_next(sk);
+       if (next) {
+               sk = next;
+               goto out;
+       }
+       ipxs = ipx_sk(sk);
+       i = ipxs->intrfc;
+       spin_unlock_bh(&i->if_sklist_lock);
+       sk = NULL;
+       for (;;) {
+               if (i->node.next == &ipx_interfaces)
+                       break;
+               i = list_entry(i->node.next, struct ipx_interface, node);
+               spin_lock_bh(&i->if_sklist_lock);
+               if (!hlist_empty(&i->if_sklist)) {
+                       sk = sk_head(&i->if_sklist);
+                       break;
+               }
+               spin_unlock_bh(&i->if_sklist_lock);
+       }
+out:
+       return sk;
+}
+
+static int ipx_seq_socket_show(struct seq_file *seq, void *v)
+{
+       struct sock *s;
+       struct ipx_sock *ipxs;
+
+       if (v == SEQ_START_TOKEN) {
+#ifdef CONFIG_IPX_INTERN
+               seq_puts(seq, "Local_Address               "
+                             "Remote_Address              Tx_Queue  "
+                             "Rx_Queue  State  Uid\n");
+#else
+               seq_puts(seq, "Local_Address  Remote_Address              "
+                             "Tx_Queue  Rx_Queue  State  Uid\n");
+#endif
+               goto out;
+       }
+
+       s = v;
+       ipxs = ipx_sk(s);
+#ifdef CONFIG_IPX_INTERN
+       seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X  ",
+                  ntohl(ipxs->intrfc->if_netnum),
+                  ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3],
+                  ipxs->node[4], ipxs->node[5], ntohs(ipxs->port));
+#else
+       seq_printf(seq, "%08X:%04X  ", ntohl(ipxs->intrfc->if_netnum),
+                  ntohs(ipxs->port));
+#endif /* CONFIG_IPX_INTERN */
+       if (s->sk_state != TCP_ESTABLISHED)
+               seq_printf(seq, "%-28s", "Not_Connected");
+       else {
+               seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X  ",
+                          ntohl(ipxs->dest_addr.net),
+                          ipxs->dest_addr.node[0], ipxs->dest_addr.node[1],
+                          ipxs->dest_addr.node[2], ipxs->dest_addr.node[3],
+                          ipxs->dest_addr.node[4], ipxs->dest_addr.node[5],
+                          ntohs(ipxs->dest_addr.sock));
+       }
+
+       seq_printf(seq, "%08X  %08X  %02X     %03u\n",
+                  sk_wmem_alloc_get(s),
+                  sk_rmem_alloc_get(s),
+                  s->sk_state,
+                  from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)));
+out:
+       return 0;
+}
+
+static const struct seq_operations ipx_seq_interface_ops = {
+       .start  = ipx_seq_interface_start,
+       .next   = ipx_seq_interface_next,
+       .stop   = ipx_seq_interface_stop,
+       .show   = ipx_seq_interface_show,
+};
+
+static const struct seq_operations ipx_seq_route_ops = {
+       .start  = ipx_seq_route_start,
+       .next   = ipx_seq_route_next,
+       .stop   = ipx_seq_route_stop,
+       .show   = ipx_seq_route_show,
+};
+
+static const struct seq_operations ipx_seq_socket_ops = {
+       .start  = ipx_seq_socket_start,
+       .next   = ipx_seq_socket_next,
+       .stop   = ipx_seq_interface_stop,
+       .show   = ipx_seq_socket_show,
+};
+
+static int ipx_seq_route_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &ipx_seq_route_ops);
+}
+
+static int ipx_seq_interface_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &ipx_seq_interface_ops);
+}
+
+static int ipx_seq_socket_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &ipx_seq_socket_ops);
+}
+
+static const struct file_operations ipx_seq_interface_fops = {
+       .open           = ipx_seq_interface_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static const struct file_operations ipx_seq_route_fops = {
+       .open           = ipx_seq_route_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static const struct file_operations ipx_seq_socket_fops = {
+       .open           = ipx_seq_socket_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static struct proc_dir_entry *ipx_proc_dir;
+
+int __init ipx_proc_init(void)
+{
+       struct proc_dir_entry *p;
+       int rc = -ENOMEM;
+
+       ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net);
+
+       if (!ipx_proc_dir)
+               goto out;
+       p = proc_create("interface", S_IRUGO,
+                       ipx_proc_dir, &ipx_seq_interface_fops);
+       if (!p)
+               goto out_interface;
+
+       p = proc_create("route", S_IRUGO, ipx_proc_dir, &ipx_seq_route_fops);
+       if (!p)
+               goto out_route;
+
+       p = proc_create("socket", S_IRUGO, ipx_proc_dir, &ipx_seq_socket_fops);
+       if (!p)
+               goto out_socket;
+
+       rc = 0;
+out:
+       return rc;
+out_socket:
+       remove_proc_entry("route", ipx_proc_dir);
+out_route:
+       remove_proc_entry("interface", ipx_proc_dir);
+out_interface:
+       remove_proc_entry("ipx", init_net.proc_net);
+       goto out;
+}
+
+void __exit ipx_proc_exit(void)
+{
+       remove_proc_entry("interface", ipx_proc_dir);
+       remove_proc_entry("route", ipx_proc_dir);
+       remove_proc_entry("socket", ipx_proc_dir);
+       remove_proc_entry("ipx", init_net.proc_net);
+}
+
+#else /* CONFIG_PROC_FS */
+
+int __init ipx_proc_init(void)
+{
+       return 0;
+}
+
+void __exit ipx_proc_exit(void)
+{
+}
+
+#endif /* CONFIG_PROC_FS */
diff --git a/drivers/staging/ipx/ipx_route.c b/drivers/staging/ipx/ipx_route.c
new file mode 100644 (file)
index 0000000..3cf93aa
--- /dev/null
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *     Implements the IPX routing routines.
+ *     Code moved from af_ipx.c.
+ *
+ *     Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2003
+ *
+ *     See net/ipx/ChangeLog.
+ */
+
+#include <linux/list.h>
+#include <linux/route.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <net/ipx.h>
+#include <net/sock.h>
+
+LIST_HEAD(ipx_routes);
+DEFINE_RWLOCK(ipx_routes_lock);
+
+extern struct ipx_interface *ipx_internal_net;
+
+extern struct ipx_interface *ipxitf_find_using_net(__be32 net);
+extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
+                              struct sk_buff *skb, int copy);
+extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
+                              struct sk_buff *skb, int copy);
+
+struct ipx_route *ipxrtr_lookup(__be32 net)
+{
+       struct ipx_route *r;
+
+       read_lock_bh(&ipx_routes_lock);
+       list_for_each_entry(r, &ipx_routes, node)
+               if (r->ir_net == net) {
+                       ipxrtr_hold(r);
+                       goto unlock;
+               }
+       r = NULL;
+unlock:
+       read_unlock_bh(&ipx_routes_lock);
+       return r;
+}
+
+/*
+ * Caller must hold a reference to intrfc
+ */
+int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
+                    unsigned char *node)
+{
+       struct ipx_route *rt;
+       int rc;
+
+       /* Get a route structure; either existing or create */
+       rt = ipxrtr_lookup(network);
+       if (!rt) {
+               rt = kmalloc(sizeof(*rt), GFP_ATOMIC);
+               rc = -EAGAIN;
+               if (!rt)
+                       goto out;
+
+               refcount_set(&rt->refcnt, 1);
+               ipxrtr_hold(rt);
+               write_lock_bh(&ipx_routes_lock);
+               list_add(&rt->node, &ipx_routes);
+               write_unlock_bh(&ipx_routes_lock);
+       } else {
+               rc = -EEXIST;
+               if (intrfc == ipx_internal_net)
+                       goto out_put;
+       }
+
+       rt->ir_net      = network;
+       rt->ir_intrfc   = intrfc;
+       if (!node) {
+               memset(rt->ir_router_node, '\0', IPX_NODE_LEN);
+               rt->ir_routed = 0;
+       } else {
+               memcpy(rt->ir_router_node, node, IPX_NODE_LEN);
+               rt->ir_routed = 1;
+       }
+
+       rc = 0;
+out_put:
+       ipxrtr_put(rt);
+out:
+       return rc;
+}
+
+void ipxrtr_del_routes(struct ipx_interface *intrfc)
+{
+       struct ipx_route *r, *tmp;
+
+       write_lock_bh(&ipx_routes_lock);
+       list_for_each_entry_safe(r, tmp, &ipx_routes, node)
+               if (r->ir_intrfc == intrfc) {
+                       list_del(&r->node);
+                       ipxrtr_put(r);
+               }
+       write_unlock_bh(&ipx_routes_lock);
+}
+
+static int ipxrtr_create(struct ipx_route_definition *rd)
+{
+       struct ipx_interface *intrfc;
+       int rc = -ENETUNREACH;
+
+       /* Find the appropriate interface */
+       intrfc = ipxitf_find_using_net(rd->ipx_router_network);
+       if (!intrfc)
+               goto out;
+       rc = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node);
+       ipxitf_put(intrfc);
+out:
+       return rc;
+}
+
+static int ipxrtr_delete(__be32 net)
+{
+       struct ipx_route *r, *tmp;
+       int rc;
+
+       write_lock_bh(&ipx_routes_lock);
+       list_for_each_entry_safe(r, tmp, &ipx_routes, node)
+               if (r->ir_net == net) {
+                       /* Directly connected; can't lose route */
+                       rc = -EPERM;
+                       if (!r->ir_routed)
+                               goto out;
+                       list_del(&r->node);
+                       ipxrtr_put(r);
+                       rc = 0;
+                       goto out;
+               }
+       rc = -ENOENT;
+out:
+       write_unlock_bh(&ipx_routes_lock);
+       return rc;
+}
+
+/*
+ * The skb has to be unshared, we'll end up calling ipxitf_send, that'll
+ * modify the packet
+ */
+int ipxrtr_route_skb(struct sk_buff *skb)
+{
+       struct ipxhdr *ipx = ipx_hdr(skb);
+       struct ipx_route *r = ipxrtr_lookup(IPX_SKB_CB(skb)->ipx_dest_net);
+
+       if (!r) {       /* no known route */
+               kfree_skb(skb);
+               return 0;
+       }
+
+       ipxitf_hold(r->ir_intrfc);
+       ipxitf_send(r->ir_intrfc, skb, r->ir_routed ?
+                       r->ir_router_node : ipx->ipx_dest.node);
+       ipxitf_put(r->ir_intrfc);
+       ipxrtr_put(r);
+
+       return 0;
+}
+
+/*
+ * Route an outgoing frame from a socket.
+ */
+int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
+                       struct msghdr *msg, size_t len, int noblock)
+{
+       struct sk_buff *skb;
+       struct ipx_sock *ipxs = ipx_sk(sk);
+       struct ipx_interface *intrfc;
+       struct ipxhdr *ipx;
+       size_t size;
+       int ipx_offset;
+       struct ipx_route *rt = NULL;
+       int rc;
+
+       /* Find the appropriate interface on which to send packet */
+       if (!usipx->sipx_network && ipx_primary_net) {
+               usipx->sipx_network = ipx_primary_net->if_netnum;
+               intrfc = ipx_primary_net;
+       } else {
+               rt = ipxrtr_lookup(usipx->sipx_network);
+               rc = -ENETUNREACH;
+               if (!rt)
+                       goto out;
+               intrfc = rt->ir_intrfc;
+       }
+
+       ipxitf_hold(intrfc);
+       ipx_offset = intrfc->if_ipx_offset;
+       size = sizeof(struct ipxhdr) + len + ipx_offset;
+
+       skb = sock_alloc_send_skb(sk, size, noblock, &rc);
+       if (!skb)
+               goto out_put;
+
+       skb_reserve(skb, ipx_offset);
+       skb->sk = sk;
+
+       /* Fill in IPX header */
+       skb_reset_network_header(skb);
+       skb_reset_transport_header(skb);
+       skb_put(skb, sizeof(struct ipxhdr));
+       ipx = ipx_hdr(skb);
+       ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr));
+       IPX_SKB_CB(skb)->ipx_tctrl = 0;
+       ipx->ipx_type    = usipx->sipx_type;
+
+       IPX_SKB_CB(skb)->last_hop.index = -1;
+#ifdef CONFIG_IPX_INTERN
+       IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum;
+       memcpy(ipx->ipx_source.node, ipxs->node, IPX_NODE_LEN);
+#else
+       rc = ntohs(ipxs->port);
+       if (rc == 0x453 || rc == 0x452) {
+               /* RIP/SAP special handling for mars_nwe */
+               IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum;
+               memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN);
+       } else {
+               IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum;
+               memcpy(ipx->ipx_source.node, ipxs->intrfc->if_node,
+                       IPX_NODE_LEN);
+       }
+#endif /* CONFIG_IPX_INTERN */
+       ipx->ipx_source.sock            = ipxs->port;
+       IPX_SKB_CB(skb)->ipx_dest_net   = usipx->sipx_network;
+       memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN);
+       ipx->ipx_dest.sock              = usipx->sipx_port;
+
+       rc = memcpy_from_msg(skb_put(skb, len), msg, len);
+       if (rc) {
+               kfree_skb(skb);
+               goto out_put;
+       }
+
+       /* Apply checksum. Not allowed on 802.3 links. */
+       if (sk->sk_no_check_tx ||
+           intrfc->if_dlink_type == htons(IPX_FRAME_8023))
+               ipx->ipx_checksum = htons(0xFFFF);
+       else
+               ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
+
+       rc = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
+                        rt->ir_router_node : ipx->ipx_dest.node);
+out_put:
+       ipxitf_put(intrfc);
+       if (rt)
+               ipxrtr_put(rt);
+out:
+       return rc;
+}
+
+/*
+ * We use a normal struct rtentry for route handling
+ */
+int ipxrtr_ioctl(unsigned int cmd, void __user *arg)
+{
+       struct rtentry rt;      /* Use these to behave like 'other' stacks */
+       struct sockaddr_ipx *sg, *st;
+       int rc = -EFAULT;
+
+       if (copy_from_user(&rt, arg, sizeof(rt)))
+               goto out;
+
+       sg = (struct sockaddr_ipx *)&rt.rt_gateway;
+       st = (struct sockaddr_ipx *)&rt.rt_dst;
+
+       rc = -EINVAL;
+       if (!(rt.rt_flags & RTF_GATEWAY) || /* Direct routes are fixed */
+           sg->sipx_family != AF_IPX ||
+           st->sipx_family != AF_IPX)
+               goto out;
+
+       switch (cmd) {
+       case SIOCDELRT:
+               rc = ipxrtr_delete(st->sipx_network);
+               break;
+       case SIOCADDRT: {
+               struct ipx_route_definition f;
+               f.ipx_network           = st->sipx_network;
+               f.ipx_router_network    = sg->sipx_network;
+               memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN);
+               rc = ipxrtr_create(&f);
+               break;
+       }
+       }
+
+out:
+       return rc;
+}
diff --git a/drivers/staging/ipx/pe2.c b/drivers/staging/ipx/pe2.c
new file mode 100644 (file)
index 0000000..ba7d421
--- /dev/null
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/in.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+
+#include <net/datalink.h>
+
+static int pEII_request(struct datalink_proto *dl,
+                       struct sk_buff *skb, unsigned char *dest_node)
+{
+       struct net_device *dev = skb->dev;
+
+       skb->protocol = htons(ETH_P_IPX);
+       dev_hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
+       return dev_queue_xmit(skb);
+}
+
+struct datalink_proto *make_EII_client(void)
+{
+       struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
+
+       if (proto) {
+               proto->header_length = 0;
+               proto->request = pEII_request;
+       }
+
+       return proto;
+}
+
+void destroy_EII_client(struct datalink_proto *dl)
+{
+       kfree(dl);
+}
diff --git a/drivers/staging/ipx/sysctl_net_ipx.c b/drivers/staging/ipx/sysctl_net_ipx.c
new file mode 100644 (file)
index 0000000..c3eef45
--- /dev/null
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+/* -*- linux-c -*-
+ * sysctl_net_ipx.c: sysctl interface to net IPX subsystem.
+ *
+ * Begun April 1, 1996, Mike Shaver.
+ * Added /proc/sys/net/ipx directory entry (empty =) ). [MS]
+ * Added /proc/sys/net/ipx/ipx_pprop_broadcasting - acme March 4, 2001
+ */
+
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <net/net_namespace.h>
+#include <net/ipx.h>
+
+#ifndef CONFIG_SYSCTL
+#error This file should not be compiled without CONFIG_SYSCTL defined
+#endif
+
+static struct ctl_table ipx_table[] = {
+       {
+               .procname       = "ipx_pprop_broadcasting",
+               .data           = &sysctl_ipx_pprop_broadcasting,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+       { },
+};
+
+static struct ctl_table_header *ipx_table_header;
+
+void ipx_register_sysctl(void)
+{
+       ipx_table_header = register_net_sysctl(&init_net, "net/ipx", ipx_table);
+}
+
+void ipx_unregister_sysctl(void)
+{
+       unregister_net_sysctl_table(ipx_table_header);
+}
index 1dba16bc7f8d7781be68fa4cb39ca41422b0625b..2ea00a6531f9f5fbdc097cefbf6d5444198cf3ad 100644 (file)
@@ -12,7 +12,6 @@
  * Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor
  *
  */
-#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
index 34355061ab0b2d140a90405ceb8f9adea89a5037..7af618fb66c0f0db8de54f67829da3f8ff618ab8 100644 (file)
@@ -1668,7 +1668,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
                        IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC,
                                    goto errlsap;);
 
-                       if ((self->slsap_sel == slsap_sel)) {
+                       if (self->slsap_sel == slsap_sel) {
                                pr_debug("Source LSAP selector=%02x in use\n",
                                         self->slsap_sel);
                                goto errlsap;
@@ -1693,7 +1693,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
        self = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
        while (self != NULL) {
                IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, goto erruncon;);
-               if ((self->slsap_sel == slsap_sel)) {
+               if (self->slsap_sel == slsap_sel) {
                        pr_debug("Source LSAP selector=%02x in use (unconnected)\n",
                                 self->slsap_sel);
                        goto erruncon;
index 880085e2f24aeca608b1d60299b0e62d889249fe..e48c55769c94c4be5fa08c66f8076e2c43d0d65e 100644 (file)
@@ -2990,7 +2990,7 @@ int ks_wlan_net_stop(struct net_device *dev)
 /**
  * is_connect_status() - return true if status is 'connected'
  * @status: high bit is used as FORCE_DISCONNECT, low bits used for
- *     connect status.
+ *     connect status.
  */
 bool is_connect_status(u32 status)
 {
@@ -3000,7 +3000,7 @@ bool is_connect_status(u32 status)
 /**
  * is_disconnect_status() - return true if status is 'disconnected'
  * @status: high bit is used as FORCE_DISCONNECT, low bits used for
- *     disconnect status.
+ *     disconnect status.
  */
 bool is_disconnect_status(u32 status)
 {
index 6ad8867e54519afe86369bcb5174781d89cf2135..ca3472cc952f0d2478d0d8ca89d2067cac94a7ad 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/libcfs/libcfs_prim.h>
 #include <linux/libcfs/libcfs_time.h>
 #include <linux/libcfs/libcfs_string.h>
-#include <linux/libcfs/libcfs_workitem.h>
 #include <linux/libcfs/libcfs_hash.h>
 #include <linux/libcfs/libcfs_fail.h>
 #include <linux/libcfs/curproc.h>
@@ -74,16 +73,6 @@ sigset_t cfs_block_sigsinv(unsigned long sigs);
 void cfs_restore_sigs(sigset_t sigset);
 void cfs_clear_sigpending(void);
 
-/*
- * Random number handling
- */
-
-/* returns a random 32-bit integer */
-unsigned int cfs_rand(void);
-/* seed the generator */
-void cfs_srand(unsigned int seed1, unsigned int seed2);
-void cfs_get_random_bytes(void *buf, int size);
-
 struct libcfs_ioctl_handler {
        struct list_head item;
        int (*handle_ioctl)(unsigned int cmd, struct libcfs_ioctl_hdr *hdr);
@@ -126,7 +115,7 @@ extern struct miscdevice libcfs_dev;
  */
 extern char lnet_debug_log_upcall[1024];
 
-extern struct cfs_wi_sched *cfs_sched_rehash;
+extern struct workqueue_struct *cfs_rehash_wq;
 
 struct lnet_debugfs_symlink_def {
        char *name;
index 6d132f9412819cd3b23cc61de4d567b0cd392a12..61bce77fddd617a00a53a218fa8d709129d7b366 100644 (file)
@@ -79,7 +79,7 @@
 /**
  * return cpumask of CPU partition \a cpt
  */
-cpumask_t *cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt);
+cpumask_var_t *cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt);
 /**
  * print string information of cpt-table
  */
@@ -96,7 +96,7 @@ struct cfs_cpt_table {
        u64                     ctb_version;
 };
 
-static inline cpumask_t *
+static inline cpumask_var_t *
 cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt)
 {
        return NULL;
index 5a27220cc608a0300bf391699359636d5004ce32..0506f1d457572f3446269a7655facbc1639cbfef 100644 (file)
@@ -248,7 +248,7 @@ struct cfs_hash {
        /** # of iterators (caller of cfs_hash_for_each_*) */
        u32                             hs_iterators;
        /** rehash workitem */
-       struct cfs_workitem             hs_rehash_wi;
+       struct work_struct              hs_rehash_work;
        /** refcount on this hash table */
        atomic_t                        hs_refcount;
        /** rehash buckets-table */
@@ -265,7 +265,7 @@ struct cfs_hash {
        /** bits when we found the max depth */
        unsigned int                    hs_dep_bits;
        /** workitem to output max depth */
-       struct cfs_workitem             hs_dep_wi;
+       struct work_struct              hs_dep_work;
 #endif
        /** name of htable */
        char                            hs_name[0];
@@ -738,7 +738,7 @@ u64 cfs_hash_size_get(struct cfs_hash *hs);
  */
 void cfs_hash_rehash_cancel_locked(struct cfs_hash *hs);
 void cfs_hash_rehash_cancel(struct cfs_hash *hs);
-int  cfs_hash_rehash(struct cfs_hash *hs, int do_rehash);
+void cfs_hash_rehash(struct cfs_hash *hs, int do_rehash);
 void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key,
                         void *new_key, struct hlist_node *hnode);
 
index 2f4ff595fac91557392f4ce4db42f9db303ebab4..491d5971d19925faf8aff744557c3e3ad40e67b2 100644 (file)
 # define DEBUG_SUBSYSTEM S_UNDEFINED
 #endif
 
-/*
- * When this is on, LASSERT macro includes check for assignment used instead
- * of equality check, but doesn't have unlikely(). Turn this on from time to
- * time to make test-builds. This shouldn't be on for production release.
- */
-#define LASSERT_CHECKED (0)
-
 #define LASSERTF(cond, fmt, ...)                                       \
 do {                                                                   \
        if (unlikely(!(cond))) {                                        \
@@ -74,8 +67,6 @@ do {                                                                  \
 # define LINVRNT(exp) ((void)sizeof !!(exp))
 #endif
 
-#define KLASSERT(e) LASSERT(e)
-
 void __noreturn lbug_with_loc(struct libcfs_debug_msg_data *msg);
 
 #define LBUG()                                                   \
@@ -84,74 +75,24 @@ do {                                                                    \
        lbug_with_loc(&msgdata);                                        \
 } while (0)
 
-#ifndef LIBCFS_VMALLOC_SIZE
-#define LIBCFS_VMALLOC_SIZE    (2 << PAGE_SHIFT) /* 2 pages */
-#endif
-
-#define LIBCFS_ALLOC_PRE(size, mask)                                   \
-       LASSERT(!in_interrupt() || ((size) <= LIBCFS_VMALLOC_SIZE &&    \
-                                   !gfpflags_allow_blocking(mask)))
-
-#define LIBCFS_ALLOC_POST(ptr, size)                                       \
-do {                                                                       \
-       if (unlikely(!(ptr))) {                                             \
-               CERROR("LNET: out of memory at %s:%d (tried to alloc '"     \
-                      #ptr "' = %d)\n", __FILE__, __LINE__, (int)(size));  \
-       } else {                                                            \
-               memset((ptr), 0, (size));                                   \
-       }                                                                   \
-} while (0)
-
-/**
- * allocate memory with GFP flags @mask
- */
-#define LIBCFS_ALLOC_GFP(ptr, size, mask)                                  \
-do {                                                                       \
-       LIBCFS_ALLOC_PRE((size), (mask));                                   \
-       (ptr) = (size) <= LIBCFS_VMALLOC_SIZE ?                             \
-               kmalloc((size), (mask)) : vmalloc(size);            \
-       LIBCFS_ALLOC_POST((ptr), (size));                                   \
-} while (0)
-
-/**
- * default allocator
- */
-#define LIBCFS_ALLOC(ptr, size) \
-       LIBCFS_ALLOC_GFP(ptr, size, GFP_NOFS)
-
-/**
- * non-sleeping allocator
+/*
+ * Use #define rather than inline, as lnet_cpt_table() might
+ * not be defined yet
  */
-#define LIBCFS_ALLOC_ATOMIC(ptr, size) \
-       LIBCFS_ALLOC_GFP(ptr, size, GFP_ATOMIC)
+#define kmalloc_cpt(size, flags, cpt) \
+       kmalloc_node(size, flags,  cfs_cpt_spread_node(lnet_cpt_table(), cpt))
 
-/**
- * allocate memory for specified CPU partition
- *   \a cptab != NULL, \a cpt is CPU partition id of \a cptab
- *   \a cptab == NULL, \a cpt is HW NUMA node id
- */
-#define LIBCFS_CPT_ALLOC_GFP(ptr, cptab, cpt, size, mask)                  \
-do {                                                                       \
-       LIBCFS_ALLOC_PRE((size), (mask));                                   \
-       (ptr) = (size) <= LIBCFS_VMALLOC_SIZE ?                             \
-               kmalloc_node((size), (mask), cfs_cpt_spread_node(cptab, cpt)) :\
-               vmalloc_node(size, cfs_cpt_spread_node(cptab, cpt));        \
-       LIBCFS_ALLOC_POST((ptr), (size));                                   \
-} while (0)
+#define kzalloc_cpt(size, flags, cpt) \
+       kmalloc_node(size, flags | __GFP_ZERO,                          \
+                    cfs_cpt_spread_node(lnet_cpt_table(), cpt))
 
-/** default numa allocator */
-#define LIBCFS_CPT_ALLOC(ptr, cptab, cpt, size)                                    \
-       LIBCFS_CPT_ALLOC_GFP(ptr, cptab, cpt, size, GFP_NOFS)
+#define kvmalloc_cpt(size, flags, cpt) \
+       kvmalloc_node(size, flags,                                      \
+                     cfs_cpt_spread_node(lnet_cpt_table(), cpt))
 
-#define LIBCFS_FREE(ptr, size)                                   \
-do {                                                               \
-       if (unlikely(!(ptr))) {                                         \
-               CERROR("LIBCFS: free NULL '" #ptr "' (%d bytes) at "    \
-                      "%s:%d\n", (int)(size), __FILE__, __LINE__);     \
-               break;                                            \
-       }                                                              \
-       kvfree(ptr);                                      \
-} while (0)
+#define kvzalloc_cpt(size, flags, cpt) \
+       kvmalloc_node(size, flags | __GFP_ZERO,                         \
+                     cfs_cpt_spread_node(lnet_cpt_table(), cpt))
 
 /******************************************************************************/
 
@@ -242,59 +183,18 @@ do {                                                          \
 #define LASSERT_ATOMIC_ZERO(a)           LASSERT_ATOMIC_EQ(a, 0)
 #define LASSERT_ATOMIC_POS(a)             LASSERT_ATOMIC_GT(a, 0)
 
-#define CFS_ALLOC_PTR(ptr)      LIBCFS_ALLOC(ptr, sizeof(*(ptr)))
-#define CFS_FREE_PTR(ptr)       LIBCFS_FREE(ptr, sizeof(*(ptr)))
-
-/* max value for numeric network address */
-#define MAX_NUMERIC_VALUE 0xffffffff
-
 /* implication */
 #define ergo(a, b) (!(a) || (b))
 /* logical equivalence */
 #define equi(a, b) (!!(a) == !!(b))
 
-/* --------------------------------------------------------------------
- * Light-weight trace
- * Support for temporary event tracing with minimal Heisenberg effect.
- * --------------------------------------------------------------------
- */
-
-#define MKSTR(ptr) ((ptr)) ? (ptr) : ""
-
-static inline size_t cfs_size_round4(int val)
-{
-       return (val + 3) & (~0x3);
-}
-
 #ifndef HAVE_CFS_SIZE_ROUND
 static inline size_t cfs_size_round(int val)
 {
-       return (val + 7) & (~0x7);
+       return round_up(val, 8);
 }
 
 #define HAVE_CFS_SIZE_ROUND
 #endif
 
-static inline size_t cfs_size_round16(int val)
-{
-       return (val + 0xf) & (~0xf);
-}
-
-static inline size_t cfs_size_round32(int val)
-{
-       return (val + 0x1f) & (~0x1f);
-}
-
-static inline size_t cfs_size_round0(int val)
-{
-       if (!val)
-               return 0;
-       return (val + 1 + 7) & (~0x7);
-}
-
-static inline size_t cfs_round_strlen(char *fset)
-{
-       return cfs_size_round((int)strlen(fset) + 1);
-}
-
 #endif
index 1191764c431a7bfc6a6588767e8c5431a2c0f35c..66463477074af51399595806ed5b02c5d5287cf0 100644 (file)
@@ -73,7 +73,6 @@ struct cfs_expr_list {
        struct list_head        el_exprs;
 };
 
-char *cfs_trimwhite(char *str);
 int cfs_gettok(struct cfs_lstr *next, char delim, struct cfs_lstr *res);
 int cfs_str2num_check(char *str, int nob, unsigned int *num,
                      unsigned int min, unsigned int max);
@@ -86,11 +85,11 @@ static inline void
 cfs_expr_list_values_free(u32 *values, int num)
 {
        /*
-        * This array is allocated by LIBCFS_ALLOC(), so it shouldn't be freed
+        * This array is allocated by kvalloc(), so it shouldn't be freed
         * by OBD_FREE() if it's called by module other than libcfs & LNet,
         * otherwise we will see fake memory leak
         */
-       LIBCFS_FREE(values, num * sizeof(values[0]));
+       kvfree(values);
 }
 
 void cfs_expr_list_free(struct cfs_expr_list *expr_list);
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_workitem.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_workitem.h
deleted file mode 100644 (file)
index fc780f6..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/include/libcfs/libcfs_workitem.h
- *
- * Author: Isaac Huang  <he.h.huang@oracle.com>
- *      Liang Zhen   <zhen.liang@sun.com>
- *
- * A workitems is deferred work with these semantics:
- * - a workitem always runs in thread context.
- * - a workitem can be concurrent with other workitems but is strictly
- *   serialized with respect to itself.
- * - no CPU affinity, a workitem does not necessarily run on the same CPU
- *   that schedules it. However, this might change in the future.
- * - if a workitem is scheduled again before it has a chance to run, it
- *   runs only once.
- * - if a workitem is scheduled while it runs, it runs again after it
- *   completes; this ensures that events occurring while other events are
- *   being processed receive due attention. This behavior also allows a
- *   workitem to reschedule itself.
- *
- * Usage notes:
- * - a workitem can sleep but it should be aware of how that sleep might
- *   affect others.
- * - a workitem runs inside a kernel thread so there's no user space to access.
- * - do not use a workitem if the scheduling latency can't be tolerated.
- *
- * When wi_action returns non-zero, it means the workitem has either been
- * freed or reused and workitem scheduler won't touch it any more.
- */
-
-#ifndef __LIBCFS_WORKITEM_H__
-#define __LIBCFS_WORKITEM_H__
-
-struct cfs_wi_sched;
-
-void cfs_wi_sched_destroy(struct cfs_wi_sched *sched);
-int cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab, int cpt,
-                       int nthrs, struct cfs_wi_sched **sched_pp);
-
-struct cfs_workitem;
-
-typedef int (*cfs_wi_action_t) (struct cfs_workitem *);
-struct cfs_workitem {
-       /** chain on runq or rerunq */
-       struct list_head       wi_list;
-       /** working function */
-       cfs_wi_action_t  wi_action;
-       /** arg for working function */
-       void        *wi_data;
-       /** in running */
-       unsigned short   wi_running:1;
-       /** scheduled */
-       unsigned short   wi_scheduled:1;
-};
-
-static inline void
-cfs_wi_init(struct cfs_workitem *wi, void *data, cfs_wi_action_t action)
-{
-       INIT_LIST_HEAD(&wi->wi_list);
-
-       wi->wi_running   = 0;
-       wi->wi_scheduled = 0;
-       wi->wi_data      = data;
-       wi->wi_action    = action;
-}
-
-void cfs_wi_schedule(struct cfs_wi_sched *sched, struct cfs_workitem *wi);
-int  cfs_wi_deschedule(struct cfs_wi_sched *sched, struct cfs_workitem *wi);
-void cfs_wi_exit(struct cfs_wi_sched *sched, struct cfs_workitem *wi);
-
-int  cfs_wi_startup(void);
-void cfs_wi_shutdown(void);
-
-/** # workitem scheduler loops before reschedule */
-#define CFS_WI_RESCHED    128
-
-#endif /* __LIBCFS_WORKITEM_H__ */
index 854c84358ab46e9f98fc4d4bc5751b7519dea455..6035376f28309905a7607fdca09a311392a6007e 100644 (file)
@@ -49,7 +49,7 @@
 /** virtual processing unit */
 struct cfs_cpu_partition {
        /* CPUs mask for this partition */
-       cpumask_t                       *cpt_cpumask;
+       cpumask_var_t                   cpt_cpumask;
        /* nodes mask for this partition */
        nodemask_t                      *cpt_nodemask;
        /* spread rotor for NUMA allocator */
@@ -69,7 +69,7 @@ struct cfs_cpt_table {
        /* shadow HW CPU to CPU partition ID */
        int                             *ctb_cpu2cpt;
        /* all cpus in this partition table */
-       cpumask_t                       *ctb_cpumask;
+       cpumask_var_t                   ctb_cpumask;
        /* all nodes in this partition table */
        nodemask_t                      *ctb_nodemask;
 };
index c1626726fa05517e787a5275887cecae53d6001e..df4c72507a15cddc77d32ea4fcb4ac0264ec223f 100644 (file)
@@ -181,21 +181,6 @@ lnet_net_lock_current(void)
 
 #define MAX_PORTALS            64
 
-static inline struct lnet_eq *
-lnet_eq_alloc(void)
-{
-       struct lnet_eq *eq;
-
-       LIBCFS_ALLOC(eq, sizeof(*eq));
-       return eq;
-}
-
-static inline void
-lnet_eq_free(struct lnet_eq *eq)
-{
-       LIBCFS_FREE(eq, sizeof(*eq));
-}
-
 static inline struct lnet_libmd *
 lnet_md_alloc(struct lnet_md *umd)
 {
@@ -211,7 +196,7 @@ lnet_md_alloc(struct lnet_md *umd)
                size = offsetof(struct lnet_libmd, md_iov.iov[niov]);
        }
 
-       LIBCFS_ALLOC(md, size);
+       md = kzalloc(size, GFP_NOFS);
 
        if (md) {
                /* Set here in case of early free */
@@ -223,52 +208,6 @@ lnet_md_alloc(struct lnet_md *umd)
        return md;
 }
 
-static inline void
-lnet_md_free(struct lnet_libmd *md)
-{
-       unsigned int size;
-
-       if (md->md_options & LNET_MD_KIOV)
-               size = offsetof(struct lnet_libmd, md_iov.kiov[md->md_niov]);
-       else
-               size = offsetof(struct lnet_libmd, md_iov.iov[md->md_niov]);
-
-       LIBCFS_FREE(md, size);
-}
-
-static inline struct lnet_me *
-lnet_me_alloc(void)
-{
-       struct lnet_me *me;
-
-       LIBCFS_ALLOC(me, sizeof(*me));
-       return me;
-}
-
-static inline void
-lnet_me_free(struct lnet_me *me)
-{
-       LIBCFS_FREE(me, sizeof(*me));
-}
-
-static inline struct lnet_msg *
-lnet_msg_alloc(void)
-{
-       struct lnet_msg *msg;
-
-       LIBCFS_ALLOC(msg, sizeof(*msg));
-
-       /* no need to zero, LIBCFS_ALLOC does for us */
-       return msg;
-}
-
-static inline void
-lnet_msg_free(struct lnet_msg *msg)
-{
-       LASSERT(!msg->msg_onactivelist);
-       LIBCFS_FREE(msg, sizeof(*msg));
-}
-
 struct lnet_libhandle *lnet_res_lh_lookup(struct lnet_res_container *rec,
                                          __u64 cookie);
 void lnet_res_lh_initialize(struct lnet_res_container *rec,
index 8024843521ab431e8b8c72151d670573e61602d8..ec84edfda2719a7542d496eae51857a6cd5edddf 100644 (file)
@@ -325,7 +325,7 @@ int kiblnd_create_peer(struct lnet_ni *ni, struct kib_peer **peerp,
        LASSERT(net);
        LASSERT(nid != LNET_NID_ANY);
 
-       LIBCFS_CPT_ALLOC(peer, lnet_cpt_table(), cpt, sizeof(*peer));
+       peer = kzalloc_cpt(sizeof(*peer), GFP_NOFS, cpt);
        if (!peer) {
                CERROR("Cannot allocate peer\n");
                return -ENOMEM;
@@ -367,7 +367,7 @@ void kiblnd_destroy_peer(struct kib_peer *peer)
        LASSERT(kiblnd_peer_idle(peer));
        LASSERT(list_empty(&peer->ibp_tx_queue));
 
-       LIBCFS_FREE(peer, sizeof(*peer));
+       kfree(peer);
 
        /*
         * NB a peer's connections keep a reference on their peer until
@@ -596,7 +596,7 @@ static void kiblnd_setup_mtu_locked(struct rdma_cm_id *cmid)
 
 static int kiblnd_get_completion_vector(struct kib_conn *conn, int cpt)
 {
-       cpumask_t *mask;
+       cpumask_var_t *mask;
        int vectors;
        int off;
        int i;
@@ -611,8 +611,8 @@ static int kiblnd_get_completion_vector(struct kib_conn *conn, int cpt)
                return 0;
 
        /* hash NID to CPU id in this partition... */
-       off = do_div(nid, cpumask_weight(mask));
-       for_each_cpu(i, mask) {
+       off = do_div(nid, cpumask_weight(*mask));
+       for_each_cpu(i, *mask) {
                if (!off--)
                        return i % vectors;
        }
@@ -656,15 +656,14 @@ struct kib_conn *kiblnd_create_conn(struct kib_peer *peer, struct rdma_cm_id *cm
 
        LASSERT(sched->ibs_nthreads > 0);
 
-       LIBCFS_CPT_ALLOC(init_qp_attr, lnet_cpt_table(), cpt,
-                        sizeof(*init_qp_attr));
+       init_qp_attr = kzalloc_cpt(sizeof(*init_qp_attr), GFP_NOFS, cpt);
        if (!init_qp_attr) {
                CERROR("Can't allocate qp_attr for %s\n",
                       libcfs_nid2str(peer->ibp_nid));
                goto failed_0;
        }
 
-       LIBCFS_CPT_ALLOC(conn, lnet_cpt_table(), cpt, sizeof(*conn));
+       conn = kzalloc_cpt(sizeof(*conn), GFP_NOFS, cpt);
        if (!conn) {
                CERROR("Can't allocate connection for %s\n",
                       libcfs_nid2str(peer->ibp_nid));
@@ -687,8 +686,7 @@ struct kib_conn *kiblnd_create_conn(struct kib_peer *peer, struct rdma_cm_id *cm
        INIT_LIST_HEAD(&conn->ibc_active_txs);
        spin_lock_init(&conn->ibc_lock);
 
-       LIBCFS_CPT_ALLOC(conn->ibc_connvars, lnet_cpt_table(), cpt,
-                        sizeof(*conn->ibc_connvars));
+       conn->ibc_connvars = kzalloc_cpt(sizeof(*conn->ibc_connvars), GFP_NOFS, cpt);
        if (!conn->ibc_connvars) {
                CERROR("Can't allocate in-progress connection state\n");
                goto failed_2;
@@ -722,8 +720,8 @@ struct kib_conn *kiblnd_create_conn(struct kib_peer *peer, struct rdma_cm_id *cm
 
        write_unlock_irqrestore(glock, flags);
 
-       LIBCFS_CPT_ALLOC(conn->ibc_rxs, lnet_cpt_table(), cpt,
-                        IBLND_RX_MSGS(conn) * sizeof(struct kib_rx));
+       conn->ibc_rxs = kzalloc_cpt(IBLND_RX_MSGS(conn) * sizeof(struct kib_rx),
+                                   GFP_NOFS, cpt);
        if (!conn->ibc_rxs) {
                CERROR("Cannot allocate RX buffers\n");
                goto failed_2;
@@ -776,7 +774,7 @@ struct kib_conn *kiblnd_create_conn(struct kib_peer *peer, struct rdma_cm_id *cm
                goto failed_2;
        }
 
-       LIBCFS_FREE(init_qp_attr, sizeof(*init_qp_attr));
+       kfree(init_qp_attr);
 
        /* 1 ref for caller and each rxmsg */
        atomic_set(&conn->ibc_refcount, 1 + IBLND_RX_MSGS(conn));
@@ -826,14 +824,15 @@ struct kib_conn *kiblnd_create_conn(struct kib_peer *peer, struct rdma_cm_id *cm
        return conn;
 
  failed_2:
-       kiblnd_destroy_conn(conn, true);
+       kiblnd_destroy_conn(conn);
+       kfree(conn);
  failed_1:
-       LIBCFS_FREE(init_qp_attr, sizeof(*init_qp_attr));
+       kfree(init_qp_attr);
  failed_0:
        return NULL;
 }
 
-void kiblnd_destroy_conn(struct kib_conn *conn, bool free_conn)
+void kiblnd_destroy_conn(struct kib_conn *conn)
 {
        struct rdma_cm_id *cmid = conn->ibc_cmid;
        struct kib_peer *peer = conn->ibc_peer;
@@ -877,13 +876,8 @@ void kiblnd_destroy_conn(struct kib_conn *conn, bool free_conn)
        if (conn->ibc_rx_pages)
                kiblnd_unmap_rx_descs(conn);
 
-       if (conn->ibc_rxs) {
-               LIBCFS_FREE(conn->ibc_rxs,
-                           IBLND_RX_MSGS(conn) * sizeof(struct kib_rx));
-       }
-
-       if (conn->ibc_connvars)
-               LIBCFS_FREE(conn->ibc_connvars, sizeof(*conn->ibc_connvars));
+       kfree(conn->ibc_rxs);
+       kfree(conn->ibc_connvars);
 
        if (conn->ibc_hdev)
                kiblnd_hdev_decref(conn->ibc_hdev);
@@ -896,8 +890,6 @@ void kiblnd_destroy_conn(struct kib_conn *conn, bool free_conn)
                rdma_destroy_id(cmid);
                atomic_dec(&net->ibn_nconns);
        }
-
-       LIBCFS_FREE(conn, sizeof(*conn));
 }
 
 int kiblnd_close_peer_conns_locked(struct kib_peer *peer, int why)
@@ -1089,7 +1081,7 @@ static void kiblnd_free_pages(struct kib_pages *p)
                        __free_page(p->ibp_pages[i]);
        }
 
-       LIBCFS_FREE(p, offsetof(struct kib_pages, ibp_pages[npages]));
+       kfree(p);
 }
 
 int kiblnd_alloc_pages(struct kib_pages **pp, int cpt, int npages)
@@ -1097,14 +1089,13 @@ int kiblnd_alloc_pages(struct kib_pages **pp, int cpt, int npages)
        struct kib_pages *p;
        int i;
 
-       LIBCFS_CPT_ALLOC(p, lnet_cpt_table(), cpt,
-                        offsetof(struct kib_pages, ibp_pages[npages]));
+       p = kzalloc_cpt(offsetof(struct kib_pages, ibp_pages[npages]),
+                       GFP_NOFS, cpt);
        if (!p) {
                CERROR("Can't allocate descriptor for %d pages\n", npages);
                return -ENOMEM;
        }
 
-       memset(p, 0, offsetof(struct kib_pages, ibp_pages[npages]));
        p->ibp_npages = npages;
 
        for (i = 0; i < npages; i++) {
@@ -1299,7 +1290,7 @@ static void kiblnd_destroy_fmr_pool(struct kib_fmr_pool *fpo)
                                         frd_list) {
                        list_del(&frd->frd_list);
                        ib_dereg_mr(frd->frd_mr);
-                       LIBCFS_FREE(frd, sizeof(*frd));
+                       kfree(frd);
                        i++;
                }
                if (i < fpo->fast_reg.fpo_pool_size)
@@ -1310,7 +1301,7 @@ static void kiblnd_destroy_fmr_pool(struct kib_fmr_pool *fpo)
        if (fpo->fpo_hdev)
                kiblnd_hdev_decref(fpo->fpo_hdev);
 
-       LIBCFS_FREE(fpo, sizeof(*fpo));
+       kfree(fpo);
 }
 
 static void kiblnd_destroy_fmr_pool_list(struct list_head *head)
@@ -1376,8 +1367,7 @@ static int kiblnd_alloc_freg_pool(struct kib_fmr_poolset *fps, struct kib_fmr_po
        INIT_LIST_HEAD(&fpo->fast_reg.fpo_pool_list);
        fpo->fast_reg.fpo_pool_size = 0;
        for (i = 0; i < fps->fps_pool_size; i++) {
-               LIBCFS_CPT_ALLOC(frd, lnet_cpt_table(), fps->fps_cpt,
-                                sizeof(*frd));
+               frd = kzalloc_cpt(sizeof(*frd), GFP_NOFS, fps->fps_cpt);
                if (!frd) {
                        CERROR("Failed to allocate a new fast_reg descriptor\n");
                        rc = -ENOMEM;
@@ -1405,14 +1395,14 @@ static int kiblnd_alloc_freg_pool(struct kib_fmr_poolset *fps, struct kib_fmr_po
 out_middle:
        if (frd->frd_mr)
                ib_dereg_mr(frd->frd_mr);
-       LIBCFS_FREE(frd, sizeof(*frd));
+       kfree(frd);
 
 out:
        list_for_each_entry_safe(frd, tmp, &fpo->fast_reg.fpo_pool_list,
                                 frd_list) {
                list_del(&frd->frd_list);
                ib_dereg_mr(frd->frd_mr);
-               LIBCFS_FREE(frd, sizeof(*frd));
+               kfree(frd);
        }
 
        return rc;
@@ -1426,7 +1416,7 @@ static int kiblnd_create_fmr_pool(struct kib_fmr_poolset *fps,
        struct kib_fmr_pool *fpo;
        int rc;
 
-       LIBCFS_CPT_ALLOC(fpo, lnet_cpt_table(), fps->fps_cpt, sizeof(*fpo));
+       fpo = kzalloc_cpt(sizeof(*fpo), GFP_NOFS, fps->fps_cpt);
        if (!fpo)
                return -ENOMEM;
 
@@ -1464,7 +1454,7 @@ static int kiblnd_create_fmr_pool(struct kib_fmr_poolset *fps,
 
 out_fpo:
        kiblnd_hdev_decref(fpo->fpo_hdev);
-       LIBCFS_FREE(fpo, sizeof(*fpo));
+       kfree(fpo);
        return rc;
 }
 
@@ -1985,33 +1975,17 @@ static void kiblnd_destroy_tx_pool(struct kib_pool *pool)
                struct kib_tx *tx = &tpo->tpo_tx_descs[i];
 
                list_del(&tx->tx_list);
-               if (tx->tx_pages)
-                       LIBCFS_FREE(tx->tx_pages,
-                                   LNET_MAX_IOV *
-                                   sizeof(*tx->tx_pages));
-               if (tx->tx_frags)
-                       LIBCFS_FREE(tx->tx_frags,
-                                   (1 + IBLND_MAX_RDMA_FRAGS) *
-                                    sizeof(*tx->tx_frags));
-               if (tx->tx_wrq)
-                       LIBCFS_FREE(tx->tx_wrq,
-                                   (1 + IBLND_MAX_RDMA_FRAGS) *
-                                   sizeof(*tx->tx_wrq));
-               if (tx->tx_sge)
-                       LIBCFS_FREE(tx->tx_sge,
-                                   (1 + IBLND_MAX_RDMA_FRAGS) *
-                                   sizeof(*tx->tx_sge));
-               if (tx->tx_rd)
-                       LIBCFS_FREE(tx->tx_rd,
-                                   offsetof(struct kib_rdma_desc,
-                                            rd_frags[IBLND_MAX_RDMA_FRAGS]));
-       }
-
-       LIBCFS_FREE(tpo->tpo_tx_descs,
-                   pool->po_size * sizeof(struct kib_tx));
+               kfree(tx->tx_pages);
+               kfree(tx->tx_frags);
+               kfree(tx->tx_wrq);
+               kfree(tx->tx_sge);
+               kfree(tx->tx_rd);
+       }
+
+       kfree(tpo->tpo_tx_descs);
 out:
        kiblnd_fini_pool(pool);
-       LIBCFS_FREE(tpo, sizeof(*tpo));
+       kfree(tpo);
 }
 
 static int kiblnd_tx_pool_size(int ncpts)
@@ -2029,7 +2003,7 @@ static int kiblnd_create_tx_pool(struct kib_poolset *ps, int size,
        struct kib_pool *pool;
        struct kib_tx_pool *tpo;
 
-       LIBCFS_CPT_ALLOC(tpo, lnet_cpt_table(), ps->ps_cpt, sizeof(*tpo));
+       tpo = kzalloc_cpt(sizeof(*tpo), GFP_NOFS, ps->ps_cpt);
        if (!tpo) {
                CERROR("Failed to allocate TX pool\n");
                return -ENOMEM;
@@ -2043,12 +2017,12 @@ static int kiblnd_create_tx_pool(struct kib_poolset *ps, int size,
        npg = DIV_ROUND_UP(size * IBLND_MSG_SIZE, PAGE_SIZE);
        if (kiblnd_alloc_pages(&tpo->tpo_tx_pages, ps->ps_cpt, npg)) {
                CERROR("Can't allocate tx pages: %d\n", npg);
-               LIBCFS_FREE(tpo, sizeof(*tpo));
+               kfree(tpo);
                return -ENOMEM;
        }
 
-       LIBCFS_CPT_ALLOC(tpo->tpo_tx_descs, lnet_cpt_table(), ps->ps_cpt,
-                        size * sizeof(struct kib_tx));
+       tpo->tpo_tx_descs = kzalloc_cpt(size * sizeof(struct kib_tx),
+                                       GFP_NOFS, ps->ps_cpt);
        if (!tpo->tpo_tx_descs) {
                CERROR("Can't allocate %d tx descriptors\n", size);
                ps->ps_pool_destroy(pool);
@@ -2062,36 +2036,35 @@ static int kiblnd_create_tx_pool(struct kib_poolset *ps, int size,
 
                tx->tx_pool = tpo;
                if (ps->ps_net->ibn_fmr_ps) {
-                       LIBCFS_CPT_ALLOC(tx->tx_pages,
-                                        lnet_cpt_table(), ps->ps_cpt,
-                                        LNET_MAX_IOV * sizeof(*tx->tx_pages));
+                       tx->tx_pages = kzalloc_cpt(LNET_MAX_IOV * sizeof(*tx->tx_pages),
+                                                  GFP_NOFS, ps->ps_cpt);
                        if (!tx->tx_pages)
                                break;
                }
 
-               LIBCFS_CPT_ALLOC(tx->tx_frags, lnet_cpt_table(), ps->ps_cpt,
-                                (1 + IBLND_MAX_RDMA_FRAGS) *
-                                sizeof(*tx->tx_frags));
+               tx->tx_frags = kzalloc_cpt((1 + IBLND_MAX_RDMA_FRAGS) *
+                                          sizeof(*tx->tx_frags),
+                                          GFP_NOFS, ps->ps_cpt);
                if (!tx->tx_frags)
                        break;
 
                sg_init_table(tx->tx_frags, IBLND_MAX_RDMA_FRAGS + 1);
 
-               LIBCFS_CPT_ALLOC(tx->tx_wrq, lnet_cpt_table(), ps->ps_cpt,
-                                (1 + IBLND_MAX_RDMA_FRAGS) *
-                                sizeof(*tx->tx_wrq));
+               tx->tx_wrq = kzalloc_cpt((1 + IBLND_MAX_RDMA_FRAGS) *
+                                        sizeof(*tx->tx_wrq),
+                                        GFP_NOFS, ps->ps_cpt);
                if (!tx->tx_wrq)
                        break;
 
-               LIBCFS_CPT_ALLOC(tx->tx_sge, lnet_cpt_table(), ps->ps_cpt,
-                                (1 + IBLND_MAX_RDMA_FRAGS) *
-                                sizeof(*tx->tx_sge));
+               tx->tx_sge = kzalloc_cpt((1 + IBLND_MAX_RDMA_FRAGS) *
+                                        sizeof(*tx->tx_sge),
+                                        GFP_NOFS, ps->ps_cpt);
                if (!tx->tx_sge)
                        break;
 
-               LIBCFS_CPT_ALLOC(tx->tx_rd, lnet_cpt_table(), ps->ps_cpt,
-                                offsetof(struct kib_rdma_desc,
-                                         rd_frags[IBLND_MAX_RDMA_FRAGS]));
+               tx->tx_rd = kzalloc_cpt(offsetof(struct kib_rdma_desc,
+                                                rd_frags[IBLND_MAX_RDMA_FRAGS]),
+                                       GFP_NOFS, ps->ps_cpt);
                if (!tx->tx_rd)
                        break;
        }
@@ -2263,7 +2236,7 @@ void kiblnd_hdev_destroy(struct kib_hca_dev *hdev)
        if (hdev->ibh_cmid)
                rdma_destroy_id(hdev->ibh_cmid);
 
-       LIBCFS_FREE(hdev, sizeof(*hdev));
+       kfree(hdev);
 }
 
 /* DUMMY */
@@ -2392,7 +2365,7 @@ int kiblnd_dev_failover(struct kib_dev *dev)
                goto out;
        }
 
-       LIBCFS_ALLOC(hdev, sizeof(*hdev));
+       hdev = kzalloc(sizeof(*hdev), GFP_NOFS);
        if (!hdev) {
                CERROR("Failed to allocate kib_hca_dev\n");
                rdma_destroy_id(cmid);
@@ -2471,7 +2444,7 @@ void kiblnd_destroy_dev(struct kib_dev *dev)
        if (dev->ibd_hdev)
                kiblnd_hdev_decref(dev->ibd_hdev);
 
-       LIBCFS_FREE(dev, sizeof(*dev));
+       kfree(dev);
 }
 
 static struct kib_dev *kiblnd_create_dev(char *ifname)
@@ -2495,7 +2468,7 @@ static struct kib_dev *kiblnd_create_dev(char *ifname)
                return NULL;
        }
 
-       LIBCFS_ALLOC(dev, sizeof(*dev));
+       dev = kzalloc(sizeof(*dev), GFP_NOFS);
        if (!dev)
                return NULL;
 
@@ -2517,7 +2490,7 @@ static struct kib_dev *kiblnd_create_dev(char *ifname)
        rc = kiblnd_dev_failover(dev);
        if (rc) {
                CERROR("Can't initialize device: %d\n", rc);
-               LIBCFS_FREE(dev, sizeof(*dev));
+               kfree(dev);
                return NULL;
        }
 
@@ -2577,11 +2550,7 @@ static void kiblnd_base_shutdown(void)
                break;
        }
 
-       if (kiblnd_data.kib_peers) {
-               LIBCFS_FREE(kiblnd_data.kib_peers,
-                           sizeof(struct list_head) *
-                           kiblnd_data.kib_peer_hash_size);
-       }
+       kvfree(kiblnd_data.kib_peers);
 
        if (kiblnd_data.kib_scheds)
                cfs_percpt_free(kiblnd_data.kib_scheds);
@@ -2648,7 +2617,7 @@ static void kiblnd_shutdown(struct lnet_ni *ni)
        net->ibn_init = IBLND_INIT_NOTHING;
        ni->ni_data = NULL;
 
-       LIBCFS_FREE(net, sizeof(*net));
+       kfree(net);
 
 out:
        if (list_empty(&kiblnd_data.kib_devs))
@@ -2673,8 +2642,9 @@ static int kiblnd_base_startup(void)
        INIT_LIST_HEAD(&kiblnd_data.kib_failed_devs);
 
        kiblnd_data.kib_peer_hash_size = IBLND_PEER_HASH_SIZE;
-       LIBCFS_ALLOC(kiblnd_data.kib_peers,
-                    sizeof(struct list_head) * kiblnd_data.kib_peer_hash_size);
+       kiblnd_data.kib_peers = kvmalloc_array(kiblnd_data.kib_peer_hash_size,
+                                              sizeof(struct list_head),
+                                              GFP_KERNEL);
        if (!kiblnd_data.kib_peers)
                goto failed;
        for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++)
@@ -2865,7 +2835,7 @@ static int kiblnd_startup(struct lnet_ni *ni)
                        return rc;
        }
 
-       LIBCFS_ALLOC(net, sizeof(*net));
+       net = kzalloc(sizeof(*net), GFP_NOFS);
        ni->ni_data = net;
        if (!net)
                goto net_failed;
index 171eced213f85ce479c337cfb746baa3f972d0cd..b18911d09e9a0bbdae0639e7848e631f0f1efc25 100644 (file)
@@ -1016,7 +1016,7 @@ int  kiblnd_close_peer_conns_locked(struct kib_peer *peer, int why);
 struct kib_conn *kiblnd_create_conn(struct kib_peer *peer,
                                    struct rdma_cm_id *cmid,
                                    int state, int version);
-void kiblnd_destroy_conn(struct kib_conn *conn, bool free_conn);
+void kiblnd_destroy_conn(struct kib_conn *conn);
 void kiblnd_close_conn(struct kib_conn *conn, int error);
 void kiblnd_close_conn_locked(struct kib_conn *conn, int error);
 
index 40e3af5d8b0484dcc48d2c2755359b529c3be133..b3e7f28eb978b28f9b52d8e1352f1b826744b961 100644 (file)
@@ -2124,7 +2124,7 @@ kiblnd_connreq_done(struct kib_conn *conn, int status)
                 (conn->ibc_state == IBLND_CONN_PASSIVE_WAIT &&
                 peer->ibp_accepting > 0));
 
-       LIBCFS_FREE(conn->ibc_connvars, sizeof(*conn->ibc_connvars));
+       kfree(conn->ibc_connvars);
        conn->ibc_connvars = NULL;
 
        if (status) {
@@ -3314,11 +3314,13 @@ kiblnd_connd(void *arg)
                        spin_unlock_irqrestore(lock, flags);
                        dropped_lock = 1;
 
-                       kiblnd_destroy_conn(conn, !peer);
+                       kiblnd_destroy_conn(conn);
 
                        spin_lock_irqsave(lock, flags);
-                       if (!peer)
+                       if (!peer) {
+                               kfree(conn);
                                continue;
+                       }
 
                        conn->ibc_peer = peer;
                        if (peer->ibp_reconnected < KIB_RECONN_HIGH_RACE)
@@ -3363,7 +3365,7 @@ kiblnd_connd(void *arg)
 
                        reconn += kiblnd_reconnect_peer(conn->ibc_peer);
                        kiblnd_peer_decref(conn->ibc_peer);
-                       LIBCFS_FREE(conn, sizeof(*conn));
+                       kfree(conn);
 
                        spin_lock_irqsave(lock, flags);
                }
index a71b765215ade042f77b15e88e5a836303843443..b9235400bf1d2431a836ba1b6fe5348d1ed96ec3 100644 (file)
@@ -181,8 +181,8 @@ int kiblnd_tunables_setup(struct lnet_ni *ni)
         * defaulted
         */
        if (!ni->ni_lnd_tunables) {
-               LIBCFS_ALLOC(ni->ni_lnd_tunables,
-                            sizeof(*ni->ni_lnd_tunables));
+               ni->ni_lnd_tunables = kzalloc(sizeof(*ni->ni_lnd_tunables),
+                                             GFP_NOFS);
                if (!ni->ni_lnd_tunables)
                        return -ENOMEM;
 
index 8267119ccc8e73108bc8e4f2edb777861192f353..ff292216290d1ea451bdf411ed5f617606938de6 100644 (file)
@@ -66,7 +66,7 @@ ksocknal_create_route(__u32 ipaddr, int port)
 {
        struct ksock_route *route;
 
-       LIBCFS_ALLOC(route, sizeof(*route));
+       route = kzalloc(sizeof(*route), GFP_NOFS);
        if (!route)
                return NULL;
 
@@ -93,7 +93,7 @@ ksocknal_destroy_route(struct ksock_route *route)
        if (route->ksnr_peer)
                ksocknal_peer_decref(route->ksnr_peer);
 
-       LIBCFS_FREE(route, sizeof(*route));
+       kfree(route);
 }
 
 static int
@@ -108,7 +108,7 @@ ksocknal_create_peer(struct ksock_peer **peerp, struct lnet_ni *ni,
        LASSERT(id.pid != LNET_PID_ANY);
        LASSERT(!in_interrupt());
 
-       LIBCFS_CPT_ALLOC(peer, lnet_cpt_table(), cpt, sizeof(*peer));
+       peer = kzalloc_cpt(sizeof(*peer), GFP_NOFS, cpt);
        if (!peer)
                return -ENOMEM;
 
@@ -132,7 +132,7 @@ ksocknal_create_peer(struct ksock_peer **peerp, struct lnet_ni *ni,
        if (net->ksnn_shutdown) {
                spin_unlock_bh(&net->ksnn_lock);
 
-               LIBCFS_FREE(peer, sizeof(*peer));
+               kfree(peer);
                CERROR("Can't create peer: network shutdown\n");
                return -ESHUTDOWN;
        }
@@ -160,7 +160,7 @@ ksocknal_destroy_peer(struct ksock_peer *peer)
        LASSERT(list_empty(&peer->ksnp_tx_queue));
        LASSERT(list_empty(&peer->ksnp_zc_req_list));
 
-       LIBCFS_FREE(peer, sizeof(*peer));
+       kfree(peer);
 
        /*
         * NB a peer's connections and routes keep a reference on their peer
@@ -985,7 +985,7 @@ ksocknal_accept(struct lnet_ni *ni, struct socket *sock)
        rc = lnet_sock_getaddr(sock, 1, &peer_ip, &peer_port);
        LASSERT(!rc);                 /* we succeeded before */
 
-       LIBCFS_ALLOC(cr, sizeof(*cr));
+       cr = kzalloc(sizeof(*cr), GFP_NOFS);
        if (!cr) {
                LCONSOLE_ERROR_MSG(0x12f, "Dropping connection request from %pI4h: memory exhausted\n",
                                   &peer_ip);
@@ -1043,7 +1043,7 @@ ksocknal_create_conn(struct lnet_ni *ni, struct ksock_route *route,
 
        LASSERT(active == (type != SOCKLND_CONN_NONE));
 
-       LIBCFS_ALLOC(conn, sizeof(*conn));
+       conn = kzalloc(sizeof(*conn), GFP_NOFS);
        if (!conn) {
                rc = -ENOMEM;
                goto failed_0;
@@ -1070,8 +1070,9 @@ ksocknal_create_conn(struct lnet_ni *ni, struct ksock_route *route,
        conn->ksnc_tx_carrier = NULL;
        atomic_set(&conn->ksnc_tx_nob, 0);
 
-       LIBCFS_ALLOC(hello, offsetof(struct ksock_hello_msg,
-                                    kshm_ips[LNET_MAX_INTERFACES]));
+       hello = kvzalloc(offsetof(struct ksock_hello_msg,
+                                 kshm_ips[LNET_MAX_INTERFACES]),
+                        GFP_KERNEL);
        if (!hello) {
                rc = -ENOMEM;
                goto failed_1;
@@ -1334,8 +1335,7 @@ ksocknal_create_conn(struct lnet_ni *ni, struct ksock_route *route,
                rc = ksocknal_send_hello(ni, conn, peerid.nid, hello);
        }
 
-       LIBCFS_FREE(hello, offsetof(struct ksock_hello_msg,
-                                   kshm_ips[LNET_MAX_INTERFACES]));
+       kvfree(hello);
 
        /*
         * setup the socket AFTER I've received hello (it disables
@@ -1415,11 +1415,9 @@ ksocknal_create_conn(struct lnet_ni *ni, struct ksock_route *route,
        ksocknal_peer_decref(peer);
 
 failed_1:
-       if (hello)
-               LIBCFS_FREE(hello, offsetof(struct ksock_hello_msg,
-                                           kshm_ips[LNET_MAX_INTERFACES]));
+       kvfree(hello);
 
-       LIBCFS_FREE(conn, sizeof(*conn));
+       kfree(conn);
 
 failed_0:
        sock_release(sock);
@@ -1716,7 +1714,7 @@ ksocknal_destroy_conn(struct ksock_conn *conn)
 
        ksocknal_peer_decref(conn->ksnc_peer);
 
-       LIBCFS_FREE(conn, sizeof(*conn));
+       kfree(conn);
 }
 
 int
@@ -2259,19 +2257,12 @@ ksocknal_free_buffers(void)
                struct ksock_sched_info *info;
                int i;
 
-               cfs_percpt_for_each(info, i, ksocknal_data.ksnd_sched_info) {
-                       if (info->ksi_scheds) {
-                               LIBCFS_FREE(info->ksi_scheds,
-                                           info->ksi_nthreads_max *
-                                           sizeof(info->ksi_scheds[0]));
-                       }
-               }
+               cfs_percpt_for_each(info, i, ksocknal_data.ksnd_sched_info)
+                       kfree(info->ksi_scheds);
                cfs_percpt_free(ksocknal_data.ksnd_sched_info);
        }
 
-       LIBCFS_FREE(ksocknal_data.ksnd_peers,
-                   sizeof(struct list_head) *
-                   ksocknal_data.ksnd_peer_hash_size);
+       kvfree(ksocknal_data.ksnd_peers);
 
        spin_lock(&ksocknal_data.ksnd_tx_lock);
 
@@ -2286,7 +2277,7 @@ ksocknal_free_buffers(void)
 
                list_for_each_entry_safe(tx, temp, &zlist, tx_list) {
                        list_del(&tx->tx_list);
-                       LIBCFS_FREE(tx, tx->tx_desc_size);
+                       kfree(tx);
                }
        } else {
                spin_unlock(&ksocknal_data.ksnd_tx_lock);
@@ -2401,9 +2392,9 @@ ksocknal_base_startup(void)
        memset(&ksocknal_data, 0, sizeof(ksocknal_data)); /* zero pointers */
 
        ksocknal_data.ksnd_peer_hash_size = SOCKNAL_PEER_HASH_SIZE;
-       LIBCFS_ALLOC(ksocknal_data.ksnd_peers,
-                    sizeof(struct list_head) *
-                    ksocknal_data.ksnd_peer_hash_size);
+       ksocknal_data.ksnd_peers = kvmalloc_array(ksocknal_data.ksnd_peer_hash_size,
+                                                 sizeof(struct list_head),
+                                                 GFP_KERNEL);
        if (!ksocknal_data.ksnd_peers)
                return -ENOMEM;
 
@@ -2456,8 +2447,8 @@ ksocknal_base_startup(void)
                info->ksi_nthreads_max = nthrs;
                info->ksi_cpt = i;
 
-               LIBCFS_CPT_ALLOC(info->ksi_scheds, lnet_cpt_table(), i,
-                                info->ksi_nthreads_max * sizeof(*sched));
+               info->ksi_scheds = kzalloc_cpt(info->ksi_nthreads_max * sizeof(*sched),
+                                              GFP_NOFS, i);
                if (!info->ksi_scheds)
                        goto failed;
 
@@ -2622,7 +2613,7 @@ ksocknal_shutdown(struct lnet_ni *ni)
        }
 
        list_del(&net->ksnn_list);
-       LIBCFS_FREE(net, sizeof(*net));
+       kfree(net);
 
        ksocknal_data.ksnd_nnets--;
        if (!ksocknal_data.ksnd_nnets)
@@ -2815,7 +2806,7 @@ ksocknal_startup(struct lnet_ni *ni)
                        return rc;
        }
 
-       LIBCFS_ALLOC(net, sizeof(*net));
+       net = kzalloc(sizeof(*net), GFP_NOFS);
        if (!net)
                goto fail_0;
 
@@ -2877,7 +2868,7 @@ ksocknal_startup(struct lnet_ni *ni)
        return 0;
 
  fail_1:
-       LIBCFS_FREE(net, sizeof(*net));
+       kfree(net);
  fail_0:
        if (!ksocknal_data.ksnd_nnets)
                ksocknal_base_shutdown();
index 27c56d5ae4e51c13eb4532f73d66548170a1318d..11fd3a36424fa30cd47567402fecfac1a1d784c7 100644 (file)
@@ -46,7 +46,7 @@ ksocknal_alloc_tx(int type, int size)
        }
 
        if (!tx)
-               LIBCFS_ALLOC(tx, size);
+               tx = kzalloc(size, GFP_NOFS);
 
        if (!tx)
                return NULL;
@@ -102,7 +102,7 @@ ksocknal_free_tx(struct ksock_tx *tx)
 
                spin_unlock(&ksocknal_data.ksnd_tx_lock);
        } else {
-               LIBCFS_FREE(tx, tx->tx_desc_size);
+               kfree(tx);
        }
 }
 
@@ -2117,7 +2117,7 @@ ksocknal_connd(void *arg)
                        ksocknal_create_conn(cr->ksncr_ni, NULL,
                                             cr->ksncr_sock, SOCKLND_CONN_NONE);
                        lnet_ni_decref(cr->ksncr_ni);
-                       LIBCFS_FREE(cr, sizeof(*cr));
+                       kfree(cr);
 
                        spin_lock_bh(connd_lock);
                }
index d827f770e831a1b72684f246f95d0d11d5d96126..05982dac781c0cf7146c8f4d640c219d806bd3e6 100644 (file)
@@ -467,7 +467,7 @@ ksocknal_send_hello_v1(struct ksock_conn *conn, struct ksock_hello_msg *hello)
 
        BUILD_BUG_ON(sizeof(struct lnet_magicversion) != offsetof(struct lnet_hdr, src_nid));
 
-       LIBCFS_ALLOC(hdr, sizeof(*hdr));
+       hdr = kzalloc(sizeof(*hdr), GFP_NOFS);
        if (!hdr) {
                CERROR("Can't allocate struct lnet_hdr\n");
                return -ENOMEM;
@@ -526,7 +526,7 @@ ksocknal_send_hello_v1(struct ksock_conn *conn, struct ksock_hello_msg *hello)
                        &conn->ksnc_ipaddr, conn->ksnc_port);
        }
 out:
-       LIBCFS_FREE(hdr, sizeof(*hdr));
+       kfree(hdr);
 
        return rc;
 }
@@ -582,7 +582,7 @@ ksocknal_recv_hello_v1(struct ksock_conn *conn, struct ksock_hello_msg *hello,
        int rc;
        int i;
 
-       LIBCFS_ALLOC(hdr, sizeof(*hdr));
+       hdr = kzalloc(sizeof(*hdr), GFP_NOFS);
        if (!hdr) {
                CERROR("Can't allocate struct lnet_hdr\n");
                return -ENOMEM;
@@ -644,7 +644,7 @@ ksocknal_recv_hello_v1(struct ksock_conn *conn, struct ksock_hello_msg *hello,
                }
        }
 out:
-       LIBCFS_FREE(hdr, sizeof(*hdr));
+       kfree(hdr);
 
        return rc;
 }
index 1607570ef8dea26747eeababa82e0e5f516601b9..730f2c675047ffd4507c1adc2863715585289fb5 100644 (file)
@@ -15,7 +15,7 @@ libcfs-linux-objs += linux-mem.o
 libcfs-linux-objs := $(addprefix linux/,$(libcfs-linux-objs))
 
 libcfs-all-objs := debug.o fail.o module.o tracefile.o \
-                  libcfs_string.o hash.o prng.o workitem.o \
+                  libcfs_string.o hash.o \
                   libcfs_cpu.o libcfs_mem.o libcfs_lock.o
 
 libcfs-objs := $(libcfs-linux-objs) $(libcfs-all-objs)
index 5d501beeb62235a101dd72e35a49986e38e071ca..39439b303d654a520cb126200e2b55fd5d127be1 100644 (file)
@@ -61,7 +61,7 @@ int __cfs_fail_check_set(u32 id, u32 value, int set)
 
        /* Fail 1/cfs_fail_val times */
        if (cfs_fail_loc & CFS_FAIL_RAND) {
-               if (cfs_fail_val < 2 || cfs_rand() % cfs_fail_val > 0)
+               if (cfs_fail_val < 2 || prandom_u32_max(cfs_fail_val) > 0)
                        return 0;
        }
 
index f4f67d2b301e4d4bf4529cc51b1826daf59c21f7..f7b3c9306456f43fc760b215109249e039bdd8a2 100644 (file)
@@ -114,7 +114,7 @@ module_param(warn_on_depth, uint, 0644);
 MODULE_PARM_DESC(warn_on_depth, "warning when hash depth is high.");
 #endif
 
-struct cfs_wi_sched *cfs_sched_rehash;
+struct workqueue_struct *cfs_rehash_wq;
 
 static inline void
 cfs_hash_nl_lock(union cfs_hash_lock *lock, int exclusive) {}
@@ -519,7 +519,7 @@ cfs_hash_bd_dep_record(struct cfs_hash *hs, struct cfs_hash_bd *bd, int dep_cur)
        hs->hs_dep_bits = hs->hs_cur_bits;
        spin_unlock(&hs->hs_dep_lock);
 
-       cfs_wi_schedule(cfs_sched_rehash, &hs->hs_dep_wi);
+       queue_work(cfs_rehash_wq, &hs->hs_dep_work);
 # endif
 }
 
@@ -864,12 +864,10 @@ cfs_hash_buckets_free(struct cfs_hash_bucket **buckets,
 {
        int i;
 
-       for (i = prev_size; i < size; i++) {
-               if (buckets[i])
-                       LIBCFS_FREE(buckets[i], bkt_size);
-       }
+       for (i = prev_size; i < size; i++)
+               kfree(buckets[i]);
 
-       LIBCFS_FREE(buckets, sizeof(buckets[0]) * size);
+       kvfree(buckets);
 }
 
 /*
@@ -889,7 +887,7 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts,
        if (old_bkts && old_size == new_size)
                return old_bkts;
 
-       LIBCFS_ALLOC(new_bkts, sizeof(new_bkts[0]) * new_size);
+       new_bkts = kvmalloc_array(new_size, sizeof(new_bkts[0]), GFP_KERNEL);
        if (!new_bkts)
                return NULL;
 
@@ -902,7 +900,7 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts,
                struct hlist_head *hhead;
                struct cfs_hash_bd bd;
 
-               LIBCFS_ALLOC(new_bkts[i], cfs_hash_bkt_size(hs));
+               new_bkts[i] = kzalloc(cfs_hash_bkt_size(hs), GFP_KERNEL);
                if (!new_bkts[i]) {
                        cfs_hash_buckets_free(new_bkts, cfs_hash_bkt_size(hs),
                                              old_size, new_size);
@@ -939,12 +937,12 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts,
  * @flags    - CFS_HASH_REHASH enable synamic hash resizing
  *          - CFS_HASH_SORT enable chained hash sort
  */
-static int cfs_hash_rehash_worker(struct cfs_workitem *wi);
+static void cfs_hash_rehash_worker(struct work_struct *work);
 
 #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1
-static int cfs_hash_dep_print(struct cfs_workitem *wi)
+static void cfs_hash_dep_print(struct work_struct *work)
 {
-       struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_dep_wi);
+       struct cfs_hash *hs = container_of(work, struct cfs_hash, hs_dep_work);
        int dep;
        int bkt;
        int off;
@@ -968,21 +966,12 @@ static int cfs_hash_dep_print(struct cfs_workitem *wi)
 static void cfs_hash_depth_wi_init(struct cfs_hash *hs)
 {
        spin_lock_init(&hs->hs_dep_lock);
-       cfs_wi_init(&hs->hs_dep_wi, hs, cfs_hash_dep_print);
+       INIT_WORK(&hs->hs_dep_work, cfs_hash_dep_print);
 }
 
 static void cfs_hash_depth_wi_cancel(struct cfs_hash *hs)
 {
-       if (cfs_wi_deschedule(cfs_sched_rehash, &hs->hs_dep_wi))
-               return;
-
-       spin_lock(&hs->hs_dep_lock);
-       while (hs->hs_dep_bits) {
-               spin_unlock(&hs->hs_dep_lock);
-               cond_resched();
-               spin_lock(&hs->hs_dep_lock);
-       }
-       spin_unlock(&hs->hs_dep_lock);
+       cancel_work_sync(&hs->hs_dep_work);
 }
 
 #else /* CFS_HASH_DEBUG_LEVEL < CFS_HASH_DEBUG_1 */
@@ -1023,7 +1012,7 @@ cfs_hash_create(char *name, unsigned int cur_bits, unsigned int max_bits,
 
        len = !(flags & CFS_HASH_BIGNAME) ?
              CFS_HASH_NAME_LEN : CFS_HASH_BIGNAME_LEN;
-       LIBCFS_ALLOC(hs, offsetof(struct cfs_hash, hs_name[len]));
+       hs = kzalloc(offsetof(struct cfs_hash, hs_name[len]), GFP_KERNEL);
        if (!hs)
                return NULL;
 
@@ -1044,7 +1033,7 @@ cfs_hash_create(char *name, unsigned int cur_bits, unsigned int max_bits,
        hs->hs_ops = ops;
        hs->hs_extra_bytes = extra_bytes;
        hs->hs_rehash_bits = 0;
-       cfs_wi_init(&hs->hs_rehash_wi, hs, cfs_hash_rehash_worker);
+       INIT_WORK(&hs->hs_rehash_work, cfs_hash_rehash_worker);
        cfs_hash_depth_wi_init(hs);
 
        if (cfs_hash_with_rehash(hs))
@@ -1055,7 +1044,7 @@ cfs_hash_create(char *name, unsigned int cur_bits, unsigned int max_bits,
        if (hs->hs_buckets)
                return hs;
 
-       LIBCFS_FREE(hs, offsetof(struct cfs_hash, hs_name[len]));
+       kfree(hs);
        return NULL;
 }
 EXPORT_SYMBOL(cfs_hash_create);
@@ -1118,7 +1107,7 @@ cfs_hash_destroy(struct cfs_hash *hs)
                              0, CFS_HASH_NBKT(hs));
        i = cfs_hash_with_bigname(hs) ?
            CFS_HASH_BIGNAME_LEN : CFS_HASH_NAME_LEN;
-       LIBCFS_FREE(hs, offsetof(struct cfs_hash, hs_name[i]));
+       kfree(hs);
 }
 
 struct cfs_hash *cfs_hash_getref(struct cfs_hash *hs)
@@ -1364,6 +1353,7 @@ cfs_hash_for_each_enter(struct cfs_hash *hs)
 
        cfs_hash_lock(hs, 1);
        hs->hs_iterators++;
+       cfs_hash_unlock(hs, 1);
 
        /* NB: iteration is mostly called by service thread,
         * we tend to cancel pending rehash-request, instead of
@@ -1371,8 +1361,7 @@ cfs_hash_for_each_enter(struct cfs_hash *hs)
         * after iteration
         */
        if (cfs_hash_is_rehashing(hs))
-               cfs_hash_rehash_cancel_locked(hs);
-       cfs_hash_unlock(hs, 1);
+               cfs_hash_rehash_cancel(hs);
 }
 
 static void
@@ -1773,43 +1762,14 @@ EXPORT_SYMBOL(cfs_hash_for_each_key);
  * this approach assumes a reasonably uniform hashing function.  The
  * theta thresholds for @hs are tunable via cfs_hash_set_theta().
  */
-void
-cfs_hash_rehash_cancel_locked(struct cfs_hash *hs)
-{
-       int i;
-
-       /* need hold cfs_hash_lock(hs, 1) */
-       LASSERT(cfs_hash_with_rehash(hs) &&
-               !cfs_hash_with_no_lock(hs));
-
-       if (!cfs_hash_is_rehashing(hs))
-               return;
-
-       if (cfs_wi_deschedule(cfs_sched_rehash, &hs->hs_rehash_wi)) {
-               hs->hs_rehash_bits = 0;
-               return;
-       }
-
-       for (i = 2; cfs_hash_is_rehashing(hs); i++) {
-               cfs_hash_unlock(hs, 1);
-               /* raise console warning while waiting too long */
-               CDEBUG(is_power_of_2(i >> 3) ? D_WARNING : D_INFO,
-                      "hash %s is still rehashing, rescheded %d\n",
-                      hs->hs_name, i - 1);
-               cond_resched();
-               cfs_hash_lock(hs, 1);
-       }
-}
-
 void
 cfs_hash_rehash_cancel(struct cfs_hash *hs)
 {
-       cfs_hash_lock(hs, 1);
-       cfs_hash_rehash_cancel_locked(hs);
-       cfs_hash_unlock(hs, 1);
+       LASSERT(cfs_hash_with_rehash(hs));
+       cancel_work_sync(&hs->hs_rehash_work);
 }
 
-int
+void
 cfs_hash_rehash(struct cfs_hash *hs, int do_rehash)
 {
        int rc;
@@ -1821,21 +1781,21 @@ cfs_hash_rehash(struct cfs_hash *hs, int do_rehash)
        rc = cfs_hash_rehash_bits(hs);
        if (rc <= 0) {
                cfs_hash_unlock(hs, 1);
-               return rc;
+               return;
        }
 
        hs->hs_rehash_bits = rc;
        if (!do_rehash) {
                /* launch and return */
-               cfs_wi_schedule(cfs_sched_rehash, &hs->hs_rehash_wi);
+               queue_work(cfs_rehash_wq, &hs->hs_rehash_work);
                cfs_hash_unlock(hs, 1);
-               return 0;
+               return;
        }
 
        /* rehash right now */
        cfs_hash_unlock(hs, 1);
 
-       return cfs_hash_rehash_worker(&hs->hs_rehash_wi);
+       cfs_hash_rehash_worker(&hs->hs_rehash_work);
 }
 
 static int
@@ -1869,10 +1829,10 @@ cfs_hash_rehash_bd(struct cfs_hash *hs, struct cfs_hash_bd *old)
        return c;
 }
 
-static int
-cfs_hash_rehash_worker(struct cfs_workitem *wi)
+static void
+cfs_hash_rehash_worker(struct work_struct *work)
 {
-       struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_rehash_wi);
+       struct cfs_hash *hs = container_of(work, struct cfs_hash, hs_rehash_work);
        struct cfs_hash_bucket **bkts;
        struct cfs_hash_bd bd;
        unsigned int old_size;
@@ -1956,8 +1916,6 @@ cfs_hash_rehash_worker(struct cfs_workitem *wi)
        hs->hs_cur_bits = hs->hs_rehash_bits;
 out:
        hs->hs_rehash_bits = 0;
-       if (rc == -ESRCH) /* never be scheduled again */
-               cfs_wi_exit(cfs_sched_rehash, wi);
        bsize = cfs_hash_bkt_size(hs);
        cfs_hash_unlock(hs, 1);
        /* can't refer to @hs anymore because it could be destroyed */
@@ -1965,8 +1923,6 @@ out:
                cfs_hash_buckets_free(bkts, bsize, new_size, old_size);
        if (rc)
                CDEBUG(D_INFO, "early quit of rehashing: %d\n", rc);
-       /* return 1 only if cfs_wi_exit is called */
-       return rc == -ESRCH;
 }
 
 /**
index e3a4c67a66b5e3152c54d2e43b386969385ed3f1..76291a350406de2918d94de945139148b4f93ac8 100644 (file)
@@ -51,7 +51,7 @@ cfs_cpt_table_alloc(unsigned int ncpt)
                return NULL;
        }
 
-       LIBCFS_ALLOC(cptab, sizeof(*cptab));
+       cptab = kzalloc(sizeof(*cptab), GFP_NOFS);
        if (cptab) {
                cptab->ctb_version = CFS_CPU_VERSION_MAGIC;
                node_set(0, cptab->ctb_nodemask);
@@ -67,7 +67,7 @@ cfs_cpt_table_free(struct cfs_cpt_table *cptab)
 {
        LASSERT(cptab->ctb_version == CFS_CPU_VERSION_MAGIC);
 
-       LIBCFS_FREE(cptab, sizeof(*cptab));
+       kfree(cptab);
 }
 EXPORT_SYMBOL(cfs_cpt_table_free);
 
@@ -113,7 +113,7 @@ cfs_cpt_nodemask(struct cfs_cpt_table *cptab, int cpt)
 {
        return &cptab->ctb_nodemask;
 }
-EXPORT_SYMBOL(cfs_cpt_cpumask);
+EXPORT_SYMBOL(cfs_cpt_nodemask);
 
 int
 cfs_cpt_set_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
index f6a0040f4ab1beebccc524b3afe7d3566e9aa883..670ad5a34224f90cb22f80e1ae978f2358e57863 100644 (file)
@@ -38,7 +38,7 @@ cfs_percpt_lock_free(struct cfs_percpt_lock *pcl)
        LASSERT(!pcl->pcl_locked);
 
        cfs_percpt_free(pcl->pcl_locks);
-       LIBCFS_FREE(pcl, sizeof(*pcl));
+       kfree(pcl);
 }
 EXPORT_SYMBOL(cfs_percpt_lock_free);
 
@@ -58,14 +58,14 @@ cfs_percpt_lock_create(struct cfs_cpt_table *cptab,
        int i;
 
        /* NB: cptab can be NULL, pcl will be for HW CPUs on that case */
-       LIBCFS_ALLOC(pcl, sizeof(*pcl));
+       pcl = kzalloc(sizeof(*pcl), GFP_NOFS);
        if (!pcl)
                return NULL;
 
        pcl->pcl_cptab = cptab;
        pcl->pcl_locks = cfs_percpt_alloc(cptab, sizeof(*lock));
        if (!pcl->pcl_locks) {
-               LIBCFS_FREE(pcl, sizeof(*pcl));
+               kfree(pcl);
                return NULL;
        }
 
index df93d8f77ea2632ed579589307d0663db710bc16..7faed94994ea25b7b3b11d740e16db309effc8e9 100644 (file)
@@ -49,13 +49,10 @@ cfs_percpt_free(void *vars)
 
        arr = container_of(vars, struct cfs_var_array, va_ptrs[0]);
 
-       for (i = 0; i < arr->va_count; i++) {
-               if (arr->va_ptrs[i])
-                       LIBCFS_FREE(arr->va_ptrs[i], arr->va_size);
-       }
+       for (i = 0; i < arr->va_count; i++)
+               kfree(arr->va_ptrs[i]);
 
-       LIBCFS_FREE(arr, offsetof(struct cfs_var_array,
-                                 va_ptrs[arr->va_count]));
+       kvfree(arr);
 }
 EXPORT_SYMBOL(cfs_percpt_free);
 
@@ -79,7 +76,8 @@ cfs_percpt_alloc(struct cfs_cpt_table *cptab, unsigned int size)
 
        count = cfs_cpt_number(cptab);
 
-       LIBCFS_ALLOC(arr, offsetof(struct cfs_var_array, va_ptrs[count]));
+       arr = kvzalloc(offsetof(struct cfs_var_array, va_ptrs[count]),
+                      GFP_KERNEL);
        if (!arr)
                return NULL;
 
@@ -89,7 +87,8 @@ cfs_percpt_alloc(struct cfs_cpt_table *cptab, unsigned int size)
        arr->va_cptab = cptab;
 
        for (i = 0; i < count; i++) {
-               LIBCFS_CPT_ALLOC(arr->va_ptrs[i], cptab, i, size);
+               arr->va_ptrs[i] = kzalloc_node(size, GFP_KERNEL,
+                                              cfs_cpt_spread_node(cptab, i));
                if (!arr->va_ptrs[i]) {
                        cfs_percpt_free((void *)&arr->va_ptrs[0]);
                        return NULL;
@@ -130,10 +129,9 @@ cfs_array_free(void *vars)
                if (!arr->va_ptrs[i])
                        continue;
 
-               LIBCFS_FREE(arr->va_ptrs[i], arr->va_size);
+               kvfree(arr->va_ptrs[i]);
        }
-       LIBCFS_FREE(arr, offsetof(struct cfs_var_array,
-                                 va_ptrs[arr->va_count]));
+       kvfree(arr);
 }
 EXPORT_SYMBOL(cfs_array_free);
 
@@ -148,7 +146,7 @@ cfs_array_alloc(int count, unsigned int size)
        struct cfs_var_array *arr;
        int i;
 
-       LIBCFS_ALLOC(arr, offsetof(struct cfs_var_array, va_ptrs[count]));
+       arr = kvmalloc(offsetof(struct cfs_var_array, va_ptrs[count]), GFP_KERNEL);
        if (!arr)
                return NULL;
 
@@ -156,7 +154,7 @@ cfs_array_alloc(int count, unsigned int size)
        arr->va_size = size;
 
        for (i = 0; i < count; i++) {
-               LIBCFS_ALLOC(arr->va_ptrs[i], size);
+               arr->va_ptrs[i] = kvzalloc(size, GFP_KERNEL);
 
                if (!arr->va_ptrs[i]) {
                        cfs_array_free((void *)&arr->va_ptrs[0]);
index bcac5074bf80c13ba6a1b42d865fe58bfbba33f0..442889a3d7296dc180e44c1dd7458e042ece64ea 100644 (file)
@@ -137,26 +137,6 @@ out:
 }
 EXPORT_SYMBOL(cfs_firststr);
 
-char *
-cfs_trimwhite(char *str)
-{
-       char *end;
-
-       while (isspace(*str))
-               str++;
-
-       end = str + strlen(str);
-       while (end > str) {
-               if (!isspace(end[-1]))
-                       break;
-               end--;
-       }
-
-       *end = 0;
-       return str;
-}
-EXPORT_SYMBOL(cfs_trimwhite);
-
 /**
  * Extracts tokens from strings.
  *
@@ -280,7 +260,7 @@ cfs_range_expr_parse(struct cfs_lstr *src, unsigned int min, unsigned int max,
        struct cfs_range_expr *re;
        struct cfs_lstr tok;
 
-       LIBCFS_ALLOC(re, sizeof(*re));
+       re = kzalloc(sizeof(*re), GFP_NOFS);
        if (!re)
                return -ENOMEM;
 
@@ -333,7 +313,7 @@ cfs_range_expr_parse(struct cfs_lstr *src, unsigned int min, unsigned int max,
        return 0;
 
  failed:
-       LIBCFS_FREE(re, sizeof(*re));
+       kfree(re);
        return -EINVAL;
 }
 
@@ -457,7 +437,7 @@ cfs_expr_list_values(struct cfs_expr_list *expr_list, int max, u32 **valpp)
                return -EINVAL;
        }
 
-       LIBCFS_ALLOC(val, sizeof(val[0]) * count);
+       val = kvmalloc_array(count, sizeof(val[0]), GFP_KERNEL | __GFP_ZERO);
        if (!val)
                return -ENOMEM;
 
@@ -488,10 +468,10 @@ cfs_expr_list_free(struct cfs_expr_list *expr_list)
                expr = list_entry(expr_list->el_exprs.next,
                                  struct cfs_range_expr, re_link);
                list_del(&expr->re_link);
-               LIBCFS_FREE(expr, sizeof(*expr));
+               kfree(expr);
        }
 
-       LIBCFS_FREE(expr_list, sizeof(*expr_list));
+       kfree(expr_list);
 }
 EXPORT_SYMBOL(cfs_expr_list_free);
 
@@ -510,7 +490,7 @@ cfs_expr_list_parse(char *str, int len, unsigned int min, unsigned int max,
        struct cfs_lstr src;
        int rc;
 
-       LIBCFS_ALLOC(expr_list, sizeof(*expr_list));
+       expr_list = kzalloc(sizeof(*expr_list), GFP_NOFS);
        if (!expr_list)
                return -ENOMEM;
 
index 51823ce71773a20221c035642a1814232fc1af3b..c07165e0ad9596ae7b68ccb2decfb0cf97bc01f7 100644 (file)
@@ -72,7 +72,7 @@ struct cfs_cpt_data {
        /* mutex to protect cpt_cpumask */
        struct mutex            cpt_mutex;
        /* scratch buffer for set/unset_node */
-       cpumask_t               *cpt_cpumask;
+       cpumask_var_t           cpt_cpumask;
 };
 
 static struct cfs_cpt_data     cpt_data;
@@ -93,35 +93,21 @@ cfs_cpt_table_free(struct cfs_cpt_table *cptab)
 {
        int i;
 
-       if (cptab->ctb_cpu2cpt) {
-               LIBCFS_FREE(cptab->ctb_cpu2cpt,
-                           num_possible_cpus() *
-                           sizeof(cptab->ctb_cpu2cpt[0]));
-       }
+       kvfree(cptab->ctb_cpu2cpt);
 
        for (i = 0; cptab->ctb_parts && i < cptab->ctb_nparts; i++) {
                struct cfs_cpu_partition *part = &cptab->ctb_parts[i];
 
-               if (part->cpt_nodemask) {
-                       LIBCFS_FREE(part->cpt_nodemask,
-                                   sizeof(*part->cpt_nodemask));
-               }
-
-               if (part->cpt_cpumask)
-                       LIBCFS_FREE(part->cpt_cpumask, cpumask_size());
+               kfree(part->cpt_nodemask);
+               free_cpumask_var(part->cpt_cpumask);
        }
 
-       if (cptab->ctb_parts) {
-               LIBCFS_FREE(cptab->ctb_parts,
-                           cptab->ctb_nparts * sizeof(cptab->ctb_parts[0]));
-       }
+       kvfree(cptab->ctb_parts);
 
-       if (cptab->ctb_nodemask)
-               LIBCFS_FREE(cptab->ctb_nodemask, sizeof(*cptab->ctb_nodemask));
-       if (cptab->ctb_cpumask)
-               LIBCFS_FREE(cptab->ctb_cpumask, cpumask_size());
+       kfree(cptab->ctb_nodemask);
+       free_cpumask_var(cptab->ctb_cpumask);
 
-       LIBCFS_FREE(cptab, sizeof(*cptab));
+       kfree(cptab);
 }
 EXPORT_SYMBOL(cfs_cpt_table_free);
 
@@ -131,36 +117,39 @@ cfs_cpt_table_alloc(unsigned int ncpt)
        struct cfs_cpt_table *cptab;
        int i;
 
-       LIBCFS_ALLOC(cptab, sizeof(*cptab));
+       cptab = kzalloc(sizeof(*cptab), GFP_NOFS);
        if (!cptab)
                return NULL;
 
        cptab->ctb_nparts = ncpt;
 
-       LIBCFS_ALLOC(cptab->ctb_cpumask, cpumask_size());
-       LIBCFS_ALLOC(cptab->ctb_nodemask, sizeof(*cptab->ctb_nodemask));
-
-       if (!cptab->ctb_cpumask || !cptab->ctb_nodemask)
+       cptab->ctb_nodemask = kzalloc(sizeof(*cptab->ctb_nodemask),
+                                     GFP_NOFS);
+       if (!zalloc_cpumask_var(&cptab->ctb_cpumask, GFP_NOFS) ||
+           !cptab->ctb_nodemask)
                goto failed;
 
-       LIBCFS_ALLOC(cptab->ctb_cpu2cpt,
-                    num_possible_cpus() * sizeof(cptab->ctb_cpu2cpt[0]));
+       cptab->ctb_cpu2cpt = kvmalloc_array(num_possible_cpus(),
+                                           sizeof(cptab->ctb_cpu2cpt[0]),
+                                           GFP_KERNEL);
        if (!cptab->ctb_cpu2cpt)
                goto failed;
 
        memset(cptab->ctb_cpu2cpt, -1,
               num_possible_cpus() * sizeof(cptab->ctb_cpu2cpt[0]));
 
-       LIBCFS_ALLOC(cptab->ctb_parts, ncpt * sizeof(cptab->ctb_parts[0]));
+       cptab->ctb_parts = kvmalloc_array(ncpt, sizeof(cptab->ctb_parts[0]),
+                                         GFP_KERNEL);
        if (!cptab->ctb_parts)
                goto failed;
 
        for (i = 0; i < ncpt; i++) {
                struct cfs_cpu_partition *part = &cptab->ctb_parts[i];
 
-               LIBCFS_ALLOC(part->cpt_cpumask, cpumask_size());
-               LIBCFS_ALLOC(part->cpt_nodemask, sizeof(*part->cpt_nodemask));
-               if (!part->cpt_cpumask || !part->cpt_nodemask)
+               part->cpt_nodemask = kzalloc(sizeof(*part->cpt_nodemask),
+                                            GFP_NOFS);
+               if (!zalloc_cpumask_var(&part->cpt_cpumask, GFP_NOFS) ||
+                   !part->cpt_nodemask)
                        goto failed;
        }
 
@@ -251,13 +240,13 @@ cfs_cpt_online(struct cfs_cpt_table *cptab, int cpt)
 }
 EXPORT_SYMBOL(cfs_cpt_online);
 
-cpumask_t *
+cpumask_var_t *
 cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt)
 {
        LASSERT(cpt == CFS_CPT_ANY || (cpt >= 0 && cpt < cptab->ctb_nparts));
 
        return cpt == CFS_CPT_ANY ?
-              cptab->ctb_cpumask : cptab->ctb_parts[cpt].cpt_cpumask;
+              &cptab->ctb_cpumask : &cptab->ctb_parts[cpt].cpt_cpumask;
 }
 EXPORT_SYMBOL(cfs_cpt_cpumask);
 
@@ -405,7 +394,6 @@ EXPORT_SYMBOL(cfs_cpt_unset_cpumask);
 int
 cfs_cpt_set_node(struct cfs_cpt_table *cptab, int cpt, int node)
 {
-       cpumask_t *mask;
        int rc;
 
        if (node < 0 || node >= MAX_NUMNODES) {
@@ -416,10 +404,9 @@ cfs_cpt_set_node(struct cfs_cpt_table *cptab, int cpt, int node)
 
        mutex_lock(&cpt_data.cpt_mutex);
 
-       mask = cpt_data.cpt_cpumask;
-       cfs_node_to_cpumask(node, mask);
+       cfs_node_to_cpumask(node, cpt_data.cpt_cpumask);
 
-       rc = cfs_cpt_set_cpumask(cptab, cpt, mask);
+       rc = cfs_cpt_set_cpumask(cptab, cpt, cpt_data.cpt_cpumask);
 
        mutex_unlock(&cpt_data.cpt_mutex);
 
@@ -430,8 +417,6 @@ EXPORT_SYMBOL(cfs_cpt_set_node);
 void
 cfs_cpt_unset_node(struct cfs_cpt_table *cptab, int cpt, int node)
 {
-       cpumask_t *mask;
-
        if (node < 0 || node >= MAX_NUMNODES) {
                CDEBUG(D_INFO,
                       "Invalid NUMA id %d for CPU partition %d\n", node, cpt);
@@ -440,10 +425,9 @@ cfs_cpt_unset_node(struct cfs_cpt_table *cptab, int cpt, int node)
 
        mutex_lock(&cpt_data.cpt_mutex);
 
-       mask = cpt_data.cpt_cpumask;
-       cfs_node_to_cpumask(node, mask);
+       cfs_node_to_cpumask(node, cpt_data.cpt_cpumask);
 
-       cfs_cpt_unset_cpumask(cptab, cpt, mask);
+       cfs_cpt_unset_cpumask(cptab, cpt, cpt_data.cpt_cpumask);
 
        mutex_unlock(&cpt_data.cpt_mutex);
 }
@@ -529,19 +513,20 @@ EXPORT_SYMBOL(cfs_cpt_spread_node);
 int
 cfs_cpt_current(struct cfs_cpt_table *cptab, int remap)
 {
-       int cpu = smp_processor_id();
-       int cpt = cptab->ctb_cpu2cpt[cpu];
+       int cpu;
+       int cpt;
 
-       if (cpt < 0) {
-               if (!remap)
-                       return cpt;
+       preempt_disable();
+       cpu = smp_processor_id();
+       cpt = cptab->ctb_cpu2cpt[cpu];
 
+       if (cpt < 0 && remap) {
                /* don't return negative value for safety of upper layer,
                 * instead we shadow the unknown cpu to a valid partition ID
                 */
                cpt = cpu % cptab->ctb_nparts;
        }
-
+       preempt_enable();
        return cpt;
 }
 EXPORT_SYMBOL(cfs_cpt_current);
@@ -558,7 +543,7 @@ EXPORT_SYMBOL(cfs_cpt_of_cpu);
 int
 cfs_cpt_bind(struct cfs_cpt_table *cptab, int cpt)
 {
-       cpumask_t *cpumask;
+       cpumask_var_t *cpumask;
        nodemask_t *nodemask;
        int rc;
        int i;
@@ -566,24 +551,24 @@ cfs_cpt_bind(struct cfs_cpt_table *cptab, int cpt)
        LASSERT(cpt == CFS_CPT_ANY || (cpt >= 0 && cpt < cptab->ctb_nparts));
 
        if (cpt == CFS_CPT_ANY) {
-               cpumask = cptab->ctb_cpumask;
+               cpumask = &cptab->ctb_cpumask;
                nodemask = cptab->ctb_nodemask;
        } else {
-               cpumask = cptab->ctb_parts[cpt].cpt_cpumask;
+               cpumask = &cptab->ctb_parts[cpt].cpt_cpumask;
                nodemask = cptab->ctb_parts[cpt].cpt_nodemask;
        }
 
-       if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids) {
+       if (cpumask_any_and(*cpumask, cpu_online_mask) >= nr_cpu_ids) {
                CERROR("No online CPU found in CPU partition %d, did someone do CPU hotplug on system? You might need to reload Lustre modules to keep system working well.\n",
                       cpt);
                return -EINVAL;
        }
 
        for_each_online_cpu(i) {
-               if (cpumask_test_cpu(i, cpumask))
+               if (cpumask_test_cpu(i, *cpumask))
                        continue;
 
-               rc = set_cpus_allowed_ptr(current, cpumask);
+               rc = set_cpus_allowed_ptr(current, *cpumask);
                set_mems_allowed(*nodemask);
                if (!rc)
                        schedule(); /* switch to allowed CPU */
@@ -604,8 +589,8 @@ static int
 cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt,
                     cpumask_t *node, int number)
 {
-       cpumask_t *socket = NULL;
-       cpumask_t *core = NULL;
+       cpumask_var_t socket;
+       cpumask_var_t core;
        int rc = 0;
        int cpu;
 
@@ -623,13 +608,17 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt,
                return 0;
        }
 
-       /* allocate scratch buffer */
-       LIBCFS_ALLOC(socket, cpumask_size());
-       LIBCFS_ALLOC(core, cpumask_size());
-       if (!socket || !core) {
+       /*
+        * Allocate scratch buffers
+        * As we cannot initialize a cpumask_var_t, we need
+        * to alloc both before we can risk trying to free either
+        */
+       if (!zalloc_cpumask_var(&socket, GFP_NOFS))
                rc = -ENOMEM;
+       if (!zalloc_cpumask_var(&core, GFP_NOFS))
+               rc = -ENOMEM;
+       if (rc)
                goto out;
-       }
 
        while (!cpumask_empty(node)) {
                cpu = cpumask_first(node);
@@ -667,10 +656,8 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt,
        }
 
 out:
-       if (socket)
-               LIBCFS_FREE(socket, cpumask_size());
-       if (core)
-               LIBCFS_FREE(core, cpumask_size());
+       free_cpumask_var(socket);
+       free_cpumask_var(core);
        return rc;
 }
 
@@ -723,7 +710,7 @@ static struct cfs_cpt_table *
 cfs_cpt_table_create(int ncpt)
 {
        struct cfs_cpt_table *cptab = NULL;
-       cpumask_t *mask = NULL;
+       cpumask_var_t mask;
        int cpt = 0;
        int num;
        int rc;
@@ -756,8 +743,7 @@ cfs_cpt_table_create(int ncpt)
                goto failed;
        }
 
-       LIBCFS_ALLOC(mask, cpumask_size());
-       if (!mask) {
+       if (!zalloc_cpumask_var(&mask, GFP_NOFS)){
                CERROR("Failed to allocate scratch cpumask\n");
                goto failed;
        }
@@ -784,7 +770,7 @@ cfs_cpt_table_create(int ncpt)
 
                        rc = cfs_cpt_choose_ncpus(cptab, cpt, mask, n);
                        if (rc < 0)
-                               goto failed;
+                               goto failed_mask;
 
                        LASSERT(num >= cpumask_weight(part->cpt_cpumask));
                        if (num == cpumask_weight(part->cpt_cpumask))
@@ -797,20 +783,19 @@ cfs_cpt_table_create(int ncpt)
                CERROR("Expect %d(%d) CPU partitions but got %d(%d), CPU hotplug/unplug while setting?\n",
                       cptab->ctb_nparts, num, cpt,
                       cpumask_weight(cptab->ctb_parts[ncpt - 1].cpt_cpumask));
-               goto failed;
+               goto failed_mask;
        }
 
-       LIBCFS_FREE(mask, cpumask_size());
+       free_cpumask_var(mask);
 
        return cptab;
 
+ failed_mask:
+       free_cpumask_var(mask);
  failed:
        CERROR("Failed to setup CPU-partition-table with %d CPU-partitions, online HW nodes: %d, HW cpus: %d.\n",
               ncpt, num_online_nodes(), num_online_cpus());
 
-       if (mask)
-               LIBCFS_FREE(mask, cpumask_size());
-
        if (cptab)
                cfs_cpt_table_free(cptab);
 
@@ -830,7 +815,7 @@ cfs_cpt_table_create_pattern(char *pattern)
        int c;
        int i;
 
-       str = cfs_trimwhite(pattern);
+       str = strim(pattern);
        if (*str == 'n' || *str == 'N') {
                pattern = str + 1;
                if (*pattern != '\0') {
@@ -882,7 +867,7 @@ cfs_cpt_table_create_pattern(char *pattern)
 
        high = node ? MAX_NUMNODES - 1 : nr_cpu_ids - 1;
 
-       for (str = cfs_trimwhite(pattern), c = 0;; c++) {
+       for (str = strim(pattern), c = 0;; c++) {
                struct cfs_range_expr *range;
                struct cfs_expr_list *el;
                char *bracket = strchr(str, '[');
@@ -917,7 +902,7 @@ cfs_cpt_table_create_pattern(char *pattern)
                        goto failed;
                }
 
-               str = cfs_trimwhite(str + n);
+               str = strim(str + n);
                if (str != bracket) {
                        CERROR("Invalid pattern %s\n", str);
                        goto failed;
@@ -957,7 +942,7 @@ cfs_cpt_table_create_pattern(char *pattern)
                        goto failed;
                }
 
-               str = cfs_trimwhite(bracket + 1);
+               str = strim(bracket + 1);
        }
 
        return cptab;
@@ -1013,8 +998,7 @@ cfs_cpu_fini(void)
                cpuhp_remove_state_nocalls(lustre_cpu_online);
        cpuhp_remove_state_nocalls(CPUHP_LUSTRE_CFS_DEAD);
 #endif
-       if (cpt_data.cpt_cpumask)
-               LIBCFS_FREE(cpt_data.cpt_cpumask, cpumask_size());
+       free_cpumask_var(cpt_data.cpt_cpumask);
 }
 
 int
@@ -1026,8 +1010,7 @@ cfs_cpu_init(void)
 
        memset(&cpt_data, 0, sizeof(cpt_data));
 
-       LIBCFS_ALLOC(cpt_data.cpt_cpumask, cpumask_size());
-       if (!cpt_data.cpt_cpumask) {
+       if (!zalloc_cpumask_var(&cpt_data.cpt_cpumask, GFP_NOFS)) {
                CERROR("Failed to allocate scratch buffer\n");
                return -1;
        }
index b5746230ab31c1ce9fddf3cfa9dfcdf292c67414..ddf625669bffcf6f95cfc7c4448ade398988a136 100644 (file)
@@ -146,7 +146,7 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp,
                return -EINVAL;
        }
 
-       LIBCFS_ALLOC(*hdr_pp, hdr.ioc_len);
+       *hdr_pp = kvmalloc(hdr.ioc_len, GFP_KERNEL);
        if (!*hdr_pp)
                return -ENOMEM;
 
@@ -164,7 +164,7 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp,
        return 0;
 
 free:
-       LIBCFS_FREE(*hdr_pp, hdr.ioc_len);
+       kvfree(*hdr_pp);
        return err;
 }
 
index 4ead55920e79fd94e8a578064d0fba49e27f9082..a03f924f1d7c000d60a3e229e4418f288e18387b 100644 (file)
@@ -156,7 +156,7 @@ int libcfs_ioctl(unsigned long cmd, void __user *uparam)
                break; }
        }
 out:
-       LIBCFS_FREE(hdr, hdr->ioc_len);
+       kvfree(hdr);
        return err;
 }
 
@@ -302,7 +302,7 @@ static int __proc_cpt_table(void *data, int write,
        LASSERT(cfs_cpt_table);
 
        while (1) {
-               LIBCFS_ALLOC(buf, len);
+               buf = kzalloc(len, GFP_KERNEL);
                if (!buf)
                        return -ENOMEM;
 
@@ -311,7 +311,7 @@ static int __proc_cpt_table(void *data, int write,
                        break;
 
                if (rc == -EFBIG) {
-                       LIBCFS_FREE(buf, len);
+                       kfree(buf);
                        len <<= 1;
                        continue;
                }
@@ -325,8 +325,7 @@ static int __proc_cpt_table(void *data, int write,
 
        rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
  out:
-       if (buf)
-               LIBCFS_FREE(buf, len);
+       kfree(buf);
        return rc;
 }
 
@@ -548,33 +547,23 @@ static int libcfs_init(void)
                goto cleanup_cpu;
        }
 
-       rc = cfs_wi_startup();
-       if (rc) {
-               CERROR("initialize workitem: error %d\n", rc);
-               goto cleanup_deregister;
-       }
-
-       /* max to 4 threads, should be enough for rehash */
-       rc = min(cfs_cpt_weight(cfs_cpt_table, CFS_CPT_ANY), 4);
-       rc = cfs_wi_sched_create("cfs_rh", cfs_cpt_table, CFS_CPT_ANY,
-                                rc, &cfs_sched_rehash);
-       if (rc) {
-               CERROR("Startup workitem scheduler: error: %d\n", rc);
+       cfs_rehash_wq = alloc_workqueue("cfs_rh", WQ_SYSFS, 4);
+       if (!cfs_rehash_wq) {
+               CERROR("Failed to start rehash workqueue.\n");
+               rc = -ENOMEM;
                goto cleanup_deregister;
        }
 
        rc = cfs_crypto_register();
        if (rc) {
                CERROR("cfs_crypto_register: error %d\n", rc);
-               goto cleanup_wi;
+               goto cleanup_deregister;
        }
 
        lustre_insert_debugfs(lnet_table, lnet_debugfs_symlinks);
 
        CDEBUG(D_OTHER, "portals setup OK\n");
        return 0;
- cleanup_wi:
-       cfs_wi_shutdown();
  cleanup_deregister:
        misc_deregister(&libcfs_dev);
 cleanup_cpu:
@@ -590,13 +579,12 @@ static void libcfs_exit(void)
 
        lustre_remove_debugfs();
 
-       if (cfs_sched_rehash) {
-               cfs_wi_sched_destroy(cfs_sched_rehash);
-               cfs_sched_rehash = NULL;
+       if (cfs_rehash_wq) {
+               destroy_workqueue(cfs_rehash_wq);
+               cfs_rehash_wq = NULL;
        }
 
        cfs_crypto_unregister();
-       cfs_wi_shutdown();
 
        misc_deregister(&libcfs_dev);
 
diff --git a/drivers/staging/lustre/lnet/libcfs/prng.c b/drivers/staging/lustre/lnet/libcfs/prng.c
deleted file mode 100644 (file)
index f47cf67..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/libcfs/prng.c
- *
- * concatenation of following two 16-bit multiply with carry generators
- * x(n)=a*x(n-1)+carry mod 2^16 and y(n)=b*y(n-1)+carry mod 2^16,
- * number and carry packed within the same 32 bit integer.
- * algorithm recommended by Marsaglia
- */
-
-#include <linux/libcfs/libcfs.h>
-
-/*
- * From: George Marsaglia <geo@stat.fsu.edu>
- * Newsgroups: sci.math
- * Subject: Re: A RANDOM NUMBER GENERATOR FOR C
- * Date: Tue, 30 Sep 1997 05:29:35 -0700
- *
- * You may replace the two constants 36969 and 18000 by any
- * pair of distinct constants from this list:
- * 18000 18030 18273 18513 18879 19074 19098 19164 19215 19584
- * 19599 19950 20088 20508 20544 20664 20814 20970 21153 21243
- * 21423 21723 21954 22125 22188 22293 22860 22938 22965 22974
- * 23109 23124 23163 23208 23508 23520 23553 23658 23865 24114
- * 24219 24660 24699 24864 24948 25023 25308 25443 26004 26088
- * 26154 26550 26679 26838 27183 27258 27753 27795 27810 27834
- * 27960 28320 28380 28689 28710 28794 28854 28959 28980 29013
- * 29379 29889 30135 30345 30459 30714 30903 30963 31059 31083
- * (or any other 16-bit constants k for which both k*2^16-1
- * and k*2^15-1 are prime)
- */
-
-#define RANDOM_CONST_A 18030
-#define RANDOM_CONST_B 29013
-
-static unsigned int seed_x = 521288629;
-static unsigned int seed_y = 362436069;
-
-/**
- * cfs_rand - creates new seeds
- *
- * First it creates new seeds from the previous seeds. Then it generates a
- * new pseudo random number for use.
- *
- * Returns a pseudo-random 32-bit integer
- */
-unsigned int cfs_rand(void)
-{
-       seed_x = RANDOM_CONST_A * (seed_x & 65535) + (seed_x >> 16);
-       seed_y = RANDOM_CONST_B * (seed_y & 65535) + (seed_y >> 16);
-
-       return ((seed_x << 16) + (seed_y & 65535));
-}
-EXPORT_SYMBOL(cfs_rand);
-
-/**
- * cfs_srand - sets the initial seed
- * @seed1 : (seed_x) should have the most entropy in the low bits of the word
- * @seed2 : (seed_y) should have the most entropy in the high bits of the word
- *
- * Replaces the original seeds with new values. Used to generate a new pseudo
- * random numbers.
- */
-void cfs_srand(unsigned int seed1, unsigned int seed2)
-{
-       if (seed1)
-               seed_x = seed1; /* use default seeds if parameter is 0 */
-       if (seed2)
-               seed_y = seed2;
-}
-EXPORT_SYMBOL(cfs_srand);
-
-/**
- * cfs_get_random_bytes - generate a bunch of random numbers
- * @buf : buffer to fill with random numbers
- * @size: size of passed in buffer
- *
- * Fills a buffer with random bytes
- */
-void cfs_get_random_bytes(void *buf, int size)
-{
-       int *p = buf;
-       int rem, tmp;
-
-       LASSERT(size >= 0);
-
-       rem = min((int)((unsigned long)buf & (sizeof(int) - 1)), size);
-       if (rem) {
-               get_random_bytes(&tmp, sizeof(tmp));
-               tmp ^= cfs_rand();
-               memcpy(buf, &tmp, rem);
-               p = buf + rem;
-               size -= rem;
-       }
-
-       while (size >= sizeof(int)) {
-               get_random_bytes(&tmp, sizeof(tmp));
-               *p = cfs_rand() ^ tmp;
-               size -= sizeof(int);
-               p++;
-       }
-       buf = p;
-       if (size) {
-               get_random_bytes(&tmp, sizeof(tmp));
-               tmp ^= cfs_rand();
-               memcpy(buf, &tmp, size);
-       }
-}
-EXPORT_SYMBOL(cfs_get_random_bytes);
index da2844f37edfacb242a8acb99e1ce0ad3c509300..57913aae1d881f8e42ece80c5ff9907ba4b4c57b 100644 (file)
@@ -785,7 +785,7 @@ int cfs_trace_copyin_string(char *knl_buffer, int knl_buffer_nob,
                return -EFAULT;
 
        nob = strnlen(knl_buffer, usr_buffer_nob);
-       while (nob-- >= 0)                    /* strip trailing whitespace */
+       while (--nob >= 0)                    /* strip trailing whitespace */
                if (!isspace(knl_buffer[nob]))
                        break;
 
diff --git a/drivers/staging/lustre/lnet/libcfs/workitem.c b/drivers/staging/lustre/lnet/libcfs/workitem.c
deleted file mode 100644 (file)
index 6a05d9b..0000000
+++ /dev/null
@@ -1,466 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/libcfs/workitem.c
- *
- * Author: Isaac Huang <isaac@clusterfs.com>
- *      Liang Zhen  <zhen.liang@sun.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LNET
-
-#include <linux/libcfs/libcfs.h>
-
-#define CFS_WS_NAME_LEN         16
-
-struct cfs_wi_sched {
-       /* chain on global list */
-       struct list_head                ws_list;
-       /** serialised workitems */
-       spinlock_t                      ws_lock;
-       /** where schedulers sleep */
-       wait_queue_head_t               ws_waitq;
-       /** concurrent workitems */
-       struct list_head                ws_runq;
-       /**
-        * rescheduled running-workitems, a workitem can be rescheduled
-        * while running in wi_action(), but we don't to execute it again
-        * unless it returns from wi_action(), so we put it on ws_rerunq
-        * while rescheduling, and move it to runq after it returns
-        * from wi_action()
-        */
-       struct list_head                ws_rerunq;
-       /** CPT-table for this scheduler */
-       struct cfs_cpt_table            *ws_cptab;
-       /** CPT id for affinity */
-       int                             ws_cpt;
-       /** number of scheduled workitems */
-       int                             ws_nscheduled;
-       /** started scheduler thread, protected by cfs_wi_data::wi_glock */
-       unsigned int                    ws_nthreads:30;
-       /** shutting down, protected by cfs_wi_data::wi_glock */
-       unsigned int                    ws_stopping:1;
-       /** serialize starting thread, protected by cfs_wi_data::wi_glock */
-       unsigned int                    ws_starting:1;
-       /** scheduler name */
-       char                            ws_name[CFS_WS_NAME_LEN];
-};
-
-static struct cfs_workitem_data {
-       /** serialize */
-       spinlock_t              wi_glock;
-       /** list of all schedulers */
-       struct list_head        wi_scheds;
-       /** WI module is initialized */
-       int                     wi_init;
-       /** shutting down the whole WI module */
-       int                     wi_stopping;
-} cfs_wi_data;
-
-static inline int
-cfs_wi_sched_cansleep(struct cfs_wi_sched *sched)
-{
-       spin_lock(&sched->ws_lock);
-       if (sched->ws_stopping) {
-               spin_unlock(&sched->ws_lock);
-               return 0;
-       }
-
-       if (!list_empty(&sched->ws_runq)) {
-               spin_unlock(&sched->ws_lock);
-               return 0;
-       }
-       spin_unlock(&sched->ws_lock);
-       return 1;
-}
-
-/* XXX:
- * 0. it only works when called from wi->wi_action.
- * 1. when it returns no one shall try to schedule the workitem.
- */
-void
-cfs_wi_exit(struct cfs_wi_sched *sched, struct cfs_workitem *wi)
-{
-       LASSERT(!in_interrupt()); /* because we use plain spinlock */
-       LASSERT(!sched->ws_stopping);
-
-       spin_lock(&sched->ws_lock);
-
-       LASSERT(wi->wi_running);
-       if (wi->wi_scheduled) { /* cancel pending schedules */
-               LASSERT(!list_empty(&wi->wi_list));
-               list_del_init(&wi->wi_list);
-
-               LASSERT(sched->ws_nscheduled > 0);
-               sched->ws_nscheduled--;
-       }
-
-       LASSERT(list_empty(&wi->wi_list));
-
-       wi->wi_scheduled = 1; /* LBUG future schedule attempts */
-       spin_unlock(&sched->ws_lock);
-}
-EXPORT_SYMBOL(cfs_wi_exit);
-
-/**
- * cancel schedule request of workitem \a wi
- */
-int
-cfs_wi_deschedule(struct cfs_wi_sched *sched, struct cfs_workitem *wi)
-{
-       int rc;
-
-       LASSERT(!in_interrupt()); /* because we use plain spinlock */
-       LASSERT(!sched->ws_stopping);
-
-       /*
-        * return 0 if it's running already, otherwise return 1, which
-        * means the workitem will not be scheduled and will not have
-        * any race with wi_action.
-        */
-       spin_lock(&sched->ws_lock);
-
-       rc = !(wi->wi_running);
-
-       if (wi->wi_scheduled) { /* cancel pending schedules */
-               LASSERT(!list_empty(&wi->wi_list));
-               list_del_init(&wi->wi_list);
-
-               LASSERT(sched->ws_nscheduled > 0);
-               sched->ws_nscheduled--;
-
-               wi->wi_scheduled = 0;
-       }
-
-       LASSERT(list_empty(&wi->wi_list));
-
-       spin_unlock(&sched->ws_lock);
-       return rc;
-}
-EXPORT_SYMBOL(cfs_wi_deschedule);
-
-/*
- * Workitem scheduled with (serial == 1) is strictly serialised not only with
- * itself, but also with others scheduled this way.
- *
- * Now there's only one static serialised queue, but in the future more might
- * be added, and even dynamic creation of serialised queues might be supported.
- */
-void
-cfs_wi_schedule(struct cfs_wi_sched *sched, struct cfs_workitem *wi)
-{
-       LASSERT(!in_interrupt()); /* because we use plain spinlock */
-       LASSERT(!sched->ws_stopping);
-
-       spin_lock(&sched->ws_lock);
-
-       if (!wi->wi_scheduled) {
-               LASSERT(list_empty(&wi->wi_list));
-
-               wi->wi_scheduled = 1;
-               sched->ws_nscheduled++;
-               if (!wi->wi_running) {
-                       list_add_tail(&wi->wi_list, &sched->ws_runq);
-                       wake_up(&sched->ws_waitq);
-               } else {
-                       list_add(&wi->wi_list, &sched->ws_rerunq);
-               }
-       }
-
-       LASSERT(!list_empty(&wi->wi_list));
-       spin_unlock(&sched->ws_lock);
-}
-EXPORT_SYMBOL(cfs_wi_schedule);
-
-static int cfs_wi_scheduler(void *arg)
-{
-       struct cfs_wi_sched *sched = (struct cfs_wi_sched *)arg;
-
-       cfs_block_allsigs();
-
-       /* CPT affinity scheduler? */
-       if (sched->ws_cptab)
-               if (cfs_cpt_bind(sched->ws_cptab, sched->ws_cpt))
-                       CWARN("Unable to bind %s on CPU partition %d\n",
-                             sched->ws_name, sched->ws_cpt);
-
-       spin_lock(&cfs_wi_data.wi_glock);
-
-       LASSERT(sched->ws_starting == 1);
-       sched->ws_starting--;
-       sched->ws_nthreads++;
-
-       spin_unlock(&cfs_wi_data.wi_glock);
-
-       spin_lock(&sched->ws_lock);
-
-       while (!sched->ws_stopping) {
-               int nloops = 0;
-               int rc;
-               struct cfs_workitem *wi;
-
-               while (!list_empty(&sched->ws_runq) &&
-                      nloops < CFS_WI_RESCHED) {
-                       wi = list_entry(sched->ws_runq.next,
-                                       struct cfs_workitem, wi_list);
-                       LASSERT(wi->wi_scheduled && !wi->wi_running);
-
-                       list_del_init(&wi->wi_list);
-
-                       LASSERT(sched->ws_nscheduled > 0);
-                       sched->ws_nscheduled--;
-
-                       wi->wi_running = 1;
-                       wi->wi_scheduled = 0;
-
-                       spin_unlock(&sched->ws_lock);
-                       nloops++;
-
-                       rc = (*wi->wi_action)(wi);
-
-                       spin_lock(&sched->ws_lock);
-                       if (rc) /* WI should be dead, even be freed! */
-                               continue;
-
-                       wi->wi_running = 0;
-                       if (list_empty(&wi->wi_list))
-                               continue;
-
-                       LASSERT(wi->wi_scheduled);
-                       /* wi is rescheduled, should be on rerunq now, we
-                        * move it to runq so it can run action now
-                        */
-                       list_move_tail(&wi->wi_list, &sched->ws_runq);
-               }
-
-               if (!list_empty(&sched->ws_runq)) {
-                       spin_unlock(&sched->ws_lock);
-                       /* don't sleep because some workitems still
-                        * expect me to come back soon
-                        */
-                       cond_resched();
-                       spin_lock(&sched->ws_lock);
-                       continue;
-               }
-
-               spin_unlock(&sched->ws_lock);
-               rc = wait_event_interruptible_exclusive(sched->ws_waitq,
-                                                       !cfs_wi_sched_cansleep(sched));
-               spin_lock(&sched->ws_lock);
-       }
-
-       spin_unlock(&sched->ws_lock);
-
-       spin_lock(&cfs_wi_data.wi_glock);
-       sched->ws_nthreads--;
-       spin_unlock(&cfs_wi_data.wi_glock);
-
-       return 0;
-}
-
-void
-cfs_wi_sched_destroy(struct cfs_wi_sched *sched)
-{
-       int i;
-
-       LASSERT(cfs_wi_data.wi_init);
-       LASSERT(!cfs_wi_data.wi_stopping);
-
-       spin_lock(&cfs_wi_data.wi_glock);
-       if (sched->ws_stopping) {
-               CDEBUG(D_INFO, "%s is in progress of stopping\n",
-                      sched->ws_name);
-               spin_unlock(&cfs_wi_data.wi_glock);
-               return;
-       }
-
-       LASSERT(!list_empty(&sched->ws_list));
-       sched->ws_stopping = 1;
-
-       spin_unlock(&cfs_wi_data.wi_glock);
-
-       i = 2;
-       wake_up_all(&sched->ws_waitq);
-
-       spin_lock(&cfs_wi_data.wi_glock);
-       while (sched->ws_nthreads > 0) {
-               CDEBUG(is_power_of_2(++i) ? D_WARNING : D_NET,
-                      "waiting for %d threads of WI sched[%s] to terminate\n",
-                      sched->ws_nthreads, sched->ws_name);
-
-               spin_unlock(&cfs_wi_data.wi_glock);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(cfs_time_seconds(1) / 20);
-               spin_lock(&cfs_wi_data.wi_glock);
-       }
-
-       list_del(&sched->ws_list);
-
-       spin_unlock(&cfs_wi_data.wi_glock);
-       LASSERT(!sched->ws_nscheduled);
-
-       LIBCFS_FREE(sched, sizeof(*sched));
-}
-EXPORT_SYMBOL(cfs_wi_sched_destroy);
-
-int
-cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab,
-                   int cpt, int nthrs, struct cfs_wi_sched **sched_pp)
-{
-       struct cfs_wi_sched *sched;
-       int rc;
-
-       LASSERT(cfs_wi_data.wi_init);
-       LASSERT(!cfs_wi_data.wi_stopping);
-       LASSERT(!cptab || cpt == CFS_CPT_ANY ||
-               (cpt >= 0 && cpt < cfs_cpt_number(cptab)));
-
-       LIBCFS_ALLOC(sched, sizeof(*sched));
-       if (!sched)
-               return -ENOMEM;
-
-       if (strlen(name) > sizeof(sched->ws_name) - 1) {
-               LIBCFS_FREE(sched, sizeof(*sched));
-               return -E2BIG;
-       }
-       strncpy(sched->ws_name, name, sizeof(sched->ws_name));
-
-       sched->ws_cptab = cptab;
-       sched->ws_cpt = cpt;
-
-       spin_lock_init(&sched->ws_lock);
-       init_waitqueue_head(&sched->ws_waitq);
-       INIT_LIST_HEAD(&sched->ws_runq);
-       INIT_LIST_HEAD(&sched->ws_rerunq);
-       INIT_LIST_HEAD(&sched->ws_list);
-
-       rc = 0;
-       while (nthrs > 0)  {
-               char name[16];
-               struct task_struct *task;
-
-               spin_lock(&cfs_wi_data.wi_glock);
-               while (sched->ws_starting > 0) {
-                       spin_unlock(&cfs_wi_data.wi_glock);
-                       schedule();
-                       spin_lock(&cfs_wi_data.wi_glock);
-               }
-
-               sched->ws_starting++;
-               spin_unlock(&cfs_wi_data.wi_glock);
-
-               if (sched->ws_cptab && sched->ws_cpt >= 0) {
-                       snprintf(name, sizeof(name), "%s_%02d_%02u",
-                                sched->ws_name, sched->ws_cpt,
-                                sched->ws_nthreads);
-               } else {
-                       snprintf(name, sizeof(name), "%s_%02u",
-                                sched->ws_name, sched->ws_nthreads);
-               }
-
-               task = kthread_run(cfs_wi_scheduler, sched, "%s", name);
-               if (!IS_ERR(task)) {
-                       nthrs--;
-                       continue;
-               }
-               rc = PTR_ERR(task);
-
-               CERROR("Failed to create thread for WI scheduler %s: %d\n",
-                      name, rc);
-
-               spin_lock(&cfs_wi_data.wi_glock);
-
-               /* make up for cfs_wi_sched_destroy */
-               list_add(&sched->ws_list, &cfs_wi_data.wi_scheds);
-               sched->ws_starting--;
-
-               spin_unlock(&cfs_wi_data.wi_glock);
-
-               cfs_wi_sched_destroy(sched);
-               return rc;
-       }
-       spin_lock(&cfs_wi_data.wi_glock);
-       list_add(&sched->ws_list, &cfs_wi_data.wi_scheds);
-       spin_unlock(&cfs_wi_data.wi_glock);
-
-       *sched_pp = sched;
-       return 0;
-}
-EXPORT_SYMBOL(cfs_wi_sched_create);
-
-int
-cfs_wi_startup(void)
-{
-       memset(&cfs_wi_data, 0, sizeof(cfs_wi_data));
-
-       spin_lock_init(&cfs_wi_data.wi_glock);
-       INIT_LIST_HEAD(&cfs_wi_data.wi_scheds);
-       cfs_wi_data.wi_init = 1;
-
-       return 0;
-}
-
-void
-cfs_wi_shutdown(void)
-{
-       struct cfs_wi_sched *sched;
-       struct cfs_wi_sched *temp;
-
-       spin_lock(&cfs_wi_data.wi_glock);
-       cfs_wi_data.wi_stopping = 1;
-       spin_unlock(&cfs_wi_data.wi_glock);
-
-       /* nobody should contend on this list */
-       list_for_each_entry(sched, &cfs_wi_data.wi_scheds, ws_list) {
-               sched->ws_stopping = 1;
-               wake_up_all(&sched->ws_waitq);
-       }
-
-       list_for_each_entry(sched, &cfs_wi_data.wi_scheds, ws_list) {
-               spin_lock(&cfs_wi_data.wi_glock);
-
-               while (sched->ws_nthreads) {
-                       spin_unlock(&cfs_wi_data.wi_glock);
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(cfs_time_seconds(1) / 20);
-                       spin_lock(&cfs_wi_data.wi_glock);
-               }
-               spin_unlock(&cfs_wi_data.wi_glock);
-       }
-       list_for_each_entry_safe(sched, temp, &cfs_wi_data.wi_scheds, ws_list) {
-               list_del(&sched->ws_list);
-               LIBCFS_FREE(sched, sizeof(*sched));
-       }
-
-       cfs_wi_data.wi_stopping = 0;
-       cfs_wi_data.wi_init = 0;
-}
index 7caff290c146a4c72768f515a82da671ea2cf3cf..2c7abad57104a8c3472cca935b456516a70c6541 100644 (file)
@@ -108,7 +108,8 @@ lnet_create_remote_nets_table(void)
 
        LASSERT(!the_lnet.ln_remote_nets_hash);
        LASSERT(the_lnet.ln_remote_nets_hbits > 0);
-       LIBCFS_ALLOC(hash, LNET_REMOTE_NETS_HASH_SIZE * sizeof(*hash));
+       hash = kvmalloc_array(LNET_REMOTE_NETS_HASH_SIZE, sizeof(*hash),
+                             GFP_KERNEL);
        if (!hash) {
                CERROR("Failed to create remote nets hash table\n");
                return -ENOMEM;
@@ -131,9 +132,7 @@ lnet_destroy_remote_nets_table(void)
        for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++)
                LASSERT(list_empty(&the_lnet.ln_remote_nets_hash[i]));
 
-       LIBCFS_FREE(the_lnet.ln_remote_nets_hash,
-                   LNET_REMOTE_NETS_HASH_SIZE *
-                   sizeof(the_lnet.ln_remote_nets_hash[0]));
+       kvfree(the_lnet.ln_remote_nets_hash);
        the_lnet.ln_remote_nets_hash = NULL;
 }
 
@@ -384,10 +383,10 @@ lnet_res_container_cleanup(struct lnet_res_container *rec)
 
                list_del_init(e);
                if (rec->rec_type == LNET_COOKIE_TYPE_EQ) {
-                       lnet_eq_free(list_entry(e, struct lnet_eq, eq_list));
+                       kfree(list_entry(e, struct lnet_eq, eq_list));
 
                } else if (rec->rec_type == LNET_COOKIE_TYPE_MD) {
-                       lnet_md_free(list_entry(e, struct lnet_libmd, md_list));
+                       kfree(list_entry(e, struct lnet_libmd, md_list));
 
                } else { /* NB: Active MEs should be attached on portals */
                        LBUG();
@@ -405,11 +404,8 @@ lnet_res_container_cleanup(struct lnet_res_container *rec)
                       count, lnet_res_type2str(rec->rec_type));
        }
 
-       if (rec->rec_lh_hash) {
-               LIBCFS_FREE(rec->rec_lh_hash,
-                           LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0]));
-               rec->rec_lh_hash = NULL;
-       }
+       kfree(rec->rec_lh_hash);
+       rec->rec_lh_hash = NULL;
 
        rec->rec_type = 0; /* mark it as finalized */
 }
@@ -427,8 +423,8 @@ lnet_res_container_setup(struct lnet_res_container *rec, int cpt, int type)
        rec->rec_lh_cookie = (cpt << LNET_COOKIE_TYPE_BITS) | type;
 
        /* Arbitrary choice of hash table size */
-       LIBCFS_CPT_ALLOC(rec->rec_lh_hash, lnet_cpt_table(), cpt,
-                        LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0]));
+       rec->rec_lh_hash = kvmalloc_cpt(LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0]),
+                                       GFP_KERNEL, cpt);
        if (!rec->rec_lh_hash) {
                rc = -ENOMEM;
                goto out;
@@ -831,7 +827,7 @@ lnet_ping_info_create(int num_ni)
        unsigned int infosz;
 
        infosz = offsetof(struct lnet_ping_info, pi_ni[num_ni]);
-       LIBCFS_ALLOC(ping_info, infosz);
+       ping_info = kvzalloc(infosz, GFP_KERNEL);
        if (!ping_info) {
                CERROR("Can't allocate ping info[%d]\n", num_ni);
                return NULL;
@@ -864,9 +860,7 @@ lnet_get_ni_count(void)
 static inline void
 lnet_ping_info_free(struct lnet_ping_info *pinfo)
 {
-       LIBCFS_FREE(pinfo,
-                   offsetof(struct lnet_ping_info,
-                            pi_ni[pinfo->pi_nnis]));
+       kvfree(pinfo);
 }
 
 static void
@@ -1280,8 +1274,8 @@ lnet_startup_lndni(struct lnet_ni *ni, struct lnet_ioctl_config_data *conf)
                lnd_tunables = (struct lnet_ioctl_config_lnd_tunables *)conf->cfg_bulk;
 
        if (lnd_tunables) {
-               LIBCFS_ALLOC(ni->ni_lnd_tunables,
-                            sizeof(*ni->ni_lnd_tunables));
+               ni->ni_lnd_tunables = kzalloc(sizeof(*ni->ni_lnd_tunables),
+                                             GFP_NOFS);
                if (!ni->ni_lnd_tunables) {
                        mutex_unlock(&the_lnet.ln_lnd_mutex);
                        rc = -ENOMEM;
@@ -2160,7 +2154,7 @@ static int lnet_ping(struct lnet_process_id id, int timeout_ms,
        if (id.pid == LNET_PID_ANY)
                id.pid = LNET_PID_LUSTRE;
 
-       LIBCFS_ALLOC(info, infosz);
+       info = kzalloc(infosz, GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
@@ -2310,6 +2304,6 @@ static int lnet_ping(struct lnet_process_id id, int timeout_ms,
        LASSERT(!rc2);
 
  out_0:
-       LIBCFS_FREE(info, infosz);
+       kfree(info);
        return rc;
 }
index 0cf0f4f994359512ce38e5664ac9d062b918fb1a..0aea268a4f1c0d97bfcded31110a2a0d2a2567f1 100644 (file)
@@ -106,19 +106,16 @@ lnet_ni_free(struct lnet_ni *ni)
        if (ni->ni_cpts)
                cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts);
 
-       if (ni->ni_lnd_tunables)
-               LIBCFS_FREE(ni->ni_lnd_tunables, sizeof(*ni->ni_lnd_tunables));
+       kfree(ni->ni_lnd_tunables);
 
-       for (i = 0; i < LNET_MAX_INTERFACES && ni->ni_interfaces[i]; i++) {
-               LIBCFS_FREE(ni->ni_interfaces[i],
-                           strlen(ni->ni_interfaces[i]) + 1);
-       }
+       for (i = 0; i < LNET_MAX_INTERFACES && ni->ni_interfaces[i]; i++)
+               kfree(ni->ni_interfaces[i]);
 
        /* release reference to net namespace */
        if (ni->ni_net_ns)
                put_net(ni->ni_net_ns);
 
-       LIBCFS_FREE(ni, sizeof(*ni));
+       kfree(ni);
 }
 
 struct lnet_ni *
@@ -135,7 +132,7 @@ lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist)
                return NULL;
        }
 
-       LIBCFS_ALLOC(ni, sizeof(*ni));
+       ni = kzalloc(sizeof(*ni), GFP_NOFS);
        if (!ni) {
                CERROR("Out of memory creating network %s\n",
                       libcfs_net2str(net));
@@ -170,7 +167,7 @@ lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist)
 
                LASSERT(rc <= LNET_CPT_NUMBER);
                if (rc == LNET_CPT_NUMBER) {
-                       LIBCFS_FREE(ni->ni_cpts, rc * sizeof(ni->ni_cpts[0]));
+                       cfs_expr_list_values_free(ni->ni_cpts, LNET_CPT_NUMBER);
                        ni->ni_cpts = NULL;
                }
 
@@ -198,7 +195,6 @@ int
 lnet_parse_networks(struct list_head *nilist, char *networks)
 {
        struct cfs_expr_list *el = NULL;
-       int tokensize;
        char *tokens;
        char *str;
        char *tmp;
@@ -219,15 +215,12 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
                return -EINVAL;
        }
 
-       tokensize = strlen(networks) + 1;
-
-       LIBCFS_ALLOC(tokens, tokensize);
+       tokens = kstrdup(networks, GFP_KERNEL);
        if (!tokens) {
                CERROR("Can't allocate net tokens\n");
                return -ENOMEM;
        }
 
-       memcpy(tokens, networks, tokensize);
        tmp = tokens;
        str = tokens;
 
@@ -275,7 +268,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
 
                        if (comma)
                                *comma++ = 0;
-                       net = libcfs_str2net(cfs_trimwhite(str));
+                       net = libcfs_str2net(strim(str));
 
                        if (net == LNET_NIDNET(LNET_NID_ANY)) {
                                LCONSOLE_ERROR_MSG(0x113,
@@ -298,7 +291,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
                }
 
                *bracket = 0;
-               net = libcfs_str2net(cfs_trimwhite(str));
+               net = libcfs_str2net(strim(str));
                if (net == LNET_NIDNET(LNET_NID_ANY)) {
                        tmp = str;
                        goto failed_syntax;
@@ -328,7 +321,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
                        if (comma)
                                *comma++ = 0;
 
-                       iface = cfs_trimwhite(iface);
+                       iface = strim(iface);
                        if (!*iface) {
                                tmp = iface;
                                goto failed_syntax;
@@ -349,14 +342,11 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
                         * The newly allocated ni_interfaces[] can be
                         * freed when freeing the NI
                         */
-                       LIBCFS_ALLOC(ni->ni_interfaces[niface],
-                                    strlen(iface) + 1);
+                       ni->ni_interfaces[niface] = kstrdup(iface, GFP_KERNEL);
                        if (!ni->ni_interfaces[niface]) {
                                CERROR("Can't allocate net interface name\n");
                                goto failed;
                        }
-                       strncpy(ni->ni_interfaces[niface], iface,
-                               strlen(iface));
                        niface++;
                        iface = comma;
                } while (iface);
@@ -365,7 +355,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
                comma = strchr(bracket + 1, ',');
                if (comma) {
                        *comma = 0;
-                       str = cfs_trimwhite(str);
+                       str = strim(str);
                        if (*str) {
                                tmp = str;
                                goto failed_syntax;
@@ -374,7 +364,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
                        continue;
                }
 
-               str = cfs_trimwhite(str);
+               str = strim(str);
                if (*str) {
                        tmp = str;
                        goto failed_syntax;
@@ -384,7 +374,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
        list_for_each(temp_node, nilist)
                nnets++;
 
-       LIBCFS_FREE(tokens, tokensize);
+       kfree(tokens);
        return nnets;
 
  failed_syntax:
@@ -400,7 +390,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
        if (el)
                cfs_expr_list_free(el);
 
-       LIBCFS_FREE(tokens, tokensize);
+       kfree(tokens);
 
        return -EINVAL;
 }
@@ -424,7 +414,7 @@ lnet_new_text_buf(int str_len)
                return NULL;
        }
 
-       LIBCFS_ALLOC(ltb, nob);
+       ltb = kzalloc(nob, GFP_KERNEL);
        if (!ltb)
                return NULL;
 
@@ -438,7 +428,7 @@ static void
 lnet_free_text_buf(struct lnet_text_buf *ltb)
 {
        lnet_tbnob -= ltb->ltb_size;
-       LIBCFS_FREE(ltb, ltb->ltb_size);
+       kfree(ltb);
 }
 
 static void
@@ -1156,7 +1146,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp)
        if (nif <= 0)
                return nif;
 
-       LIBCFS_ALLOC(ipaddrs, nif * sizeof(*ipaddrs));
+       ipaddrs = kcalloc(nif, sizeof(*ipaddrs), GFP_KERNEL);
        if (!ipaddrs) {
                CERROR("Can't allocate ipaddrs[%d]\n", nif);
                lnet_ipif_free_enumeration(ifnames, nif);
@@ -1189,7 +1179,8 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp)
                *ipaddrsp = ipaddrs;
        } else {
                if (nip > 0) {
-                       LIBCFS_ALLOC(ipaddrs2, nip * sizeof(*ipaddrs2));
+                       ipaddrs2 = kcalloc(nip, sizeof(*ipaddrs2),
+                                          GFP_KERNEL);
                        if (!ipaddrs2) {
                                CERROR("Can't allocate ipaddrs[%d]\n", nip);
                                nip = -ENOMEM;
@@ -1200,7 +1191,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp)
                                rc = nip;
                        }
                }
-               LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs));
+               kfree(ipaddrs);
        }
        return nip;
 }
@@ -1226,7 +1217,7 @@ lnet_parse_ip2nets(char **networksp, char *ip2nets)
        }
 
        rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip);
-       LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs));
+       kfree(ipaddrs);
 
        if (rc < 0) {
                LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc);
index daf74427700315127a664ac154979e1f84999db5..a173b69e2f922701aa572fba77b13f387b05cd97 100644 (file)
@@ -90,12 +90,13 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback,
        if (!count && callback == LNET_EQ_HANDLER_NONE)
                return -EINVAL;
 
-       eq = lnet_eq_alloc();
+       eq = kzalloc(sizeof(*eq), GFP_NOFS);
        if (!eq)
                return -ENOMEM;
 
        if (count) {
-               LIBCFS_ALLOC(eq->eq_events, count * sizeof(struct lnet_event));
+               eq->eq_events = kvmalloc_array(count, sizeof(struct lnet_event),
+                                              GFP_KERNEL | __GFP_ZERO);
                if (!eq->eq_events)
                        goto failed;
                /*
@@ -132,13 +133,12 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback,
        return 0;
 
 failed:
-       if (eq->eq_events)
-               LIBCFS_FREE(eq->eq_events, count * sizeof(struct lnet_event));
+       kvfree(eq->eq_events);
 
        if (eq->eq_refs)
                cfs_percpt_free(eq->eq_refs);
 
-       lnet_eq_free(eq);
+       kfree(eq);
        return -ENOMEM;
 }
 EXPORT_SYMBOL(LNetEQAlloc);
@@ -197,13 +197,12 @@ LNetEQFree(struct lnet_handle_eq eqh)
 
        lnet_res_lh_invalidate(&eq->eq_lh);
        list_del(&eq->eq_list);
-       lnet_eq_free(eq);
+       kfree(eq);
  out:
        lnet_eq_wait_unlock();
        lnet_res_unlock(LNET_LOCK_EX);
 
-       if (events)
-               LIBCFS_FREE(events, size * sizeof(struct lnet_event));
+       kvfree(events);
        if (refs)
                cfs_percpt_free(refs);
 
index ac5b9593d59716b7e92a15b23c36cf87a5701469..8a22514aaf713ab7c00dfc71114c250de71d8cfb 100644 (file)
@@ -81,7 +81,7 @@ lnet_md_unlink(struct lnet_libmd *md)
 
        LASSERT(!list_empty(&md->md_list));
        list_del_init(&md->md_list);
-       lnet_md_free(md);
+       kfree(md);
 }
 
 static int
@@ -173,7 +173,7 @@ lnet_md_link(struct lnet_libmd *md, struct lnet_handle_eq eq_handle, int cpt)
        /*
         * NB we are passed an allocated, but inactive md.
         * if we return success, caller may lnet_md_unlink() it.
-        * otherwise caller may only lnet_md_free() it.
+        * otherwise caller may only kfree() it.
         */
        /*
         * This implementation doesn't know how to create START events or
@@ -329,7 +329,7 @@ LNetMDAttach(struct lnet_handle_me meh, struct lnet_md umd,
 out_unlock:
        lnet_res_unlock(cpt);
 out_free:
-       lnet_md_free(md);
+       kfree(md);
        return rc;
 }
 EXPORT_SYMBOL(LNetMDAttach);
@@ -390,7 +390,7 @@ LNetMDBind(struct lnet_md umd, enum lnet_unlink unlink,
 out_unlock:
        lnet_res_unlock(cpt);
 out_free:
-       lnet_md_free(md);
+       kfree(md);
 
        return rc;
 }
index dd5d3cf6d3e22e2db46a65d5041cde411c8087e7..672e37bdd045c443e3dace6b9081f60621d81d54 100644 (file)
@@ -90,7 +90,7 @@ LNetMEAttach(unsigned int portal,
        if (!mtable) /* can't match portal type */
                return -EPERM;
 
-       me = lnet_me_alloc();
+       me = kzalloc(sizeof(*me), GFP_NOFS);
        if (!me)
                return -ENOMEM;
 
@@ -157,7 +157,7 @@ LNetMEInsert(struct lnet_handle_me current_meh,
        if (pos == LNET_INS_LOCAL)
                return -EPERM;
 
-       new_me = lnet_me_alloc();
+       new_me = kzalloc(sizeof(*new_me), GFP_NOFS);
        if (!new_me)
                return -ENOMEM;
 
@@ -167,7 +167,7 @@ LNetMEInsert(struct lnet_handle_me current_meh,
 
        current_me = lnet_handle2me(&current_meh);
        if (!current_me) {
-               lnet_me_free(new_me);
+               kfree(new_me);
 
                lnet_res_unlock(cpt);
                return -ENOENT;
@@ -178,7 +178,7 @@ LNetMEInsert(struct lnet_handle_me current_meh,
        ptl = the_lnet.ln_portals[current_me->me_portal];
        if (lnet_ptl_is_unique(ptl)) {
                /* nosense to insertion on unique portal */
-               lnet_me_free(new_me);
+               kfree(new_me);
                lnet_res_unlock(cpt);
                return -EPERM;
        }
@@ -270,5 +270,5 @@ lnet_me_unlink(struct lnet_me *me)
        }
 
        lnet_res_lh_invalidate(&me->me_lh);
-       lnet_me_free(me);
+       kfree(me);
 }
index 68d16ffec980e98dc4c4e5d672a005e157ad8b57..c673037dbce4338c3feed236d3f9c167b0c4b79d 100644 (file)
@@ -57,7 +57,7 @@ lnet_fail_nid(lnet_nid_t nid, unsigned int threshold)
        /* NB: use lnet_net_lock(0) to serialize operations on test peers */
        if (threshold) {
                /* Adding a new entry */
-               LIBCFS_ALLOC(tp, sizeof(*tp));
+               tp = kzalloc(sizeof(*tp), GFP_NOFS);
                if (!tp)
                        return -ENOMEM;
 
@@ -90,7 +90,7 @@ lnet_fail_nid(lnet_nid_t nid, unsigned int threshold)
 
        list_for_each_entry_safe(tp, temp, &cull, tp_list) {
                list_del(&tp->tp_list);
-               LIBCFS_FREE(tp, sizeof(*tp));
+               kfree(tp);
        }
        return 0;
 }
@@ -149,7 +149,7 @@ fail_peer(lnet_nid_t nid, int outgoing)
        list_for_each_entry_safe(tp, temp, &cull, tp_list) {
                list_del(&tp->tp_list);
 
-               LIBCFS_FREE(tp, sizeof(*tp));
+               kfree(tp);
        }
 
        return fail;
@@ -1769,7 +1769,7 @@ lnet_parse(struct lnet_ni *ni, struct lnet_hdr *hdr, lnet_nid_t from_nid,
                goto drop;
        }
 
-       msg = lnet_msg_alloc();
+       msg = kzalloc(sizeof(*msg), GFP_NOFS);
        if (!msg) {
                CERROR("%s, src %s: Dropping %s (out of memory)\n",
                       libcfs_nid2str(from_nid), libcfs_nid2str(src_nid),
@@ -1777,7 +1777,7 @@ lnet_parse(struct lnet_ni *ni, struct lnet_hdr *hdr, lnet_nid_t from_nid,
                goto drop;
        }
 
-       /* msg zeroed in lnet_msg_alloc;
+       /* msg zeroed by kzalloc()
         * i.e. flags all clear, pointers NULL etc
         */
        msg->msg_type = type;
@@ -1812,7 +1812,7 @@ lnet_parse(struct lnet_ni *ni, struct lnet_hdr *hdr, lnet_nid_t from_nid,
                CERROR("%s, src %s: Dropping %s (error %d looking up sender)\n",
                       libcfs_nid2str(from_nid), libcfs_nid2str(src_nid),
                       lnet_msgtyp2str(type), rc);
-               lnet_msg_free(msg);
+               kfree(msg);
                if (rc == -ESHUTDOWN)
                        /* We are shutting down. Don't do anything more */
                        return 0;
@@ -2010,7 +2010,7 @@ LNetPut(lnet_nid_t self, struct lnet_handle_md mdh, enum lnet_ack_req ack,
                return -EIO;
        }
 
-       msg = lnet_msg_alloc();
+       msg = kzalloc(sizeof(*msg), GFP_NOFS);
        if (!msg) {
                CERROR("Dropping PUT to %s: ENOMEM on struct lnet_msg\n",
                       libcfs_id2str(target));
@@ -2031,7 +2031,7 @@ LNetPut(lnet_nid_t self, struct lnet_handle_md mdh, enum lnet_ack_req ack,
                               md->md_me->me_portal);
                lnet_res_unlock(cpt);
 
-               lnet_msg_free(msg);
+               kfree(msg);
                return -ENOENT;
        }
 
@@ -2086,7 +2086,7 @@ lnet_create_reply_msg(struct lnet_ni *ni, struct lnet_msg *getmsg)
         * CAVEAT EMPTOR: 'getmsg' is the original GET, which is freed when
         * lnet_finalize() is called on it, so the LND must call this first
         */
-       struct lnet_msg *msg = lnet_msg_alloc();
+       struct lnet_msg *msg = kzalloc(sizeof(*msg), GFP_NOFS);
        struct lnet_libmd *getmd = getmsg->msg_md;
        struct lnet_process_id peer_id = getmsg->msg_target;
        int cpt;
@@ -2146,8 +2146,7 @@ lnet_create_reply_msg(struct lnet_ni *ni, struct lnet_msg *getmsg)
        the_lnet.ln_counters[cpt]->drop_length += getmd->md_length;
        lnet_net_unlock(cpt);
 
-       if (msg)
-               lnet_msg_free(msg);
+       kfree(msg);
 
        return NULL;
 }
@@ -2215,7 +2214,7 @@ LNetGet(lnet_nid_t self, struct lnet_handle_md mdh,
                return -EIO;
        }
 
-       msg = lnet_msg_alloc();
+       msg = kzalloc(sizeof(*msg), GFP_NOFS);
        if (!msg) {
                CERROR("Dropping GET to %s: ENOMEM on struct lnet_msg\n",
                       libcfs_id2str(target));
@@ -2236,7 +2235,7 @@ LNetGet(lnet_nid_t self, struct lnet_handle_md mdh,
 
                lnet_res_unlock(cpt);
 
-               lnet_msg_free(msg);
+               kfree(msg);
                return -ENOENT;
        }
 
index c72ef05b242000c4a5055c35f55983d04ce140bf..0091273c04b921ce1349fc89d51aec70fd617ead 100644 (file)
@@ -433,7 +433,7 @@ lnet_complete_msg_locked(struct lnet_msg *msg, int cpt)
        }
 
        lnet_msg_decommit(msg, cpt, status);
-       lnet_msg_free(msg);
+       kfree(msg);
        return 0;
 }
 
@@ -466,7 +466,7 @@ lnet_finalize(struct lnet_ni *ni, struct lnet_msg *msg, int status)
        if (!msg->msg_tx_committed && !msg->msg_rx_committed) {
                /* not committed to network yet */
                LASSERT(!msg->msg_onactivelist);
-               lnet_msg_free(msg);
+               kfree(msg);
                return;
        }
 
@@ -546,19 +546,15 @@ lnet_msg_container_cleanup(struct lnet_msg_container *container)
                LASSERT(msg->msg_onactivelist);
                msg->msg_onactivelist = 0;
                list_del(&msg->msg_activelist);
-               lnet_msg_free(msg);
+               kfree(msg);
                count++;
        }
 
        if (count > 0)
                CERROR("%d active msg on exit\n", count);
 
-       if (container->msc_finalizers) {
-               LIBCFS_FREE(container->msc_finalizers,
-                           container->msc_nfinalizers *
-                           sizeof(*container->msc_finalizers));
-               container->msc_finalizers = NULL;
-       }
+       kvfree(container->msc_finalizers);
+       container->msc_finalizers = NULL;
        container->msc_init = 0;
 }
 
@@ -573,9 +569,9 @@ lnet_msg_container_setup(struct lnet_msg_container *container, int cpt)
        /* number of CPUs */
        container->msc_nfinalizers = cfs_cpt_weight(lnet_cpt_table(), cpt);
 
-       LIBCFS_CPT_ALLOC(container->msc_finalizers, lnet_cpt_table(), cpt,
-                        container->msc_nfinalizers *
-                        sizeof(*container->msc_finalizers));
+       container->msc_finalizers = kvzalloc_cpt(container->msc_nfinalizers *
+                                                sizeof(*container->msc_finalizers),
+                                                GFP_KERNEL, cpt);
 
        if (!container->msc_finalizers) {
                CERROR("Failed to allocate message finalizers\n");
index 8ae93bf6fd1baf05ea5dc8bb7882661ccc312a20..471f2f6c86f45cc1b73e41bd42c0c67baeea5ae9 100644 (file)
@@ -771,11 +771,11 @@ lnet_ptl_cleanup(struct lnet_portal *ptl)
                                                struct lnet_me, me_list);
                                CERROR("Active ME %p on exit\n", me);
                                list_del(&me->me_list);
-                               lnet_me_free(me);
+                               kfree(me);
                        }
                }
                /* the extra entry is for MEs with ignore bits */
-               LIBCFS_FREE(mhash, sizeof(*mhash) * (LNET_MT_HASH_SIZE + 1));
+               kvfree(mhash);
        }
 
        cfs_percpt_free(ptl->ptl_mtables);
@@ -803,8 +803,8 @@ lnet_ptl_setup(struct lnet_portal *ptl, int index)
        spin_lock_init(&ptl->ptl_lock);
        cfs_percpt_for_each(mtable, i, ptl->ptl_mtables) {
                /* the extra entry is for MEs with ignore bits */
-               LIBCFS_CPT_ALLOC(mhash, lnet_cpt_table(), i,
-                                sizeof(*mhash) * (LNET_MT_HASH_SIZE + 1));
+               mhash = kvzalloc_cpt(sizeof(*mhash) * (LNET_MT_HASH_SIZE + 1),
+                                    GFP_KERNEL, i);
                if (!mhash) {
                        CERROR("Failed to create match hash for portal %d\n",
                               index);
index ed46aaca0ba3f489e6e8176af93959d2cc12ae99..ce93806eefca077f33478f2765f1a9e6d9fa71c8 100644 (file)
@@ -170,7 +170,7 @@ lnet_ipif_enumerate(char ***namesp)
                              nalloc);
                }
 
-               LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
+               ifr = kzalloc(nalloc * sizeof(*ifr), GFP_KERNEL);
                if (!ifr) {
                        CERROR("ENOMEM enumerating up to %d interfaces\n",
                               nalloc);
@@ -195,14 +195,14 @@ lnet_ipif_enumerate(char ***namesp)
                if (nfound < nalloc || toobig)
                        break;
 
-               LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
+               kfree(ifr);
                nalloc *= 2;
        }
 
        if (!nfound)
                goto out1;
 
-       LIBCFS_ALLOC(names, nfound * sizeof(*names));
+       names = kzalloc(nfound * sizeof(*names), GFP_KERNEL);
        if (!names) {
                rc = -ENOMEM;
                goto out1;
@@ -218,7 +218,7 @@ lnet_ipif_enumerate(char ***namesp)
                        goto out2;
                }
 
-               LIBCFS_ALLOC(names[i], IFNAMSIZ);
+               names[i] = kmalloc(IFNAMSIZ, GFP_KERNEL);
                if (!names[i]) {
                        rc = -ENOMEM;
                        goto out2;
@@ -235,7 +235,7 @@ out2:
        if (rc < 0)
                lnet_ipif_free_enumeration(names, nfound);
 out1:
-       LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
+       kfree(ifr);
 out0:
        return rc;
 }
@@ -249,9 +249,9 @@ lnet_ipif_free_enumeration(char **names, int n)
        LASSERT(n > 0);
 
        for (i = 0; i < n && names[i]; i++)
-               LIBCFS_FREE(names[i], IFNAMSIZ);
+               kfree(names[i]);
 
-       LIBCFS_FREE(names, n * sizeof(*names));
+       kfree(names);
 }
 EXPORT_SYMBOL(lnet_ipif_free_enumeration);
 
index 5a5d1811ffbeac436dd02fd8fc5700569ae5ef25..e3468cef273b95c615ff33508e86010ed304ef33 100644 (file)
@@ -161,7 +161,7 @@ lnet_drop_rule_add(struct lnet_fault_attr *attr)
        if (lnet_fault_attr_validate(attr))
                return -EINVAL;
 
-       CFS_ALLOC_PTR(rule);
+       rule = kzalloc(sizeof(*rule), GFP_NOFS);
        if (!rule)
                return -ENOMEM;
 
@@ -170,10 +170,10 @@ lnet_drop_rule_add(struct lnet_fault_attr *attr)
        rule->dr_attr = *attr;
        if (attr->u.drop.da_interval) {
                rule->dr_time_base = cfs_time_shift(attr->u.drop.da_interval);
-               rule->dr_drop_time = cfs_time_shift(cfs_rand() %
-                                                   attr->u.drop.da_interval);
+               rule->dr_drop_time = cfs_time_shift(
+                       prandom_u32_max(attr->u.drop.da_interval));
        } else {
-               rule->dr_drop_at = cfs_rand() % attr->u.drop.da_rate;
+               rule->dr_drop_at = prandom_u32_max(attr->u.drop.da_rate);
        }
 
        lnet_net_lock(LNET_LOCK_EX);
@@ -223,7 +223,7 @@ lnet_drop_rule_del(lnet_nid_t src, lnet_nid_t dst)
                       rule->dr_attr.u.drop.da_interval);
 
                list_del(&rule->dr_link);
-               CFS_FREE_PTR(rule);
+               kfree(rule);
                n++;
        }
 
@@ -277,10 +277,10 @@ lnet_drop_rule_reset(void)
 
                memset(&rule->dr_stat, 0, sizeof(rule->dr_stat));
                if (attr->u.drop.da_rate) {
-                       rule->dr_drop_at = cfs_rand() % attr->u.drop.da_rate;
+                       rule->dr_drop_at = prandom_u32_max(attr->u.drop.da_rate);
                } else {
-                       rule->dr_drop_time = cfs_time_shift(cfs_rand() %
-                                               attr->u.drop.da_interval);
+                       rule->dr_drop_time = cfs_time_shift(
+                               prandom_u32_max(attr->u.drop.da_interval));
                        rule->dr_time_base = cfs_time_shift(attr->u.drop.da_interval);
                }
                spin_unlock(&rule->dr_lock);
@@ -315,8 +315,8 @@ drop_rule_match(struct lnet_drop_rule *rule, lnet_nid_t src,
                                rule->dr_time_base = now;
 
                        rule->dr_drop_time = rule->dr_time_base +
-                                            cfs_time_seconds(cfs_rand() %
-                                               attr->u.drop.da_interval);
+                               cfs_time_seconds(
+                                       prandom_u32_max(attr->u.drop.da_interval));
                        rule->dr_time_base += cfs_time_seconds(attr->u.drop.da_interval);
 
                        CDEBUG(D_NET, "Drop Rule %s->%s: next drop : %lu\n",
@@ -330,7 +330,7 @@ drop_rule_match(struct lnet_drop_rule *rule, lnet_nid_t src,
 
                if (!do_div(rule->dr_stat.fs_count, attr->u.drop.da_rate)) {
                        rule->dr_drop_at = rule->dr_stat.fs_count +
-                                          cfs_rand() % attr->u.drop.da_rate;
+                               prandom_u32_max(attr->u.drop.da_rate);
                        CDEBUG(D_NET, "Drop Rule %s->%s: next drop: %lu\n",
                               libcfs_nid2str(attr->fa_src),
                               libcfs_nid2str(attr->fa_dst), rule->dr_drop_at);
@@ -452,7 +452,7 @@ delay_rule_decref(struct lnet_delay_rule *rule)
                LASSERT(list_empty(&rule->dl_msg_list));
                LASSERT(list_empty(&rule->dl_link));
 
-               CFS_FREE_PTR(rule);
+               kfree(rule);
        }
 }
 
@@ -483,8 +483,9 @@ delay_rule_match(struct lnet_delay_rule *rule, lnet_nid_t src,
                                rule->dl_time_base = now;
 
                        rule->dl_delay_time = rule->dl_time_base +
-                                            cfs_time_seconds(cfs_rand() %
-                                               attr->u.delay.la_interval);
+                               cfs_time_seconds(
+                                       prandom_u32_max(
+                                               attr->u.delay.la_interval));
                        rule->dl_time_base += cfs_time_seconds(attr->u.delay.la_interval);
 
                        CDEBUG(D_NET, "Delay Rule %s->%s: next delay : %lu\n",
@@ -498,7 +499,7 @@ delay_rule_match(struct lnet_delay_rule *rule, lnet_nid_t src,
                /* generate the next random rate sequence */
                if (!do_div(rule->dl_stat.fs_count, attr->u.delay.la_rate)) {
                        rule->dl_delay_at = rule->dl_stat.fs_count +
-                                           cfs_rand() % attr->u.delay.la_rate;
+                               prandom_u32_max(attr->u.delay.la_rate);
                        CDEBUG(D_NET, "Delay Rule %s->%s: next delay: %lu\n",
                               libcfs_nid2str(attr->fa_src),
                               libcfs_nid2str(attr->fa_dst), rule->dl_delay_at);
@@ -738,7 +739,7 @@ lnet_delay_rule_add(struct lnet_fault_attr *attr)
        if (lnet_fault_attr_validate(attr))
                return -EINVAL;
 
-       CFS_ALLOC_PTR(rule);
+       rule = kzalloc(sizeof(*rule), GFP_NOFS);
        if (!rule)
                return -ENOMEM;
 
@@ -771,10 +772,10 @@ lnet_delay_rule_add(struct lnet_fault_attr *attr)
        rule->dl_attr = *attr;
        if (attr->u.delay.la_interval) {
                rule->dl_time_base = cfs_time_shift(attr->u.delay.la_interval);
-               rule->dl_delay_time = cfs_time_shift(cfs_rand() %
-                                                    attr->u.delay.la_interval);
+               rule->dl_delay_time = cfs_time_shift(
+                       prandom_u32_max(attr->u.delay.la_interval));
        } else {
-               rule->dl_delay_at = cfs_rand() % attr->u.delay.la_rate;
+               rule->dl_delay_at = prandom_u32_max(attr->u.delay.la_rate);
        }
 
        rule->dl_msg_send = -1;
@@ -792,7 +793,7 @@ lnet_delay_rule_add(struct lnet_fault_attr *attr)
        return 0;
 failed:
        mutex_unlock(&delay_dd.dd_mutex);
-       CFS_FREE_PTR(rule);
+       kfree(rule);
        return rc;
 }
 
@@ -920,10 +921,11 @@ lnet_delay_rule_reset(void)
 
                memset(&rule->dl_stat, 0, sizeof(rule->dl_stat));
                if (attr->u.delay.la_rate) {
-                       rule->dl_delay_at = cfs_rand() % attr->u.delay.la_rate;
+                       rule->dl_delay_at = prandom_u32_max(attr->u.delay.la_rate);
                } else {
-                       rule->dl_delay_time = cfs_time_shift(cfs_rand() %
-                                               attr->u.delay.la_interval);
+                       rule->dl_delay_time =
+                               cfs_time_shift(prandom_u32_max(
+                                                      attr->u.delay.la_interval));
                        rule->dl_time_base = cfs_time_shift(attr->u.delay.la_interval);
                }
                spin_unlock(&rule->dl_lock);
index 05b120c2d45a309f44f1d8d15f776f103be1e1e1..3aba1421c741f80b07dcb2388219d3aa97688fbc 100644 (file)
@@ -166,7 +166,7 @@ parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange)
                return 0;
        }
 
-       LIBCFS_ALLOC(addrrange, sizeof(struct addrrange));
+       addrrange = kzalloc(sizeof(struct addrrange), GFP_NOFS);
        if (!addrrange)
                return -ENOMEM;
        list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges);
@@ -225,7 +225,7 @@ add_nidrange(const struct cfs_lstr *src,
                return nr;
        }
 
-       LIBCFS_ALLOC(nr, sizeof(struct nidrange));
+       nr = kzalloc(sizeof(struct nidrange), GFP_NOFS);
        if (!nr)
                return NULL;
        list_add_tail(&nr->nr_link, nidlist);
@@ -286,7 +286,7 @@ free_addrranges(struct list_head *list)
 
                cfs_expr_list_free_list(&ar->ar_numaddr_ranges);
                list_del(&ar->ar_link);
-               LIBCFS_FREE(ar, sizeof(struct addrrange));
+               kfree(ar);
        }
 }
 
@@ -308,7 +308,7 @@ cfs_free_nidlist(struct list_head *list)
                nr = list_entry(pos, struct nidrange, nr_link);
                free_addrranges(&nr->nr_addrranges);
                list_del(pos);
-               LIBCFS_FREE(nr, sizeof(struct nidrange));
+               kfree(nr);
        }
 }
 EXPORT_SYMBOL(cfs_free_nidlist);
index 5e94ad349454b7ea22be99547a0c36c65af192bc..3e157c10fec4a8727edcd83bcc9b5bbd8a85324b 100644 (file)
@@ -56,8 +56,8 @@ lnet_peer_tables_create(void)
        cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) {
                INIT_LIST_HEAD(&ptable->pt_deathrow);
 
-               LIBCFS_CPT_ALLOC(hash, lnet_cpt_table(), i,
-                                LNET_PEER_HASH_SIZE * sizeof(*hash));
+               hash = kvmalloc_cpt(LNET_PEER_HASH_SIZE * sizeof(*hash),
+                                   GFP_KERNEL, i);
                if (!hash) {
                        CERROR("Failed to create peer hash table\n");
                        lnet_peer_tables_destroy();
@@ -94,7 +94,7 @@ lnet_peer_tables_destroy(void)
                for (j = 0; j < LNET_PEER_HASH_SIZE; j++)
                        LASSERT(list_empty(&hash[j]));
 
-               LIBCFS_FREE(hash, LNET_PEER_HASH_SIZE * sizeof(*hash));
+               kvfree(hash);
        }
 
        cfs_percpt_free(the_lnet.ln_peer_tables);
@@ -212,7 +212,7 @@ lnet_peer_tables_cleanup(struct lnet_ni *ni)
 
        list_for_each_entry_safe(lp, temp, &deathrow, lp_hashlist) {
                list_del(&lp->lp_hashlist);
-               LIBCFS_FREE(lp, sizeof(*lp));
+               kfree(lp);
        }
 }
 
@@ -297,7 +297,7 @@ lnet_nid2peer_locked(struct lnet_peer **lpp, lnet_nid_t nid, int cpt)
        if (lp)
                memset(lp, 0, sizeof(*lp));
        else
-               LIBCFS_CPT_ALLOC(lp, lnet_cpt_table(), cpt2, sizeof(*lp));
+               lp = kzalloc_cpt(sizeof(*lp), GFP_NOFS, cpt2);
 
        if (!lp) {
                rc = -ENOMEM;
index 88283ca3f860ac880ea58efc8ece9ff1e36be9d2..6504761ca598bb6ecfa2a27f3b05242e059fdfb7 100644 (file)
@@ -238,28 +238,25 @@ lnet_find_net_locked(__u32 net)
 static void lnet_shuffle_seed(void)
 {
        static int seeded;
-       __u32 lnd_type, seed[2];
-       struct timespec64 ts;
        struct lnet_ni *ni;
 
        if (seeded)
                return;
 
-       cfs_get_random_bytes(seed, sizeof(seed));
-
        /*
         * Nodes with small feet have little entropy
         * the NID for this node gives the most entropy in the low bits
         */
        list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) {
-               lnd_type = LNET_NETTYP(LNET_NIDNET(ni->ni_nid));
+               __u32 lnd_type, seed;
 
-               if (lnd_type != LOLND)
-                       seed[0] ^= (LNET_NIDADDR(ni->ni_nid) | lnd_type);
+               lnd_type = LNET_NETTYP(LNET_NIDNET(ni->ni_nid));
+               if (lnd_type != LOLND) {
+                       seed = (LNET_NIDADDR(ni->ni_nid) | lnd_type);
+                       add_device_randomness(&seed, sizeof(seed));
+               }
        }
 
-       ktime_get_ts64(&ts);
-       cfs_srand(ts.tv_sec ^ seed[0], ts.tv_nsec ^ seed[1]);
        seeded = 1;
 }
 
@@ -277,8 +274,8 @@ lnet_add_route_to_rnet(struct lnet_remotenet *rnet, struct lnet_route *route)
                len++;
        }
 
-       /* len+1 positions to add a new entry, also prevents division by 0 */
-       offset = cfs_rand() % (len + 1);
+       /* len+1 positions to add a new entry */
+       offset = prandom_u32_max(len + 1);
        list_for_each(e, &rnet->lrn_routes) {
                if (!offset)
                        break;
@@ -318,15 +315,13 @@ lnet_add_route(__u32 net, __u32 hops, lnet_nid_t gateway,
                return -EEXIST;
 
        /* Assume net, route, all new */
-       LIBCFS_ALLOC(route, sizeof(*route));
-       LIBCFS_ALLOC(rnet, sizeof(*rnet));
+       route = kzalloc(sizeof(*route), GFP_NOFS);
+       rnet = kzalloc(sizeof(*rnet), GFP_NOFS);
        if (!route || !rnet) {
                CERROR("Out of memory creating route %s %d %s\n",
                       libcfs_net2str(net), hops, libcfs_nid2str(gateway));
-               if (route)
-                       LIBCFS_FREE(route, sizeof(*route));
-               if (rnet)
-                       LIBCFS_FREE(rnet, sizeof(*rnet));
+               kfree(route);
+               kfree(rnet);
                return -ENOMEM;
        }
 
@@ -342,8 +337,8 @@ lnet_add_route(__u32 net, __u32 hops, lnet_nid_t gateway,
        if (rc) {
                lnet_net_unlock(LNET_LOCK_EX);
 
-               LIBCFS_FREE(route, sizeof(*route));
-               LIBCFS_FREE(rnet, sizeof(*rnet));
+               kfree(route);
+               kfree(rnet);
 
                if (rc == -EHOSTUNREACH) /* gateway is not on a local net */
                        return rc;      /* ignore the route entry */
@@ -398,11 +393,11 @@ lnet_add_route(__u32 net, __u32 hops, lnet_nid_t gateway,
 
        if (!add_route) {
                rc = -EEXIST;
-               LIBCFS_FREE(route, sizeof(*route));
+               kfree(route);
        }
 
        if (rnet != rnet2)
-               LIBCFS_FREE(rnet, sizeof(*rnet));
+               kfree(rnet);
 
        /* indicate to startup the router checker if configured */
        wake_up(&the_lnet.ln_rc_waitq);
@@ -520,10 +515,8 @@ lnet_del_route(__u32 net, lnet_nid_t gw_nid)
 
                        lnet_net_unlock(LNET_LOCK_EX);
 
-                       LIBCFS_FREE(route, sizeof(*route));
-
-                       if (rnet)
-                               LIBCFS_FREE(rnet, sizeof(*rnet));
+                       kfree(route);
+                       kfree(rnet);
 
                        rc = 0;
                        lnet_net_lock(LNET_LOCK_EX);
@@ -891,10 +884,9 @@ lnet_destroy_rc_data(struct lnet_rc_data *rcd)
                lnet_net_unlock(cpt);
        }
 
-       if (rcd->rcd_pinginfo)
-               LIBCFS_FREE(rcd->rcd_pinginfo, LNET_PINGINFO_SIZE);
+       kfree(rcd->rcd_pinginfo);
 
-       LIBCFS_FREE(rcd, sizeof(*rcd));
+       kfree(rcd);
 }
 
 static struct lnet_rc_data *
@@ -908,14 +900,14 @@ lnet_create_rc_data_locked(struct lnet_peer *gateway)
 
        lnet_net_unlock(gateway->lp_cpt);
 
-       LIBCFS_ALLOC(rcd, sizeof(*rcd));
+       rcd = kzalloc(sizeof(*rcd), GFP_NOFS);
        if (!rcd)
                goto out;
 
        LNetInvalidateMDHandle(&rcd->rcd_mdh);
        INIT_LIST_HEAD(&rcd->rcd_list);
 
-       LIBCFS_ALLOC(pi, LNET_PINGINFO_SIZE);
+       pi = kzalloc(LNET_PINGINFO_SIZE, GFP_NOFS);
        if (!pi)
                goto out;
 
@@ -1304,12 +1296,10 @@ rescan:
 void
 lnet_destroy_rtrbuf(struct lnet_rtrbuf *rb, int npages)
 {
-       int sz = offsetof(struct lnet_rtrbuf, rb_kiov[npages]);
-
        while (--npages >= 0)
                __free_page(rb->rb_kiov[npages].bv_page);
 
-       LIBCFS_FREE(rb, sz);
+       kfree(rb);
 }
 
 static struct lnet_rtrbuf *
@@ -1321,7 +1311,7 @@ lnet_new_rtrbuf(struct lnet_rtrbufpool *rbp, int cpt)
        struct lnet_rtrbuf *rb;
        int i;
 
-       LIBCFS_CPT_ALLOC(rb, lnet_cpt_table(), cpt, sz);
+       rb = kzalloc_cpt(sz, GFP_NOFS, cpt);
        if (!rb)
                return NULL;
 
@@ -1335,7 +1325,7 @@ lnet_new_rtrbuf(struct lnet_rtrbufpool *rbp, int cpt)
                        while (--i >= 0)
                                __free_page(rb->rb_kiov[i].bv_page);
 
-                       LIBCFS_FREE(rb, sz);
+                       kfree(rb);
                        return NULL;
                }
 
index d32d653edcb030c9032c8bb7e8589912bc82d79f..1a71ffebc889b73a70236b92c11c9a49429cf0d7 100644 (file)
@@ -91,13 +91,13 @@ static int __proc_lnet_stats(void *data, int write,
 
        /* read */
 
-       LIBCFS_ALLOC(ctrs, sizeof(*ctrs));
+       ctrs = kzalloc(sizeof(*ctrs), GFP_NOFS);
        if (!ctrs)
                return -ENOMEM;
 
-       LIBCFS_ALLOC(tmpstr, tmpsiz);
+       tmpstr = kmalloc(tmpsiz, GFP_KERNEL);
        if (!tmpstr) {
-               LIBCFS_FREE(ctrs, sizeof(*ctrs));
+               kfree(ctrs);
                return -ENOMEM;
        }
 
@@ -118,8 +118,8 @@ static int __proc_lnet_stats(void *data, int write,
                rc = cfs_trace_copyout_string(buffer, nob,
                                              tmpstr + pos, "\n");
 
-       LIBCFS_FREE(tmpstr, tmpsiz);
-       LIBCFS_FREE(ctrs, sizeof(*ctrs));
+       kfree(tmpstr);
+       kfree(ctrs);
        return rc;
 }
 
@@ -151,7 +151,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write,
        if (!*lenp)
                return 0;
 
-       LIBCFS_ALLOC(tmpstr, tmpsiz);
+       tmpstr = kmalloc(tmpsiz, GFP_KERNEL);
        if (!tmpstr)
                return -ENOMEM;
 
@@ -183,7 +183,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write,
 
                if (ver != LNET_PROC_VERSION(the_lnet.ln_remote_nets_version)) {
                        lnet_net_unlock(0);
-                       LIBCFS_FREE(tmpstr, tmpsiz);
+                       kfree(tmpstr);
                        return -ESTALE;
                }
 
@@ -248,7 +248,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write,
                }
        }
 
-       LIBCFS_FREE(tmpstr, tmpsiz);
+       kfree(tmpstr);
 
        if (!rc)
                *lenp = len;
@@ -275,7 +275,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write,
        if (!*lenp)
                return 0;
 
-       LIBCFS_ALLOC(tmpstr, tmpsiz);
+       tmpstr = kmalloc(tmpsiz, GFP_KERNEL);
        if (!tmpstr)
                return -ENOMEM;
 
@@ -303,7 +303,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write,
                if (ver != LNET_PROC_VERSION(the_lnet.ln_routers_version)) {
                        lnet_net_unlock(0);
 
-                       LIBCFS_FREE(tmpstr, tmpsiz);
+                       kfree(tmpstr);
                        return -ESTALE;
                }
 
@@ -385,7 +385,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write,
                }
        }
 
-       LIBCFS_FREE(tmpstr, tmpsiz);
+       kfree(tmpstr);
 
        if (!rc)
                *lenp = len;
@@ -418,7 +418,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write,
                return 0;
        }
 
-       LIBCFS_ALLOC(tmpstr, tmpsiz);
+       tmpstr = kmalloc(tmpsiz, GFP_KERNEL);
        if (!tmpstr)
                return -ENOMEM;
 
@@ -448,7 +448,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write,
 
                if (ver != LNET_PROC_VERSION(ptable->pt_version)) {
                        lnet_net_unlock(cpt);
-                       LIBCFS_FREE(tmpstr, tmpsiz);
+                       kfree(tmpstr);
                        return -ESTALE;
                }
 
@@ -556,7 +556,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write,
                        *ppos = LNET_PROC_POS_MAKE(cpt, ver, hash, hoff);
        }
 
-       LIBCFS_FREE(tmpstr, tmpsiz);
+       kfree(tmpstr);
 
        if (!rc)
                *lenp = len;
@@ -579,7 +579,7 @@ static int __proc_lnet_buffers(void *data, int write,
 
        /* (4 %d) * 4 * LNET_CPT_NUMBER */
        tmpsiz = 64 * (LNET_NRBPOOLS + 1) * LNET_CPT_NUMBER;
-       LIBCFS_ALLOC(tmpstr, tmpsiz);
+       tmpstr = kvmalloc(tmpsiz, GFP_KERNEL);
        if (!tmpstr)
                return -ENOMEM;
 
@@ -618,7 +618,7 @@ static int __proc_lnet_buffers(void *data, int write,
                rc = cfs_trace_copyout_string(buffer, nob,
                                              tmpstr + pos, NULL);
 
-       LIBCFS_FREE(tmpstr, tmpsiz);
+       kvfree(tmpstr);
        return rc;
 }
 
@@ -643,7 +643,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write,
        if (!*lenp)
                return 0;
 
-       LIBCFS_ALLOC(tmpstr, tmpsiz);
+       tmpstr = kvmalloc(tmpsiz, GFP_KERNEL);
        if (!tmpstr)
                return -ENOMEM;
 
@@ -744,7 +744,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write,
                        *ppos += 1;
        }
 
-       LIBCFS_FREE(tmpstr, tmpsiz);
+       kvfree(tmpstr);
 
        if (!rc)
                *lenp = len;
@@ -795,7 +795,7 @@ static int __proc_lnet_portal_rotor(void *data, int write,
        int rc;
        int i;
 
-       LIBCFS_ALLOC(buf, buf_len);
+       buf = kmalloc(buf_len, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
 
@@ -829,7 +829,7 @@ static int __proc_lnet_portal_rotor(void *data, int write,
        if (rc < 0)
                goto out;
 
-       tmp = cfs_trimwhite(buf);
+       tmp = strim(buf);
 
        rc = -EINVAL;
        lnet_res_lock(0);
@@ -843,7 +843,7 @@ static int __proc_lnet_portal_rotor(void *data, int write,
        }
        lnet_res_unlock(0);
 out:
-       LIBCFS_FREE(buf, buf_len);
+       kfree(buf);
        return rc;
 }
 
index 082c0afacf2309ea3a1df2cf44858447bb45312f..34ba440b3c028ac62894f777722558f9c3421b52 100644 (file)
@@ -45,7 +45,7 @@
 static int
 lst_session_new_ioctl(struct lstio_session_new_args *args)
 {
-       char *name;
+       char name[LST_NAME_SIZE + 1];
        int rc;
 
        if (!args->lstio_ses_idp ||     /* address for output sid */
@@ -55,13 +55,8 @@ lst_session_new_ioctl(struct lstio_session_new_args *args)
            args->lstio_ses_nmlen > LST_NAME_SIZE)
                return -EINVAL;
 
-       LIBCFS_ALLOC(name, args->lstio_ses_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_ses_namep,
                           args->lstio_ses_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_ses_nmlen + 1);
                return -EFAULT;
        }
 
@@ -74,7 +69,6 @@ lst_session_new_ioctl(struct lstio_session_new_args *args)
                                args->lstio_ses_force,
                                args->lstio_ses_idp);
 
-       LIBCFS_FREE(name, args->lstio_ses_nmlen + 1);
        return rc;
 }
 
@@ -112,7 +106,7 @@ lst_session_info_ioctl(struct lstio_session_info_args *args)
 static int
 lst_debug_ioctl(struct lstio_debug_args *args)
 {
-       char *name = NULL;
+       char name[LST_NAME_SIZE + 1];
        int client = 1;
        int rc;
 
@@ -128,16 +122,10 @@ lst_debug_ioctl(struct lstio_debug_args *args)
                return -EINVAL;
 
        if (args->lstio_dbg_namep) {
-               LIBCFS_ALLOC(name, args->lstio_dbg_nmlen + 1);
-               if (!name)
-                       return -ENOMEM;
 
                if (copy_from_user(name, args->lstio_dbg_namep,
-                                  args->lstio_dbg_nmlen)) {
-                       LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
-
+                                  args->lstio_dbg_nmlen))
                        return -EFAULT;
-               }
 
                name[args->lstio_dbg_nmlen] = 0;
        }
@@ -154,7 +142,7 @@ lst_debug_ioctl(struct lstio_debug_args *args)
                client = 0;
                /* fall through */
        case LST_OPC_BATCHCLI:
-               if (!name)
+               if (!args->lstio_dbg_namep)
                        goto out;
 
                rc = lstcon_batch_debug(args->lstio_dbg_timeout,
@@ -162,7 +150,7 @@ lst_debug_ioctl(struct lstio_debug_args *args)
                break;
 
        case LST_OPC_GROUP:
-               if (!name)
+               if (!args->lstio_dbg_namep)
                        goto out;
 
                rc = lstcon_group_debug(args->lstio_dbg_timeout,
@@ -185,16 +173,13 @@ lst_debug_ioctl(struct lstio_debug_args *args)
        }
 
 out:
-       if (name)
-               LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
-
        return rc;
 }
 
 static int
 lst_group_add_ioctl(struct lstio_group_add_args *args)
 {
-       char *name;
+       char name[LST_NAME_SIZE + 1];
        int rc;
 
        if (args->lstio_grp_key != console_session.ses_key)
@@ -205,22 +190,14 @@ lst_group_add_ioctl(struct lstio_group_add_args *args)
            args->lstio_grp_nmlen > LST_NAME_SIZE)
                return -EINVAL;
 
-       LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_grp_namep,
-                          args->lstio_grp_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_grp_nmlen);
+                          args->lstio_grp_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_grp_nmlen] = 0;
 
        rc = lstcon_group_add(name);
 
-       LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
-
        return rc;
 }
 
@@ -228,7 +205,7 @@ static int
 lst_group_del_ioctl(struct lstio_group_del_args *args)
 {
        int rc;
-       char *name;
+       char name[LST_NAME_SIZE + 1];
 
        if (args->lstio_grp_key != console_session.ses_key)
                return -EACCES;
@@ -238,22 +215,14 @@ lst_group_del_ioctl(struct lstio_group_del_args *args)
            args->lstio_grp_nmlen > LST_NAME_SIZE)
                return -EINVAL;
 
-       LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_grp_namep,
-                          args->lstio_grp_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
+                          args->lstio_grp_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_grp_nmlen] = 0;
 
        rc = lstcon_group_del(name);
 
-       LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
-
        return rc;
 }
 
@@ -261,7 +230,7 @@ static int
 lst_group_update_ioctl(struct lstio_group_update_args *args)
 {
        int rc;
-       char *name;
+       char name[LST_NAME_SIZE + 1];
 
        if (args->lstio_grp_key != console_session.ses_key)
                return -EACCES;
@@ -272,15 +241,9 @@ lst_group_update_ioctl(struct lstio_group_update_args *args)
            args->lstio_grp_nmlen > LST_NAME_SIZE)
                return -EINVAL;
 
-       LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_grp_namep,
-                          args->lstio_grp_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
+                          args->lstio_grp_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_grp_nmlen] = 0;
 
@@ -309,8 +272,6 @@ lst_group_update_ioctl(struct lstio_group_update_args *args)
                break;
        }
 
-       LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
-
        return rc;
 }
 
@@ -319,7 +280,7 @@ lst_nodes_add_ioctl(struct lstio_group_nodes_args *args)
 {
        unsigned int feats;
        int rc;
-       char *name;
+       char name[LST_NAME_SIZE + 1];
 
        if (args->lstio_grp_key != console_session.ses_key)
                return -EACCES;
@@ -333,16 +294,9 @@ lst_nodes_add_ioctl(struct lstio_group_nodes_args *args)
            args->lstio_grp_nmlen > LST_NAME_SIZE)
                return -EINVAL;
 
-       LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_grp_namep,
-                          args->lstio_grp_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
-
+                          args->lstio_grp_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_grp_nmlen] = 0;
 
@@ -350,7 +304,6 @@ lst_nodes_add_ioctl(struct lstio_group_nodes_args *args)
                              args->lstio_grp_idsp, &feats,
                              args->lstio_grp_resultp);
 
-       LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
        if (!rc &&
            copy_to_user(args->lstio_grp_featp, &feats, sizeof(feats))) {
                return -EINVAL;
@@ -379,7 +332,7 @@ lst_group_list_ioctl(struct lstio_group_list_args *args)
 static int
 lst_group_info_ioctl(struct lstio_group_info_args *args)
 {
-       char *name;
+       char name[LST_NAME_SIZE + 1];
        int ndent;
        int index;
        int rc;
@@ -411,23 +364,15 @@ lst_group_info_ioctl(struct lstio_group_info_args *args)
                        return -EINVAL;
        }
 
-       LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_grp_namep,
-                          args->lstio_grp_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
+                          args->lstio_grp_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_grp_nmlen] = 0;
 
        rc = lstcon_group_info(name, args->lstio_grp_entp,
                               &index, &ndent, args->lstio_grp_dentsp);
 
-       LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
-
        if (rc)
                return rc;
 
@@ -443,7 +388,7 @@ static int
 lst_batch_add_ioctl(struct lstio_batch_add_args *args)
 {
        int rc;
-       char *name;
+       char name[LST_NAME_SIZE + 1];
 
        if (args->lstio_bat_key != console_session.ses_key)
                return -EACCES;
@@ -453,22 +398,14 @@ lst_batch_add_ioctl(struct lstio_batch_add_args *args)
            args->lstio_bat_nmlen > LST_NAME_SIZE)
                return -EINVAL;
 
-       LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_bat_namep,
-                          args->lstio_bat_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
+                          args->lstio_bat_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_bat_nmlen] = 0;
 
        rc = lstcon_batch_add(name);
 
-       LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
-
        return rc;
 }
 
@@ -476,7 +413,7 @@ static int
 lst_batch_run_ioctl(struct lstio_batch_run_args *args)
 {
        int rc;
-       char *name;
+       char name[LST_NAME_SIZE + 1];
 
        if (args->lstio_bat_key != console_session.ses_key)
                return -EACCES;
@@ -486,23 +423,15 @@ lst_batch_run_ioctl(struct lstio_batch_run_args *args)
            args->lstio_bat_nmlen > LST_NAME_SIZE)
                return -EINVAL;
 
-       LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_bat_namep,
-                          args->lstio_bat_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
+                          args->lstio_bat_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_bat_nmlen] = 0;
 
        rc = lstcon_batch_run(name, args->lstio_bat_timeout,
                              args->lstio_bat_resultp);
 
-       LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
-
        return rc;
 }
 
@@ -510,7 +439,7 @@ static int
 lst_batch_stop_ioctl(struct lstio_batch_stop_args *args)
 {
        int rc;
-       char *name;
+       char name[LST_NAME_SIZE + 1];
 
        if (args->lstio_bat_key != console_session.ses_key)
                return -EACCES;
@@ -521,30 +450,22 @@ lst_batch_stop_ioctl(struct lstio_batch_stop_args *args)
            args->lstio_bat_nmlen > LST_NAME_SIZE)
                return -EINVAL;
 
-       LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_bat_namep,
-                          args->lstio_bat_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
+                          args->lstio_bat_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_bat_nmlen] = 0;
 
        rc = lstcon_batch_stop(name, args->lstio_bat_force,
                               args->lstio_bat_resultp);
 
-       LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
-
        return rc;
 }
 
 static int
 lst_batch_query_ioctl(struct lstio_batch_query_args *args)
 {
-       char *name;
+       char name[LST_NAME_SIZE + 1];
        int rc;
 
        if (args->lstio_bat_key != console_session.ses_key)
@@ -559,15 +480,9 @@ lst_batch_query_ioctl(struct lstio_batch_query_args *args)
        if (args->lstio_bat_testidx < 0)
                return -EINVAL;
 
-       LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_bat_namep,
-                          args->lstio_bat_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
+                          args->lstio_bat_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_bat_nmlen] = 0;
 
@@ -577,8 +492,6 @@ lst_batch_query_ioctl(struct lstio_batch_query_args *args)
                                     args->lstio_bat_timeout,
                                     args->lstio_bat_resultp);
 
-       LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
-
        return rc;
 }
 
@@ -602,7 +515,7 @@ lst_batch_list_ioctl(struct lstio_batch_list_args *args)
 static int
 lst_batch_info_ioctl(struct lstio_batch_info_args *args)
 {
-       char *name;
+       char name[LST_NAME_SIZE + 1];
        int rc;
        int index;
        int ndent;
@@ -634,15 +547,9 @@ lst_batch_info_ioctl(struct lstio_batch_info_args *args)
                        return -EINVAL;
        }
 
-       LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
-       if (!name)
-               return -ENOMEM;
-
        if (copy_from_user(name, args->lstio_bat_namep,
-                          args->lstio_bat_nmlen)) {
-               LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
+                          args->lstio_bat_nmlen))
                return -EFAULT;
-       }
 
        name[args->lstio_bat_nmlen] = 0;
 
@@ -650,8 +557,6 @@ lst_batch_info_ioctl(struct lstio_batch_info_args *args)
                               args->lstio_bat_server, args->lstio_bat_testidx,
                               &index, &ndent, args->lstio_bat_dentsp);
 
-       LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
-
        if (rc)
                return rc;
 
@@ -667,7 +572,7 @@ static int
 lst_stat_query_ioctl(struct lstio_stat_args *args)
 {
        int rc;
-       char *name = NULL;
+       char name[LST_NAME_SIZE + 1];
 
        /* TODO: not finished */
        if (args->lstio_sta_key != console_session.ses_key)
@@ -689,10 +594,6 @@ lst_stat_query_ioctl(struct lstio_stat_args *args)
                    args->lstio_sta_nmlen > LST_NAME_SIZE)
                        return -EINVAL;
 
-               LIBCFS_ALLOC(name, args->lstio_sta_nmlen + 1);
-               if (!name)
-                       return -ENOMEM;
-
                rc = copy_from_user(name, args->lstio_sta_namep,
                                    args->lstio_sta_nmlen);
                if (!rc)
@@ -704,16 +605,14 @@ lst_stat_query_ioctl(struct lstio_stat_args *args)
                rc = -EINVAL;
        }
 
-       if (name)
-               LIBCFS_FREE(name, args->lstio_sta_nmlen + 1);
        return rc;
 }
 
 static int lst_test_add_ioctl(struct lstio_test_args *args)
 {
-       char *batch_name;
-       char *src_name = NULL;
-       char *dst_name = NULL;
+       char batch_name[LST_NAME_SIZE + 1];
+       char src_name[LST_NAME_SIZE + 1];
+       char dst_name[LST_NAME_SIZE + 1];
        void *param = NULL;
        int ret = 0;
        int rc = -ENOMEM;
@@ -748,20 +647,8 @@ static int lst_test_add_ioctl(struct lstio_test_args *args)
        if (!args->lstio_tes_param && args->lstio_tes_param_len)
                return -EINVAL;
 
-       LIBCFS_ALLOC(batch_name, args->lstio_tes_bat_nmlen + 1);
-       if (!batch_name)
-               return rc;
-
-       LIBCFS_ALLOC(src_name, args->lstio_tes_sgrp_nmlen + 1);
-       if (!src_name)
-               goto out;
-
-       LIBCFS_ALLOC(dst_name, args->lstio_tes_dgrp_nmlen + 1);
-       if (!dst_name)
-               goto out;
-
        if (args->lstio_tes_param) {
-               LIBCFS_ALLOC(param, args->lstio_tes_param_len);
+               param = kmalloc(args->lstio_tes_param_len, GFP_KERNEL);
                if (!param)
                        goto out;
                if (copy_from_user(param, args->lstio_tes_param,
@@ -791,17 +678,7 @@ static int lst_test_add_ioctl(struct lstio_test_args *args)
                rc = (copy_to_user(args->lstio_tes_retp, &ret,
                                   sizeof(ret))) ? -EFAULT : 0;
 out:
-       if (batch_name)
-               LIBCFS_FREE(batch_name, args->lstio_tes_bat_nmlen + 1);
-
-       if (src_name)
-               LIBCFS_FREE(src_name, args->lstio_tes_sgrp_nmlen + 1);
-
-       if (dst_name)
-               LIBCFS_FREE(dst_name, args->lstio_tes_dgrp_nmlen + 1);
-
-       if (param)
-               LIBCFS_FREE(param, args->lstio_tes_param_len);
+       kfree(param);
 
        return rc;
 }
@@ -824,13 +701,13 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
        if (data->ioc_plen1 > PAGE_SIZE)
                return -EINVAL;
 
-       LIBCFS_ALLOC(buf, data->ioc_plen1);
+       buf = kmalloc(data->ioc_plen1, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
 
        /* copy in parameter */
        if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
-               LIBCFS_FREE(buf, data->ioc_plen1);
+               kfree(buf);
                return -EFAULT;
        }
 
@@ -920,7 +797,7 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
 out:
        mutex_unlock(&console_session.ses_mutex);
 
-       LIBCFS_FREE(buf, data->ioc_plen1);
+       kfree(buf);
 
        return rc;
 }
index 6a0f770e0e24466a23d1eba47381cb94072ef168..7aa515c345944d5db67d5e8cccd17bfc9665640c 100644 (file)
@@ -129,7 +129,7 @@ lstcon_rpc_prep(struct lstcon_node *nd, int service, unsigned int feats,
        spin_unlock(&console_session.ses_rpc_lock);
 
        if (!crpc) {
-               LIBCFS_ALLOC(crpc, sizeof(*crpc));
+               crpc = kzalloc(sizeof(*crpc), GFP_NOFS);
                if (!crpc)
                        return -ENOMEM;
        }
@@ -140,7 +140,7 @@ lstcon_rpc_prep(struct lstcon_node *nd, int service, unsigned int feats,
                return 0;
        }
 
-       LIBCFS_FREE(crpc, sizeof(*crpc));
+       kfree(crpc);
 
        return rc;
 }
@@ -250,7 +250,7 @@ lstcon_rpc_trans_prep(struct list_head *translist, int transop,
        }
 
        /* create a trans group */
-       LIBCFS_ALLOC(trans, sizeof(*trans));
+       trans = kzalloc(sizeof(*trans), GFP_NOFS);
        if (!trans)
                return -ENOMEM;
 
@@ -585,7 +585,7 @@ lstcon_rpc_trans_destroy(struct lstcon_rpc_trans *trans)
        CDEBUG(D_NET, "Transaction %s destroyed with %d pending RPCs\n",
               lstcon_rpc_trans_name(trans->tas_opc), count);
 
-       LIBCFS_FREE(trans, sizeof(*trans));
+       kfree(trans);
 }
 
 int
@@ -1369,7 +1369,7 @@ lstcon_rpc_cleanup_wait(void)
 
        list_for_each_entry_safe(crpc, temp, &zlist, crp_link) {
                list_del(&crpc->crp_link);
-               LIBCFS_FREE(crpc, sizeof(struct lstcon_rpc));
+               kfree(crpc);
        }
 }
 
index a2662638d59910cc9d95954bc0c27100a2260ca6..1acd5cb324b1723c1b9567158448ef69f4aa58a7 100644 (file)
@@ -88,7 +88,7 @@ lstcon_node_find(struct lnet_process_id id, struct lstcon_node **ndpp,
        if (!create)
                return -ENOENT;
 
-       LIBCFS_ALLOC(*ndpp, sizeof(**ndpp) + sizeof(*ndl));
+       *ndpp = kzalloc(sizeof(**ndpp) + sizeof(*ndl), GFP_KERNEL);
        if (!*ndpp)
                return -ENOMEM;
 
@@ -133,7 +133,7 @@ lstcon_node_put(struct lstcon_node *nd)
        list_del(&ndl->ndl_link);
        list_del(&ndl->ndl_hlink);
 
-       LIBCFS_FREE(nd, sizeof(*nd) + sizeof(*ndl));
+       kfree(nd);
 }
 
 static int
@@ -166,7 +166,7 @@ lstcon_ndlink_find(struct list_head *hash, struct lnet_process_id id,
        if (rc)
                return rc;
 
-       LIBCFS_ALLOC(ndl, sizeof(struct lstcon_ndlink));
+       ndl = kzalloc(sizeof(struct lstcon_ndlink), GFP_NOFS);
        if (!ndl) {
                lstcon_node_put(nd);
                return -ENOMEM;
@@ -190,7 +190,7 @@ lstcon_ndlink_release(struct lstcon_ndlink *ndl)
        list_del(&ndl->ndl_hlink); /* delete from hash */
        lstcon_node_put(ndl->ndl_node);
 
-       LIBCFS_FREE(ndl, sizeof(*ndl));
+       kfree(ndl);
 }
 
 static int
@@ -199,16 +199,16 @@ lstcon_group_alloc(char *name, struct lstcon_group **grpp)
        struct lstcon_group *grp;
        int i;
 
-       LIBCFS_ALLOC(grp, offsetof(struct lstcon_group,
-                                  grp_ndl_hash[LST_NODE_HASHSIZE]));
+       grp = kmalloc(offsetof(struct lstcon_group,
+                              grp_ndl_hash[LST_NODE_HASHSIZE]),
+                     GFP_KERNEL);
        if (!grp)
                return -ENOMEM;
 
        grp->grp_ref = 1;
        if (name) {
                if (strlen(name) > sizeof(grp->grp_name) - 1) {
-                       LIBCFS_FREE(grp, offsetof(struct lstcon_group,
-                                   grp_ndl_hash[LST_NODE_HASHSIZE]));
+                       kfree(grp);
                        return -E2BIG;
                }
                strncpy(grp->grp_name, name, sizeof(grp->grp_name));
@@ -263,8 +263,7 @@ lstcon_group_decref(struct lstcon_group *grp)
        for (i = 0; i < LST_NODE_HASHSIZE; i++)
                LASSERT(list_empty(&grp->grp_ndl_hash[i]));
 
-       LIBCFS_FREE(grp, offsetof(struct lstcon_group,
-                                 grp_ndl_hash[LST_NODE_HASHSIZE]));
+       kfree(grp);
 }
 
 static int
@@ -807,7 +806,7 @@ lstcon_group_info(char *name, struct lstcon_ndlist_ent __user *gents_p,
        }
 
        /* non-verbose query */
-       LIBCFS_ALLOC(gentp, sizeof(struct lstcon_ndlist_ent));
+       gentp = kzalloc(sizeof(struct lstcon_ndlist_ent), GFP_NOFS);
        if (!gentp) {
                CERROR("Can't allocate ndlist_ent\n");
                lstcon_group_decref(grp);
@@ -821,7 +820,7 @@ lstcon_group_info(char *name, struct lstcon_ndlist_ent __user *gents_p,
        rc = copy_to_user(gents_p, gentp,
                          sizeof(struct lstcon_ndlist_ent)) ? -EFAULT : 0;
 
-       LIBCFS_FREE(gentp, sizeof(struct lstcon_ndlist_ent));
+       kfree(gentp);
 
        lstcon_group_decref(grp);
 
@@ -856,35 +855,35 @@ lstcon_batch_add(char *name)
                return rc;
        }
 
-       LIBCFS_ALLOC(bat, sizeof(struct lstcon_batch));
+       bat = kzalloc(sizeof(struct lstcon_batch), GFP_NOFS);
        if (!bat) {
                CERROR("Can't allocate descriptor for batch %s\n", name);
                return -ENOMEM;
        }
 
-       LIBCFS_ALLOC(bat->bat_cli_hash,
-                    sizeof(struct list_head) * LST_NODE_HASHSIZE);
+       bat->bat_cli_hash = kmalloc(sizeof(struct list_head) * LST_NODE_HASHSIZE,
+                                   GFP_KERNEL);
        if (!bat->bat_cli_hash) {
                CERROR("Can't allocate hash for batch %s\n", name);
-               LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
+               kfree(bat);
 
                return -ENOMEM;
        }
 
-       LIBCFS_ALLOC(bat->bat_srv_hash,
-                    sizeof(struct list_head) * LST_NODE_HASHSIZE);
+       bat->bat_srv_hash = kmalloc(sizeof(struct list_head) * LST_NODE_HASHSIZE,
+                                   GFP_KERNEL);
        if (!bat->bat_srv_hash) {
                CERROR("Can't allocate hash for batch %s\n", name);
-               LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
-               LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
+               kfree(bat->bat_cli_hash);
+               kfree(bat);
 
                return -ENOMEM;
        }
 
        if (strlen(name) > sizeof(bat->bat_name) - 1) {
-               LIBCFS_FREE(bat->bat_srv_hash, LST_NODE_HASHSIZE);
-               LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
-               LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
+               kfree(bat->bat_srv_hash);
+               kfree(bat->bat_cli_hash);
+               kfree(bat);
                return -E2BIG;
        }
        strncpy(bat->bat_name, name, sizeof(bat->bat_name));
@@ -971,7 +970,7 @@ lstcon_batch_info(char *name, struct lstcon_test_batch_ent __user *ent_up,
        }
 
        /* non-verbose query */
-       LIBCFS_ALLOC(entp, sizeof(struct lstcon_test_batch_ent));
+       entp = kzalloc(sizeof(struct lstcon_test_batch_ent), GFP_NOFS);
        if (!entp)
                return -ENOMEM;
 
@@ -993,7 +992,7 @@ lstcon_batch_info(char *name, struct lstcon_test_batch_ent __user *ent_up,
        rc = copy_to_user(ent_up, entp,
                          sizeof(struct lstcon_test_batch_ent)) ? -EFAULT : 0;
 
-       LIBCFS_FREE(entp, sizeof(struct lstcon_test_batch_ent));
+       kfree(entp);
 
        return rc;
 }
@@ -1107,8 +1106,7 @@ lstcon_batch_destroy(struct lstcon_batch *bat)
                lstcon_group_decref(test->tes_src_grp);
                lstcon_group_decref(test->tes_dst_grp);
 
-               LIBCFS_FREE(test, offsetof(struct lstcon_test,
-                                          tes_param[test->tes_paramlen]));
+               kfree(test);
        }
 
        LASSERT(list_empty(&bat->bat_trans_list));
@@ -1134,11 +1132,9 @@ lstcon_batch_destroy(struct lstcon_batch *bat)
                LASSERT(list_empty(&bat->bat_srv_hash[i]));
        }
 
-       LIBCFS_FREE(bat->bat_cli_hash,
-                   sizeof(struct list_head) * LST_NODE_HASHSIZE);
-       LIBCFS_FREE(bat->bat_srv_hash,
-                   sizeof(struct list_head) * LST_NODE_HASHSIZE);
-       LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
+       kfree(bat->bat_cli_hash);
+       kfree(bat->bat_srv_hash);
+       kfree(bat);
 }
 
 static int
@@ -1311,7 +1307,8 @@ lstcon_test_add(char *batch_name, int type, int loop,
        if (dst_grp->grp_userland)
                *retp = 1;
 
-       LIBCFS_ALLOC(test, offsetof(struct lstcon_test, tes_param[paramlen]));
+       test = kzalloc(offsetof(struct lstcon_test, tes_param[paramlen]),
+                      GFP_KERNEL);
        if (!test) {
                CERROR("Can't allocate test descriptor\n");
                rc = -ENOMEM;
@@ -1357,8 +1354,7 @@ lstcon_test_add(char *batch_name, int type, int loop,
        /*  hold groups so nobody can change them */
        return rc;
 out:
-       if (test)
-               LIBCFS_FREE(test, offsetof(struct lstcon_test, tes_param[paramlen]));
+       kfree(test);
 
        if (dst_grp)
                lstcon_group_decref(dst_grp);
@@ -1790,7 +1786,7 @@ lstcon_session_info(struct lst_sid __user *sid_up, int __user *key_up,
        if (console_session.ses_state != LST_SESSION_ACTIVE)
                return -ESRCH;
 
-       LIBCFS_ALLOC(entp, sizeof(*entp));
+       entp = kzalloc(sizeof(*entp), GFP_NOFS);
        if (!entp)
                return -ENOMEM;
 
@@ -1807,7 +1803,7 @@ lstcon_session_info(struct lst_sid __user *sid_up, int __user *key_up,
            copy_to_user(name_up, console_session.ses_name, len))
                rc = -EFAULT;
 
-       LIBCFS_FREE(entp, sizeof(*entp));
+       kfree(entp);
 
        return rc;
 }
@@ -2027,8 +2023,8 @@ lstcon_console_init(void)
        INIT_LIST_HEAD(&console_session.ses_bat_list);
        INIT_LIST_HEAD(&console_session.ses_trans_list);
 
-       LIBCFS_ALLOC(console_session.ses_ndl_hash,
-                    sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
+       console_session.ses_ndl_hash =
+               kmalloc(sizeof(struct list_head) * LST_GLOBAL_HASHSIZE, GFP_KERNEL);
        if (!console_session.ses_ndl_hash)
                return -ENOMEM;
 
@@ -2041,8 +2037,7 @@ lstcon_console_init(void)
        rc = srpc_add_service(&lstcon_acceptor_service);
        LASSERT(rc != -EBUSY);
        if (rc) {
-               LIBCFS_FREE(console_session.ses_ndl_hash,
-                           sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
+               kfree(console_session.ses_ndl_hash);
                return rc;
        }
 
@@ -2064,8 +2059,7 @@ out:
        srpc_shutdown_service(&lstcon_acceptor_service);
        srpc_remove_service(&lstcon_acceptor_service);
 
-       LIBCFS_FREE(console_session.ses_ndl_hash,
-                   sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
+       kfree(console_session.ses_ndl_hash);
 
        srpc_wait_service_shutdown(&lstcon_acceptor_service);
 
@@ -2099,8 +2093,7 @@ lstcon_console_fini(void)
        for (i = 0; i < LST_NODE_HASHSIZE; i++)
                LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
 
-       LIBCFS_FREE(console_session.ses_ndl_hash,
-                   sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
+       kfree(console_session.ses_ndl_hash);
 
        srpc_wait_service_shutdown(&lstcon_acceptor_service);
 
index fe889607ff3f6229aa1c6379d3bd070f44534754..c7697f66f663bd5ce939849dc9c3f6b1ae529b28 100644 (file)
@@ -143,7 +143,7 @@ sfw_register_test(struct srpc_service *service,
                return -EEXIST;
        }
 
-       LIBCFS_ALLOC(tsc, sizeof(struct sfw_test_case));
+       tsc = kzalloc(sizeof(struct sfw_test_case), GFP_NOFS);
        if (!tsc)
                return -ENOMEM;
 
@@ -344,7 +344,7 @@ sfw_bid2batch(struct lst_bid bid)
        if (bat)
                return bat;
 
-       LIBCFS_ALLOC(bat, sizeof(struct sfw_batch));
+       bat = kzalloc(sizeof(struct sfw_batch), GFP_NOFS);
        if (!bat)
                return NULL;
 
@@ -447,7 +447,7 @@ sfw_make_session(struct srpc_mksn_reqst *request, struct srpc_mksn_reply *reply)
        }
 
        /* brand new or create by force */
-       LIBCFS_ALLOC(sn, sizeof(struct sfw_session));
+       sn = kzalloc(sizeof(struct sfw_session), GFP_NOFS);
        if (!sn) {
                CERROR("dropping RPC mksn under memory pressure\n");
                return -ENOMEM;
@@ -632,19 +632,19 @@ sfw_destroy_test_instance(struct sfw_test_instance *tsi)
                tsu = list_entry(tsi->tsi_units.next,
                                 struct sfw_test_unit, tsu_list);
                list_del(&tsu->tsu_list);
-               LIBCFS_FREE(tsu, sizeof(*tsu));
+               kfree(tsu);
        }
 
        while (!list_empty(&tsi->tsi_free_rpcs)) {
                rpc = list_entry(tsi->tsi_free_rpcs.next,
                                 struct srpc_client_rpc, crpc_list);
                list_del(&rpc->crpc_list);
-               LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc));
+               kfree(rpc);
        }
 
 clean:
        sfw_unload_test(tsi);
-       LIBCFS_FREE(tsi, sizeof(*tsi));
+       kfree(tsi);
 }
 
 static void
@@ -662,7 +662,7 @@ sfw_destroy_batch(struct sfw_batch *tsb)
                sfw_destroy_test_instance(tsi);
        }
 
-       LIBCFS_FREE(tsb, sizeof(struct sfw_batch));
+       kfree(tsb);
 }
 
 void
@@ -680,7 +680,7 @@ sfw_destroy_session(struct sfw_session *sn)
                sfw_destroy_batch(batch);
        }
 
-       LIBCFS_FREE(sn, sizeof(*sn));
+       kfree(sn);
        atomic_dec(&sfw_data.fw_nzombies);
 }
 
@@ -740,7 +740,7 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc)
        int i;
        int rc;
 
-       LIBCFS_ALLOC(tsi, sizeof(*tsi));
+       tsi = kzalloc(sizeof(*tsi), GFP_NOFS);
        if (!tsi) {
                CERROR("Can't allocate test instance for batch: %llu\n",
                       tsb->bat_id.bat_id);
@@ -763,7 +763,7 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc)
 
        rc = sfw_load_test(tsi);
        if (rc) {
-               LIBCFS_FREE(tsi, sizeof(*tsi));
+               kfree(tsi);
                return rc;
        }
 
@@ -795,7 +795,7 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc)
                        sfw_unpack_id(id);
 
                for (j = 0; j < tsi->tsi_concur; j++) {
-                       LIBCFS_ALLOC(tsu, sizeof(struct sfw_test_unit));
+                       tsu = kzalloc(sizeof(struct sfw_test_unit), GFP_NOFS);
                        if (!tsu) {
                                rc = -ENOMEM;
                                CERROR("Can't allocate tsu for %d\n",
@@ -941,15 +941,13 @@ sfw_create_test_rpc(struct sfw_test_unit *tsu, struct lnet_process_id peer,
        return 0;
 }
 
-static int
+static void
 sfw_run_test(struct swi_workitem *wi)
 {
-       struct sfw_test_unit *tsu = wi->swi_workitem.wi_data;
+       struct sfw_test_unit *tsu = container_of(wi, struct sfw_test_unit, tsu_worker);
        struct sfw_test_instance *tsi = tsu->tsu_instance;
        struct srpc_client_rpc *rpc = NULL;
 
-       LASSERT(wi == &tsu->tsu_worker);
-
        if (tsi->tsi_ops->tso_prep_rpc(tsu, tsu->tsu_dest, &rpc)) {
                LASSERT(!rpc);
                goto test_done;
@@ -975,7 +973,7 @@ sfw_run_test(struct swi_workitem *wi)
        rpc->crpc_timeout = rpc_timeout;
        srpc_post_rpc(rpc);
        spin_unlock(&rpc->crpc_lock);
-       return 0;
+       return;
 
 test_done:
        /*
@@ -985,9 +983,7 @@ test_done:
         * - my batch is still active; no one can run it again now.
         * Cancel pending schedules and prevent future schedule attempts:
         */
-       swi_exit_workitem(wi);
        sfw_test_unit_done(tsu);
-       return 1;
 }
 
 static int
@@ -1016,8 +1012,8 @@ sfw_run_batch(struct sfw_batch *tsb)
                        atomic_inc(&tsi->tsi_nactive);
                        tsu->tsu_loop = tsi->tsi_loop;
                        wi = &tsu->tsu_worker;
-                       swi_init_workitem(wi, tsu, sfw_run_test,
-                                         lst_sched_test[lnet_cpt_of_nid(tsu->tsu_dest.nid)]);
+                       swi_init_workitem(wi, sfw_run_test,
+                                         lst_test_wq[lnet_cpt_of_nid(tsu->tsu_dest.nid)]);
                        swi_schedule_workitem(wi);
                }
        }
@@ -1767,7 +1763,7 @@ sfw_shutdown(void)
                                 struct srpc_client_rpc, crpc_list);
                list_del(&rpc->crpc_list);
 
-               LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc));
+               kfree(rpc);
        }
 
        for (i = 0; ; i++) {
@@ -1785,6 +1781,6 @@ sfw_shutdown(void)
                srpc_wait_service_shutdown(tsc->tsc_srv_service);
 
                list_del(&tsc->tsc_list);
-               LIBCFS_FREE(tsc, sizeof(*tsc));
+               kfree(tsc);
        }
 }
index 1d44d912f01458162b3b8a567d7f540241073e0a..7359aa56d9b3bf5303fd0324eb04bfcfc2d594c3 100644 (file)
@@ -47,8 +47,8 @@ enum {
 
 static int lst_init_step = LST_INIT_NONE;
 
-struct cfs_wi_sched *lst_sched_serial;
-struct cfs_wi_sched **lst_sched_test;
+struct workqueue_struct *lst_serial_wq;
+struct workqueue_struct **lst_test_wq;
 
 static void
 lnet_selftest_exit(void)
@@ -68,18 +68,16 @@ lnet_selftest_exit(void)
        case LST_INIT_WI_TEST:
                for (i = 0;
                     i < cfs_cpt_number(lnet_cpt_table()); i++) {
-                       if (!lst_sched_test[i])
+                       if (!lst_test_wq[i])
                                continue;
-                       cfs_wi_sched_destroy(lst_sched_test[i]);
+                       destroy_workqueue(lst_test_wq[i]);
                }
-               LIBCFS_FREE(lst_sched_test,
-                           sizeof(lst_sched_test[0]) *
-                           cfs_cpt_number(lnet_cpt_table()));
-               lst_sched_test = NULL;
+               kvfree(lst_test_wq);
+               lst_test_wq = NULL;
                /* fall through */
        case LST_INIT_WI_SERIAL:
-               cfs_wi_sched_destroy(lst_sched_serial);
-               lst_sched_serial = NULL;
+               destroy_workqueue(lst_serial_wq);
+               lst_serial_wq = NULL;
        case LST_INIT_NONE:
                break;
        default:
@@ -91,35 +89,45 @@ static int
 lnet_selftest_init(void)
 {
        int nscheds;
-       int rc;
+       int rc = -ENOMEM;
        int i;
 
-       rc = cfs_wi_sched_create("lst_s", lnet_cpt_table(), CFS_CPT_ANY,
-                                1, &lst_sched_serial);
-       if (rc) {
+       lst_serial_wq = alloc_ordered_workqueue("lst_s", 0);
+       if (!lst_serial_wq) {
                CERROR("Failed to create serial WI scheduler for LST\n");
-               return rc;
+               return -ENOMEM;
        }
        lst_init_step = LST_INIT_WI_SERIAL;
 
        nscheds = cfs_cpt_number(lnet_cpt_table());
-       LIBCFS_ALLOC(lst_sched_test, sizeof(lst_sched_test[0]) * nscheds);
-       if (!lst_sched_test)
+       lst_test_wq = kvmalloc_array(nscheds, sizeof(lst_test_wq[0]),
+                                       GFP_KERNEL | __GFP_ZERO);
+       if (!lst_test_wq) {
+               rc = -ENOMEM;
                goto error;
+       }
 
        lst_init_step = LST_INIT_WI_TEST;
        for (i = 0; i < nscheds; i++) {
                int nthrs = cfs_cpt_weight(lnet_cpt_table(), i);
+               struct workqueue_attrs attrs = {0};
+               cpumask_var_t *mask = cfs_cpt_cpumask(lnet_cpt_table(), i);
 
                /* reserve at least one CPU for LND */
                nthrs = max(nthrs - 1, 1);
-               rc = cfs_wi_sched_create("lst_t", lnet_cpt_table(), i,
-                                        nthrs, &lst_sched_test[i]);
-               if (rc) {
+               lst_test_wq[i] = alloc_workqueue("lst_t", WQ_UNBOUND, nthrs);
+               if (!lst_test_wq[i]) {
                        CWARN("Failed to create CPU partition affinity WI scheduler %d for LST\n",
                              i);
+                       rc = -ENOMEM;
                        goto error;
                }
+
+               if (mask && alloc_cpumask_var(&attrs.cpumask, GFP_KERNEL)) {
+                       cpumask_copy(attrs.cpumask, *mask);
+                       apply_workqueue_attrs(lst_test_wq[i], &attrs);
+                       free_cpumask_var(attrs.cpumask);
+               }
        }
 
        rc = srpc_startup();
index ab7e8a8e58b89e3f3ed022bcb77c277580ea083e..f8198ad1046ef22c5fdff0272e71c31cacb2f9e5 100644 (file)
@@ -68,7 +68,7 @@ srpc_serv_portal(int svc_id)
 }
 
 /* forward ref's */
-int srpc_handle_rpc(struct swi_workitem *wi);
+void srpc_handle_rpc(struct swi_workitem *wi);
 
 void srpc_get_counters(struct srpc_counters *cnt)
 {
@@ -113,7 +113,7 @@ srpc_free_bulk(struct srpc_bulk *bk)
                __free_page(pg);
        }
 
-       LIBCFS_FREE(bk, offsetof(struct srpc_bulk, bk_iovs[bk->bk_niov]));
+       kfree(bk);
 }
 
 struct srpc_bulk *
@@ -125,8 +125,8 @@ srpc_alloc_bulk(int cpt, unsigned int bulk_off, unsigned int bulk_npg,
 
        LASSERT(bulk_npg > 0 && bulk_npg <= LNET_MAX_IOV);
 
-       LIBCFS_CPT_ALLOC(bk, lnet_cpt_table(), cpt,
-                        offsetof(struct srpc_bulk, bk_iovs[bulk_npg]));
+       bk = kzalloc_cpt(offsetof(struct srpc_bulk, bk_iovs[bulk_npg]),
+                        GFP_KERNEL, cpt);
        if (!bk) {
                CERROR("Can't allocate descriptor for %d pages\n", bulk_npg);
                return NULL;
@@ -176,9 +176,9 @@ srpc_init_server_rpc(struct srpc_server_rpc *rpc,
                     struct srpc_buffer *buffer)
 {
        memset(rpc, 0, sizeof(*rpc));
-       swi_init_workitem(&rpc->srpc_wi, rpc, srpc_handle_rpc,
+       swi_init_workitem(&rpc->srpc_wi, srpc_handle_rpc,
                          srpc_serv_is_framework(scd->scd_svc) ?
-                         lst_sched_serial : lst_sched_test[scd->scd_cpt]);
+                         lst_serial_wq : lst_test_wq[scd->scd_cpt]);
 
        rpc->srpc_ev.ev_fired = 1; /* no event expected now */
 
@@ -214,7 +214,7 @@ srpc_service_fini(struct srpc_service *svc)
                                buf = list_entry(q->next, struct srpc_buffer,
                                                 buf_list);
                                list_del(&buf->buf_list);
-                               LIBCFS_FREE(buf, sizeof(*buf));
+                               kfree(buf);
                        }
                }
 
@@ -225,7 +225,7 @@ srpc_service_fini(struct srpc_service *svc)
                                         struct srpc_server_rpc,
                                         srpc_list);
                        list_del(&rpc->srpc_list);
-                       LIBCFS_FREE(rpc, sizeof(*rpc));
+                       kfree(rpc);
                }
        }
 
@@ -242,7 +242,7 @@ srpc_service_nrpcs(struct srpc_service *svc)
               max(nrpcs, SFW_FRWK_WI_MIN) : max(nrpcs, SFW_TEST_WI_MIN);
 }
 
-int srpc_add_buffer(struct swi_workitem *wi);
+void srpc_add_buffer(struct swi_workitem *wi);
 
 static int
 srpc_service_init(struct srpc_service *svc)
@@ -277,11 +277,11 @@ srpc_service_init(struct srpc_service *svc)
                scd->scd_ev.ev_type = SRPC_REQUEST_RCVD;
 
                /*
-                * NB: don't use lst_sched_serial for adding buffer,
+                * NB: don't use lst_serial_wq for adding buffer,
                 * see details in srpc_service_add_buffers()
                 */
-               swi_init_workitem(&scd->scd_buf_wi, scd,
-                                 srpc_add_buffer, lst_sched_test[i]);
+               swi_init_workitem(&scd->scd_buf_wi,
+                                 srpc_add_buffer, lst_test_wq[i]);
 
                if (i && srpc_serv_is_framework(svc)) {
                        /*
@@ -294,8 +294,7 @@ srpc_service_init(struct srpc_service *svc)
                }
 
                for (j = 0; j < nrpcs; j++) {
-                       LIBCFS_CPT_ALLOC(rpc, lnet_cpt_table(),
-                                        i, sizeof(*rpc));
+                       rpc = kzalloc_cpt(sizeof(*rpc), GFP_NOFS, i);
                        if (!rpc) {
                                srpc_service_fini(svc);
                                return -ENOMEM;
@@ -508,16 +507,16 @@ __must_hold(&scd->scd_lock)
        list_del(&buf->buf_list);
        spin_unlock(&scd->scd_lock);
 
-       LIBCFS_FREE(buf, sizeof(*buf));
+       kfree(buf);
 
        spin_lock(&scd->scd_lock);
        return rc;
 }
 
-int
+void
 srpc_add_buffer(struct swi_workitem *wi)
 {
-       struct srpc_service_cd *scd = wi->swi_workitem.wi_data;
+       struct srpc_service_cd *scd = container_of(wi, struct srpc_service_cd, scd_buf_wi);
        struct srpc_buffer *buf;
        int rc = 0;
 
@@ -535,7 +534,7 @@ srpc_add_buffer(struct swi_workitem *wi)
 
                spin_unlock(&scd->scd_lock);
 
-               LIBCFS_ALLOC(buf, sizeof(*buf));
+               buf = kzalloc(sizeof(*buf), GFP_NOFS);
                if (!buf) {
                        CERROR("Failed to add new buf to service: %s\n",
                               scd->scd_svc->sv_name);
@@ -547,7 +546,7 @@ srpc_add_buffer(struct swi_workitem *wi)
                spin_lock(&scd->scd_lock);
                if (scd->scd_svc->sv_shuttingdown) {
                        spin_unlock(&scd->scd_lock);
-                       LIBCFS_FREE(buf, sizeof(*buf));
+                       kfree(buf);
 
                        spin_lock(&scd->scd_lock);
                        rc = -ESHUTDOWN;
@@ -573,7 +572,6 @@ srpc_add_buffer(struct swi_workitem *wi)
        }
 
        spin_unlock(&scd->scd_lock);
-       return 0;
 }
 
 int
@@ -605,15 +603,15 @@ srpc_service_add_buffers(struct srpc_service *sv, int nbuffer)
                spin_lock(&scd->scd_lock);
                /*
                 * NB: srpc_service_add_buffers() can be called inside
-                * thread context of lst_sched_serial, and we don't normally
+                * thread context of lst_serial_wq, and we don't normally
                 * allow to sleep inside thread context of WI scheduler
                 * because it will block current scheduler thread from doing
                 * anything else, even worse, it could deadlock if it's
                 * waiting on result from another WI of the same scheduler.
                 * However, it's safe at here because scd_buf_wi is scheduled
-                * by thread in a different WI scheduler (lst_sched_test),
+                * by thread in a different WI scheduler (lst_test_wq),
                 * so we don't have any risk of deadlock, though this could
-                * block all WIs pending on lst_sched_serial for a moment
+                * block all WIs pending on lst_serial_wq for a moment
                 * which is not good but not fatal.
                 */
                lst_wait_until(scd->scd_buf_err ||
@@ -660,11 +658,9 @@ srpc_finish_service(struct srpc_service *sv)
        LASSERT(sv->sv_shuttingdown); /* srpc_shutdown_service called */
 
        cfs_percpt_for_each(scd, i, sv->sv_cpt_data) {
+               swi_cancel_workitem(&scd->scd_buf_wi);
+
                spin_lock(&scd->scd_lock);
-               if (!swi_deschedule_workitem(&scd->scd_buf_wi)) {
-                       spin_unlock(&scd->scd_lock);
-                       return 0;
-               }
 
                if (scd->scd_buf_nposted > 0) {
                        CDEBUG(D_NET, "waiting for %d posted buffers to unlink\n",
@@ -680,11 +676,9 @@ srpc_finish_service(struct srpc_service *sv)
 
                rpc = list_entry(scd->scd_rpc_active.next,
                                 struct srpc_server_rpc, srpc_list);
-               CNETERR("Active RPC %p on shutdown: sv %s, peer %s, wi %s scheduled %d running %d, ev fired %d type %d status %d lnet %d\n",
+               CNETERR("Active RPC %p on shutdown: sv %s, peer %s, wi %s, ev fired %d type %d status %d lnet %d\n",
                        rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer),
                        swi_state2str(rpc->srpc_wi.swi_state),
-                       rpc->srpc_wi.swi_workitem.wi_scheduled,
-                       rpc->srpc_wi.swi_workitem.wi_running,
                        rpc->srpc_ev.ev_fired, rpc->srpc_ev.ev_type,
                        rpc->srpc_ev.ev_status, rpc->srpc_ev.ev_lnet);
                spin_unlock(&scd->scd_lock);
@@ -725,7 +719,7 @@ __must_hold(&scd->scd_lock)
        }
 
        spin_unlock(&scd->scd_lock);
-       LIBCFS_FREE(buf, sizeof(*buf));
+       kfree(buf);
        spin_lock(&scd->scd_lock);
 }
 
@@ -947,7 +941,6 @@ srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status)
         * Cancel pending schedules and prevent future schedule attempts:
         */
        LASSERT(rpc->srpc_ev.ev_fired);
-       swi_exit_workitem(&rpc->srpc_wi);
 
        if (!sv->sv_shuttingdown && !list_empty(&scd->scd_buf_blocked)) {
                buffer = list_entry(scd->scd_buf_blocked.next,
@@ -965,10 +958,10 @@ srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status)
 }
 
 /* handles an incoming RPC */
-int
+void
 srpc_handle_rpc(struct swi_workitem *wi)
 {
-       struct srpc_server_rpc *rpc = wi->swi_workitem.wi_data;
+       struct srpc_server_rpc *rpc = container_of(wi, struct srpc_server_rpc, srpc_wi);
        struct srpc_service_cd *scd = rpc->srpc_scd;
        struct srpc_service *sv = scd->scd_svc;
        struct srpc_event *ev = &rpc->srpc_ev;
@@ -987,9 +980,8 @@ srpc_handle_rpc(struct swi_workitem *wi)
 
                if (ev->ev_fired) { /* no more event, OK to finish */
                        srpc_server_rpc_done(rpc, -ESHUTDOWN);
-                       return 1;
                }
-               return 0;
+               return;
        }
 
        spin_unlock(&scd->scd_lock);
@@ -1007,7 +999,7 @@ srpc_handle_rpc(struct swi_workitem *wi)
                if (!msg->msg_magic) {
                        /* moaned already in srpc_lnet_ev_handler */
                        srpc_server_rpc_done(rpc, EBADMSG);
-                       return 1;
+                       return;
                }
 
                srpc_unpack_msg_hdr(msg);
@@ -1023,7 +1015,7 @@ srpc_handle_rpc(struct swi_workitem *wi)
                        LASSERT(!reply->status || !rpc->srpc_bulk);
                        if (rc) {
                                srpc_server_rpc_done(rpc, rc);
-                               return 1;
+                               return;
                        }
                }
 
@@ -1032,7 +1024,7 @@ srpc_handle_rpc(struct swi_workitem *wi)
                if (rpc->srpc_bulk) {
                        rc = srpc_do_bulk(rpc);
                        if (!rc)
-                               return 0; /* wait for bulk */
+                               return; /* wait for bulk */
 
                        LASSERT(ev->ev_fired);
                        ev->ev_status = rc;
@@ -1050,16 +1042,16 @@ srpc_handle_rpc(struct swi_workitem *wi)
 
                        if (rc) {
                                srpc_server_rpc_done(rpc, rc);
-                               return 1;
+                               return;
                        }
                }
 
                wi->swi_state = SWI_STATE_REPLY_SUBMITTED;
                rc = srpc_send_reply(rpc);
                if (!rc)
-                       return 0; /* wait for reply */
+                       return; /* wait for reply */
                srpc_server_rpc_done(rpc, rc);
-               return 1;
+               return;
 
        case SWI_STATE_REPLY_SUBMITTED:
                if (!ev->ev_fired) {
@@ -1072,10 +1064,8 @@ srpc_handle_rpc(struct swi_workitem *wi)
 
                wi->swi_state = SWI_STATE_DONE;
                srpc_server_rpc_done(rpc, ev->ev_status);
-               return 1;
+               return;
        }
-
-       return 0;
 }
 
 static void
@@ -1170,7 +1160,6 @@ srpc_client_rpc_done(struct srpc_client_rpc *rpc, int status)
         * Cancel pending schedules and prevent future schedule attempts:
         */
        LASSERT(!srpc_event_pending(rpc));
-       swi_exit_workitem(wi);
 
        spin_unlock(&rpc->crpc_lock);
 
@@ -1178,7 +1167,7 @@ srpc_client_rpc_done(struct srpc_client_rpc *rpc, int status)
 }
 
 /* sends an outgoing RPC */
-int
+void
 srpc_send_rpc(struct swi_workitem *wi)
 {
        int rc = 0;
@@ -1188,7 +1177,7 @@ srpc_send_rpc(struct swi_workitem *wi)
 
        LASSERT(wi);
 
-       rpc = wi->swi_workitem.wi_data;
+       rpc = container_of(wi, struct srpc_client_rpc, crpc_wi);
 
        LASSERT(rpc);
        LASSERT(wi == &rpc->crpc_wi);
@@ -1214,7 +1203,7 @@ srpc_send_rpc(struct swi_workitem *wi)
                rc = srpc_prepare_reply(rpc);
                if (rc) {
                        srpc_client_rpc_done(rpc, rc);
-                       return 1;
+                       return;
                }
 
                rc = srpc_prepare_bulk(rpc);
@@ -1291,7 +1280,7 @@ srpc_send_rpc(struct swi_workitem *wi)
 
                wi->swi_state = SWI_STATE_DONE;
                srpc_client_rpc_done(rpc, rc);
-               return 1;
+               return;
        }
 
        if (rc) {
@@ -1308,10 +1297,9 @@ abort:
 
                if (!srpc_event_pending(rpc)) {
                        srpc_client_rpc_done(rpc, -EINTR);
-                       return 1;
+                       return;
                }
        }
-       return 0;
 }
 
 struct srpc_client_rpc *
@@ -1322,8 +1310,8 @@ srpc_create_client_rpc(struct lnet_process_id peer, int service,
 {
        struct srpc_client_rpc *rpc;
 
-       LIBCFS_ALLOC(rpc, offsetof(struct srpc_client_rpc,
-                                  crpc_bulk.bk_iovs[nbulkiov]));
+       rpc = kzalloc(offsetof(struct srpc_client_rpc,
+                              crpc_bulk.bk_iovs[nbulkiov]), GFP_KERNEL);
        if (!rpc)
                return NULL;
 
index 8c10f0f149d5358445d284ebc686a0d4d4010534..ad04534f000c82fba4d6059cfd0d1aa8b8f86e6f 100644 (file)
@@ -169,11 +169,11 @@ struct srpc_buffer {
 };
 
 struct swi_workitem;
-typedef int (*swi_action_t) (struct swi_workitem *);
+typedef void (*swi_action_t) (struct swi_workitem *);
 
 struct swi_workitem {
-       struct cfs_wi_sched *swi_sched;
-       struct cfs_workitem swi_workitem;
+       struct workqueue_struct *swi_wq;
+       struct work_struct  swi_work;
        swi_action_t        swi_action;
        int                 swi_state;
 };
@@ -444,7 +444,7 @@ void srpc_free_bulk(struct srpc_bulk *bk);
 struct srpc_bulk *srpc_alloc_bulk(int cpt, unsigned int off,
                                  unsigned int bulk_npg, unsigned int bulk_len,
                                  int sink);
-int srpc_send_rpc(struct swi_workitem *wi);
+void srpc_send_rpc(struct swi_workitem *wi);
 int srpc_send_reply(struct srpc_server_rpc *rpc);
 int srpc_add_service(struct srpc_service *sv);
 int srpc_remove_service(struct srpc_service *sv);
@@ -456,8 +456,8 @@ void srpc_service_remove_buffers(struct srpc_service *sv, int nbuffer);
 void srpc_get_counters(struct srpc_counters *cnt);
 void srpc_set_counters(const struct srpc_counters *cnt);
 
-extern struct cfs_wi_sched *lst_sched_serial;
-extern struct cfs_wi_sched **lst_sched_test;
+extern struct workqueue_struct *lst_serial_wq;
+extern struct workqueue_struct **lst_test_wq;
 
 static inline int
 srpc_serv_is_framework(struct srpc_service *svc)
@@ -465,42 +465,36 @@ srpc_serv_is_framework(struct srpc_service *svc)
        return svc->sv_id < SRPC_FRAMEWORK_SERVICE_MAX_ID;
 }
 
-static inline int
-swi_wi_action(struct cfs_workitem *wi)
+static void
+swi_wi_action(struct work_struct *wi)
 {
        struct swi_workitem *swi;
 
-       swi = container_of(wi, struct swi_workitem, swi_workitem);
+       swi = container_of(wi, struct swi_workitem, swi_work);
 
-       return swi->swi_action(swi);
+       swi->swi_action(swi);
 }
 
 static inline void
-swi_init_workitem(struct swi_workitem *swi, void *data,
-                 swi_action_t action, struct cfs_wi_sched *sched)
+swi_init_workitem(struct swi_workitem *swi,
+                 swi_action_t action, struct workqueue_struct *wq)
 {
-       swi->swi_sched = sched;
+       swi->swi_wq = wq;
        swi->swi_action = action;
        swi->swi_state = SWI_STATE_NEWBORN;
-       cfs_wi_init(&swi->swi_workitem, data, swi_wi_action);
+       INIT_WORK(&swi->swi_work, swi_wi_action);
 }
 
 static inline void
 swi_schedule_workitem(struct swi_workitem *wi)
 {
-       cfs_wi_schedule(wi->swi_sched, &wi->swi_workitem);
-}
-
-static inline void
-swi_exit_workitem(struct swi_workitem *swi)
-{
-       cfs_wi_exit(swi->swi_sched, &swi->swi_workitem);
+       queue_work(wi->swi_wq, &wi->swi_work);
 }
 
 static inline int
-swi_deschedule_workitem(struct swi_workitem *swi)
+swi_cancel_workitem(struct swi_workitem *swi)
 {
-       return cfs_wi_deschedule(swi->swi_sched, &swi->swi_workitem);
+       return cancel_work_sync(&swi->swi_work);
 }
 
 int sfw_startup(void);
@@ -516,7 +510,7 @@ srpc_destroy_client_rpc(struct srpc_client_rpc *rpc)
        LASSERT(!atomic_read(&rpc->crpc_refcount));
 
        if (!rpc->crpc_fini)
-               LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc));
+               kfree(rpc);
        else
                (*rpc->crpc_fini)(rpc);
 }
@@ -533,8 +527,8 @@ srpc_init_client_rpc(struct srpc_client_rpc *rpc, struct lnet_process_id peer,
                                crpc_bulk.bk_iovs[nbulkiov]));
 
        INIT_LIST_HEAD(&rpc->crpc_list);
-       swi_init_workitem(&rpc->crpc_wi, rpc, srpc_send_rpc,
-                         lst_sched_test[lnet_cpt_of_nid(peer.nid)]);
+       swi_init_workitem(&rpc->crpc_wi, srpc_send_rpc,
+                         lst_test_wq[lnet_cpt_of_nid(peer.nid)]);
        spin_lock_init(&rpc->crpc_lock);
        atomic_set(&rpc->crpc_refcount, 1); /* 1 ref for caller */
 
index 7d6a7106c0a5030a856a6c870d668bb4e266374c..ecf8b9e1ed5c3f5332509190997adc9225391c45 100644 (file)
@@ -213,19 +213,18 @@ static inline void fld_cache_entry_add(struct fld_cache *cache,
  */
 static int fld_cache_shrink(struct fld_cache *cache)
 {
-       struct fld_cache_entry *flde;
-       struct list_head *curr;
        int num = 0;
 
        if (cache->fci_cache_count < cache->fci_cache_size)
                return 0;
 
-       curr = cache->fci_lru.prev;
-
        while (cache->fci_cache_count + cache->fci_threshold >
-              cache->fci_cache_size && curr != &cache->fci_lru) {
-               flde = list_entry(curr, struct fld_cache_entry, fce_lru);
-               curr = curr->prev;
+              cache->fci_cache_size &&
+              !list_empty(&cache->fci_lru)) {
+               struct fld_cache_entry *flde =
+                       list_last_entry(&cache->fci_lru,
+                                       struct fld_cache_entry, fce_lru);
+
                fld_cache_entry_delete(cache, flde);
                num++;
        }
index 8f1a225270063c9698ccfb1e1913fb7ff9fe53ba..100e993ab00be2ac0b7ad0a0b074e0973371c4b3 100644 (file)
@@ -141,9 +141,9 @@ struct lustre_sb_info {
 /* obd_mount.c */
 
 int lustre_start_mgc(struct super_block *sb);
-void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb,
-                                                 struct vfsmount *mnt));
-void lustre_register_kill_super_cb(void (*cfs)(struct super_block *sb));
+void lustre_register_super_ops(struct module *mod,
+                              int (*cfs)(struct super_block *sb),
+                              void (*ksc)(struct super_block *sb));
 int lustre_common_put_super(struct super_block *sb);
 
 int mgc_fsname2resid(char *fsname, struct ldlm_res_id *res_id, int type);
index a40f706a53a1e9adcba259033716714c30238e25..64b6fd4fed8f7a4670c05be3c324d09028dd2f4b 100644 (file)
@@ -341,8 +341,8 @@ void sptlrpc_conf_client_adapt(struct obd_device *obd);
 #define SPTLRPC_MAX_PAYLOAD     (1024)
 
 struct vfs_cred {
-       uint32_t        vc_uid;
-       uint32_t        vc_gid;
+       u32     vc_uid;
+       u32     vc_gid;
 };
 
 struct ptlrpc_ctx_ops {
index 67c535c5aa98698e1a4e37ff7cc933631d18f477..531e8ddfa9e50ed09313bde141ab8ce455ce92ab 100644 (file)
 #include <lustre_lib.h>
 #include <lprocfs_status.h>
 
-#define OBD_STATFS_NODELAY      0x0001  /* requests should be send without delay
-                                        * and resends for avoid deadlocks
-                                        */
-#define OBD_STATFS_FROM_CACHE   0x0002  /* the statfs callback should not update
-                                        * obd_osfs_age
-                                        */
-#define OBD_STATFS_FOR_MDT0    0x0004  /* The statfs is only for retrieving
-                                        * information from MDT0.
-                                        */
+/* requests should be send without delay and resends for avoid deadlocks */
+#define OBD_STATFS_NODELAY      0x0001
+/* the statfs callback should not update obd_osfs_age */
+#define OBD_STATFS_FROM_CACHE   0x0002
+/* the statfs is only for retrieving information from MDT0 */
+#define OBD_STATFS_FOR_MDT0    0x0004
 
 /* OBD Device Declarations */
 extern struct obd_device *obd_devs[MAX_OBD_DEVICES];
 extern rwlock_t obd_dev_lock;
 
 /* OBD Operations Declarations */
-struct obd_device *class_exp2obd(struct obd_export *);
+struct obd_device *class_exp2obd(struct obd_export *exp);
 int class_handle_ioctl(unsigned int cmd, unsigned long arg);
 int lustre_get_jobid(char *jobid);
 
@@ -63,10 +60,10 @@ struct lu_device_type;
 
 /* genops.c */
 extern struct list_head obd_types;
-struct obd_export *class_conn2export(struct lustre_handle *);
-int class_register_type(struct obd_ops *, struct md_ops *,
-                       const char *nm, struct lu_device_type *ldt);
-int class_unregister_type(const char *nm);
+struct obd_export *class_conn2export(struct lustre_handle *conn);
+int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
+                       const char *name, struct lu_device_type *ldt);
+int class_unregister_type(const char *name);
 
 struct obd_device *class_newdev(const char *type_name, const char *name);
 void class_release_dev(struct obd_device *obd);
@@ -137,7 +134,7 @@ int class_config_llog_handler(const struct lu_env *env,
                              struct llog_rec_hdr *rec, void *data);
 int class_add_uuid(const char *uuid, __u64 nid);
 
-/*obdecho*/
+/* obdecho */
 void lprocfs_echo_init_vars(struct lprocfs_static_vars *lvars);
 
 #define CFG_F_START     0x01   /* Set when we start updating from a log */
@@ -148,13 +145,13 @@ void lprocfs_echo_init_vars(struct lprocfs_static_vars *lvars);
 
 /* Passed as data param to class_config_parse_llog */
 struct config_llog_instance {
-       char           *cfg_obdname;
-       void           *cfg_instance;
+       char               *cfg_obdname;
+       void               *cfg_instance;
        struct super_block *cfg_sb;
        struct obd_uuid     cfg_uuid;
        llog_cb_t           cfg_callback;
-       int              cfg_last_idx; /* for partial llog processing */
-       int              cfg_flags;
+       int                 cfg_last_idx; /* for partial llog processing */
+       int                 cfg_flags;
 };
 
 int class_config_parse_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
@@ -172,30 +169,31 @@ enum {
 
 /* list of active configuration logs  */
 struct config_llog_data {
-       struct ldlm_res_id        cld_resid;
+       struct ldlm_res_id          cld_resid;
        struct config_llog_instance cld_cfg;
-       struct list_head                  cld_list_chain;
-       atomic_t                cld_refcount;
+       struct list_head            cld_list_chain;
+       atomic_t                    cld_refcount;
        struct config_llog_data    *cld_sptlrpc;/* depended sptlrpc log */
        struct config_llog_data    *cld_params; /* common parameters log */
        struct config_llog_data    *cld_recover;/* imperative recover log */
-       struct obd_export         *cld_mgcexp;
+       struct obd_export          *cld_mgcexp;
        struct mutex                cld_lock;
-       int                      cld_type;
-       unsigned int            cld_stopping:1, /* we were told to stop
-                                                * watching
-                                                */
-                               cld_lostlock:1; /* lock not requeued */
-       char                    cld_logname[0];
+       int                         cld_type;
+       unsigned int                cld_stopping:1, /*
+                                                    * we were told to stop
+                                                    * watching
+                                                    */
+                                   cld_lostlock:1; /* lock not requeued */
+       char                        cld_logname[0];
 };
 
 struct lustre_profile {
-       struct list_head       lp_list;
-       char        *lp_profile;
-       char        *lp_dt;
-       char        *lp_md;
-       int                     lp_refs;
-       bool                    lp_list_deleted;
+       struct list_head lp_list;
+       char            *lp_profile;
+       char            *lp_dt;
+       char            *lp_md;
+       int              lp_refs;
+       bool             lp_list_deleted;
 };
 
 struct lustre_profile *class_get_profile(const char *prof);
@@ -205,9 +203,11 @@ void class_del_profiles(void);
 
 #if LUSTRE_TRACKS_LOCK_EXP_REFS
 
-void __class_export_add_lock_ref(struct obd_export *, struct ldlm_lock *);
-void __class_export_del_lock_ref(struct obd_export *, struct ldlm_lock *);
-extern void (*class_export_dump_hook)(struct obd_export *);
+void __class_export_add_lock_ref(struct obd_export *exp,
+                                struct ldlm_lock *lock);
+void __class_export_del_lock_ref(struct obd_export *exp,
+                                struct ldlm_lock *lock);
+extern void (*class_export_dump_hook)(struct obd_export *exp);
 
 #else
 
@@ -223,8 +223,8 @@ struct obd_export *class_new_export(struct obd_device *obddev,
                                    struct obd_uuid *cluuid);
 void class_unlink_export(struct obd_export *exp);
 
-struct obd_import *class_import_get(struct obd_import *);
-void class_import_put(struct obd_import *);
+struct obd_import *class_import_get(struct obd_import *imp);
+void class_import_put(struct obd_import *imp);
 struct obd_import *class_new_import(struct obd_device *obd);
 void class_destroy_import(struct obd_import *exp);
 
@@ -299,7 +299,8 @@ void obdo_to_ioobj(const struct obdo *oa, struct obd_ioobj *ioobj);
 #define MDP(dev, op)    (dev)->obd_type->typ_md_ops->op
 #define CTXTP(ctxt, op) (ctxt)->loc_logops->lop_##op
 
-/* Ensure obd_setup: used for cleanup which must be called
+/*
+ * Ensure obd_setup: used for cleanup which must be called
  * while obd is stopping
  */
 static inline int obd_check_dev(struct obd_device *obd)
@@ -326,108 +327,116 @@ static inline int obd_check_dev_active(struct obd_device *obd)
        return rc;
 }
 
-#define OBD_COUNTER_OFFSET(op)                           \
-       ((offsetof(struct obd_ops, op) -                  \
-         offsetof(struct obd_ops, iocontrol))          \
-        / sizeof(((struct obd_ops *)(0))->iocontrol))
-
-#define OBD_COUNTER_INCREMENT(obdx, op)                           \
-       if ((obdx)->obd_stats) {                                  \
-               unsigned int coffset;                        \
-               coffset = (unsigned int)((obdx)->obd_cntr_base) + \
-                       OBD_COUNTER_OFFSET(op);            \
-               LASSERT(coffset < (obdx)->obd_stats->ls_num);     \
-               lprocfs_counter_incr((obdx)->obd_stats, coffset); \
-       }
+#define OBD_COUNTER_OFFSET(op)                                 \
+       ((offsetof(struct obd_ops, op) -                        \
+               offsetof(struct obd_ops, iocontrol))            \
+               / sizeof(((struct obd_ops *)(0))->iocontrol))
 
-#define EXP_COUNTER_INCREMENT(export, op)                                  \
-       if ((export)->exp_obd->obd_stats) {                       \
+#define OBD_COUNTER_INCREMENT(obdx, op)                                        \
+do {                                                                   \
+       if ((obdx)->obd_stats) {                                        \
                unsigned int coffset;                                   \
+               coffset = (unsigned int)((obdx)->obd_cntr_base) +       \
+                       OBD_COUNTER_OFFSET(op);                         \
+               LASSERT(coffset < (obdx)->obd_stats->ls_num);           \
+               lprocfs_counter_incr((obdx)->obd_stats, coffset);       \
+       }                                                               \
+} while (0)
+
+#define EXP_COUNTER_INCREMENT(export, op)                                   \
+do {                                                                        \
+       if ((export)->exp_obd->obd_stats) {                                  \
+               unsigned int coffset;                                        \
                coffset = (unsigned int)((export)->exp_obd->obd_cntr_base) + \
-                       OBD_COUNTER_OFFSET(op);                       \
+                       OBD_COUNTER_OFFSET(op);                              \
                LASSERT(coffset < (export)->exp_obd->obd_stats->ls_num);     \
                lprocfs_counter_incr((export)->exp_obd->obd_stats, coffset); \
-       }
+       }                                                                    \
+} while (0)
 
-#define MD_COUNTER_OFFSET(op)                             \
-       ((offsetof(struct md_ops, op) -            \
-         offsetof(struct md_ops, getstatus))            \
-        / sizeof(((struct md_ops *)(0))->getstatus))
+#define MD_COUNTER_OFFSET(op)                                  \
+       ((offsetof(struct md_ops, op) -                         \
+               offsetof(struct md_ops, getstatus))             \
+               / sizeof(((struct md_ops *)(0))->getstatus))
 
-#define MD_COUNTER_INCREMENT(obdx, op)                    \
-       if ((obd)->md_stats) {                     \
-               unsigned int coffset;                       \
+#define MD_COUNTER_INCREMENT(obdx, op)                          \
+do {                                                            \
+       if ((obd)->md_stats) {                                   \
+               unsigned int coffset;                            \
                coffset = (unsigned int)((obdx)->md_cntr_base) + \
-                       MD_COUNTER_OFFSET(op);             \
-               LASSERT(coffset < (obdx)->md_stats->ls_num);     \
+                       MD_COUNTER_OFFSET(op);                   \
+               LASSERT(coffset < (obdx)->md_stats->ls_num);     \
                lprocfs_counter_incr((obdx)->md_stats, coffset); \
-       }
+       }                                                        \
+} while (0)
 
-#define EXP_MD_COUNTER_INCREMENT(export, op)                            \
-       if ((export)->exp_obd->obd_stats) {                               \
-               unsigned int coffset;                                   \
-               coffset = (unsigned int)((export)->exp_obd->md_cntr_base) +  \
-                       MD_COUNTER_OFFSET(op);                         \
-               LASSERT(coffset < (export)->exp_obd->md_stats->ls_num);      \
-               lprocfs_counter_incr((export)->exp_obd->md_stats, coffset);  \
-               if ((export)->exp_md_stats)                               \
-                       lprocfs_counter_incr(                           \
+#define EXP_MD_COUNTER_INCREMENT(export, op)                               \
+do {                                                                       \
+       if ((export)->exp_obd->obd_stats) {                                 \
+               unsigned int coffset;                                       \
+               coffset = (unsigned int)((export)->exp_obd->md_cntr_base) + \
+                       MD_COUNTER_OFFSET(op);                              \
+               LASSERT(coffset < (export)->exp_obd->md_stats->ls_num);     \
+               lprocfs_counter_incr((export)->exp_obd->md_stats, coffset); \
+               if ((export)->exp_md_stats)                                 \
+                       lprocfs_counter_incr(                               \
                                (export)->exp_md_stats, coffset);           \
-       }
+       }                                                                   \
+} while (0)
 
 #define EXP_CHECK_MD_OP(exp, op)                               \
-do {                                                       \
-       if (!(exp)) {                               \
-               CERROR("obd_" #op ": NULL export\n");      \
-               return -ENODEV;                         \
-       }                                                      \
-       if (!(exp)->exp_obd || !OBT((exp)->exp_obd)) {   \
+do {                                                           \
+       if (!(exp)) {                                           \
+               CERROR("obd_" #op ": NULL export\n");           \
+               return -ENODEV;                                 \
+       }                                                       \
+       if (!(exp)->exp_obd || !OBT((exp)->exp_obd)) {          \
                CERROR("obd_" #op ": cleaned up obd\n");        \
-               return -EOPNOTSUPP;                         \
-       }                                                      \
-       if (!OBT((exp)->exp_obd) || !MDP((exp)->exp_obd, op)) { \
+               return -EOPNOTSUPP;                             \
+       }                                                       \
+       if (!OBT((exp)->exp_obd) || !MDP((exp)->exp_obd, op)) { \
                CERROR("obd_" #op ": dev %s/%d no operation\n", \
-                      (exp)->exp_obd->obd_name,                \
-                      (exp)->exp_obd->obd_minor);            \
-               return -EOPNOTSUPP;                         \
-       }                                                      \
+                       (exp)->exp_obd->obd_name,               \
+                       (exp)->exp_obd->obd_minor);             \
+               return -EOPNOTSUPP;                             \
+       }                                                       \
 } while (0)
 
-#define OBD_CHECK_DT_OP(obd, op, err)                     \
-do {                                                       \
-       if (!OBT(obd) || !OBP((obd), op)) {                  \
-               if (err)                                        \
-                       CERROR("obd_" #op ": dev %d no operation\n",    \
-                              obd->obd_minor);          \
-               return err;                                 \
-       }                                                      \
+#define OBD_CHECK_DT_OP(obd, op, err)                                  \
+do {                                                                   \
+       if (!OBT(obd) || !OBP((obd), op)) {                             \
+               if (err)                                                \
+                       CERROR("obd_" #op ": dev %d no operation\n",    \
+                               obd->obd_minor);                        \
+               return err;                                             \
+       }                                                               \
 } while (0)
 
 #define EXP_CHECK_DT_OP(exp, op)                               \
-do {                                                       \
-       if (!(exp)) {                               \
-               CERROR("obd_" #op ": NULL export\n");      \
-               return -ENODEV;                         \
-       }                                                      \
-       if (!(exp)->exp_obd || !OBT((exp)->exp_obd)) {   \
+do {                                                           \
+       if (!(exp)) {                                           \
+               CERROR("obd_" #op ": NULL export\n");           \
+               return -ENODEV;                                 \
+       }                                                       \
+       if (!(exp)->exp_obd || !OBT((exp)->exp_obd)) {          \
                CERROR("obd_" #op ": cleaned up obd\n");        \
-               return -EOPNOTSUPP;                         \
-       }                                                      \
-       if (!OBT((exp)->exp_obd) || !OBP((exp)->exp_obd, op)) { \
-               CERROR("obd_" #op ": dev %d no operation\n",    \
-                      (exp)->exp_obd->obd_minor);            \
-               return -EOPNOTSUPP;                         \
-       }                                                      \
+               return -EOPNOTSUPP;                             \
+       }                                                       \
+       if (!OBT((exp)->exp_obd) || !OBP((exp)->exp_obd, op)) { \
+               CERROR("obd_" #op ": dev %d no operation\n",    \
+                       (exp)->exp_obd->obd_minor);             \
+               return -EOPNOTSUPP;                             \
+       }                                                       \
 } while (0)
 
-#define CTXT_CHECK_OP(ctxt, op, err)                            \
-do {                                                            \
-       if (!OBT(ctxt->loc_obd) || !CTXTP((ctxt), op)) {             \
-               if (err)                                             \
-                       CERROR("lop_" #op ": dev %d no operation\n", \
-                              ctxt->loc_obd->obd_minor);           \
-               return err;                                      \
-       }                                                           \
+#define CTXT_CHECK_OP(ctxt, op, err)                                   \
+do {                                                                   \
+       if (!OBT(ctxt->loc_obd) || !CTXTP((ctxt), op)) {                \
+               if (err)                                                \
+                       CERROR("lop_" #op ": dev %d no operation\n",    \
+                               ctxt->loc_obd->obd_minor);              \
+               return err;                                             \
+       }                                                               \
 } while (0)
 
 static inline int class_devno_max(void)
@@ -481,14 +490,11 @@ static inline int obd_set_info_async(const struct lu_env *env,
  * obd_precleanup() and obd_cleanup() call both lu_device and obd operations.
  */
 
-#define DECLARE_LU_VARS(ldt, d)                 \
-       struct lu_device_type *ldt;       \
-       struct lu_device *d
-
 static inline int obd_setup(struct obd_device *obd, struct lustre_cfg *cfg)
 {
        int rc;
-       DECLARE_LU_VARS(ldt, d);
+       struct lu_device_type *ldt;
+       struct lu_device *d;
 
        ldt = obd->obd_type->typ_lu;
        if (ldt) {
@@ -526,7 +532,8 @@ static inline int obd_setup(struct obd_device *obd, struct lustre_cfg *cfg)
 static inline int obd_precleanup(struct obd_device *obd)
 {
        int rc;
-       DECLARE_LU_VARS(ldt, d);
+       struct lu_device_type *ldt;
+       struct lu_device *d;
 
        rc = obd_check_dev(obd);
        if (rc)
@@ -552,7 +559,8 @@ static inline int obd_precleanup(struct obd_device *obd)
 static inline int obd_cleanup(struct obd_device *obd)
 {
        int rc;
-       DECLARE_LU_VARS(ldt, d);
+       struct lu_device_type *ldt;
+       struct lu_device *d;
 
        rc = obd_check_dev(obd);
        if (rc)
@@ -579,7 +587,8 @@ static inline int obd_cleanup(struct obd_device *obd)
 
 static inline void obd_cleanup_client_import(struct obd_device *obd)
 {
-       /* If we set up but never connected, the
+       /*
+        * If we set up but never connected, the
         * client import will not have been cleaned.
         */
        down_write(&obd->u.cli.cl_sem);
@@ -600,7 +609,8 @@ static inline int
 obd_process_config(struct obd_device *obd, int datalen, void *data)
 {
        int rc;
-       DECLARE_LU_VARS(ldt, d);
+       struct lu_device_type *ldt;
+       struct lu_device *d;
 
        rc = obd_check_dev(obd);
        if (rc)
@@ -717,7 +727,8 @@ static inline struct obd_uuid *obd_get_uuid(struct obd_export *exp)
        return uuid;
 }
 
-/** Create a new /a exp on device /a obd for the uuid /a cluuid
+/*
+ * Create a new /a exp on device /a obd for the uuid /a cluuid
  * @param exp New export handle
  * @param d Connect data, supported flags are set, flags also understood
  *    by obd are returned.
@@ -729,7 +740,8 @@ static inline int obd_connect(const struct lu_env *env,
                              void *localdata)
 {
        int rc;
-       __u64 ocf = data ? data->ocd_connect_flags : 0; /* for post-condition
+       __u64 ocf = data ? data->ocd_connect_flags : 0; /*
+                                                        * for post-condition
                                                         * check
                                                         */
 
@@ -838,7 +850,9 @@ static inline int obd_pool_del(struct obd_device *obd, char *poolname)
        return rc;
 }
 
-static inline int obd_pool_add(struct obd_device *obd, char *poolname, char *ostname)
+static inline int obd_pool_add(struct obd_device *obd,
+                              char *poolname,
+                              char *ostname)
 {
        int rc;
 
@@ -849,7 +863,9 @@ static inline int obd_pool_add(struct obd_device *obd, char *poolname, char *ost
        return rc;
 }
 
-static inline int obd_pool_rem(struct obd_device *obd, char *poolname, char *ostname)
+static inline int obd_pool_rem(struct obd_device *obd,
+                              char *poolname,
+                              char *ostname)
 {
        int rc;
 
@@ -894,7 +910,8 @@ static inline int obd_destroy_export(struct obd_export *exp)
        return 0;
 }
 
-/* @max_age is the oldest time in jiffies that we accept using a cached data.
+/*
+ * @max_age is the oldest time in jiffies that we accept using a cached data.
  * If the cache is older than @max_age we will get a new value from the
  * target.  Use a value of "cfs_time_current() + HZ" to guarantee freshness.
  */
@@ -955,7 +972,8 @@ static inline int obd_statfs_rqset(struct obd_export *exp,
        return rc;
 }
 
-/* @max_age is the oldest time in jiffies that we accept using a cached data.
+/*
+ * @max_age is the oldest time in jiffies that we accept using a cached data.
  * If the cache is older than @max_age we will get a new value from the
  * target.  Use a value of "cfs_time_current() + HZ" to guarantee freshness.
  */
@@ -983,7 +1001,8 @@ static inline int obd_statfs(const struct lu_env *env, struct obd_export *exp,
                        spin_unlock(&obd->obd_osfs_lock);
                }
        } else {
-               CDEBUG(D_SUPER, "%s: use %p cache blocks %llu/%llu objects %llu/%llu\n",
+               CDEBUG(D_SUPER,
+                      "%s: use %p cache blocks %llu/%llu objects %llu/%llu\n",
                       obd->obd_name, &obd->obd_osfs,
                       obd->obd_osfs.os_bavail, obd->obd_osfs.os_blocks,
                       obd->obd_osfs.os_ffree, obd->obd_osfs.os_files);
@@ -1118,7 +1137,8 @@ static inline int obd_quotactl(struct obd_export *exp,
 static inline int obd_health_check(const struct lu_env *env,
                                   struct obd_device *obd)
 {
-       /* returns: 0 on healthy
+       /*
+        * returns: 0 on healthy
         *       >0 on unhealthy + reason code/flag
         *          however the only supported reason == 1 right now
         *          We'll need to define some better reasons
@@ -1491,7 +1511,8 @@ static inline int md_get_fid_from_lsm(struct obd_export *exp,
        return rc;
 }
 
-/* Unpack an MD struct from disk to in-memory format.
+/*
+ * Unpack an MD struct from disk to in-memory format.
  * Returns +ve size of unpacked MD (0 for free), or -ve error.
  *
  * If *plsm != NULL and lmm == NULL then *lsm will be freed.
@@ -1523,11 +1544,12 @@ struct lwp_register_item {
        struct obd_export **lri_exp;
        register_lwp_cb     lri_cb_func;
        void               *lri_cb_data;
-       struct list_head            lri_list;
+       struct list_head    lri_list;
        char                lri_name[MTI_NAME_MAXLEN];
 };
 
-/* I'm as embarrassed about this as you are.
+/*
+ * I'm as embarrassed about this as you are.
  *
  * <shaver> // XXX do not look into _superhack with remaining eye
  * <shaver> // XXX if this were any uglier, I'd get my own show on MTV
@@ -1562,7 +1584,8 @@ int class_procfs_init(void);
 int class_procfs_clean(void);
 
 /* prng.c */
-#define ll_generate_random_uuid(uuid_out) cfs_get_random_bytes(uuid_out, sizeof(class_uuid_t))
+#define ll_generate_random_uuid(uuid_out) \
+       get_random_bytes(uuid_out, sizeof(class_uuid_t))
 
 /* statfs_pack.c */
 struct kstatfs;
index fac9d19d50b6c60149a49fbe8676a6eab48b9e63..11b11b5f321667654ebf2e03ed5dfc3ad62a5eb8 100644 (file)
@@ -64,7 +64,6 @@
 __u64 ldlm_extent_shift_kms(struct ldlm_lock *lock, __u64 old_kms)
 {
        struct ldlm_resource *res = lock->l_resource;
-       struct list_head *tmp;
        struct ldlm_lock *lck;
        __u64 kms = 0;
 
@@ -74,8 +73,7 @@ __u64 ldlm_extent_shift_kms(struct ldlm_lock *lock, __u64 old_kms)
         */
        ldlm_set_kms_ignore(lock);
 
-       list_for_each(tmp, &res->lr_granted) {
-               lck = list_entry(tmp, struct ldlm_lock, l_res_link);
+       list_for_each_entry(lck, &res->lr_granted, l_res_link) {
 
                if (ldlm_is_kms_ignore(lck))
                        continue;
index 7cb61e2e7d3bf6801206873ee1da9cde186ec2fc..7cbc6a06afec11af9fd37e3c729bbf3c1be6c483 100644 (file)
@@ -886,17 +886,15 @@ static void search_granted_lock(struct list_head *queue,
                                struct ldlm_lock *req,
                                struct sl_insert_point *prev)
 {
-       struct list_head *tmp;
        struct ldlm_lock *lock, *mode_end, *policy_end;
 
-       list_for_each(tmp, queue) {
-               lock = list_entry(tmp, struct ldlm_lock, l_res_link);
+       list_for_each_entry(lock, queue, l_res_link) {
 
                mode_end = list_prev_entry(lock, l_sl_mode);
 
                if (lock->l_req_mode != req->l_req_mode) {
                        /* jump to last lock of mode group */
-                       tmp = &mode_end->l_res_link;
+                       lock = mode_end;
                        continue;
                }
 
@@ -933,9 +931,7 @@ static void search_granted_lock(struct list_head *queue,
                                        break;
 
                                /* go to next policy group within mode group */
-                               tmp = policy_end->l_res_link.next;
-                               lock = list_entry(tmp, struct ldlm_lock,
-                                                 l_res_link);
+                               lock = list_next_entry(policy_end, l_res_link);
                        }  /* loop over policy groups within the mode group */
 
                        /* insert point is last lock of the mode group,
@@ -1687,7 +1683,7 @@ ldlm_work_bl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
        if (list_empty(arg->list))
                return -ENOENT;
 
-       lock = list_entry(arg->list->next, struct ldlm_lock, l_bl_ast);
+       lock = list_first_entry(arg->list, struct ldlm_lock, l_bl_ast);
 
        /* nobody should touch l_bl_ast */
        lock_res_and_lock(lock);
@@ -1723,7 +1719,7 @@ ldlm_work_cp_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
        if (list_empty(arg->list))
                return -ENOENT;
 
-       lock = list_entry(arg->list->next, struct ldlm_lock, l_cp_ast);
+       lock = list_first_entry(arg->list, struct ldlm_lock, l_cp_ast);
 
        /* It's possible to receive a completion AST before we've set
         * the l_completion_ast pointer: either because the AST arrived
@@ -1769,7 +1765,7 @@ ldlm_work_revoke_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
        if (list_empty(arg->list))
                return -ENOENT;
 
-       lock = list_entry(arg->list->next, struct ldlm_lock, l_rk_ast);
+       lock = list_first_entry(arg->list, struct ldlm_lock, l_rk_ast);
        list_del_init(&lock->l_rk_ast);
 
        /* the desc just pretend to exclusive */
@@ -1796,7 +1792,7 @@ static int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
        if (list_empty(arg->list))
                return -ENOENT;
 
-       gl_work = list_entry(arg->list->next, struct ldlm_glimpse_work,
+       gl_work = list_first_entry(arg->list, struct ldlm_glimpse_work,
                             gl_list);
        list_del_init(&gl_work->gl_list);
 
index 2d5a2c932ddc80d40c3842d287e3f63c0638f7fb..5f6e7c933b8124983428b1ecc23acbe215f449a7 100644 (file)
@@ -696,13 +696,13 @@ static int ldlm_bl_get_work(struct ldlm_bl_pool *blp,
        /* process a request from the blp_list at least every blp_num_threads */
        if (!list_empty(&blp->blp_list) &&
            (list_empty(&blp->blp_prio_list) || num_bl == 0))
-               blwi = list_entry(blp->blp_list.next,
-                                 struct ldlm_bl_work_item, blwi_entry);
+               blwi = list_first_entry(&blp->blp_list,
+                                       struct ldlm_bl_work_item, blwi_entry);
        else
                if (!list_empty(&blp->blp_prio_list))
-                       blwi = list_entry(blp->blp_prio_list.next,
-                                         struct ldlm_bl_work_item,
-                                         blwi_entry);
+                       blwi = list_first_entry(&blp->blp_prio_list,
+                                               struct ldlm_bl_work_item,
+                                               blwi_entry);
 
        if (blwi) {
                if (++num_bl >= num_th)
@@ -1093,8 +1093,10 @@ static int ldlm_cleanup(void)
                kset_unregister(ldlm_ns_kset);
        if (ldlm_svc_kset)
                kset_unregister(ldlm_svc_kset);
-       if (ldlm_kobj)
+       if (ldlm_kobj) {
+               sysfs_remove_group(ldlm_kobj, &ldlm_attr_group);
                kobject_put(ldlm_kobj);
+       }
 
        ldlm_debugfs_cleanup();
 
index da65d00a7811d94440552f65a6ae75da6420d2c1..8563bd32befa32ddb055c49bf888656e4d3ad2da 100644 (file)
@@ -1086,8 +1086,12 @@ int ldlm_pools_init(void)
        int rc;
 
        rc = ldlm_pools_thread_start();
-       if (rc == 0)
-               register_shrinker(&ldlm_pools_cli_shrinker);
+       if (rc)
+               return rc;
+
+       rc = register_shrinker(&ldlm_pools_cli_shrinker);
+       if (rc)
+               ldlm_pools_thread_stop();
 
        return rc;
 }
index 02ea14c9b089e773246dead9d7070d7204793027..6aa37463db46b2548485fb10e795352dd612c5c0 100644 (file)
@@ -1656,7 +1656,7 @@ int ldlm_cli_cancel_list(struct list_head *cancels, int count,
         */
        while (count > 0) {
                LASSERT(!list_empty(cancels));
-               lock = list_entry(cancels->next, struct ldlm_lock, l_bl_ast);
+               lock = list_first_entry(cancels, struct ldlm_lock, l_bl_ast);
                LASSERT(lock->l_conn_export);
 
                if (exp_connect_cancelset(lock->l_conn_export)) {
@@ -1780,7 +1780,7 @@ EXPORT_SYMBOL(ldlm_cli_cancel_unused);
 static int ldlm_resource_foreach(struct ldlm_resource *res,
                                 ldlm_iterator_t iter, void *closure)
 {
-       struct list_head *tmp, *next;
+       struct ldlm_lock *tmp;
        struct ldlm_lock *lock;
        int rc = LDLM_ITER_CONTINUE;
 
@@ -1788,18 +1788,14 @@ static int ldlm_resource_foreach(struct ldlm_resource *res,
                return LDLM_ITER_CONTINUE;
 
        lock_res(res);
-       list_for_each_safe(tmp, next, &res->lr_granted) {
-               lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-
+       list_for_each_entry_safe(lock, tmp, &res->lr_granted, l_res_link) {
                if (iter(lock, closure) == LDLM_ITER_STOP) {
                        rc = LDLM_ITER_STOP;
                        goto out;
                }
        }
 
-       list_for_each_safe(tmp, next, &res->lr_waiting) {
-               lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-
+       list_for_each_entry_safe(lock, tmp, &res->lr_waiting, l_res_link) {
                if (iter(lock, closure) == LDLM_ITER_STOP) {
                        rc = LDLM_ITER_STOP;
                        goto out;
index 2689ffdf10e36f9ddd3e3200053b7f3f10309ad1..9958533cc227c36ee473f9b05a5adc573fbc2542 100644 (file)
@@ -752,24 +752,22 @@ extern struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock);
 static void cleanup_resource(struct ldlm_resource *res, struct list_head *q,
                             __u64 flags)
 {
-       struct list_head *tmp;
        int rc = 0;
        bool local_only = !!(flags & LDLM_FL_LOCAL_ONLY);
 
        do {
-               struct ldlm_lock *lock = NULL;
+               struct ldlm_lock *lock = NULL, *tmp;
                struct lustre_handle lockh;
 
                /* First, we look for non-cleaned-yet lock
                 * all cleaned locks are marked by CLEANED flag.
                 */
                lock_res(res);
-               list_for_each(tmp, q) {
-                       lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-                       if (ldlm_is_cleaned(lock)) {
-                               lock = NULL;
+               list_for_each_entry(tmp, q, l_res_link) {
+                       if (ldlm_is_cleaned(tmp))
                                continue;
-                       }
+
+                       lock = tmp;
                        LDLM_LOCK_GET(lock);
                        ldlm_set_cleaned(lock);
                        break;
@@ -1283,19 +1281,15 @@ void ldlm_res2desc(struct ldlm_resource *res, struct ldlm_resource_desc *desc)
  */
 void ldlm_dump_all_namespaces(enum ldlm_side client, int level)
 {
-       struct list_head *tmp;
+       struct ldlm_namespace *ns;
 
        if (!((libcfs_debug | D_ERROR) & level))
                return;
 
        mutex_lock(ldlm_namespace_lock(client));
 
-       list_for_each(tmp, ldlm_namespace_list(client)) {
-               struct ldlm_namespace *ns;
-
-               ns = list_entry(tmp, struct ldlm_namespace, ns_list_chain);
+       list_for_each_entry(ns, ldlm_namespace_list(client), ns_list_chain)
                ldlm_namespace_dump(level, ns);
-       }
 
        mutex_unlock(ldlm_namespace_lock(client));
 }
index 6f59045be0f922d9ecc711c165ba53d0d7b591e2..99b0b77c75f51f5d8205ceec875d5de0446588e7 100644 (file)
@@ -1337,9 +1337,9 @@ finish_req:
                                               cmd == LL_IOC_MDC_GETINFO)) {
                                rc = 0;
                                goto skip_lmm;
-                       } else {
-                               goto out_req;
                        }
+
+                       goto out_req;
                }
 
                if (cmd == IOC_MDC_GETFILESTRIPE ||
index 0d62fcf016dca013dfdde5a7094e9a20a7088717..f68c2e88f12b935d97376043a789d16625411d40 100644 (file)
@@ -792,7 +792,7 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request,
 extern struct super_operations lustre_super_operations;
 
 void ll_lli_init(struct ll_inode_info *lli);
-int ll_fill_super(struct super_block *sb, struct vfsmount *mnt);
+int ll_fill_super(struct super_block *sb);
 void ll_put_super(struct super_block *sb);
 void ll_kill_super(struct super_block *sb);
 struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock);
index 8666f1e81ade7ad24e2e60760ac03aa4c1d1dad0..6735a6f006d2b18e2321ef0e8589e6deaf2f1b1e 100644 (file)
@@ -146,8 +146,7 @@ static void ll_free_sbi(struct super_block *sb)
        kfree(sbi);
 }
 
-static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
-                                   struct vfsmount *mnt)
+static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
 {
        struct inode *root = NULL;
        struct ll_sb_info *sbi = ll_s2sbi(sb);
@@ -236,7 +235,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                                   "An MDT (md %s) is performing recovery, of which this client is not a part. Please wait for recovery to complete, abort, or time out.\n",
                                   md);
                goto out;
-       } else if (err) {
+       }
+
+       if (err) {
                CERROR("cannot connect to %s: rc = %d\n", md, err);
                goto out;
        }
@@ -865,7 +866,7 @@ void ll_lli_init(struct ll_inode_info *lli)
        mutex_init(&lli->lli_layout_mutex);
 }
 
-int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
+int ll_fill_super(struct super_block *sb)
 {
        struct lustre_profile *lprof = NULL;
        struct lustre_sb_info *lsi = s2lsi(sb);
@@ -942,7 +943,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
        }
 
        /* connections, registrations, sb setup */
-       err = client_common_fill_super(sb, md, dt, mnt);
+       err = client_common_fill_super(sb, md, dt);
        if (!err)
                sbi->ll_client_common_fill_super_succeeded = 1;
 
index 0bda111a096ed4131fa272fdf9a070a4eea2edda..9b0bb3541a84a8a95f2d26173a7a3cbaef87f6da 100644 (file)
@@ -86,8 +86,7 @@ MODULE_ALIAS_FS("lustre");
 static int __init lustre_init(void)
 {
        struct lnet_process_id lnet_id;
-       struct timespec64 ts;
-       int i, rc, seed[2];
+       int i, rc;
 
        BUILD_BUG_ON(sizeof(LUSTRE_VOLATILE_HDR) !=
                     LUSTRE_VOLATILE_HDR_LEN + 1);
@@ -126,22 +125,20 @@ static int __init lustre_init(void)
                goto out_debugfs;
        }
 
-       cfs_get_random_bytes(seed, sizeof(seed));
-
        /* Nodes with small feet have little entropy. The NID for this
         * node gives the most entropy in the low bits
         */
        for (i = 0;; i++) {
+               u32 seed;
+
                if (LNetGetId(i, &lnet_id) == -ENOENT)
                        break;
-
-               if (LNET_NETTYP(LNET_NIDNET(lnet_id.nid)) != LOLND)
-                       seed[0] ^= LNET_NIDADDR(lnet_id.nid);
+               if (LNET_NETTYP(LNET_NIDNET(lnet_id.nid)) != LOLND) {
+                        seed = LNET_NIDADDR(lnet_id.nid);
+                        add_device_randomness(&seed, sizeof(seed));
+               }
        }
 
-       ktime_get_ts64(&ts);
-       cfs_srand(ts.tv_sec ^ seed[0], ts.tv_nsec ^ seed[1]);
-
        rc = vvp_global_init();
        if (rc != 0)
                goto out_sysfs;
@@ -159,8 +156,7 @@ static int __init lustre_init(void)
        if (rc != 0)
                goto out_inode_fini_env;
 
-       lustre_register_client_fill_super(ll_fill_super);
-       lustre_register_kill_super_cb(ll_kill_super);
+       lustre_register_super_ops(THIS_MODULE, ll_fill_super, ll_kill_super);
        lustre_register_client_process_config(ll_process_config);
 
        return 0;
@@ -181,8 +177,7 @@ out_cache:
 
 static void __exit lustre_exit(void)
 {
-       lustre_register_client_fill_super(NULL);
-       lustre_register_kill_super_cb(NULL);
+       lustre_register_super_ops(NULL, NULL, NULL);
        lustre_register_client_process_config(NULL);
 
        debugfs_remove(llite_root);
index 8ccc8b799c026cab94ff719ce555e8990b774a12..987c03b058e6f719907262bdd4449f7323db9948 100644 (file)
@@ -384,7 +384,7 @@ int cl_sb_fini(struct super_block *sb)
 struct vvp_pgcache_id {
        unsigned int             vpi_bucket;
        unsigned int             vpi_depth;
-       uint32_t                 vpi_index;
+       u32                      vpi_index;
 
        unsigned int             vpi_curdep;
        struct lu_object_header *vpi_obj;
index bfae98e82d6f3c0e1f4ab217f64f4dc75e65defd..e7a4778e02e4f53559083233680e6bd6fb6c664e 100644 (file)
@@ -699,7 +699,7 @@ static int vvp_io_read_start(const struct lu_env *env,
        result = vvp_prep_size(env, obj, io, pos, tot, &exceed);
        if (result != 0)
                return result;
-       else if (exceed != 0)
+       if (exceed != 0)
                goto out;
 
        LU_OBJECT_HEADER(D_INODE, env, &obj->co_lu,
index ae28ddf80d9b3eb110cca0c70831647eee7d3195..a56d71c2dda2b0f8bec7164d6b79fb01ee0cd851 100644 (file)
@@ -115,19 +115,19 @@ static inline const struct lsm_operations *lsm_op_find(int magic)
  */
 #if BITS_PER_LONG == 64
 # define lov_do_div64(n, base) ({                                      \
-       uint64_t __base = (base);                                       \
-       uint64_t __rem;                                                 \
-       __rem = ((uint64_t)(n)) % __base;                               \
-       (n) = ((uint64_t)(n)) / __base;                                 \
+       u64 __base = (base);                                    \
+       u64 __rem;                                                      \
+       __rem = ((u64)(n)) % __base;                            \
+       (n) = ((u64)(n)) / __base;                                      \
        __rem;                                                          \
 })
 #elif BITS_PER_LONG == 32
 # define lov_do_div64(n, base) ({                                      \
-       uint64_t __rem;                                                 \
+       u64 __rem;                                                      \
        if ((sizeof(base) > 4) && (((base) & 0xffffffff00000000ULL) != 0)) {  \
                int __remainder;                                              \
                LASSERTF(!((base) & (LOV_MIN_STRIPE_SIZE - 1)), "64 bit lov " \
-                        "division %llu / %llu\n", (n), (uint64_t)(base));    \
+                        "division %llu / %llu\n", (n), (u64)(base));    \
                __remainder = (n) & (LOV_MIN_STRIPE_SIZE - 1);          \
                (n) >>= LOV_MIN_STRIPE_BITS;                            \
                __rem = do_div(n, (base) >> LOV_MIN_STRIPE_BITS);       \
index 7ce01026a40937e1c62ede11be647e9eb15cefdd..ec70c12e5b40d46b53bb11ecbdc2ca8cbc991248 100644 (file)
@@ -828,11 +828,9 @@ out:
 static int lov_cleanup(struct obd_device *obd)
 {
        struct lov_obd *lov = &obd->u.lov;
-       struct list_head *pos, *tmp;
-       struct pool_desc *pool;
+       struct pool_desc *pool, *tmp;
 
-       list_for_each_safe(pos, tmp, &lov->lov_pool_list) {
-               pool = list_entry(pos, struct pool_desc, pool_list);
+       list_for_each_entry_safe(pool, tmp, &lov->lov_pool_list, pool_list) {
                /* free pool structs */
                CDEBUG(D_INFO, "delete pool %p\n", pool);
                /* In the function below, .hs_keycmp resolves to
index 105b707eed148ca6541fd89b618da22a3c83aac9..897cf2cd4a244e28e4532ad6025ffbef5e2bdb6d 100644 (file)
@@ -1335,7 +1335,7 @@ static int lov_object_fiemap(const struct lu_env *env, struct cl_object *obj,
        int rc = 0;
        int cur_stripe;
        int stripe_count;
-       struct fiemap_state fs = { 0 };
+       struct fiemap_state fs = { NULL };
 
        lsm = lov_lsm_addref(cl2lov(obj));
        if (!lsm)
index 3bdf48e4edb4bea224c2d09c5a708970269dec5b..cfa1d7f92b0f8c7ec9e58ddecce5b984220381a5 100644 (file)
@@ -49,15 +49,13 @@ static void lov_init_set(struct lov_request_set *set)
 
 static void lov_finish_set(struct lov_request_set *set)
 {
-       struct list_head *pos, *n;
+       struct lov_request *req;
 
        LASSERT(set);
-       list_for_each_safe(pos, n, &set->set_list) {
-               struct lov_request *req = list_entry(pos,
-                                                        struct lov_request,
-                                                        rq_link);
+       while ((req = list_first_entry_or_null(&set->set_list,
+                                              struct lov_request,
+                                              rq_link)) != NULL) {
                list_del_init(&req->rq_link);
-
                kfree(req->rq_oi.oi_osfs);
                kfree(req);
        }
index 77fa8fea0249d10b5e3cd300621a03f2f09deeea..79ff85feab6429215e735368e7793f3073ee2d87 100644 (file)
@@ -523,7 +523,7 @@ static void do_requeue(struct config_llog_data *cld)
  * in order to not flood the MGS.
  */
 #define MGC_TIMEOUT_MIN_SECONDS   5
-#define MGC_TIMEOUT_RAND_CENTISEC 0x1ff /* ~500 */
+#define MGC_TIMEOUT_RAND_CENTISEC 500
 
 static int mgc_requeue_thread(void *data)
 {
@@ -537,7 +537,7 @@ static int mgc_requeue_thread(void *data)
        while (!(rq_state & RQ_STOP)) {
                struct l_wait_info lwi;
                struct config_llog_data *cld, *cld_prev;
-               int rand = cfs_rand() & MGC_TIMEOUT_RAND_CENTISEC;
+               int rand = prandom_u32_max(MGC_TIMEOUT_RAND_CENTISEC);
                int to;
 
                /* Any new or requeued lostlocks will change the state */
index d415f83960382c2643af97211335c1125c67eb0c..3b683b774fefec00299dadd2cf6d6a4a9d8ff982 100644 (file)
@@ -79,13 +79,12 @@ EXPORT_SYMBOL(cl_lock_slice_add);
 
 void cl_lock_fini(const struct lu_env *env, struct cl_lock *lock)
 {
+       struct cl_lock_slice *slice;
        cl_lock_trace(D_DLMTRACE, env, "destroy lock", lock);
 
-       while (!list_empty(&lock->cll_layers)) {
-               struct cl_lock_slice *slice;
-
-               slice = list_entry(lock->cll_layers.next,
-                                  struct cl_lock_slice, cls_linkage);
+       while ((slice = list_first_entry_or_null(&lock->cll_layers,
+                                                struct cl_lock_slice,
+                                                cls_linkage)) != NULL) {
                list_del_init(lock->cll_layers.next);
                slice->cls_ops->clo_fini(env, slice);
        }
index fdd27ce46fdae63f957350b67aab5542531e551c..7b18d775b001297e1aa75643d9d00641688de4de 100644 (file)
@@ -510,13 +510,13 @@ locks: ...... ...... ...... ...... ...... [...... ...... ...... ...... ......]
  */
        lu_site_stats_print(&site->cs_lu, m);
        cache_stats_print(&site->cs_pages, m, 1);
-       seq_printf(m, " [");
+       seq_puts(m, " [");
        for (i = 0; i < ARRAY_SIZE(site->cs_pages_state); ++i)
                seq_printf(m, "%s: %u ", pstate[i],
                           atomic_read(&site->cs_pages_state[i]));
-       seq_printf(m, "]\n");
+       seq_puts(m, "]\n");
        cache_stats_print(&cl_env_stats, m, 0);
-       seq_printf(m, "\n");
+       seq_puts(m, "\n");
        return 0;
 }
 EXPORT_SYMBOL(cl_site_stats_print);
@@ -1017,7 +1017,7 @@ int cl_global_init(void)
 {
        int result;
 
-       cl_envs = kzalloc(sizeof(*cl_envs) * num_possible_cpus(), GFP_KERNEL);
+       cl_envs = kcalloc(num_possible_cpus(), sizeof(*cl_envs), GFP_KERNEL);
        if (!cl_envs) {
                result = -ENOMEM;
                goto out;
index 7f65439f9b95cfdf1dad176081b24d7d94bd14cb..d3b25667bc3a63bddaf2701a948db53790a2dc97 100644 (file)
@@ -202,7 +202,7 @@ struct cl_page *cl_page_find(const struct lu_env *env,
                 * vmpage lock is used to protect the child/parent
                 * relationship
                 */
-               KLASSERT(PageLocked(vmpage));
+               LASSERT(PageLocked(vmpage));
                /*
                 * cl_vmpage_page() can be called here without any locks as
                 *
@@ -340,7 +340,7 @@ struct cl_page *cl_vmpage_page(struct page *vmpage, struct cl_object *obj)
 {
        struct cl_page *page;
 
-       KLASSERT(PageLocked(vmpage));
+       LASSERT(PageLocked(vmpage));
 
        /*
         * NOTE: absence of races and liveness of data are guaranteed by page
index 2985bca4dc4cfa4e231d8188f9e86c4c96de5c5e..3e24b76f6301a27729dbd3f153a9e33a470a5193 100644 (file)
@@ -377,7 +377,8 @@ static int obd_init_checks(void)
        char buf[64];
        int len, ret = 0;
 
-       CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s\n", "%llu", "%lld", "%#llx");
+       CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s\n", "%llu", "%lld",
+              "%#llx");
 
        CDEBUG(D_INFO, "OBD_OBJECT_EOF = %#llx\n", (__u64)OBD_OBJECT_EOF);
 
index fc59f29a4290670081becfcb105fd93937de145e..57951237def245fd698d61730d2b030d67de1ca3 100644 (file)
@@ -501,6 +501,7 @@ int class_procfs_init(void)
                rc = debugfs_lustre_root ? PTR_ERR(debugfs_lustre_root)
                                         : -ENOMEM;
                debugfs_lustre_root = NULL;
+               sysfs_remove_group(lustre_kobj, &lustre_attr_group);
                kobject_put(lustre_kobj);
                goto out;
        }
@@ -509,6 +510,7 @@ int class_procfs_init(void)
                                   &obd_device_list_fops);
        if (IS_ERR_OR_NULL(file)) {
                rc = file ? PTR_ERR(file) : -ENOMEM;
+               sysfs_remove_group(lustre_kobj, &lustre_attr_group);
                kobject_put(lustre_kobj);
                goto out;
        }
@@ -522,6 +524,7 @@ int class_procfs_clean(void)
 
        debugfs_lustre_root = NULL;
 
+       sysfs_remove_group(lustre_kobj, &lustre_attr_group);
        kobject_put(lustre_kobj);
 
        return 0;
index 05d71f5688376199b3b1efab669395abe964db31..e1f4ef2bddd4bccfd58c8c298b4aed966325e25e 100644 (file)
@@ -1093,7 +1093,7 @@ int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
        LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
 
        percpusize = lprocfs_stats_counter_size(stats);
-       LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[cpuid], percpusize);
+       stats->ls_percpu[cpuid] = kzalloc(percpusize, GFP_ATOMIC);
        if (stats->ls_percpu[cpuid]) {
                rc = 0;
                if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
@@ -1137,7 +1137,8 @@ struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
                num_entry = num_possible_cpus();
 
        /* alloc percpu pointers for all possible cpu slots */
-       LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
+       stats = kvzalloc(offsetof(typeof(*stats), ls_percpu[num_entry]),
+                        GFP_KERNEL);
        if (!stats)
                return NULL;
 
@@ -1146,15 +1147,16 @@ struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
        spin_lock_init(&stats->ls_lock);
 
        /* alloc num of counter headers */
-       LIBCFS_ALLOC(stats->ls_cnt_header,
-                    stats->ls_num * sizeof(struct lprocfs_counter_header));
+       stats->ls_cnt_header = kvmalloc_array(stats->ls_num,
+                                             sizeof(struct lprocfs_counter_header),
+                                             GFP_KERNEL | __GFP_ZERO);
        if (!stats->ls_cnt_header)
                goto fail;
 
        if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
                /* contains only one set counters */
                percpusize = lprocfs_stats_counter_size(stats);
-               LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
+               stats->ls_percpu[0] = kzalloc(percpusize, GFP_ATOMIC);
                if (!stats->ls_percpu[0])
                        goto fail;
                stats->ls_biggest_alloc_num = 1;
@@ -1191,12 +1193,9 @@ void lprocfs_free_stats(struct lprocfs_stats **statsh)
 
        percpusize = lprocfs_stats_counter_size(stats);
        for (i = 0; i < num_entry; i++)
-               if (stats->ls_percpu[i])
-                       LIBCFS_FREE(stats->ls_percpu[i], percpusize);
-       if (stats->ls_cnt_header)
-               LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
-                                       sizeof(struct lprocfs_counter_header));
-       LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
+               kfree(stats->ls_percpu[i]);
+       kvfree(stats->ls_cnt_header);
+       kvfree(stats);
 }
 EXPORT_SYMBOL(lprocfs_free_stats);
 
index b938a3f9d50a74c734025df2607b3d756e97e369..2719abbff85f9dfcb6607514d5441f894fb2db97 100644 (file)
@@ -1932,8 +1932,10 @@ int lu_global_init(void)
 
        LU_CONTEXT_KEY_INIT(&lu_global_key);
        result = lu_context_key_register(&lu_global_key);
-       if (result != 0)
+       if (result != 0) {
+               lu_ref_global_fini();
                return result;
+       }
 
        /*
         * At this level, we don't know what tags are needed, so allocate them
@@ -1943,17 +1945,31 @@ int lu_global_init(void)
        down_write(&lu_sites_guard);
        result = lu_env_init(&lu_shrink_env, LCT_SHRINKER);
        up_write(&lu_sites_guard);
-       if (result != 0)
+       if (result != 0) {
+               lu_context_key_degister(&lu_global_key);
+               lu_ref_global_fini();
                return result;
+       }
 
        /*
         * seeks estimation: 3 seeks to read a record from oi, one to read
         * inode, one for ea. Unfortunately setting this high value results in
         * lu_object/inode cache consuming all the memory.
         */
-       register_shrinker(&lu_site_shrinker);
+       result = register_shrinker(&lu_site_shrinker);
+       if (result != 0) {
+               /* Order explained in lu_global_fini(). */
+               lu_context_key_degister(&lu_global_key);
 
-       return result;
+               down_write(&lu_sites_guard);
+               lu_env_fini(&lu_shrink_env);
+               up_write(&lu_sites_guard);
+
+               lu_ref_global_fini();
+               return result;
+       }
+
+       return 0;
 }
 
 /**
index 71329adc0318c4879fd2b1dda8035be98b100541..2d6da2431a09e175a10204bbe7a9224e7e0c136d 100644 (file)
@@ -181,8 +181,6 @@ EXPORT_SYMBOL(class_handle_free_cb);
 int class_handle_init(void)
 {
        struct handle_bucket *bucket;
-       struct timespec64 ts;
-       int seed[2];
 
        LASSERT(!handle_hash);
 
@@ -198,12 +196,7 @@ int class_handle_init(void)
                spin_lock_init(&bucket->lock);
        }
 
-       /** bug 21430: add randomness to the initial base */
-       cfs_get_random_bytes(seed, sizeof(seed));
-       ktime_get_ts64(&ts);
-       cfs_srand(ts.tv_sec ^ seed[0], ts.tv_nsec ^ seed[1]);
-
-       cfs_get_random_bytes(&handle_base, sizeof(handle_base));
+       get_random_bytes(&handle_base, sizeof(handle_base));
        LASSERT(handle_base != 0ULL);
 
        return 0;
index c0e192ae22a9273441b5fa5385b4bc4510039d77..997c0f9aafb5505c5ae6699448844b4c70292c2f 100644 (file)
@@ -236,7 +236,7 @@ static int class_attach(struct lustre_cfg *lcfg)
        uuid = lustre_cfg_string(lcfg, 2);
 
        CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
-              MKSTR(typename), MKSTR(name), MKSTR(uuid));
+              typename, name, uuid);
 
        obd = class_newdev(typename, name);
        if (IS_ERR(obd)) {
index 2a79a223b98a740275084d6a319428c405477417..acc1ea773c9c67a571b3126f77b357b7d92e062a 100644 (file)
@@ -49,9 +49,9 @@
 #include <lustre_disk.h>
 #include <uapi/linux/lustre/lustre_param.h>
 
-static int (*client_fill_super)(struct super_block *sb,
-                               struct vfsmount *mnt);
-
+static DEFINE_SPINLOCK(client_lock);
+static struct module *client_mod;
+static int (*client_fill_super)(struct super_block *sb);
 static void (*kill_super_cb)(struct super_block *sb);
 
 /**************** config llog ********************/
@@ -1107,20 +1107,14 @@ invalid:
        return -EINVAL;
 }
 
-struct lustre_mount_data2 {
-       void *lmd2_data;
-       struct vfsmount *lmd2_mnt;
-};
-
 /** This is the entry point for the mount call into Lustre.
  * This is called when a server or client is mounted,
  * and this is where we start setting things up.
  * @param data Mount options (e.g. -o flock,abort_recov)
  */
-static int lustre_fill_super(struct super_block *sb, void *data, int silent)
+static int lustre_fill_super(struct super_block *sb, void *lmd2_data, int silent)
 {
        struct lustre_mount_data *lmd;
-       struct lustre_mount_data2 *lmd2 = data;
        struct lustre_sb_info *lsi;
        int rc;
 
@@ -1143,17 +1137,22 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent)
        obd_zombie_barrier();
 
        /* Figure out the lmd from the mount options */
-       if (lmd_parse((lmd2->lmd2_data), lmd)) {
+       if (lmd_parse(lmd2_data, lmd)) {
                lustre_put_lsi(sb);
                rc = -EINVAL;
                goto out;
        }
 
        if (lmd_is_client(lmd)) {
+               bool have_client = false;
                CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
                if (!client_fill_super)
                        request_module("lustre");
-               if (!client_fill_super) {
+               spin_lock(&client_lock);
+               if (client_fill_super && try_module_get(client_mod))
+                       have_client = true;
+               spin_unlock(&client_lock);
+               if (!have_client) {
                        LCONSOLE_ERROR_MSG(0x165, "Nothing registered for client mount! Is the 'lustre' module loaded?\n");
                        lustre_put_lsi(sb);
                        rc = -ENODEV;
@@ -1165,8 +1164,10 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent)
                        }
                        /* Connect and start */
                        /* (should always be ll_fill_super) */
-                       rc = (*client_fill_super)(sb, lmd2->lmd2_mnt);
-                       /* c_f_s will call lustre_common_put_super on failure */
+                       rc = (*client_fill_super)(sb);
+                       /* c_f_s will call lustre_common_put_super on failure, otherwise
+                        * c_f_s will have taken another reference to the module */
+                       module_put(client_mod);
                }
        } else {
                CERROR("This is client-side-only module, cannot handle server mount.\n");
@@ -1192,29 +1193,23 @@ out:
 /* We can't call ll_fill_super by name because it lives in a module that
  * must be loaded after this one.
  */
-void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb,
-                                                 struct vfsmount *mnt))
+void lustre_register_super_ops(struct module *mod,
+                              int (*cfs)(struct super_block *sb),
+                              void (*ksc)(struct super_block *sb))
 {
+       spin_lock(&client_lock);
+       client_mod = mod;
        client_fill_super = cfs;
+       kill_super_cb = ksc;
+       spin_unlock(&client_lock);
 }
-EXPORT_SYMBOL(lustre_register_client_fill_super);
-
-void lustre_register_kill_super_cb(void (*cfs)(struct super_block *sb))
-{
-       kill_super_cb = cfs;
-}
-EXPORT_SYMBOL(lustre_register_kill_super_cb);
+EXPORT_SYMBOL(lustre_register_super_ops);
 
 /***************** FS registration ******************/
 static struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
                                   const char *devname, void *data)
 {
-       struct lustre_mount_data2 lmd2 = {
-               .lmd2_data = data,
-               .lmd2_mnt = NULL
-       };
-
-       return mount_nodev(fs_type, flags, &lmd2, lustre_fill_super);
+       return mount_nodev(fs_type, flags, data, lustre_fill_super);
 }
 
 static void lustre_kill_super(struct super_block *sb)
@@ -1230,11 +1225,11 @@ static void lustre_kill_super(struct super_block *sb)
 /** Register the "lustre" fs type
  */
 static struct file_system_type lustre_fs_type = {
-       .owner  = THIS_MODULE,
-       .name    = "lustre",
-       .mount  = lustre_mount,
-       .kill_sb      = lustre_kill_super,
-       .fs_flags       = FS_REQUIRES_DEV | FS_RENAME_DOES_D_MOVE,
+       .owner          = THIS_MODULE,
+       .name           = "lustre",
+       .mount          = lustre_mount,
+       .kill_sb        = lustre_kill_super,
+       .fs_flags       = FS_RENAME_DOES_D_MOVE,
 };
 MODULE_ALIAS_FS("lustre");
 
index feda61bcdb9b8af7c518de128ce414dbe1a868b0..32db150fd42ec37aa80b3f736c07a4f43cec31bc 100644 (file)
@@ -168,9 +168,9 @@ struct osc_device {
 
        /* Write stats is actually protected by client_obd's lock. */
        struct osc_stats {
-               uint64_t     os_lockless_writes;          /* by bytes */
-               uint64_t     os_lockless_reads;    /* by bytes */
-               uint64_t     os_lockless_truncates;       /* by times */
+               u64     os_lockless_writes;       /* by bytes */
+               u64     os_lockless_reads;        /* by bytes */
+               u64     os_lockless_truncates;    /* by times */
        } od_stats;
 
        /* configuration item(s) */
index 53eda4c99142b086b5c9c5cf21c504e1d17e6738..45b1ebf33363427aa31904c3707c7780f26b8519 100644 (file)
@@ -2844,7 +2844,9 @@ static int __init osc_init(void)
        if (rc)
                goto out_kmem;
 
-       register_shrinker(&osc_cache_shrinker);
+       rc = register_shrinker(&osc_cache_shrinker);
+       if (rc)
+               goto out_type;
 
        /* This is obviously too much memory, only prevent overflow here */
        if (osc_reqpool_mem_max >= 1 << 12 || osc_reqpool_mem_max == 0) {
index 2a9f2f2ebaa83308d7628e6e37672f756846a13b..bac4b2304bad749dfd44c649c0c67bd173350e68 100644 (file)
@@ -3067,7 +3067,7 @@ void ptlrpc_init_xid(void)
 
        spin_lock_init(&ptlrpc_last_xid_lock);
        if (now < YEAR_2004) {
-               cfs_get_random_bytes(&ptlrpc_last_xid, sizeof(ptlrpc_last_xid));
+               get_random_bytes(&ptlrpc_last_xid, sizeof(ptlrpc_last_xid));
                ptlrpc_last_xid >>= 2;
                ptlrpc_last_xid |= (1ULL << 61);
        } else {
index 77a3721beaee8d57242873c60fa9a932be0c8e98..134ee727e8b72dfb4e9b67b3e75dab9e21854660 100644 (file)
@@ -396,6 +396,8 @@ static struct shrinker pools_shrinker = {
 
 int sptlrpc_enc_pool_init(void)
 {
+       int rc;
+
        /*
         * maximum capacity is 1/8 of total physical memory.
         * is the 1/8 a good number?
@@ -432,9 +434,11 @@ int sptlrpc_enc_pool_init(void)
        if (!page_pools.epp_pools)
                return -ENOMEM;
 
-       register_shrinker(&pools_shrinker);
+       rc = register_shrinker(&pools_shrinker);
+       if (rc)
+               enc_pools_free();
 
-       return 0;
+       return rc;
 }
 
 void sptlrpc_enc_pool_fini(void)
index bb1d6dafca83473eea250ff24be74b1505c9b533..26994b429cf2a6a70dc568015953856c057cb50b 100644 (file)
@@ -207,13 +207,9 @@ static irqreturn_t csi_idmac_eof_interrupt(int irq, void *dev_id)
                goto unlock;
        }
 
-       if (priv->fim) {
-               struct timespec cur_ts;
-
-               ktime_get_ts(&cur_ts);
+       if (priv->fim)
                /* call frame interval monitor */
-               imx_media_fim_eof_monitor(priv->fim, &cur_ts);
-       }
+               imx_media_fim_eof_monitor(priv->fim, ktime_get());
 
        csi_vb2_buf_done(priv);
 
index 47275ef803f3515742e3adc6fd614390c0487e4e..6df189135db88c84b0a9acdd3e613452423440f2 100644 (file)
@@ -66,7 +66,7 @@ struct imx_media_fim {
        int               icap_flags;
 
        int               counter;
-       struct timespec   last_ts;
+       ktime_t           last_ts;
        unsigned long     sum;       /* usec */
        unsigned long     nominal;   /* usec */
 
@@ -147,22 +147,26 @@ static void send_fim_event(struct imx_media_fim *fim, unsigned long error)
  * (presumably random) interrupt latency.
  */
 static void frame_interval_monitor(struct imx_media_fim *fim,
-                                  struct timespec *ts)
+                                  ktime_t timestamp)
 {
-       unsigned long interval, error, error_avg;
+       long long interval, error;
+       unsigned long error_avg;
        bool send_event = false;
-       struct timespec diff;
 
        if (!fim->enabled || ++fim->counter <= 0)
                goto out_update_ts;
 
-       diff = timespec_sub(*ts, fim->last_ts);
-       interval = diff.tv_sec * 1000 * 1000 + diff.tv_nsec / 1000;
-       error = abs(interval - fim->nominal);
+       /* max error is less than l00µs, so use 32-bit division or fail */
+       interval = ktime_to_ns(ktime_sub(timestamp, fim->last_ts));
+       error = abs(interval - NSEC_PER_USEC * (u64)fim->nominal);
+       if (error > U32_MAX)
+               error = U32_MAX;
+       else
+               error = abs((u32)error / NSEC_PER_USEC);
 
        if (fim->tolerance_max && error >= fim->tolerance_max) {
                dev_dbg(fim->sd->dev,
-                       "FIM: %lu ignored, out of tolerance bounds\n",
+                       "FIM: %llu ignored, out of tolerance bounds\n",
                        error);
                fim->counter--;
                goto out_update_ts;
@@ -184,7 +188,7 @@ static void frame_interval_monitor(struct imx_media_fim *fim,
        }
 
 out_update_ts:
-       fim->last_ts = *ts;
+       fim->last_ts = timestamp;
        if (send_event)
                send_fim_event(fim, error_avg);
 }
@@ -195,14 +199,14 @@ out_update_ts:
  * to interrupt latency.
  */
 static void fim_input_capture_handler(int channel, void *dev_id,
-                                     struct timespec *ts)
+                                     ktime_t timestamp)
 {
        struct imx_media_fim *fim = dev_id;
        unsigned long flags;
 
        spin_lock_irqsave(&fim->lock, flags);
 
-       frame_interval_monitor(fim, ts);
+       frame_interval_monitor(fim, timestamp);
 
        if (!completion_done(&fim->icap_first_event))
                complete(&fim->icap_first_event);
@@ -405,14 +409,14 @@ err_free:
  * the frame_interval_monitor() is called by the input capture event
  * callback handler in that case.
  */
-void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts)
+void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&fim->lock, flags);
 
        if (!icap_enabled(fim))
-               frame_interval_monitor(fim, ts);
+               frame_interval_monitor(fim, timestamp);
 
        spin_unlock_irqrestore(&fim->lock, flags);
 }
index d409170632bd3f2537f57c3f234b7ed6e609ef79..ac3ab115394f4589561277725b62f57bd76614d6 100644 (file)
@@ -280,7 +280,7 @@ int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd,
 
 /* imx-media-fim.c */
 struct imx_media_fim;
-void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts);
+void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp);
 int imx_media_fim_set_stream(struct imx_media_fim *fim,
                             const struct v4l2_fract *frame_interval,
                             bool on);
diff --git a/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt
new file mode 100644 (file)
index 0000000..d8fa841
--- /dev/null
@@ -0,0 +1,313 @@
+What:          /sys/bus/most/devices/.../description
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Provides information about the interface type and the physical
+               location of the device. Hardware attached via USB, for instance,
+               might return <usb_device 1-1.1:1.0>
+Users:
+
+What:          /sys/bus/most/devices/.../interface
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the type of peripheral interface the device uses.
+Users:
+
+What:          /sys/bus/most/devices/.../dci
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               If the network interface controller is attached via USB, a dci
+               directory is created that allows applications to read and
+               write the controller's DCI registers.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/arb_address
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to set an arbitrary DCI register address an
+               application wants to read from or write to.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/arb_value
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to read and write the DCI register whose address
+               is stored in arb_address.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/mep_eui48_hi
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to check and configure the MAC address.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/mep_eui48_lo
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to check and configure the MAC address.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/mep_eui48_mi
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to check and configure the MAC address.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/mep_filter
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to check and configure the MEP filter address.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/mep_hash0
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to check and configure the MEP hash table.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/mep_hash1
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to check and configure the MEP hash table.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/mep_hash2
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to check and configure the MEP hash table.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/mep_hash3
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to check and configure the MEP hash table.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/ni_state
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the current network interface state.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/node_address
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the current node address.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/node_position
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the current node position.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/packet_bandwidth
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the configured packet bandwidth.
+Users:
+
+What:          /sys/bus/most/devices/.../dci/sync_ep
+Date:          June 2016
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Triggers the controller's synchronization process for a certain
+               endpoint.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               For every channel of the device a directory is created, whose
+               name is dictated by the HDM. This enables an application to
+               collect information about the channel's capabilities and
+               configure it.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/available_datatypes
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the data types the current channel can transport.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/available_directions
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the directions the current channel is capable of.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/number_of_packet_buffers
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the number of packet buffers the current channel can
+               handle.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/number_of_stream_buffers
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the number of streaming buffers the current channel can
+               handle.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/size_of_packet_buffer
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the size of a packet buffer the current channel can
+               handle.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/size_of_stream_buffer
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the size of a streaming buffer the current channel can
+               handle.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/set_number_of_buffers
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the number of buffers of the current channel.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/set_buffer_size
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the size of a buffer of the current channel.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/set_direction
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the direction of the current channel.
+               The following strings will be accepted:
+                       'dir_tx',
+                       'dir_rx'
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/set_datatype
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the data type of the current channel.
+               The following strings will be accepted:
+                       'control',
+                       'async',
+                       'sync',
+                       'isoc_avp'
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/set_subbuffer_size
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the subbuffer size of the current channel.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/set_packets_per_xact
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the number of packets per transaction of
+               the current channel. This is only needed network interface
+               controller is attached via USB.
+Users:
+
+What:          /sys/bus/most/devices/.../<channel>/channel_starving
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates whether current channel ran out of buffers.
+Users:
+
+What:          /sys/bus/most/drivers/mostcore/add_link
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to link a channel to a component of the
+               mostcore. A link created by writing to this file is
+               referred to as pipe.
+Users:
+
+What:          /sys/bus/most/drivers/mostcore/remove_link
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to unlink a channel from a component.
+Users:
+
+What:          /sys/bus/most/drivers/mostcore/components
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to retrieve a list of registered components.
+Users:
+
+What:          /sys/bus/most/drivers/mostcore/links
+Date:          March 2017
+KernelVersion: 4.15
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to retrieve a list of established links.
+Users:
index a4dc0c348fbc331ed87580a092f561860e4723ee..bb9b4e870199db2f979a24dd11cfa1262c247b49 100644 (file)
@@ -23,20 +23,29 @@ audio/video streaming. Therefore, the driver perfectly fits to the mission
 of Automotive Grade Linux to create open source software solutions for
 automotive applications.
 
-The driver consists basically of three layers. The hardware layer, the
-core layer and the application layer. The core layer consists of the core
-module only. This module handles the communication flow through all three
-layers, the configuration of the driver, the configuration interface
-representation in sysfs, and the buffer management.
-For each of the other two layers a selection of modules is provided. These
-modules can arbitrarily be combined to meet the needs of the desired
-system architecture. A module of the hardware layer is referred to as an
-HDM (hardware dependent module). Each module of this layer handles exactly
-one of the peripheral interfaces of a network interface controller (e.g.
-USB, MediaLB, I2C). A module of the application layer is referred to as an
-AIM (application interfacing module). The modules of this layer give access
-to MOST via one the following ways: character devices, ALSA, Networking or
-V4L2.
+The MOST driver uses module stacking to divide the associated modules into
+three layers. From bottom up these layers are: the adapter layer, the core
+layer and the application layer. The core layer implements the MOST
+subsystem and consists basically of the module core.c and its API. It
+registers the MOST bus with the kernel's device model, handles the data
+routing through all three layers, the configuration of the driver, the
+representation of the configuration interface in sysfs and the buffer
+management.
+
+For each of the other two layers a set of modules is provided. Those can be
+arbitrarily combined with the core to meet the connectivity of the desired
+system architecture.
+
+A module of the adapter layer is basically a device driver for a different
+subsystem. It is registered with the core to connect the MOST subsystem to
+the attached network interface controller hardware. Hence, a given module
+of this layer is designed to handle exactly one of the peripheral
+interfaces (e.g. USB, MediaLB, I2C) the hardware provides.
+
+A module of the application layer is referred to as a core comoponent,
+which kind of extends the core by providing connectivity to the user space.
+Applications, then, can access a MOST network via character devices, an
+ALSA soundcard, a Network adapter or a V4L2 capture device.
 
 To physically access MOST, an Intelligent Network Interface Controller
 (INIC) is needed. For more information on available controllers visit:
@@ -44,15 +53,14 @@ www.microchip.com
 
 
 
-               Section 1.1 Hardware Layer
+               Section 1.1 Adapter Layer
 
-The hardware layer contains so called hardware dependent modules (HDM). For each
-peripheral interface the hardware supports the driver has a suitable module
-that handles the interface.
-
-The HDMs encapsulate the peripheral interface specific knowledge of the driver
-and provides an easy way of extending the number of supported interfaces.
-Currently the following HDMs are available:
+The adapter layer contains a pool of device drivers. For each peripheral
+interface the hardware supports there is one suitable module that handles
+the interface. Adapter drivers encapsulate the peripheral interface
+specific knowledge of the MOST driver stack and provide an easy way of
+extending the number of supported interfaces. Currently the following
+interfaces are available:
 
        1) MediaLB (DIM2)
           Host wants to communicate with hardware via MediaLB.
@@ -63,26 +71,34 @@ Currently the following HDMs are available:
        3) USB
           Host wants to communicate with the hardware via USB.
 
+Once an adapter driver recognizes a MOST device being attached, it
+registers it with the core, which, in turn, assigns the necessary members
+of the embedded struct device (e.g. the bus this device belongs to and
+attribute groups) and registers it with the kernel's device model.
 
-               Section 1.2 Core Layer
-
-The core layer contains the mostcore module only, which processes the driver
-configuration via sysfs, buffer management and data forwarding.
 
+               Section 1.2 Core Layer
 
+This layer implements the MOST subsystem. It contains the core module and
+the header file most.h that exposes the API of the core. When inserted in
+the kernel, it registers the MOST bus_type with the kernel's device model
+and registers itself as a device driver for this bus. Besides these meta
+tasks the core populates the configuration directory for a registered MOST
+device (represented by struct most_interface) in sysfs and processes the
+configuration of the device's interface. The core layer also handles the
+buffer management and the data/message routing.
 
-               Section 1.2 Application Layer
 
-The application layer contains so called application interfacing modules (AIM).
-Depending on how the driver should interface to the application, one or more
-suitable modules can be selected.
+               Section 1.3 Application Layer
 
-The AIMs encapsulate the application interface specific knowledge of the driver
-and provides access to user space or other kernel subsystems.
-Currently the following AIMs are available
+This layer contains a pool of device drivers that are components of the
+core designed to make up the userspace experience of the MOST driver stack.
+Depending on how an application is meant to interface the driver, one or
+more modules of this pool can be registered with the core. Currently the
+following components are available
 
        1) Character Device
-          Applications can access the driver by means of character devices.
+          Userspace can access the driver by means of character devices.
 
        2) Networking
           Standard networking applications (e.g. iperf) can by used to access
@@ -97,84 +113,86 @@ Currently the following AIMs are available
           used to access the driver via the ALSA subsystem.
 
 
+               Section 2 Usage of the MOST Driver
 
-               Section 2 Configuration
+               Section 2.1 Configuration
 
-See ABI/sysfs-class-most.txt
+See ABI/sysfs-bus-most.txt
 
 
+               Section 2.2 Routing Channels
 
-               Section 3 USB Padding
+To connect a configured channel to a certain core component and make it
+accessible for user space applications, the driver attribute 'add_link' is
+used. The configuration string passed to it has the following format:
 
-When transceiving synchronous or isochronous data, the number of packets per USB
-transaction and the sub-buffer size need to be configured. These values
-are needed for the driver to process buffer padding, as expected by hardware,
-which is for performance optimization purposes of the USB transmission.
+       "device_name:channel_name:component_name:link_name[.param]"
 
-When transmitting synchronous data the allocated channel width needs to be
-written to 'set_subbuffer_size'. Additionally, the number of MOST frames that
-should travel to the host within one USB transaction need to be written to
-'packets_per_xact'.
+It is the concatenation of up to four substrings separated by a colon. The
+substrings contain the names of the MOST interface, the channel, the
+component driver and a custom name with which the link is going to be
+referenced with. Since some components need additional information, the
+link name can be extended with a component-specific parameter (separated by
+a dot). In case the character device component is loaded, the handle would
+also appear as a device node in the /dev directory.
 
-Internally the synchronous threshold is calculated as follows:
+Cdev component example:
+        $ echo "mdev0:ep_81:cdev:my_rx_channel" >$(DRV_DIR)/add_link
 
-       frame_size = set_subbuffer_size * packets_per_xact
 
-In case 'packets_per_xact' is set to 0xFF the maximum number of packets,
-allocated within one MOST frame, is calculated that fit into _one_ 512 byte
-USB full packet.
+Sound component example:
 
-       frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync
+The sound component needs an additional parameter to determine the audio
+resolution that is going to be used. The following formats are available:
 
-This frame_size is the number of synchronous data within an USB transaction,
-which renders MTU_USB - frame_size bytes for padding.
+       - "1x8" (Mono)
+       - "2x16" (16-bit stereo)
+       - "2x24" (24-bit stereo)
+       - "2x32" (32-bit stereo)
+       - "6x16" (16-bit surround 5.1)
 
-When transmitting isochronous AVP data the desired packet size needs to be
-written to 'set_subbuffer_size' and hardware will always expect two isochronous
-packets within one USB transaction. This renders
+        $ echo "mdev0:ep_81:sound:most51_playback.6x16" >$(DRV_DIR)/add_link
 
-       MTU_USB - (2 * set_subbuffer_size)
 
-bytes for padding.
-
-Note that at least 2 times set_subbuffer_size bytes for isochronous data or
-set_subbuffer_size times packts_per_xact bytes for synchronous data need to be
-put in the transmission buffer and passed to the driver.
 
-Since HDMs are allowed to change a chosen configuration to best fit its
-constraints, it is recommended to always double check the configuration and read
-back the previously written files.
+               Section 2.3 USB Padding
 
+When transceiving synchronous or isochronous data, the number of packets
+per USB transaction and the sub-buffer size need to be configured. These
+values are needed for the driver to process buffer padding, as expected by
+hardware, which is for performance optimization purposes of the USB
+transmission.
 
+When transmitting synchronous data the allocated channel width needs to be
+written to 'set_subbuffer_size'. Additionally, the number of MOST frames
+that should travel to the host within one USB transaction need to be
+written to 'packets_per_xact'.
 
-               Section 4 Routing Channels
+The driver, then, calculates the synchronous threshold as follows:
 
-To connect a channel that has been configured as outlined above to an AIM and
-make it accessible to user space applications, the attribute file 'add_link' is
-used. To actually bind a channel to the AIM a string needs to be written to the
-file that complies with the following syntax:
+       frame_size = set_subbuffer_size * packets_per_xact
 
-       "most_device:channel_name:link_name[.param]"
+In case 'packets_per_xact' is set to 0xFF the maximum number of packets,
+allocated within one MOST frame, is calculated that fit into _one_ 512 byte
+USB full packet.
 
-The example above links the channel "channel_name" of the device "most_device"
-to the AIM. In case the AIM interfaces the VFS this would also create a device
-node "link_name" in the /dev directory. The parameter "param" is an AIM dependent
-string, which can be omitted in case the used AIM does not make any use of it.
+       frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync
 
-Cdev AIM example:
-        $ echo "mdev0:ep_81:my_rx_channel" >add_link
-        $ echo "mdev0:ep_81" >add_link
+This frame_size is the number of synchronous data within an USB
+transaction, which renders MTU_USB - frame_size bytes for padding.
 
+When transmitting isochronous AVP data the desired packet size needs to be
+written to 'set_subbuffer_size' and hardware will always expect two
+isochronous packets within one USB transaction. This renders
 
-Sound/ALSA AIM example:
+       MTU_USB - (2 * set_subbuffer_size)
 
-The sound/ALSA AIM needs an additional parameter to determine the audio resolution
-that is going to be used. The following strings can be used:
+bytes for padding.
 
-       - "1x8" (Mono)
-       - "2x16" (16-bit stereo)
-       - "2x24" (24-bit stereo)
-       - "2x32" (32-bit stereo)
+Note that at least (2 * set_subbuffer_size) bytes for isochronous data or
+(set_subbuffer_size * packts_per_xact) bytes for synchronous data need to
+be put in the transmission buffer and passed to the driver.
 
-        $ echo "mdev0:ep_81:audio_rx.2x16" >add_link
-        $ echo "mdev0:ep_81" >add_link
+Since adapter drivers are allowed to change a chosen configuration to best
+fit its constraints, it is recommended to always double check the
+configuration and read back the previously written files.
index 0b9b9b539f70562d2a908e6741df729d0ea2d9fc..20047abbe56052b0797bea4ea128599d4dd040c7 100644 (file)
@@ -1,10 +1,15 @@
 menuconfig MOST
-        tristate "MOST driver"
+        tristate "MOST support"
        depends on HAS_DMA
-        select MOSTCORE
         default n
         ---help---
-          This option allows you to enable support for MOST Network transceivers.
+         Say Y here if you want to enable MOST support.
+         This driver needs at least one additional component to enable the
+         desired access from userspace (e.g. character devices) and one that
+         matches the network controller's hardware interface (e.g. USB).
+
+         To compile this driver as a module, choose M here: the
+         module will be called most_core.
 
           If in doubt, say N here.
 
@@ -12,20 +17,18 @@ menuconfig MOST
 
 if MOST
 
-source "drivers/staging/most/mostcore/Kconfig"
-
-source "drivers/staging/most/aim-cdev/Kconfig"
+source "drivers/staging/most/cdev/Kconfig"
 
-source "drivers/staging/most/aim-network/Kconfig"
+source "drivers/staging/most/net/Kconfig"
 
-source "drivers/staging/most/aim-sound/Kconfig"
+source "drivers/staging/most/sound/Kconfig"
 
-source "drivers/staging/most/aim-v4l2/Kconfig"
+source "drivers/staging/most/video/Kconfig"
 
-source "drivers/staging/most/hdm-dim2/Kconfig"
+source "drivers/staging/most/dim2/Kconfig"
 
-source "drivers/staging/most/hdm-i2c/Kconfig"
+source "drivers/staging/most/i2c/Kconfig"
 
-source "drivers/staging/most/hdm-usb/Kconfig"
+source "drivers/staging/most/usb/Kconfig"
 
 endif
index f5bbb9deaab56f1c7119d531dacb7a7443357ff3..f8bcf488ecf2e44b57a3db4164e40fce5df57662 100644 (file)
@@ -1,9 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_MOSTCORE) += mostcore/
-obj-$(CONFIG_AIM_CDEV) += aim-cdev/
-obj-$(CONFIG_AIM_NETWORK)      += aim-network/
-obj-$(CONFIG_AIM_SOUND)        += aim-sound/
-obj-$(CONFIG_AIM_V4L2) += aim-v4l2/
-obj-$(CONFIG_HDM_DIM2) += hdm-dim2/
-obj-$(CONFIG_HDM_I2C)  += hdm-i2c/
-obj-$(CONFIG_HDM_USB)  += hdm-usb/
+obj-$(CONFIG_MOST) += most_core.o
+most_core-y := core.o
+ccflags-y += -Idrivers/staging/
+
+obj-$(CONFIG_MOST_CDEV)        += cdev/
+obj-$(CONFIG_MOST_NET) += net/
+obj-$(CONFIG_MOST_SOUND)       += sound/
+obj-$(CONFIG_MOST_VIDEO)       += video/
+obj-$(CONFIG_MOST_DIM2)        += dim2/
+obj-$(CONFIG_MOST_I2C) += i2c/
+obj-$(CONFIG_MOST_USB) += usb/
diff --git a/drivers/staging/most/aim-cdev/Kconfig b/drivers/staging/most/aim-cdev/Kconfig
deleted file mode 100644 (file)
index 3c59f1b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# MOST Cdev configuration
-#
-
-config AIM_CDEV
-       tristate "Cdev AIM"
-
-       ---help---
-         Say Y here if you want to commumicate via character devices.
-
-         To compile this driver as a module, choose M here: the
-         module will be called aim_cdev.
\ No newline at end of file
diff --git a/drivers/staging/most/aim-cdev/Makefile b/drivers/staging/most/aim-cdev/Makefile
deleted file mode 100644 (file)
index 0bcc6c6..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_AIM_CDEV) += aim_cdev.o
-
-aim_cdev-objs := cdev.o
-ccflags-y += -Idrivers/staging/most/mostcore/
\ No newline at end of file
diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c
deleted file mode 100644 (file)
index 69f5309..0000000
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * cdev.c - Application interfacing module for character devices
- *
- * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
-#include <linux/poll.h>
-#include <linux/kfifo.h>
-#include <linux/uaccess.h>
-#include <linux/idr.h>
-#include "mostcore.h"
-
-static dev_t aim_devno;
-static struct class *aim_class;
-static struct ida minor_id;
-static unsigned int major;
-static struct most_aim cdev_aim;
-
-struct aim_channel {
-       wait_queue_head_t wq;
-       spinlock_t unlink;      /* synchronization lock to unlink channels */
-       struct cdev cdev;
-       struct device *dev;
-       struct mutex io_mutex;
-       struct most_interface *iface;
-       struct most_channel_config *cfg;
-       unsigned int channel_id;
-       dev_t devno;
-       size_t mbo_offs;
-       DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *));
-       int access_ref;
-       struct list_head list;
-};
-
-#define to_channel(d) container_of(d, struct aim_channel, cdev)
-static struct list_head channel_list;
-static spinlock_t ch_list_lock;
-
-static inline bool ch_has_mbo(struct aim_channel *c)
-{
-       return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0;
-}
-
-static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo)
-{
-       if (!kfifo_peek(&c->fifo, mbo)) {
-               *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim);
-               if (*mbo)
-                       kfifo_in(&c->fifo, mbo, 1);
-       }
-       return *mbo;
-}
-
-static struct aim_channel *get_channel(struct most_interface *iface, int id)
-{
-       struct aim_channel *c, *tmp;
-       unsigned long flags;
-       int found_channel = 0;
-
-       spin_lock_irqsave(&ch_list_lock, flags);
-       list_for_each_entry_safe(c, tmp, &channel_list, list) {
-               if ((c->iface == iface) && (c->channel_id == id)) {
-                       found_channel = 1;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&ch_list_lock, flags);
-       if (!found_channel)
-               return NULL;
-       return c;
-}
-
-static void stop_channel(struct aim_channel *c)
-{
-       struct mbo *mbo;
-
-       while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1))
-               most_put_mbo(mbo);
-       most_stop_channel(c->iface, c->channel_id, &cdev_aim);
-}
-
-static void destroy_cdev(struct aim_channel *c)
-{
-       unsigned long flags;
-
-       device_destroy(aim_class, c->devno);
-       cdev_del(&c->cdev);
-       spin_lock_irqsave(&ch_list_lock, flags);
-       list_del(&c->list);
-       spin_unlock_irqrestore(&ch_list_lock, flags);
-}
-
-static void destroy_channel(struct aim_channel *c)
-{
-       ida_simple_remove(&minor_id, MINOR(c->devno));
-       kfifo_free(&c->fifo);
-       kfree(c);
-}
-
-/**
- * aim_open - implements the syscall to open the device
- * @inode: inode pointer
- * @filp: file pointer
- *
- * This stores the channel pointer in the private data field of
- * the file structure and activates the channel within the core.
- */
-static int aim_open(struct inode *inode, struct file *filp)
-{
-       struct aim_channel *c;
-       int ret;
-
-       c = to_channel(inode->i_cdev);
-       filp->private_data = c;
-
-       if (((c->cfg->direction == MOST_CH_RX) &&
-            ((filp->f_flags & O_ACCMODE) != O_RDONLY)) ||
-            ((c->cfg->direction == MOST_CH_TX) &&
-               ((filp->f_flags & O_ACCMODE) != O_WRONLY))) {
-               pr_info("WARN: Access flags mismatch\n");
-               return -EACCES;
-       }
-
-       mutex_lock(&c->io_mutex);
-       if (!c->dev) {
-               pr_info("WARN: Device is destroyed\n");
-               mutex_unlock(&c->io_mutex);
-               return -ENODEV;
-       }
-
-       if (c->access_ref) {
-               pr_info("WARN: Device is busy\n");
-               mutex_unlock(&c->io_mutex);
-               return -EBUSY;
-       }
-
-       c->mbo_offs = 0;
-       ret = most_start_channel(c->iface, c->channel_id, &cdev_aim);
-       if (!ret)
-               c->access_ref = 1;
-       mutex_unlock(&c->io_mutex);
-       return ret;
-}
-
-/**
- * aim_close - implements the syscall to close the device
- * @inode: inode pointer
- * @filp: file pointer
- *
- * This stops the channel within the core.
- */
-static int aim_close(struct inode *inode, struct file *filp)
-{
-       struct aim_channel *c = to_channel(inode->i_cdev);
-
-       mutex_lock(&c->io_mutex);
-       spin_lock(&c->unlink);
-       c->access_ref = 0;
-       spin_unlock(&c->unlink);
-       if (c->dev) {
-               stop_channel(c);
-               mutex_unlock(&c->io_mutex);
-       } else {
-               mutex_unlock(&c->io_mutex);
-               destroy_channel(c);
-       }
-       return 0;
-}
-
-/**
- * aim_write - implements the syscall to write to the device
- * @filp: file pointer
- * @buf: pointer to user buffer
- * @count: number of bytes to write
- * @offset: offset from where to start writing
- */
-static ssize_t aim_write(struct file *filp, const char __user *buf,
-                        size_t count, loff_t *offset)
-{
-       int ret;
-       size_t to_copy, left;
-       struct mbo *mbo = NULL;
-       struct aim_channel *c = filp->private_data;
-
-       mutex_lock(&c->io_mutex);
-       while (c->dev && !ch_get_mbo(c, &mbo)) {
-               mutex_unlock(&c->io_mutex);
-
-               if ((filp->f_flags & O_NONBLOCK))
-                       return -EAGAIN;
-               if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev))
-                       return -ERESTARTSYS;
-               mutex_lock(&c->io_mutex);
-       }
-
-       if (unlikely(!c->dev)) {
-               ret = -ENODEV;
-               goto unlock;
-       }
-
-       to_copy = min(count, c->cfg->buffer_size - c->mbo_offs);
-       left = copy_from_user(mbo->virt_address + c->mbo_offs, buf, to_copy);
-       if (left == to_copy) {
-               ret = -EFAULT;
-               goto unlock;
-       }
-
-       c->mbo_offs += to_copy - left;
-       if (c->mbo_offs >= c->cfg->buffer_size ||
-           c->cfg->data_type == MOST_CH_CONTROL ||
-           c->cfg->data_type == MOST_CH_ASYNC) {
-               kfifo_skip(&c->fifo);
-               mbo->buffer_length = c->mbo_offs;
-               c->mbo_offs = 0;
-               most_submit_mbo(mbo);
-       }
-
-       ret = to_copy - left;
-unlock:
-       mutex_unlock(&c->io_mutex);
-       return ret;
-}
-
-/**
- * aim_read - implements the syscall to read from the device
- * @filp: file pointer
- * @buf: pointer to user buffer
- * @count: number of bytes to read
- * @offset: offset from where to start reading
- */
-static ssize_t
-aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
-{
-       size_t to_copy, not_copied, copied;
-       struct mbo *mbo;
-       struct aim_channel *c = filp->private_data;
-
-       mutex_lock(&c->io_mutex);
-       while (c->dev && !kfifo_peek(&c->fifo, &mbo)) {
-               mutex_unlock(&c->io_mutex);
-               if (filp->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-               if (wait_event_interruptible(c->wq,
-                                            (!kfifo_is_empty(&c->fifo) ||
-                                             (!c->dev))))
-                       return -ERESTARTSYS;
-               mutex_lock(&c->io_mutex);
-       }
-
-       /* make sure we don't submit to gone devices */
-       if (unlikely(!c->dev)) {
-               mutex_unlock(&c->io_mutex);
-               return -ENODEV;
-       }
-
-       to_copy = min_t(size_t,
-                       count,
-                       mbo->processed_length - c->mbo_offs);
-
-       not_copied = copy_to_user(buf,
-                                 mbo->virt_address + c->mbo_offs,
-                                 to_copy);
-
-       copied = to_copy - not_copied;
-
-       c->mbo_offs += copied;
-       if (c->mbo_offs >= mbo->processed_length) {
-               kfifo_skip(&c->fifo);
-               most_put_mbo(mbo);
-               c->mbo_offs = 0;
-       }
-       mutex_unlock(&c->io_mutex);
-       return copied;
-}
-
-static __poll_t aim_poll(struct file *filp, poll_table *wait)
-{
-       struct aim_channel *c = filp->private_data;
-       __poll_t mask = 0;
-
-       poll_wait(filp, &c->wq, wait);
-
-       if (c->cfg->direction == MOST_CH_RX) {
-               if (!kfifo_is_empty(&c->fifo))
-                       mask |= POLLIN | POLLRDNORM;
-       } else {
-               if (!kfifo_is_empty(&c->fifo) || ch_has_mbo(c))
-                       mask |= POLLOUT | POLLWRNORM;
-       }
-       return mask;
-}
-
-/**
- * Initialization of struct file_operations
- */
-static const struct file_operations channel_fops = {
-       .owner = THIS_MODULE,
-       .read = aim_read,
-       .write = aim_write,
-       .open = aim_open,
-       .release = aim_close,
-       .poll = aim_poll,
-};
-
-/**
- * aim_disconnect_channel - disconnect a channel
- * @iface: pointer to interface instance
- * @channel_id: channel index
- *
- * This frees allocated memory and removes the cdev that represents this
- * channel in user space.
- */
-static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
-{
-       struct aim_channel *c;
-
-       if (!iface) {
-               pr_info("Bad interface pointer\n");
-               return -EINVAL;
-       }
-
-       c = get_channel(iface, channel_id);
-       if (!c)
-               return -ENXIO;
-
-       mutex_lock(&c->io_mutex);
-       spin_lock(&c->unlink);
-       c->dev = NULL;
-       spin_unlock(&c->unlink);
-       destroy_cdev(c);
-       if (c->access_ref) {
-               stop_channel(c);
-               wake_up_interruptible(&c->wq);
-               mutex_unlock(&c->io_mutex);
-       } else {
-               mutex_unlock(&c->io_mutex);
-               destroy_channel(c);
-       }
-       return 0;
-}
-
-/**
- * aim_rx_completion - completion handler for rx channels
- * @mbo: pointer to buffer object that has completed
- *
- * This searches for the channel linked to this MBO and stores it in the local
- * fifo buffer.
- */
-static int aim_rx_completion(struct mbo *mbo)
-{
-       struct aim_channel *c;
-
-       if (!mbo)
-               return -EINVAL;
-
-       c = get_channel(mbo->ifp, mbo->hdm_channel_id);
-       if (!c)
-               return -ENXIO;
-
-       spin_lock(&c->unlink);
-       if (!c->access_ref || !c->dev) {
-               spin_unlock(&c->unlink);
-               return -ENODEV;
-       }
-       kfifo_in(&c->fifo, &mbo, 1);
-       spin_unlock(&c->unlink);
-#ifdef DEBUG_MESG
-       if (kfifo_is_full(&c->fifo))
-               pr_info("WARN: Fifo is full\n");
-#endif
-       wake_up_interruptible(&c->wq);
-       return 0;
-}
-
-/**
- * aim_tx_completion - completion handler for tx channels
- * @iface: pointer to interface instance
- * @channel_id: channel index/ID
- *
- * This wakes sleeping processes in the wait-queue.
- */
-static int aim_tx_completion(struct most_interface *iface, int channel_id)
-{
-       struct aim_channel *c;
-
-       if (!iface) {
-               pr_info("Bad interface pointer\n");
-               return -EINVAL;
-       }
-       if ((channel_id < 0) || (channel_id >= iface->num_channels)) {
-               pr_info("Channel ID out of range\n");
-               return -EINVAL;
-       }
-
-       c = get_channel(iface, channel_id);
-       if (!c)
-               return -ENXIO;
-       wake_up_interruptible(&c->wq);
-       return 0;
-}
-
-/**
- * aim_probe - probe function of the driver module
- * @iface: pointer to interface instance
- * @channel_id: channel index/ID
- * @cfg: pointer to actual channel configuration
- * @parent: pointer to kobject (needed for sysfs hook-up)
- * @name: name of the device to be created
- *
- * This allocates achannel object and creates the device node in /dev
- *
- * Returns 0 on success or error code otherwise.
- */
-static int aim_probe(struct most_interface *iface, int channel_id,
-                    struct most_channel_config *cfg,
-                    struct kobject *parent, char *name)
-{
-       struct aim_channel *c;
-       unsigned long cl_flags;
-       int retval;
-       int current_minor;
-
-       if ((!iface) || (!cfg) || (!parent) || (!name)) {
-               pr_info("Probing AIM with bad arguments");
-               return -EINVAL;
-       }
-       c = get_channel(iface, channel_id);
-       if (c)
-               return -EEXIST;
-
-       current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL);
-       if (current_minor < 0)
-               return current_minor;
-
-       c = kzalloc(sizeof(*c), GFP_KERNEL);
-       if (!c) {
-               retval = -ENOMEM;
-               goto error_alloc_channel;
-       }
-
-       c->devno = MKDEV(major, current_minor);
-       cdev_init(&c->cdev, &channel_fops);
-       c->cdev.owner = THIS_MODULE;
-       cdev_add(&c->cdev, c->devno, 1);
-       c->iface = iface;
-       c->cfg = cfg;
-       c->channel_id = channel_id;
-       c->access_ref = 0;
-       spin_lock_init(&c->unlink);
-       INIT_KFIFO(c->fifo);
-       retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL);
-       if (retval) {
-               pr_info("failed to alloc channel kfifo");
-               goto error_alloc_kfifo;
-       }
-       init_waitqueue_head(&c->wq);
-       mutex_init(&c->io_mutex);
-       spin_lock_irqsave(&ch_list_lock, cl_flags);
-       list_add_tail(&c->list, &channel_list);
-       spin_unlock_irqrestore(&ch_list_lock, cl_flags);
-       c->dev = device_create(aim_class,
-                                    NULL,
-                                    c->devno,
-                                    NULL,
-                                    "%s", name);
-
-       if (IS_ERR(c->dev)) {
-               retval = PTR_ERR(c->dev);
-               pr_info("failed to create new device node %s\n", name);
-               goto error_create_device;
-       }
-       kobject_uevent(&c->dev->kobj, KOBJ_ADD);
-       return 0;
-
-error_create_device:
-       kfifo_free(&c->fifo);
-       list_del(&c->list);
-error_alloc_kfifo:
-       cdev_del(&c->cdev);
-       kfree(c);
-error_alloc_channel:
-       ida_simple_remove(&minor_id, current_minor);
-       return retval;
-}
-
-static struct most_aim cdev_aim = {
-       .name = "cdev",
-       .probe_channel = aim_probe,
-       .disconnect_channel = aim_disconnect_channel,
-       .rx_completion = aim_rx_completion,
-       .tx_completion = aim_tx_completion,
-};
-
-static int __init mod_init(void)
-{
-       int err;
-
-       pr_info("init()\n");
-
-       INIT_LIST_HEAD(&channel_list);
-       spin_lock_init(&ch_list_lock);
-       ida_init(&minor_id);
-
-       err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev");
-       if (err < 0)
-               goto dest_ida;
-       major = MAJOR(aim_devno);
-
-       aim_class = class_create(THIS_MODULE, "most_cdev_aim");
-       if (IS_ERR(aim_class)) {
-               pr_err("no udev support\n");
-               err = PTR_ERR(aim_class);
-               goto free_cdev;
-       }
-       err = most_register_aim(&cdev_aim);
-       if (err)
-               goto dest_class;
-       return 0;
-
-dest_class:
-       class_destroy(aim_class);
-free_cdev:
-       unregister_chrdev_region(aim_devno, 1);
-dest_ida:
-       ida_destroy(&minor_id);
-       return err;
-}
-
-static void __exit mod_exit(void)
-{
-       struct aim_channel *c, *tmp;
-
-       pr_info("exit module\n");
-
-       most_deregister_aim(&cdev_aim);
-
-       list_for_each_entry_safe(c, tmp, &channel_list, list) {
-               destroy_cdev(c);
-               destroy_channel(c);
-       }
-       class_destroy(aim_class);
-       unregister_chrdev_region(aim_devno, 1);
-       ida_destroy(&minor_id);
-}
-
-module_init(mod_init);
-module_exit(mod_exit);
-MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("character device AIM for mostcore");
diff --git a/drivers/staging/most/aim-network/Kconfig b/drivers/staging/most/aim-network/Kconfig
deleted file mode 100644 (file)
index 4c66b24..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# MOST Networking configuration
-#
-
-config AIM_NETWORK
-       tristate "Networking AIM"
-       depends on NET
-
-       ---help---
-         Say Y here if you want to commumicate via a networking device.
-
-         To compile this driver as a module, choose M here: the
-         module will be called aim_network.
diff --git a/drivers/staging/most/aim-network/Makefile b/drivers/staging/most/aim-network/Makefile
deleted file mode 100644 (file)
index 840c1dd..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_AIM_NETWORK) += aim_network.o
-
-aim_network-objs := networking.o
-ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
deleted file mode 100644 (file)
index 936f013..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * Networking AIM - Networking Application Interface Module for MostCore
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/wait.h>
-#include <linux/kobject.h>
-#include "mostcore.h"
-
-#define MEP_HDR_LEN 8
-#define MDP_HDR_LEN 16
-#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)
-
-#define PMHL 5
-
-#define PMS_TELID_UNSEGM_MAMAC 0x0A
-#define PMS_FIFONO_MDP         0x01
-#define PMS_FIFONO_MEP         0x04
-#define PMS_MSGTYPE_DATA       0x04
-#define PMS_DEF_PRIO           0
-#define MEP_DEF_RETRY          15
-
-#define PMS_FIFONO_MASK                0x07
-#define PMS_FIFONO_SHIFT       3
-#define PMS_RETRY_SHIFT                4
-#define PMS_TELID_MASK         0x0F
-#define PMS_TELID_SHIFT                4
-
-#define HB(value)              ((u8)((u16)(value) >> 8))
-#define LB(value)              ((u8)(value))
-
-#define EXTRACT_BIT_SET(bitset_name, value) \
-       (((value) >> bitset_name##_SHIFT) & bitset_name##_MASK)
-
-#define PMS_IS_MEP(buf, len) \
-       ((len) > MEP_HDR_LEN && \
-        EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP)
-
-#define PMS_IS_MAMAC(buf, len) \
-       ((len) > MDP_HDR_LEN && \
-        EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \
-        EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC)
-
-struct net_dev_channel {
-       bool linked;
-       int ch_id;
-};
-
-struct net_dev_context {
-       struct most_interface *iface;
-       bool is_mamac;
-       struct net_device *dev;
-       struct net_dev_channel rx;
-       struct net_dev_channel tx;
-       struct list_head list;
-};
-
-static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
-static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */
-static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */
-static struct most_aim aim;
-
-static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
-{
-       u8 *buff = mbo->virt_address;
-       const u8 broadcast[] = { 0x03, 0xFF };
-       const u8 *dest_addr = skb->data + 4;
-       const u8 *eth_type = skb->data + 12;
-       unsigned int payload_len = skb->len - ETH_HLEN;
-       unsigned int mdp_len = payload_len + MDP_HDR_LEN;
-
-       if (mbo->buffer_length < mdp_len) {
-               pr_err("drop: too small buffer! (%d for %d)\n",
-                      mbo->buffer_length, mdp_len);
-               return -EINVAL;
-       }
-
-       if (skb->len < ETH_HLEN) {
-               pr_err("drop: too small packet! (%d)\n", skb->len);
-               return -EINVAL;
-       }
-
-       if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF)
-               dest_addr = broadcast;
-
-       *buff++ = HB(mdp_len - 2);
-       *buff++ = LB(mdp_len - 2);
-
-       *buff++ = PMHL;
-       *buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
-       *buff++ = PMS_DEF_PRIO;
-       *buff++ = dest_addr[0];
-       *buff++ = dest_addr[1];
-       *buff++ = 0x00;
-
-       *buff++ = HB(payload_len + 6);
-       *buff++ = LB(payload_len + 6);
-
-       /* end of FPH here */
-
-       *buff++ = eth_type[0];
-       *buff++ = eth_type[1];
-       *buff++ = 0;
-       *buff++ = 0;
-
-       *buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len);
-       *buff++ = LB(payload_len);
-
-       memcpy(buff, skb->data + ETH_HLEN, payload_len);
-       mbo->buffer_length = mdp_len;
-       return 0;
-}
-
-static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
-{
-       u8 *buff = mbo->virt_address;
-       unsigned int mep_len = skb->len + MEP_HDR_LEN;
-
-       if (mbo->buffer_length < mep_len) {
-               pr_err("drop: too small buffer! (%d for %d)\n",
-                      mbo->buffer_length, mep_len);
-               return -EINVAL;
-       }
-
-       *buff++ = HB(mep_len - 2);
-       *buff++ = LB(mep_len - 2);
-
-       *buff++ = PMHL;
-       *buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
-       *buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO;
-       *buff++ = 0;
-       *buff++ = 0;
-       *buff++ = 0;
-
-       memcpy(buff, skb->data, skb->len);
-       mbo->buffer_length = mep_len;
-       return 0;
-}
-
-static int most_nd_set_mac_address(struct net_device *dev, void *p)
-{
-       struct net_dev_context *nd = netdev_priv(dev);
-       int err = eth_mac_addr(dev, p);
-
-       if (err)
-               return err;
-
-       nd->is_mamac =
-               (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
-                dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);
-
-       /*
-        * Set default MTU for the given packet type.
-        * It is still possible to change MTU using ip tools afterwards.
-        */
-       dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN;
-
-       return 0;
-}
-
-static void on_netinfo(struct most_interface *iface,
-                      unsigned char link_stat, unsigned char *mac_addr);
-
-static int most_nd_open(struct net_device *dev)
-{
-       struct net_dev_context *nd = netdev_priv(dev);
-       int ret = 0;
-
-       mutex_lock(&probe_disc_mt);
-
-       if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
-               netdev_err(dev, "most_start_channel() failed\n");
-               ret = -EBUSY;
-               goto unlock;
-       }
-
-       if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) {
-               netdev_err(dev, "most_start_channel() failed\n");
-               most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
-               ret = -EBUSY;
-               goto unlock;
-       }
-
-       netif_carrier_off(dev);
-       if (is_valid_ether_addr(dev->dev_addr))
-               netif_dormant_off(dev);
-       else
-               netif_dormant_on(dev);
-       netif_wake_queue(dev);
-       if (nd->iface->request_netinfo)
-               nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo);
-
-unlock:
-       mutex_unlock(&probe_disc_mt);
-       return ret;
-}
-
-static int most_nd_stop(struct net_device *dev)
-{
-       struct net_dev_context *nd = netdev_priv(dev);
-
-       netif_stop_queue(dev);
-       if (nd->iface->request_netinfo)
-               nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL);
-       most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
-       most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
-
-       return 0;
-}
-
-static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
-                                     struct net_device *dev)
-{
-       struct net_dev_context *nd = netdev_priv(dev);
-       struct mbo *mbo;
-       int ret;
-
-       mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim);
-
-       if (!mbo) {
-               netif_stop_queue(dev);
-               dev->stats.tx_fifo_errors++;
-               return NETDEV_TX_BUSY;
-       }
-
-       if (nd->is_mamac)
-               ret = skb_to_mamac(skb, mbo);
-       else
-               ret = skb_to_mep(skb, mbo);
-
-       if (ret) {
-               most_put_mbo(mbo);
-               dev->stats.tx_dropped++;
-               kfree_skb(skb);
-               return NETDEV_TX_OK;
-       }
-
-       most_submit_mbo(mbo);
-       dev->stats.tx_packets++;
-       dev->stats.tx_bytes += skb->len;
-       kfree_skb(skb);
-       return NETDEV_TX_OK;
-}
-
-static const struct net_device_ops most_nd_ops = {
-       .ndo_open = most_nd_open,
-       .ndo_stop = most_nd_stop,
-       .ndo_start_xmit = most_nd_start_xmit,
-       .ndo_set_mac_address = most_nd_set_mac_address,
-};
-
-static void most_nd_setup(struct net_device *dev)
-{
-       ether_setup(dev);
-       dev->netdev_ops = &most_nd_ops;
-}
-
-static struct net_dev_context *get_net_dev(struct most_interface *iface)
-{
-       struct net_dev_context *nd;
-
-       list_for_each_entry(nd, &net_devices, list)
-               if (nd->iface == iface)
-                       return nd;
-       return NULL;
-}
-
-static struct net_dev_context *get_net_dev_hold(struct most_interface *iface)
-{
-       struct net_dev_context *nd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&list_lock, flags);
-       nd = get_net_dev(iface);
-       if (nd && nd->rx.linked && nd->tx.linked)
-               dev_hold(nd->dev);
-       else
-               nd = NULL;
-       spin_unlock_irqrestore(&list_lock, flags);
-       return nd;
-}
-
-static int aim_probe_channel(struct most_interface *iface, int channel_idx,
-                            struct most_channel_config *ccfg,
-                            struct kobject *parent, char *name)
-{
-       struct net_dev_context *nd;
-       struct net_dev_channel *ch;
-       struct net_device *dev;
-       unsigned long flags;
-       int ret = 0;
-
-       if (!iface)
-               return -EINVAL;
-
-       if (ccfg->data_type != MOST_CH_ASYNC)
-               return -EINVAL;
-
-       mutex_lock(&probe_disc_mt);
-       nd = get_net_dev(iface);
-       if (!nd) {
-               dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d",
-                                  NET_NAME_UNKNOWN, most_nd_setup);
-               if (!dev) {
-                       ret = -ENOMEM;
-                       goto unlock;
-               }
-
-               nd = netdev_priv(dev);
-               nd->iface = iface;
-               nd->dev = dev;
-
-               spin_lock_irqsave(&list_lock, flags);
-               list_add(&nd->list, &net_devices);
-               spin_unlock_irqrestore(&list_lock, flags);
-
-               ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
-       } else {
-               ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
-               if (ch->linked) {
-                       pr_err("direction is allocated\n");
-                       ret = -EINVAL;
-                       goto unlock;
-               }
-
-               if (register_netdev(nd->dev)) {
-                       pr_err("register_netdev() failed\n");
-                       ret = -EINVAL;
-                       goto unlock;
-               }
-       }
-       ch->ch_id = channel_idx;
-       ch->linked = true;
-
-unlock:
-       mutex_unlock(&probe_disc_mt);
-       return ret;
-}
-
-static int aim_disconnect_channel(struct most_interface *iface,
-                                 int channel_idx)
-{
-       struct net_dev_context *nd;
-       struct net_dev_channel *ch;
-       unsigned long flags;
-       int ret = 0;
-
-       mutex_lock(&probe_disc_mt);
-       nd = get_net_dev(iface);
-       if (!nd) {
-               ret = -EINVAL;
-               goto unlock;
-       }
-
-       if (nd->rx.linked && channel_idx == nd->rx.ch_id) {
-               ch = &nd->rx;
-       } else if (nd->tx.linked && channel_idx == nd->tx.ch_id) {
-               ch = &nd->tx;
-       } else {
-               ret = -EINVAL;
-               goto unlock;
-       }
-
-       if (nd->rx.linked && nd->tx.linked) {
-               spin_lock_irqsave(&list_lock, flags);
-               ch->linked = false;
-               spin_unlock_irqrestore(&list_lock, flags);
-
-               /*
-                * do not call most_stop_channel() here, because channels are
-                * going to be closed in ndo_stop() after unregister_netdev()
-                */
-               unregister_netdev(nd->dev);
-       } else {
-               spin_lock_irqsave(&list_lock, flags);
-               list_del(&nd->list);
-               spin_unlock_irqrestore(&list_lock, flags);
-
-               free_netdev(nd->dev);
-       }
-
-unlock:
-       mutex_unlock(&probe_disc_mt);
-       return ret;
-}
-
-static int aim_resume_tx_channel(struct most_interface *iface,
-                                int channel_idx)
-{
-       struct net_dev_context *nd;
-
-       nd = get_net_dev_hold(iface);
-       if (!nd)
-               return 0;
-
-       if (nd->tx.ch_id != channel_idx)
-               goto put_nd;
-
-       netif_wake_queue(nd->dev);
-
-put_nd:
-       dev_put(nd->dev);
-       return 0;
-}
-
-static int aim_rx_data(struct mbo *mbo)
-{
-       const u32 zero = 0;
-       struct net_dev_context *nd;
-       char *buf = mbo->virt_address;
-       u32 len = mbo->processed_length;
-       struct sk_buff *skb;
-       struct net_device *dev;
-       unsigned int skb_len;
-       int ret = 0;
-
-       nd = get_net_dev_hold(mbo->ifp);
-       if (!nd)
-               return -EIO;
-
-       if (nd->rx.ch_id != mbo->hdm_channel_id) {
-               ret = -EIO;
-               goto put_nd;
-       }
-
-       dev = nd->dev;
-
-       if (nd->is_mamac) {
-               if (!PMS_IS_MAMAC(buf, len)) {
-                       ret = -EIO;
-                       goto put_nd;
-               }
-
-               skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
-       } else {
-               if (!PMS_IS_MEP(buf, len)) {
-                       ret = -EIO;
-                       goto put_nd;
-               }
-
-               skb = dev_alloc_skb(len - MEP_HDR_LEN);
-       }
-
-       if (!skb) {
-               dev->stats.rx_dropped++;
-               pr_err_once("drop packet: no memory for skb\n");
-               goto out;
-       }
-
-       skb->dev = dev;
-
-       if (nd->is_mamac) {
-               /* dest */
-               ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr);
-
-               /* src */
-               skb_put_data(skb, &zero, 4);
-               skb_put_data(skb, buf + 5, 2);
-
-               /* eth type */
-               skb_put_data(skb, buf + 10, 2);
-
-               buf += MDP_HDR_LEN;
-               len -= MDP_HDR_LEN;
-       } else {
-               buf += MEP_HDR_LEN;
-               len -= MEP_HDR_LEN;
-       }
-
-       skb_put_data(skb, buf, len);
-       skb->protocol = eth_type_trans(skb, dev);
-       skb_len = skb->len;
-       if (netif_rx(skb) == NET_RX_SUCCESS) {
-               dev->stats.rx_packets++;
-               dev->stats.rx_bytes += skb_len;
-       } else {
-               dev->stats.rx_dropped++;
-       }
-
-out:
-       most_put_mbo(mbo);
-
-put_nd:
-       dev_put(nd->dev);
-       return ret;
-}
-
-static struct most_aim aim = {
-       .name = "networking",
-       .probe_channel = aim_probe_channel,
-       .disconnect_channel = aim_disconnect_channel,
-       .tx_completion = aim_resume_tx_channel,
-       .rx_completion = aim_rx_data,
-};
-
-static int __init most_net_init(void)
-{
-       spin_lock_init(&list_lock);
-       mutex_init(&probe_disc_mt);
-       return most_register_aim(&aim);
-}
-
-static void __exit most_net_exit(void)
-{
-       most_deregister_aim(&aim);
-}
-
-/**
- * on_netinfo - callback for HDM to be informed about HW's MAC
- * @param iface - most interface instance
- * @param link_stat - link status
- * @param mac_addr - MAC address
- */
-static void on_netinfo(struct most_interface *iface,
-                      unsigned char link_stat, unsigned char *mac_addr)
-{
-       struct net_dev_context *nd;
-       struct net_device *dev;
-       const u8 *m = mac_addr;
-
-       nd = get_net_dev_hold(iface);
-       if (!nd)
-               return;
-
-       dev = nd->dev;
-
-       if (link_stat)
-               netif_carrier_on(dev);
-       else
-               netif_carrier_off(dev);
-
-       if (m && is_valid_ether_addr(m)) {
-               if (!is_valid_ether_addr(dev->dev_addr)) {
-                       netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n",
-                                   m[0], m[1], m[2], m[3], m[4], m[5]);
-                       ether_addr_copy(dev->dev_addr, m);
-                       netif_dormant_off(dev);
-               } else if (!ether_addr_equal(dev->dev_addr, m)) {
-                       netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n",
-                                   m[0], m[1], m[2], m[3], m[4], m[5]);
-               }
-       }
-
-       dev_put(nd->dev);
-}
-
-module_init(most_net_init);
-module_exit(most_net_exit);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
-MODULE_DESCRIPTION("Networking Application Interface Module for MostCore");
diff --git a/drivers/staging/most/aim-sound/Kconfig b/drivers/staging/most/aim-sound/Kconfig
deleted file mode 100644 (file)
index 3194c21..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# MOST ALSA configuration
-#
-
-config AIM_SOUND
-       tristate "ALSA AIM"
-       depends on SND
-       select SND_PCM
-       ---help---
-         Say Y here if you want to commumicate via ALSA/sound devices.
-
-         To compile this driver as a module, choose M here: the
-         module will be called aim_sound.
diff --git a/drivers/staging/most/aim-sound/Makefile b/drivers/staging/most/aim-sound/Makefile
deleted file mode 100644 (file)
index beba958..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_AIM_SOUND) += aim_sound.o
-
-aim_sound-objs := sound.o
-ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c
deleted file mode 100644 (file)
index ea1366a..0000000
+++ /dev/null
@@ -1,765 +0,0 @@
-/*
- * sound.c - Audio Application Interface Module for Mostcore
- *
- * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/printk.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <mostcore.h>
-
-#define DRIVER_NAME "sound"
-
-static struct list_head dev_list;
-static struct most_aim audio_aim;
-
-/**
- * struct channel - private structure to keep channel specific data
- * @substream: stores the substream structure
- * @iface: interface for which the channel belongs to
- * @cfg: channel configuration
- * @card: registered sound card
- * @list: list for private use
- * @id: channel index
- * @period_pos: current period position (ring buffer)
- * @buffer_pos: current buffer position (ring buffer)
- * @is_stream_running: identifies whether a stream is running or not
- * @opened: set when the stream is opened
- * @playback_task: playback thread
- * @playback_waitq: waitq used by playback thread
- */
-struct channel {
-       struct snd_pcm_substream *substream;
-       struct snd_pcm_hardware pcm_hardware;
-       struct most_interface *iface;
-       struct most_channel_config *cfg;
-       struct snd_card *card;
-       struct list_head list;
-       int id;
-       unsigned int period_pos;
-       unsigned int buffer_pos;
-       bool is_stream_running;
-
-       struct task_struct *playback_task;
-       wait_queue_head_t playback_waitq;
-
-       void (*copy_fn)(void *alsa, void *most, unsigned int bytes);
-};
-
-#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
-                      SNDRV_PCM_INFO_MMAP_VALID | \
-                      SNDRV_PCM_INFO_BATCH | \
-                      SNDRV_PCM_INFO_INTERLEAVED | \
-                      SNDRV_PCM_INFO_BLOCK_TRANSFER)
-
-#define swap16(val) ( \
-       (((u16)(val) << 8) & (u16)0xFF00) | \
-       (((u16)(val) >> 8) & (u16)0x00FF))
-
-#define swap32(val) ( \
-       (((u32)(val) << 24) & (u32)0xFF000000) | \
-       (((u32)(val) <<  8) & (u32)0x00FF0000) | \
-       (((u32)(val) >>  8) & (u32)0x0000FF00) | \
-       (((u32)(val) >> 24) & (u32)0x000000FF))
-
-static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes)
-{
-       unsigned int i = 0;
-
-       while (i < (bytes / 2)) {
-               dest[i] = swap16(source[i]);
-               i++;
-       }
-}
-
-static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes)
-{
-       unsigned int i = 0;
-
-       while (i < bytes - 2) {
-               dest[i] = source[i + 2];
-               dest[i + 1] = source[i + 1];
-               dest[i + 2] = source[i];
-               i += 3;
-       }
-}
-
-static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes)
-{
-       unsigned int i = 0;
-
-       while (i < bytes / 4) {
-               dest[i] = swap32(source[i]);
-               i++;
-       }
-}
-
-static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes)
-{
-       memcpy(most, alsa, bytes);
-}
-
-static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes)
-{
-       swap_copy16(most, alsa, bytes);
-}
-
-static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes)
-{
-       swap_copy24(most, alsa, bytes);
-}
-
-static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes)
-{
-       swap_copy32(most, alsa, bytes);
-}
-
-static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes)
-{
-       memcpy(alsa, most, bytes);
-}
-
-static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes)
-{
-       swap_copy16(alsa, most, bytes);
-}
-
-static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes)
-{
-       swap_copy24(alsa, most, bytes);
-}
-
-static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes)
-{
-       swap_copy32(alsa, most, bytes);
-}
-
-/**
- * get_channel - get pointer to channel
- * @iface: interface structure
- * @channel_id: channel ID
- *
- * This traverses the channel list and returns the channel matching the
- * ID and interface.
- *
- * Returns pointer to channel on success or NULL otherwise.
- */
-static struct channel *get_channel(struct most_interface *iface,
-                                  int channel_id)
-{
-       struct channel *channel, *tmp;
-
-       list_for_each_entry_safe(channel, tmp, &dev_list, list) {
-               if ((channel->iface == iface) && (channel->id == channel_id))
-                       return channel;
-       }
-
-       return NULL;
-}
-
-/**
- * copy_data - implements data copying function
- * @channel: channel
- * @mbo: MBO from core
- *
- * Copy data from/to ring buffer to/from MBO and update the buffer position
- */
-static bool copy_data(struct channel *channel, struct mbo *mbo)
-{
-       struct snd_pcm_runtime *const runtime = channel->substream->runtime;
-       unsigned int const frame_bytes = channel->cfg->subbuffer_size;
-       unsigned int const buffer_size = runtime->buffer_size;
-       unsigned int frames;
-       unsigned int fr0;
-
-       if (channel->cfg->direction & MOST_CH_RX)
-               frames = mbo->processed_length / frame_bytes;
-       else
-               frames = mbo->buffer_length / frame_bytes;
-       fr0 = min(buffer_size - channel->buffer_pos, frames);
-
-       channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes,
-                        mbo->virt_address,
-                        fr0 * frame_bytes);
-
-       if (frames > fr0) {
-               /* wrap around at end of ring buffer */
-               channel->copy_fn(runtime->dma_area,
-                                mbo->virt_address + fr0 * frame_bytes,
-                                (frames - fr0) * frame_bytes);
-       }
-
-       channel->buffer_pos += frames;
-       if (channel->buffer_pos >= buffer_size)
-               channel->buffer_pos -= buffer_size;
-       channel->period_pos += frames;
-       if (channel->period_pos >= runtime->period_size) {
-               channel->period_pos -= runtime->period_size;
-               return true;
-       }
-
-       return false;
-}
-
-/**
- * playback_thread - function implements the playback thread
- * @data: private data
- *
- * Thread which does the playback functionality in a loop. It waits for a free
- * MBO from mostcore for a particular channel and copy the data from ring buffer
- * to MBO. Submit the MBO back to mostcore, after copying the data.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int playback_thread(void *data)
-{
-       struct channel *const channel = data;
-
-       while (!kthread_should_stop()) {
-               struct mbo *mbo = NULL;
-               bool period_elapsed = false;
-
-               wait_event_interruptible(
-                       channel->playback_waitq,
-                       kthread_should_stop() ||
-                       (channel->is_stream_running &&
-                        (mbo = most_get_mbo(channel->iface, channel->id,
-                                            &audio_aim))));
-               if (!mbo)
-                       continue;
-
-               if (channel->is_stream_running)
-                       period_elapsed = copy_data(channel, mbo);
-               else
-                       memset(mbo->virt_address, 0, mbo->buffer_length);
-
-               most_submit_mbo(mbo);
-               if (period_elapsed)
-                       snd_pcm_period_elapsed(channel->substream);
-       }
-
-       return 0;
-}
-
-/**
- * pcm_open - implements open callback function for PCM middle layer
- * @substream: pointer to ALSA PCM substream
- *
- * This is called when a PCM substream is opened. At least, the function should
- * initialize the runtime->hw record.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_open(struct snd_pcm_substream *substream)
-{
-       struct channel *channel = substream->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct most_channel_config *cfg = channel->cfg;
-
-       channel->substream = substream;
-
-       if (cfg->direction == MOST_CH_TX) {
-               channel->playback_task = kthread_run(playback_thread, channel,
-                                                    "most_audio_playback");
-               if (IS_ERR(channel->playback_task)) {
-                       pr_err("Couldn't start thread\n");
-                       return PTR_ERR(channel->playback_task);
-               }
-       }
-
-       if (most_start_channel(channel->iface, channel->id, &audio_aim)) {
-               pr_err("most_start_channel() failed!\n");
-               if (cfg->direction == MOST_CH_TX)
-                       kthread_stop(channel->playback_task);
-               return -EBUSY;
-       }
-
-       runtime->hw = channel->pcm_hardware;
-       return 0;
-}
-
-/**
- * pcm_close - implements close callback function for PCM middle layer
- * @substream: sub-stream pointer
- *
- * Obviously, this is called when a PCM substream is closed. Any private
- * instance for a PCM substream allocated in the open callback will be
- * released here.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_close(struct snd_pcm_substream *substream)
-{
-       struct channel *channel = substream->private_data;
-
-       if (channel->cfg->direction == MOST_CH_TX)
-               kthread_stop(channel->playback_task);
-       most_stop_channel(channel->iface, channel->id, &audio_aim);
-
-       return 0;
-}
-
-/**
- * pcm_hw_params - implements hw_params callback function for PCM middle layer
- * @substream: sub-stream pointer
- * @hw_params: contains the hardware parameters set by the application
- *
- * This is called when the hardware parameters is set by the application, that
- * is, once when the buffer size, the period size, the format, etc. are defined
- * for the PCM substream. Many hardware setups should be done is this callback,
- * including the allocation of buffers.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_hw_params(struct snd_pcm_substream *substream,
-                        struct snd_pcm_hw_params *hw_params)
-{
-       struct channel *channel = substream->private_data;
-
-       if ((params_channels(hw_params) > channel->pcm_hardware.channels_max) ||
-           (params_channels(hw_params) < channel->pcm_hardware.channels_min)) {
-               pr_err("Requested number of channels not supported.\n");
-               return -EINVAL;
-       }
-       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                               params_buffer_bytes(hw_params));
-}
-
-/**
- * pcm_hw_free - implements hw_free callback function for PCM middle layer
- * @substream: substream pointer
- *
- * This is called to release the resources allocated via hw_params.
- * This function will be always called before the close callback is called.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_vmalloc_buffer(substream);
-}
-
-/**
- * pcm_prepare - implements prepare callback function for PCM middle layer
- * @substream: substream pointer
- *
- * This callback is called when the PCM is "prepared". Format rate, sample rate,
- * etc., can be set here. This callback can be called many times at each setup.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_prepare(struct snd_pcm_substream *substream)
-{
-       struct channel *channel = substream->private_data;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct most_channel_config *cfg = channel->cfg;
-       int width = snd_pcm_format_physical_width(runtime->format);
-
-       channel->copy_fn = NULL;
-
-       if (cfg->direction == MOST_CH_TX) {
-               if (snd_pcm_format_big_endian(runtime->format) || width == 8)
-                       channel->copy_fn = alsa_to_most_memcpy;
-               else if (width == 16)
-                       channel->copy_fn = alsa_to_most_copy16;
-               else if (width == 24)
-                       channel->copy_fn = alsa_to_most_copy24;
-               else if (width == 32)
-                       channel->copy_fn = alsa_to_most_copy32;
-       } else {
-               if (snd_pcm_format_big_endian(runtime->format) || width == 8)
-                       channel->copy_fn = most_to_alsa_memcpy;
-               else if (width == 16)
-                       channel->copy_fn = most_to_alsa_copy16;
-               else if (width == 24)
-                       channel->copy_fn = most_to_alsa_copy24;
-               else if (width == 32)
-                       channel->copy_fn = most_to_alsa_copy32;
-       }
-
-       if (!channel->copy_fn) {
-               pr_err("unsupported format\n");
-               return -EINVAL;
-       }
-
-       channel->period_pos = 0;
-       channel->buffer_pos = 0;
-
-       return 0;
-}
-
-/**
- * pcm_trigger - implements trigger callback function for PCM middle layer
- * @substream: substream pointer
- * @cmd: action to perform
- *
- * This is called when the PCM is started, stopped or paused. The action will be
- * specified in the second argument, SNDRV_PCM_TRIGGER_XXX
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       struct channel *channel = substream->private_data;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               channel->is_stream_running = true;
-               wake_up_interruptible(&channel->playback_waitq);
-               return 0;
-
-       case SNDRV_PCM_TRIGGER_STOP:
-               channel->is_stream_running = false;
-               return 0;
-
-       default:
-               pr_info("%s(), invalid\n", __func__);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/**
- * pcm_pointer - implements pointer callback function for PCM middle layer
- * @substream: substream pointer
- *
- * This callback is called when the PCM middle layer inquires the current
- * hardware position on the buffer. The position must be returned in frames,
- * ranging from 0 to buffer_size-1.
- */
-static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream)
-{
-       struct channel *channel = substream->private_data;
-
-       return channel->buffer_pos;
-}
-
-/**
- * Initialization of struct snd_pcm_ops
- */
-static const struct snd_pcm_ops pcm_ops = {
-       .open       = pcm_open,
-       .close      = pcm_close,
-       .ioctl      = snd_pcm_lib_ioctl,
-       .hw_params  = pcm_hw_params,
-       .hw_free    = pcm_hw_free,
-       .prepare    = pcm_prepare,
-       .trigger    = pcm_trigger,
-       .pointer    = pcm_pointer,
-       .page       = snd_pcm_lib_get_vmalloc_page,
-       .mmap       = snd_pcm_lib_mmap_vmalloc,
-};
-
-static int split_arg_list(char *buf, char **card_name, char **pcm_format)
-{
-       *card_name = strsep(&buf, ".");
-       if (!*card_name)
-               return -EIO;
-       *pcm_format = strsep(&buf, ".\n");
-       if (!*pcm_format)
-               return -EIO;
-       return 0;
-}
-
-static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw,
-                              char *pcm_format,
-                              struct most_channel_config *cfg)
-{
-       pcm_hw->info = MOST_PCM_INFO;
-       pcm_hw->rates = SNDRV_PCM_RATE_48000;
-       pcm_hw->rate_min = 48000;
-       pcm_hw->rate_max = 48000;
-       pcm_hw->buffer_bytes_max = cfg->num_buffers * cfg->buffer_size;
-       pcm_hw->period_bytes_min = cfg->buffer_size;
-       pcm_hw->period_bytes_max = cfg->buffer_size;
-       pcm_hw->periods_min = 1;
-       pcm_hw->periods_max = cfg->num_buffers;
-
-       if (!strcmp(pcm_format, "1x8")) {
-               if (cfg->subbuffer_size != 1)
-                       goto error;
-               pr_info("PCM format is 8-bit mono\n");
-               pcm_hw->channels_min = 1;
-               pcm_hw->channels_max = 1;
-               pcm_hw->formats = SNDRV_PCM_FMTBIT_S8;
-       } else if (!strcmp(pcm_format, "2x16")) {
-               if (cfg->subbuffer_size != 4)
-                       goto error;
-               pr_info("PCM format is 16-bit stereo\n");
-               pcm_hw->channels_min = 2;
-               pcm_hw->channels_max = 2;
-               pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE |
-                                 SNDRV_PCM_FMTBIT_S16_BE;
-       } else if (!strcmp(pcm_format, "2x24")) {
-               if (cfg->subbuffer_size != 6)
-                       goto error;
-               pr_info("PCM format is 24-bit stereo\n");
-               pcm_hw->channels_min = 2;
-               pcm_hw->channels_max = 2;
-               pcm_hw->formats = SNDRV_PCM_FMTBIT_S24_3LE |
-                                 SNDRV_PCM_FMTBIT_S24_3BE;
-       } else if (!strcmp(pcm_format, "2x32")) {
-               if (cfg->subbuffer_size != 8)
-                       goto error;
-               pr_info("PCM format is 32-bit stereo\n");
-               pcm_hw->channels_min = 2;
-               pcm_hw->channels_max = 2;
-               pcm_hw->formats = SNDRV_PCM_FMTBIT_S32_LE |
-                                 SNDRV_PCM_FMTBIT_S32_BE;
-       } else if (!strcmp(pcm_format, "6x16")) {
-               if (cfg->subbuffer_size != 12)
-                       goto error;
-               pr_info("PCM format is 16-bit 5.1 multi channel\n");
-               pcm_hw->channels_min = 6;
-               pcm_hw->channels_max = 6;
-               pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE |
-                                 SNDRV_PCM_FMTBIT_S16_BE;
-       } else {
-               pr_err("PCM format %s not supported\n", pcm_format);
-               return -EIO;
-       }
-       return 0;
-error:
-       pr_err("Audio resolution doesn't fit subbuffer size\n");
-       return -EINVAL;
-}
-
-/**
- * audio_probe_channel - probe function of the driver module
- * @iface: pointer to interface instance
- * @channel_id: channel index/ID
- * @cfg: pointer to actual channel configuration
- * @parent: pointer to kobject (needed for sysfs hook-up)
- * @arg_list: string that provides the name of the device to be created in /dev
- *           plus the desired audio resolution
- *
- * Creates sound card, pcm device, sets pcm ops and registers sound card.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int audio_probe_channel(struct most_interface *iface, int channel_id,
-                              struct most_channel_config *cfg,
-                              struct kobject *parent, char *arg_list)
-{
-       struct channel *channel;
-       struct snd_card *card;
-       struct snd_pcm *pcm;
-       int playback_count = 0;
-       int capture_count = 0;
-       int ret;
-       int direction;
-       char *card_name;
-       char *pcm_format;
-
-       if (!iface)
-               return -EINVAL;
-
-       if (cfg->data_type != MOST_CH_SYNC) {
-               pr_err("Incompatible channel type\n");
-               return -EINVAL;
-       }
-
-       if (get_channel(iface, channel_id)) {
-               pr_err("channel (%s:%d) is already linked\n",
-                      iface->description, channel_id);
-               return -EINVAL;
-       }
-
-       if (cfg->direction == MOST_CH_TX) {
-               playback_count = 1;
-               direction = SNDRV_PCM_STREAM_PLAYBACK;
-       } else {
-               capture_count = 1;
-               direction = SNDRV_PCM_STREAM_CAPTURE;
-       }
-
-       ret = split_arg_list(arg_list, &card_name, &pcm_format);
-       if (ret < 0) {
-               pr_info("PCM format missing\n");
-               return ret;
-       }
-
-       ret = snd_card_new(NULL, -1, card_name, THIS_MODULE,
-                          sizeof(*channel), &card);
-       if (ret < 0)
-               return ret;
-
-       channel = card->private_data;
-       channel->card = card;
-       channel->cfg = cfg;
-       channel->iface = iface;
-       channel->id = channel_id;
-       init_waitqueue_head(&channel->playback_waitq);
-
-       ret = audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg);
-       if (ret)
-               goto err_free_card;
-
-       snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME);
-       snprintf(card->shortname, sizeof(card->shortname), "Microchip MOST:%d",
-                card->number);
-       snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d",
-                card->shortname, iface->description, channel_id);
-
-       ret = snd_pcm_new(card, card_name, 0, playback_count,
-                         capture_count, &pcm);
-       if (ret < 0)
-               goto err_free_card;
-
-       pcm->private_data = channel;
-
-       snd_pcm_set_ops(pcm, direction, &pcm_ops);
-
-       ret = snd_card_register(card);
-       if (ret < 0)
-               goto err_free_card;
-
-       list_add_tail(&channel->list, &dev_list);
-
-       return 0;
-
-err_free_card:
-       snd_card_free(card);
-       return ret;
-}
-
-/**
- * audio_disconnect_channel - function to disconnect a channel
- * @iface: pointer to interface instance
- * @channel_id: channel index
- *
- * This frees allocated memory and removes the sound card from ALSA
- *
- * Returns 0 on success or error code otherwise.
- */
-static int audio_disconnect_channel(struct most_interface *iface,
-                                   int channel_id)
-{
-       struct channel *channel;
-
-       channel = get_channel(iface, channel_id);
-       if (!channel) {
-               pr_err("sound_disconnect_channel(), invalid channel %d\n",
-                      channel_id);
-               return -EINVAL;
-       }
-
-       list_del(&channel->list);
-       snd_card_free(channel->card);
-
-       return 0;
-}
-
-/**
- * audio_rx_completion - completion handler for rx channels
- * @mbo: pointer to buffer object that has completed
- *
- * This searches for the channel this MBO belongs to and copy the data from MBO
- * to ring buffer
- *
- * Returns 0 on success or error code otherwise.
- */
-static int audio_rx_completion(struct mbo *mbo)
-{
-       struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
-       bool period_elapsed = false;
-
-       if (!channel) {
-               pr_err("sound_rx_completion(), invalid channel %d\n",
-                      mbo->hdm_channel_id);
-               return -EINVAL;
-       }
-
-       if (channel->is_stream_running)
-               period_elapsed = copy_data(channel, mbo);
-
-       most_put_mbo(mbo);
-
-       if (period_elapsed)
-               snd_pcm_period_elapsed(channel->substream);
-
-       return 0;
-}
-
-/**
- * audio_tx_completion - completion handler for tx channels
- * @iface: pointer to interface instance
- * @channel_id: channel index/ID
- *
- * This searches the channel that belongs to this combination of interface
- * pointer and channel ID and wakes a process sitting in the wait queue of
- * this channel.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int audio_tx_completion(struct most_interface *iface, int channel_id)
-{
-       struct channel *channel = get_channel(iface, channel_id);
-
-       if (!channel) {
-               pr_err("sound_tx_completion(), invalid channel %d\n",
-                      channel_id);
-               return -EINVAL;
-       }
-
-       wake_up_interruptible(&channel->playback_waitq);
-
-       return 0;
-}
-
-/**
- * Initialization of the struct most_aim
- */
-static struct most_aim audio_aim = {
-       .name = DRIVER_NAME,
-       .probe_channel = audio_probe_channel,
-       .disconnect_channel = audio_disconnect_channel,
-       .rx_completion = audio_rx_completion,
-       .tx_completion = audio_tx_completion,
-};
-
-static int __init audio_init(void)
-{
-       pr_info("init()\n");
-
-       INIT_LIST_HEAD(&dev_list);
-
-       return most_register_aim(&audio_aim);
-}
-
-static void __exit audio_exit(void)
-{
-       struct channel *channel, *tmp;
-
-       pr_info("exit()\n");
-
-       list_for_each_entry_safe(channel, tmp, &dev_list, list) {
-               list_del(&channel->list);
-               snd_card_free(channel->card);
-       }
-
-       most_deregister_aim(&audio_aim);
-}
-
-module_init(audio_init);
-module_exit(audio_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
-MODULE_DESCRIPTION("Audio Application Interface Module for MostCore");
diff --git a/drivers/staging/most/aim-v4l2/Kconfig b/drivers/staging/most/aim-v4l2/Kconfig
deleted file mode 100644 (file)
index d70eaaf..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# MOST V4L2 configuration
-#
-
-config AIM_V4L2
-       tristate "V4L2 AIM"
-       depends on VIDEO_V4L2
-       ---help---
-         Say Y here if you want to commumicate via Video 4 Linux.
-
-         To compile this driver as a module, choose M here: the
-         module will be called aim_v4l2.
\ No newline at end of file
diff --git a/drivers/staging/most/aim-v4l2/Makefile b/drivers/staging/most/aim-v4l2/Makefile
deleted file mode 100644 (file)
index 69a7524..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_AIM_V4L2) += aim_v4l2.o
-
-aim_v4l2-objs := video.o
-
-ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c
deleted file mode 100644 (file)
index 7783bc2..0000000
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * V4L2 AIM - V4L2 Application Interface Module for MostCore
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/suspend.h>
-#include <linux/videodev2.h>
-#include <linux/mutex.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-
-#include "mostcore.h"
-
-#define V4L2_AIM_MAX_INPUT  1
-
-static struct most_aim aim_info;
-
-struct most_video_dev {
-       struct most_interface *iface;
-       int ch_idx;
-       struct list_head list;
-       bool mute;
-
-       struct list_head pending_mbos;
-       spinlock_t list_lock;
-
-       struct v4l2_device v4l2_dev;
-       atomic_t access_ref;
-       struct video_device *vdev;
-       unsigned int ctrl_input;
-
-       struct mutex lock;
-
-       wait_queue_head_t wait_data;
-};
-
-struct aim_fh {
-       /* must be the first field of this struct! */
-       struct v4l2_fh fh;
-       struct most_video_dev *mdev;
-       u32 offs;
-};
-
-static struct list_head video_devices = LIST_HEAD_INIT(video_devices);
-static struct spinlock list_lock;
-
-static inline bool data_ready(struct most_video_dev *mdev)
-{
-       return !list_empty(&mdev->pending_mbos);
-}
-
-static inline struct mbo *get_top_mbo(struct most_video_dev *mdev)
-{
-       return list_first_entry(&mdev->pending_mbos, struct mbo, list);
-}
-
-static int aim_vdev_open(struct file *filp)
-{
-       int ret;
-       struct video_device *vdev = video_devdata(filp);
-       struct most_video_dev *mdev = video_drvdata(filp);
-       struct aim_fh *fh;
-
-       v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n");
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (!fh)
-               return -ENOMEM;
-
-       if (!atomic_inc_and_test(&mdev->access_ref)) {
-               v4l2_err(&mdev->v4l2_dev, "too many clients\n");
-               ret = -EBUSY;
-               goto err_dec;
-       }
-
-       fh->mdev = mdev;
-       v4l2_fh_init(&fh->fh, vdev);
-       filp->private_data = fh;
-
-       v4l2_fh_add(&fh->fh);
-
-       ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info);
-       if (ret) {
-               v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n");
-               goto err_rm;
-       }
-
-       return 0;
-
-err_rm:
-       v4l2_fh_del(&fh->fh);
-       v4l2_fh_exit(&fh->fh);
-
-err_dec:
-       atomic_dec(&mdev->access_ref);
-       kfree(fh);
-       return ret;
-}
-
-static int aim_vdev_close(struct file *filp)
-{
-       struct aim_fh *fh = filp->private_data;
-       struct most_video_dev *mdev = fh->mdev;
-       struct mbo *mbo, *tmp;
-
-       v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n");
-
-       /*
-        * We need to put MBOs back before we call most_stop_channel()
-        * to deallocate MBOs.
-        * From the other hand mostcore still calling rx_completion()
-        * to deliver MBOs until most_stop_channel() is called.
-        * Use mute to work around this issue.
-        * This must be implemented in core.
-        */
-
-       spin_lock_irq(&mdev->list_lock);
-       mdev->mute = true;
-       list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) {
-               list_del(&mbo->list);
-               spin_unlock_irq(&mdev->list_lock);
-               most_put_mbo(mbo);
-               spin_lock_irq(&mdev->list_lock);
-       }
-       spin_unlock_irq(&mdev->list_lock);
-       most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info);
-       mdev->mute = false;
-
-       v4l2_fh_del(&fh->fh);
-       v4l2_fh_exit(&fh->fh);
-
-       atomic_dec(&mdev->access_ref);
-       kfree(fh);
-       return 0;
-}
-
-static ssize_t aim_vdev_read(struct file *filp, char __user *buf,
-                            size_t count, loff_t *pos)
-{
-       struct aim_fh *fh = filp->private_data;
-       struct most_video_dev *mdev = fh->mdev;
-       int ret = 0;
-
-       if (*pos)
-               return -ESPIPE;
-
-       if (!mdev)
-               return -ENODEV;
-
-       /* wait for the first buffer */
-       if (!(filp->f_flags & O_NONBLOCK)) {
-               if (wait_event_interruptible(mdev->wait_data, data_ready(mdev)))
-                       return -ERESTARTSYS;
-       }
-
-       if (!data_ready(mdev))
-               return -EAGAIN;
-
-       while (count > 0 && data_ready(mdev)) {
-               struct mbo *const mbo = get_top_mbo(mdev);
-               int const rem = mbo->processed_length - fh->offs;
-               int const cnt = rem < count ? rem : count;
-
-               if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) {
-                       v4l2_err(&mdev->v4l2_dev, "read: copy_to_user failed\n");
-                       if (!ret)
-                               ret = -EFAULT;
-                       return ret;
-               }
-
-               fh->offs += cnt;
-               count -= cnt;
-               buf += cnt;
-               ret += cnt;
-
-               if (cnt >= rem) {
-                       fh->offs = 0;
-                       spin_lock_irq(&mdev->list_lock);
-                       list_del(&mbo->list);
-                       spin_unlock_irq(&mdev->list_lock);
-                       most_put_mbo(mbo);
-               }
-       }
-       return ret;
-}
-
-static __poll_t aim_vdev_poll(struct file *filp, poll_table *wait)
-{
-       struct aim_fh *fh = filp->private_data;
-       struct most_video_dev *mdev = fh->mdev;
-       __poll_t mask = 0;
-
-       /* only wait if no data is available */
-       if (!data_ready(mdev))
-               poll_wait(filp, &mdev->wait_data, wait);
-       if (data_ready(mdev))
-               mask |= POLLIN | POLLRDNORM;
-
-       return mask;
-}
-
-static void aim_set_format_struct(struct v4l2_format *f)
-{
-       f->fmt.pix.width = 8;
-       f->fmt.pix.height = 8;
-       f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage = 188 * 2;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
-       f->fmt.pix.field = V4L2_FIELD_NONE;
-       f->fmt.pix.priv = 0;
-}
-
-static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
-                         struct v4l2_format *format)
-{
-       if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG)
-               return -EINVAL;
-
-       if (cmd == VIDIOC_TRY_FMT)
-               return 0;
-
-       aim_set_format_struct(format);
-
-       return 0;
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       struct aim_fh *fh = priv;
-       struct most_video_dev *mdev = fh->mdev;
-
-       v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n");
-
-       strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver));
-       strlcpy(cap->card, "MOST", sizeof(cap->card));
-       snprintf(cap->bus_info, sizeof(cap->bus_info),
-                "%s", mdev->iface->description);
-
-       cap->capabilities =
-               V4L2_CAP_READWRITE |
-               V4L2_CAP_TUNER |
-               V4L2_CAP_VIDEO_CAPTURE;
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
-                                  struct v4l2_fmtdesc *f)
-{
-       struct aim_fh *fh = priv;
-       struct most_video_dev *mdev = fh->mdev;
-
-       v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index);
-
-       if (f->index)
-               return -EINVAL;
-
-       strcpy(f->description, "MPEG");
-       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       f->flags = V4L2_FMT_FLAG_COMPRESSED;
-       f->pixelformat = V4L2_PIX_FMT_MPEG;
-
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct aim_fh *fh = priv;
-       struct most_video_dev *mdev = fh->mdev;
-
-       v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n");
-
-       aim_set_format_struct(f);
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                                 struct v4l2_format *f)
-{
-       struct aim_fh *fh = priv;
-       struct most_video_dev *mdev = fh->mdev;
-
-       return aim_set_format(mdev, VIDIOC_TRY_FMT, f);
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct aim_fh *fh = priv;
-       struct most_video_dev *mdev = fh->mdev;
-
-       return aim_set_format(mdev, VIDIOC_S_FMT, f);
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       struct aim_fh *fh = priv;
-       struct most_video_dev *mdev = fh->mdev;
-
-       v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n");
-
-       *norm = V4L2_STD_UNKNOWN;
-       return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
-                            struct v4l2_input *input)
-{
-       struct aim_fh *fh = priv;
-       struct most_video_dev *mdev = fh->mdev;
-
-       if (input->index >= V4L2_AIM_MAX_INPUT)
-               return -EINVAL;
-
-       strcpy(input->name, "MOST Video");
-       input->type |= V4L2_INPUT_TYPE_CAMERA;
-       input->audioset = 0;
-
-       input->std = mdev->vdev->tvnorms;
-
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct aim_fh *fh = priv;
-       struct most_video_dev *mdev = fh->mdev;
-       *i = mdev->ctrl_input;
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
-{
-       struct aim_fh *fh = priv;
-       struct most_video_dev *mdev = fh->mdev;
-
-       v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index);
-
-       if (index >= V4L2_AIM_MAX_INPUT)
-               return -EINVAL;
-       mdev->ctrl_input = index;
-       return 0;
-}
-
-static const struct v4l2_file_operations aim_fops = {
-       .owner      = THIS_MODULE,
-       .open       = aim_vdev_open,
-       .release    = aim_vdev_close,
-       .read       = aim_vdev_read,
-       .poll       = aim_vdev_poll,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap            = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
-       .vidioc_g_std               = vidioc_g_std,
-       .vidioc_enum_input          = vidioc_enum_input,
-       .vidioc_g_input             = vidioc_g_input,
-       .vidioc_s_input             = vidioc_s_input,
-};
-
-static const struct video_device aim_videodev_template = {
-       .fops = &aim_fops,
-       .release = video_device_release,
-       .ioctl_ops = &video_ioctl_ops,
-       .tvnorms = V4L2_STD_UNKNOWN,
-};
-
-/**************************************************************************/
-
-static struct most_video_dev *get_aim_dev(
-       struct most_interface *iface, int channel_idx)
-{
-       struct most_video_dev *mdev;
-       unsigned long flags;
-
-       spin_lock_irqsave(&list_lock, flags);
-       list_for_each_entry(mdev, &video_devices, list) {
-               if (mdev->iface == iface && mdev->ch_idx == channel_idx) {
-                       spin_unlock_irqrestore(&list_lock, flags);
-                       return mdev;
-               }
-       }
-       spin_unlock_irqrestore(&list_lock, flags);
-       return NULL;
-}
-
-static int aim_rx_data(struct mbo *mbo)
-{
-       unsigned long flags;
-       struct most_video_dev *mdev =
-               get_aim_dev(mbo->ifp, mbo->hdm_channel_id);
-
-       if (!mdev)
-               return -EIO;
-
-       spin_lock_irqsave(&mdev->list_lock, flags);
-       if (unlikely(mdev->mute)) {
-               spin_unlock_irqrestore(&mdev->list_lock, flags);
-               return -EIO;
-       }
-
-       list_add_tail(&mbo->list, &mdev->pending_mbos);
-       spin_unlock_irqrestore(&mdev->list_lock, flags);
-       wake_up_interruptible(&mdev->wait_data);
-       return 0;
-}
-
-static int aim_register_videodev(struct most_video_dev *mdev)
-{
-       int ret;
-
-       v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n");
-
-       init_waitqueue_head(&mdev->wait_data);
-
-       /* allocate and fill v4l2 video struct */
-       mdev->vdev = video_device_alloc();
-       if (!mdev->vdev)
-               return -ENOMEM;
-
-       /* Fill the video capture device struct */
-       *mdev->vdev = aim_videodev_template;
-       mdev->vdev->v4l2_dev = &mdev->v4l2_dev;
-       mdev->vdev->lock = &mdev->lock;
-       snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s",
-                mdev->v4l2_dev.name);
-
-       /* Register the v4l2 device */
-       video_set_drvdata(mdev->vdev, mdev);
-       ret = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1);
-       if (ret) {
-               v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n",
-                        ret);
-               video_device_release(mdev->vdev);
-       }
-
-       return ret;
-}
-
-static void aim_unregister_videodev(struct most_video_dev *mdev)
-{
-       v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n");
-
-       video_unregister_device(mdev->vdev);
-}
-
-static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
-{
-       struct most_video_dev *mdev =
-               container_of(v4l2_dev, struct most_video_dev, v4l2_dev);
-
-       v4l2_device_unregister(v4l2_dev);
-       kfree(mdev);
-}
-
-static int aim_probe_channel(struct most_interface *iface, int channel_idx,
-                            struct most_channel_config *ccfg,
-                            struct kobject *parent, char *name)
-{
-       int ret;
-       struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
-
-       pr_info("aim_probe_channel(%s)\n", name);
-
-       if (mdev) {
-               pr_err("channel already linked\n");
-               return -EEXIST;
-       }
-
-       if (ccfg->direction != MOST_CH_RX) {
-               pr_err("wrong direction, expect rx\n");
-               return -EINVAL;
-       }
-
-       if (ccfg->data_type != MOST_CH_SYNC &&
-           ccfg->data_type != MOST_CH_ISOC) {
-               pr_err("wrong channel type, expect sync or isoc\n");
-               return -EINVAL;
-       }
-
-       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
-       if (!mdev)
-               return -ENOMEM;
-
-       mutex_init(&mdev->lock);
-       atomic_set(&mdev->access_ref, -1);
-       spin_lock_init(&mdev->list_lock);
-       INIT_LIST_HEAD(&mdev->pending_mbos);
-       mdev->iface = iface;
-       mdev->ch_idx = channel_idx;
-       mdev->v4l2_dev.release = aim_v4l2_dev_release;
-
-       /* Create the v4l2_device */
-       strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name));
-       ret = v4l2_device_register(NULL, &mdev->v4l2_dev);
-       if (ret) {
-               pr_err("v4l2_device_register() failed\n");
-               kfree(mdev);
-               return ret;
-       }
-
-       ret = aim_register_videodev(mdev);
-       if (ret)
-               goto err_unreg;
-
-       spin_lock_irq(&list_lock);
-       list_add(&mdev->list, &video_devices);
-       spin_unlock_irq(&list_lock);
-       v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n");
-       return 0;
-
-err_unreg:
-       v4l2_device_disconnect(&mdev->v4l2_dev);
-       v4l2_device_put(&mdev->v4l2_dev);
-       return ret;
-}
-
-static int aim_disconnect_channel(struct most_interface *iface,
-                                 int channel_idx)
-{
-       struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
-
-       if (!mdev) {
-               pr_err("no such channel is linked\n");
-               return -ENOENT;
-       }
-
-       v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n");
-
-       spin_lock_irq(&list_lock);
-       list_del(&mdev->list);
-       spin_unlock_irq(&list_lock);
-
-       aim_unregister_videodev(mdev);
-       v4l2_device_disconnect(&mdev->v4l2_dev);
-       v4l2_device_put(&mdev->v4l2_dev);
-       return 0;
-}
-
-static struct most_aim aim_info = {
-       .name = "v4l",
-       .probe_channel = aim_probe_channel,
-       .disconnect_channel = aim_disconnect_channel,
-       .rx_completion = aim_rx_data,
-};
-
-static int __init aim_init(void)
-{
-       spin_lock_init(&list_lock);
-       return most_register_aim(&aim_info);
-}
-
-static void __exit aim_exit(void)
-{
-       struct most_video_dev *mdev, *tmp;
-
-       /*
-        * As the mostcore currently doesn't call disconnect_channel()
-        * for linked channels while we call most_deregister_aim()
-        * we simulate this call here.
-        * This must be fixed in core.
-        */
-       spin_lock_irq(&list_lock);
-       list_for_each_entry_safe(mdev, tmp, &video_devices, list) {
-               list_del(&mdev->list);
-               spin_unlock_irq(&list_lock);
-
-               aim_unregister_videodev(mdev);
-               v4l2_device_disconnect(&mdev->v4l2_dev);
-               v4l2_device_put(&mdev->v4l2_dev);
-               spin_lock_irq(&list_lock);
-       }
-       spin_unlock_irq(&list_lock);
-
-       most_deregister_aim(&aim_info);
-       BUG_ON(!list_empty(&video_devices));
-}
-
-module_init(aim_init);
-module_exit(aim_exit);
-
-MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore");
-MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/cdev/Kconfig b/drivers/staging/most/cdev/Kconfig
new file mode 100644 (file)
index 0000000..2b04e26
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# MOST Cdev configuration
+#
+
+config MOST_CDEV
+       tristate "Cdev"
+
+       ---help---
+         Say Y here if you want to commumicate via character devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called most_cdev.
diff --git a/drivers/staging/most/cdev/Makefile b/drivers/staging/most/cdev/Makefile
new file mode 100644 (file)
index 0000000..afb9870
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_CDEV) += most_cdev.o
+
+most_cdev-objs := cdev.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c
new file mode 100644 (file)
index 0000000..c183489
--- /dev/null
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * cdev.c - Character device component for Mostcore
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/poll.h>
+#include <linux/kfifo.h>
+#include <linux/uaccess.h>
+#include <linux/idr.h>
+#include "most/core.h"
+
+static struct cdev_component {
+       dev_t devno;
+       struct ida minor_id;
+       unsigned int major;
+       struct class *class;
+       struct core_component cc;
+} comp;
+
+struct comp_channel {
+       wait_queue_head_t wq;
+       spinlock_t unlink;      /* synchronization lock to unlink channels */
+       struct cdev cdev;
+       struct device *dev;
+       struct mutex io_mutex;
+       struct most_interface *iface;
+       struct most_channel_config *cfg;
+       unsigned int channel_id;
+       dev_t devno;
+       size_t mbo_offs;
+       DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *));
+       int access_ref;
+       struct list_head list;
+};
+
+#define to_channel(d) container_of(d, struct comp_channel, cdev)
+static struct list_head channel_list;
+static spinlock_t ch_list_lock;
+
+static inline bool ch_has_mbo(struct comp_channel *c)
+{
+       return channel_has_mbo(c->iface, c->channel_id, &comp.cc) > 0;
+}
+
+static inline bool ch_get_mbo(struct comp_channel *c, struct mbo **mbo)
+{
+       if (!kfifo_peek(&c->fifo, mbo)) {
+               *mbo = most_get_mbo(c->iface, c->channel_id, &comp.cc);
+               if (*mbo)
+                       kfifo_in(&c->fifo, mbo, 1);
+       }
+       return *mbo;
+}
+
+static struct comp_channel *get_channel(struct most_interface *iface, int id)
+{
+       struct comp_channel *c, *tmp;
+       unsigned long flags;
+       int found_channel = 0;
+
+       spin_lock_irqsave(&ch_list_lock, flags);
+       list_for_each_entry_safe(c, tmp, &channel_list, list) {
+               if ((c->iface == iface) && (c->channel_id == id)) {
+                       found_channel = 1;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&ch_list_lock, flags);
+       if (!found_channel)
+               return NULL;
+       return c;
+}
+
+static void stop_channel(struct comp_channel *c)
+{
+       struct mbo *mbo;
+
+       while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1))
+               most_put_mbo(mbo);
+       most_stop_channel(c->iface, c->channel_id, &comp.cc);
+}
+
+static void destroy_cdev(struct comp_channel *c)
+{
+       unsigned long flags;
+
+       device_destroy(comp.class, c->devno);
+       cdev_del(&c->cdev);
+       spin_lock_irqsave(&ch_list_lock, flags);
+       list_del(&c->list);
+       spin_unlock_irqrestore(&ch_list_lock, flags);
+}
+
+static void destroy_channel(struct comp_channel *c)
+{
+       ida_simple_remove(&comp.minor_id, MINOR(c->devno));
+       kfifo_free(&c->fifo);
+       kfree(c);
+}
+
+/**
+ * comp_open - implements the syscall to open the device
+ * @inode: inode pointer
+ * @filp: file pointer
+ *
+ * This stores the channel pointer in the private data field of
+ * the file structure and activates the channel within the core.
+ */
+static int comp_open(struct inode *inode, struct file *filp)
+{
+       struct comp_channel *c;
+       int ret;
+
+       c = to_channel(inode->i_cdev);
+       filp->private_data = c;
+
+       if (((c->cfg->direction == MOST_CH_RX) &&
+            ((filp->f_flags & O_ACCMODE) != O_RDONLY)) ||
+            ((c->cfg->direction == MOST_CH_TX) &&
+               ((filp->f_flags & O_ACCMODE) != O_WRONLY))) {
+               pr_info("WARN: Access flags mismatch\n");
+               return -EACCES;
+       }
+
+       mutex_lock(&c->io_mutex);
+       if (!c->dev) {
+               pr_info("WARN: Device is destroyed\n");
+               mutex_unlock(&c->io_mutex);
+               return -ENODEV;
+       }
+
+       if (c->access_ref) {
+               pr_info("WARN: Device is busy\n");
+               mutex_unlock(&c->io_mutex);
+               return -EBUSY;
+       }
+
+       c->mbo_offs = 0;
+       ret = most_start_channel(c->iface, c->channel_id, &comp.cc);
+       if (!ret)
+               c->access_ref = 1;
+       mutex_unlock(&c->io_mutex);
+       return ret;
+}
+
+/**
+ * comp_close - implements the syscall to close the device
+ * @inode: inode pointer
+ * @filp: file pointer
+ *
+ * This stops the channel within the core.
+ */
+static int comp_close(struct inode *inode, struct file *filp)
+{
+       struct comp_channel *c = to_channel(inode->i_cdev);
+
+       mutex_lock(&c->io_mutex);
+       spin_lock(&c->unlink);
+       c->access_ref = 0;
+       spin_unlock(&c->unlink);
+       if (c->dev) {
+               stop_channel(c);
+               mutex_unlock(&c->io_mutex);
+       } else {
+               mutex_unlock(&c->io_mutex);
+               destroy_channel(c);
+       }
+       return 0;
+}
+
+/**
+ * comp_write - implements the syscall to write to the device
+ * @filp: file pointer
+ * @buf: pointer to user buffer
+ * @count: number of bytes to write
+ * @offset: offset from where to start writing
+ */
+static ssize_t comp_write(struct file *filp, const char __user *buf,
+                         size_t count, loff_t *offset)
+{
+       int ret;
+       size_t to_copy, left;
+       struct mbo *mbo = NULL;
+       struct comp_channel *c = filp->private_data;
+
+       mutex_lock(&c->io_mutex);
+       while (c->dev && !ch_get_mbo(c, &mbo)) {
+               mutex_unlock(&c->io_mutex);
+
+               if ((filp->f_flags & O_NONBLOCK))
+                       return -EAGAIN;
+               if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev))
+                       return -ERESTARTSYS;
+               mutex_lock(&c->io_mutex);
+       }
+
+       if (unlikely(!c->dev)) {
+               ret = -ENODEV;
+               goto unlock;
+       }
+
+       to_copy = min(count, c->cfg->buffer_size - c->mbo_offs);
+       left = copy_from_user(mbo->virt_address + c->mbo_offs, buf, to_copy);
+       if (left == to_copy) {
+               ret = -EFAULT;
+               goto unlock;
+       }
+
+       c->mbo_offs += to_copy - left;
+       if (c->mbo_offs >= c->cfg->buffer_size ||
+           c->cfg->data_type == MOST_CH_CONTROL ||
+           c->cfg->data_type == MOST_CH_ASYNC) {
+               kfifo_skip(&c->fifo);
+               mbo->buffer_length = c->mbo_offs;
+               c->mbo_offs = 0;
+               most_submit_mbo(mbo);
+       }
+
+       ret = to_copy - left;
+unlock:
+       mutex_unlock(&c->io_mutex);
+       return ret;
+}
+
+/**
+ * comp_read - implements the syscall to read from the device
+ * @filp: file pointer
+ * @buf: pointer to user buffer
+ * @count: number of bytes to read
+ * @offset: offset from where to start reading
+ */
+static ssize_t
+comp_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
+{
+       size_t to_copy, not_copied, copied;
+       struct mbo *mbo;
+       struct comp_channel *c = filp->private_data;
+
+       mutex_lock(&c->io_mutex);
+       while (c->dev && !kfifo_peek(&c->fifo, &mbo)) {
+               mutex_unlock(&c->io_mutex);
+               if (filp->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               if (wait_event_interruptible(c->wq,
+                                            (!kfifo_is_empty(&c->fifo) ||
+                                             (!c->dev))))
+                       return -ERESTARTSYS;
+               mutex_lock(&c->io_mutex);
+       }
+
+       /* make sure we don't submit to gone devices */
+       if (unlikely(!c->dev)) {
+               mutex_unlock(&c->io_mutex);
+               return -ENODEV;
+       }
+
+       to_copy = min_t(size_t,
+                       count,
+                       mbo->processed_length - c->mbo_offs);
+
+       not_copied = copy_to_user(buf,
+                                 mbo->virt_address + c->mbo_offs,
+                                 to_copy);
+
+       copied = to_copy - not_copied;
+
+       c->mbo_offs += copied;
+       if (c->mbo_offs >= mbo->processed_length) {
+               kfifo_skip(&c->fifo);
+               most_put_mbo(mbo);
+               c->mbo_offs = 0;
+       }
+       mutex_unlock(&c->io_mutex);
+       return copied;
+}
+
+static __poll_t comp_poll(struct file *filp, poll_table *wait)
+{
+       struct comp_channel *c = filp->private_data;
+       __poll_t mask = 0;
+
+       poll_wait(filp, &c->wq, wait);
+
+       if (c->cfg->direction == MOST_CH_RX) {
+               if (!kfifo_is_empty(&c->fifo))
+                       mask |= POLLIN | POLLRDNORM;
+       } else {
+               if (!kfifo_is_empty(&c->fifo) || ch_has_mbo(c))
+                       mask |= POLLOUT | POLLWRNORM;
+       }
+       return mask;
+}
+
+/**
+ * Initialization of struct file_operations
+ */
+static const struct file_operations channel_fops = {
+       .owner = THIS_MODULE,
+       .read = comp_read,
+       .write = comp_write,
+       .open = comp_open,
+       .release = comp_close,
+       .poll = comp_poll,
+};
+
+/**
+ * comp_disconnect_channel - disconnect a channel
+ * @iface: pointer to interface instance
+ * @channel_id: channel index
+ *
+ * This frees allocated memory and removes the cdev that represents this
+ * channel in user space.
+ */
+static int comp_disconnect_channel(struct most_interface *iface, int channel_id)
+{
+       struct comp_channel *c;
+
+       if (!iface) {
+               pr_info("Bad interface pointer\n");
+               return -EINVAL;
+       }
+
+       c = get_channel(iface, channel_id);
+       if (!c)
+               return -ENXIO;
+
+       mutex_lock(&c->io_mutex);
+       spin_lock(&c->unlink);
+       c->dev = NULL;
+       spin_unlock(&c->unlink);
+       destroy_cdev(c);
+       if (c->access_ref) {
+               stop_channel(c);
+               wake_up_interruptible(&c->wq);
+               mutex_unlock(&c->io_mutex);
+       } else {
+               mutex_unlock(&c->io_mutex);
+               destroy_channel(c);
+       }
+       return 0;
+}
+
+/**
+ * comp_rx_completion - completion handler for rx channels
+ * @mbo: pointer to buffer object that has completed
+ *
+ * This searches for the channel linked to this MBO and stores it in the local
+ * fifo buffer.
+ */
+static int comp_rx_completion(struct mbo *mbo)
+{
+       struct comp_channel *c;
+
+       if (!mbo)
+               return -EINVAL;
+
+       c = get_channel(mbo->ifp, mbo->hdm_channel_id);
+       if (!c)
+               return -ENXIO;
+
+       spin_lock(&c->unlink);
+       if (!c->access_ref || !c->dev) {
+               spin_unlock(&c->unlink);
+               return -ENODEV;
+       }
+       kfifo_in(&c->fifo, &mbo, 1);
+       spin_unlock(&c->unlink);
+#ifdef DEBUG_MESG
+       if (kfifo_is_full(&c->fifo))
+               pr_info("WARN: Fifo is full\n");
+#endif
+       wake_up_interruptible(&c->wq);
+       return 0;
+}
+
+/**
+ * comp_tx_completion - completion handler for tx channels
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ *
+ * This wakes sleeping processes in the wait-queue.
+ */
+static int comp_tx_completion(struct most_interface *iface, int channel_id)
+{
+       struct comp_channel *c;
+
+       if (!iface) {
+               pr_info("Bad interface pointer\n");
+               return -EINVAL;
+       }
+       if ((channel_id < 0) || (channel_id >= iface->num_channels)) {
+               pr_info("Channel ID out of range\n");
+               return -EINVAL;
+       }
+
+       c = get_channel(iface, channel_id);
+       if (!c)
+               return -ENXIO;
+       wake_up_interruptible(&c->wq);
+       return 0;
+}
+
+/**
+ * comp_probe - probe function of the driver module
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ * @cfg: pointer to actual channel configuration
+ * @name: name of the device to be created
+ *
+ * This allocates achannel object and creates the device node in /dev
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int comp_probe(struct most_interface *iface, int channel_id,
+                     struct most_channel_config *cfg, char *name)
+{
+       struct comp_channel *c;
+       unsigned long cl_flags;
+       int retval;
+       int current_minor;
+
+       if ((!iface) || (!cfg) || (!name)) {
+               pr_info("Probing component with bad arguments");
+               return -EINVAL;
+       }
+       c = get_channel(iface, channel_id);
+       if (c)
+               return -EEXIST;
+
+       current_minor = ida_simple_get(&comp.minor_id, 0, 0, GFP_KERNEL);
+       if (current_minor < 0)
+               return current_minor;
+
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
+       if (!c) {
+               retval = -ENOMEM;
+               goto error_alloc_channel;
+       }
+
+       c->devno = MKDEV(comp.major, current_minor);
+       cdev_init(&c->cdev, &channel_fops);
+       c->cdev.owner = THIS_MODULE;
+       cdev_add(&c->cdev, c->devno, 1);
+       c->iface = iface;
+       c->cfg = cfg;
+       c->channel_id = channel_id;
+       c->access_ref = 0;
+       spin_lock_init(&c->unlink);
+       INIT_KFIFO(c->fifo);
+       retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL);
+       if (retval) {
+               pr_info("failed to alloc channel kfifo");
+               goto error_alloc_kfifo;
+       }
+       init_waitqueue_head(&c->wq);
+       mutex_init(&c->io_mutex);
+       spin_lock_irqsave(&ch_list_lock, cl_flags);
+       list_add_tail(&c->list, &channel_list);
+       spin_unlock_irqrestore(&ch_list_lock, cl_flags);
+       c->dev = device_create(comp.class, NULL, c->devno, NULL, "%s", name);
+
+       if (IS_ERR(c->dev)) {
+               retval = PTR_ERR(c->dev);
+               pr_info("failed to create new device node %s\n", name);
+               goto error_create_device;
+       }
+       kobject_uevent(&c->dev->kobj, KOBJ_ADD);
+       return 0;
+
+error_create_device:
+       kfifo_free(&c->fifo);
+       list_del(&c->list);
+error_alloc_kfifo:
+       cdev_del(&c->cdev);
+       kfree(c);
+error_alloc_channel:
+       ida_simple_remove(&comp.minor_id, current_minor);
+       return retval;
+}
+
+static struct cdev_component comp = {
+       .cc = {
+               .name = "cdev",
+               .probe_channel = comp_probe,
+               .disconnect_channel = comp_disconnect_channel,
+               .rx_completion = comp_rx_completion,
+               .tx_completion = comp_tx_completion,
+       },
+};
+
+static int __init mod_init(void)
+{
+       int err;
+
+       pr_info("init()\n");
+
+       comp.class = class_create(THIS_MODULE, "most_cdev");
+       if (IS_ERR(comp.class)) {
+               pr_info("No udev support.\n");
+               return PTR_ERR(comp.class);
+       }
+
+       INIT_LIST_HEAD(&channel_list);
+       spin_lock_init(&ch_list_lock);
+       ida_init(&comp.minor_id);
+
+       err = alloc_chrdev_region(&comp.devno, 0, 50, "cdev");
+       if (err < 0)
+               goto dest_ida;
+       comp.major = MAJOR(comp.devno);
+       err = most_register_component(&comp.cc);
+       if (err)
+               goto free_cdev;
+       return 0;
+
+free_cdev:
+       unregister_chrdev_region(comp.devno, 1);
+dest_ida:
+       ida_destroy(&comp.minor_id);
+       class_destroy(comp.class);
+       return err;
+}
+
+static void __exit mod_exit(void)
+{
+       struct comp_channel *c, *tmp;
+
+       pr_info("exit module\n");
+
+       most_deregister_component(&comp.cc);
+
+       list_for_each_entry_safe(c, tmp, &channel_list, list) {
+               destroy_cdev(c);
+               destroy_channel(c);
+       }
+       unregister_chrdev_region(comp.devno, 1);
+       ida_destroy(&comp.minor_id);
+       class_destroy(comp.class);
+}
+
+module_init(mod_init);
+module_exit(mod_exit);
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("character device component for mostcore");
diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
new file mode 100644 (file)
index 0000000..3dda8d8
--- /dev/null
@@ -0,0 +1,1603 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * core.c - Implementation of core module of MOST Linux driver stack
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/sysfs.h>
+#include <linux/kthread.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <most/core.h>
+
+#define MAX_CHANNELS   64
+#define STRING_SIZE    80
+
+static struct ida mdev_id;
+static int dummy_num_buffers;
+
+static struct mostcore {
+       struct device dev;
+       struct device_driver drv;
+       struct bus_type bus;
+       struct list_head comp_list;
+} mc;
+
+#define to_driver(d) container_of(d, struct mostcore, drv)
+
+struct pipe {
+       struct core_component *comp;
+       int refs;
+       int num_buffers;
+};
+
+struct most_channel {
+       struct device dev;
+       struct completion cleanup;
+       atomic_t mbo_ref;
+       atomic_t mbo_nq_level;
+       u16 channel_id;
+       char name[STRING_SIZE];
+       bool is_poisoned;
+       struct mutex start_mutex;
+       struct mutex nq_mutex; /* nq thread synchronization */
+       int is_starving;
+       struct most_interface *iface;
+       struct most_channel_config cfg;
+       bool keep_mbo;
+       bool enqueue_halt;
+       struct list_head fifo;
+       spinlock_t fifo_lock;
+       struct list_head halt_fifo;
+       struct list_head list;
+       struct pipe pipe0;
+       struct pipe pipe1;
+       struct list_head trash_fifo;
+       struct task_struct *hdm_enqueue_task;
+       wait_queue_head_t hdm_fifo_wq;
+
+};
+
+#define to_channel(d) container_of(d, struct most_channel, dev)
+
+struct interface_private {
+       int dev_id;
+       char name[STRING_SIZE];
+       struct most_channel *channel[MAX_CHANNELS];
+       struct list_head channel_list;
+};
+
+static const struct {
+       int most_ch_data_type;
+       const char *name;
+} ch_data_type[] = {
+       { MOST_CH_CONTROL, "control\n" },
+       { MOST_CH_ASYNC, "async\n" },
+       { MOST_CH_SYNC, "sync\n" },
+       { MOST_CH_ISOC, "isoc\n"},
+       { MOST_CH_ISOC, "isoc_avp\n"},
+};
+
+/**
+ * list_pop_mbo - retrieves the first MBO of the list and removes it
+ * @ptr: the list head to grab the MBO from.
+ */
+#define list_pop_mbo(ptr)                                              \
+({                                                                     \
+       struct mbo *_mbo = list_first_entry(ptr, struct mbo, list);     \
+       list_del(&_mbo->list);                                          \
+       _mbo;                                                           \
+})
+
+/**
+ * most_free_mbo_coherent - free an MBO and its coherent buffer
+ * @mbo: most buffer
+ */
+static void most_free_mbo_coherent(struct mbo *mbo)
+{
+       struct most_channel *c = mbo->context;
+       u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
+
+       dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address,
+                         mbo->bus_address);
+       kfree(mbo);
+       if (atomic_sub_and_test(1, &c->mbo_ref))
+               complete(&c->cleanup);
+}
+
+/**
+ * flush_channel_fifos - clear the channel fifos
+ * @c: pointer to channel object
+ */
+static void flush_channel_fifos(struct most_channel *c)
+{
+       unsigned long flags, hf_flags;
+       struct mbo *mbo, *tmp;
+
+       if (list_empty(&c->fifo) && list_empty(&c->halt_fifo))
+               return;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       list_for_each_entry_safe(mbo, tmp, &c->fifo, list) {
+               list_del(&mbo->list);
+               spin_unlock_irqrestore(&c->fifo_lock, flags);
+               most_free_mbo_coherent(mbo);
+               spin_lock_irqsave(&c->fifo_lock, flags);
+       }
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+       spin_lock_irqsave(&c->fifo_lock, hf_flags);
+       list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) {
+               list_del(&mbo->list);
+               spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
+               most_free_mbo_coherent(mbo);
+               spin_lock_irqsave(&c->fifo_lock, hf_flags);
+       }
+       spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
+
+       if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo))))
+               pr_info("WARN: fifo | trash fifo not empty\n");
+}
+
+/**
+ * flush_trash_fifo - clear the trash fifo
+ * @c: pointer to channel object
+ */
+static int flush_trash_fifo(struct most_channel *c)
+{
+       struct mbo *mbo, *tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) {
+               list_del(&mbo->list);
+               spin_unlock_irqrestore(&c->fifo_lock, flags);
+               most_free_mbo_coherent(mbo);
+               spin_lock_irqsave(&c->fifo_lock, flags);
+       }
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+       return 0;
+}
+
+static ssize_t available_directions_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+       unsigned int i = c->channel_id;
+
+       strcpy(buf, "");
+       if (c->iface->channel_vector[i].direction & MOST_CH_RX)
+               strcat(buf, "rx ");
+       if (c->iface->channel_vector[i].direction & MOST_CH_TX)
+               strcat(buf, "tx ");
+       strcat(buf, "\n");
+       return strlen(buf);
+}
+
+static ssize_t available_datatypes_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+       unsigned int i = c->channel_id;
+
+       strcpy(buf, "");
+       if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL)
+               strcat(buf, "control ");
+       if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC)
+               strcat(buf, "async ");
+       if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC)
+               strcat(buf, "sync ");
+       if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC)
+               strcat(buf, "isoc ");
+       strcat(buf, "\n");
+       return strlen(buf);
+}
+
+static ssize_t number_of_packet_buffers_show(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+       unsigned int i = c->channel_id;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       c->iface->channel_vector[i].num_buffers_packet);
+}
+
+static ssize_t number_of_stream_buffers_show(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+       unsigned int i = c->channel_id;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       c->iface->channel_vector[i].num_buffers_streaming);
+}
+
+static ssize_t size_of_packet_buffer_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+       unsigned int i = c->channel_id;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       c->iface->channel_vector[i].buffer_size_packet);
+}
+
+static ssize_t size_of_stream_buffer_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+       unsigned int i = c->channel_id;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       c->iface->channel_vector[i].buffer_size_streaming);
+}
+
+static ssize_t channel_starving_show(struct device *dev,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
+}
+
+static ssize_t set_number_of_buffers_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
+}
+
+static ssize_t set_number_of_buffers_store(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf,
+                                          size_t count)
+{
+       struct most_channel *c = to_channel(dev);
+       int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
+
+       if (ret)
+               return ret;
+       return count;
+}
+
+static ssize_t set_buffer_size_show(struct device *dev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
+}
+
+static ssize_t set_buffer_size_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf,
+                                    size_t count)
+{
+       struct most_channel *c = to_channel(dev);
+       int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
+
+       if (ret)
+               return ret;
+       return count;
+}
+
+static ssize_t set_direction_show(struct device *dev,
+                                 struct device_attribute *attr,
+                                 char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+
+       if (c->cfg.direction & MOST_CH_TX)
+               return snprintf(buf, PAGE_SIZE, "tx\n");
+       else if (c->cfg.direction & MOST_CH_RX)
+               return snprintf(buf, PAGE_SIZE, "rx\n");
+       return snprintf(buf, PAGE_SIZE, "unconfigured\n");
+}
+
+static ssize_t set_direction_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf,
+                                  size_t count)
+{
+       struct most_channel *c = to_channel(dev);
+
+       if (!strcmp(buf, "dir_rx\n")) {
+               c->cfg.direction = MOST_CH_RX;
+       } else if (!strcmp(buf, "rx\n")) {
+               c->cfg.direction = MOST_CH_RX;
+       } else if (!strcmp(buf, "dir_tx\n")) {
+               c->cfg.direction = MOST_CH_TX;
+       } else if (!strcmp(buf, "tx\n")) {
+               c->cfg.direction = MOST_CH_TX;
+       } else {
+               pr_info("WARN: invalid attribute settings\n");
+               return -EINVAL;
+       }
+       return count;
+}
+
+static ssize_t set_datatype_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       int i;
+       struct most_channel *c = to_channel(dev);
+
+       for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
+               if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
+                       return snprintf(buf, PAGE_SIZE, ch_data_type[i].name);
+       }
+       return snprintf(buf, PAGE_SIZE, "unconfigured\n");
+}
+
+static ssize_t set_datatype_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf,
+                                 size_t count)
+{
+       int i;
+       struct most_channel *c = to_channel(dev);
+
+       for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
+               if (!strcmp(buf, ch_data_type[i].name)) {
+                       c->cfg.data_type = ch_data_type[i].most_ch_data_type;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(ch_data_type)) {
+               pr_info("WARN: invalid attribute settings\n");
+               return -EINVAL;
+       }
+       return count;
+}
+
+static ssize_t set_subbuffer_size_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
+}
+
+static ssize_t set_subbuffer_size_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf,
+                                       size_t count)
+{
+       struct most_channel *c = to_channel(dev);
+       int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
+
+       if (ret)
+               return ret;
+       return count;
+}
+
+static ssize_t set_packets_per_xact_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct most_channel *c = to_channel(dev);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact);
+}
+
+static ssize_t set_packets_per_xact_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf,
+                                         size_t count)
+{
+       struct most_channel *c = to_channel(dev);
+       int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
+
+       if (ret)
+               return ret;
+       return count;
+}
+
+#define DEV_ATTR(_name)  (&dev_attr_##_name.attr)
+
+static DEVICE_ATTR_RO(available_directions);
+static DEVICE_ATTR_RO(available_datatypes);
+static DEVICE_ATTR_RO(number_of_packet_buffers);
+static DEVICE_ATTR_RO(number_of_stream_buffers);
+static DEVICE_ATTR_RO(size_of_stream_buffer);
+static DEVICE_ATTR_RO(size_of_packet_buffer);
+static DEVICE_ATTR_RO(channel_starving);
+static DEVICE_ATTR_RW(set_buffer_size);
+static DEVICE_ATTR_RW(set_number_of_buffers);
+static DEVICE_ATTR_RW(set_direction);
+static DEVICE_ATTR_RW(set_datatype);
+static DEVICE_ATTR_RW(set_subbuffer_size);
+static DEVICE_ATTR_RW(set_packets_per_xact);
+
+static struct attribute *channel_attrs[] = {
+       DEV_ATTR(available_directions),
+       DEV_ATTR(available_datatypes),
+       DEV_ATTR(number_of_packet_buffers),
+       DEV_ATTR(number_of_stream_buffers),
+       DEV_ATTR(size_of_stream_buffer),
+       DEV_ATTR(size_of_packet_buffer),
+       DEV_ATTR(channel_starving),
+       DEV_ATTR(set_buffer_size),
+       DEV_ATTR(set_number_of_buffers),
+       DEV_ATTR(set_direction),
+       DEV_ATTR(set_datatype),
+       DEV_ATTR(set_subbuffer_size),
+       DEV_ATTR(set_packets_per_xact),
+       NULL,
+};
+
+static struct attribute_group channel_attr_group = {
+       .attrs = channel_attrs,
+};
+
+static const struct attribute_group *channel_attr_groups[] = {
+       &channel_attr_group,
+       NULL,
+};
+
+static ssize_t description_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct most_interface *iface = to_most_interface(dev);
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", iface->description);
+}
+
+static ssize_t interface_show(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       struct most_interface *iface = to_most_interface(dev);
+
+       switch (iface->interface) {
+       case ITYPE_LOOPBACK:
+               return snprintf(buf, PAGE_SIZE, "loopback\n");
+       case ITYPE_I2C:
+               return snprintf(buf, PAGE_SIZE, "i2c\n");
+       case ITYPE_I2S:
+               return snprintf(buf, PAGE_SIZE, "i2s\n");
+       case ITYPE_TSI:
+               return snprintf(buf, PAGE_SIZE, "tsi\n");
+       case ITYPE_HBI:
+               return snprintf(buf, PAGE_SIZE, "hbi\n");
+       case ITYPE_MEDIALB_DIM:
+               return snprintf(buf, PAGE_SIZE, "mlb_dim\n");
+       case ITYPE_MEDIALB_DIM2:
+               return snprintf(buf, PAGE_SIZE, "mlb_dim2\n");
+       case ITYPE_USB:
+               return snprintf(buf, PAGE_SIZE, "usb\n");
+       case ITYPE_PCIE:
+               return snprintf(buf, PAGE_SIZE, "pcie\n");
+       }
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+static DEVICE_ATTR_RO(description);
+static DEVICE_ATTR_RO(interface);
+
+static struct attribute *interface_attrs[] = {
+       DEV_ATTR(description),
+       DEV_ATTR(interface),
+       NULL,
+};
+
+static struct attribute_group interface_attr_group = {
+       .attrs = interface_attrs,
+};
+
+static const struct attribute_group *interface_attr_groups[] = {
+       &interface_attr_group,
+       NULL,
+};
+
+static struct core_component *match_component(char *name)
+{
+       struct core_component *comp;
+
+       list_for_each_entry(comp, &mc.comp_list, list) {
+               if (!strcmp(comp->name, name))
+                       return comp;
+       }
+       return NULL;
+}
+
+struct show_links_data {
+       int offs;
+       char *buf;
+};
+
+static int print_links(struct device *dev, void *data)
+{
+       struct show_links_data *d = data;
+       int offs = d->offs;
+       char *buf = d->buf;
+       struct most_channel *c;
+       struct most_interface *iface = to_most_interface(dev);
+
+       list_for_each_entry(c, &iface->p->channel_list, list) {
+               if (c->pipe0.comp) {
+                       offs += snprintf(buf + offs,
+                                        PAGE_SIZE - offs,
+                                        "%s:%s:%s\n",
+                                        c->pipe0.comp->name,
+                                        dev_name(&iface->dev),
+                                        dev_name(&c->dev));
+               }
+               if (c->pipe1.comp) {
+                       offs += snprintf(buf + offs,
+                                        PAGE_SIZE - offs,
+                                        "%s:%s:%s\n",
+                                        c->pipe1.comp->name,
+                                        dev_name(&iface->dev),
+                                        dev_name(&c->dev));
+               }
+       }
+       d->offs = offs;
+       return 0;
+}
+
+static ssize_t links_show(struct device_driver *drv, char *buf)
+{
+       struct show_links_data d = { .buf = buf };
+
+       bus_for_each_dev(&mc.bus, NULL, &d, print_links);
+       return d.offs;
+}
+
+static ssize_t components_show(struct device_driver *drv, char *buf)
+{
+       struct core_component *comp;
+       int offs = 0;
+
+       list_for_each_entry(comp, &mc.comp_list, list) {
+               offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s\n",
+                                comp->name);
+       }
+       return offs;
+}
+/**
+ * split_string - parses buf and extracts ':' separated substrings.
+ *
+ * @buf: complete string from attribute 'add_channel'
+ * @a: storage for 1st substring (=interface name)
+ * @b: storage for 2nd substring (=channel name)
+ * @c: storage for 3rd substring (=component name)
+ * @d: storage optional 4th substring (=user defined name)
+ *
+ * Examples:
+ *
+ * Input: "mdev0:ch6:cdev:my_channel\n" or
+ *        "mdev0:ch6:cdev:my_channel"
+ *
+ * Output: *a -> "mdev0", *b -> "ch6", *c -> "cdev" *d -> "my_channel"
+ *
+ * Input: "mdev1:ep81:cdev\n"
+ * Output: *a -> "mdev1", *b -> "ep81", *c -> "cdev" *d -> ""
+ *
+ * Input: "mdev1:ep81"
+ * Output: *a -> "mdev1", *b -> "ep81", *c -> "cdev" *d == NULL
+ */
+static int split_string(char *buf, char **a, char **b, char **c, char **d)
+{
+       *a = strsep(&buf, ":");
+       if (!*a)
+               return -EIO;
+
+       *b = strsep(&buf, ":\n");
+       if (!*b)
+               return -EIO;
+
+       *c = strsep(&buf, ":\n");
+       if (!*c)
+               return -EIO;
+
+       if (d)
+               *d = strsep(&buf, ":\n");
+
+       return 0;
+}
+
+static int match_bus_dev(struct device *dev, void *data)
+{
+       char *mdev_name = data;
+
+       return !strcmp(dev_name(dev), mdev_name);
+}
+
+/**
+ * get_channel - get pointer to channel
+ * @mdev: name of the device interface
+ * @mdev_ch: name of channel
+ */
+static struct most_channel *get_channel(char *mdev, char *mdev_ch)
+{
+       struct device *dev = NULL;
+       struct most_interface *iface;
+       struct most_channel *c, *tmp;
+
+       dev = bus_find_device(&mc.bus, NULL, mdev, match_bus_dev);
+       if (!dev)
+               return NULL;
+       iface = to_most_interface(dev);
+       list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) {
+               if (!strcmp(dev_name(&c->dev), mdev_ch))
+                       return c;
+       }
+       return NULL;
+}
+
+static
+inline int link_channel_to_component(struct most_channel *c,
+                                    struct core_component *comp,
+                                    char *comp_param)
+{
+       int ret;
+       struct core_component **comp_ptr;
+
+       if (!c->pipe0.comp)
+               comp_ptr = &c->pipe0.comp;
+       else if (!c->pipe1.comp)
+               comp_ptr = &c->pipe1.comp;
+       else
+               return -ENOSPC;
+
+       *comp_ptr = comp;
+       ret = comp->probe_channel(c->iface, c->channel_id, &c->cfg, comp_param);
+       if (ret) {
+               *comp_ptr = NULL;
+               return ret;
+       }
+       return 0;
+}
+
+/**
+ * add_link_store - store function for add_link attribute
+ * @drv: device driver
+ * @buf: buffer
+ * @len: buffer length
+ *
+ * This parses the string given by buf and splits it into
+ * four substrings. Note: last substring is optional. In case a cdev
+ * component is loaded the optional 4th substring will make up the name of
+ * device node in the /dev directory. If omitted, the device node will
+ * inherit the channel's name within sysfs.
+ *
+ * Searches for (device, channel) pair and probes the component
+ *
+ * Example:
+ * (1) echo "mdev0:ch6:cdev:my_rxchannel" >add_link
+ * (2) echo "mdev1:ep81:cdev" >add_link
+ *
+ * (1) would create the device node /dev/my_rxchannel
+ * (2) would create the device node /dev/mdev1-ep81
+ */
+static ssize_t add_link_store(struct device_driver *drv,
+                             const char *buf,
+                             size_t len)
+{
+       struct most_channel *c;
+       struct core_component *comp;
+       char buffer[STRING_SIZE];
+       char *mdev;
+       char *mdev_ch;
+       char *comp_name;
+       char *comp_param;
+       char devnod_buf[STRING_SIZE];
+       int ret;
+       size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
+
+       strlcpy(buffer, buf, max_len);
+       ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, &comp_param);
+       if (ret)
+               return ret;
+       comp = match_component(comp_name);
+       if (!comp)
+               return -ENODEV;
+       if (!comp_param || *comp_param == 0) {
+               snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev,
+                        mdev_ch);
+               comp_param = devnod_buf;
+       }
+
+       c = get_channel(mdev, mdev_ch);
+       if (!c)
+               return -ENODEV;
+
+       ret = link_channel_to_component(c, comp, comp_param);
+       if (ret)
+               return ret;
+       return len;
+}
+
+/**
+ * remove_link_store - store function for remove_link attribute
+ * @drv: device driver
+ * @buf: buffer
+ * @len: buffer length
+ *
+ * Example:
+ * echo "mdev0:ep81" >remove_link
+ */
+static ssize_t remove_link_store(struct device_driver *drv,
+                                const char *buf,
+                                size_t len)
+{
+       struct most_channel *c;
+       struct core_component *comp;
+       char buffer[STRING_SIZE];
+       char *mdev;
+       char *mdev_ch;
+       char *comp_name;
+       int ret;
+       size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
+
+       strlcpy(buffer, buf, max_len);
+       ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, NULL);
+       if (ret)
+               return ret;
+       comp = match_component(comp_name);
+       if (!comp)
+               return -ENODEV;
+       c = get_channel(mdev, mdev_ch);
+       if (!c)
+               return -ENODEV;
+
+       if (comp->disconnect_channel(c->iface, c->channel_id))
+               return -EIO;
+       if (c->pipe0.comp == comp)
+               c->pipe0.comp = NULL;
+       if (c->pipe1.comp == comp)
+               c->pipe1.comp = NULL;
+       return len;
+}
+
+#define DRV_ATTR(_name)  (&driver_attr_##_name.attr)
+
+static DRIVER_ATTR_RO(links);
+static DRIVER_ATTR_RO(components);
+static DRIVER_ATTR_WO(add_link);
+static DRIVER_ATTR_WO(remove_link);
+
+static struct attribute *mc_attrs[] = {
+       DRV_ATTR(links),
+       DRV_ATTR(components),
+       DRV_ATTR(add_link),
+       DRV_ATTR(remove_link),
+       NULL,
+};
+
+static struct attribute_group mc_attr_group = {
+       .attrs = mc_attrs,
+};
+
+static const struct attribute_group *mc_attr_groups[] = {
+       &mc_attr_group,
+       NULL,
+};
+
+static int most_match(struct device *dev, struct device_driver *drv)
+{
+       if (!strcmp(dev_name(dev), "most"))
+               return 0;
+       else
+               return 1;
+}
+
+static inline void trash_mbo(struct mbo *mbo)
+{
+       unsigned long flags;
+       struct most_channel *c = mbo->context;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       list_add(&mbo->list, &c->trash_fifo);
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+}
+
+static bool hdm_mbo_ready(struct most_channel *c)
+{
+       bool empty;
+
+       if (c->enqueue_halt)
+               return false;
+
+       spin_lock_irq(&c->fifo_lock);
+       empty = list_empty(&c->halt_fifo);
+       spin_unlock_irq(&c->fifo_lock);
+
+       return !empty;
+}
+
+static void nq_hdm_mbo(struct mbo *mbo)
+{
+       unsigned long flags;
+       struct most_channel *c = mbo->context;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       list_add_tail(&mbo->list, &c->halt_fifo);
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+       wake_up_interruptible(&c->hdm_fifo_wq);
+}
+
+static int hdm_enqueue_thread(void *data)
+{
+       struct most_channel *c = data;
+       struct mbo *mbo;
+       int ret;
+       typeof(c->iface->enqueue) enqueue = c->iface->enqueue;
+
+       while (likely(!kthread_should_stop())) {
+               wait_event_interruptible(c->hdm_fifo_wq,
+                                        hdm_mbo_ready(c) ||
+                                        kthread_should_stop());
+
+               mutex_lock(&c->nq_mutex);
+               spin_lock_irq(&c->fifo_lock);
+               if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) {
+                       spin_unlock_irq(&c->fifo_lock);
+                       mutex_unlock(&c->nq_mutex);
+                       continue;
+               }
+
+               mbo = list_pop_mbo(&c->halt_fifo);
+               spin_unlock_irq(&c->fifo_lock);
+
+               if (c->cfg.direction == MOST_CH_RX)
+                       mbo->buffer_length = c->cfg.buffer_size;
+
+               ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo);
+               mutex_unlock(&c->nq_mutex);
+
+               if (unlikely(ret)) {
+                       pr_err("hdm enqueue failed\n");
+                       nq_hdm_mbo(mbo);
+                       c->hdm_enqueue_task = NULL;
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
+static int run_enqueue_thread(struct most_channel *c, int channel_id)
+{
+       struct task_struct *task =
+               kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d",
+                           channel_id);
+
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+
+       c->hdm_enqueue_task = task;
+       return 0;
+}
+
+/**
+ * arm_mbo - recycle MBO for further usage
+ * @mbo: most buffer
+ *
+ * This puts an MBO back to the list to have it ready for up coming
+ * tx transactions.
+ *
+ * In case the MBO belongs to a channel that recently has been
+ * poisoned, the MBO is scheduled to be trashed.
+ * Calls the completion handler of an attached component.
+ */
+static void arm_mbo(struct mbo *mbo)
+{
+       unsigned long flags;
+       struct most_channel *c;
+
+       BUG_ON((!mbo) || (!mbo->context));
+       c = mbo->context;
+
+       if (c->is_poisoned) {
+               trash_mbo(mbo);
+               return;
+       }
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       ++*mbo->num_buffers_ptr;
+       list_add_tail(&mbo->list, &c->fifo);
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+       if (c->pipe0.refs && c->pipe0.comp->tx_completion)
+               c->pipe0.comp->tx_completion(c->iface, c->channel_id);
+
+       if (c->pipe1.refs && c->pipe1.comp->tx_completion)
+               c->pipe1.comp->tx_completion(c->iface, c->channel_id);
+}
+
+/**
+ * arm_mbo_chain - helper function that arms an MBO chain for the HDM
+ * @c: pointer to interface channel
+ * @dir: direction of the channel
+ * @compl: pointer to completion function
+ *
+ * This allocates buffer objects including the containing DMA coherent
+ * buffer and puts them in the fifo.
+ * Buffers of Rx channels are put in the kthread fifo, hence immediately
+ * submitted to the HDM.
+ *
+ * Returns the number of allocated and enqueued MBOs.
+ */
+static int arm_mbo_chain(struct most_channel *c, int dir,
+                        void (*compl)(struct mbo *))
+{
+       unsigned int i;
+       int retval;
+       struct mbo *mbo;
+       u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
+
+       atomic_set(&c->mbo_nq_level, 0);
+
+       for (i = 0; i < c->cfg.num_buffers; i++) {
+               mbo = kzalloc(sizeof(*mbo), GFP_KERNEL);
+               if (!mbo) {
+                       retval = i;
+                       goto _exit;
+               }
+               mbo->context = c;
+               mbo->ifp = c->iface;
+               mbo->hdm_channel_id = c->channel_id;
+               mbo->virt_address = dma_alloc_coherent(NULL,
+                                                      coherent_buf_size,
+                                                      &mbo->bus_address,
+                                                      GFP_KERNEL);
+               if (!mbo->virt_address) {
+                       pr_info("WARN: No DMA coherent buffer.\n");
+                       retval = i;
+                       goto _error1;
+               }
+               mbo->complete = compl;
+               mbo->num_buffers_ptr = &dummy_num_buffers;
+               if (dir == MOST_CH_RX) {
+                       nq_hdm_mbo(mbo);
+                       atomic_inc(&c->mbo_nq_level);
+               } else {
+                       arm_mbo(mbo);
+               }
+       }
+       return i;
+
+_error1:
+       kfree(mbo);
+_exit:
+       return retval;
+}
+
+/**
+ * most_submit_mbo - submits an MBO to fifo
+ * @mbo: most buffer
+ */
+void most_submit_mbo(struct mbo *mbo)
+{
+       if (WARN_ONCE(!mbo || !mbo->context,
+                     "bad mbo or missing channel reference\n"))
+               return;
+
+       nq_hdm_mbo(mbo);
+}
+EXPORT_SYMBOL_GPL(most_submit_mbo);
+
+/**
+ * most_write_completion - write completion handler
+ * @mbo: most buffer
+ *
+ * This recycles the MBO for further usage. In case the channel has been
+ * poisoned, the MBO is scheduled to be trashed.
+ */
+static void most_write_completion(struct mbo *mbo)
+{
+       struct most_channel *c;
+
+       BUG_ON((!mbo) || (!mbo->context));
+
+       c = mbo->context;
+       if (mbo->status == MBO_E_INVAL)
+               pr_info("WARN: Tx MBO status: invalid\n");
+       if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE)))
+               trash_mbo(mbo);
+       else
+               arm_mbo(mbo);
+}
+
+int channel_has_mbo(struct most_interface *iface, int id,
+                   struct core_component *comp)
+{
+       struct most_channel *c = iface->p->channel[id];
+       unsigned long flags;
+       int empty;
+
+       if (unlikely(!c))
+               return -EINVAL;
+
+       if (c->pipe0.refs && c->pipe1.refs &&
+           ((comp == c->pipe0.comp && c->pipe0.num_buffers <= 0) ||
+            (comp == c->pipe1.comp && c->pipe1.num_buffers <= 0)))
+               return 0;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       empty = list_empty(&c->fifo);
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+       return !empty;
+}
+EXPORT_SYMBOL_GPL(channel_has_mbo);
+
+/**
+ * most_get_mbo - get pointer to an MBO of pool
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ * @comp: driver component
+ *
+ * This attempts to get a free buffer out of the channel fifo.
+ * Returns a pointer to MBO on success or NULL otherwise.
+ */
+struct mbo *most_get_mbo(struct most_interface *iface, int id,
+                        struct core_component *comp)
+{
+       struct mbo *mbo;
+       struct most_channel *c;
+       unsigned long flags;
+       int *num_buffers_ptr;
+
+       c = iface->p->channel[id];
+       if (unlikely(!c))
+               return NULL;
+
+       if (c->pipe0.refs && c->pipe1.refs &&
+           ((comp == c->pipe0.comp && c->pipe0.num_buffers <= 0) ||
+            (comp == c->pipe1.comp && c->pipe1.num_buffers <= 0)))
+               return NULL;
+
+       if (comp == c->pipe0.comp)
+               num_buffers_ptr = &c->pipe0.num_buffers;
+       else if (comp == c->pipe1.comp)
+               num_buffers_ptr = &c->pipe1.num_buffers;
+       else
+               num_buffers_ptr = &dummy_num_buffers;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       if (list_empty(&c->fifo)) {
+               spin_unlock_irqrestore(&c->fifo_lock, flags);
+               return NULL;
+       }
+       mbo = list_pop_mbo(&c->fifo);
+       --*num_buffers_ptr;
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+       mbo->num_buffers_ptr = num_buffers_ptr;
+       mbo->buffer_length = c->cfg.buffer_size;
+       return mbo;
+}
+EXPORT_SYMBOL_GPL(most_get_mbo);
+
+/**
+ * most_put_mbo - return buffer to pool
+ * @mbo: most buffer
+ */
+void most_put_mbo(struct mbo *mbo)
+{
+       struct most_channel *c = mbo->context;
+
+       if (c->cfg.direction == MOST_CH_TX) {
+               arm_mbo(mbo);
+               return;
+       }
+       nq_hdm_mbo(mbo);
+       atomic_inc(&c->mbo_nq_level);
+}
+EXPORT_SYMBOL_GPL(most_put_mbo);
+
+/**
+ * most_read_completion - read completion handler
+ * @mbo: most buffer
+ *
+ * This function is called by the HDM when data has been received from the
+ * hardware and copied to the buffer of the MBO.
+ *
+ * In case the channel has been poisoned it puts the buffer in the trash queue.
+ * Otherwise, it passes the buffer to an component for further processing.
+ */
+static void most_read_completion(struct mbo *mbo)
+{
+       struct most_channel *c = mbo->context;
+
+       if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) {
+               trash_mbo(mbo);
+               return;
+       }
+
+       if (mbo->status == MBO_E_INVAL) {
+               nq_hdm_mbo(mbo);
+               atomic_inc(&c->mbo_nq_level);
+               return;
+       }
+
+       if (atomic_sub_and_test(1, &c->mbo_nq_level))
+               c->is_starving = 1;
+
+       if (c->pipe0.refs && c->pipe0.comp->rx_completion &&
+           c->pipe0.comp->rx_completion(mbo) == 0)
+               return;
+
+       if (c->pipe1.refs && c->pipe1.comp->rx_completion &&
+           c->pipe1.comp->rx_completion(mbo) == 0)
+               return;
+
+       most_put_mbo(mbo);
+}
+
+/**
+ * most_start_channel - prepares a channel for communication
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ * @comp: driver component
+ *
+ * This prepares the channel for usage. Cross-checks whether the
+ * channel's been properly configured.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+int most_start_channel(struct most_interface *iface, int id,
+                      struct core_component *comp)
+{
+       int num_buffer;
+       int ret;
+       struct most_channel *c = iface->p->channel[id];
+
+       if (unlikely(!c))
+               return -EINVAL;
+
+       mutex_lock(&c->start_mutex);
+       if (c->pipe0.refs + c->pipe1.refs > 0)
+               goto out; /* already started by another component */
+
+       if (!try_module_get(iface->mod)) {
+               pr_info("failed to acquire HDM lock\n");
+               mutex_unlock(&c->start_mutex);
+               return -ENOLCK;
+       }
+
+       c->cfg.extra_len = 0;
+       if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) {
+               pr_info("channel configuration failed. Go check settings...\n");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       init_waitqueue_head(&c->hdm_fifo_wq);
+
+       if (c->cfg.direction == MOST_CH_RX)
+               num_buffer = arm_mbo_chain(c, c->cfg.direction,
+                                          most_read_completion);
+       else
+               num_buffer = arm_mbo_chain(c, c->cfg.direction,
+                                          most_write_completion);
+       if (unlikely(!num_buffer)) {
+               pr_info("failed to allocate memory\n");
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       ret = run_enqueue_thread(c, id);
+       if (ret)
+               goto error;
+
+       c->is_starving = 0;
+       c->pipe0.num_buffers = c->cfg.num_buffers / 2;
+       c->pipe1.num_buffers = c->cfg.num_buffers - c->pipe0.num_buffers;
+       atomic_set(&c->mbo_ref, num_buffer);
+
+out:
+       if (comp == c->pipe0.comp)
+               c->pipe0.refs++;
+       if (comp == c->pipe1.comp)
+               c->pipe1.refs++;
+       mutex_unlock(&c->start_mutex);
+       return 0;
+
+error:
+       module_put(iface->mod);
+       mutex_unlock(&c->start_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(most_start_channel);
+
+/**
+ * most_stop_channel - stops a running channel
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ * @comp: driver component
+ */
+int most_stop_channel(struct most_interface *iface, int id,
+                     struct core_component *comp)
+{
+       struct most_channel *c;
+
+       if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
+               pr_err("Bad interface or index out of range\n");
+               return -EINVAL;
+       }
+       c = iface->p->channel[id];
+       if (unlikely(!c))
+               return -EINVAL;
+
+       mutex_lock(&c->start_mutex);
+       if (c->pipe0.refs + c->pipe1.refs >= 2)
+               goto out;
+
+       if (c->hdm_enqueue_task)
+               kthread_stop(c->hdm_enqueue_task);
+       c->hdm_enqueue_task = NULL;
+
+       if (iface->mod)
+               module_put(iface->mod);
+
+       c->is_poisoned = true;
+       if (c->iface->poison_channel(c->iface, c->channel_id)) {
+               pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id,
+                      c->iface->description);
+               mutex_unlock(&c->start_mutex);
+               return -EAGAIN;
+       }
+       flush_trash_fifo(c);
+       flush_channel_fifos(c);
+
+#ifdef CMPL_INTERRUPTIBLE
+       if (wait_for_completion_interruptible(&c->cleanup)) {
+               pr_info("Interrupted while clean up ch %d\n", c->channel_id);
+               mutex_unlock(&c->start_mutex);
+               return -EINTR;
+       }
+#else
+       wait_for_completion(&c->cleanup);
+#endif
+       c->is_poisoned = false;
+
+out:
+       if (comp == c->pipe0.comp)
+               c->pipe0.refs--;
+       if (comp == c->pipe1.comp)
+               c->pipe1.refs--;
+       mutex_unlock(&c->start_mutex);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(most_stop_channel);
+
+/**
+ * most_register_component - registers a driver component with the core
+ * @comp: driver component
+ */
+int most_register_component(struct core_component *comp)
+{
+       if (!comp) {
+               pr_err("Bad component\n");
+               return -EINVAL;
+       }
+       list_add_tail(&comp->list, &mc.comp_list);
+       pr_info("registered new core component %s\n", comp->name);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(most_register_component);
+
+static int disconnect_channels(struct device *dev, void *data)
+{
+       struct most_interface *iface;
+       struct most_channel *c, *tmp;
+       struct core_component *comp = data;
+
+       iface = to_most_interface(dev);
+       list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) {
+               if (c->pipe0.comp == comp || c->pipe1.comp == comp)
+                       comp->disconnect_channel(c->iface, c->channel_id);
+               if (c->pipe0.comp == comp)
+                       c->pipe0.comp = NULL;
+               if (c->pipe1.comp == comp)
+                       c->pipe1.comp = NULL;
+       }
+       return 0;
+}
+
+/**
+ * most_deregister_component - deregisters a driver component with the core
+ * @comp: driver component
+ */
+int most_deregister_component(struct core_component *comp)
+{
+       if (!comp) {
+               pr_err("Bad component\n");
+               return -EINVAL;
+       }
+
+       bus_for_each_dev(&mc.bus, NULL, comp, disconnect_channels);
+       list_del(&comp->list);
+       pr_info("deregistering component %s\n", comp->name);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(most_deregister_component);
+
+static void release_interface(struct device *dev)
+{
+       pr_info("releasing interface dev %s...\n", dev_name(dev));
+}
+
+static void release_channel(struct device *dev)
+{
+       pr_info("releasing channel dev %s...\n", dev_name(dev));
+}
+
+/**
+ * most_register_interface - registers an interface with core
+ * @iface: device interface
+ *
+ * Allocates and initializes a new interface instance and all of its channels.
+ * Returns a pointer to kobject or an error pointer.
+ */
+int most_register_interface(struct most_interface *iface)
+{
+       unsigned int i;
+       int id;
+       struct most_channel *c;
+
+       if (!iface || !iface->enqueue || !iface->configure ||
+           !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) {
+               pr_err("Bad interface or channel overflow\n");
+               return -EINVAL;
+       }
+
+       id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL);
+       if (id < 0) {
+               pr_info("Failed to alloc mdev ID\n");
+               return id;
+       }
+
+       iface->p = kzalloc(sizeof(*iface->p), GFP_KERNEL);
+       if (!iface->p) {
+               pr_info("Failed to allocate interface instance\n");
+               ida_simple_remove(&mdev_id, id);
+               return -ENOMEM;
+       }
+
+       INIT_LIST_HEAD(&iface->p->channel_list);
+       iface->p->dev_id = id;
+       snprintf(iface->p->name, STRING_SIZE, "mdev%d", id);
+       iface->dev.init_name = iface->p->name;
+       iface->dev.bus = &mc.bus;
+       iface->dev.parent = &mc.dev;
+       iface->dev.groups = interface_attr_groups;
+       iface->dev.release = release_interface;
+       if (device_register(&iface->dev)) {
+               pr_err("registering iface->dev failed\n");
+               kfree(iface->p);
+               ida_simple_remove(&mdev_id, id);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < iface->num_channels; i++) {
+               const char *name_suffix = iface->channel_vector[i].name_suffix;
+
+               c = kzalloc(sizeof(*c), GFP_KERNEL);
+               if (!c)
+                       goto free_instance;
+               if (!name_suffix)
+                       snprintf(c->name, STRING_SIZE, "ch%d", i);
+               else
+                       snprintf(c->name, STRING_SIZE, "%s", name_suffix);
+               c->dev.init_name = c->name;
+               c->dev.parent = &iface->dev;
+               c->dev.groups = channel_attr_groups;
+               c->dev.release = release_channel;
+               if (device_register(&c->dev)) {
+                       pr_err("registering c->dev failed\n");
+                       goto free_instance_nodev;
+               }
+               iface->p->channel[i] = c;
+               c->is_starving = 0;
+               c->iface = iface;
+               c->channel_id = i;
+               c->keep_mbo = false;
+               c->enqueue_halt = false;
+               c->is_poisoned = false;
+               c->cfg.direction = 0;
+               c->cfg.data_type = 0;
+               c->cfg.num_buffers = 0;
+               c->cfg.buffer_size = 0;
+               c->cfg.subbuffer_size = 0;
+               c->cfg.packets_per_xact = 0;
+               spin_lock_init(&c->fifo_lock);
+               INIT_LIST_HEAD(&c->fifo);
+               INIT_LIST_HEAD(&c->trash_fifo);
+               INIT_LIST_HEAD(&c->halt_fifo);
+               init_completion(&c->cleanup);
+               atomic_set(&c->mbo_ref, 0);
+               mutex_init(&c->start_mutex);
+               mutex_init(&c->nq_mutex);
+               list_add_tail(&c->list, &iface->p->channel_list);
+       }
+       pr_info("registered new device mdev%d (%s)\n",
+               id, iface->description);
+       return 0;
+
+free_instance_nodev:
+       kfree(c);
+
+free_instance:
+       while (i > 0) {
+               c = iface->p->channel[--i];
+               device_unregister(&c->dev);
+               kfree(c);
+       }
+       kfree(iface->p);
+       device_unregister(&iface->dev);
+       ida_simple_remove(&mdev_id, id);
+       return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(most_register_interface);
+
+/**
+ * most_deregister_interface - deregisters an interface with core
+ * @iface: device interface
+ *
+ * Before removing an interface instance from the list, all running
+ * channels are stopped and poisoned.
+ */
+void most_deregister_interface(struct most_interface *iface)
+{
+       int i;
+       struct most_channel *c;
+
+       pr_info("deregistering device %s (%s)\n", dev_name(&iface->dev), iface->description);
+       for (i = 0; i < iface->num_channels; i++) {
+               c = iface->p->channel[i];
+               if (c->pipe0.comp)
+                       c->pipe0.comp->disconnect_channel(c->iface,
+                                                       c->channel_id);
+               if (c->pipe1.comp)
+                       c->pipe1.comp->disconnect_channel(c->iface,
+                                                       c->channel_id);
+               c->pipe0.comp = NULL;
+               c->pipe1.comp = NULL;
+               list_del(&c->list);
+               device_unregister(&c->dev);
+               kfree(c);
+       }
+
+       ida_simple_remove(&mdev_id, iface->p->dev_id);
+       kfree(iface->p);
+       device_unregister(&iface->dev);
+}
+EXPORT_SYMBOL_GPL(most_deregister_interface);
+
+/**
+ * most_stop_enqueue - prevents core from enqueueing MBOs
+ * @iface: pointer to interface
+ * @id: channel id
+ *
+ * This is called by an HDM that _cannot_ attend to its duties and
+ * is imminent to get run over by the core. The core is not going to
+ * enqueue any further packets unless the flagging HDM calls
+ * most_resume enqueue().
+ */
+void most_stop_enqueue(struct most_interface *iface, int id)
+{
+       struct most_channel *c = iface->p->channel[id];
+
+       if (!c)
+               return;
+
+       mutex_lock(&c->nq_mutex);
+       c->enqueue_halt = true;
+       mutex_unlock(&c->nq_mutex);
+}
+EXPORT_SYMBOL_GPL(most_stop_enqueue);
+
+/**
+ * most_resume_enqueue - allow core to enqueue MBOs again
+ * @iface: pointer to interface
+ * @id: channel id
+ *
+ * This clears the enqueue halt flag and enqueues all MBOs currently
+ * sitting in the wait fifo.
+ */
+void most_resume_enqueue(struct most_interface *iface, int id)
+{
+       struct most_channel *c = iface->p->channel[id];
+
+       if (!c)
+               return;
+
+       mutex_lock(&c->nq_mutex);
+       c->enqueue_halt = false;
+       mutex_unlock(&c->nq_mutex);
+
+       wake_up_interruptible(&c->hdm_fifo_wq);
+}
+EXPORT_SYMBOL_GPL(most_resume_enqueue);
+
+static void release_most_sub(struct device *dev)
+{
+       pr_info("releasing most_subsystem\n");
+}
+
+static int __init most_init(void)
+{
+       int err;
+
+       pr_info("init()\n");
+       INIT_LIST_HEAD(&mc.comp_list);
+       ida_init(&mdev_id);
+
+       mc.bus.name = "most",
+       mc.bus.match = most_match,
+       mc.drv.name = "most_core",
+       mc.drv.bus = &mc.bus,
+       mc.drv.groups = mc_attr_groups;
+
+       err = bus_register(&mc.bus);
+       if (err) {
+               pr_info("Cannot register most bus\n");
+               return err;
+       }
+       err = driver_register(&mc.drv);
+       if (err) {
+               pr_info("Cannot register core driver\n");
+               goto exit_bus;
+       }
+       mc.dev.init_name = "most_bus";
+       mc.dev.release = release_most_sub;
+       if (device_register(&mc.dev)) {
+               err = -ENOMEM;
+               goto exit_driver;
+       }
+
+       return 0;
+
+exit_driver:
+       driver_unregister(&mc.drv);
+exit_bus:
+       bus_unregister(&mc.bus);
+       return err;
+}
+
+static void __exit most_exit(void)
+{
+       pr_info("exit core module\n");
+       device_unregister(&mc.dev);
+       driver_unregister(&mc.drv);
+       bus_unregister(&mc.bus);
+       ida_destroy(&mdev_id);
+}
+
+module_init(most_init);
+module_exit(most_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("Core module of stacked MOST Linux driver");
diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
new file mode 100644 (file)
index 0000000..74a2916
--- /dev/null
@@ -0,0 +1,318 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * most.h - API for component and adapter drivers
+ *
+ * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#ifndef __MOST_CORE_H__
+#define __MOST_CORE_H__
+
+#include <linux/types.h>
+#include <linux/device.h>
+
+struct module;
+struct interface_private;
+
+/**
+ * Interface type
+ */
+enum most_interface_type {
+       ITYPE_LOOPBACK = 1,
+       ITYPE_I2C,
+       ITYPE_I2S,
+       ITYPE_TSI,
+       ITYPE_HBI,
+       ITYPE_MEDIALB_DIM,
+       ITYPE_MEDIALB_DIM2,
+       ITYPE_USB,
+       ITYPE_PCIE
+};
+
+/**
+ * Channel direction.
+ */
+enum most_channel_direction {
+       MOST_CH_RX = 1 << 0,
+       MOST_CH_TX = 1 << 1,
+};
+
+/**
+ * Channel data type.
+ */
+enum most_channel_data_type {
+       MOST_CH_CONTROL = 1 << 0,
+       MOST_CH_ASYNC = 1 << 1,
+       MOST_CH_ISOC = 1 << 2,
+       MOST_CH_SYNC = 1 << 5,
+};
+
+enum mbo_status_flags {
+       /* MBO was processed successfully (data was send or received )*/
+       MBO_SUCCESS = 0,
+       /* The MBO contains wrong or missing information.  */
+       MBO_E_INVAL,
+       /* MBO was completed as HDM Channel will be closed */
+       MBO_E_CLOSE,
+};
+
+/**
+ * struct most_channel_capability - Channel capability
+ * @direction: Supported channel directions.
+ * The value is bitwise OR-combination of the values from the
+ * enumeration most_channel_direction. Zero is allowed value and means
+ * "channel may not be used".
+ * @data_type: Supported channel data types.
+ * The value is bitwise OR-combination of the values from the
+ * enumeration most_channel_data_type. Zero is allowed value and means
+ * "channel may not be used".
+ * @num_buffers_packet: Maximum number of buffers supported by this channel
+ * for packet data types (Async,Control,QoS)
+ * @buffer_size_packet: Maximum buffer size supported by this channel
+ * for packet data types (Async,Control,QoS)
+ * @num_buffers_streaming: Maximum number of buffers supported by this channel
+ * for streaming data types (Sync,AV Packetized)
+ * @buffer_size_streaming: Maximum buffer size supported by this channel
+ * for streaming data types (Sync,AV Packetized)
+ * @name_suffix: Optional suffix providean by an HDM that is attached to the
+ * regular channel name.
+ *
+ * Describes the capabilities of a MOST channel like supported Data Types
+ * and directions. This information is provided by an HDM for the MostCore.
+ *
+ * The Core creates read only sysfs attribute files in
+ * /sys/devices/most/mdev#/<channel>/ with the
+ * following attributes:
+ *     -available_directions
+ *     -available_datatypes
+ *     -number_of_packet_buffers
+ *     -number_of_stream_buffers
+ *     -size_of_packet_buffer
+ *     -size_of_stream_buffer
+ * where content of each file is a string with all supported properties of this
+ * very channel attribute.
+ */
+struct most_channel_capability {
+       u16 direction;
+       u16 data_type;
+       u16 num_buffers_packet;
+       u16 buffer_size_packet;
+       u16 num_buffers_streaming;
+       u16 buffer_size_streaming;
+       const char *name_suffix;
+};
+
+/**
+ * struct most_channel_config - stores channel configuration
+ * @direction: direction of the channel
+ * @data_type: data type travelling over this channel
+ * @num_buffers: number of buffers
+ * @buffer_size: size of a buffer for AIM.
+ * Buffer size may be cutted down by HDM in a configure callback
+ * to match to a given interface and channel type.
+ * @extra_len: additional buffer space for internal HDM purposes like padding.
+ * May be set by HDM in a configure callback if needed.
+ * @subbuffer_size: size of a subbuffer
+ * @packets_per_xact: number of MOST frames that are packet inside one USB
+ *                   packet. This is USB specific
+ *
+ * Describes the configuration for a MOST channel. This information is
+ * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a
+ * parameter of the "configure" function call.
+ */
+struct most_channel_config {
+       enum most_channel_direction direction;
+       enum most_channel_data_type data_type;
+       u16 num_buffers;
+       u16 buffer_size;
+       u16 extra_len;
+       u16 subbuffer_size;
+       u16 packets_per_xact;
+};
+
+/*
+ * struct mbo - MOST Buffer Object.
+ * @context: context for core completion handler
+ * @priv: private data for HDM
+ *
+ *     public: documented fields that are used for the communications
+ *     between MostCore and HDMs
+ *
+ * @list: list head for use by the mbo's current owner
+ * @ifp: (in) associated interface instance
+ * @num_buffers_ptr: amount of pool buffers
+ * @hdm_channel_id: (in) HDM channel instance
+ * @virt_address: (in) kernel virtual address of the buffer
+ * @bus_address: (in) bus address of the buffer
+ * @buffer_length: (in) buffer payload length
+ * @processed_length: (out) processed length
+ * @status: (out) transfer status
+ * @complete: (in) completion routine
+ *
+ * The core allocates and initializes the MBO.
+ *
+ * The HDM receives MBO for transfer from the core with the call to enqueue().
+ * The HDM copies the data to- or from the buffer depending on configured
+ * channel direction, set "processed_length" and "status" and completes
+ * the transfer procedure by calling the completion routine.
+ *
+ * Finally, the MBO is being deallocated or recycled for further
+ * transfers of the same or a different HDM.
+ *
+ * Directions of usage:
+ * The core driver should never access any MBO fields (even if marked
+ * as "public") while the MBO is owned by an HDM. The ownership starts with
+ * the call of enqueue() and ends with the call of its complete() routine.
+ *
+ *                                     II.
+ * Every HDM attached to the core driver _must_ ensure that it returns any MBO
+ * it owns (due to a previous call to enqueue() by the core driver) before it
+ * de-registers an interface or gets unloaded from the kernel. If this direction
+ * is violated memory leaks will occur, since the core driver does _not_ track
+ * MBOs it is currently not in control of.
+ *
+ */
+struct mbo {
+       void *context;
+       void *priv;
+       struct list_head list;
+       struct most_interface *ifp;
+       int *num_buffers_ptr;
+       u16 hdm_channel_id;
+       void *virt_address;
+       dma_addr_t bus_address;
+       u16 buffer_length;
+       u16 processed_length;
+       enum mbo_status_flags status;
+       void (*complete)(struct mbo *);
+};
+
+/**
+ * Interface instance description.
+ *
+ * Describes an interface of a MOST device the core driver is bound to.
+ * This structure is allocated and initialized in the HDM. MostCore may not
+ * modify this structure.
+ *
+ * @dev: the actual device
+ * @mod: module
+ * @interface Interface type. \sa most_interface_type.
+ * @description PRELIMINARY.
+ *   Unique description of the device instance from point of view of the
+ *   interface in free text form (ASCII).
+ *   It may be a hexadecimal presentation of the memory address for the MediaLB
+ *   IP or USB device ID with USB properties for USB interface, etc.
+ * @num_channels Number of channels and size of the channel_vector.
+ * @channel_vector Properties of the channels.
+ *   Array index represents channel ID by the driver.
+ * @configure Callback to change data type for the channel of the
+ *   interface instance. May be zero if the instance of the interface is not
+ *   configurable. Parameter channel_config describes direction and data
+ *   type for the channel, configured by the higher level. The content of
+ * @enqueue Delivers MBO to the HDM for processing.
+ *   After HDM completes Rx- or Tx- operation the processed MBO shall
+ *   be returned back to the MostCore using completion routine.
+ *   The reason to get the MBO delivered from the MostCore after the channel
+ *   is poisoned is the re-opening of the channel by the application.
+ *   In this case the HDM shall hold MBOs and service the channel as usual.
+ *   The HDM must be able to hold at least one MBO for each channel.
+ *   The callback returns a negative value on error, otherwise 0.
+ * @poison_channel Informs HDM about closing the channel. The HDM shall
+ *   cancel all transfers and synchronously or asynchronously return
+ *   all enqueued for this channel MBOs using the completion routine.
+ *   The callback returns a negative value on error, otherwise 0.
+ * @request_netinfo: triggers retrieving of network info from the HDM by
+ *   means of "Message exchange over MDP/MEP"
+ *   The call of the function request_netinfo with the parameter on_netinfo as
+ *   NULL prohibits use of the previously obtained function pointer.
+ * @priv Private field used by mostcore to store context information.
+ */
+struct most_interface {
+       struct device dev;
+       struct module *mod;
+       enum most_interface_type interface;
+       const char *description;
+       unsigned int num_channels;
+       struct most_channel_capability *channel_vector;
+       int (*configure)(struct most_interface *iface, int channel_idx,
+                        struct most_channel_config *channel_config);
+       int (*enqueue)(struct most_interface *iface, int channel_idx,
+                      struct mbo *mbo);
+       int (*poison_channel)(struct most_interface *iface, int channel_idx);
+       void (*request_netinfo)(struct most_interface *iface, int channel_idx,
+                               void (*on_netinfo)(struct most_interface *iface,
+                                                  unsigned char link_stat,
+                                                  unsigned char *mac_addr));
+       void *priv;
+       struct interface_private *p;
+};
+
+#define to_most_interface(d) container_of(d, struct most_interface, dev)
+
+/**
+ * struct core_component - identifies a loadable component for the mostcore
+ * @list: list_head
+ * @name: component name
+ * @probe_channel: function for core to notify driver about channel connection
+ * @disconnect_channel: callback function to disconnect a certain channel
+ * @rx_completion: completion handler for received packets
+ * @tx_completion: completion handler for transmitted packets
+ */
+struct core_component {
+       struct list_head list;
+       const char *name;
+       int (*probe_channel)(struct most_interface *iface, int channel_idx,
+                            struct most_channel_config *cfg, char *name);
+       int (*disconnect_channel)(struct most_interface *iface,
+                                 int channel_idx);
+       int (*rx_completion)(struct mbo *mbo);
+       int (*tx_completion)(struct most_interface *iface, int channel_idx);
+};
+
+/**
+ * most_register_interface - Registers instance of the interface.
+ * @iface: Pointer to the interface instance description.
+ *
+ * Returns a pointer to the kobject of the generated instance.
+ *
+ * Note: HDM has to ensure that any reference held on the kobj is
+ * released before deregistering the interface.
+ */
+int most_register_interface(struct most_interface *iface);
+
+/**
+ * Deregisters instance of the interface.
+ * @intf_instance Pointer to the interface instance description.
+ */
+void most_deregister_interface(struct most_interface *iface);
+void most_submit_mbo(struct mbo *mbo);
+
+/**
+ * most_stop_enqueue - prevents core from enqueing MBOs
+ * @iface: pointer to interface
+ * @channel_idx: channel index
+ */
+void most_stop_enqueue(struct most_interface *iface, int channel_idx);
+
+/**
+ * most_resume_enqueue - allow core to enqueue MBOs again
+ * @iface: pointer to interface
+ * @channel_idx: channel index
+ *
+ * This clears the enqueue halt flag and enqueues all MBOs currently
+ * in wait fifo.
+ */
+void most_resume_enqueue(struct most_interface *iface, int channel_idx);
+int most_register_component(struct core_component *comp);
+int most_deregister_component(struct core_component *comp);
+struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
+                        struct core_component *comp);
+void most_put_mbo(struct mbo *mbo);
+int channel_has_mbo(struct most_interface *iface, int channel_idx,
+                   struct core_component *comp);
+int most_start_channel(struct most_interface *iface, int channel_idx,
+                      struct core_component *comp);
+int most_stop_channel(struct most_interface *iface, int channel_idx,
+                     struct core_component *comp);
+
+#endif /* MOST_CORE_H_ */
diff --git a/drivers/staging/most/dim2/Kconfig b/drivers/staging/most/dim2/Kconfig
new file mode 100644 (file)
index 0000000..e39c4e5
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# MediaLB configuration
+#
+
+config MOST_DIM2
+       tristate "DIM2"
+       depends on HAS_IOMEM
+
+       ---help---
+         Say Y here if you want to connect via MediaLB to network transceiver.
+         This device driver is platform dependent and needs an additional
+         platform driver to be installed. For more information contact
+         maintainer of this driver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called most_dim2.
diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile
new file mode 100644 (file)
index 0000000..66676f5
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_DIM2) += most_dim2.o
+
+most_dim2-objs := dim2.o hal.o sysfs.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c
new file mode 100644 (file)
index 0000000..f9bc7de
--- /dev/null
@@ -0,0 +1,915 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dim2.c - MediaLB DIM2 Hardware Dependent Module
+ *
+ * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+
+#include "most/core.h"
+#include "hal.h"
+#include "dim2.h"
+#include "errors.h"
+#include "sysfs.h"
+
+#define DMA_CHANNELS (32 - 1)  /* channel 0 is a system channel */
+
+#define MAX_BUFFERS_PACKET      32
+#define MAX_BUFFERS_STREAMING   32
+#define MAX_BUF_SIZE_PACKET     2048
+#define MAX_BUF_SIZE_STREAMING  (8 * 1024)
+
+/* command line parameter to select clock speed */
+static char *clock_speed;
+module_param(clock_speed, charp, 0000);
+MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed");
+
+/*
+ * The parameter representing the number of frames per sub-buffer for
+ * synchronous channels.  Valid values: [0 .. 6].
+ *
+ * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per
+ * sub-buffer 1, 2, 4, 8, 16, 32, 64.
+ */
+static u8 fcnt = 4;  /* (1 << fcnt) frames per subbuffer */
+module_param(fcnt, byte, 0000);
+MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2");
+
+static DEFINE_SPINLOCK(dim_lock);
+
+static void dim2_tasklet_fn(unsigned long data);
+static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0);
+
+/**
+ * struct hdm_channel - private structure to keep channel specific data
+ * @is_initialized: identifier to know whether the channel is initialized
+ * @ch: HAL specific channel data
+ * @pending_list: list to keep MBO's before starting transfer
+ * @started_list: list to keep MBO's after starting transfer
+ * @direction: channel direction (TX or RX)
+ * @data_type: channel data type
+ */
+struct hdm_channel {
+       char name[sizeof "caNNN"];
+       bool is_initialized;
+       struct dim_channel ch;
+       struct list_head pending_list;  /* before dim_enqueue_buffer() */
+       struct list_head started_list;  /* after dim_enqueue_buffer() */
+       enum most_channel_direction direction;
+       enum most_channel_data_type data_type;
+};
+
+/**
+ * struct dim2_hdm - private structure to keep interface specific data
+ * @hch: an array of channel specific data
+ * @most_iface: most interface structure
+ * @capabilities: an array of channel capability data
+ * @io_base: I/O register base address
+ * @clk_speed: user selectable (through command line parameter) clock speed
+ * @netinfo_task: thread to deliver network status
+ * @netinfo_waitq: waitq for the thread to sleep
+ * @deliver_netinfo: to identify whether network status received
+ * @mac_addrs: INIC mac address
+ * @link_state: network link state
+ * @atx_idx: index of async tx channel
+ */
+struct dim2_hdm {
+       struct device dev;
+       struct hdm_channel hch[DMA_CHANNELS];
+       struct most_channel_capability capabilities[DMA_CHANNELS];
+       struct most_interface most_iface;
+       char name[16 + sizeof "dim2-"];
+       void __iomem *io_base;
+       int clk_speed;
+       struct task_struct *netinfo_task;
+       wait_queue_head_t netinfo_waitq;
+       int deliver_netinfo;
+       unsigned char mac_addrs[6];
+       unsigned char link_state;
+       int atx_idx;
+       struct medialb_bus bus;
+       void (*on_netinfo)(struct most_interface *most_iface,
+                          unsigned char link_state, unsigned char *addrs);
+};
+
+#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface)
+
+/* Macro to identify a network status message */
+#define PACKET_IS_NET_INFO(p)  \
+       (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \
+        ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A))
+
+bool dim2_sysfs_get_state_cb(void)
+{
+       bool state;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       state = dim_get_lock_state();
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       return state;
+}
+
+/**
+ * dimcb_io_read - callback from HAL to read an I/O register
+ * @ptr32: register address
+ */
+u32 dimcb_io_read(u32 __iomem *ptr32)
+{
+       return readl(ptr32);
+}
+
+/**
+ * dimcb_io_write - callback from HAL to write value to an I/O register
+ * @ptr32: register address
+ * @value: value to write
+ */
+void dimcb_io_write(u32 __iomem *ptr32, u32 value)
+{
+       writel(value, ptr32);
+}
+
+/**
+ * dimcb_on_error - callback from HAL to report miscommunication between
+ * HDM and HAL
+ * @error_id: Error ID
+ * @error_message: Error message. Some text in a free format
+ */
+void dimcb_on_error(u8 error_id, const char *error_message)
+{
+       pr_err("%s: error_id - %d, error_message - %s\n", __func__, error_id,
+              error_message);
+}
+
+/**
+ * startup_dim - initialize the dim2 interface
+ * @pdev: platform device
+ *
+ * Get the value of command line parameter "clock_speed" if given or use the
+ * default value, enable the clock and PLL, and initialize the dim2 interface.
+ */
+static int startup_dim(struct platform_device *pdev)
+{
+       struct dim2_hdm *dev = platform_get_drvdata(pdev);
+       struct dim2_platform_data *pdata = pdev->dev.platform_data;
+       u8 hal_ret;
+
+       dev->clk_speed = -1;
+
+       if (clock_speed) {
+               if (!strcmp(clock_speed, "256fs"))
+                       dev->clk_speed = CLK_256FS;
+               else if (!strcmp(clock_speed, "512fs"))
+                       dev->clk_speed = CLK_512FS;
+               else if (!strcmp(clock_speed, "1024fs"))
+                       dev->clk_speed = CLK_1024FS;
+               else if (!strcmp(clock_speed, "2048fs"))
+                       dev->clk_speed = CLK_2048FS;
+               else if (!strcmp(clock_speed, "3072fs"))
+                       dev->clk_speed = CLK_3072FS;
+               else if (!strcmp(clock_speed, "4096fs"))
+                       dev->clk_speed = CLK_4096FS;
+               else if (!strcmp(clock_speed, "6144fs"))
+                       dev->clk_speed = CLK_6144FS;
+               else if (!strcmp(clock_speed, "8192fs"))
+                       dev->clk_speed = CLK_8192FS;
+       }
+
+       if (dev->clk_speed == -1) {
+               pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n");
+               dev->clk_speed = CLK_3072FS;
+       } else {
+               pr_info("Selected clock speed: %s\n", clock_speed);
+       }
+       if (pdata && pdata->init) {
+               int ret = pdata->init(pdata, dev->io_base, dev->clk_speed);
+
+               if (ret)
+                       return ret;
+       }
+
+       pr_info("sync: num of frames per sub-buffer: %u\n", fcnt);
+       hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt);
+       if (hal_ret != DIM_NO_ERROR) {
+               pr_err("dim_startup failed: %d\n", hal_ret);
+               if (pdata && pdata->destroy)
+                       pdata->destroy(pdata);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/**
+ * try_start_dim_transfer - try to transfer a buffer on a channel
+ * @hdm_ch: channel specific data
+ *
+ * Transfer a buffer from pending_list if the channel is ready
+ */
+static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
+{
+       u16 buf_size;
+       struct list_head *head = &hdm_ch->pending_list;
+       struct mbo *mbo;
+       unsigned long flags;
+       struct dim_ch_state_t st;
+
+       BUG_ON(!hdm_ch);
+       BUG_ON(!hdm_ch->is_initialized);
+
+       spin_lock_irqsave(&dim_lock, flags);
+       if (list_empty(head)) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               return -EAGAIN;
+       }
+
+       if (!dim_get_channel_state(&hdm_ch->ch, &st)->ready) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               return -EAGAIN;
+       }
+
+       mbo = list_first_entry(head, struct mbo, list);
+       buf_size = mbo->buffer_length;
+
+       if (dim_dbr_space(&hdm_ch->ch) < buf_size) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               return -EAGAIN;
+       }
+
+       BUG_ON(mbo->bus_address == 0);
+       if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) {
+               list_del(head->next);
+               spin_unlock_irqrestore(&dim_lock, flags);
+               mbo->processed_length = 0;
+               mbo->status = MBO_E_INVAL;
+               mbo->complete(mbo);
+               return -EFAULT;
+       }
+
+       list_move_tail(head->next, &hdm_ch->started_list);
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       return 0;
+}
+
+/**
+ * deliver_netinfo_thread - thread to deliver network status to mostcore
+ * @data: private data
+ *
+ * Wait for network status and deliver it to mostcore once it is received
+ */
+static int deliver_netinfo_thread(void *data)
+{
+       struct dim2_hdm *dev = data;
+
+       while (!kthread_should_stop()) {
+               wait_event_interruptible(dev->netinfo_waitq,
+                                        dev->deliver_netinfo ||
+                                        kthread_should_stop());
+
+               if (dev->deliver_netinfo) {
+                       dev->deliver_netinfo--;
+                       if (dev->on_netinfo) {
+                               dev->on_netinfo(&dev->most_iface,
+                                               dev->link_state,
+                                               dev->mac_addrs);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * retrieve_netinfo - retrieve network status from received buffer
+ * @dev: private data
+ * @mbo: received MBO
+ *
+ * Parse the message in buffer and get node address, link state, MAC address.
+ * Wake up a thread to deliver this status to mostcore
+ */
+static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo)
+{
+       u8 *data = mbo->virt_address;
+
+       pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]);
+       dev->link_state = data[18];
+       pr_info("NIState: %d\n", dev->link_state);
+       memcpy(dev->mac_addrs, data + 19, 6);
+       dev->deliver_netinfo++;
+       wake_up_interruptible(&dev->netinfo_waitq);
+}
+
+/**
+ * service_done_flag - handle completed buffers
+ * @dev: private data
+ * @ch_idx: channel index
+ *
+ * Return back the completed buffers to mostcore, using completion callback
+ */
+static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
+{
+       struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+       struct dim_ch_state_t st;
+       struct list_head *head;
+       struct mbo *mbo;
+       int done_buffers;
+       unsigned long flags;
+       u8 *data;
+
+       BUG_ON(!hdm_ch);
+       BUG_ON(!hdm_ch->is_initialized);
+
+       spin_lock_irqsave(&dim_lock, flags);
+
+       done_buffers = dim_get_channel_state(&hdm_ch->ch, &st)->done_buffers;
+       if (!done_buffers) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               return;
+       }
+
+       if (!dim_detach_buffers(&hdm_ch->ch, done_buffers)) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       head = &hdm_ch->started_list;
+
+       while (done_buffers) {
+               spin_lock_irqsave(&dim_lock, flags);
+               if (list_empty(head)) {
+                       spin_unlock_irqrestore(&dim_lock, flags);
+                       pr_crit("hard error: started_mbo list is empty whereas DIM2 has sent buffers\n");
+                       break;
+               }
+
+               mbo = list_first_entry(head, struct mbo, list);
+               list_del(head->next);
+               spin_unlock_irqrestore(&dim_lock, flags);
+
+               data = mbo->virt_address;
+
+               if (hdm_ch->data_type == MOST_CH_ASYNC &&
+                   hdm_ch->direction == MOST_CH_RX &&
+                   PACKET_IS_NET_INFO(data)) {
+                       retrieve_netinfo(dev, mbo);
+
+                       spin_lock_irqsave(&dim_lock, flags);
+                       list_add_tail(&mbo->list, &hdm_ch->pending_list);
+                       spin_unlock_irqrestore(&dim_lock, flags);
+               } else {
+                       if (hdm_ch->data_type == MOST_CH_CONTROL ||
+                           hdm_ch->data_type == MOST_CH_ASYNC) {
+                               u32 const data_size =
+                                       (u32)data[0] * 256 + data[1] + 2;
+
+                               mbo->processed_length =
+                                       min_t(u32, data_size,
+                                             mbo->buffer_length);
+                       } else {
+                               mbo->processed_length = mbo->buffer_length;
+                       }
+                       mbo->status = MBO_SUCCESS;
+                       mbo->complete(mbo);
+               }
+
+               done_buffers--;
+       }
+}
+
+static struct dim_channel **get_active_channels(struct dim2_hdm *dev,
+                                               struct dim_channel **buffer)
+{
+       int idx = 0;
+       int ch_idx;
+
+       for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
+               if (dev->hch[ch_idx].is_initialized)
+                       buffer[idx++] = &dev->hch[ch_idx].ch;
+       }
+       buffer[idx++] = NULL;
+
+       return buffer;
+}
+
+static irqreturn_t dim2_mlb_isr(int irq, void *_dev)
+{
+       struct dim2_hdm *dev = _dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       dim_service_mlb_int_irq();
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       if (dev->atx_idx >= 0 && dev->hch[dev->atx_idx].is_initialized)
+               while (!try_start_dim_transfer(dev->hch + dev->atx_idx))
+                       continue;
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * dim2_tasklet_fn - tasklet function
+ * @data: private data
+ *
+ * Service each initialized channel, if needed
+ */
+static void dim2_tasklet_fn(unsigned long data)
+{
+       struct dim2_hdm *dev = (struct dim2_hdm *)data;
+       unsigned long flags;
+       int ch_idx;
+
+       for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
+               if (!dev->hch[ch_idx].is_initialized)
+                       continue;
+
+               spin_lock_irqsave(&dim_lock, flags);
+               dim_service_channel(&dev->hch[ch_idx].ch);
+               spin_unlock_irqrestore(&dim_lock, flags);
+
+               service_done_flag(dev, ch_idx);
+               while (!try_start_dim_transfer(dev->hch + ch_idx))
+                       continue;
+       }
+}
+
+/**
+ * dim2_ahb_isr - interrupt service routine
+ * @irq: irq number
+ * @_dev: private data
+ *
+ * Acknowledge the interrupt and schedule a tasklet to service channels.
+ * Return IRQ_HANDLED.
+ */
+static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
+{
+       struct dim2_hdm *dev = _dev;
+       struct dim_channel *buffer[DMA_CHANNELS + 1];
+       unsigned long flags;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       dim_service_ahb_int_irq(get_active_channels(dev, buffer));
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       dim2_tasklet.data = (unsigned long)dev;
+       tasklet_schedule(&dim2_tasklet);
+       return IRQ_HANDLED;
+}
+
+/**
+ * complete_all_mbos - complete MBO's in a list
+ * @head: list head
+ *
+ * Delete all the entries in list and return back MBO's to mostcore using
+ * completion call back.
+ */
+static void complete_all_mbos(struct list_head *head)
+{
+       unsigned long flags;
+       struct mbo *mbo;
+
+       for (;;) {
+               spin_lock_irqsave(&dim_lock, flags);
+               if (list_empty(head)) {
+                       spin_unlock_irqrestore(&dim_lock, flags);
+                       break;
+               }
+
+               mbo = list_first_entry(head, struct mbo, list);
+               list_del(head->next);
+               spin_unlock_irqrestore(&dim_lock, flags);
+
+               mbo->processed_length = 0;
+               mbo->status = MBO_E_CLOSE;
+               mbo->complete(mbo);
+       }
+}
+
+/**
+ * configure_channel - initialize a channel
+ * @iface: interface the channel belongs to
+ * @channel: channel to be configured
+ * @channel_config: structure that holds the configuration information
+ *
+ * Receives configuration information from mostcore and initialize
+ * the corresponding channel. Return 0 on success, negative on failure.
+ */
+static int configure_channel(struct most_interface *most_iface, int ch_idx,
+                            struct most_channel_config *ccfg)
+{
+       struct dim2_hdm *dev = iface_to_hdm(most_iface);
+       bool const is_tx = ccfg->direction == MOST_CH_TX;
+       u16 const sub_size = ccfg->subbuffer_size;
+       u16 const buf_size = ccfg->buffer_size;
+       u16 new_size;
+       unsigned long flags;
+       u8 hal_ret;
+       int const ch_addr = ch_idx * 2 + 2;
+       struct hdm_channel *const hdm_ch = dev->hch + ch_idx;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+       if (hdm_ch->is_initialized)
+               return -EPERM;
+
+       switch (ccfg->data_type) {
+       case MOST_CH_CONTROL:
+               new_size = dim_norm_ctrl_async_buffer_size(buf_size);
+               if (new_size == 0) {
+                       pr_err("%s: too small buffer size\n", hdm_ch->name);
+                       return -EINVAL;
+               }
+               ccfg->buffer_size = new_size;
+               if (new_size != buf_size)
+                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
+                               hdm_ch->name, buf_size, new_size);
+               spin_lock_irqsave(&dim_lock, flags);
+               hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr,
+                                          is_tx ? new_size * 2 : new_size);
+               break;
+       case MOST_CH_ASYNC:
+               new_size = dim_norm_ctrl_async_buffer_size(buf_size);
+               if (new_size == 0) {
+                       pr_err("%s: too small buffer size\n", hdm_ch->name);
+                       return -EINVAL;
+               }
+               ccfg->buffer_size = new_size;
+               if (new_size != buf_size)
+                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
+                               hdm_ch->name, buf_size, new_size);
+               spin_lock_irqsave(&dim_lock, flags);
+               hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr,
+                                        is_tx ? new_size * 2 : new_size);
+               break;
+       case MOST_CH_ISOC:
+               new_size = dim_norm_isoc_buffer_size(buf_size, sub_size);
+               if (new_size == 0) {
+                       pr_err("%s: invalid sub-buffer size or too small buffer size\n",
+                              hdm_ch->name);
+                       return -EINVAL;
+               }
+               ccfg->buffer_size = new_size;
+               if (new_size != buf_size)
+                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
+                               hdm_ch->name, buf_size, new_size);
+               spin_lock_irqsave(&dim_lock, flags);
+               hal_ret = dim_init_isoc(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+               break;
+       case MOST_CH_SYNC:
+               new_size = dim_norm_sync_buffer_size(buf_size, sub_size);
+               if (new_size == 0) {
+                       pr_err("%s: invalid sub-buffer size or too small buffer size\n",
+                              hdm_ch->name);
+                       return -EINVAL;
+               }
+               ccfg->buffer_size = new_size;
+               if (new_size != buf_size)
+                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
+                               hdm_ch->name, buf_size, new_size);
+               spin_lock_irqsave(&dim_lock, flags);
+               hal_ret = dim_init_sync(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+               break;
+       default:
+               pr_err("%s: configure failed, bad channel type: %d\n",
+                      hdm_ch->name, ccfg->data_type);
+               return -EINVAL;
+       }
+
+       if (hal_ret != DIM_NO_ERROR) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n",
+                      hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx);
+               return -ENODEV;
+       }
+
+       hdm_ch->data_type = ccfg->data_type;
+       hdm_ch->direction = ccfg->direction;
+       hdm_ch->is_initialized = true;
+
+       if (hdm_ch->data_type == MOST_CH_ASYNC &&
+           hdm_ch->direction == MOST_CH_TX &&
+           dev->atx_idx < 0)
+               dev->atx_idx = ch_idx;
+
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       return 0;
+}
+
+/**
+ * enqueue - enqueue a buffer for data transfer
+ * @iface: intended interface
+ * @channel: ID of the channel the buffer is intended for
+ * @mbo: pointer to the buffer object
+ *
+ * Push the buffer into pending_list and try to transfer one buffer from
+ * pending_list. Return 0 on success, negative on failure.
+ */
+static int enqueue(struct most_interface *most_iface, int ch_idx,
+                  struct mbo *mbo)
+{
+       struct dim2_hdm *dev = iface_to_hdm(most_iface);
+       struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+       unsigned long flags;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+       if (!hdm_ch->is_initialized)
+               return -EPERM;
+
+       if (mbo->bus_address == 0)
+               return -EFAULT;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       list_add_tail(&mbo->list, &hdm_ch->pending_list);
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       (void)try_start_dim_transfer(hdm_ch);
+
+       return 0;
+}
+
+/**
+ * request_netinfo - triggers retrieving of network info
+ * @iface: pointer to the interface
+ * @channel_id: corresponding channel ID
+ *
+ * Send a command to INIC which triggers retrieving of network info by means of
+ * "Message exchange over MDP/MEP". Return 0 on success, negative on failure.
+ */
+static void request_netinfo(struct most_interface *most_iface, int ch_idx,
+                           void (*on_netinfo)(struct most_interface *,
+                                              unsigned char, unsigned char *))
+{
+       struct dim2_hdm *dev = iface_to_hdm(most_iface);
+       struct mbo *mbo;
+       u8 *data;
+
+       dev->on_netinfo = on_netinfo;
+       if (!on_netinfo)
+               return;
+
+       if (dev->atx_idx < 0) {
+               pr_err("Async Tx Not initialized\n");
+               return;
+       }
+
+       mbo = most_get_mbo(&dev->most_iface, dev->atx_idx, NULL);
+       if (!mbo)
+               return;
+
+       mbo->buffer_length = 5;
+
+       data = mbo->virt_address;
+
+       data[0] = 0x00; /* PML High byte */
+       data[1] = 0x03; /* PML Low byte */
+       data[2] = 0x02; /* PMHL */
+       data[3] = 0x08; /* FPH */
+       data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */
+
+       most_submit_mbo(mbo);
+}
+
+/**
+ * poison_channel - poison buffers of a channel
+ * @iface: pointer to the interface the channel to be poisoned belongs to
+ * @channel_id: corresponding channel ID
+ *
+ * Destroy a channel and complete all the buffers in both started_list &
+ * pending_list. Return 0 on success, negative on failure.
+ */
+static int poison_channel(struct most_interface *most_iface, int ch_idx)
+{
+       struct dim2_hdm *dev = iface_to_hdm(most_iface);
+       struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+       unsigned long flags;
+       u8 hal_ret;
+       int ret = 0;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+       if (!hdm_ch->is_initialized)
+               return -EPERM;
+
+       tasklet_disable(&dim2_tasklet);
+       spin_lock_irqsave(&dim_lock, flags);
+       hal_ret = dim_destroy_channel(&hdm_ch->ch);
+       hdm_ch->is_initialized = false;
+       if (ch_idx == dev->atx_idx)
+               dev->atx_idx = -1;
+       spin_unlock_irqrestore(&dim_lock, flags);
+       tasklet_enable(&dim2_tasklet);
+       if (hal_ret != DIM_NO_ERROR) {
+               pr_err("HAL Failed to close channel %s\n", hdm_ch->name);
+               ret = -EFAULT;
+       }
+
+       complete_all_mbos(&hdm_ch->started_list);
+       complete_all_mbos(&hdm_ch->pending_list);
+
+       return ret;
+}
+
+/*
+ * dim2_probe - dim2 probe handler
+ * @pdev: platform device structure
+ *
+ * Register the dim2 interface with mostcore and initialize it.
+ * Return 0 on success, negative on failure.
+ */
+static int dim2_probe(struct platform_device *pdev)
+{
+       struct dim2_hdm *dev;
+       struct resource *res;
+       int ret, i;
+       int irq;
+
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       dev->atx_idx = -1;
+
+       platform_set_drvdata(pdev, dev);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       dev->io_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(dev->io_base))
+               return PTR_ERR(dev->io_base);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq);
+               return irq;
+       }
+
+       ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0,
+                              "dim2_ahb0_int", dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq);
+               return ret;
+       }
+
+       irq = platform_get_irq(pdev, 1);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq);
+               return irq;
+       }
+
+       ret = devm_request_irq(&pdev->dev, irq, dim2_mlb_isr, 0,
+                              "dim2_mlb_int", dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq);
+               return ret;
+       }
+
+       init_waitqueue_head(&dev->netinfo_waitq);
+       dev->deliver_netinfo = 0;
+       dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev,
+                                       "dim2_netinfo");
+       if (IS_ERR(dev->netinfo_task))
+               return PTR_ERR(dev->netinfo_task);
+
+       for (i = 0; i < DMA_CHANNELS; i++) {
+               struct most_channel_capability *cap = dev->capabilities + i;
+               struct hdm_channel *hdm_ch = dev->hch + i;
+
+               INIT_LIST_HEAD(&hdm_ch->pending_list);
+               INIT_LIST_HEAD(&hdm_ch->started_list);
+               hdm_ch->is_initialized = false;
+               snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2);
+
+               cap->name_suffix = hdm_ch->name;
+               cap->direction = MOST_CH_RX | MOST_CH_TX;
+               cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
+                                MOST_CH_ISOC | MOST_CH_SYNC;
+               cap->num_buffers_packet = MAX_BUFFERS_PACKET;
+               cap->buffer_size_packet = MAX_BUF_SIZE_PACKET;
+               cap->num_buffers_streaming = MAX_BUFFERS_STREAMING;
+               cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING;
+       }
+
+       {
+               const char *fmt;
+
+               if (sizeof(res->start) == sizeof(long long))
+                       fmt = "dim2-%016llx";
+               else if (sizeof(res->start) == sizeof(long))
+                       fmt = "dim2-%016lx";
+               else
+                       fmt = "dim2-%016x";
+
+               snprintf(dev->name, sizeof(dev->name), fmt, res->start);
+       }
+
+       dev->most_iface.interface = ITYPE_MEDIALB_DIM2;
+       dev->most_iface.description = dev->name;
+       dev->most_iface.num_channels = DMA_CHANNELS;
+       dev->most_iface.channel_vector = dev->capabilities;
+       dev->most_iface.configure = configure_channel;
+       dev->most_iface.enqueue = enqueue;
+       dev->most_iface.poison_channel = poison_channel;
+       dev->most_iface.request_netinfo = request_netinfo;
+       dev->dev.init_name = "dim2_state";
+       dev->dev.parent = &dev->most_iface.dev;
+
+       ret = most_register_interface(&dev->most_iface);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register MOST interface\n");
+               goto err_stop_thread;
+       }
+
+       ret = dim2_sysfs_probe(&dev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to create sysfs attribute\n");
+               goto err_unreg_iface;
+       }
+
+       ret = startup_dim(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to initialize DIM2\n");
+               goto err_destroy_bus;
+       }
+
+       return 0;
+
+err_destroy_bus:
+       dim2_sysfs_destroy(&dev->dev);
+err_unreg_iface:
+       most_deregister_interface(&dev->most_iface);
+err_stop_thread:
+       kthread_stop(dev->netinfo_task);
+
+       return ret;
+}
+
+/**
+ * dim2_remove - dim2 remove handler
+ * @pdev: platform device structure
+ *
+ * Unregister the interface from mostcore
+ */
+static int dim2_remove(struct platform_device *pdev)
+{
+       struct dim2_hdm *dev = platform_get_drvdata(pdev);
+       struct dim2_platform_data *pdata = pdev->dev.platform_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       dim_shutdown();
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       if (pdata && pdata->destroy)
+               pdata->destroy(pdata);
+
+       dim2_sysfs_destroy(&dev->dev);
+       most_deregister_interface(&dev->most_iface);
+       kthread_stop(dev->netinfo_task);
+
+       /*
+        * break link to local platform_device_id struct
+        * to prevent crash by unload platform device module
+        */
+       pdev->id_entry = NULL;
+
+       return 0;
+}
+
+static const struct platform_device_id dim2_id[] = {
+       { "medialb_dim2" },
+       { }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(platform, dim2_id);
+
+static struct platform_driver dim2_driver = {
+       .probe = dim2_probe,
+       .remove = dim2_remove,
+       .id_table = dim2_id,
+       .driver = {
+               .name = "hdm_dim2",
+       },
+};
+
+module_platform_driver(dim2_driver);
+
+MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/dim2/dim2.h b/drivers/staging/most/dim2/dim2.h
new file mode 100644 (file)
index 0000000..6a9fc51
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dim2.h - MediaLB DIM2 HDM Header
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#ifndef DIM2_HDM_H
+#define        DIM2_HDM_H
+
+struct device;
+
+/* platform dependent data for dim2 interface */
+struct dim2_platform_data {
+       int (*init)(struct dim2_platform_data *pd, void __iomem *io_base,
+                   int clk_speed);
+       void (*destroy)(struct dim2_platform_data *pd);
+       void *priv;
+};
+
+#endif /* DIM2_HDM_H */
diff --git a/drivers/staging/most/dim2/errors.h b/drivers/staging/most/dim2/errors.h
new file mode 100644 (file)
index 0000000..3487510
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * errors.h - Definitions of errors for DIM2 HAL API
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#ifndef _MOST_DIM_ERRORS_H
+#define _MOST_DIM_ERRORS_H
+
+/**
+ * MOST DIM errors.
+ */
+enum dim_errors_t {
+       /** Not an error */
+       DIM_NO_ERROR = 0,
+
+       /** Bad base address for DIM2 IP */
+       DIM_INIT_ERR_DIM_ADDR = 0x10,
+
+       /**< Bad MediaLB clock */
+       DIM_INIT_ERR_MLB_CLOCK,
+
+       /** Bad channel address */
+       DIM_INIT_ERR_CHANNEL_ADDRESS,
+
+       /** Out of DBR memory */
+       DIM_INIT_ERR_OUT_OF_MEMORY,
+
+       /** DIM API is called while DIM is not initialized successfully */
+       DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20,
+
+       /**
+        * Configuration does not respect hardware limitations
+        * for isochronous or synchronous channels
+        */
+       DIM_ERR_BAD_CONFIG,
+
+       /**
+        * Buffer size does not respect hardware limitations
+        * for isochronous or synchronous channels
+        */
+       DIM_ERR_BAD_BUFFER_SIZE,
+
+       DIM_ERR_UNDERFLOW,
+
+       DIM_ERR_OVERFLOW,
+};
+
+#endif /* _MOST_DIM_ERRORS_H */
diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c
new file mode 100644 (file)
index 0000000..17c04e1
--- /dev/null
@@ -0,0 +1,979 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * hal.c - DIM2 HAL implementation
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#include "hal.h"
+#include "errors.h"
+#include "reg.h"
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+
+/*
+ * Size factor for isochronous DBR buffer.
+ * Minimal value is 3.
+ */
+#define ISOC_DBR_FACTOR 3u
+
+/*
+ * Number of 32-bit units for DBR map.
+ *
+ * 1: block size is 512, max allocation is 16K
+ * 2: block size is 256, max allocation is 8K
+ * 4: block size is 128, max allocation is 4K
+ * 8: block size is 64, max allocation is 2K
+ *
+ * Min allocated space is block size.
+ * Max possible allocated space is 32 blocks.
+ */
+#define DBR_MAP_SIZE 2
+
+/* -------------------------------------------------------------------------- */
+/* not configurable area */
+
+#define CDT 0x00
+#define ADT 0x40
+#define MLB_CAT 0x80
+#define AHB_CAT 0x88
+
+#define DBR_SIZE  (16 * 1024) /* specified by IP */
+#define DBR_BLOCK_SIZE  (DBR_SIZE / 32 / DBR_MAP_SIZE)
+
+#define ROUND_UP_TO(x, d)  (DIV_ROUND_UP(x, (d)) * (d))
+
+/* -------------------------------------------------------------------------- */
+/* generic helper functions and macros */
+
+static inline u32 bit_mask(u8 position)
+{
+       return (u32)1 << position;
+}
+
+static inline bool dim_on_error(u8 error_id, const char *error_message)
+{
+       dimcb_on_error(error_id, error_message);
+       return false;
+}
+
+/* -------------------------------------------------------------------------- */
+/* types and local variables */
+
+struct async_tx_dbr {
+       u8 ch_addr;
+       u16 rpc;
+       u16 wpc;
+       u16 rest_size;
+       u16 sz_queue[CDT0_RPC_MASK + 1];
+};
+
+struct lld_global_vars_t {
+       bool dim_is_initialized;
+       bool mcm_is_initialized;
+       struct dim2_regs __iomem *dim2; /* DIM2 core base address */
+       struct async_tx_dbr atx_dbr;
+       u32 fcnt;
+       u32 dbr_map[DBR_MAP_SIZE];
+};
+
+static struct lld_global_vars_t g = { false };
+
+/* -------------------------------------------------------------------------- */
+
+static int dbr_get_mask_size(u16 size)
+{
+       int i;
+
+       for (i = 0; i < 6; i++)
+               if (size <= (DBR_BLOCK_SIZE << i))
+                       return 1 << i;
+       return 0;
+}
+
+/**
+ * Allocates DBR memory.
+ * @param size Allocating memory size.
+ * @return Offset in DBR memory by success or DBR_SIZE if out of memory.
+ */
+static int alloc_dbr(u16 size)
+{
+       int mask_size;
+       int i, block_idx = 0;
+
+       if (size <= 0)
+               return DBR_SIZE; /* out of memory */
+
+       mask_size = dbr_get_mask_size(size);
+       if (mask_size == 0)
+               return DBR_SIZE; /* out of memory */
+
+       for (i = 0; i < DBR_MAP_SIZE; i++) {
+               u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
+               u32 mask = ~((~(u32)0) << blocks);
+
+               do {
+                       if ((g.dbr_map[i] & mask) == 0) {
+                               g.dbr_map[i] |= mask;
+                               return block_idx * DBR_BLOCK_SIZE;
+                       }
+                       block_idx += mask_size;
+                       /* do shift left with 2 steps in case mask_size == 32 */
+                       mask <<= mask_size - 1;
+               } while ((mask <<= 1) != 0);
+       }
+
+       return DBR_SIZE; /* out of memory */
+}
+
+static void free_dbr(int offs, int size)
+{
+       int block_idx = offs / DBR_BLOCK_SIZE;
+       u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
+       u32 mask = ~((~(u32)0) << blocks);
+
+       mask <<= block_idx % 32;
+       g.dbr_map[block_idx / 32] &= ~mask;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void dim2_transfer_madr(u32 val)
+{
+       dimcb_io_write(&g.dim2->MADR, val);
+
+       /* wait for transfer completion */
+       while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1)
+               continue;
+
+       dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
+}
+
+static void dim2_clear_dbr(u16 addr, u16 size)
+{
+       enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 };
+
+       u16 const end_addr = addr + size;
+       u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT);
+
+       dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
+       dimcb_io_write(&g.dim2->MDAT0, 0);
+
+       for (; addr < end_addr; addr++)
+               dim2_transfer_madr(cmd | addr);
+}
+
+static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx)
+{
+       dim2_transfer_madr(ctr_addr);
+
+       return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx);
+}
+
+static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value)
+{
+       enum { MADR_WNR_BIT = 31 };
+
+       dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
+
+       if (mask[0] != 0)
+               dimcb_io_write(&g.dim2->MDAT0, value[0]);
+       if (mask[1] != 0)
+               dimcb_io_write(&g.dim2->MDAT1, value[1]);
+       if (mask[2] != 0)
+               dimcb_io_write(&g.dim2->MDAT2, value[2]);
+       if (mask[3] != 0)
+               dimcb_io_write(&g.dim2->MDAT3, value[3]);
+
+       dimcb_io_write(&g.dim2->MDWE0, mask[0]);
+       dimcb_io_write(&g.dim2->MDWE1, mask[1]);
+       dimcb_io_write(&g.dim2->MDWE2, mask[2]);
+       dimcb_io_write(&g.dim2->MDWE3, mask[3]);
+
+       dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr);
+}
+
+static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value)
+{
+       u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+
+       dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static inline void dim2_clear_ctr(u32 ctr_addr)
+{
+       u32 const value[4] = { 0, 0, 0, 0 };
+
+       dim2_write_ctr(ctr_addr, value);
+}
+
+static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type,
+                              bool read_not_write)
+{
+       bool isoc_fce = ch_type == CAT_CT_VAL_ISOC;
+       bool sync_mfe = ch_type == CAT_CT_VAL_SYNC;
+       u16 const cat =
+               (read_not_write << CAT_RNW_BIT) |
+               (ch_type << CAT_CT_SHIFT) |
+               (ch_addr << CAT_CL_SHIFT) |
+               (isoc_fce << CAT_FCE_BIT) |
+               (sync_mfe << CAT_MFE_BIT) |
+               (false << CAT_MT_BIT) |
+               (true << CAT_CE_BIT);
+       u8 const ctr_addr = cat_base + ch_addr / 8;
+       u8 const idx = (ch_addr % 8) / 2;
+       u8 const shift = (ch_addr % 2) * 16;
+       u32 mask[4] = { 0, 0, 0, 0 };
+       u32 value[4] = { 0, 0, 0, 0 };
+
+       mask[idx] = (u32)0xFFFF << shift;
+       value[idx] = cat << shift;
+       dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static void dim2_clear_cat(u8 cat_base, u8 ch_addr)
+{
+       u8 const ctr_addr = cat_base + ch_addr / 8;
+       u8 const idx = (ch_addr % 8) / 2;
+       u8 const shift = (ch_addr % 2) * 16;
+       u32 mask[4] = { 0, 0, 0, 0 };
+       u32 value[4] = { 0, 0, 0, 0 };
+
+       mask[idx] = (u32)0xFFFF << shift;
+       dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size,
+                              u16 packet_length)
+{
+       u32 cdt[4] = { 0, 0, 0, 0 };
+
+       if (packet_length)
+               cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT);
+
+       cdt[3] =
+               ((hw_buffer_size - 1) << CDT3_BD_SHIFT) |
+               (dbr_address << CDT3_BA_SHIFT);
+       dim2_write_ctr(CDT + ch_addr, cdt);
+}
+
+static u16 dim2_rpc(u8 ch_addr)
+{
+       u32 cdt0 = dim2_read_ctr(CDT + ch_addr, 0);
+
+       return (cdt0 >> CDT0_RPC_SHIFT) & CDT0_RPC_MASK;
+}
+
+static void dim2_clear_cdt(u8 ch_addr)
+{
+       u32 cdt[4] = { 0, 0, 0, 0 };
+
+       dim2_write_ctr(CDT + ch_addr, cdt);
+}
+
+static void dim2_configure_adt(u8 ch_addr)
+{
+       u32 adt[4] = { 0, 0, 0, 0 };
+
+       adt[0] =
+               (true << ADT0_CE_BIT) |
+               (true << ADT0_LE_BIT) |
+               (0 << ADT0_PG_BIT);
+
+       dim2_write_ctr(ADT + ch_addr, adt);
+}
+
+static void dim2_clear_adt(u8 ch_addr)
+{
+       u32 adt[4] = { 0, 0, 0, 0 };
+
+       dim2_write_ctr(ADT + ch_addr, adt);
+}
+
+static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr,
+                                 u16 buffer_size)
+{
+       u8 const shift = idx * 16;
+
+       u32 mask[4] = { 0, 0, 0, 0 };
+       u32 adt[4] = { 0, 0, 0, 0 };
+
+       mask[1] =
+               bit_mask(ADT1_PS_BIT + shift) |
+               bit_mask(ADT1_RDY_BIT + shift) |
+               (ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
+       adt[1] =
+               (true << (ADT1_PS_BIT + shift)) |
+               (true << (ADT1_RDY_BIT + shift)) |
+               ((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
+
+       mask[idx + 2] = 0xFFFFFFFF;
+       adt[idx + 2] = buf_addr;
+
+       dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
+}
+
+static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr,
+                                u16 buffer_size)
+{
+       u8 const shift = idx * 16;
+
+       u32 mask[4] = { 0, 0, 0, 0 };
+       u32 adt[4] = { 0, 0, 0, 0 };
+
+       mask[1] =
+               bit_mask(ADT1_RDY_BIT + shift) |
+               (ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
+       adt[1] =
+               (true << (ADT1_RDY_BIT + shift)) |
+               ((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
+
+       mask[idx + 2] = 0xFFFFFFFF;
+       adt[idx + 2] = buf_addr;
+
+       dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
+}
+
+static void dim2_clear_ctram(void)
+{
+       u32 ctr_addr;
+
+       for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++)
+               dim2_clear_ctr(ctr_addr);
+}
+
+static void dim2_configure_channel(
+       u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size,
+       u16 packet_length)
+{
+       dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length);
+       dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0);
+
+       dim2_configure_adt(ch_addr);
+       dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1);
+
+       /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */
+       dimcb_io_write(&g.dim2->ACMR0,
+                      dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr));
+}
+
+static void dim2_clear_channel(u8 ch_addr)
+{
+       /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */
+       dimcb_io_write(&g.dim2->ACMR0,
+                      dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr));
+
+       dim2_clear_cat(AHB_CAT, ch_addr);
+       dim2_clear_adt(ch_addr);
+
+       dim2_clear_cat(MLB_CAT, ch_addr);
+       dim2_clear_cdt(ch_addr);
+
+       /* clear channel status bit */
+       dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr));
+}
+
+/* -------------------------------------------------------------------------- */
+/* trace async tx dbr fill state */
+
+static inline u16 norm_pc(u16 pc)
+{
+       return pc & CDT0_RPC_MASK;
+}
+
+static void dbrcnt_init(u8 ch_addr, u16 dbr_size)
+{
+       g.atx_dbr.rest_size = dbr_size;
+       g.atx_dbr.rpc = dim2_rpc(ch_addr);
+       g.atx_dbr.wpc = g.atx_dbr.rpc;
+}
+
+static void dbrcnt_enq(int buf_sz)
+{
+       g.atx_dbr.rest_size -= buf_sz;
+       g.atx_dbr.sz_queue[norm_pc(g.atx_dbr.wpc)] = buf_sz;
+       g.atx_dbr.wpc++;
+}
+
+u16 dim_dbr_space(struct dim_channel *ch)
+{
+       u16 cur_rpc;
+       struct async_tx_dbr *dbr = &g.atx_dbr;
+
+       if (ch->addr != dbr->ch_addr)
+               return 0xFFFF;
+
+       cur_rpc = dim2_rpc(ch->addr);
+
+       while (norm_pc(dbr->rpc) != cur_rpc) {
+               dbr->rest_size += dbr->sz_queue[norm_pc(dbr->rpc)];
+               dbr->rpc++;
+       }
+
+       if ((u16)(dbr->wpc - dbr->rpc) >= CDT0_RPC_MASK)
+               return 0;
+
+       return dbr->rest_size;
+}
+
+/* -------------------------------------------------------------------------- */
+/* channel state helpers */
+
+static void state_init(struct int_ch_state *state)
+{
+       state->request_counter = 0;
+       state->service_counter = 0;
+
+       state->idx1 = 0;
+       state->idx2 = 0;
+       state->level = 0;
+}
+
+/* -------------------------------------------------------------------------- */
+/* macro helper functions */
+
+static inline bool check_channel_address(u32 ch_address)
+{
+       return ch_address > 0 && (ch_address % 2) == 0 &&
+              (ch_address / 2) <= (u32)CAT_CL_MASK;
+}
+
+static inline bool check_packet_length(u32 packet_length)
+{
+       u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR;
+
+       if (packet_length <= 0)
+               return false; /* too small */
+
+       if (packet_length > max_size)
+               return false; /* too big */
+
+       if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK)
+               return false; /* too big */
+
+       return true;
+}
+
+static inline bool check_bytes_per_frame(u32 bytes_per_frame)
+{
+       u16 const bd_factor = g.fcnt + 2;
+       u16 const max_size = ((u16)CDT3_BD_MASK + 1u) >> bd_factor;
+
+       if (bytes_per_frame <= 0)
+               return false; /* too small */
+
+       if (bytes_per_frame > max_size)
+               return false; /* too big */
+
+       return true;
+}
+
+static inline u16 norm_ctrl_async_buffer_size(u16 buf_size)
+{
+       u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u;
+
+       if (buf_size > max_size)
+               return max_size;
+
+       return buf_size;
+}
+
+static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
+{
+       u16 n;
+       u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
+
+       if (buf_size > max_size)
+               buf_size = max_size;
+
+       n = buf_size / packet_length;
+
+       if (n < 2u)
+               return 0; /* too small buffer for given packet_length */
+
+       return packet_length * n;
+}
+
+static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
+{
+       u16 n;
+       u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
+       u32 const unit = bytes_per_frame << g.fcnt;
+
+       if (buf_size > max_size)
+               buf_size = max_size;
+
+       n = buf_size / unit;
+
+       if (n < 1u)
+               return 0; /* too small buffer for given bytes_per_frame */
+
+       return unit * n;
+}
+
+static void dim2_cleanup(void)
+{
+       /* disable MediaLB */
+       dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT);
+
+       dim2_clear_ctram();
+
+       /* disable mlb_int interrupt */
+       dimcb_io_write(&g.dim2->MIEN, 0);
+
+       /* clear status for all dma channels */
+       dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF);
+       dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF);
+
+       /* mask interrupts for all channels */
+       dimcb_io_write(&g.dim2->ACMR0, 0);
+       dimcb_io_write(&g.dim2->ACMR1, 0);
+}
+
+static void dim2_initialize(bool enable_6pin, u8 mlb_clock)
+{
+       dim2_cleanup();
+
+       /* configure and enable MediaLB */
+       dimcb_io_write(&g.dim2->MLBC0,
+                      enable_6pin << MLBC0_MLBPEN_BIT |
+                      mlb_clock << MLBC0_MLBCLK_SHIFT |
+                      g.fcnt << MLBC0_FCNT_SHIFT |
+                      true << MLBC0_MLBEN_BIT);
+
+       /* activate all HBI channels */
+       dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF);
+       dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF);
+
+       /* enable HBI */
+       dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT));
+
+       /* configure DMA */
+       dimcb_io_write(&g.dim2->ACTL,
+                      ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT |
+                      true << ACTL_SCE_BIT);
+}
+
+static bool dim2_is_mlb_locked(void)
+{
+       u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT);
+       u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) |
+                         bit_mask(MLBC1_LOCKERR_BIT);
+       u32 const c1 = dimcb_io_read(&g.dim2->MLBC1);
+       u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT;
+
+       dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask);
+       return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 &&
+              (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0;
+}
+
+/* -------------------------------------------------------------------------- */
+/* channel help routines */
+
+static inline bool service_channel(u8 ch_addr, u8 idx)
+{
+       u8 const shift = idx * 16;
+       u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1);
+       u32 mask[4] = { 0, 0, 0, 0 };
+       u32 adt_w[4] = { 0, 0, 0, 0 };
+
+       if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0)
+               return false;
+
+       mask[1] =
+               bit_mask(ADT1_DNE_BIT + shift) |
+               bit_mask(ADT1_ERR_BIT + shift) |
+               bit_mask(ADT1_RDY_BIT + shift);
+       dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w);
+
+       /* clear channel status bit */
+       dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr));
+
+       return true;
+}
+
+/* -------------------------------------------------------------------------- */
+/* channel init routines */
+
+static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length)
+{
+       state_init(&ch->state);
+
+       ch->addr = ch_addr;
+
+       ch->packet_length = packet_length;
+       ch->bytes_per_frame = 0;
+       ch->done_sw_buffers_number = 0;
+}
+
+static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame)
+{
+       state_init(&ch->state);
+
+       ch->addr = ch_addr;
+
+       ch->packet_length = 0;
+       ch->bytes_per_frame = bytes_per_frame;
+       ch->done_sw_buffers_number = 0;
+}
+
+static void channel_init(struct dim_channel *ch, u8 ch_addr)
+{
+       state_init(&ch->state);
+
+       ch->addr = ch_addr;
+
+       ch->packet_length = 0;
+       ch->bytes_per_frame = 0;
+       ch->done_sw_buffers_number = 0;
+}
+
+/* returns true if channel interrupt state is cleared */
+static bool channel_service_interrupt(struct dim_channel *ch)
+{
+       struct int_ch_state *const state = &ch->state;
+
+       if (!service_channel(ch->addr, state->idx2))
+               return false;
+
+       state->idx2 ^= 1;
+       state->request_counter++;
+       return true;
+}
+
+static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size)
+{
+       struct int_ch_state *const state = &ch->state;
+
+       if (buf_size <= 0)
+               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size");
+
+       if (ch->packet_length == 0 && ch->bytes_per_frame == 0 &&
+           buf_size != norm_ctrl_async_buffer_size(buf_size))
+               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+                                   "Bad control/async buffer size");
+
+       if (ch->packet_length &&
+           buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length))
+               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+                                   "Bad isochronous buffer size");
+
+       if (ch->bytes_per_frame &&
+           buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame))
+               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+                                   "Bad synchronous buffer size");
+
+       if (state->level >= 2u)
+               return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow");
+
+       ++state->level;
+
+       if (ch->addr == g.atx_dbr.ch_addr)
+               dbrcnt_enq(buf_size);
+
+       if (ch->packet_length || ch->bytes_per_frame)
+               dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size);
+       else
+               dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr,
+                                     buf_size);
+       state->idx1 ^= 1;
+
+       return true;
+}
+
+static u8 channel_service(struct dim_channel *ch)
+{
+       struct int_ch_state *const state = &ch->state;
+
+       if (state->service_counter != state->request_counter) {
+               state->service_counter++;
+               if (state->level == 0)
+                       return DIM_ERR_UNDERFLOW;
+
+               --state->level;
+               ch->done_sw_buffers_number++;
+       }
+
+       return DIM_NO_ERROR;
+}
+
+static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number)
+{
+       if (buffers_number > ch->done_sw_buffers_number)
+               return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow");
+
+       ch->done_sw_buffers_number -= buffers_number;
+       return true;
+}
+
+/* -------------------------------------------------------------------------- */
+/* API */
+
+u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock,
+              u32 fcnt)
+{
+       g.dim_is_initialized = false;
+
+       if (!dim_base_address)
+               return DIM_INIT_ERR_DIM_ADDR;
+
+       /* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */
+       /* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */
+       if (mlb_clock >= 8)
+               return DIM_INIT_ERR_MLB_CLOCK;
+
+       if (fcnt > MLBC0_FCNT_MAX_VAL)
+               return DIM_INIT_ERR_MLB_CLOCK;
+
+       g.dim2 = dim_base_address;
+       g.fcnt = fcnt;
+       g.dbr_map[0] = 0;
+       g.dbr_map[1] = 0;
+
+       dim2_initialize(mlb_clock >= 3, mlb_clock);
+
+       g.dim_is_initialized = true;
+
+       return DIM_NO_ERROR;
+}
+
+void dim_shutdown(void)
+{
+       g.dim_is_initialized = false;
+       dim2_cleanup();
+}
+
+bool dim_get_lock_state(void)
+{
+       return dim2_is_mlb_locked();
+}
+
+static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx,
+                         u16 ch_address, u16 hw_buffer_size)
+{
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       if (!check_channel_address(ch_address))
+               return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+       ch->dbr_size = ROUND_UP_TO(hw_buffer_size, DBR_BLOCK_SIZE);
+       ch->dbr_addr = alloc_dbr(ch->dbr_size);
+       if (ch->dbr_addr >= DBR_SIZE)
+               return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+       channel_init(ch, ch_address / 2);
+
+       dim2_configure_channel(ch->addr, type, is_tx,
+                              ch->dbr_addr, ch->dbr_size, 0);
+
+       return DIM_NO_ERROR;
+}
+
+void dim_service_mlb_int_irq(void)
+{
+       dimcb_io_write(&g.dim2->MS0, 0);
+       dimcb_io_write(&g.dim2->MS1, 0);
+}
+
+u16 dim_norm_ctrl_async_buffer_size(u16 buf_size)
+{
+       return norm_ctrl_async_buffer_size(buf_size);
+}
+
+/**
+ * Retrieves maximal possible correct buffer size for isochronous data type
+ * conform to given packet length and not bigger than given buffer size.
+ *
+ * Returns non-zero correct buffer size or zero by error.
+ */
+u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
+{
+       if (!check_packet_length(packet_length))
+               return 0;
+
+       return norm_isoc_buffer_size(buf_size, packet_length);
+}
+
+/**
+ * Retrieves maximal possible correct buffer size for synchronous data type
+ * conform to given bytes per frame and not bigger than given buffer size.
+ *
+ * Returns non-zero correct buffer size or zero by error.
+ */
+u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
+{
+       if (!check_bytes_per_frame(bytes_per_frame))
+               return 0;
+
+       return norm_sync_buffer_size(buf_size, bytes_per_frame);
+}
+
+u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                   u16 max_buffer_size)
+{
+       return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address,
+                              max_buffer_size);
+}
+
+u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                 u16 max_buffer_size)
+{
+       u8 ret = init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address,
+                                max_buffer_size);
+
+       if (is_tx && !g.atx_dbr.ch_addr) {
+               g.atx_dbr.ch_addr = ch->addr;
+               dbrcnt_init(ch->addr, ch->dbr_size);
+               dimcb_io_write(&g.dim2->MIEN, bit_mask(20));
+       }
+
+       return ret;
+}
+
+u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                u16 packet_length)
+{
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       if (!check_channel_address(ch_address))
+               return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+       if (!check_packet_length(packet_length))
+               return DIM_ERR_BAD_CONFIG;
+
+       ch->dbr_size = packet_length * ISOC_DBR_FACTOR;
+       ch->dbr_addr = alloc_dbr(ch->dbr_size);
+       if (ch->dbr_addr >= DBR_SIZE)
+               return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+       isoc_init(ch, ch_address / 2, packet_length);
+
+       dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr,
+                              ch->dbr_size, packet_length);
+
+       return DIM_NO_ERROR;
+}
+
+u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                u16 bytes_per_frame)
+{
+       u16 bd_factor = g.fcnt + 2;
+
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       if (!check_channel_address(ch_address))
+               return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+       if (!check_bytes_per_frame(bytes_per_frame))
+               return DIM_ERR_BAD_CONFIG;
+
+       ch->dbr_size = bytes_per_frame << bd_factor;
+       ch->dbr_addr = alloc_dbr(ch->dbr_size);
+       if (ch->dbr_addr >= DBR_SIZE)
+               return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+       sync_init(ch, ch_address / 2, bytes_per_frame);
+
+       dim2_clear_dbr(ch->dbr_addr, ch->dbr_size);
+       dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx,
+                              ch->dbr_addr, ch->dbr_size, 0);
+
+       return DIM_NO_ERROR;
+}
+
+u8 dim_destroy_channel(struct dim_channel *ch)
+{
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       if (ch->addr == g.atx_dbr.ch_addr) {
+               dimcb_io_write(&g.dim2->MIEN, 0);
+               g.atx_dbr.ch_addr = 0;
+       }
+
+       dim2_clear_channel(ch->addr);
+       if (ch->dbr_addr < DBR_SIZE)
+               free_dbr(ch->dbr_addr, ch->dbr_size);
+       ch->dbr_addr = DBR_SIZE;
+
+       return DIM_NO_ERROR;
+}
+
+void dim_service_ahb_int_irq(struct dim_channel *const *channels)
+{
+       bool state_changed;
+
+       if (!g.dim_is_initialized) {
+               dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+                            "DIM is not initialized");
+               return;
+       }
+
+       if (!channels) {
+               dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels");
+               return;
+       }
+
+       /*
+        * Use while-loop and a flag to make sure the age is changed back at
+        * least once, otherwise the interrupt may never come if CPU generates
+        * interrupt on changing age.
+        * This cycle runs not more than number of channels, because
+        * channel_service_interrupt() routine doesn't start the channel again.
+        */
+       do {
+               struct dim_channel *const *ch = channels;
+
+               state_changed = false;
+
+               while (*ch) {
+                       state_changed |= channel_service_interrupt(*ch);
+                       ++ch;
+               }
+       } while (state_changed);
+}
+
+u8 dim_service_channel(struct dim_channel *ch)
+{
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       return channel_service(ch);
+}
+
+struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
+                                            struct dim_ch_state_t *state_ptr)
+{
+       if (!ch || !state_ptr)
+               return NULL;
+
+       state_ptr->ready = ch->state.level < 2;
+       state_ptr->done_buffers = ch->done_sw_buffers_number;
+
+       return state_ptr;
+}
+
+bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
+                       u16 buffer_size)
+{
+       if (!ch)
+               return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+                                   "Bad channel");
+
+       return channel_start(ch, buffer_addr, buffer_size);
+}
+
+bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number)
+{
+       if (!ch)
+               return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+                                   "Bad channel");
+
+       return channel_detach_buffers(ch, buffers_number);
+}
diff --git a/drivers/staging/most/dim2/hal.h b/drivers/staging/most/dim2/hal.h
new file mode 100644 (file)
index 0000000..e04a535
--- /dev/null
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * hal.h - DIM2 HAL interface
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#ifndef _DIM2_HAL_H
+#define _DIM2_HAL_H
+
+#include <linux/types.h>
+#include "reg.h"
+
+/*
+ * The values below are specified in the hardware specification.
+ * So, they should not be changed until the hardware specification changes.
+ */
+enum mlb_clk_speed {
+       CLK_256FS = 0,
+       CLK_512FS = 1,
+       CLK_1024FS = 2,
+       CLK_2048FS = 3,
+       CLK_3072FS = 4,
+       CLK_4096FS = 5,
+       CLK_6144FS = 6,
+       CLK_8192FS = 7,
+};
+
+struct dim_ch_state_t {
+       bool ready; /* Shows readiness to enqueue next buffer */
+       u16 done_buffers; /* Number of completed buffers */
+};
+
+struct int_ch_state {
+       /* changed only in interrupt context */
+       volatile int request_counter;
+
+       /* changed only in task context */
+       volatile int service_counter;
+
+       u8 idx1;
+       u8 idx2;
+       u8 level; /* [0..2], buffering level */
+};
+
+struct dim_channel {
+       struct int_ch_state state;
+       u8 addr;
+       u16 dbr_addr;
+       u16 dbr_size;
+       u16 packet_length; /*< Isochronous packet length in bytes. */
+       u16 bytes_per_frame; /*< Synchronous bytes per frame. */
+       u16 done_sw_buffers_number; /*< Done software buffers number. */
+};
+
+u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock,
+              u32 fcnt);
+
+void dim_shutdown(void);
+
+bool dim_get_lock_state(void);
+
+u16 dim_norm_ctrl_async_buffer_size(u16 buf_size);
+
+u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length);
+
+u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame);
+
+u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                   u16 max_buffer_size);
+
+u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                 u16 max_buffer_size);
+
+u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                u16 packet_length);
+
+u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                u16 bytes_per_frame);
+
+u8 dim_destroy_channel(struct dim_channel *ch);
+
+void dim_service_mlb_int_irq(void);
+
+void dim_service_ahb_int_irq(struct dim_channel *const *channels);
+
+u8 dim_service_channel(struct dim_channel *ch);
+
+struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
+                                            struct dim_ch_state_t *state_ptr);
+
+u16 dim_dbr_space(struct dim_channel *ch);
+
+bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
+                       u16 buffer_size);
+
+bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number);
+
+u32 dimcb_io_read(u32 __iomem *ptr32);
+
+void dimcb_io_write(u32 __iomem *ptr32, u32 value);
+
+void dimcb_on_error(u8 error_id, const char *error_message);
+
+#endif /* _DIM2_HAL_H */
diff --git a/drivers/staging/most/dim2/reg.h b/drivers/staging/most/dim2/reg.h
new file mode 100644 (file)
index 0000000..69cbf78
--- /dev/null
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * reg.h - Definitions for registers of DIM2
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#ifndef DIM2_OS62420_H
+#define        DIM2_OS62420_H
+
+#include <linux/types.h>
+
+struct dim2_regs {
+       /* 0x00 */ u32 MLBC0;
+       /* 0x01 */ u32 rsvd0[1];
+       /* 0x02 */ u32 MLBPC0;
+       /* 0x03 */ u32 MS0;
+       /* 0x04 */ u32 rsvd1[1];
+       /* 0x05 */ u32 MS1;
+       /* 0x06 */ u32 rsvd2[2];
+       /* 0x08 */ u32 MSS;
+       /* 0x09 */ u32 MSD;
+       /* 0x0A */ u32 rsvd3[1];
+       /* 0x0B */ u32 MIEN;
+       /* 0x0C */ u32 rsvd4[1];
+       /* 0x0D */ u32 MLBPC2;
+       /* 0x0E */ u32 MLBPC1;
+       /* 0x0F */ u32 MLBC1;
+       /* 0x10 */ u32 rsvd5[0x10];
+       /* 0x20 */ u32 HCTL;
+       /* 0x21 */ u32 rsvd6[1];
+       /* 0x22 */ u32 HCMR0;
+       /* 0x23 */ u32 HCMR1;
+       /* 0x24 */ u32 HCER0;
+       /* 0x25 */ u32 HCER1;
+       /* 0x26 */ u32 HCBR0;
+       /* 0x27 */ u32 HCBR1;
+       /* 0x28 */ u32 rsvd7[8];
+       /* 0x30 */ u32 MDAT0;
+       /* 0x31 */ u32 MDAT1;
+       /* 0x32 */ u32 MDAT2;
+       /* 0x33 */ u32 MDAT3;
+       /* 0x34 */ u32 MDWE0;
+       /* 0x35 */ u32 MDWE1;
+       /* 0x36 */ u32 MDWE2;
+       /* 0x37 */ u32 MDWE3;
+       /* 0x38 */ u32 MCTL;
+       /* 0x39 */ u32 MADR;
+       /* 0x3A */ u32 rsvd8[0xB6];
+       /* 0xF0 */ u32 ACTL;
+       /* 0xF1 */ u32 rsvd9[3];
+       /* 0xF4 */ u32 ACSR0;
+       /* 0xF5 */ u32 ACSR1;
+       /* 0xF6 */ u32 ACMR0;
+       /* 0xF7 */ u32 ACMR1;
+};
+
+#define DIM2_MASK(n)  (~((~(u32)0) << (n)))
+
+enum {
+       MLBC0_MLBLK_BIT = 7,
+
+       MLBC0_MLBPEN_BIT = 5,
+
+       MLBC0_MLBCLK_SHIFT = 2,
+       MLBC0_MLBCLK_VAL_256FS = 0,
+       MLBC0_MLBCLK_VAL_512FS = 1,
+       MLBC0_MLBCLK_VAL_1024FS = 2,
+       MLBC0_MLBCLK_VAL_2048FS = 3,
+
+       MLBC0_FCNT_SHIFT = 15,
+       MLBC0_FCNT_MASK = 7,
+       MLBC0_FCNT_MAX_VAL = 6,
+
+       MLBC0_MLBEN_BIT = 0,
+
+       MIEN_CTX_BREAK_BIT = 29,
+       MIEN_CTX_PE_BIT = 28,
+       MIEN_CTX_DONE_BIT = 27,
+
+       MIEN_CRX_BREAK_BIT = 26,
+       MIEN_CRX_PE_BIT = 25,
+       MIEN_CRX_DONE_BIT = 24,
+
+       MIEN_ATX_BREAK_BIT = 22,
+       MIEN_ATX_PE_BIT = 21,
+       MIEN_ATX_DONE_BIT = 20,
+
+       MIEN_ARX_BREAK_BIT = 19,
+       MIEN_ARX_PE_BIT = 18,
+       MIEN_ARX_DONE_BIT = 17,
+
+       MIEN_SYNC_PE_BIT = 16,
+
+       MIEN_ISOC_BUFO_BIT = 1,
+       MIEN_ISOC_PE_BIT = 0,
+
+       MLBC1_NDA_SHIFT = 8,
+       MLBC1_NDA_MASK = 0xFF,
+
+       MLBC1_CLKMERR_BIT = 7,
+       MLBC1_LOCKERR_BIT = 6,
+
+       ACTL_DMA_MODE_BIT = 2,
+       ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0,
+       ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1,
+       ACTL_SCE_BIT = 0,
+
+       HCTL_EN_BIT = 15
+};
+
+enum {
+       CDT0_RPC_SHIFT = 16 + 11,
+       CDT0_RPC_MASK = DIM2_MASK(5),
+
+       CDT1_BS_ISOC_SHIFT = 0,
+       CDT1_BS_ISOC_MASK = DIM2_MASK(9),
+
+       CDT3_BD_SHIFT = 0,
+       CDT3_BD_MASK = DIM2_MASK(12),
+       CDT3_BD_ISOC_MASK = DIM2_MASK(13),
+       CDT3_BA_SHIFT = 16,
+
+       ADT0_CE_BIT = 15,
+       ADT0_LE_BIT = 14,
+       ADT0_PG_BIT = 13,
+
+       ADT1_RDY_BIT = 15,
+       ADT1_DNE_BIT = 14,
+       ADT1_ERR_BIT = 13,
+       ADT1_PS_BIT = 12,
+       ADT1_MEP_BIT = 11,
+       ADT1_BD_SHIFT = 0,
+       ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
+       ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),
+
+       CAT_FCE_BIT = 14,
+       CAT_MFE_BIT = 14,
+
+       CAT_MT_BIT = 13,
+
+       CAT_RNW_BIT = 12,
+
+       CAT_CE_BIT = 11,
+
+       CAT_CT_SHIFT = 8,
+       CAT_CT_VAL_SYNC = 0,
+       CAT_CT_VAL_CONTROL = 1,
+       CAT_CT_VAL_ASYNC = 2,
+       CAT_CT_VAL_ISOC = 3,
+
+       CAT_CL_SHIFT = 0,
+       CAT_CL_MASK = DIM2_MASK(6)
+};
+
+#endif /* DIM2_OS62420_H */
diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c
new file mode 100644 (file)
index 0000000..c85b2cd
--- /dev/null
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * sysfs.c - MediaLB sysfs information
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include "sysfs.h"
+#include <linux/device.h>
+
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       bool state = dim2_sysfs_get_state_cb();
+
+       return sprintf(buf, "%s\n", state ? "locked" : "");
+}
+
+static DEVICE_ATTR_RO(state);
+
+static struct attribute *dev_attrs[] = {
+       &dev_attr_state.attr,
+       NULL,
+};
+
+static struct attribute_group dev_attr_group = {
+       .attrs = dev_attrs,
+};
+
+static const struct attribute_group *dev_attr_groups[] = {
+       &dev_attr_group,
+       NULL,
+};
+
+int dim2_sysfs_probe(struct device *dev)
+{
+       dev->groups = dev_attr_groups;
+       return device_register(dev);
+}
+
+void dim2_sysfs_destroy(struct device *dev)
+{
+       device_unregister(dev);
+}
diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h
new file mode 100644 (file)
index 0000000..33756a3
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * sysfs.h - MediaLB sysfs information
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#ifndef DIM2_SYSFS_H
+#define        DIM2_SYSFS_H
+
+#include <linux/kobject.h>
+
+struct medialb_bus {
+       struct kobject kobj_group;
+};
+
+struct device;
+
+int dim2_sysfs_probe(struct device *dev);
+void dim2_sysfs_destroy(struct device *dev);
+
+/*
+ * callback,
+ * must deliver MediaLB state as true if locked or false if unlocked
+ */
+bool dim2_sysfs_get_state_cb(void);
+
+#endif /* DIM2_SYSFS_H */
diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/hdm-dim2/Kconfig
deleted file mode 100644 (file)
index 663bfeb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# MediaLB configuration
-#
-
-config HDM_DIM2
-       tristate "DIM2 HDM"
-       depends on HAS_IOMEM
-
-       ---help---
-         Say Y here if you want to connect via MediaLB to network transceiver.
-         This device driver is platform dependent and needs an additional
-         platform driver to be installed. For more information contact
-         maintainer of this driver.
-
-         To compile this driver as a module, choose M here: the
-         module will be called hdm_dim2.
diff --git a/drivers/staging/most/hdm-dim2/Makefile b/drivers/staging/most/hdm-dim2/Makefile
deleted file mode 100644 (file)
index 6bbee87..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_HDM_DIM2) += hdm_dim2.o
-
-hdm_dim2-objs := dim2_hdm.o dim2_hal.o dim2_sysfs.o
-ccflags-y += -Idrivers/staging/most/mostcore/
-ccflags-y += -Idrivers/staging/most/aim-network/
diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h
deleted file mode 100644 (file)
index 66343ba..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * dim2_errors.h - Definitions of errors for DIM2 HAL API
- * (MediaLB, Device Interface Macro IP, OS62420)
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#ifndef _MOST_DIM_ERRORS_H
-#define _MOST_DIM_ERRORS_H
-
-/**
- * MOST DIM errors.
- */
-enum dim_errors_t {
-       /** Not an error */
-       DIM_NO_ERROR = 0,
-
-       /** Bad base address for DIM2 IP */
-       DIM_INIT_ERR_DIM_ADDR = 0x10,
-
-       /**< Bad MediaLB clock */
-       DIM_INIT_ERR_MLB_CLOCK,
-
-       /** Bad channel address */
-       DIM_INIT_ERR_CHANNEL_ADDRESS,
-
-       /** Out of DBR memory */
-       DIM_INIT_ERR_OUT_OF_MEMORY,
-
-       /** DIM API is called while DIM is not initialized successfully */
-       DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20,
-
-       /**
-        * Configuration does not respect hardware limitations
-        * for isochronous or synchronous channels
-        */
-       DIM_ERR_BAD_CONFIG,
-
-       /**
-        * Buffer size does not respect hardware limitations
-        * for isochronous or synchronous channels
-        */
-       DIM_ERR_BAD_BUFFER_SIZE,
-
-       DIM_ERR_UNDERFLOW,
-
-       DIM_ERR_OVERFLOW,
-};
-
-#endif /* _MOST_DIM_ERRORS_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c
deleted file mode 100644 (file)
index 9148464..0000000
+++ /dev/null
@@ -1,985 +0,0 @@
-/*
- * dim2_hal.c - DIM2 HAL implementation
- * (MediaLB, Device Interface Macro IP, OS62420)
- *
- * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
-
-#include "dim2_hal.h"
-#include "dim2_errors.h"
-#include "dim2_reg.h"
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-
-/*
- * Size factor for isochronous DBR buffer.
- * Minimal value is 3.
- */
-#define ISOC_DBR_FACTOR 3u
-
-/*
- * Number of 32-bit units for DBR map.
- *
- * 1: block size is 512, max allocation is 16K
- * 2: block size is 256, max allocation is 8K
- * 4: block size is 128, max allocation is 4K
- * 8: block size is 64, max allocation is 2K
- *
- * Min allocated space is block size.
- * Max possible allocated space is 32 blocks.
- */
-#define DBR_MAP_SIZE 2
-
-/* -------------------------------------------------------------------------- */
-/* not configurable area */
-
-#define CDT 0x00
-#define ADT 0x40
-#define MLB_CAT 0x80
-#define AHB_CAT 0x88
-
-#define DBR_SIZE  (16 * 1024) /* specified by IP */
-#define DBR_BLOCK_SIZE  (DBR_SIZE / 32 / DBR_MAP_SIZE)
-
-#define ROUND_UP_TO(x, d)  (DIV_ROUND_UP(x, (d)) * (d))
-
-/* -------------------------------------------------------------------------- */
-/* generic helper functions and macros */
-
-static inline u32 bit_mask(u8 position)
-{
-       return (u32)1 << position;
-}
-
-static inline bool dim_on_error(u8 error_id, const char *error_message)
-{
-       dimcb_on_error(error_id, error_message);
-       return false;
-}
-
-/* -------------------------------------------------------------------------- */
-/* types and local variables */
-
-struct async_tx_dbr {
-       u8 ch_addr;
-       u16 rpc;
-       u16 wpc;
-       u16 rest_size;
-       u16 sz_queue[CDT0_RPC_MASK + 1];
-};
-
-struct lld_global_vars_t {
-       bool dim_is_initialized;
-       bool mcm_is_initialized;
-       struct dim2_regs __iomem *dim2; /* DIM2 core base address */
-       struct async_tx_dbr atx_dbr;
-       u32 fcnt;
-       u32 dbr_map[DBR_MAP_SIZE];
-};
-
-static struct lld_global_vars_t g = { false };
-
-/* -------------------------------------------------------------------------- */
-
-static int dbr_get_mask_size(u16 size)
-{
-       int i;
-
-       for (i = 0; i < 6; i++)
-               if (size <= (DBR_BLOCK_SIZE << i))
-                       return 1 << i;
-       return 0;
-}
-
-/**
- * Allocates DBR memory.
- * @param size Allocating memory size.
- * @return Offset in DBR memory by success or DBR_SIZE if out of memory.
- */
-static int alloc_dbr(u16 size)
-{
-       int mask_size;
-       int i, block_idx = 0;
-
-       if (size <= 0)
-               return DBR_SIZE; /* out of memory */
-
-       mask_size = dbr_get_mask_size(size);
-       if (mask_size == 0)
-               return DBR_SIZE; /* out of memory */
-
-       for (i = 0; i < DBR_MAP_SIZE; i++) {
-               u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
-               u32 mask = ~((~(u32)0) << blocks);
-
-               do {
-                       if ((g.dbr_map[i] & mask) == 0) {
-                               g.dbr_map[i] |= mask;
-                               return block_idx * DBR_BLOCK_SIZE;
-                       }
-                       block_idx += mask_size;
-                       /* do shift left with 2 steps in case mask_size == 32 */
-                       mask <<= mask_size - 1;
-               } while ((mask <<= 1) != 0);
-       }
-
-       return DBR_SIZE; /* out of memory */
-}
-
-static void free_dbr(int offs, int size)
-{
-       int block_idx = offs / DBR_BLOCK_SIZE;
-       u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
-       u32 mask = ~((~(u32)0) << blocks);
-
-       mask <<= block_idx % 32;
-       g.dbr_map[block_idx / 32] &= ~mask;
-}
-
-/* -------------------------------------------------------------------------- */
-
-static void dim2_transfer_madr(u32 val)
-{
-       dimcb_io_write(&g.dim2->MADR, val);
-
-       /* wait for transfer completion */
-       while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1)
-               continue;
-
-       dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
-}
-
-static void dim2_clear_dbr(u16 addr, u16 size)
-{
-       enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 };
-
-       u16 const end_addr = addr + size;
-       u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT);
-
-       dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
-       dimcb_io_write(&g.dim2->MDAT0, 0);
-
-       for (; addr < end_addr; addr++)
-               dim2_transfer_madr(cmd | addr);
-}
-
-static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx)
-{
-       dim2_transfer_madr(ctr_addr);
-
-       return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx);
-}
-
-static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value)
-{
-       enum { MADR_WNR_BIT = 31 };
-
-       dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
-
-       if (mask[0] != 0)
-               dimcb_io_write(&g.dim2->MDAT0, value[0]);
-       if (mask[1] != 0)
-               dimcb_io_write(&g.dim2->MDAT1, value[1]);
-       if (mask[2] != 0)
-               dimcb_io_write(&g.dim2->MDAT2, value[2]);
-       if (mask[3] != 0)
-               dimcb_io_write(&g.dim2->MDAT3, value[3]);
-
-       dimcb_io_write(&g.dim2->MDWE0, mask[0]);
-       dimcb_io_write(&g.dim2->MDWE1, mask[1]);
-       dimcb_io_write(&g.dim2->MDWE2, mask[2]);
-       dimcb_io_write(&g.dim2->MDWE3, mask[3]);
-
-       dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr);
-}
-
-static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value)
-{
-       u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
-
-       dim2_write_ctr_mask(ctr_addr, mask, value);
-}
-
-static inline void dim2_clear_ctr(u32 ctr_addr)
-{
-       u32 const value[4] = { 0, 0, 0, 0 };
-
-       dim2_write_ctr(ctr_addr, value);
-}
-
-static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type,
-                              bool read_not_write)
-{
-       bool isoc_fce = ch_type == CAT_CT_VAL_ISOC;
-       bool sync_mfe = ch_type == CAT_CT_VAL_SYNC;
-       u16 const cat =
-               (read_not_write << CAT_RNW_BIT) |
-               (ch_type << CAT_CT_SHIFT) |
-               (ch_addr << CAT_CL_SHIFT) |
-               (isoc_fce << CAT_FCE_BIT) |
-               (sync_mfe << CAT_MFE_BIT) |
-               (false << CAT_MT_BIT) |
-               (true << CAT_CE_BIT);
-       u8 const ctr_addr = cat_base + ch_addr / 8;
-       u8 const idx = (ch_addr % 8) / 2;
-       u8 const shift = (ch_addr % 2) * 16;
-       u32 mask[4] = { 0, 0, 0, 0 };
-       u32 value[4] = { 0, 0, 0, 0 };
-
-       mask[idx] = (u32)0xFFFF << shift;
-       value[idx] = cat << shift;
-       dim2_write_ctr_mask(ctr_addr, mask, value);
-}
-
-static void dim2_clear_cat(u8 cat_base, u8 ch_addr)
-{
-       u8 const ctr_addr = cat_base + ch_addr / 8;
-       u8 const idx = (ch_addr % 8) / 2;
-       u8 const shift = (ch_addr % 2) * 16;
-       u32 mask[4] = { 0, 0, 0, 0 };
-       u32 value[4] = { 0, 0, 0, 0 };
-
-       mask[idx] = (u32)0xFFFF << shift;
-       dim2_write_ctr_mask(ctr_addr, mask, value);
-}
-
-static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size,
-                              u16 packet_length)
-{
-       u32 cdt[4] = { 0, 0, 0, 0 };
-
-       if (packet_length)
-               cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT);
-
-       cdt[3] =
-               ((hw_buffer_size - 1) << CDT3_BD_SHIFT) |
-               (dbr_address << CDT3_BA_SHIFT);
-       dim2_write_ctr(CDT + ch_addr, cdt);
-}
-
-static u16 dim2_rpc(u8 ch_addr)
-{
-       u32 cdt0 = dim2_read_ctr(CDT + ch_addr, 0);
-
-       return (cdt0 >> CDT0_RPC_SHIFT) & CDT0_RPC_MASK;
-}
-
-static void dim2_clear_cdt(u8 ch_addr)
-{
-       u32 cdt[4] = { 0, 0, 0, 0 };
-
-       dim2_write_ctr(CDT + ch_addr, cdt);
-}
-
-static void dim2_configure_adt(u8 ch_addr)
-{
-       u32 adt[4] = { 0, 0, 0, 0 };
-
-       adt[0] =
-               (true << ADT0_CE_BIT) |
-               (true << ADT0_LE_BIT) |
-               (0 << ADT0_PG_BIT);
-
-       dim2_write_ctr(ADT + ch_addr, adt);
-}
-
-static void dim2_clear_adt(u8 ch_addr)
-{
-       u32 adt[4] = { 0, 0, 0, 0 };
-
-       dim2_write_ctr(ADT + ch_addr, adt);
-}
-
-static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr,
-                                 u16 buffer_size)
-{
-       u8 const shift = idx * 16;
-
-       u32 mask[4] = { 0, 0, 0, 0 };
-       u32 adt[4] = { 0, 0, 0, 0 };
-
-       mask[1] =
-               bit_mask(ADT1_PS_BIT + shift) |
-               bit_mask(ADT1_RDY_BIT + shift) |
-               (ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
-       adt[1] =
-               (true << (ADT1_PS_BIT + shift)) |
-               (true << (ADT1_RDY_BIT + shift)) |
-               ((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
-
-       mask[idx + 2] = 0xFFFFFFFF;
-       adt[idx + 2] = buf_addr;
-
-       dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
-}
-
-static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr,
-                                u16 buffer_size)
-{
-       u8 const shift = idx * 16;
-
-       u32 mask[4] = { 0, 0, 0, 0 };
-       u32 adt[4] = { 0, 0, 0, 0 };
-
-       mask[1] =
-               bit_mask(ADT1_RDY_BIT + shift) |
-               (ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
-       adt[1] =
-               (true << (ADT1_RDY_BIT + shift)) |
-               ((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
-
-       mask[idx + 2] = 0xFFFFFFFF;
-       adt[idx + 2] = buf_addr;
-
-       dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
-}
-
-static void dim2_clear_ctram(void)
-{
-       u32 ctr_addr;
-
-       for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++)
-               dim2_clear_ctr(ctr_addr);
-}
-
-static void dim2_configure_channel(
-       u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size,
-       u16 packet_length)
-{
-       dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length);
-       dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0);
-
-       dim2_configure_adt(ch_addr);
-       dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1);
-
-       /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */
-       dimcb_io_write(&g.dim2->ACMR0,
-                      dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr));
-}
-
-static void dim2_clear_channel(u8 ch_addr)
-{
-       /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */
-       dimcb_io_write(&g.dim2->ACMR0,
-                      dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr));
-
-       dim2_clear_cat(AHB_CAT, ch_addr);
-       dim2_clear_adt(ch_addr);
-
-       dim2_clear_cat(MLB_CAT, ch_addr);
-       dim2_clear_cdt(ch_addr);
-
-       /* clear channel status bit */
-       dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr));
-}
-
-/* -------------------------------------------------------------------------- */
-/* trace async tx dbr fill state */
-
-static inline u16 norm_pc(u16 pc)
-{
-       return pc & CDT0_RPC_MASK;
-}
-
-static void dbrcnt_init(u8 ch_addr, u16 dbr_size)
-{
-       g.atx_dbr.rest_size = dbr_size;
-       g.atx_dbr.rpc = dim2_rpc(ch_addr);
-       g.atx_dbr.wpc = g.atx_dbr.rpc;
-}
-
-static void dbrcnt_enq(int buf_sz)
-{
-       g.atx_dbr.rest_size -= buf_sz;
-       g.atx_dbr.sz_queue[norm_pc(g.atx_dbr.wpc)] = buf_sz;
-       g.atx_dbr.wpc++;
-}
-
-u16 dim_dbr_space(struct dim_channel *ch)
-{
-       u16 cur_rpc;
-       struct async_tx_dbr *dbr = &g.atx_dbr;
-
-       if (ch->addr != dbr->ch_addr)
-               return 0xFFFF;
-
-       cur_rpc = dim2_rpc(ch->addr);
-
-       while (norm_pc(dbr->rpc) != cur_rpc) {
-               dbr->rest_size += dbr->sz_queue[norm_pc(dbr->rpc)];
-               dbr->rpc++;
-       }
-
-       if ((u16)(dbr->wpc - dbr->rpc) >= CDT0_RPC_MASK)
-               return 0;
-
-       return dbr->rest_size;
-}
-
-/* -------------------------------------------------------------------------- */
-/* channel state helpers */
-
-static void state_init(struct int_ch_state *state)
-{
-       state->request_counter = 0;
-       state->service_counter = 0;
-
-       state->idx1 = 0;
-       state->idx2 = 0;
-       state->level = 0;
-}
-
-/* -------------------------------------------------------------------------- */
-/* macro helper functions */
-
-static inline bool check_channel_address(u32 ch_address)
-{
-       return ch_address > 0 && (ch_address % 2) == 0 &&
-              (ch_address / 2) <= (u32)CAT_CL_MASK;
-}
-
-static inline bool check_packet_length(u32 packet_length)
-{
-       u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR;
-
-       if (packet_length <= 0)
-               return false; /* too small */
-
-       if (packet_length > max_size)
-               return false; /* too big */
-
-       if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK)
-               return false; /* too big */
-
-       return true;
-}
-
-static inline bool check_bytes_per_frame(u32 bytes_per_frame)
-{
-       u16 const bd_factor = g.fcnt + 2;
-       u16 const max_size = ((u16)CDT3_BD_MASK + 1u) >> bd_factor;
-
-       if (bytes_per_frame <= 0)
-               return false; /* too small */
-
-       if (bytes_per_frame > max_size)
-               return false; /* too big */
-
-       return true;
-}
-
-static inline u16 norm_ctrl_async_buffer_size(u16 buf_size)
-{
-       u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u;
-
-       if (buf_size > max_size)
-               return max_size;
-
-       return buf_size;
-}
-
-static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
-{
-       u16 n;
-       u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
-
-       if (buf_size > max_size)
-               buf_size = max_size;
-
-       n = buf_size / packet_length;
-
-       if (n < 2u)
-               return 0; /* too small buffer for given packet_length */
-
-       return packet_length * n;
-}
-
-static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
-{
-       u16 n;
-       u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
-       u32 const unit = bytes_per_frame << g.fcnt;
-
-       if (buf_size > max_size)
-               buf_size = max_size;
-
-       n = buf_size / unit;
-
-       if (n < 1u)
-               return 0; /* too small buffer for given bytes_per_frame */
-
-       return unit * n;
-}
-
-static void dim2_cleanup(void)
-{
-       /* disable MediaLB */
-       dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT);
-
-       dim2_clear_ctram();
-
-       /* disable mlb_int interrupt */
-       dimcb_io_write(&g.dim2->MIEN, 0);
-
-       /* clear status for all dma channels */
-       dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF);
-       dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF);
-
-       /* mask interrupts for all channels */
-       dimcb_io_write(&g.dim2->ACMR0, 0);
-       dimcb_io_write(&g.dim2->ACMR1, 0);
-}
-
-static void dim2_initialize(bool enable_6pin, u8 mlb_clock)
-{
-       dim2_cleanup();
-
-       /* configure and enable MediaLB */
-       dimcb_io_write(&g.dim2->MLBC0,
-                      enable_6pin << MLBC0_MLBPEN_BIT |
-                      mlb_clock << MLBC0_MLBCLK_SHIFT |
-                      g.fcnt << MLBC0_FCNT_SHIFT |
-                      true << MLBC0_MLBEN_BIT);
-
-       /* activate all HBI channels */
-       dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF);
-       dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF);
-
-       /* enable HBI */
-       dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT));
-
-       /* configure DMA */
-       dimcb_io_write(&g.dim2->ACTL,
-                      ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT |
-                      true << ACTL_SCE_BIT);
-}
-
-static bool dim2_is_mlb_locked(void)
-{
-       u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT);
-       u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) |
-                         bit_mask(MLBC1_LOCKERR_BIT);
-       u32 const c1 = dimcb_io_read(&g.dim2->MLBC1);
-       u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT;
-
-       dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask);
-       return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 &&
-              (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0;
-}
-
-/* -------------------------------------------------------------------------- */
-/* channel help routines */
-
-static inline bool service_channel(u8 ch_addr, u8 idx)
-{
-       u8 const shift = idx * 16;
-       u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1);
-       u32 mask[4] = { 0, 0, 0, 0 };
-       u32 adt_w[4] = { 0, 0, 0, 0 };
-
-       if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0)
-               return false;
-
-       mask[1] =
-               bit_mask(ADT1_DNE_BIT + shift) |
-               bit_mask(ADT1_ERR_BIT + shift) |
-               bit_mask(ADT1_RDY_BIT + shift);
-       dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w);
-
-       /* clear channel status bit */
-       dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr));
-
-       return true;
-}
-
-/* -------------------------------------------------------------------------- */
-/* channel init routines */
-
-static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length)
-{
-       state_init(&ch->state);
-
-       ch->addr = ch_addr;
-
-       ch->packet_length = packet_length;
-       ch->bytes_per_frame = 0;
-       ch->done_sw_buffers_number = 0;
-}
-
-static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame)
-{
-       state_init(&ch->state);
-
-       ch->addr = ch_addr;
-
-       ch->packet_length = 0;
-       ch->bytes_per_frame = bytes_per_frame;
-       ch->done_sw_buffers_number = 0;
-}
-
-static void channel_init(struct dim_channel *ch, u8 ch_addr)
-{
-       state_init(&ch->state);
-
-       ch->addr = ch_addr;
-
-       ch->packet_length = 0;
-       ch->bytes_per_frame = 0;
-       ch->done_sw_buffers_number = 0;
-}
-
-/* returns true if channel interrupt state is cleared */
-static bool channel_service_interrupt(struct dim_channel *ch)
-{
-       struct int_ch_state *const state = &ch->state;
-
-       if (!service_channel(ch->addr, state->idx2))
-               return false;
-
-       state->idx2 ^= 1;
-       state->request_counter++;
-       return true;
-}
-
-static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size)
-{
-       struct int_ch_state *const state = &ch->state;
-
-       if (buf_size <= 0)
-               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size");
-
-       if (ch->packet_length == 0 && ch->bytes_per_frame == 0 &&
-           buf_size != norm_ctrl_async_buffer_size(buf_size))
-               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
-                                   "Bad control/async buffer size");
-
-       if (ch->packet_length &&
-           buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length))
-               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
-                                   "Bad isochronous buffer size");
-
-       if (ch->bytes_per_frame &&
-           buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame))
-               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
-                                   "Bad synchronous buffer size");
-
-       if (state->level >= 2u)
-               return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow");
-
-       ++state->level;
-
-       if (ch->addr == g.atx_dbr.ch_addr)
-               dbrcnt_enq(buf_size);
-
-       if (ch->packet_length || ch->bytes_per_frame)
-               dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size);
-       else
-               dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr,
-                                     buf_size);
-       state->idx1 ^= 1;
-
-       return true;
-}
-
-static u8 channel_service(struct dim_channel *ch)
-{
-       struct int_ch_state *const state = &ch->state;
-
-       if (state->service_counter != state->request_counter) {
-               state->service_counter++;
-               if (state->level == 0)
-                       return DIM_ERR_UNDERFLOW;
-
-               --state->level;
-               ch->done_sw_buffers_number++;
-       }
-
-       return DIM_NO_ERROR;
-}
-
-static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number)
-{
-       if (buffers_number > ch->done_sw_buffers_number)
-               return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow");
-
-       ch->done_sw_buffers_number -= buffers_number;
-       return true;
-}
-
-/* -------------------------------------------------------------------------- */
-/* API */
-
-u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock,
-              u32 fcnt)
-{
-       g.dim_is_initialized = false;
-
-       if (!dim_base_address)
-               return DIM_INIT_ERR_DIM_ADDR;
-
-       /* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */
-       /* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */
-       if (mlb_clock >= 8)
-               return DIM_INIT_ERR_MLB_CLOCK;
-
-       if (fcnt > MLBC0_FCNT_MAX_VAL)
-               return DIM_INIT_ERR_MLB_CLOCK;
-
-       g.dim2 = dim_base_address;
-       g.fcnt = fcnt;
-       g.dbr_map[0] = 0;
-       g.dbr_map[1] = 0;
-
-       dim2_initialize(mlb_clock >= 3, mlb_clock);
-
-       g.dim_is_initialized = true;
-
-       return DIM_NO_ERROR;
-}
-
-void dim_shutdown(void)
-{
-       g.dim_is_initialized = false;
-       dim2_cleanup();
-}
-
-bool dim_get_lock_state(void)
-{
-       return dim2_is_mlb_locked();
-}
-
-static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx,
-                         u16 ch_address, u16 hw_buffer_size)
-{
-       if (!g.dim_is_initialized || !ch)
-               return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-       if (!check_channel_address(ch_address))
-               return DIM_INIT_ERR_CHANNEL_ADDRESS;
-
-       ch->dbr_size = ROUND_UP_TO(hw_buffer_size, DBR_BLOCK_SIZE);
-       ch->dbr_addr = alloc_dbr(ch->dbr_size);
-       if (ch->dbr_addr >= DBR_SIZE)
-               return DIM_INIT_ERR_OUT_OF_MEMORY;
-
-       channel_init(ch, ch_address / 2);
-
-       dim2_configure_channel(ch->addr, type, is_tx,
-                              ch->dbr_addr, ch->dbr_size, 0);
-
-       return DIM_NO_ERROR;
-}
-
-void dim_service_mlb_int_irq(void)
-{
-       dimcb_io_write(&g.dim2->MS0, 0);
-       dimcb_io_write(&g.dim2->MS1, 0);
-}
-
-u16 dim_norm_ctrl_async_buffer_size(u16 buf_size)
-{
-       return norm_ctrl_async_buffer_size(buf_size);
-}
-
-/**
- * Retrieves maximal possible correct buffer size for isochronous data type
- * conform to given packet length and not bigger than given buffer size.
- *
- * Returns non-zero correct buffer size or zero by error.
- */
-u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
-{
-       if (!check_packet_length(packet_length))
-               return 0;
-
-       return norm_isoc_buffer_size(buf_size, packet_length);
-}
-
-/**
- * Retrieves maximal possible correct buffer size for synchronous data type
- * conform to given bytes per frame and not bigger than given buffer size.
- *
- * Returns non-zero correct buffer size or zero by error.
- */
-u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
-{
-       if (!check_bytes_per_frame(bytes_per_frame))
-               return 0;
-
-       return norm_sync_buffer_size(buf_size, bytes_per_frame);
-}
-
-u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-                   u16 max_buffer_size)
-{
-       return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address,
-                              max_buffer_size);
-}
-
-u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-                 u16 max_buffer_size)
-{
-       u8 ret = init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address,
-                                max_buffer_size);
-
-       if (is_tx && !g.atx_dbr.ch_addr) {
-               g.atx_dbr.ch_addr = ch->addr;
-               dbrcnt_init(ch->addr, ch->dbr_size);
-               dimcb_io_write(&g.dim2->MIEN, bit_mask(20));
-       }
-
-       return ret;
-}
-
-u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-                u16 packet_length)
-{
-       if (!g.dim_is_initialized || !ch)
-               return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-       if (!check_channel_address(ch_address))
-               return DIM_INIT_ERR_CHANNEL_ADDRESS;
-
-       if (!check_packet_length(packet_length))
-               return DIM_ERR_BAD_CONFIG;
-
-       ch->dbr_size = packet_length * ISOC_DBR_FACTOR;
-       ch->dbr_addr = alloc_dbr(ch->dbr_size);
-       if (ch->dbr_addr >= DBR_SIZE)
-               return DIM_INIT_ERR_OUT_OF_MEMORY;
-
-       isoc_init(ch, ch_address / 2, packet_length);
-
-       dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr,
-                              ch->dbr_size, packet_length);
-
-       return DIM_NO_ERROR;
-}
-
-u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-                u16 bytes_per_frame)
-{
-       u16 bd_factor = g.fcnt + 2;
-
-       if (!g.dim_is_initialized || !ch)
-               return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-       if (!check_channel_address(ch_address))
-               return DIM_INIT_ERR_CHANNEL_ADDRESS;
-
-       if (!check_bytes_per_frame(bytes_per_frame))
-               return DIM_ERR_BAD_CONFIG;
-
-       ch->dbr_size = bytes_per_frame << bd_factor;
-       ch->dbr_addr = alloc_dbr(ch->dbr_size);
-       if (ch->dbr_addr >= DBR_SIZE)
-               return DIM_INIT_ERR_OUT_OF_MEMORY;
-
-       sync_init(ch, ch_address / 2, bytes_per_frame);
-
-       dim2_clear_dbr(ch->dbr_addr, ch->dbr_size);
-       dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx,
-                              ch->dbr_addr, ch->dbr_size, 0);
-
-       return DIM_NO_ERROR;
-}
-
-u8 dim_destroy_channel(struct dim_channel *ch)
-{
-       if (!g.dim_is_initialized || !ch)
-               return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-       if (ch->addr == g.atx_dbr.ch_addr) {
-               dimcb_io_write(&g.dim2->MIEN, 0);
-               g.atx_dbr.ch_addr = 0;
-       }
-
-       dim2_clear_channel(ch->addr);
-       if (ch->dbr_addr < DBR_SIZE)
-               free_dbr(ch->dbr_addr, ch->dbr_size);
-       ch->dbr_addr = DBR_SIZE;
-
-       return DIM_NO_ERROR;
-}
-
-void dim_service_ahb_int_irq(struct dim_channel *const *channels)
-{
-       bool state_changed;
-
-       if (!g.dim_is_initialized) {
-               dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
-                            "DIM is not initialized");
-               return;
-       }
-
-       if (!channels) {
-               dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels");
-               return;
-       }
-
-       /*
-        * Use while-loop and a flag to make sure the age is changed back at
-        * least once, otherwise the interrupt may never come if CPU generates
-        * interrupt on changing age.
-        * This cycle runs not more than number of channels, because
-        * channel_service_interrupt() routine doesn't start the channel again.
-        */
-       do {
-               struct dim_channel *const *ch = channels;
-
-               state_changed = false;
-
-               while (*ch) {
-                       state_changed |= channel_service_interrupt(*ch);
-                       ++ch;
-               }
-       } while (state_changed);
-}
-
-u8 dim_service_channel(struct dim_channel *ch)
-{
-       if (!g.dim_is_initialized || !ch)
-               return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-       return channel_service(ch);
-}
-
-struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
-                                            struct dim_ch_state_t *state_ptr)
-{
-       if (!ch || !state_ptr)
-               return NULL;
-
-       state_ptr->ready = ch->state.level < 2;
-       state_ptr->done_buffers = ch->done_sw_buffers_number;
-
-       return state_ptr;
-}
-
-bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
-                       u16 buffer_size)
-{
-       if (!ch)
-               return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
-                                   "Bad channel");
-
-       return channel_start(ch, buffer_addr, buffer_size);
-}
-
-bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number)
-{
-       if (!ch)
-               return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
-                                   "Bad channel");
-
-       return channel_detach_buffers(ch, buffers_number);
-}
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h
deleted file mode 100644 (file)
index 6df6ea5..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * dim2_hal.h - DIM2 HAL interface
- * (MediaLB, Device Interface Macro IP, OS62420)
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#ifndef _DIM2_HAL_H
-#define _DIM2_HAL_H
-
-#include <linux/types.h>
-#include "dim2_reg.h"
-
-/*
- * The values below are specified in the hardware specification.
- * So, they should not be changed until the hardware specification changes.
- */
-enum mlb_clk_speed {
-       CLK_256FS = 0,
-       CLK_512FS = 1,
-       CLK_1024FS = 2,
-       CLK_2048FS = 3,
-       CLK_3072FS = 4,
-       CLK_4096FS = 5,
-       CLK_6144FS = 6,
-       CLK_8192FS = 7,
-};
-
-struct dim_ch_state_t {
-       bool ready; /* Shows readiness to enqueue next buffer */
-       u16 done_buffers; /* Number of completed buffers */
-};
-
-struct int_ch_state {
-       /* changed only in interrupt context */
-       volatile int request_counter;
-
-       /* changed only in task context */
-       volatile int service_counter;
-
-       u8 idx1;
-       u8 idx2;
-       u8 level; /* [0..2], buffering level */
-};
-
-struct dim_channel {
-       struct int_ch_state state;
-       u8 addr;
-       u16 dbr_addr;
-       u16 dbr_size;
-       u16 packet_length; /*< Isochronous packet length in bytes. */
-       u16 bytes_per_frame; /*< Synchronous bytes per frame. */
-       u16 done_sw_buffers_number; /*< Done software buffers number. */
-};
-
-u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock,
-              u32 fcnt);
-
-void dim_shutdown(void);
-
-bool dim_get_lock_state(void);
-
-u16 dim_norm_ctrl_async_buffer_size(u16 buf_size);
-
-u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length);
-
-u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame);
-
-u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-                   u16 max_buffer_size);
-
-u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-                 u16 max_buffer_size);
-
-u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-                u16 packet_length);
-
-u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-                u16 bytes_per_frame);
-
-u8 dim_destroy_channel(struct dim_channel *ch);
-
-void dim_service_mlb_int_irq(void);
-
-void dim_service_ahb_int_irq(struct dim_channel *const *channels);
-
-u8 dim_service_channel(struct dim_channel *ch);
-
-struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
-                                            struct dim_ch_state_t *state_ptr);
-
-u16 dim_dbr_space(struct dim_channel *ch);
-
-bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
-                       u16 buffer_size);
-
-bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number);
-
-u32 dimcb_io_read(u32 __iomem *ptr32);
-
-void dimcb_io_write(u32 __iomem *ptr32, u32 value);
-
-void dimcb_on_error(u8 error_id, const char *error_message);
-
-#endif /* _DIM2_HAL_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c
deleted file mode 100644 (file)
index df7021c..0000000
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module
- *
- * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/printk.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-
-#include <mostcore.h>
-#include "dim2_hal.h"
-#include "dim2_hdm.h"
-#include "dim2_errors.h"
-#include "dim2_sysfs.h"
-
-#define DMA_CHANNELS (32 - 1)  /* channel 0 is a system channel */
-
-#define MAX_BUFFERS_PACKET      32
-#define MAX_BUFFERS_STREAMING   32
-#define MAX_BUF_SIZE_PACKET     2048
-#define MAX_BUF_SIZE_STREAMING  (8 * 1024)
-
-/* command line parameter to select clock speed */
-static char *clock_speed;
-module_param(clock_speed, charp, 0000);
-MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed");
-
-/*
- * The parameter representing the number of frames per sub-buffer for
- * synchronous channels.  Valid values: [0 .. 6].
- *
- * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per
- * sub-buffer 1, 2, 4, 8, 16, 32, 64.
- */
-static u8 fcnt = 4;  /* (1 << fcnt) frames per subbuffer */
-module_param(fcnt, byte, 0000);
-MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2");
-
-static DEFINE_SPINLOCK(dim_lock);
-
-static void dim2_tasklet_fn(unsigned long data);
-static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0);
-
-/**
- * struct hdm_channel - private structure to keep channel specific data
- * @is_initialized: identifier to know whether the channel is initialized
- * @ch: HAL specific channel data
- * @pending_list: list to keep MBO's before starting transfer
- * @started_list: list to keep MBO's after starting transfer
- * @direction: channel direction (TX or RX)
- * @data_type: channel data type
- */
-struct hdm_channel {
-       char name[sizeof "caNNN"];
-       bool is_initialized;
-       struct dim_channel ch;
-       struct list_head pending_list;  /* before dim_enqueue_buffer() */
-       struct list_head started_list;  /* after dim_enqueue_buffer() */
-       enum most_channel_direction direction;
-       enum most_channel_data_type data_type;
-};
-
-/**
- * struct dim2_hdm - private structure to keep interface specific data
- * @hch: an array of channel specific data
- * @most_iface: most interface structure
- * @capabilities: an array of channel capability data
- * @io_base: I/O register base address
- * @clk_speed: user selectable (through command line parameter) clock speed
- * @netinfo_task: thread to deliver network status
- * @netinfo_waitq: waitq for the thread to sleep
- * @deliver_netinfo: to identify whether network status received
- * @mac_addrs: INIC mac address
- * @link_state: network link state
- * @atx_idx: index of async tx channel
- */
-struct dim2_hdm {
-       struct hdm_channel hch[DMA_CHANNELS];
-       struct most_channel_capability capabilities[DMA_CHANNELS];
-       struct most_interface most_iface;
-       char name[16 + sizeof "dim2-"];
-       void __iomem *io_base;
-       int clk_speed;
-       struct task_struct *netinfo_task;
-       wait_queue_head_t netinfo_waitq;
-       int deliver_netinfo;
-       unsigned char mac_addrs[6];
-       unsigned char link_state;
-       int atx_idx;
-       struct medialb_bus bus;
-       void (*on_netinfo)(struct most_interface *,
-                          unsigned char, unsigned char *);
-};
-
-#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface)
-
-/* Macro to identify a network status message */
-#define PACKET_IS_NET_INFO(p)  \
-       (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \
-        ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A))
-
-bool dim2_sysfs_get_state_cb(void)
-{
-       bool state;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dim_lock, flags);
-       state = dim_get_lock_state();
-       spin_unlock_irqrestore(&dim_lock, flags);
-
-       return state;
-}
-
-/**
- * dimcb_io_read - callback from HAL to read an I/O register
- * @ptr32: register address
- */
-u32 dimcb_io_read(u32 __iomem *ptr32)
-{
-       return readl(ptr32);
-}
-
-/**
- * dimcb_io_write - callback from HAL to write value to an I/O register
- * @ptr32: register address
- * @value: value to write
- */
-void dimcb_io_write(u32 __iomem *ptr32, u32 value)
-{
-       writel(value, ptr32);
-}
-
-/**
- * dimcb_on_error - callback from HAL to report miscommunication between
- * HDM and HAL
- * @error_id: Error ID
- * @error_message: Error message. Some text in a free format
- */
-void dimcb_on_error(u8 error_id, const char *error_message)
-{
-       pr_err("dimcb_on_error: error_id - %d, error_message - %s\n", error_id,
-              error_message);
-}
-
-/**
- * startup_dim - initialize the dim2 interface
- * @pdev: platform device
- *
- * Get the value of command line parameter "clock_speed" if given or use the
- * default value, enable the clock and PLL, and initialize the dim2 interface.
- */
-static int startup_dim(struct platform_device *pdev)
-{
-       struct dim2_hdm *dev = platform_get_drvdata(pdev);
-       struct dim2_platform_data *pdata = pdev->dev.platform_data;
-       u8 hal_ret;
-
-       dev->clk_speed = -1;
-
-       if (clock_speed) {
-               if (!strcmp(clock_speed, "256fs"))
-                       dev->clk_speed = CLK_256FS;
-               else if (!strcmp(clock_speed, "512fs"))
-                       dev->clk_speed = CLK_512FS;
-               else if (!strcmp(clock_speed, "1024fs"))
-                       dev->clk_speed = CLK_1024FS;
-               else if (!strcmp(clock_speed, "2048fs"))
-                       dev->clk_speed = CLK_2048FS;
-               else if (!strcmp(clock_speed, "3072fs"))
-                       dev->clk_speed = CLK_3072FS;
-               else if (!strcmp(clock_speed, "4096fs"))
-                       dev->clk_speed = CLK_4096FS;
-               else if (!strcmp(clock_speed, "6144fs"))
-                       dev->clk_speed = CLK_6144FS;
-               else if (!strcmp(clock_speed, "8192fs"))
-                       dev->clk_speed = CLK_8192FS;
-       }
-
-       if (dev->clk_speed == -1) {
-               pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n");
-               dev->clk_speed = CLK_3072FS;
-       } else {
-               pr_info("Selected clock speed: %s\n", clock_speed);
-       }
-       if (pdata && pdata->init) {
-               int ret = pdata->init(pdata, dev->io_base, dev->clk_speed);
-
-               if (ret)
-                       return ret;
-       }
-
-       pr_info("sync: num of frames per sub-buffer: %u\n", fcnt);
-       hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt);
-       if (hal_ret != DIM_NO_ERROR) {
-               pr_err("dim_startup failed: %d\n", hal_ret);
-               if (pdata && pdata->destroy)
-                       pdata->destroy(pdata);
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-/**
- * try_start_dim_transfer - try to transfer a buffer on a channel
- * @hdm_ch: channel specific data
- *
- * Transfer a buffer from pending_list if the channel is ready
- */
-static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
-{
-       u16 buf_size;
-       struct list_head *head = &hdm_ch->pending_list;
-       struct mbo *mbo;
-       unsigned long flags;
-       struct dim_ch_state_t st;
-
-       BUG_ON(!hdm_ch);
-       BUG_ON(!hdm_ch->is_initialized);
-
-       spin_lock_irqsave(&dim_lock, flags);
-       if (list_empty(head)) {
-               spin_unlock_irqrestore(&dim_lock, flags);
-               return -EAGAIN;
-       }
-
-       if (!dim_get_channel_state(&hdm_ch->ch, &st)->ready) {
-               spin_unlock_irqrestore(&dim_lock, flags);
-               return -EAGAIN;
-       }
-
-       mbo = list_first_entry(head, struct mbo, list);
-       buf_size = mbo->buffer_length;
-
-       if (dim_dbr_space(&hdm_ch->ch) < buf_size) {
-               spin_unlock_irqrestore(&dim_lock, flags);
-               return -EAGAIN;
-       }
-
-       BUG_ON(mbo->bus_address == 0);
-       if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) {
-               list_del(head->next);
-               spin_unlock_irqrestore(&dim_lock, flags);
-               mbo->processed_length = 0;
-               mbo->status = MBO_E_INVAL;
-               mbo->complete(mbo);
-               return -EFAULT;
-       }
-
-       list_move_tail(head->next, &hdm_ch->started_list);
-       spin_unlock_irqrestore(&dim_lock, flags);
-
-       return 0;
-}
-
-/**
- * deliver_netinfo_thread - thread to deliver network status to mostcore
- * @data: private data
- *
- * Wait for network status and deliver it to mostcore once it is received
- */
-static int deliver_netinfo_thread(void *data)
-{
-       struct dim2_hdm *dev = data;
-
-       while (!kthread_should_stop()) {
-               wait_event_interruptible(dev->netinfo_waitq,
-                                        dev->deliver_netinfo ||
-                                        kthread_should_stop());
-
-               if (dev->deliver_netinfo) {
-                       dev->deliver_netinfo--;
-                       if (dev->on_netinfo) {
-                               dev->on_netinfo(&dev->most_iface,
-                                               dev->link_state,
-                                               dev->mac_addrs);
-                       }
-               }
-       }
-
-       return 0;
-}
-
-/**
- * retrieve_netinfo - retrieve network status from received buffer
- * @dev: private data
- * @mbo: received MBO
- *
- * Parse the message in buffer and get node address, link state, MAC address.
- * Wake up a thread to deliver this status to mostcore
- */
-static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo)
-{
-       u8 *data = mbo->virt_address;
-
-       pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]);
-       dev->link_state = data[18];
-       pr_info("NIState: %d\n", dev->link_state);
-       memcpy(dev->mac_addrs, data + 19, 6);
-       dev->deliver_netinfo++;
-       wake_up_interruptible(&dev->netinfo_waitq);
-}
-
-/**
- * service_done_flag - handle completed buffers
- * @dev: private data
- * @ch_idx: channel index
- *
- * Return back the completed buffers to mostcore, using completion callback
- */
-static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
-{
-       struct hdm_channel *hdm_ch = dev->hch + ch_idx;
-       struct dim_ch_state_t st;
-       struct list_head *head;
-       struct mbo *mbo;
-       int done_buffers;
-       unsigned long flags;
-       u8 *data;
-
-       BUG_ON(!hdm_ch);
-       BUG_ON(!hdm_ch->is_initialized);
-
-       spin_lock_irqsave(&dim_lock, flags);
-
-       done_buffers = dim_get_channel_state(&hdm_ch->ch, &st)->done_buffers;
-       if (!done_buffers) {
-               spin_unlock_irqrestore(&dim_lock, flags);
-               return;
-       }
-
-       if (!dim_detach_buffers(&hdm_ch->ch, done_buffers)) {
-               spin_unlock_irqrestore(&dim_lock, flags);
-               return;
-       }
-       spin_unlock_irqrestore(&dim_lock, flags);
-
-       head = &hdm_ch->started_list;
-
-       while (done_buffers) {
-               spin_lock_irqsave(&dim_lock, flags);
-               if (list_empty(head)) {
-                       spin_unlock_irqrestore(&dim_lock, flags);
-                       pr_crit("hard error: started_mbo list is empty whereas DIM2 has sent buffers\n");
-                       break;
-               }
-
-               mbo = list_first_entry(head, struct mbo, list);
-               list_del(head->next);
-               spin_unlock_irqrestore(&dim_lock, flags);
-
-               data = mbo->virt_address;
-
-               if (hdm_ch->data_type == MOST_CH_ASYNC &&
-                   hdm_ch->direction == MOST_CH_RX &&
-                   PACKET_IS_NET_INFO(data)) {
-                       retrieve_netinfo(dev, mbo);
-
-                       spin_lock_irqsave(&dim_lock, flags);
-                       list_add_tail(&mbo->list, &hdm_ch->pending_list);
-                       spin_unlock_irqrestore(&dim_lock, flags);
-               } else {
-                       if (hdm_ch->data_type == MOST_CH_CONTROL ||
-                           hdm_ch->data_type == MOST_CH_ASYNC) {
-                               u32 const data_size =
-                                       (u32)data[0] * 256 + data[1] + 2;
-
-                               mbo->processed_length =
-                                       min_t(u32, data_size,
-                                             mbo->buffer_length);
-                       } else {
-                               mbo->processed_length = mbo->buffer_length;
-                       }
-                       mbo->status = MBO_SUCCESS;
-                       mbo->complete(mbo);
-               }
-
-               done_buffers--;
-       }
-}
-
-static struct dim_channel **get_active_channels(struct dim2_hdm *dev,
-                                               struct dim_channel **buffer)
-{
-       int idx = 0;
-       int ch_idx;
-
-       for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
-               if (dev->hch[ch_idx].is_initialized)
-                       buffer[idx++] = &dev->hch[ch_idx].ch;
-       }
-       buffer[idx++] = NULL;
-
-       return buffer;
-}
-
-static irqreturn_t dim2_mlb_isr(int irq, void *_dev)
-{
-       struct dim2_hdm *dev = _dev;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dim_lock, flags);
-       dim_service_mlb_int_irq();
-       spin_unlock_irqrestore(&dim_lock, flags);
-
-       if (dev->atx_idx >= 0 && dev->hch[dev->atx_idx].is_initialized)
-               while (!try_start_dim_transfer(dev->hch + dev->atx_idx))
-                       continue;
-
-       return IRQ_HANDLED;
-}
-
-/**
- * dim2_tasklet_fn - tasklet function
- * @data: private data
- *
- * Service each initialized channel, if needed
- */
-static void dim2_tasklet_fn(unsigned long data)
-{
-       struct dim2_hdm *dev = (struct dim2_hdm *)data;
-       unsigned long flags;
-       int ch_idx;
-
-       for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
-               if (!dev->hch[ch_idx].is_initialized)
-                       continue;
-
-               spin_lock_irqsave(&dim_lock, flags);
-               dim_service_channel(&dev->hch[ch_idx].ch);
-               spin_unlock_irqrestore(&dim_lock, flags);
-
-               service_done_flag(dev, ch_idx);
-               while (!try_start_dim_transfer(dev->hch + ch_idx))
-                       continue;
-       }
-}
-
-/**
- * dim2_ahb_isr - interrupt service routine
- * @irq: irq number
- * @_dev: private data
- *
- * Acknowledge the interrupt and schedule a tasklet to service channels.
- * Return IRQ_HANDLED.
- */
-static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
-{
-       struct dim2_hdm *dev = _dev;
-       struct dim_channel *buffer[DMA_CHANNELS + 1];
-       unsigned long flags;
-
-       spin_lock_irqsave(&dim_lock, flags);
-       dim_service_ahb_int_irq(get_active_channels(dev, buffer));
-       spin_unlock_irqrestore(&dim_lock, flags);
-
-       dim2_tasklet.data = (unsigned long)dev;
-       tasklet_schedule(&dim2_tasklet);
-       return IRQ_HANDLED;
-}
-
-/**
- * complete_all_mbos - complete MBO's in a list
- * @head: list head
- *
- * Delete all the entries in list and return back MBO's to mostcore using
- * completion call back.
- */
-static void complete_all_mbos(struct list_head *head)
-{
-       unsigned long flags;
-       struct mbo *mbo;
-
-       for (;;) {
-               spin_lock_irqsave(&dim_lock, flags);
-               if (list_empty(head)) {
-                       spin_unlock_irqrestore(&dim_lock, flags);
-                       break;
-               }
-
-               mbo = list_first_entry(head, struct mbo, list);
-               list_del(head->next);
-               spin_unlock_irqrestore(&dim_lock, flags);
-
-               mbo->processed_length = 0;
-               mbo->status = MBO_E_CLOSE;
-               mbo->complete(mbo);
-       }
-}
-
-/**
- * configure_channel - initialize a channel
- * @iface: interface the channel belongs to
- * @channel: channel to be configured
- * @channel_config: structure that holds the configuration information
- *
- * Receives configuration information from mostcore and initialize
- * the corresponding channel. Return 0 on success, negative on failure.
- */
-static int configure_channel(struct most_interface *most_iface, int ch_idx,
-                            struct most_channel_config *ccfg)
-{
-       struct dim2_hdm *dev = iface_to_hdm(most_iface);
-       bool const is_tx = ccfg->direction == MOST_CH_TX;
-       u16 const sub_size = ccfg->subbuffer_size;
-       u16 const buf_size = ccfg->buffer_size;
-       u16 new_size;
-       unsigned long flags;
-       u8 hal_ret;
-       int const ch_addr = ch_idx * 2 + 2;
-       struct hdm_channel *const hdm_ch = dev->hch + ch_idx;
-
-       BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
-
-       if (hdm_ch->is_initialized)
-               return -EPERM;
-
-       switch (ccfg->data_type) {
-       case MOST_CH_CONTROL:
-               new_size = dim_norm_ctrl_async_buffer_size(buf_size);
-               if (new_size == 0) {
-                       pr_err("%s: too small buffer size\n", hdm_ch->name);
-                       return -EINVAL;
-               }
-               ccfg->buffer_size = new_size;
-               if (new_size != buf_size)
-                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
-                               hdm_ch->name, buf_size, new_size);
-               spin_lock_irqsave(&dim_lock, flags);
-               hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr,
-                                          is_tx ? new_size * 2 : new_size);
-               break;
-       case MOST_CH_ASYNC:
-               new_size = dim_norm_ctrl_async_buffer_size(buf_size);
-               if (new_size == 0) {
-                       pr_err("%s: too small buffer size\n", hdm_ch->name);
-                       return -EINVAL;
-               }
-               ccfg->buffer_size = new_size;
-               if (new_size != buf_size)
-                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
-                               hdm_ch->name, buf_size, new_size);
-               spin_lock_irqsave(&dim_lock, flags);
-               hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr,
-                                        is_tx ? new_size * 2 : new_size);
-               break;
-       case MOST_CH_ISOC:
-               new_size = dim_norm_isoc_buffer_size(buf_size, sub_size);
-               if (new_size == 0) {
-                       pr_err("%s: invalid sub-buffer size or too small buffer size\n",
-                              hdm_ch->name);
-                       return -EINVAL;
-               }
-               ccfg->buffer_size = new_size;
-               if (new_size != buf_size)
-                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
-                               hdm_ch->name, buf_size, new_size);
-               spin_lock_irqsave(&dim_lock, flags);
-               hal_ret = dim_init_isoc(&hdm_ch->ch, is_tx, ch_addr, sub_size);
-               break;
-       case MOST_CH_SYNC:
-               new_size = dim_norm_sync_buffer_size(buf_size, sub_size);
-               if (new_size == 0) {
-                       pr_err("%s: invalid sub-buffer size or too small buffer size\n",
-                              hdm_ch->name);
-                       return -EINVAL;
-               }
-               ccfg->buffer_size = new_size;
-               if (new_size != buf_size)
-                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
-                               hdm_ch->name, buf_size, new_size);
-               spin_lock_irqsave(&dim_lock, flags);
-               hal_ret = dim_init_sync(&hdm_ch->ch, is_tx, ch_addr, sub_size);
-               break;
-       default:
-               pr_err("%s: configure failed, bad channel type: %d\n",
-                      hdm_ch->name, ccfg->data_type);
-               return -EINVAL;
-       }
-
-       if (hal_ret != DIM_NO_ERROR) {
-               spin_unlock_irqrestore(&dim_lock, flags);
-               pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n",
-                      hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx);
-               return -ENODEV;
-       }
-
-       hdm_ch->data_type = ccfg->data_type;
-       hdm_ch->direction = ccfg->direction;
-       hdm_ch->is_initialized = true;
-
-       if (hdm_ch->data_type == MOST_CH_ASYNC &&
-           hdm_ch->direction == MOST_CH_TX &&
-           dev->atx_idx < 0)
-               dev->atx_idx = ch_idx;
-
-       spin_unlock_irqrestore(&dim_lock, flags);
-
-       return 0;
-}
-
-/**
- * enqueue - enqueue a buffer for data transfer
- * @iface: intended interface
- * @channel: ID of the channel the buffer is intended for
- * @mbo: pointer to the buffer object
- *
- * Push the buffer into pending_list and try to transfer one buffer from
- * pending_list. Return 0 on success, negative on failure.
- */
-static int enqueue(struct most_interface *most_iface, int ch_idx,
-                  struct mbo *mbo)
-{
-       struct dim2_hdm *dev = iface_to_hdm(most_iface);
-       struct hdm_channel *hdm_ch = dev->hch + ch_idx;
-       unsigned long flags;
-
-       BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
-
-       if (!hdm_ch->is_initialized)
-               return -EPERM;
-
-       if (mbo->bus_address == 0)
-               return -EFAULT;
-
-       spin_lock_irqsave(&dim_lock, flags);
-       list_add_tail(&mbo->list, &hdm_ch->pending_list);
-       spin_unlock_irqrestore(&dim_lock, flags);
-
-       (void)try_start_dim_transfer(hdm_ch);
-
-       return 0;
-}
-
-/**
- * request_netinfo - triggers retrieving of network info
- * @iface: pointer to the interface
- * @channel_id: corresponding channel ID
- *
- * Send a command to INIC which triggers retrieving of network info by means of
- * "Message exchange over MDP/MEP". Return 0 on success, negative on failure.
- */
-static void request_netinfo(struct most_interface *most_iface, int ch_idx,
-                           void (*on_netinfo)(struct most_interface *,
-                                              unsigned char, unsigned char *))
-{
-       struct dim2_hdm *dev = iface_to_hdm(most_iface);
-       struct mbo *mbo;
-       u8 *data;
-
-       dev->on_netinfo = on_netinfo;
-       if (!on_netinfo)
-               return;
-
-       if (dev->atx_idx < 0) {
-               pr_err("Async Tx Not initialized\n");
-               return;
-       }
-
-       mbo = most_get_mbo(&dev->most_iface, dev->atx_idx, NULL);
-       if (!mbo)
-               return;
-
-       mbo->buffer_length = 5;
-
-       data = mbo->virt_address;
-
-       data[0] = 0x00; /* PML High byte */
-       data[1] = 0x03; /* PML Low byte */
-       data[2] = 0x02; /* PMHL */
-       data[3] = 0x08; /* FPH */
-       data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */
-
-       most_submit_mbo(mbo);
-}
-
-/**
- * poison_channel - poison buffers of a channel
- * @iface: pointer to the interface the channel to be poisoned belongs to
- * @channel_id: corresponding channel ID
- *
- * Destroy a channel and complete all the buffers in both started_list &
- * pending_list. Return 0 on success, negative on failure.
- */
-static int poison_channel(struct most_interface *most_iface, int ch_idx)
-{
-       struct dim2_hdm *dev = iface_to_hdm(most_iface);
-       struct hdm_channel *hdm_ch = dev->hch + ch_idx;
-       unsigned long flags;
-       u8 hal_ret;
-       int ret = 0;
-
-       BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
-
-       if (!hdm_ch->is_initialized)
-               return -EPERM;
-
-       tasklet_disable(&dim2_tasklet);
-       spin_lock_irqsave(&dim_lock, flags);
-       hal_ret = dim_destroy_channel(&hdm_ch->ch);
-       hdm_ch->is_initialized = false;
-       if (ch_idx == dev->atx_idx)
-               dev->atx_idx = -1;
-       spin_unlock_irqrestore(&dim_lock, flags);
-       tasklet_enable(&dim2_tasklet);
-       if (hal_ret != DIM_NO_ERROR) {
-               pr_err("HAL Failed to close channel %s\n", hdm_ch->name);
-               ret = -EFAULT;
-       }
-
-       complete_all_mbos(&hdm_ch->started_list);
-       complete_all_mbos(&hdm_ch->pending_list);
-
-       return ret;
-}
-
-/*
- * dim2_probe - dim2 probe handler
- * @pdev: platform device structure
- *
- * Register the dim2 interface with mostcore and initialize it.
- * Return 0 on success, negative on failure.
- */
-static int dim2_probe(struct platform_device *pdev)
-{
-       struct dim2_hdm *dev;
-       struct resource *res;
-       int ret, i;
-       struct kobject *kobj;
-       int irq;
-
-       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return -ENOMEM;
-
-       dev->atx_idx = -1;
-
-       platform_set_drvdata(pdev, dev);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       dev->io_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(dev->io_base))
-               return PTR_ERR(dev->io_base);
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq);
-               return irq;
-       }
-
-       ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0,
-                              "dim2_ahb0_int", dev);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq);
-               return ret;
-       }
-
-       irq = platform_get_irq(pdev, 1);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq);
-               return irq;
-       }
-
-       ret = devm_request_irq(&pdev->dev, irq, dim2_mlb_isr, 0,
-                              "dim2_mlb_int", dev);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq);
-               return ret;
-       }
-
-       init_waitqueue_head(&dev->netinfo_waitq);
-       dev->deliver_netinfo = 0;
-       dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev,
-                                       "dim2_netinfo");
-       if (IS_ERR(dev->netinfo_task))
-               return PTR_ERR(dev->netinfo_task);
-
-       for (i = 0; i < DMA_CHANNELS; i++) {
-               struct most_channel_capability *cap = dev->capabilities + i;
-               struct hdm_channel *hdm_ch = dev->hch + i;
-
-               INIT_LIST_HEAD(&hdm_ch->pending_list);
-               INIT_LIST_HEAD(&hdm_ch->started_list);
-               hdm_ch->is_initialized = false;
-               snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2);
-
-               cap->name_suffix = hdm_ch->name;
-               cap->direction = MOST_CH_RX | MOST_CH_TX;
-               cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
-                                MOST_CH_ISOC | MOST_CH_SYNC;
-               cap->num_buffers_packet = MAX_BUFFERS_PACKET;
-               cap->buffer_size_packet = MAX_BUF_SIZE_PACKET;
-               cap->num_buffers_streaming = MAX_BUFFERS_STREAMING;
-               cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING;
-       }
-
-       {
-               const char *fmt;
-
-               if (sizeof(res->start) == sizeof(long long))
-                       fmt = "dim2-%016llx";
-               else if (sizeof(res->start) == sizeof(long))
-                       fmt = "dim2-%016lx";
-               else
-                       fmt = "dim2-%016x";
-
-               snprintf(dev->name, sizeof(dev->name), fmt, res->start);
-       }
-
-       dev->most_iface.interface = ITYPE_MEDIALB_DIM2;
-       dev->most_iface.description = dev->name;
-       dev->most_iface.num_channels = DMA_CHANNELS;
-       dev->most_iface.channel_vector = dev->capabilities;
-       dev->most_iface.configure = configure_channel;
-       dev->most_iface.enqueue = enqueue;
-       dev->most_iface.poison_channel = poison_channel;
-       dev->most_iface.request_netinfo = request_netinfo;
-
-       kobj = most_register_interface(&dev->most_iface);
-       if (IS_ERR(kobj)) {
-               ret = PTR_ERR(kobj);
-               dev_err(&pdev->dev, "failed to register MOST interface\n");
-               goto err_stop_thread;
-       }
-
-       ret = dim2_sysfs_probe(&dev->bus, kobj);
-       if (ret)
-               goto err_unreg_iface;
-
-       ret = startup_dim(pdev);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to initialize DIM2\n");
-               goto err_destroy_bus;
-       }
-
-       return 0;
-
-err_destroy_bus:
-       dim2_sysfs_destroy(&dev->bus);
-err_unreg_iface:
-       most_deregister_interface(&dev->most_iface);
-err_stop_thread:
-       kthread_stop(dev->netinfo_task);
-
-       return ret;
-}
-
-/**
- * dim2_remove - dim2 remove handler
- * @pdev: platform device structure
- *
- * Unregister the interface from mostcore
- */
-static int dim2_remove(struct platform_device *pdev)
-{
-       struct dim2_hdm *dev = platform_get_drvdata(pdev);
-       struct dim2_platform_data *pdata = pdev->dev.platform_data;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dim_lock, flags);
-       dim_shutdown();
-       spin_unlock_irqrestore(&dim_lock, flags);
-
-       if (pdata && pdata->destroy)
-               pdata->destroy(pdata);
-
-       dim2_sysfs_destroy(&dev->bus);
-       most_deregister_interface(&dev->most_iface);
-       kthread_stop(dev->netinfo_task);
-
-       /*
-        * break link to local platform_device_id struct
-        * to prevent crash by unload platform device module
-        */
-       pdev->id_entry = NULL;
-
-       return 0;
-}
-
-static const struct platform_device_id dim2_id[] = {
-       { "medialb_dim2" },
-       { }, /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(platform, dim2_id);
-
-static struct platform_driver dim2_driver = {
-       .probe = dim2_probe,
-       .remove = dim2_remove,
-       .id_table = dim2_id,
-       .driver = {
-               .name = "hdm_dim2",
-       },
-};
-
-module_platform_driver(dim2_driver);
-
-MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
-MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
-MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h
deleted file mode 100644 (file)
index 4050e7c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * dim2_hdm.h - MediaLB DIM2 HDM Header
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#ifndef DIM2_HDM_H
-#define        DIM2_HDM_H
-
-struct device;
-
-/* platform dependent data for dim2 interface */
-struct dim2_platform_data {
-       int (*init)(struct dim2_platform_data *pd, void __iomem *io_base,
-                   int clk_speed);
-       void (*destroy)(struct dim2_platform_data *pd);
-       void *priv;
-};
-
-#endif /* DIM2_HDM_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h
deleted file mode 100644 (file)
index f7d9fbc..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * dim2_reg.h - Definitions for registers of DIM2
- * (MediaLB, Device Interface Macro IP, OS62420)
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#ifndef DIM2_OS62420_H
-#define        DIM2_OS62420_H
-
-#include <linux/types.h>
-
-struct dim2_regs {
-       /* 0x00 */ u32 MLBC0;
-       /* 0x01 */ u32 rsvd0[1];
-       /* 0x02 */ u32 MLBPC0;
-       /* 0x03 */ u32 MS0;
-       /* 0x04 */ u32 rsvd1[1];
-       /* 0x05 */ u32 MS1;
-       /* 0x06 */ u32 rsvd2[2];
-       /* 0x08 */ u32 MSS;
-       /* 0x09 */ u32 MSD;
-       /* 0x0A */ u32 rsvd3[1];
-       /* 0x0B */ u32 MIEN;
-       /* 0x0C */ u32 rsvd4[1];
-       /* 0x0D */ u32 MLBPC2;
-       /* 0x0E */ u32 MLBPC1;
-       /* 0x0F */ u32 MLBC1;
-       /* 0x10 */ u32 rsvd5[0x10];
-       /* 0x20 */ u32 HCTL;
-       /* 0x21 */ u32 rsvd6[1];
-       /* 0x22 */ u32 HCMR0;
-       /* 0x23 */ u32 HCMR1;
-       /* 0x24 */ u32 HCER0;
-       /* 0x25 */ u32 HCER1;
-       /* 0x26 */ u32 HCBR0;
-       /* 0x27 */ u32 HCBR1;
-       /* 0x28 */ u32 rsvd7[8];
-       /* 0x30 */ u32 MDAT0;
-       /* 0x31 */ u32 MDAT1;
-       /* 0x32 */ u32 MDAT2;
-       /* 0x33 */ u32 MDAT3;
-       /* 0x34 */ u32 MDWE0;
-       /* 0x35 */ u32 MDWE1;
-       /* 0x36 */ u32 MDWE2;
-       /* 0x37 */ u32 MDWE3;
-       /* 0x38 */ u32 MCTL;
-       /* 0x39 */ u32 MADR;
-       /* 0x3A */ u32 rsvd8[0xB6];
-       /* 0xF0 */ u32 ACTL;
-       /* 0xF1 */ u32 rsvd9[3];
-       /* 0xF4 */ u32 ACSR0;
-       /* 0xF5 */ u32 ACSR1;
-       /* 0xF6 */ u32 ACMR0;
-       /* 0xF7 */ u32 ACMR1;
-};
-
-#define DIM2_MASK(n)  (~((~(u32)0) << (n)))
-
-enum {
-       MLBC0_MLBLK_BIT = 7,
-
-       MLBC0_MLBPEN_BIT = 5,
-
-       MLBC0_MLBCLK_SHIFT = 2,
-       MLBC0_MLBCLK_VAL_256FS = 0,
-       MLBC0_MLBCLK_VAL_512FS = 1,
-       MLBC0_MLBCLK_VAL_1024FS = 2,
-       MLBC0_MLBCLK_VAL_2048FS = 3,
-
-       MLBC0_FCNT_SHIFT = 15,
-       MLBC0_FCNT_MASK = 7,
-       MLBC0_FCNT_MAX_VAL = 6,
-
-       MLBC0_MLBEN_BIT = 0,
-
-       MIEN_CTX_BREAK_BIT = 29,
-       MIEN_CTX_PE_BIT = 28,
-       MIEN_CTX_DONE_BIT = 27,
-
-       MIEN_CRX_BREAK_BIT = 26,
-       MIEN_CRX_PE_BIT = 25,
-       MIEN_CRX_DONE_BIT = 24,
-
-       MIEN_ATX_BREAK_BIT = 22,
-       MIEN_ATX_PE_BIT = 21,
-       MIEN_ATX_DONE_BIT = 20,
-
-       MIEN_ARX_BREAK_BIT = 19,
-       MIEN_ARX_PE_BIT = 18,
-       MIEN_ARX_DONE_BIT = 17,
-
-       MIEN_SYNC_PE_BIT = 16,
-
-       MIEN_ISOC_BUFO_BIT = 1,
-       MIEN_ISOC_PE_BIT = 0,
-
-       MLBC1_NDA_SHIFT = 8,
-       MLBC1_NDA_MASK = 0xFF,
-
-       MLBC1_CLKMERR_BIT = 7,
-       MLBC1_LOCKERR_BIT = 6,
-
-       ACTL_DMA_MODE_BIT = 2,
-       ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0,
-       ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1,
-       ACTL_SCE_BIT = 0,
-
-       HCTL_EN_BIT = 15
-};
-
-enum {
-       CDT0_RPC_SHIFT = 16 + 11,
-       CDT0_RPC_MASK = DIM2_MASK(5),
-
-       CDT1_BS_ISOC_SHIFT = 0,
-       CDT1_BS_ISOC_MASK = DIM2_MASK(9),
-
-       CDT3_BD_SHIFT = 0,
-       CDT3_BD_MASK = DIM2_MASK(12),
-       CDT3_BD_ISOC_MASK = DIM2_MASK(13),
-       CDT3_BA_SHIFT = 16,
-
-       ADT0_CE_BIT = 15,
-       ADT0_LE_BIT = 14,
-       ADT0_PG_BIT = 13,
-
-       ADT1_RDY_BIT = 15,
-       ADT1_DNE_BIT = 14,
-       ADT1_ERR_BIT = 13,
-       ADT1_PS_BIT = 12,
-       ADT1_MEP_BIT = 11,
-       ADT1_BD_SHIFT = 0,
-       ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
-       ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),
-
-       CAT_FCE_BIT = 14,
-       CAT_MFE_BIT = 14,
-
-       CAT_MT_BIT = 13,
-
-       CAT_RNW_BIT = 12,
-
-       CAT_CE_BIT = 11,
-
-       CAT_CT_SHIFT = 8,
-       CAT_CT_VAL_SYNC = 0,
-       CAT_CT_VAL_CONTROL = 1,
-       CAT_CT_VAL_ASYNC = 2,
-       CAT_CT_VAL_ISOC = 3,
-
-       CAT_CL_SHIFT = 0,
-       CAT_CL_MASK = DIM2_MASK(6)
-};
-
-#endif /* DIM2_OS62420_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c
deleted file mode 100644 (file)
index d8b22f9..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * dim2_sysfs.c - MediaLB sysfs information
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include "dim2_sysfs.h"
-
-struct bus_attr {
-       struct attribute attr;
-       ssize_t (*show)(struct medialb_bus *bus, char *buf);
-       ssize_t (*store)(struct medialb_bus *bus, const char *buf,
-                        size_t count);
-};
-
-static ssize_t state_show(struct medialb_bus *bus, char *buf)
-{
-       bool state = dim2_sysfs_get_state_cb();
-
-       return sprintf(buf, "%s\n", state ? "locked" : "");
-}
-
-static struct bus_attr state_attr = __ATTR_RO(state);
-
-static struct attribute *bus_default_attrs[] = {
-       &state_attr.attr,
-       NULL,
-};
-
-static const struct attribute_group bus_attr_group = {
-       .attrs = bus_default_attrs,
-};
-
-static void bus_kobj_release(struct kobject *kobj)
-{
-}
-
-static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
-                                 char *buf)
-{
-       struct medialb_bus *bus =
-               container_of(kobj, struct medialb_bus, kobj_group);
-       struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
-
-       if (!xattr->show)
-               return -EIO;
-
-       return xattr->show(bus, buf);
-}
-
-static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
-                                  const char *buf, size_t count)
-{
-       struct medialb_bus *bus =
-               container_of(kobj, struct medialb_bus, kobj_group);
-       struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
-
-       if (!xattr->store)
-               return -EIO;
-
-       return xattr->store(bus, buf, count);
-}
-
-static struct sysfs_ops const bus_kobj_sysfs_ops = {
-       .show = bus_kobj_attr_show,
-       .store = bus_kobj_attr_store,
-};
-
-static struct kobj_type bus_ktype = {
-       .release = bus_kobj_release,
-       .sysfs_ops = &bus_kobj_sysfs_ops,
-};
-
-int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
-{
-       int err;
-
-       kobject_init(&bus->kobj_group, &bus_ktype);
-       err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
-       if (err) {
-               pr_err("kobject_add() failed: %d\n", err);
-               goto err_kobject_add;
-       }
-
-       err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
-       if (err) {
-               pr_err("sysfs_create_group() failed: %d\n", err);
-               goto err_create_group;
-       }
-
-       return 0;
-
-err_create_group:
-       kobject_put(&bus->kobj_group);
-
-err_kobject_add:
-       return err;
-}
-
-void dim2_sysfs_destroy(struct medialb_bus *bus)
-{
-       kobject_put(&bus->kobj_group);
-}
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h
deleted file mode 100644 (file)
index b71dd02..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * dim2_sysfs.h - MediaLB sysfs information
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
-
-#ifndef DIM2_SYSFS_H
-#define        DIM2_SYSFS_H
-
-#include <linux/kobject.h>
-
-struct medialb_bus {
-       struct kobject kobj_group;
-};
-
-struct dim2_hdm;
-
-int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj);
-void dim2_sysfs_destroy(struct medialb_bus *bus);
-
-/*
- * callback,
- * must deliver MediaLB state as true if locked or false if unlocked
- */
-bool dim2_sysfs_get_state_cb(void);
-
-#endif /* DIM2_SYSFS_H */
diff --git a/drivers/staging/most/hdm-i2c/Kconfig b/drivers/staging/most/hdm-i2c/Kconfig
deleted file mode 100644 (file)
index 6fd7983..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# MOST I2C configuration
-#
-
-config HDM_I2C
-       tristate "I2C HDM"
-       depends on I2C
-       ---help---
-         Say Y here if you want to connect via I2C to network tranceiver.
-
-         To compile this driver as a module, choose M here: the
-         module will be called hdm_i2c.
diff --git a/drivers/staging/most/hdm-i2c/Makefile b/drivers/staging/most/hdm-i2c/Makefile
deleted file mode 100644 (file)
index 03a4a59..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_HDM_I2C) += hdm_i2c.o
-
-ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c
deleted file mode 100644 (file)
index 2b4de40..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * hdm_i2c.c - Hardware Dependent Module for I2C Interface
- *
- * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-
-#include <mostcore.h>
-
-enum { CH_RX, CH_TX, NUM_CHANNELS };
-
-#define MAX_BUFFERS_CONTROL 32
-#define MAX_BUF_SIZE_CONTROL 256
-
-/**
- * list_first_mbo - get the first mbo from a list
- * @ptr:       the list head to take the mbo from.
- */
-#define list_first_mbo(ptr) \
-       list_first_entry(ptr, struct mbo, list)
-
-/* IRQ / Polling option */
-static bool polling_req;
-module_param(polling_req, bool, 0444);
-MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)");
-
-/* Polling Rate */
-static int scan_rate = 100;
-module_param(scan_rate, int, 0644);
-MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 100");
-
-struct hdm_i2c {
-       bool is_open[NUM_CHANNELS];
-       bool polling_mode;
-       struct most_interface most_iface;
-       struct most_channel_capability capabilities[NUM_CHANNELS];
-       struct i2c_client *client;
-       struct rx {
-               struct delayed_work dwork;
-               wait_queue_head_t waitq;
-               struct list_head list;
-               struct mutex list_mutex;
-       } rx;
-       char name[64];
-};
-
-#define to_hdm(iface) container_of(iface, struct hdm_i2c, most_iface)
-
-/**
- * configure_channel - called from MOST core to configure a channel
- * @iface: interface the channel belongs to
- * @channel: channel to be configured
- * @channel_config: structure that holds the configuration information
- *
- * Return 0 on success, negative on failure.
- *
- * Receives configuration information from MOST core and initialize the
- * corresponding channel.
- */
-static int configure_channel(struct most_interface *most_iface,
-                            int ch_idx,
-                            struct most_channel_config *channel_config)
-{
-       struct hdm_i2c *dev = to_hdm(most_iface);
-
-       BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
-       BUG_ON(dev->is_open[ch_idx]);
-
-       if (channel_config->data_type != MOST_CH_CONTROL) {
-               pr_err("bad data type for channel %d\n", ch_idx);
-               return -EPERM;
-       }
-
-       if (channel_config->direction != dev->capabilities[ch_idx].direction) {
-               pr_err("bad direction for channel %d\n", ch_idx);
-               return -EPERM;
-       }
-
-       if ((channel_config->direction == MOST_CH_RX) && (dev->polling_mode)) {
-               schedule_delayed_work(&dev->rx.dwork,
-                                     msecs_to_jiffies(MSEC_PER_SEC / 4));
-       }
-       dev->is_open[ch_idx] = true;
-
-       return 0;
-}
-
-/**
- * enqueue - called from MOST core to enqueue a buffer for data transfer
- * @iface: intended interface
- * @channel: ID of the channel the buffer is intended for
- * @mbo: pointer to the buffer object
- *
- * Return 0 on success, negative on failure.
- *
- * Transmit the data over I2C if it is a "write" request or push the buffer into
- * list if it is an "read" request
- */
-static int enqueue(struct most_interface *most_iface,
-                  int ch_idx, struct mbo *mbo)
-{
-       struct hdm_i2c *dev = to_hdm(most_iface);
-       int ret;
-
-       BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
-       BUG_ON(!dev->is_open[ch_idx]);
-
-       if (ch_idx == CH_RX) {
-               /* RX */
-               mutex_lock(&dev->rx.list_mutex);
-               list_add_tail(&mbo->list, &dev->rx.list);
-               mutex_unlock(&dev->rx.list_mutex);
-               wake_up_interruptible(&dev->rx.waitq);
-       } else {
-               /* TX */
-               ret = i2c_master_send(dev->client, mbo->virt_address,
-                                     mbo->buffer_length);
-               if (ret <= 0) {
-                       mbo->processed_length = 0;
-                       mbo->status = MBO_E_INVAL;
-               } else {
-                       mbo->processed_length = mbo->buffer_length;
-                       mbo->status = MBO_SUCCESS;
-               }
-               mbo->complete(mbo);
-       }
-
-       return 0;
-}
-
-/**
- * poison_channel - called from MOST core to poison buffers of a channel
- * @iface: pointer to the interface the channel to be poisoned belongs to
- * @channel_id: corresponding channel ID
- *
- * Return 0 on success, negative on failure.
- *
- * If channel direction is RX, complete the buffers in list with
- * status MBO_E_CLOSE
- */
-static int poison_channel(struct most_interface *most_iface,
-                         int ch_idx)
-{
-       struct hdm_i2c *dev = to_hdm(most_iface);
-       struct mbo *mbo;
-
-       BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
-       BUG_ON(!dev->is_open[ch_idx]);
-
-       dev->is_open[ch_idx] = false;
-
-       if (ch_idx == CH_RX) {
-               mutex_lock(&dev->rx.list_mutex);
-               while (!list_empty(&dev->rx.list)) {
-                       mbo = list_first_mbo(&dev->rx.list);
-                       list_del(&mbo->list);
-                       mutex_unlock(&dev->rx.list_mutex);
-
-                       mbo->processed_length = 0;
-                       mbo->status = MBO_E_CLOSE;
-                       mbo->complete(mbo);
-
-                       mutex_lock(&dev->rx.list_mutex);
-               }
-               mutex_unlock(&dev->rx.list_mutex);
-               wake_up_interruptible(&dev->rx.waitq);
-       }
-
-       return 0;
-}
-
-static void do_rx_work(struct hdm_i2c *dev)
-{
-       struct mbo *mbo;
-       unsigned char msg[MAX_BUF_SIZE_CONTROL];
-       int ret, ch_idx = CH_RX;
-       u16 pml, data_size;
-
-       /* Read PML (2 bytes) */
-       ret = i2c_master_recv(dev->client, msg, 2);
-       if (ret <= 0) {
-               pr_err("Failed to receive PML\n");
-               return;
-       }
-
-       pml = (msg[0] << 8) | msg[1];
-       if (!pml)
-               return;
-
-       data_size = pml + 2;
-
-       /* Read the whole message, including PML */
-       ret = i2c_master_recv(dev->client, msg, data_size);
-       if (ret <= 0) {
-               pr_err("Failed to receive a Port Message\n");
-               return;
-       }
-
-       for (;;) {
-               /* Conditions to wait for: poisoned channel or free buffer
-                * available for reading
-                */
-               if (wait_event_interruptible(dev->rx.waitq,
-                                            !dev->is_open[ch_idx] ||
-                                            !list_empty(&dev->rx.list))) {
-                       pr_err("wait_event_interruptible() failed\n");
-                       return;
-               }
-
-               if (!dev->is_open[ch_idx])
-                       return;
-
-               mutex_lock(&dev->rx.list_mutex);
-
-               /* list may be empty if poison or remove is called */
-               if (!list_empty(&dev->rx.list))
-                       break;
-
-               mutex_unlock(&dev->rx.list_mutex);
-       }
-
-       mbo = list_first_mbo(&dev->rx.list);
-       list_del(&mbo->list);
-       mutex_unlock(&dev->rx.list_mutex);
-
-       mbo->processed_length = min(data_size, mbo->buffer_length);
-       memcpy(mbo->virt_address, msg, mbo->processed_length);
-       mbo->status = MBO_SUCCESS;
-       mbo->complete(mbo);
-}
-
-/**
- * pending_rx_work - Read pending messages through I2C
- * @work: definition of this work item
- *
- * Invoked by the Interrupt Service Routine, most_irq_handler()
- */
-static void pending_rx_work(struct work_struct *work)
-{
-       struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work);
-
-       do_rx_work(dev);
-
-       if (dev->polling_mode) {
-               if (dev->is_open[CH_RX])
-                       schedule_delayed_work(&dev->rx.dwork,
-                                             msecs_to_jiffies(MSEC_PER_SEC
-                                                              / scan_rate));
-       } else {
-               enable_irq(dev->client->irq);
-       }
-}
-
-/*
- * most_irq_handler - Interrupt Service Routine
- * @irq: irq number
- * @_dev: private data
- *
- * Schedules a delayed work
- *
- * By default the interrupt line behavior is Active Low. Once an interrupt is
- * generated by the device, until driver clears the interrupt (by reading
- * the PMP message), device keeps the interrupt line in low state. Since i2c
- * read is done in work queue, the interrupt line must be disabled temporarily
- * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue,
- * after reading the message.
- *
- * Note: If we use the interrupt line in Falling edge mode, there is a
- * possibility to miss interrupts when ISR is getting executed.
- *
- */
-static irqreturn_t most_irq_handler(int irq, void *_dev)
-{
-       struct hdm_i2c *dev = _dev;
-
-       disable_irq_nosync(irq);
-
-       schedule_delayed_work(&dev->rx.dwork, 0);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * i2c_probe - i2c probe handler
- * @client: i2c client device structure
- * @id: i2c client device id
- *
- * Return 0 on success, negative on failure.
- *
- * Register the i2c client device as a MOST interface
- */
-static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
-       struct hdm_i2c *dev;
-       int ret, i;
-       struct kobject *kobj;
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return -ENOMEM;
-
-       /* ID format: i2c-<bus>-<address> */
-       snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x",
-                client->adapter->nr, client->addr);
-
-       for (i = 0; i < NUM_CHANNELS; i++) {
-               dev->is_open[i] = false;
-               dev->capabilities[i].data_type = MOST_CH_CONTROL;
-               dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL;
-               dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL;
-       }
-       dev->capabilities[CH_RX].direction = MOST_CH_RX;
-       dev->capabilities[CH_RX].name_suffix = "rx";
-       dev->capabilities[CH_TX].direction = MOST_CH_TX;
-       dev->capabilities[CH_TX].name_suffix = "tx";
-
-       dev->most_iface.interface = ITYPE_I2C;
-       dev->most_iface.description = dev->name;
-       dev->most_iface.num_channels = NUM_CHANNELS;
-       dev->most_iface.channel_vector = dev->capabilities;
-       dev->most_iface.configure = configure_channel;
-       dev->most_iface.enqueue = enqueue;
-       dev->most_iface.poison_channel = poison_channel;
-
-       INIT_LIST_HEAD(&dev->rx.list);
-       mutex_init(&dev->rx.list_mutex);
-       init_waitqueue_head(&dev->rx.waitq);
-
-       INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work);
-
-       dev->client = client;
-       i2c_set_clientdata(client, dev);
-
-       kobj = most_register_interface(&dev->most_iface);
-       if (IS_ERR(kobj)) {
-               pr_err("Failed to register i2c as a MOST interface\n");
-               kfree(dev);
-               return PTR_ERR(kobj);
-       }
-
-       dev->polling_mode = polling_req || client->irq <= 0;
-       if (!dev->polling_mode) {
-               pr_info("Requesting IRQ: %d\n", client->irq);
-               ret = request_irq(client->irq, most_irq_handler, 0,
-                                 client->name, dev);
-               if (ret) {
-                       pr_info("IRQ request failed: %d, falling back to polling\n",
-                               ret);
-                       dev->polling_mode = true;
-               }
-       }
-
-       if (dev->polling_mode)
-               pr_info("Using polling at rate: %d times/sec\n", scan_rate);
-
-       return 0;
-}
-
-/*
- * i2c_remove - i2c remove handler
- * @client: i2c client device structure
- *
- * Return 0 on success.
- *
- * Unregister the i2c client device as a MOST interface
- */
-static int i2c_remove(struct i2c_client *client)
-{
-       struct hdm_i2c *dev = i2c_get_clientdata(client);
-       int i;
-
-       if (!dev->polling_mode)
-               free_irq(client->irq, dev);
-
-       most_deregister_interface(&dev->most_iface);
-
-       for (i = 0 ; i < NUM_CHANNELS; i++)
-               if (dev->is_open[i])
-                       poison_channel(&dev->most_iface, i);
-       cancel_delayed_work_sync(&dev->rx.dwork);
-       kfree(dev);
-
-       return 0;
-}
-
-static const struct i2c_device_id i2c_id[] = {
-       { "most_i2c", 0 },
-       { }, /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(i2c, i2c_id);
-
-static struct i2c_driver i2c_driver = {
-       .driver = {
-               .name = "hdm_i2c",
-       },
-       .probe = i2c_probe,
-       .remove = i2c_remove,
-       .id_table = i2c_id,
-};
-
-module_i2c_driver(i2c_driver);
-
-MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
-MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
-MODULE_DESCRIPTION("I2C Hardware Dependent Module");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-usb/Kconfig b/drivers/staging/most/hdm-usb/Kconfig
deleted file mode 100644 (file)
index 487f1f3..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# MOST USB configuration
-#
-
-config HDM_USB
-       tristate "USB HDM"
-       depends on USB && NET
-
-       ---help---
-         Say Y here if you want to connect via USB to network tranceiver.
-         This device driver depends on the networking AIM.
-
-         To compile this driver as a module, choose M here: the
-         module will be called hdm_usb.
diff --git a/drivers/staging/most/hdm-usb/Makefile b/drivers/staging/most/hdm-usb/Makefile
deleted file mode 100644 (file)
index 6bbacb4..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_HDM_USB) += hdm_usb.o
-
-ccflags-y += -Idrivers/staging/most/mostcore/
-ccflags-y += -Idrivers/staging/most/aim-network/
diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c
deleted file mode 100644 (file)
index 667daca..0000000
+++ /dev/null
@@ -1,1306 +0,0 @@
-/*
- * hdm_usb.c - Hardware dependent module for USB
- *
- * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/cdev.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/completion.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/sysfs.h>
-#include <linux/dma-mapping.h>
-#include <linux/etherdevice.h>
-#include <linux/uaccess.h>
-#include "mostcore.h"
-
-#define USB_MTU                        512
-#define NO_ISOCHRONOUS_URB     0
-#define AV_PACKETS_PER_XACT    2
-#define BUF_CHAIN_SIZE         0xFFFF
-#define MAX_NUM_ENDPOINTS      30
-#define MAX_SUFFIX_LEN         10
-#define MAX_STRING_LEN         80
-#define MAX_BUF_SIZE           0xFFFF
-
-#define USB_VENDOR_ID_SMSC     0x0424  /* VID: SMSC */
-#define USB_DEV_ID_BRDG                0xC001  /* PID: USB Bridge */
-#define USB_DEV_ID_OS81118     0xCF18  /* PID: USB OS81118 */
-#define USB_DEV_ID_OS81119     0xCF19  /* PID: USB OS81119 */
-#define USB_DEV_ID_OS81210     0xCF30  /* PID: USB OS81210 */
-/* DRCI Addresses */
-#define DRCI_REG_NI_STATE      0x0100
-#define DRCI_REG_PACKET_BW     0x0101
-#define DRCI_REG_NODE_ADDR     0x0102
-#define DRCI_REG_NODE_POS      0x0103
-#define DRCI_REG_MEP_FILTER    0x0140
-#define DRCI_REG_HASH_TBL0     0x0141
-#define DRCI_REG_HASH_TBL1     0x0142
-#define DRCI_REG_HASH_TBL2     0x0143
-#define DRCI_REG_HASH_TBL3     0x0144
-#define DRCI_REG_HW_ADDR_HI    0x0145
-#define DRCI_REG_HW_ADDR_MI    0x0146
-#define DRCI_REG_HW_ADDR_LO    0x0147
-#define DRCI_REG_BASE          0x1100
-#define DRCI_COMMAND           0x02
-#define DRCI_READ_REQ          0xA0
-#define DRCI_WRITE_REQ         0xA1
-
-/**
- * struct most_dci_obj - Direct Communication Interface
- * @kobj:position in sysfs
- * @usb_device: pointer to the usb device
- * @reg_addr: register address for arbitrary DCI access
- */
-struct most_dci_obj {
-       struct kobject kobj;
-       struct usb_device *usb_device;
-       u16 reg_addr;
-};
-
-#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj)
-
-struct most_dev;
-
-struct clear_hold_work {
-       struct work_struct ws;
-       struct most_dev *mdev;
-       unsigned int channel;
-       int pipe;
-};
-
-#define to_clear_hold_work(w) container_of(w, struct clear_hold_work, ws)
-
-/**
- * struct most_dev - holds all usb interface specific stuff
- * @parent: parent object in sysfs
- * @usb_device: pointer to usb device
- * @iface: hardware interface
- * @cap: channel capabilities
- * @conf: channel configuration
- * @dci: direct communication interface of hardware
- * @ep_address: endpoint address table
- * @description: device description
- * @suffix: suffix for channel name
- * @channel_lock: synchronize channel access
- * @padding_active: indicates channel uses padding
- * @is_channel_healthy: health status table of each channel
- * @busy_urbs: list of anchored items
- * @io_mutex: synchronize I/O with disconnect
- * @link_stat_timer: timer for link status reports
- * @poll_work_obj: work for polling link status
- */
-struct most_dev {
-       struct kobject *parent;
-       struct usb_device *usb_device;
-       struct most_interface iface;
-       struct most_channel_capability *cap;
-       struct most_channel_config *conf;
-       struct most_dci_obj *dci;
-       u8 *ep_address;
-       char description[MAX_STRING_LEN];
-       char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN];
-       spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */
-       bool padding_active[MAX_NUM_ENDPOINTS];
-       bool is_channel_healthy[MAX_NUM_ENDPOINTS];
-       struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS];
-       struct usb_anchor *busy_urbs;
-       struct mutex io_mutex;
-       struct timer_list link_stat_timer;
-       struct work_struct poll_work_obj;
-       void (*on_netinfo)(struct most_interface *, unsigned char,
-                          unsigned char *);
-};
-
-#define to_mdev(d) container_of(d, struct most_dev, iface)
-#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj)
-
-static void wq_clear_halt(struct work_struct *wq_obj);
-static void wq_netinfo(struct work_struct *wq_obj);
-
-/**
- * drci_rd_reg - read a DCI register
- * @dev: usb device
- * @reg: register address
- * @buf: buffer to store data
- *
- * This is reads data from INIC's direct register communication interface
- */
-static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf)
-{
-       int retval;
-       __le16 *dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL);
-       u8 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-
-       if (!dma_buf)
-               return -ENOMEM;
-
-       retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                                DRCI_READ_REQ, req_type,
-                                0x0000,
-                                reg, dma_buf, sizeof(*dma_buf), 5 * HZ);
-       *buf = le16_to_cpu(*dma_buf);
-       kfree(dma_buf);
-
-       return retval;
-}
-
-/**
- * drci_wr_reg - write a DCI register
- * @dev: usb device
- * @reg: register address
- * @data: data to write
- *
- * This is writes data to INIC's direct register communication interface
- */
-static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data)
-{
-       return usb_control_msg(dev,
-                              usb_sndctrlpipe(dev, 0),
-                              DRCI_WRITE_REQ,
-                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                              data,
-                              reg,
-                              NULL,
-                              0,
-                              5 * HZ);
-}
-
-static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep)
-{
-       return drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep * 16, 1);
-}
-
-/**
- * get_stream_frame_size - calculate frame size of current configuration
- * @cfg: channel configuration
- */
-static unsigned int get_stream_frame_size(struct most_channel_config *cfg)
-{
-       unsigned int frame_size = 0;
-       unsigned int sub_size = cfg->subbuffer_size;
-
-       if (!sub_size) {
-               pr_warn("Misconfig: Subbuffer size zero.\n");
-               return frame_size;
-       }
-       switch (cfg->data_type) {
-       case MOST_CH_ISOC:
-               frame_size = AV_PACKETS_PER_XACT * sub_size;
-               break;
-       case MOST_CH_SYNC:
-               if (cfg->packets_per_xact == 0) {
-                       pr_warn("Misconfig: Packets per XACT zero\n");
-                       frame_size = 0;
-               } else if (cfg->packets_per_xact == 0xFF) {
-                       frame_size = (USB_MTU / sub_size) * sub_size;
-               } else {
-                       frame_size = cfg->packets_per_xact * sub_size;
-               }
-               break;
-       default:
-               pr_warn("Query frame size of non-streaming channel\n");
-               break;
-       }
-       return frame_size;
-}
-
-/**
- * hdm_poison_channel - mark buffers of this channel as invalid
- * @iface: pointer to the interface
- * @channel: channel ID
- *
- * This unlinks all URBs submitted to the HCD,
- * calls the associated completion function of the core and removes
- * them from the list.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int hdm_poison_channel(struct most_interface *iface, int channel)
-{
-       struct most_dev *mdev = to_mdev(iface);
-       unsigned long flags;
-       spinlock_t *lock; /* temp. lock */
-
-       if (unlikely(!iface)) {
-               dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n");
-               return -EIO;
-       }
-       if (unlikely(channel < 0 || channel >= iface->num_channels)) {
-               dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n");
-               return -ECHRNG;
-       }
-
-       lock = mdev->channel_lock + channel;
-       spin_lock_irqsave(lock, flags);
-       mdev->is_channel_healthy[channel] = false;
-       spin_unlock_irqrestore(lock, flags);
-
-       cancel_work_sync(&mdev->clear_work[channel].ws);
-
-       mutex_lock(&mdev->io_mutex);
-       usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
-       if (mdev->padding_active[channel])
-               mdev->padding_active[channel] = false;
-
-       if (mdev->conf[channel].data_type == MOST_CH_ASYNC) {
-               del_timer_sync(&mdev->link_stat_timer);
-               cancel_work_sync(&mdev->poll_work_obj);
-       }
-       mutex_unlock(&mdev->io_mutex);
-       return 0;
-}
-
-/**
- * hdm_add_padding - add padding bytes
- * @mdev: most device
- * @channel: channel ID
- * @mbo: buffer object
- *
- * This inserts the INIC hardware specific padding bytes into a streaming
- * channel's buffer
- */
-static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
-{
-       struct most_channel_config *conf = &mdev->conf[channel];
-       unsigned int frame_size = get_stream_frame_size(conf);
-       unsigned int j, num_frames;
-
-       if (!frame_size)
-               return -EIO;
-       num_frames = mbo->buffer_length / frame_size;
-
-       if (num_frames < 1) {
-               dev_err(&mdev->usb_device->dev,
-                       "Missed minimal transfer unit.\n");
-               return -EIO;
-       }
-
-       for (j = num_frames - 1; j > 0; j--)
-               memmove(mbo->virt_address + j * USB_MTU,
-                       mbo->virt_address + j * frame_size,
-                       frame_size);
-       mbo->buffer_length = num_frames * USB_MTU;
-       return 0;
-}
-
-/**
- * hdm_remove_padding - remove padding bytes
- * @mdev: most device
- * @channel: channel ID
- * @mbo: buffer object
- *
- * This takes the INIC hardware specific padding bytes off a streaming
- * channel's buffer.
- */
-static int hdm_remove_padding(struct most_dev *mdev, int channel,
-                             struct mbo *mbo)
-{
-       struct most_channel_config *const conf = &mdev->conf[channel];
-       unsigned int frame_size = get_stream_frame_size(conf);
-       unsigned int j, num_frames;
-
-       if (!frame_size)
-               return -EIO;
-       num_frames = mbo->processed_length / USB_MTU;
-
-       for (j = 1; j < num_frames; j++)
-               memmove(mbo->virt_address + frame_size * j,
-                       mbo->virt_address + USB_MTU * j,
-                       frame_size);
-
-       mbo->processed_length = frame_size * num_frames;
-       return 0;
-}
-
-/**
- * hdm_write_completion - completion function for submitted Tx URBs
- * @urb: the URB that has been completed
- *
- * This checks the status of the completed URB. In case the URB has been
- * unlinked before, it is immediately freed. On any other error the MBO
- * transfer flag is set. On success it frees allocated resources and calls
- * the completion function.
- *
- * Context: interrupt!
- */
-static void hdm_write_completion(struct urb *urb)
-{
-       struct mbo *mbo = urb->context;
-       struct most_dev *mdev = to_mdev(mbo->ifp);
-       unsigned int channel = mbo->hdm_channel_id;
-       struct device *dev = &mdev->usb_device->dev;
-       spinlock_t *lock = mdev->channel_lock + channel;
-       unsigned long flags;
-
-       spin_lock_irqsave(lock, flags);
-
-       mbo->processed_length = 0;
-       mbo->status = MBO_E_INVAL;
-       if (likely(mdev->is_channel_healthy[channel])) {
-               switch (urb->status) {
-               case 0:
-               case -ESHUTDOWN:
-                       mbo->processed_length = urb->actual_length;
-                       mbo->status = MBO_SUCCESS;
-                       break;
-               case -EPIPE:
-                       dev_warn(dev, "Broken OUT pipe detected\n");
-                       mdev->is_channel_healthy[channel] = false;
-                       mdev->clear_work[channel].pipe = urb->pipe;
-                       schedule_work(&mdev->clear_work[channel].ws);
-                       break;
-               case -ENODEV:
-               case -EPROTO:
-                       mbo->status = MBO_E_CLOSE;
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(lock, flags);
-
-       if (likely(mbo->complete))
-               mbo->complete(mbo);
-       usb_free_urb(urb);
-}
-
-/**
- * hdm_read_completion - completion function for submitted Rx URBs
- * @urb: the URB that has been completed
- *
- * This checks the status of the completed URB. In case the URB has been
- * unlinked before it is immediately freed. On any other error the MBO transfer
- * flag is set. On success it frees allocated resources, removes
- * padding bytes -if necessary- and calls the completion function.
- *
- * Context: interrupt!
- *
- * **************************************************************************
- *                   Error codes returned by in urb->status
- *                   or in iso_frame_desc[n].status (for ISO)
- * *************************************************************************
- *
- * USB device drivers may only test urb status values in completion handlers.
- * This is because otherwise there would be a race between HCDs updating
- * these values on one CPU, and device drivers testing them on another CPU.
- *
- * A transfer's actual_length may be positive even when an error has been
- * reported.  That's because transfers often involve several packets, so that
- * one or more packets could finish before an error stops further endpoint I/O.
- *
- * For isochronous URBs, the urb status value is non-zero only if the URB is
- * unlinked, the device is removed, the host controller is disabled or the total
- * transferred length is less than the requested length and the URB_SHORT_NOT_OK
- * flag is set.  Completion handlers for isochronous URBs should only see
- * urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO.
- * Individual frame descriptor status fields may report more status codes.
- *
- *
- * 0                   Transfer completed successfully
- *
- * -ENOENT             URB was synchronously unlinked by usb_unlink_urb
- *
- * -EINPROGRESS                URB still pending, no results yet
- *                     (That is, if drivers see this it's a bug.)
- *
- * -EPROTO (*, **)     a) bitstuff error
- *                     b) no response packet received within the
- *                        prescribed bus turn-around time
- *                     c) unknown USB error
- *
- * -EILSEQ (*, **)     a) CRC mismatch
- *                     b) no response packet received within the
- *                        prescribed bus turn-around time
- *                     c) unknown USB error
- *
- *                     Note that often the controller hardware does not
- *                     distinguish among cases a), b), and c), so a
- *                     driver cannot tell whether there was a protocol
- *                     error, a failure to respond (often caused by
- *                     device disconnect), or some other fault.
- *
- * -ETIME (**)         No response packet received within the prescribed
- *                     bus turn-around time.  This error may instead be
- *                     reported as -EPROTO or -EILSEQ.
- *
- * -ETIMEDOUT          Synchronous USB message functions use this code
- *                     to indicate timeout expired before the transfer
- *                     completed, and no other error was reported by HC.
- *
- * -EPIPE (**)         Endpoint stalled.  For non-control endpoints,
- *                     reset this status with usb_clear_halt().
- *
- * -ECOMM              During an IN transfer, the host controller
- *                     received data from an endpoint faster than it
- *                     could be written to system memory
- *
- * -ENOSR              During an OUT transfer, the host controller
- *                     could not retrieve data from system memory fast
- *                     enough to keep up with the USB data rate
- *
- * -EOVERFLOW (*)      The amount of data returned by the endpoint was
- *                     greater than either the max packet size of the
- *                     endpoint or the remaining buffer size.  "Babble".
- *
- * -EREMOTEIO          The data read from the endpoint did not fill the
- *                     specified buffer, and URB_SHORT_NOT_OK was set in
- *                     urb->transfer_flags.
- *
- * -ENODEV             Device was removed.  Often preceded by a burst of
- *                     other errors, since the hub driver doesn't detect
- *                     device removal events immediately.
- *
- * -EXDEV              ISO transfer only partially completed
- *                     (only set in iso_frame_desc[n].status, not urb->status)
- *
- * -EINVAL             ISO madness, if this happens: Log off and go home
- *
- * -ECONNRESET         URB was asynchronously unlinked by usb_unlink_urb
- *
- * -ESHUTDOWN          The device or host controller has been disabled due
- *                     to some problem that could not be worked around,
- *                     such as a physical disconnect.
- *
- *
- * (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate
- * hardware problems such as bad devices (including firmware) or cables.
- *
- * (**) This is also one of several codes that different kinds of host
- * controller use to indicate a transfer has failed because of device
- * disconnect.  In the interval before the hub driver starts disconnect
- * processing, devices may receive such fault reports for every request.
- *
- * See <https://www.kernel.org/doc/Documentation/driver-api/usb/error-codes.rst>
- */
-static void hdm_read_completion(struct urb *urb)
-{
-       struct mbo *mbo = urb->context;
-       struct most_dev *mdev = to_mdev(mbo->ifp);
-       unsigned int channel = mbo->hdm_channel_id;
-       struct device *dev = &mdev->usb_device->dev;
-       spinlock_t *lock = mdev->channel_lock + channel;
-       unsigned long flags;
-
-       spin_lock_irqsave(lock, flags);
-
-       mbo->processed_length = 0;
-       mbo->status = MBO_E_INVAL;
-       if (likely(mdev->is_channel_healthy[channel])) {
-               switch (urb->status) {
-               case 0:
-               case -ESHUTDOWN:
-                       mbo->processed_length = urb->actual_length;
-                       mbo->status = MBO_SUCCESS;
-                       if (mdev->padding_active[channel] &&
-                           hdm_remove_padding(mdev, channel, mbo)) {
-                               mbo->processed_length = 0;
-                               mbo->status = MBO_E_INVAL;
-                       }
-                       break;
-               case -EPIPE:
-                       dev_warn(dev, "Broken IN pipe detected\n");
-                       mdev->is_channel_healthy[channel] = false;
-                       mdev->clear_work[channel].pipe = urb->pipe;
-                       schedule_work(&mdev->clear_work[channel].ws);
-                       break;
-               case -ENODEV:
-               case -EPROTO:
-                       mbo->status = MBO_E_CLOSE;
-                       break;
-               case -EOVERFLOW:
-                       dev_warn(dev, "Babble on IN pipe detected\n");
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(lock, flags);
-
-       if (likely(mbo->complete))
-               mbo->complete(mbo);
-       usb_free_urb(urb);
-}
-
-/**
- * hdm_enqueue - receive a buffer to be used for data transfer
- * @iface: interface to enqueue to
- * @channel: ID of the channel
- * @mbo: pointer to the buffer object
- *
- * This allocates a new URB and fills it according to the channel
- * that is being used for transmission of data. Before the URB is
- * submitted it is stored in the private anchor list.
- *
- * Returns 0 on success. On any error the URB is freed and a error code
- * is returned.
- *
- * Context: Could in _some_ cases be interrupt!
- */
-static int hdm_enqueue(struct most_interface *iface, int channel,
-                      struct mbo *mbo)
-{
-       struct most_dev *mdev;
-       struct most_channel_config *conf;
-       struct device *dev;
-       int retval = 0;
-       struct urb *urb;
-       unsigned long length;
-       void *virt_address;
-
-       if (unlikely(!iface || !mbo))
-               return -EIO;
-       if (unlikely(iface->num_channels <= channel || channel < 0))
-               return -ECHRNG;
-
-       mdev = to_mdev(iface);
-       conf = &mdev->conf[channel];
-       dev = &mdev->usb_device->dev;
-
-       if (!mdev->usb_device)
-               return -ENODEV;
-
-       urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC);
-       if (!urb)
-               return -ENOMEM;
-
-       if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] &&
-           hdm_add_padding(mdev, channel, mbo)) {
-               retval = -EIO;
-               goto _error;
-       }
-
-       urb->transfer_dma = mbo->bus_address;
-       virt_address = mbo->virt_address;
-       length = mbo->buffer_length;
-
-       if (conf->direction & MOST_CH_TX) {
-               usb_fill_bulk_urb(urb, mdev->usb_device,
-                                 usb_sndbulkpipe(mdev->usb_device,
-                                                 mdev->ep_address[channel]),
-                                 virt_address,
-                                 length,
-                                 hdm_write_completion,
-                                 mbo);
-               if (conf->data_type != MOST_CH_ISOC)
-                       urb->transfer_flags |= URB_ZERO_PACKET;
-       } else {
-               usb_fill_bulk_urb(urb, mdev->usb_device,
-                                 usb_rcvbulkpipe(mdev->usb_device,
-                                                 mdev->ep_address[channel]),
-                                 virt_address,
-                                 length + conf->extra_len,
-                                 hdm_read_completion,
-                                 mbo);
-       }
-       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-       usb_anchor_urb(urb, &mdev->busy_urbs[channel]);
-
-       retval = usb_submit_urb(urb, GFP_KERNEL);
-       if (retval) {
-               dev_err(dev, "URB submit failed with error %d.\n", retval);
-               goto _error_1;
-       }
-       return 0;
-
-_error_1:
-       usb_unanchor_urb(urb);
-_error:
-       usb_free_urb(urb);
-       return retval;
-}
-
-/**
- * hdm_configure_channel - receive channel configuration from core
- * @iface: interface
- * @channel: channel ID
- * @conf: structure that holds the configuration information
- *
- * The attached network interface controller (NIC) supports a padding mode
- * to avoid short packets on USB, hence increasing the performance due to a
- * lower interrupt load. This mode is default for synchronous data and can
- * be switched on for isochronous data. In case padding is active the
- * driver needs to know the frame size of the payload in order to calculate
- * the number of bytes it needs to pad when transmitting or to cut off when
- * receiving data.
- *
- */
-static int hdm_configure_channel(struct most_interface *iface, int channel,
-                                struct most_channel_config *conf)
-{
-       unsigned int num_frames;
-       unsigned int frame_size;
-       struct most_dev *mdev = to_mdev(iface);
-       struct device *dev = &mdev->usb_device->dev;
-
-       mdev->is_channel_healthy[channel] = true;
-       mdev->clear_work[channel].channel = channel;
-       mdev->clear_work[channel].mdev = mdev;
-       INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt);
-
-       if (unlikely(!iface || !conf)) {
-               dev_err(dev, "Bad interface or config pointer.\n");
-               return -EINVAL;
-       }
-       if (unlikely(channel < 0 || channel >= iface->num_channels)) {
-               dev_err(dev, "Channel ID out of range.\n");
-               return -EINVAL;
-       }
-       if (!conf->num_buffers || !conf->buffer_size) {
-               dev_err(dev, "Misconfig: buffer size or #buffers zero.\n");
-               return -EINVAL;
-       }
-
-       if (conf->data_type != MOST_CH_SYNC &&
-           !(conf->data_type == MOST_CH_ISOC &&
-             conf->packets_per_xact != 0xFF)) {
-               mdev->padding_active[channel] = false;
-               /*
-                * Since the NIC's padding mode is not going to be
-                * used, we can skip the frame size calculations and
-                * move directly on to exit.
-                */
-               goto exit;
-       }
-
-       mdev->padding_active[channel] = true;
-
-       frame_size = get_stream_frame_size(conf);
-       if (frame_size == 0 || frame_size > USB_MTU) {
-               dev_warn(dev, "Misconfig: frame size wrong\n");
-               return -EINVAL;
-       }
-
-       num_frames = conf->buffer_size / frame_size;
-
-       if (conf->buffer_size % frame_size) {
-               u16 old_size = conf->buffer_size;
-
-               conf->buffer_size = num_frames * frame_size;
-               dev_warn(dev, "%s: fixed buffer size (%d -> %d)\n",
-                        mdev->suffix[channel], old_size, conf->buffer_size);
-       }
-
-       /* calculate extra length to comply w/ HW padding */
-       conf->extra_len = num_frames * (USB_MTU - frame_size);
-
-exit:
-       mdev->conf[channel] = *conf;
-       if (conf->data_type == MOST_CH_ASYNC) {
-               u16 ep = mdev->ep_address[channel];
-
-               if (start_sync_ep(mdev->usb_device, ep) < 0)
-                       dev_warn(dev, "sync for ep%02x failed", ep);
-       }
-       return 0;
-}
-
-/**
- * hdm_request_netinfo - request network information
- * @iface: pointer to interface
- * @channel: channel ID
- *
- * This is used as trigger to set up the link status timer that
- * polls for the NI state of the INIC every 2 seconds.
- *
- */
-static void hdm_request_netinfo(struct most_interface *iface, int channel,
-                               void (*on_netinfo)(struct most_interface *,
-                                                  unsigned char,
-                                                  unsigned char *))
-{
-       struct most_dev *mdev;
-
-       BUG_ON(!iface);
-       mdev = to_mdev(iface);
-       mdev->on_netinfo = on_netinfo;
-       if (!on_netinfo)
-               return;
-
-       mdev->link_stat_timer.expires = jiffies + HZ;
-       mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires);
-}
-
-/**
- * link_stat_timer_handler - schedule work obtaining mac address and link status
- * @data: pointer to USB device instance
- *
- * The handler runs in interrupt context. That's why we need to defer the
- * tasks to a work queue.
- */
-static void link_stat_timer_handler(struct timer_list *t)
-{
-       struct most_dev *mdev = from_timer(mdev, t, link_stat_timer);
-
-       schedule_work(&mdev->poll_work_obj);
-       mdev->link_stat_timer.expires = jiffies + (2 * HZ);
-       add_timer(&mdev->link_stat_timer);
-}
-
-/**
- * wq_netinfo - work queue function to deliver latest networking information
- * @wq_obj: object that holds data for our deferred work to do
- *
- * This retrieves the network interface status of the USB INIC
- */
-static void wq_netinfo(struct work_struct *wq_obj)
-{
-       struct most_dev *mdev = to_mdev_from_work(wq_obj);
-       struct usb_device *usb_device = mdev->usb_device;
-       struct device *dev = &usb_device->dev;
-       u16 hi, mi, lo, link;
-       u8 hw_addr[6];
-
-       if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) {
-               dev_err(dev, "Vendor request 'hw_addr_hi' failed\n");
-               return;
-       }
-
-       if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) {
-               dev_err(dev, "Vendor request 'hw_addr_mid' failed\n");
-               return;
-       }
-
-       if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) {
-               dev_err(dev, "Vendor request 'hw_addr_low' failed\n");
-               return;
-       }
-
-       if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) {
-               dev_err(dev, "Vendor request 'link status' failed\n");
-               return;
-       }
-
-       hw_addr[0] = hi >> 8;
-       hw_addr[1] = hi;
-       hw_addr[2] = mi >> 8;
-       hw_addr[3] = mi;
-       hw_addr[4] = lo >> 8;
-       hw_addr[5] = lo;
-
-       if (mdev->on_netinfo)
-               mdev->on_netinfo(&mdev->iface, link, hw_addr);
-}
-
-/**
- * wq_clear_halt - work queue function
- * @wq_obj: work_struct object to execute
- *
- * This sends a clear_halt to the given USB pipe.
- */
-static void wq_clear_halt(struct work_struct *wq_obj)
-{
-       struct clear_hold_work *clear_work = to_clear_hold_work(wq_obj);
-       struct most_dev *mdev = clear_work->mdev;
-       unsigned int channel = clear_work->channel;
-       int pipe = clear_work->pipe;
-
-       mutex_lock(&mdev->io_mutex);
-       most_stop_enqueue(&mdev->iface, channel);
-       usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
-       if (usb_clear_halt(mdev->usb_device, pipe))
-               dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n");
-
-       mdev->is_channel_healthy[channel] = true;
-       most_resume_enqueue(&mdev->iface, channel);
-       mutex_unlock(&mdev->io_mutex);
-}
-
-/**
- * hdm_usb_fops - file operation table for USB driver
- */
-static const struct file_operations hdm_usb_fops = {
-       .owner = THIS_MODULE,
-};
-
-/**
- * usb_device_id - ID table for HCD device probing
- */
-static const struct usb_device_id usbid[] = {
-       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), },
-       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), },
-       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), },
-       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81210), },
-       { } /* Terminating entry */
-};
-
-#define MOST_DCI_RO_ATTR(_name) \
-       struct most_dci_attribute most_dci_attr_##_name = \
-               __ATTR(_name, 0444, show_value, NULL)
-
-#define MOST_DCI_ATTR(_name) \
-       struct most_dci_attribute most_dci_attr_##_name = \
-               __ATTR(_name, 0644, show_value, store_value)
-
-#define MOST_DCI_WO_ATTR(_name) \
-       struct most_dci_attribute most_dci_attr_##_name = \
-               __ATTR(_name, 0200, NULL, store_value)
-
-/**
- * struct most_dci_attribute - to access the attributes of a dci object
- * @attr: attributes of a dci object
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_dci_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct most_dci_obj *d,
-                       struct most_dci_attribute *attr,
-                       char *buf);
-       ssize_t (*store)(struct most_dci_obj *d,
-                        struct most_dci_attribute *attr,
-                        const char *buf,
-                        size_t count);
-};
-
-#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
-
-/**
- * dci_attr_show - show function for dci object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr,
-                            char *buf)
-{
-       struct most_dci_attribute *dci_attr = to_dci_attr(attr);
-       struct most_dci_obj *dci_obj = to_dci_obj(kobj);
-
-       if (!dci_attr->show)
-               return -EIO;
-
-       return dci_attr->show(dci_obj, dci_attr, buf);
-}
-
-/**
- * dci_attr_store - store function for dci object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t dci_attr_store(struct kobject *kobj,
-                             struct attribute *attr,
-                             const char *buf,
-                             size_t len)
-{
-       struct most_dci_attribute *dci_attr = to_dci_attr(attr);
-       struct most_dci_obj *dci_obj = to_dci_obj(kobj);
-
-       if (!dci_attr->store)
-               return -EIO;
-
-       return dci_attr->store(dci_obj, dci_attr, buf, len);
-}
-
-static const struct sysfs_ops most_dci_sysfs_ops = {
-       .show = dci_attr_show,
-       .store = dci_attr_store,
-};
-
-/**
- * most_dci_release - release function for dci object
- * @kobj: pointer to kobject
- *
- * This frees the memory allocated for the dci object
- */
-static void most_dci_release(struct kobject *kobj)
-{
-       struct most_dci_obj *dci_obj = to_dci_obj(kobj);
-
-       kfree(dci_obj);
-}
-
-struct regs {
-       const char *name;
-       u16 reg;
-};
-
-static const struct regs ro_regs[] = {
-       { "ni_state", DRCI_REG_NI_STATE },
-       { "packet_bandwidth", DRCI_REG_PACKET_BW },
-       { "node_address", DRCI_REG_NODE_ADDR },
-       { "node_position", DRCI_REG_NODE_POS },
-};
-
-static const struct regs rw_regs[] = {
-       { "mep_filter", DRCI_REG_MEP_FILTER },
-       { "mep_hash0", DRCI_REG_HASH_TBL0 },
-       { "mep_hash1", DRCI_REG_HASH_TBL1 },
-       { "mep_hash2", DRCI_REG_HASH_TBL2 },
-       { "mep_hash3", DRCI_REG_HASH_TBL3 },
-       { "mep_eui48_hi", DRCI_REG_HW_ADDR_HI },
-       { "mep_eui48_mi", DRCI_REG_HW_ADDR_MI },
-       { "mep_eui48_lo", DRCI_REG_HW_ADDR_LO },
-};
-
-static int get_stat_reg_addr(const struct regs *regs, int size,
-                            const char *name, u16 *reg_addr)
-{
-       int i;
-
-       for (i = 0; i < size; i++) {
-               if (!strcmp(name, regs[i].name)) {
-                       *reg_addr = regs[i].reg;
-                       return 0;
-               }
-       }
-       return -EFAULT;
-}
-
-#define get_static_reg_addr(regs, name, reg_addr) \
-       get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr)
-
-static ssize_t show_value(struct most_dci_obj *dci_obj,
-                         struct most_dci_attribute *attr, char *buf)
-{
-       const char *name = attr->attr.name;
-       u16 val;
-       u16 reg_addr;
-       int err;
-
-       if (!strcmp(name, "arb_address"))
-               return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr);
-
-       if (!strcmp(name, "arb_value"))
-               reg_addr = dci_obj->reg_addr;
-       else if (get_static_reg_addr(ro_regs, name, &reg_addr) &&
-                get_static_reg_addr(rw_regs, name, &reg_addr))
-               return -EFAULT;
-
-       err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val);
-       if (err < 0)
-               return err;
-
-       return snprintf(buf, PAGE_SIZE, "%04x\n", val);
-}
-
-static ssize_t store_value(struct most_dci_obj *dci_obj,
-                          struct most_dci_attribute *attr,
-                          const char *buf, size_t count)
-{
-       u16 val;
-       u16 reg_addr;
-       const char *name = attr->attr.name;
-       struct usb_device *usb_dev = dci_obj->usb_device;
-       int err = kstrtou16(buf, 16, &val);
-
-       if (err)
-               return err;
-
-       if (!strcmp(name, "arb_address")) {
-               dci_obj->reg_addr = val;
-               return count;
-       }
-
-       if (!strcmp(name, "arb_value"))
-               err = drci_wr_reg(usb_dev, dci_obj->reg_addr, val);
-       else if (!strcmp(name, "sync_ep"))
-               err = start_sync_ep(usb_dev, val);
-       else if (!get_static_reg_addr(rw_regs, name, &reg_addr))
-               err = drci_wr_reg(usb_dev, reg_addr, val);
-       else
-               return -EFAULT;
-
-       if (err < 0)
-               return err;
-
-       return count;
-}
-
-static MOST_DCI_RO_ATTR(ni_state);
-static MOST_DCI_RO_ATTR(packet_bandwidth);
-static MOST_DCI_RO_ATTR(node_address);
-static MOST_DCI_RO_ATTR(node_position);
-static MOST_DCI_WO_ATTR(sync_ep);
-static MOST_DCI_ATTR(mep_filter);
-static MOST_DCI_ATTR(mep_hash0);
-static MOST_DCI_ATTR(mep_hash1);
-static MOST_DCI_ATTR(mep_hash2);
-static MOST_DCI_ATTR(mep_hash3);
-static MOST_DCI_ATTR(mep_eui48_hi);
-static MOST_DCI_ATTR(mep_eui48_mi);
-static MOST_DCI_ATTR(mep_eui48_lo);
-static MOST_DCI_ATTR(arb_address);
-static MOST_DCI_ATTR(arb_value);
-
-/**
- * most_dci_def_attrs - array of default attribute files of the dci object
- */
-static struct attribute *most_dci_def_attrs[] = {
-       &most_dci_attr_ni_state.attr,
-       &most_dci_attr_packet_bandwidth.attr,
-       &most_dci_attr_node_address.attr,
-       &most_dci_attr_node_position.attr,
-       &most_dci_attr_sync_ep.attr,
-       &most_dci_attr_mep_filter.attr,
-       &most_dci_attr_mep_hash0.attr,
-       &most_dci_attr_mep_hash1.attr,
-       &most_dci_attr_mep_hash2.attr,
-       &most_dci_attr_mep_hash3.attr,
-       &most_dci_attr_mep_eui48_hi.attr,
-       &most_dci_attr_mep_eui48_mi.attr,
-       &most_dci_attr_mep_eui48_lo.attr,
-       &most_dci_attr_arb_address.attr,
-       &most_dci_attr_arb_value.attr,
-       NULL,
-};
-
-/**
- * DCI ktype
- */
-static struct kobj_type most_dci_ktype = {
-       .sysfs_ops = &most_dci_sysfs_ops,
-       .release = most_dci_release,
-       .default_attrs = most_dci_def_attrs,
-};
-
-/**
- * create_most_dci_obj - allocates a dci object
- * @parent: parent kobject
- *
- * This creates a dci object and registers it with sysfs.
- * Returns a pointer to the object or NULL when something went wrong.
- */
-static struct
-most_dci_obj *create_most_dci_obj(struct kobject *parent)
-{
-       struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL);
-       int retval;
-
-       if (!most_dci)
-               return NULL;
-
-       retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent,
-                                     "dci");
-       if (retval) {
-               kobject_put(&most_dci->kobj);
-               return NULL;
-       }
-       return most_dci;
-}
-
-/**
- * destroy_most_dci_obj - DCI object release function
- * @p: pointer to dci object
- */
-static void destroy_most_dci_obj(struct most_dci_obj *p)
-{
-       kobject_put(&p->kobj);
-}
-
-/**
- * hdm_probe - probe function of USB device driver
- * @interface: Interface of the attached USB device
- * @id: Pointer to the USB ID table.
- *
- * This allocates and initializes the device instance, adds the new
- * entry to the internal list, scans the USB descriptors and registers
- * the interface with the core.
- * Additionally, the DCI objects are created and the hardware is sync'd.
- *
- * Return 0 on success. In case of an error a negative number is returned.
- */
-static int
-hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
-{
-       struct usb_host_interface *usb_iface_desc = interface->cur_altsetting;
-       struct usb_device *usb_dev = interface_to_usbdev(interface);
-       struct device *dev = &usb_dev->dev;
-       struct most_dev *mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
-       unsigned int i;
-       unsigned int num_endpoints;
-       struct most_channel_capability *tmp_cap;
-       struct usb_endpoint_descriptor *ep_desc;
-       int ret = 0;
-
-       if (!mdev)
-               goto exit_ENOMEM;
-
-       usb_set_intfdata(interface, mdev);
-       num_endpoints = usb_iface_desc->desc.bNumEndpoints;
-       mutex_init(&mdev->io_mutex);
-       INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
-       timer_setup(&mdev->link_stat_timer, link_stat_timer_handler, 0);
-
-       mdev->usb_device = usb_dev;
-       mdev->link_stat_timer.expires = jiffies + (2 * HZ);
-
-       mdev->iface.mod = hdm_usb_fops.owner;
-       mdev->iface.interface = ITYPE_USB;
-       mdev->iface.configure = hdm_configure_channel;
-       mdev->iface.request_netinfo = hdm_request_netinfo;
-       mdev->iface.enqueue = hdm_enqueue;
-       mdev->iface.poison_channel = hdm_poison_channel;
-       mdev->iface.description = mdev->description;
-       mdev->iface.num_channels = num_endpoints;
-
-       snprintf(mdev->description, sizeof(mdev->description),
-                "usb_device %d-%s:%d.%d",
-                usb_dev->bus->busnum,
-                usb_dev->devpath,
-                usb_dev->config->desc.bConfigurationValue,
-                usb_iface_desc->desc.bInterfaceNumber);
-
-       mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL);
-       if (!mdev->conf)
-               goto exit_free;
-
-       mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL);
-       if (!mdev->cap)
-               goto exit_free1;
-
-       mdev->iface.channel_vector = mdev->cap;
-       mdev->iface.priv = NULL;
-
-       mdev->ep_address =
-               kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
-       if (!mdev->ep_address)
-               goto exit_free2;
-
-       mdev->busy_urbs =
-               kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL);
-       if (!mdev->busy_urbs)
-               goto exit_free3;
-
-       tmp_cap = mdev->cap;
-       for (i = 0; i < num_endpoints; i++) {
-               ep_desc = &usb_iface_desc->endpoint[i].desc;
-               mdev->ep_address[i] = ep_desc->bEndpointAddress;
-               mdev->padding_active[i] = false;
-               mdev->is_channel_healthy[i] = true;
-
-               snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x",
-                        mdev->ep_address[i]);
-
-               tmp_cap->name_suffix = &mdev->suffix[i][0];
-               tmp_cap->buffer_size_packet = MAX_BUF_SIZE;
-               tmp_cap->buffer_size_streaming = MAX_BUF_SIZE;
-               tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE;
-               tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE;
-               tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
-                                    MOST_CH_ISOC | MOST_CH_SYNC;
-               if (usb_endpoint_dir_in(ep_desc))
-                       tmp_cap->direction = MOST_CH_RX;
-               else
-                       tmp_cap->direction = MOST_CH_TX;
-               tmp_cap++;
-               init_usb_anchor(&mdev->busy_urbs[i]);
-               spin_lock_init(&mdev->channel_lock[i]);
-       }
-       dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n",
-                  le16_to_cpu(usb_dev->descriptor.idVendor),
-                  le16_to_cpu(usb_dev->descriptor.idProduct),
-                  usb_dev->bus->busnum,
-                  usb_dev->devnum);
-
-       dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n",
-                  usb_dev->bus->busnum,
-                  usb_dev->devpath,
-                  usb_dev->config->desc.bConfigurationValue,
-                  usb_iface_desc->desc.bInterfaceNumber);
-
-       mdev->parent = most_register_interface(&mdev->iface);
-       if (IS_ERR(mdev->parent)) {
-               ret = PTR_ERR(mdev->parent);
-               goto exit_free4;
-       }
-
-       mutex_lock(&mdev->io_mutex);
-       if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 ||
-           le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 ||
-           le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) {
-               /* this increments the reference count of the instance
-                * object of the core
-                */
-               mdev->dci = create_most_dci_obj(mdev->parent);
-               if (!mdev->dci) {
-                       mutex_unlock(&mdev->io_mutex);
-                       most_deregister_interface(&mdev->iface);
-                       ret = -ENOMEM;
-                       goto exit_free4;
-               }
-
-               kobject_uevent(&mdev->dci->kobj, KOBJ_ADD);
-               mdev->dci->usb_device = mdev->usb_device;
-       }
-       mutex_unlock(&mdev->io_mutex);
-       return 0;
-
-exit_free4:
-       kfree(mdev->busy_urbs);
-exit_free3:
-       kfree(mdev->ep_address);
-exit_free2:
-       kfree(mdev->cap);
-exit_free1:
-       kfree(mdev->conf);
-exit_free:
-       kfree(mdev);
-exit_ENOMEM:
-       if (ret == 0 || ret == -ENOMEM) {
-               ret = -ENOMEM;
-               dev_err(dev, "out of memory\n");
-       }
-       return ret;
-}
-
-/**
- * hdm_disconnect - disconnect function of USB device driver
- * @interface: Interface of the attached USB device
- *
- * This deregisters the interface with the core, removes the kernel timer
- * and frees resources.
- *
- * Context: hub kernel thread
- */
-static void hdm_disconnect(struct usb_interface *interface)
-{
-       struct most_dev *mdev = usb_get_intfdata(interface);
-
-       mutex_lock(&mdev->io_mutex);
-       usb_set_intfdata(interface, NULL);
-       mdev->usb_device = NULL;
-       mutex_unlock(&mdev->io_mutex);
-
-       del_timer_sync(&mdev->link_stat_timer);
-       cancel_work_sync(&mdev->poll_work_obj);
-
-       destroy_most_dci_obj(mdev->dci);
-       most_deregister_interface(&mdev->iface);
-
-       kfree(mdev->busy_urbs);
-       kfree(mdev->cap);
-       kfree(mdev->conf);
-       kfree(mdev->ep_address);
-       kfree(mdev);
-}
-
-static struct usb_driver hdm_usb = {
-       .name = "hdm_usb",
-       .id_table = usbid,
-       .probe = hdm_probe,
-       .disconnect = hdm_disconnect,
-};
-
-module_usb_driver(hdm_usb);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
-MODULE_DESCRIPTION("HDM_4_USB");
diff --git a/drivers/staging/most/i2c/Kconfig b/drivers/staging/most/i2c/Kconfig
new file mode 100644 (file)
index 0000000..79d0ff2
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# MOST I2C configuration
+#
+
+config MOST_I2C
+       tristate "I2C"
+       depends on I2C
+       ---help---
+         Say Y here if you want to connect via I2C to network tranceiver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called most_i2c.
diff --git a/drivers/staging/most/i2c/Makefile b/drivers/staging/most/i2c/Makefile
new file mode 100644 (file)
index 0000000..a7d094c
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_I2C) += most_i2c.o
+
+most_i2c-objs := i2c.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c
new file mode 100644 (file)
index 0000000..141239f
--- /dev/null
@@ -0,0 +1,416 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * i2c.c - Hardware Dependent Module for I2C Interface
+ *
+ * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+
+#include "most/core.h"
+
+enum { CH_RX, CH_TX, NUM_CHANNELS };
+
+#define MAX_BUFFERS_CONTROL 32
+#define MAX_BUF_SIZE_CONTROL 256
+
+/**
+ * list_first_mbo - get the first mbo from a list
+ * @ptr:       the list head to take the mbo from.
+ */
+#define list_first_mbo(ptr) \
+       list_first_entry(ptr, struct mbo, list)
+
+/* IRQ / Polling option */
+static bool polling_req;
+module_param(polling_req, bool, 0444);
+MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)");
+
+/* Polling Rate */
+static int scan_rate = 100;
+module_param(scan_rate, int, 0644);
+MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 100");
+
+struct hdm_i2c {
+       bool is_open[NUM_CHANNELS];
+       bool polling_mode;
+       struct most_interface most_iface;
+       struct most_channel_capability capabilities[NUM_CHANNELS];
+       struct i2c_client *client;
+       struct rx {
+               struct delayed_work dwork;
+               wait_queue_head_t waitq;
+               struct list_head list;
+               struct mutex list_mutex;
+       } rx;
+       char name[64];
+};
+
+#define to_hdm(iface) container_of(iface, struct hdm_i2c, most_iface)
+
+/**
+ * configure_channel - called from MOST core to configure a channel
+ * @iface: interface the channel belongs to
+ * @channel: channel to be configured
+ * @channel_config: structure that holds the configuration information
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Receives configuration information from MOST core and initialize the
+ * corresponding channel.
+ */
+static int configure_channel(struct most_interface *most_iface,
+                            int ch_idx,
+                            struct most_channel_config *channel_config)
+{
+       struct hdm_i2c *dev = to_hdm(most_iface);
+
+       BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+       BUG_ON(dev->is_open[ch_idx]);
+
+       if (channel_config->data_type != MOST_CH_CONTROL) {
+               pr_err("bad data type for channel %d\n", ch_idx);
+               return -EPERM;
+       }
+
+       if (channel_config->direction != dev->capabilities[ch_idx].direction) {
+               pr_err("bad direction for channel %d\n", ch_idx);
+               return -EPERM;
+       }
+
+       if ((channel_config->direction == MOST_CH_RX) && (dev->polling_mode)) {
+               schedule_delayed_work(&dev->rx.dwork,
+                                     msecs_to_jiffies(MSEC_PER_SEC / 4));
+       }
+       dev->is_open[ch_idx] = true;
+
+       return 0;
+}
+
+/**
+ * enqueue - called from MOST core to enqueue a buffer for data transfer
+ * @iface: intended interface
+ * @channel: ID of the channel the buffer is intended for
+ * @mbo: pointer to the buffer object
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Transmit the data over I2C if it is a "write" request or push the buffer into
+ * list if it is an "read" request
+ */
+static int enqueue(struct most_interface *most_iface,
+                  int ch_idx, struct mbo *mbo)
+{
+       struct hdm_i2c *dev = to_hdm(most_iface);
+       int ret;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+       BUG_ON(!dev->is_open[ch_idx]);
+
+       if (ch_idx == CH_RX) {
+               /* RX */
+               mutex_lock(&dev->rx.list_mutex);
+               list_add_tail(&mbo->list, &dev->rx.list);
+               mutex_unlock(&dev->rx.list_mutex);
+               wake_up_interruptible(&dev->rx.waitq);
+       } else {
+               /* TX */
+               ret = i2c_master_send(dev->client, mbo->virt_address,
+                                     mbo->buffer_length);
+               if (ret <= 0) {
+                       mbo->processed_length = 0;
+                       mbo->status = MBO_E_INVAL;
+               } else {
+                       mbo->processed_length = mbo->buffer_length;
+                       mbo->status = MBO_SUCCESS;
+               }
+               mbo->complete(mbo);
+       }
+
+       return 0;
+}
+
+/**
+ * poison_channel - called from MOST core to poison buffers of a channel
+ * @iface: pointer to the interface the channel to be poisoned belongs to
+ * @channel_id: corresponding channel ID
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * If channel direction is RX, complete the buffers in list with
+ * status MBO_E_CLOSE
+ */
+static int poison_channel(struct most_interface *most_iface,
+                         int ch_idx)
+{
+       struct hdm_i2c *dev = to_hdm(most_iface);
+       struct mbo *mbo;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+       BUG_ON(!dev->is_open[ch_idx]);
+
+       dev->is_open[ch_idx] = false;
+
+       if (ch_idx == CH_RX) {
+               mutex_lock(&dev->rx.list_mutex);
+               while (!list_empty(&dev->rx.list)) {
+                       mbo = list_first_mbo(&dev->rx.list);
+                       list_del(&mbo->list);
+                       mutex_unlock(&dev->rx.list_mutex);
+
+                       mbo->processed_length = 0;
+                       mbo->status = MBO_E_CLOSE;
+                       mbo->complete(mbo);
+
+                       mutex_lock(&dev->rx.list_mutex);
+               }
+               mutex_unlock(&dev->rx.list_mutex);
+               wake_up_interruptible(&dev->rx.waitq);
+       }
+
+       return 0;
+}
+
+static void do_rx_work(struct hdm_i2c *dev)
+{
+       struct mbo *mbo;
+       unsigned char msg[MAX_BUF_SIZE_CONTROL];
+       int ret, ch_idx = CH_RX;
+       u16 pml, data_size;
+
+       /* Read PML (2 bytes) */
+       ret = i2c_master_recv(dev->client, msg, 2);
+       if (ret <= 0) {
+               pr_err("Failed to receive PML\n");
+               return;
+       }
+
+       pml = (msg[0] << 8) | msg[1];
+       if (!pml)
+               return;
+
+       data_size = pml + 2;
+
+       /* Read the whole message, including PML */
+       ret = i2c_master_recv(dev->client, msg, data_size);
+       if (ret <= 0) {
+               pr_err("Failed to receive a Port Message\n");
+               return;
+       }
+
+       for (;;) {
+               /* Conditions to wait for: poisoned channel or free buffer
+                * available for reading
+                */
+               if (wait_event_interruptible(dev->rx.waitq,
+                                            !dev->is_open[ch_idx] ||
+                                            !list_empty(&dev->rx.list))) {
+                       pr_err("wait_event_interruptible() failed\n");
+                       return;
+               }
+
+               if (!dev->is_open[ch_idx])
+                       return;
+
+               mutex_lock(&dev->rx.list_mutex);
+
+               /* list may be empty if poison or remove is called */
+               if (!list_empty(&dev->rx.list))
+                       break;
+
+               mutex_unlock(&dev->rx.list_mutex);
+       }
+
+       mbo = list_first_mbo(&dev->rx.list);
+       list_del(&mbo->list);
+       mutex_unlock(&dev->rx.list_mutex);
+
+       mbo->processed_length = min(data_size, mbo->buffer_length);
+       memcpy(mbo->virt_address, msg, mbo->processed_length);
+       mbo->status = MBO_SUCCESS;
+       mbo->complete(mbo);
+}
+
+/**
+ * pending_rx_work - Read pending messages through I2C
+ * @work: definition of this work item
+ *
+ * Invoked by the Interrupt Service Routine, most_irq_handler()
+ */
+static void pending_rx_work(struct work_struct *work)
+{
+       struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work);
+
+       do_rx_work(dev);
+
+       if (dev->polling_mode) {
+               if (dev->is_open[CH_RX])
+                       schedule_delayed_work(&dev->rx.dwork,
+                                             msecs_to_jiffies(MSEC_PER_SEC
+                                                              / scan_rate));
+       } else {
+               enable_irq(dev->client->irq);
+       }
+}
+
+/*
+ * most_irq_handler - Interrupt Service Routine
+ * @irq: irq number
+ * @_dev: private data
+ *
+ * Schedules a delayed work
+ *
+ * By default the interrupt line behavior is Active Low. Once an interrupt is
+ * generated by the device, until driver clears the interrupt (by reading
+ * the PMP message), device keeps the interrupt line in low state. Since i2c
+ * read is done in work queue, the interrupt line must be disabled temporarily
+ * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue,
+ * after reading the message.
+ *
+ * Note: If we use the interrupt line in Falling edge mode, there is a
+ * possibility to miss interrupts when ISR is getting executed.
+ *
+ */
+static irqreturn_t most_irq_handler(int irq, void *_dev)
+{
+       struct hdm_i2c *dev = _dev;
+
+       disable_irq_nosync(irq);
+
+       schedule_delayed_work(&dev->rx.dwork, 0);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * i2c_probe - i2c probe handler
+ * @client: i2c client device structure
+ * @id: i2c client device id
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Register the i2c client device as a MOST interface
+ */
+static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       struct hdm_i2c *dev;
+       int ret, i;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       /* ID format: i2c-<bus>-<address> */
+       snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x",
+                client->adapter->nr, client->addr);
+
+       for (i = 0; i < NUM_CHANNELS; i++) {
+               dev->is_open[i] = false;
+               dev->capabilities[i].data_type = MOST_CH_CONTROL;
+               dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL;
+               dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL;
+       }
+       dev->capabilities[CH_RX].direction = MOST_CH_RX;
+       dev->capabilities[CH_RX].name_suffix = "rx";
+       dev->capabilities[CH_TX].direction = MOST_CH_TX;
+       dev->capabilities[CH_TX].name_suffix = "tx";
+
+       dev->most_iface.interface = ITYPE_I2C;
+       dev->most_iface.description = dev->name;
+       dev->most_iface.num_channels = NUM_CHANNELS;
+       dev->most_iface.channel_vector = dev->capabilities;
+       dev->most_iface.configure = configure_channel;
+       dev->most_iface.enqueue = enqueue;
+       dev->most_iface.poison_channel = poison_channel;
+
+       INIT_LIST_HEAD(&dev->rx.list);
+       mutex_init(&dev->rx.list_mutex);
+       init_waitqueue_head(&dev->rx.waitq);
+
+       INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work);
+
+       dev->client = client;
+       i2c_set_clientdata(client, dev);
+
+       ret = most_register_interface(&dev->most_iface);
+       if (ret) {
+               pr_err("Failed to register i2c as a MOST interface\n");
+               kfree(dev);
+               return ret;
+       }
+
+       dev->polling_mode = polling_req || client->irq <= 0;
+       if (!dev->polling_mode) {
+               pr_info("Requesting IRQ: %d\n", client->irq);
+               ret = request_irq(client->irq, most_irq_handler, 0,
+                                 client->name, dev);
+               if (ret) {
+                       pr_info("IRQ request failed: %d, falling back to polling\n",
+                               ret);
+                       dev->polling_mode = true;
+               }
+       }
+
+       if (dev->polling_mode)
+               pr_info("Using polling at rate: %d times/sec\n", scan_rate);
+
+       return 0;
+}
+
+/*
+ * i2c_remove - i2c remove handler
+ * @client: i2c client device structure
+ *
+ * Return 0 on success.
+ *
+ * Unregister the i2c client device as a MOST interface
+ */
+static int i2c_remove(struct i2c_client *client)
+{
+       struct hdm_i2c *dev = i2c_get_clientdata(client);
+       int i;
+
+       if (!dev->polling_mode)
+               free_irq(client->irq, dev);
+
+       most_deregister_interface(&dev->most_iface);
+
+       for (i = 0 ; i < NUM_CHANNELS; i++)
+               if (dev->is_open[i])
+                       poison_channel(&dev->most_iface, i);
+       cancel_delayed_work_sync(&dev->rx.dwork);
+       kfree(dev);
+
+       return 0;
+}
+
+static const struct i2c_device_id i2c_id[] = {
+       { "most_i2c", 0 },
+       { }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(i2c, i2c_id);
+
+static struct i2c_driver i2c_driver = {
+       .driver = {
+               .name = "hdm_i2c",
+       },
+       .probe = i2c_probe,
+       .remove = i2c_remove,
+       .id_table = i2c_id,
+};
+
+module_i2c_driver(i2c_driver);
+
+MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("I2C Hardware Dependent Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/mostcore/Kconfig b/drivers/staging/most/mostcore/Kconfig
deleted file mode 100644 (file)
index 4717254..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# MOSTCore configuration
-#
-
-config MOSTCORE
-       tristate "MOST Core"
-       depends on HAS_DMA
-
-       ---help---
-         Say Y here if you want to enable MOST support.
-         This device driver needs at least an additional AIM and HDM to work.
-
-         To compile this driver as a module, choose M here: the
-         module will be called mostcore.
diff --git a/drivers/staging/most/mostcore/Makefile b/drivers/staging/most/mostcore/Makefile
deleted file mode 100644 (file)
index a078f01..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_MOSTCORE) += mostcore.o
-
-mostcore-objs := core.o
diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c
deleted file mode 100644 (file)
index 069269d..0000000
+++ /dev/null
@@ -1,1949 +0,0 @@
-/*
- * core.c - Implementation of core module of MOST Linux driver stack
- *
- * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/poll.h>
-#include <linux/wait.h>
-#include <linux/kobject.h>
-#include <linux/mutex.h>
-#include <linux/completion.h>
-#include <linux/sysfs.h>
-#include <linux/kthread.h>
-#include <linux/dma-mapping.h>
-#include <linux/idr.h>
-#include "mostcore.h"
-
-#define MAX_CHANNELS   64
-#define STRING_SIZE    80
-
-static struct class *most_class;
-static struct device *core_dev;
-static struct ida mdev_id;
-static int dummy_num_buffers;
-
-struct most_c_aim_obj {
-       struct most_aim *ptr;
-       int refs;
-       int num_buffers;
-};
-
-struct most_c_obj {
-       struct kobject kobj;
-       struct completion cleanup;
-       atomic_t mbo_ref;
-       atomic_t mbo_nq_level;
-       u16 channel_id;
-       bool is_poisoned;
-       struct mutex start_mutex;
-       struct mutex nq_mutex; /* nq thread synchronization */
-       int is_starving;
-       struct most_interface *iface;
-       struct most_inst_obj *inst;
-       struct most_channel_config cfg;
-       bool keep_mbo;
-       bool enqueue_halt;
-       struct list_head fifo;
-       spinlock_t fifo_lock;
-       struct list_head halt_fifo;
-       struct list_head list;
-       struct most_c_aim_obj aim0;
-       struct most_c_aim_obj aim1;
-       struct list_head trash_fifo;
-       struct task_struct *hdm_enqueue_task;
-       wait_queue_head_t hdm_fifo_wq;
-};
-
-#define to_c_obj(d) container_of(d, struct most_c_obj, kobj)
-
-struct most_inst_obj {
-       int dev_id;
-       struct most_interface *iface;
-       struct list_head channel_list;
-       struct most_c_obj *channel[MAX_CHANNELS];
-       struct kobject kobj;
-       struct list_head list;
-};
-
-static const struct {
-       int most_ch_data_type;
-       const char *name;
-} ch_data_type[] = {
-       { MOST_CH_CONTROL, "control\n" },
-       { MOST_CH_ASYNC, "async\n" },
-       { MOST_CH_SYNC, "sync\n" },
-       { MOST_CH_ISOC, "isoc\n"},
-       { MOST_CH_ISOC, "isoc_avp\n"},
-};
-
-#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
-
-/**
- * list_pop_mbo - retrieves the first MBO of the list and removes it
- * @ptr: the list head to grab the MBO from.
- */
-#define list_pop_mbo(ptr)                                              \
-({                                                                     \
-       struct mbo *_mbo = list_first_entry(ptr, struct mbo, list);     \
-       list_del(&_mbo->list);                                          \
-       _mbo;                                                           \
-})
-
-/*                  ___             ___
- *                  ___C H A N N E L___
- */
-
-/**
- * struct most_c_attr - to access the attributes of a channel object
- * @attr: attributes of a channel
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_c_attr {
-       struct attribute attr;
-       ssize_t (*show)(struct most_c_obj *d,
-                       struct most_c_attr *attr,
-                       char *buf);
-       ssize_t (*store)(struct most_c_obj *d,
-                        struct most_c_attr *attr,
-                        const char *buf,
-                        size_t count);
-};
-
-#define to_channel_attr(a) container_of(a, struct most_c_attr, attr)
-
-/**
- * channel_attr_show - show function of channel object
- * @kobj: pointer to its kobject
- * @attr: pointer to its attributes
- * @buf: buffer
- */
-static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr,
-                                char *buf)
-{
-       struct most_c_attr *channel_attr = to_channel_attr(attr);
-       struct most_c_obj *c_obj = to_c_obj(kobj);
-
-       if (!channel_attr->show)
-               return -EIO;
-
-       return channel_attr->show(c_obj, channel_attr, buf);
-}
-
-/**
- * channel_attr_store - store function of channel object
- * @kobj: pointer to its kobject
- * @attr: pointer to its attributes
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t channel_attr_store(struct kobject *kobj,
-                                 struct attribute *attr,
-                                 const char *buf,
-                                 size_t len)
-{
-       struct most_c_attr *channel_attr = to_channel_attr(attr);
-       struct most_c_obj *c_obj = to_c_obj(kobj);
-
-       if (!channel_attr->store)
-               return -EIO;
-       return channel_attr->store(c_obj, channel_attr, buf, len);
-}
-
-static const struct sysfs_ops most_channel_sysfs_ops = {
-       .show = channel_attr_show,
-       .store = channel_attr_store,
-};
-
-/**
- * most_free_mbo_coherent - free an MBO and its coherent buffer
- * @mbo: buffer to be released
- *
- */
-static void most_free_mbo_coherent(struct mbo *mbo)
-{
-       struct most_c_obj *c = mbo->context;
-       u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
-
-       dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address,
-                         mbo->bus_address);
-       kfree(mbo);
-       if (atomic_sub_and_test(1, &c->mbo_ref))
-               complete(&c->cleanup);
-}
-
-/**
- * flush_channel_fifos - clear the channel fifos
- * @c: pointer to channel object
- */
-static void flush_channel_fifos(struct most_c_obj *c)
-{
-       unsigned long flags, hf_flags;
-       struct mbo *mbo, *tmp;
-
-       if (list_empty(&c->fifo) && list_empty(&c->halt_fifo))
-               return;
-
-       spin_lock_irqsave(&c->fifo_lock, flags);
-       list_for_each_entry_safe(mbo, tmp, &c->fifo, list) {
-               list_del(&mbo->list);
-               spin_unlock_irqrestore(&c->fifo_lock, flags);
-               most_free_mbo_coherent(mbo);
-               spin_lock_irqsave(&c->fifo_lock, flags);
-       }
-       spin_unlock_irqrestore(&c->fifo_lock, flags);
-
-       spin_lock_irqsave(&c->fifo_lock, hf_flags);
-       list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) {
-               list_del(&mbo->list);
-               spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
-               most_free_mbo_coherent(mbo);
-               spin_lock_irqsave(&c->fifo_lock, hf_flags);
-       }
-       spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
-
-       if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo))))
-               pr_info("WARN: fifo | trash fifo not empty\n");
-}
-
-/**
- * flush_trash_fifo - clear the trash fifo
- * @c: pointer to channel object
- */
-static int flush_trash_fifo(struct most_c_obj *c)
-{
-       struct mbo *mbo, *tmp;
-       unsigned long flags;
-
-       spin_lock_irqsave(&c->fifo_lock, flags);
-       list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) {
-               list_del(&mbo->list);
-               spin_unlock_irqrestore(&c->fifo_lock, flags);
-               most_free_mbo_coherent(mbo);
-               spin_lock_irqsave(&c->fifo_lock, flags);
-       }
-       spin_unlock_irqrestore(&c->fifo_lock, flags);
-       return 0;
-}
-
-/**
- * most_channel_release - release function of channel object
- * @kobj: pointer to channel's kobject
- */
-static void most_channel_release(struct kobject *kobj)
-{
-       struct most_c_obj *c = to_c_obj(kobj);
-
-       kfree(c);
-}
-
-static ssize_t available_directions_show(struct most_c_obj *c,
-                                        struct most_c_attr *attr,
-                                        char *buf)
-{
-       unsigned int i = c->channel_id;
-
-       strcpy(buf, "");
-       if (c->iface->channel_vector[i].direction & MOST_CH_RX)
-               strcat(buf, "rx ");
-       if (c->iface->channel_vector[i].direction & MOST_CH_TX)
-               strcat(buf, "tx ");
-       strcat(buf, "\n");
-       return strlen(buf);
-}
-
-static ssize_t available_datatypes_show(struct most_c_obj *c,
-                                       struct most_c_attr *attr,
-                                       char *buf)
-{
-       unsigned int i = c->channel_id;
-
-       strcpy(buf, "");
-       if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL)
-               strcat(buf, "control ");
-       if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC)
-               strcat(buf, "async ");
-       if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC)
-               strcat(buf, "sync ");
-       if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC)
-               strcat(buf, "isoc ");
-       strcat(buf, "\n");
-       return strlen(buf);
-}
-
-static ssize_t number_of_packet_buffers_show(struct most_c_obj *c,
-                                            struct most_c_attr *attr,
-                                            char *buf)
-{
-       unsigned int i = c->channel_id;
-
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       c->iface->channel_vector[i].num_buffers_packet);
-}
-
-static ssize_t number_of_stream_buffers_show(struct most_c_obj *c,
-                                            struct most_c_attr *attr,
-                                            char *buf)
-{
-       unsigned int i = c->channel_id;
-
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       c->iface->channel_vector[i].num_buffers_streaming);
-}
-
-static ssize_t size_of_packet_buffer_show(struct most_c_obj *c,
-                                         struct most_c_attr *attr,
-                                         char *buf)
-{
-       unsigned int i = c->channel_id;
-
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       c->iface->channel_vector[i].buffer_size_packet);
-}
-
-static ssize_t size_of_stream_buffer_show(struct most_c_obj *c,
-                                         struct most_c_attr *attr,
-                                         char *buf)
-{
-       unsigned int i = c->channel_id;
-
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       c->iface->channel_vector[i].buffer_size_streaming);
-}
-
-static ssize_t channel_starving_show(struct most_c_obj *c,
-                                    struct most_c_attr *attr,
-                                    char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
-}
-
-static ssize_t set_number_of_buffers_show(struct most_c_obj *c,
-                                         struct most_c_attr *attr,
-                                         char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
-}
-
-static ssize_t set_number_of_buffers_store(struct most_c_obj *c,
-                                          struct most_c_attr *attr,
-                                          const char *buf,
-                                          size_t count)
-{
-       int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
-
-       if (ret)
-               return ret;
-       return count;
-}
-
-static ssize_t set_buffer_size_show(struct most_c_obj *c,
-                                   struct most_c_attr *attr,
-                                   char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
-}
-
-static ssize_t set_buffer_size_store(struct most_c_obj *c,
-                                    struct most_c_attr *attr,
-                                    const char *buf,
-                                    size_t count)
-{
-       int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
-
-       if (ret)
-               return ret;
-       return count;
-}
-
-static ssize_t set_direction_show(struct most_c_obj *c,
-                                 struct most_c_attr *attr,
-                                 char *buf)
-{
-       if (c->cfg.direction & MOST_CH_TX)
-               return snprintf(buf, PAGE_SIZE, "tx\n");
-       else if (c->cfg.direction & MOST_CH_RX)
-               return snprintf(buf, PAGE_SIZE, "rx\n");
-       return snprintf(buf, PAGE_SIZE, "unconfigured\n");
-}
-
-static ssize_t set_direction_store(struct most_c_obj *c,
-                                  struct most_c_attr *attr,
-                                  const char *buf,
-                                  size_t count)
-{
-       if (!strcmp(buf, "dir_rx\n")) {
-               c->cfg.direction = MOST_CH_RX;
-       } else if (!strcmp(buf, "rx\n")) {
-               c->cfg.direction = MOST_CH_RX;
-       } else if (!strcmp(buf, "dir_tx\n")) {
-               c->cfg.direction = MOST_CH_TX;
-       } else if (!strcmp(buf, "tx\n")) {
-               c->cfg.direction = MOST_CH_TX;
-       } else {
-               pr_info("WARN: invalid attribute settings\n");
-               return -EINVAL;
-       }
-       return count;
-}
-
-static ssize_t set_datatype_show(struct most_c_obj *c,
-                                struct most_c_attr *attr,
-                                char *buf)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
-               if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
-                       return snprintf(buf, PAGE_SIZE, ch_data_type[i].name);
-       }
-       return snprintf(buf, PAGE_SIZE, "unconfigured\n");
-}
-
-static ssize_t set_datatype_store(struct most_c_obj *c,
-                                 struct most_c_attr *attr,
-                                 const char *buf,
-                                 size_t count)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
-               if (!strcmp(buf, ch_data_type[i].name)) {
-                       c->cfg.data_type = ch_data_type[i].most_ch_data_type;
-                       break;
-               }
-       }
-
-       if (i == ARRAY_SIZE(ch_data_type)) {
-               pr_info("WARN: invalid attribute settings\n");
-               return -EINVAL;
-       }
-       return count;
-}
-
-static ssize_t set_subbuffer_size_show(struct most_c_obj *c,
-                                      struct most_c_attr *attr,
-                                      char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
-}
-
-static ssize_t set_subbuffer_size_store(struct most_c_obj *c,
-                                       struct most_c_attr *attr,
-                                       const char *buf,
-                                       size_t count)
-{
-       int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
-
-       if (ret)
-               return ret;
-       return count;
-}
-
-static ssize_t set_packets_per_xact_show(struct most_c_obj *c,
-                                        struct most_c_attr *attr,
-                                        char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact);
-}
-
-static ssize_t set_packets_per_xact_store(struct most_c_obj *c,
-                                         struct most_c_attr *attr,
-                                         const char *buf,
-                                         size_t count)
-{
-       int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
-
-       if (ret)
-               return ret;
-       return count;
-}
-
-static struct most_c_attr most_c_attrs[] = {
-       __ATTR_RO(available_directions),
-       __ATTR_RO(available_datatypes),
-       __ATTR_RO(number_of_packet_buffers),
-       __ATTR_RO(number_of_stream_buffers),
-       __ATTR_RO(size_of_stream_buffer),
-       __ATTR_RO(size_of_packet_buffer),
-       __ATTR_RO(channel_starving),
-       __ATTR_RW(set_buffer_size),
-       __ATTR_RW(set_number_of_buffers),
-       __ATTR_RW(set_direction),
-       __ATTR_RW(set_datatype),
-       __ATTR_RW(set_subbuffer_size),
-       __ATTR_RW(set_packets_per_xact),
-};
-
-/**
- * most_channel_def_attrs - array of default attributes of channel object
- */
-static struct attribute *most_channel_def_attrs[] = {
-       &most_c_attrs[0].attr,
-       &most_c_attrs[1].attr,
-       &most_c_attrs[2].attr,
-       &most_c_attrs[3].attr,
-       &most_c_attrs[4].attr,
-       &most_c_attrs[5].attr,
-       &most_c_attrs[6].attr,
-       &most_c_attrs[7].attr,
-       &most_c_attrs[8].attr,
-       &most_c_attrs[9].attr,
-       &most_c_attrs[10].attr,
-       &most_c_attrs[11].attr,
-       &most_c_attrs[12].attr,
-       NULL,
-};
-
-static struct kobj_type most_channel_ktype = {
-       .sysfs_ops = &most_channel_sysfs_ops,
-       .release = most_channel_release,
-       .default_attrs = most_channel_def_attrs,
-};
-
-static struct kset *most_channel_kset;
-
-/**
- * create_most_c_obj - allocates a channel object
- * @name: name of the channel object
- * @parent: parent kobject
- *
- * This create a channel object and registers it with sysfs.
- * Returns a pointer to the object or NULL when something went wrong.
- */
-static struct most_c_obj *
-create_most_c_obj(const char *name, struct kobject *parent)
-{
-       struct most_c_obj *c;
-       int retval;
-
-       c = kzalloc(sizeof(*c), GFP_KERNEL);
-       if (!c)
-               return NULL;
-       c->kobj.kset = most_channel_kset;
-       retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent,
-                                     "%s", name);
-       if (retval) {
-               kobject_put(&c->kobj);
-               return NULL;
-       }
-       kobject_uevent(&c->kobj, KOBJ_ADD);
-       return c;
-}
-
-/*                  ___               ___
- *                  ___I N S T A N C E___
- */
-
-static struct list_head instance_list;
-
-/**
- * struct most_inst_attribute - to access the attributes of instance object
- * @attr: attributes of an instance
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_inst_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct most_inst_obj *d,
-                       struct most_inst_attribute *attr,
-                       char *buf);
-       ssize_t (*store)(struct most_inst_obj *d,
-                        struct most_inst_attribute *attr,
-                        const char *buf,
-                        size_t count);
-};
-
-#define to_instance_attr(a) \
-       container_of(a, struct most_inst_attribute, attr)
-
-/**
- * instance_attr_show - show function for an instance object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t instance_attr_show(struct kobject *kobj,
-                                 struct attribute *attr,
-                                 char *buf)
-{
-       struct most_inst_attribute *instance_attr;
-       struct most_inst_obj *instance_obj;
-
-       instance_attr = to_instance_attr(attr);
-       instance_obj = to_inst_obj(kobj);
-
-       if (!instance_attr->show)
-               return -EIO;
-
-       return instance_attr->show(instance_obj, instance_attr, buf);
-}
-
-/**
- * instance_attr_store - store function for an instance object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t instance_attr_store(struct kobject *kobj,
-                                  struct attribute *attr,
-                                  const char *buf,
-                                  size_t len)
-{
-       struct most_inst_attribute *instance_attr;
-       struct most_inst_obj *instance_obj;
-
-       instance_attr = to_instance_attr(attr);
-       instance_obj = to_inst_obj(kobj);
-
-       if (!instance_attr->store)
-               return -EIO;
-
-       return instance_attr->store(instance_obj, instance_attr, buf, len);
-}
-
-static const struct sysfs_ops most_inst_sysfs_ops = {
-       .show = instance_attr_show,
-       .store = instance_attr_store,
-};
-
-/**
- * most_inst_release - release function for instance object
- * @kobj: pointer to instance's kobject
- *
- * This frees the allocated memory for the instance object
- */
-static void most_inst_release(struct kobject *kobj)
-{
-       struct most_inst_obj *inst = to_inst_obj(kobj);
-
-       kfree(inst);
-}
-
-static ssize_t description_show(struct most_inst_obj *instance_obj,
-                               struct most_inst_attribute *attr,
-                               char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%s\n",
-                       instance_obj->iface->description);
-}
-
-static ssize_t interface_show(struct most_inst_obj *instance_obj,
-                             struct most_inst_attribute *attr,
-                             char *buf)
-{
-       switch (instance_obj->iface->interface) {
-       case ITYPE_LOOPBACK:
-               return snprintf(buf, PAGE_SIZE, "loopback\n");
-       case ITYPE_I2C:
-               return snprintf(buf, PAGE_SIZE, "i2c\n");
-       case ITYPE_I2S:
-               return snprintf(buf, PAGE_SIZE, "i2s\n");
-       case ITYPE_TSI:
-               return snprintf(buf, PAGE_SIZE, "tsi\n");
-       case ITYPE_HBI:
-               return snprintf(buf, PAGE_SIZE, "hbi\n");
-       case ITYPE_MEDIALB_DIM:
-               return snprintf(buf, PAGE_SIZE, "mlb_dim\n");
-       case ITYPE_MEDIALB_DIM2:
-               return snprintf(buf, PAGE_SIZE, "mlb_dim2\n");
-       case ITYPE_USB:
-               return snprintf(buf, PAGE_SIZE, "usb\n");
-       case ITYPE_PCIE:
-               return snprintf(buf, PAGE_SIZE, "pcie\n");
-       }
-       return snprintf(buf, PAGE_SIZE, "unknown\n");
-}
-
-static struct most_inst_attribute most_inst_attr_description =
-       __ATTR_RO(description);
-
-static struct most_inst_attribute most_inst_attr_interface =
-       __ATTR_RO(interface);
-
-static struct attribute *most_inst_def_attrs[] = {
-       &most_inst_attr_description.attr,
-       &most_inst_attr_interface.attr,
-       NULL,
-};
-
-static struct kobj_type most_inst_ktype = {
-       .sysfs_ops = &most_inst_sysfs_ops,
-       .release = most_inst_release,
-       .default_attrs = most_inst_def_attrs,
-};
-
-static struct kset *most_inst_kset;
-
-/**
- * create_most_inst_obj - creates an instance object
- * @name: name of the object to be created
- *
- * This allocates memory for an instance structure, assigns the proper kset
- * and registers it with sysfs.
- *
- * Returns a pointer to the instance object or NULL when something went wrong.
- */
-static struct most_inst_obj *create_most_inst_obj(const char *name)
-{
-       struct most_inst_obj *inst;
-       int retval;
-
-       inst = kzalloc(sizeof(*inst), GFP_KERNEL);
-       if (!inst)
-               return NULL;
-       inst->kobj.kset = most_inst_kset;
-       retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL,
-                                     "%s", name);
-       if (retval) {
-               kobject_put(&inst->kobj);
-               return NULL;
-       }
-       kobject_uevent(&inst->kobj, KOBJ_ADD);
-       return inst;
-}
-
-/**
- * destroy_most_inst_obj - MOST instance release function
- * @inst: pointer to the instance object
- *
- * This decrements the reference counter of the instance object.
- * If the reference count turns zero, its release function is called
- */
-static void destroy_most_inst_obj(struct most_inst_obj *inst)
-{
-       struct most_c_obj *c, *tmp;
-
-       list_for_each_entry_safe(c, tmp, &inst->channel_list, list) {
-               flush_trash_fifo(c);
-               flush_channel_fifos(c);
-               kobject_put(&c->kobj);
-       }
-       kobject_put(&inst->kobj);
-}
-
-/*                  ___     ___
- *                  ___A I M___
- */
-struct most_aim_obj {
-       struct kobject kobj;
-       struct list_head list;
-       struct most_aim *driver;
-};
-
-#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj)
-
-static struct list_head aim_list;
-
-/**
- * struct most_aim_attribute - to access the attributes of AIM object
- * @attr: attributes of an AIM
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_aim_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct most_aim_obj *d,
-                       struct most_aim_attribute *attr,
-                       char *buf);
-       ssize_t (*store)(struct most_aim_obj *d,
-                        struct most_aim_attribute *attr,
-                        const char *buf,
-                        size_t count);
-};
-
-#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr)
-
-/**
- * aim_attr_show - show function of an AIM object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t aim_attr_show(struct kobject *kobj,
-                            struct attribute *attr,
-                            char *buf)
-{
-       struct most_aim_attribute *aim_attr;
-       struct most_aim_obj *aim_obj;
-
-       aim_attr = to_aim_attr(attr);
-       aim_obj = to_aim_obj(kobj);
-
-       if (!aim_attr->show)
-               return -EIO;
-
-       return aim_attr->show(aim_obj, aim_attr, buf);
-}
-
-/**
- * aim_attr_store - store function of an AIM object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t aim_attr_store(struct kobject *kobj,
-                             struct attribute *attr,
-                             const char *buf,
-                             size_t len)
-{
-       struct most_aim_attribute *aim_attr;
-       struct most_aim_obj *aim_obj;
-
-       aim_attr = to_aim_attr(attr);
-       aim_obj = to_aim_obj(kobj);
-
-       if (!aim_attr->store)
-               return -EIO;
-       return aim_attr->store(aim_obj, aim_attr, buf, len);
-}
-
-static const struct sysfs_ops most_aim_sysfs_ops = {
-       .show = aim_attr_show,
-       .store = aim_attr_store,
-};
-
-/**
- * most_aim_release - AIM release function
- * @kobj: pointer to AIM's kobject
- */
-static void most_aim_release(struct kobject *kobj)
-{
-       struct most_aim_obj *aim_obj = to_aim_obj(kobj);
-
-       kfree(aim_obj);
-}
-
-static ssize_t links_show(struct most_aim_obj *aim_obj,
-                         struct most_aim_attribute *attr,
-                         char *buf)
-{
-       struct most_c_obj *c;
-       struct most_inst_obj *i;
-       int offs = 0;
-
-       list_for_each_entry(i, &instance_list, list) {
-               list_for_each_entry(c, &i->channel_list, list) {
-                       if (c->aim0.ptr == aim_obj->driver ||
-                           c->aim1.ptr == aim_obj->driver) {
-                               offs += snprintf(buf + offs, PAGE_SIZE - offs,
-                                                "%s:%s\n",
-                                                kobject_name(&i->kobj),
-                                                kobject_name(&c->kobj));
-                       }
-               }
-       }
-
-       return offs;
-}
-
-/**
- * split_string - parses and changes string in the buffer buf and
- * splits it into two mandatory and one optional substrings.
- *
- * @buf: complete string from attribute 'add_channel'
- * @a: address of pointer to 1st substring (=instance name)
- * @b: address of pointer to 2nd substring (=channel name)
- * @c: optional address of pointer to 3rd substring (=user defined name)
- *
- * Examples:
- *
- * Input: "mdev0:ch6:my_channel\n" or
- *        "mdev0:ch6:my_channel"
- *
- * Output: *a -> "mdev0", *b -> "ch6", *c -> "my_channel"
- *
- * Input: "mdev1:ep81\n"
- * Output: *a -> "mdev1", *b -> "ep81", *c -> ""
- *
- * Input: "mdev1:ep81"
- * Output: *a -> "mdev1", *b -> "ep81", *c == NULL
- */
-static int split_string(char *buf, char **a, char **b, char **c)
-{
-       *a = strsep(&buf, ":");
-       if (!*a)
-               return -EIO;
-
-       *b = strsep(&buf, ":\n");
-       if (!*b)
-               return -EIO;
-
-       if (c)
-               *c = strsep(&buf, ":\n");
-
-       return 0;
-}
-
-/**
- * get_channel_by_name - get pointer to channel object
- * @mdev: name of the device instance
- * @mdev_ch: name of the respective channel
- *
- * This retrieves the pointer to a channel object.
- */
-static struct
-most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
-{
-       struct most_c_obj *c, *tmp;
-       struct most_inst_obj *i, *i_tmp;
-       int found = 0;
-
-       list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-               if (!strcmp(kobject_name(&i->kobj), mdev)) {
-                       found++;
-                       break;
-               }
-       }
-       if (unlikely(!found))
-               return ERR_PTR(-EIO);
-
-       list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
-               if (!strcmp(kobject_name(&c->kobj), mdev_ch)) {
-                       found++;
-                       break;
-               }
-       }
-       if (unlikely(found < 2))
-               return ERR_PTR(-EIO);
-       return c;
-}
-
-/**
- * add_link_store - store() function for add_link attribute
- * @aim_obj: pointer to AIM object
- * @attr: its attributes
- * @buf: buffer
- * @len: buffer length
- *
- * This parses the string given by buf and splits it into
- * three substrings. Note: third substring is optional. In case a cdev
- * AIM is loaded the optional 3rd substring will make up the name of
- * device node in the /dev directory. If omitted, the device node will
- * inherit the channel's name within sysfs.
- *
- * Searches for a pair of device and channel and probes the AIM
- *
- * Example:
- * (1) echo "mdev0:ch6:my_rxchannel" >add_link
- * (2) echo "mdev1:ep81" >add_link
- *
- * (1) would create the device node /dev/my_rxchannel
- * (2) would create the device node /dev/mdev1-ep81
- */
-static ssize_t add_link_store(struct most_aim_obj *aim_obj,
-                             struct most_aim_attribute *attr,
-                             const char *buf,
-                             size_t len)
-{
-       struct most_c_obj *c;
-       struct most_aim **aim_ptr;
-       char buffer[STRING_SIZE];
-       char *mdev;
-       char *mdev_ch;
-       char *mdev_devnod;
-       char devnod_buf[STRING_SIZE];
-       int ret;
-       size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
-
-       strlcpy(buffer, buf, max_len);
-
-       ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod);
-       if (ret)
-               return ret;
-
-       if (!mdev_devnod || *mdev_devnod == 0) {
-               snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev,
-                        mdev_ch);
-               mdev_devnod = devnod_buf;
-       }
-
-       c = get_channel_by_name(mdev, mdev_ch);
-       if (IS_ERR(c))
-               return -ENODEV;
-
-       if (!c->aim0.ptr)
-               aim_ptr = &c->aim0.ptr;
-       else if (!c->aim1.ptr)
-               aim_ptr = &c->aim1.ptr;
-       else
-               return -ENOSPC;
-
-       *aim_ptr = aim_obj->driver;
-       ret = aim_obj->driver->probe_channel(c->iface, c->channel_id,
-                                            &c->cfg, &c->kobj, mdev_devnod);
-       if (ret) {
-               *aim_ptr = NULL;
-               return ret;
-       }
-
-       return len;
-}
-
-/**
- * remove_link_store - store function for remove_link attribute
- * @aim_obj: pointer to AIM object
- * @attr: its attributes
- * @buf: buffer
- * @len: buffer length
- *
- * Example:
- * echo "mdev0:ep81" >remove_link
- */
-static ssize_t remove_link_store(struct most_aim_obj *aim_obj,
-                                struct most_aim_attribute *attr,
-                                const char *buf,
-                                size_t len)
-{
-       struct most_c_obj *c;
-       char buffer[STRING_SIZE];
-       char *mdev;
-       char *mdev_ch;
-       int ret;
-       size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
-
-       strlcpy(buffer, buf, max_len);
-       ret = split_string(buffer, &mdev, &mdev_ch, NULL);
-       if (ret)
-               return ret;
-
-       c = get_channel_by_name(mdev, mdev_ch);
-       if (IS_ERR(c))
-               return -ENODEV;
-
-       if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id))
-               return -EIO;
-       if (c->aim0.ptr == aim_obj->driver)
-               c->aim0.ptr = NULL;
-       if (c->aim1.ptr == aim_obj->driver)
-               c->aim1.ptr = NULL;
-       return len;
-}
-
-static struct most_aim_attribute most_aim_attrs[] = {
-       __ATTR_RO(links),
-       __ATTR_WO(add_link),
-       __ATTR_WO(remove_link),
-};
-
-static struct attribute *most_aim_def_attrs[] = {
-       &most_aim_attrs[0].attr,
-       &most_aim_attrs[1].attr,
-       &most_aim_attrs[2].attr,
-       NULL,
-};
-
-static struct kobj_type most_aim_ktype = {
-       .sysfs_ops = &most_aim_sysfs_ops,
-       .release = most_aim_release,
-       .default_attrs = most_aim_def_attrs,
-};
-
-static struct kset *most_aim_kset;
-
-/**
- * create_most_aim_obj - creates an AIM object
- * @name: name of the AIM
- *
- * This creates an AIM object assigns the proper kset and registers
- * it with sysfs.
- * Returns a pointer to the object or NULL if something went wrong.
- */
-static struct most_aim_obj *create_most_aim_obj(const char *name)
-{
-       struct most_aim_obj *most_aim;
-       int retval;
-
-       most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL);
-       if (!most_aim)
-               return NULL;
-       most_aim->kobj.kset = most_aim_kset;
-       retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype,
-                                     NULL, "%s", name);
-       if (retval) {
-               kobject_put(&most_aim->kobj);
-               return NULL;
-       }
-       kobject_uevent(&most_aim->kobj, KOBJ_ADD);
-       return most_aim;
-}
-
-/**
- * destroy_most_aim_obj - AIM release function
- * @p: pointer to AIM object
- *
- * This decrements the reference counter of the AIM object. If the
- * reference count turns zero, its release function will be called.
- */
-static void destroy_most_aim_obj(struct most_aim_obj *p)
-{
-       kobject_put(&p->kobj);
-}
-
-/*                  ___       ___
- *                  ___C O R E___
- */
-
-/**
- * Instantiation of the MOST bus
- */
-static struct bus_type most_bus = {
-       .name = "most",
-};
-
-/**
- * Instantiation of the core driver
- */
-static struct device_driver mostcore = {
-       .name = "mostcore",
-       .bus = &most_bus,
-};
-
-static inline void trash_mbo(struct mbo *mbo)
-{
-       unsigned long flags;
-       struct most_c_obj *c = mbo->context;
-
-       spin_lock_irqsave(&c->fifo_lock, flags);
-       list_add(&mbo->list, &c->trash_fifo);
-       spin_unlock_irqrestore(&c->fifo_lock, flags);
-}
-
-static bool hdm_mbo_ready(struct most_c_obj *c)
-{
-       bool empty;
-
-       if (c->enqueue_halt)
-               return false;
-
-       spin_lock_irq(&c->fifo_lock);
-       empty = list_empty(&c->halt_fifo);
-       spin_unlock_irq(&c->fifo_lock);
-
-       return !empty;
-}
-
-static void nq_hdm_mbo(struct mbo *mbo)
-{
-       unsigned long flags;
-       struct most_c_obj *c = mbo->context;
-
-       spin_lock_irqsave(&c->fifo_lock, flags);
-       list_add_tail(&mbo->list, &c->halt_fifo);
-       spin_unlock_irqrestore(&c->fifo_lock, flags);
-       wake_up_interruptible(&c->hdm_fifo_wq);
-}
-
-static int hdm_enqueue_thread(void *data)
-{
-       struct most_c_obj *c = data;
-       struct mbo *mbo;
-       int ret;
-       typeof(c->iface->enqueue) enqueue = c->iface->enqueue;
-
-       while (likely(!kthread_should_stop())) {
-               wait_event_interruptible(c->hdm_fifo_wq,
-                                        hdm_mbo_ready(c) ||
-                                        kthread_should_stop());
-
-               mutex_lock(&c->nq_mutex);
-               spin_lock_irq(&c->fifo_lock);
-               if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) {
-                       spin_unlock_irq(&c->fifo_lock);
-                       mutex_unlock(&c->nq_mutex);
-                       continue;
-               }
-
-               mbo = list_pop_mbo(&c->halt_fifo);
-               spin_unlock_irq(&c->fifo_lock);
-
-               if (c->cfg.direction == MOST_CH_RX)
-                       mbo->buffer_length = c->cfg.buffer_size;
-
-               ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo);
-               mutex_unlock(&c->nq_mutex);
-
-               if (unlikely(ret)) {
-                       pr_err("hdm enqueue failed\n");
-                       nq_hdm_mbo(mbo);
-                       c->hdm_enqueue_task = NULL;
-                       return 0;
-               }
-       }
-
-       return 0;
-}
-
-static int run_enqueue_thread(struct most_c_obj *c, int channel_id)
-{
-       struct task_struct *task =
-               kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d",
-                           channel_id);
-
-       if (IS_ERR(task))
-               return PTR_ERR(task);
-
-       c->hdm_enqueue_task = task;
-       return 0;
-}
-
-/**
- * arm_mbo - recycle MBO for further usage
- * @mbo: buffer object
- *
- * This puts an MBO back to the list to have it ready for up coming
- * tx transactions.
- *
- * In case the MBO belongs to a channel that recently has been
- * poisoned, the MBO is scheduled to be trashed.
- * Calls the completion handler of an attached AIM.
- */
-static void arm_mbo(struct mbo *mbo)
-{
-       unsigned long flags;
-       struct most_c_obj *c;
-
-       BUG_ON((!mbo) || (!mbo->context));
-       c = mbo->context;
-
-       if (c->is_poisoned) {
-               trash_mbo(mbo);
-               return;
-       }
-
-       spin_lock_irqsave(&c->fifo_lock, flags);
-       ++*mbo->num_buffers_ptr;
-       list_add_tail(&mbo->list, &c->fifo);
-       spin_unlock_irqrestore(&c->fifo_lock, flags);
-
-       if (c->aim0.refs && c->aim0.ptr->tx_completion)
-               c->aim0.ptr->tx_completion(c->iface, c->channel_id);
-
-       if (c->aim1.refs && c->aim1.ptr->tx_completion)
-               c->aim1.ptr->tx_completion(c->iface, c->channel_id);
-}
-
-/**
- * arm_mbo_chain - helper function that arms an MBO chain for the HDM
- * @c: pointer to interface channel
- * @dir: direction of the channel
- * @compl: pointer to completion function
- *
- * This allocates buffer objects including the containing DMA coherent
- * buffer and puts them in the fifo.
- * Buffers of Rx channels are put in the kthread fifo, hence immediately
- * submitted to the HDM.
- *
- * Returns the number of allocated and enqueued MBOs.
- */
-static int arm_mbo_chain(struct most_c_obj *c, int dir,
-                        void (*compl)(struct mbo *))
-{
-       unsigned int i;
-       int retval;
-       struct mbo *mbo;
-       u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
-
-       atomic_set(&c->mbo_nq_level, 0);
-
-       for (i = 0; i < c->cfg.num_buffers; i++) {
-               mbo = kzalloc(sizeof(*mbo), GFP_KERNEL);
-               if (!mbo) {
-                       retval = i;
-                       goto _exit;
-               }
-               mbo->context = c;
-               mbo->ifp = c->iface;
-               mbo->hdm_channel_id = c->channel_id;
-               mbo->virt_address = dma_alloc_coherent(NULL,
-                                                      coherent_buf_size,
-                                                      &mbo->bus_address,
-                                                      GFP_KERNEL);
-               if (!mbo->virt_address) {
-                       pr_info("WARN: No DMA coherent buffer.\n");
-                       retval = i;
-                       goto _error1;
-               }
-               mbo->complete = compl;
-               mbo->num_buffers_ptr = &dummy_num_buffers;
-               if (dir == MOST_CH_RX) {
-                       nq_hdm_mbo(mbo);
-                       atomic_inc(&c->mbo_nq_level);
-               } else {
-                       arm_mbo(mbo);
-               }
-       }
-       return i;
-
-_error1:
-       kfree(mbo);
-_exit:
-       return retval;
-}
-
-/**
- * most_submit_mbo - submits an MBO to fifo
- * @mbo: pointer to the MBO
- */
-void most_submit_mbo(struct mbo *mbo)
-{
-       if (WARN_ONCE(!mbo || !mbo->context,
-                     "bad mbo or missing channel reference\n"))
-               return;
-
-       nq_hdm_mbo(mbo);
-}
-EXPORT_SYMBOL_GPL(most_submit_mbo);
-
-/**
- * most_write_completion - write completion handler
- * @mbo: pointer to MBO
- *
- * This recycles the MBO for further usage. In case the channel has been
- * poisoned, the MBO is scheduled to be trashed.
- */
-static void most_write_completion(struct mbo *mbo)
-{
-       struct most_c_obj *c;
-
-       BUG_ON((!mbo) || (!mbo->context));
-
-       c = mbo->context;
-       if (mbo->status == MBO_E_INVAL)
-               pr_info("WARN: Tx MBO status: invalid\n");
-       if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE)))
-               trash_mbo(mbo);
-       else
-               arm_mbo(mbo);
-}
-
-/**
- * get_channel_by_iface - get pointer to channel object
- * @iface: pointer to interface instance
- * @id: channel ID
- *
- * This retrieves a pointer to a channel of the given interface and channel ID.
- */
-static struct
-most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
-{
-       struct most_inst_obj *i;
-
-       if (unlikely(!iface)) {
-               pr_err("Bad interface\n");
-               return NULL;
-       }
-       if (unlikely((id < 0) || (id >= iface->num_channels))) {
-               pr_err("Channel index (%d) out of range\n", id);
-               return NULL;
-       }
-       i = iface->priv;
-       if (unlikely(!i)) {
-               pr_err("interface is not registered\n");
-               return NULL;
-       }
-       return i->channel[id];
-}
-
-int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
-{
-       struct most_c_obj *c = get_channel_by_iface(iface, id);
-       unsigned long flags;
-       int empty;
-
-       if (unlikely(!c))
-               return -EINVAL;
-
-       if (c->aim0.refs && c->aim1.refs &&
-           ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
-            (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
-               return 0;
-
-       spin_lock_irqsave(&c->fifo_lock, flags);
-       empty = list_empty(&c->fifo);
-       spin_unlock_irqrestore(&c->fifo_lock, flags);
-       return !empty;
-}
-EXPORT_SYMBOL_GPL(channel_has_mbo);
-
-/**
- * most_get_mbo - get pointer to an MBO of pool
- * @iface: pointer to interface instance
- * @id: channel ID
- *
- * This attempts to get a free buffer out of the channel fifo.
- * Returns a pointer to MBO on success or NULL otherwise.
- */
-struct mbo *most_get_mbo(struct most_interface *iface, int id,
-                        struct most_aim *aim)
-{
-       struct mbo *mbo;
-       struct most_c_obj *c;
-       unsigned long flags;
-       int *num_buffers_ptr;
-
-       c = get_channel_by_iface(iface, id);
-       if (unlikely(!c))
-               return NULL;
-
-       if (c->aim0.refs && c->aim1.refs &&
-           ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
-            (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
-               return NULL;
-
-       if (aim == c->aim0.ptr)
-               num_buffers_ptr = &c->aim0.num_buffers;
-       else if (aim == c->aim1.ptr)
-               num_buffers_ptr = &c->aim1.num_buffers;
-       else
-               num_buffers_ptr = &dummy_num_buffers;
-
-       spin_lock_irqsave(&c->fifo_lock, flags);
-       if (list_empty(&c->fifo)) {
-               spin_unlock_irqrestore(&c->fifo_lock, flags);
-               return NULL;
-       }
-       mbo = list_pop_mbo(&c->fifo);
-       --*num_buffers_ptr;
-       spin_unlock_irqrestore(&c->fifo_lock, flags);
-
-       mbo->num_buffers_ptr = num_buffers_ptr;
-       mbo->buffer_length = c->cfg.buffer_size;
-       return mbo;
-}
-EXPORT_SYMBOL_GPL(most_get_mbo);
-
-/**
- * most_put_mbo - return buffer to pool
- * @mbo: buffer object
- */
-void most_put_mbo(struct mbo *mbo)
-{
-       struct most_c_obj *c = mbo->context;
-
-       if (c->cfg.direction == MOST_CH_TX) {
-               arm_mbo(mbo);
-               return;
-       }
-       nq_hdm_mbo(mbo);
-       atomic_inc(&c->mbo_nq_level);
-}
-EXPORT_SYMBOL_GPL(most_put_mbo);
-
-/**
- * most_read_completion - read completion handler
- * @mbo: pointer to MBO
- *
- * This function is called by the HDM when data has been received from the
- * hardware and copied to the buffer of the MBO.
- *
- * In case the channel has been poisoned it puts the buffer in the trash queue.
- * Otherwise, it passes the buffer to an AIM for further processing.
- */
-static void most_read_completion(struct mbo *mbo)
-{
-       struct most_c_obj *c = mbo->context;
-
-       if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) {
-               trash_mbo(mbo);
-               return;
-       }
-
-       if (mbo->status == MBO_E_INVAL) {
-               nq_hdm_mbo(mbo);
-               atomic_inc(&c->mbo_nq_level);
-               return;
-       }
-
-       if (atomic_sub_and_test(1, &c->mbo_nq_level))
-               c->is_starving = 1;
-
-       if (c->aim0.refs && c->aim0.ptr->rx_completion &&
-           c->aim0.ptr->rx_completion(mbo) == 0)
-               return;
-
-       if (c->aim1.refs && c->aim1.ptr->rx_completion &&
-           c->aim1.ptr->rx_completion(mbo) == 0)
-               return;
-
-       most_put_mbo(mbo);
-}
-
-/**
- * most_start_channel - prepares a channel for communication
- * @iface: pointer to interface instance
- * @id: channel ID
- *
- * This prepares the channel for usage. Cross-checks whether the
- * channel's been properly configured.
- *
- * Returns 0 on success or error code otherwise.
- */
-int most_start_channel(struct most_interface *iface, int id,
-                      struct most_aim *aim)
-{
-       int num_buffer;
-       int ret;
-       struct most_c_obj *c = get_channel_by_iface(iface, id);
-
-       if (unlikely(!c))
-               return -EINVAL;
-
-       mutex_lock(&c->start_mutex);
-       if (c->aim0.refs + c->aim1.refs > 0)
-               goto out; /* already started by other aim */
-
-       if (!try_module_get(iface->mod)) {
-               pr_info("failed to acquire HDM lock\n");
-               mutex_unlock(&c->start_mutex);
-               return -ENOLCK;
-       }
-
-       c->cfg.extra_len = 0;
-       if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) {
-               pr_info("channel configuration failed. Go check settings...\n");
-               ret = -EINVAL;
-               goto error;
-       }
-
-       init_waitqueue_head(&c->hdm_fifo_wq);
-
-       if (c->cfg.direction == MOST_CH_RX)
-               num_buffer = arm_mbo_chain(c, c->cfg.direction,
-                                          most_read_completion);
-       else
-               num_buffer = arm_mbo_chain(c, c->cfg.direction,
-                                          most_write_completion);
-       if (unlikely(!num_buffer)) {
-               pr_info("failed to allocate memory\n");
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       ret = run_enqueue_thread(c, id);
-       if (ret)
-               goto error;
-
-       c->is_starving = 0;
-       c->aim0.num_buffers = c->cfg.num_buffers / 2;
-       c->aim1.num_buffers = c->cfg.num_buffers - c->aim0.num_buffers;
-       atomic_set(&c->mbo_ref, num_buffer);
-
-out:
-       if (aim == c->aim0.ptr)
-               c->aim0.refs++;
-       if (aim == c->aim1.ptr)
-               c->aim1.refs++;
-       mutex_unlock(&c->start_mutex);
-       return 0;
-
-error:
-       module_put(iface->mod);
-       mutex_unlock(&c->start_mutex);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(most_start_channel);
-
-/**
- * most_stop_channel - stops a running channel
- * @iface: pointer to interface instance
- * @id: channel ID
- */
-int most_stop_channel(struct most_interface *iface, int id,
-                     struct most_aim *aim)
-{
-       struct most_c_obj *c;
-
-       if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
-               pr_err("Bad interface or index out of range\n");
-               return -EINVAL;
-       }
-       c = get_channel_by_iface(iface, id);
-       if (unlikely(!c))
-               return -EINVAL;
-
-       mutex_lock(&c->start_mutex);
-       if (c->aim0.refs + c->aim1.refs >= 2)
-               goto out;
-
-       if (c->hdm_enqueue_task)
-               kthread_stop(c->hdm_enqueue_task);
-       c->hdm_enqueue_task = NULL;
-
-       if (iface->mod)
-               module_put(iface->mod);
-
-       c->is_poisoned = true;
-       if (c->iface->poison_channel(c->iface, c->channel_id)) {
-               pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id,
-                      c->iface->description);
-               mutex_unlock(&c->start_mutex);
-               return -EAGAIN;
-       }
-       flush_trash_fifo(c);
-       flush_channel_fifos(c);
-
-#ifdef CMPL_INTERRUPTIBLE
-       if (wait_for_completion_interruptible(&c->cleanup)) {
-               pr_info("Interrupted while clean up ch %d\n", c->channel_id);
-               mutex_unlock(&c->start_mutex);
-               return -EINTR;
-       }
-#else
-       wait_for_completion(&c->cleanup);
-#endif
-       c->is_poisoned = false;
-
-out:
-       if (aim == c->aim0.ptr)
-               c->aim0.refs--;
-       if (aim == c->aim1.ptr)
-               c->aim1.refs--;
-       mutex_unlock(&c->start_mutex);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(most_stop_channel);
-
-/**
- * most_register_aim - registers an AIM (driver) with the core
- * @aim: instance of AIM to be registered
- */
-int most_register_aim(struct most_aim *aim)
-{
-       struct most_aim_obj *aim_obj;
-
-       if (!aim) {
-               pr_err("Bad driver\n");
-               return -EINVAL;
-       }
-       aim_obj = create_most_aim_obj(aim->name);
-       if (!aim_obj) {
-               pr_info("failed to alloc driver object\n");
-               return -ENOMEM;
-       }
-       aim_obj->driver = aim;
-       aim->context = aim_obj;
-       pr_info("registered new application interfacing module %s\n",
-               aim->name);
-       list_add_tail(&aim_obj->list, &aim_list);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(most_register_aim);
-
-/**
- * most_deregister_aim - deregisters an AIM (driver) with the core
- * @aim: AIM to be removed
- */
-int most_deregister_aim(struct most_aim *aim)
-{
-       struct most_aim_obj *aim_obj;
-       struct most_c_obj *c, *tmp;
-       struct most_inst_obj *i, *i_tmp;
-
-       if (!aim) {
-               pr_err("Bad driver\n");
-               return -EINVAL;
-       }
-
-       aim_obj = aim->context;
-       if (!aim_obj) {
-               pr_info("driver not registered.\n");
-               return -EINVAL;
-       }
-       list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-               list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
-                       if (c->aim0.ptr == aim || c->aim1.ptr == aim)
-                               aim->disconnect_channel(
-                                       c->iface, c->channel_id);
-                       if (c->aim0.ptr == aim)
-                               c->aim0.ptr = NULL;
-                       if (c->aim1.ptr == aim)
-                               c->aim1.ptr = NULL;
-               }
-       }
-       list_del(&aim_obj->list);
-       destroy_most_aim_obj(aim_obj);
-       pr_info("deregistering application interfacing module %s\n", aim->name);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(most_deregister_aim);
-
-/**
- * most_register_interface - registers an interface with core
- * @iface: pointer to the instance of the interface description.
- *
- * Allocates and initializes a new interface instance and all of its channels.
- * Returns a pointer to kobject or an error pointer.
- */
-struct kobject *most_register_interface(struct most_interface *iface)
-{
-       unsigned int i;
-       int id;
-       char name[STRING_SIZE];
-       char channel_name[STRING_SIZE];
-       struct most_c_obj *c;
-       struct most_inst_obj *inst;
-
-       if (!iface || !iface->enqueue || !iface->configure ||
-           !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) {
-               pr_err("Bad interface or channel overflow\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL);
-       if (id < 0) {
-               pr_info("Failed to alloc mdev ID\n");
-               return ERR_PTR(id);
-       }
-       snprintf(name, STRING_SIZE, "mdev%d", id);
-
-       inst = create_most_inst_obj(name);
-       if (!inst) {
-               pr_info("Failed to allocate interface instance\n");
-               ida_simple_remove(&mdev_id, id);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       iface->priv = inst;
-       INIT_LIST_HEAD(&inst->channel_list);
-       inst->iface = iface;
-       inst->dev_id = id;
-       list_add_tail(&inst->list, &instance_list);
-
-       for (i = 0; i < iface->num_channels; i++) {
-               const char *name_suffix = iface->channel_vector[i].name_suffix;
-
-               if (!name_suffix)
-                       snprintf(channel_name, STRING_SIZE, "ch%d", i);
-               else
-                       snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
-
-               /* this increments the reference count of this instance */
-               c = create_most_c_obj(channel_name, &inst->kobj);
-               if (!c)
-                       goto free_instance;
-               inst->channel[i] = c;
-               c->is_starving = 0;
-               c->iface = iface;
-               c->inst = inst;
-               c->channel_id = i;
-               c->keep_mbo = false;
-               c->enqueue_halt = false;
-               c->is_poisoned = false;
-               c->cfg.direction = 0;
-               c->cfg.data_type = 0;
-               c->cfg.num_buffers = 0;
-               c->cfg.buffer_size = 0;
-               c->cfg.subbuffer_size = 0;
-               c->cfg.packets_per_xact = 0;
-               spin_lock_init(&c->fifo_lock);
-               INIT_LIST_HEAD(&c->fifo);
-               INIT_LIST_HEAD(&c->trash_fifo);
-               INIT_LIST_HEAD(&c->halt_fifo);
-               init_completion(&c->cleanup);
-               atomic_set(&c->mbo_ref, 0);
-               mutex_init(&c->start_mutex);
-               mutex_init(&c->nq_mutex);
-               list_add_tail(&c->list, &inst->channel_list);
-       }
-       pr_info("registered new MOST device mdev%d (%s)\n",
-               inst->dev_id, iface->description);
-       return &inst->kobj;
-
-free_instance:
-       pr_info("Failed allocate channel(s)\n");
-       list_del(&inst->list);
-       ida_simple_remove(&mdev_id, id);
-       destroy_most_inst_obj(inst);
-       return ERR_PTR(-ENOMEM);
-}
-EXPORT_SYMBOL_GPL(most_register_interface);
-
-/**
- * most_deregister_interface - deregisters an interface with core
- * @iface: pointer to the interface instance description.
- *
- * Before removing an interface instance from the list, all running
- * channels are stopped and poisoned.
- */
-void most_deregister_interface(struct most_interface *iface)
-{
-       struct most_inst_obj *i = iface->priv;
-       struct most_c_obj *c;
-
-       if (unlikely(!i)) {
-               pr_info("Bad Interface\n");
-               return;
-       }
-       pr_info("deregistering MOST device %s (%s)\n", i->kobj.name,
-               iface->description);
-
-       list_for_each_entry(c, &i->channel_list, list) {
-               if (c->aim0.ptr)
-                       c->aim0.ptr->disconnect_channel(c->iface,
-                                                       c->channel_id);
-               if (c->aim1.ptr)
-                       c->aim1.ptr->disconnect_channel(c->iface,
-                                                       c->channel_id);
-               c->aim0.ptr = NULL;
-               c->aim1.ptr = NULL;
-       }
-
-       ida_simple_remove(&mdev_id, i->dev_id);
-       list_del(&i->list);
-       destroy_most_inst_obj(i);
-}
-EXPORT_SYMBOL_GPL(most_deregister_interface);
-
-/**
- * most_stop_enqueue - prevents core from enqueueing MBOs
- * @iface: pointer to interface
- * @id: channel id
- *
- * This is called by an HDM that _cannot_ attend to its duties and
- * is imminent to get run over by the core. The core is not going to
- * enqueue any further packets unless the flagging HDM calls
- * most_resume enqueue().
- */
-void most_stop_enqueue(struct most_interface *iface, int id)
-{
-       struct most_c_obj *c = get_channel_by_iface(iface, id);
-
-       if (!c)
-               return;
-
-       mutex_lock(&c->nq_mutex);
-       c->enqueue_halt = true;
-       mutex_unlock(&c->nq_mutex);
-}
-EXPORT_SYMBOL_GPL(most_stop_enqueue);
-
-/**
- * most_resume_enqueue - allow core to enqueue MBOs again
- * @iface: pointer to interface
- * @id: channel id
- *
- * This clears the enqueue halt flag and enqueues all MBOs currently
- * sitting in the wait fifo.
- */
-void most_resume_enqueue(struct most_interface *iface, int id)
-{
-       struct most_c_obj *c = get_channel_by_iface(iface, id);
-
-       if (!c)
-               return;
-
-       mutex_lock(&c->nq_mutex);
-       c->enqueue_halt = false;
-       mutex_unlock(&c->nq_mutex);
-
-       wake_up_interruptible(&c->hdm_fifo_wq);
-}
-EXPORT_SYMBOL_GPL(most_resume_enqueue);
-
-static int __init most_init(void)
-{
-       int err;
-
-       pr_info("init()\n");
-       INIT_LIST_HEAD(&instance_list);
-       INIT_LIST_HEAD(&aim_list);
-       ida_init(&mdev_id);
-
-       err = bus_register(&most_bus);
-       if (err) {
-               pr_info("Cannot register most bus\n");
-               return err;
-       }
-
-       most_class = class_create(THIS_MODULE, "most");
-       if (IS_ERR(most_class)) {
-               pr_info("No udev support.\n");
-               err = PTR_ERR(most_class);
-               goto exit_bus;
-       }
-
-       err = driver_register(&mostcore);
-       if (err) {
-               pr_info("Cannot register core driver\n");
-               goto exit_class;
-       }
-
-       core_dev = device_create(most_class, NULL, 0, NULL, "mostcore");
-       if (IS_ERR(core_dev)) {
-               err = PTR_ERR(core_dev);
-               goto exit_driver;
-       }
-
-       most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj);
-       if (!most_aim_kset) {
-               err = -ENOMEM;
-               goto exit_class_container;
-       }
-
-       most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj);
-       if (!most_inst_kset) {
-               err = -ENOMEM;
-               goto exit_driver_kset;
-       }
-
-       return 0;
-
-exit_driver_kset:
-       kset_unregister(most_aim_kset);
-exit_class_container:
-       device_destroy(most_class, 0);
-exit_driver:
-       driver_unregister(&mostcore);
-exit_class:
-       class_destroy(most_class);
-exit_bus:
-       bus_unregister(&most_bus);
-       return err;
-}
-
-static void __exit most_exit(void)
-{
-       struct most_inst_obj *i, *i_tmp;
-       struct most_aim_obj *d, *d_tmp;
-
-       pr_info("exit core module\n");
-       list_for_each_entry_safe(d, d_tmp, &aim_list, list) {
-               destroy_most_aim_obj(d);
-       }
-
-       list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-               list_del(&i->list);
-               destroy_most_inst_obj(i);
-       }
-       kset_unregister(most_inst_kset);
-       kset_unregister(most_aim_kset);
-       device_destroy(most_class, 0);
-       driver_unregister(&mostcore);
-       class_destroy(most_class);
-       bus_unregister(&most_bus);
-       ida_destroy(&mdev_id);
-}
-
-module_init(most_init);
-module_exit(most_exit);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
-MODULE_DESCRIPTION("Core module of stacked MOST Linux driver");
diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h
deleted file mode 100644 (file)
index 915e515..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * mostcore.h - Interface between MostCore,
- *   Hardware Dependent Module (HDM) and Application Interface Module (AIM).
- *
- * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-/*
- * Authors:
- *   Andrey Shvetsov <andrey.shvetsov@k2l.de>
- *   Christian Gromm <christian.gromm@microchip.com>
- *   Sebastian Graf
- */
-
-#ifndef __MOST_CORE_H__
-#define __MOST_CORE_H__
-
-#include <linux/types.h>
-
-struct kobject;
-struct module;
-
-/**
- * Interface type
- */
-enum most_interface_type {
-       ITYPE_LOOPBACK = 1,
-       ITYPE_I2C,
-       ITYPE_I2S,
-       ITYPE_TSI,
-       ITYPE_HBI,
-       ITYPE_MEDIALB_DIM,
-       ITYPE_MEDIALB_DIM2,
-       ITYPE_USB,
-       ITYPE_PCIE
-};
-
-/**
- * Channel direction.
- */
-enum most_channel_direction {
-       MOST_CH_RX = 1 << 0,
-       MOST_CH_TX = 1 << 1,
-};
-
-/**
- * Channel data type.
- */
-enum most_channel_data_type {
-       MOST_CH_CONTROL = 1 << 0,
-       MOST_CH_ASYNC = 1 << 1,
-       MOST_CH_ISOC = 1 << 2,
-       MOST_CH_SYNC = 1 << 5,
-};
-
-enum mbo_status_flags {
-       /* MBO was processed successfully (data was send or received )*/
-       MBO_SUCCESS = 0,
-       /* The MBO contains wrong or missing information.  */
-       MBO_E_INVAL,
-       /* MBO was completed as HDM Channel will be closed */
-       MBO_E_CLOSE,
-};
-
-/**
- * struct most_channel_capability - Channel capability
- * @direction: Supported channel directions.
- * The value is bitwise OR-combination of the values from the
- * enumeration most_channel_direction. Zero is allowed value and means
- * "channel may not be used".
- * @data_type: Supported channel data types.
- * The value is bitwise OR-combination of the values from the
- * enumeration most_channel_data_type. Zero is allowed value and means
- * "channel may not be used".
- * @num_buffer_packet: Maximum number of buffers supported by this channel
- * for packet data types (Async,Control,QoS)
- * @buffer_size_packet: Maximum buffer size supported by this channel
- * for packet data types (Async,Control,QoS)
- * @num_buffer_streaming: Maximum number of buffers supported by this channel
- * for streaming data types (Sync,AV Packetized)
- * @buffer_size_streaming: Maximum buffer size supported by this channel
- * for streaming data types (Sync,AV Packetized)
- * @name_suffix: Optional suffix providean by an HDM that is attached to the
- * regular channel name.
- *
- * Describes the capabilities of a MostCore channel like supported Data Types
- * and directions. This information is provided by an HDM for the MostCore.
- *
- * The Core creates read only sysfs attribute files in
- * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the
- * following attributes:
- *     -available_directions
- *     -available_datatypes
- *     -number_of_packet_buffers
- *     -number_of_stream_buffers
- *     -size_of_packet_buffer
- *     -size_of_stream_buffer
- * where content of each file is a string with all supported properties of this
- * very channel attribute.
- */
-struct most_channel_capability {
-       u16 direction;
-       u16 data_type;
-       u16 num_buffers_packet;
-       u16 buffer_size_packet;
-       u16 num_buffers_streaming;
-       u16 buffer_size_streaming;
-       const char *name_suffix;
-};
-
-/**
- * struct most_channel_config - stores channel configuration
- * @direction: direction of the channel
- * @data_type: data type travelling over this channel
- * @num_buffers: number of buffers
- * @buffer_size: size of a buffer for AIM.
- * Buffer size may be cutted down by HDM in a configure callback
- * to match to a given interface and channel type.
- * @extra_len: additional buffer space for internal HDM purposes like padding.
- * May be set by HDM in a configure callback if needed.
- * @subbuffer_size: size of a subbuffer
- * @packets_per_xact: number of MOST frames that are packet inside one USB
- *                   packet. This is USB specific
- *
- * Describes the configuration for a MostCore channel. This information is
- * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a
- * parameter of the "configure" function call.
- */
-struct most_channel_config {
-       enum most_channel_direction direction;
-       enum most_channel_data_type data_type;
-       u16 num_buffers;
-       u16 buffer_size;
-       u16 extra_len;
-       u16 subbuffer_size;
-       u16 packets_per_xact;
-};
-
-/*
- * struct mbo - MOST Buffer Object.
- * @context: context for core completion handler
- * @priv: private data for HDM
- *
- *     public: documented fields that are used for the communications
- *     between MostCore and HDMs
- *
- * @list: list head for use by the mbo's current owner
- * @ifp: (in) associated interface instance
- * @hdm_channel_id: (in) HDM channel instance
- * @virt_address: (in) kernel virtual address of the buffer
- * @bus_address: (in) bus address of the buffer
- * @buffer_length: (in) buffer payload length
- * @processed_length: (out) processed length
- * @status: (out) transfer status
- * @complete: (in) completion routine
- *
- * The MostCore allocates and initializes the MBO.
- *
- * The HDM receives MBO for transfer from MostCore with the call to enqueue().
- * The HDM copies the data to- or from the buffer depending on configured
- * channel direction, set "processed_length" and "status" and completes
- * the transfer procedure by calling the completion routine.
- *
- * At the end the MostCore deallocates the MBO or recycles it for further
- * transfers for the same or different HDM.
- *
- * Directions of usage:
- * The core driver should never access any MBO fields (even if marked
- * as "public") while the MBO is owned by an HDM. The ownership starts with
- * the call of enqueue() and ends with the call of its complete() routine.
- *
- *                                     II.
- * Every HDM attached to the core driver _must_ ensure that it returns any MBO
- * it owns (due to a previous call to enqueue() by the core driver) before it
- * de-registers an interface or gets unloaded from the kernel. If this direction
- * is violated memory leaks will occur, since the core driver does _not_ track
- * MBOs it is currently not in control of.
- *
- */
-struct mbo {
-       void *context;
-       void *priv;
-       struct list_head list;
-       struct most_interface *ifp;
-       int *num_buffers_ptr;
-       u16 hdm_channel_id;
-       void *virt_address;
-       dma_addr_t bus_address;
-       u16 buffer_length;
-       u16 processed_length;
-       enum mbo_status_flags status;
-       void (*complete)(struct mbo *);
-};
-
-/**
- * Interface instance description.
- *
- * Describes one instance of an interface like Medusa PCIe or Vantage USB.
- * This structure is allocated and initialized in the HDM. MostCore may not
- * modify this structure.
- *
- * @interface Interface type. \sa most_interface_type.
- * @description PRELIMINARY.
- *   Unique description of the device instance from point of view of the
- *   interface in free text form (ASCII).
- *   It may be a hexadecimal presentation of the memory address for the MediaLB
- *   IP or USB device ID with USB properties for USB interface, etc.
- * @num_channels Number of channels and size of the channel_vector.
- * @channel_vector Properties of the channels.
- *   Array index represents channel ID by the driver.
- * @configure Callback to change data type for the channel of the
- *   interface instance. May be zero if the instance of the interface is not
- *   configurable. Parameter channel_config describes direction and data
- *   type for the channel, configured by the higher level. The content of
- * @enqueue Delivers MBO to the HDM for processing.
- *   After HDM completes Rx- or Tx- operation the processed MBO shall
- *   be returned back to the MostCore using completion routine.
- *   The reason to get the MBO delivered from the MostCore after the channel
- *   is poisoned is the re-opening of the channel by the application.
- *   In this case the HDM shall hold MBOs and service the channel as usual.
- *   The HDM must be able to hold at least one MBO for each channel.
- *   The callback returns a negative value on error, otherwise 0.
- * @poison_channel Informs HDM about closing the channel. The HDM shall
- *   cancel all transfers and synchronously or asynchronously return
- *   all enqueued for this channel MBOs using the completion routine.
- *   The callback returns a negative value on error, otherwise 0.
- * @request_netinfo: triggers retrieving of network info from the HDM by
- *   means of "Message exchange over MDP/MEP"
- *   The call of the function request_netinfo with the parameter on_netinfo as
- *   NULL prohibits use of the previously obtained function pointer.
- * @priv Private field used by mostcore to store context information.
- */
-struct most_interface {
-       struct module *mod;
-       enum most_interface_type interface;
-       const char *description;
-       int num_channels;
-       struct most_channel_capability *channel_vector;
-       int (*configure)(struct most_interface *iface, int channel_idx,
-                        struct most_channel_config *channel_config);
-       int (*enqueue)(struct most_interface *iface, int channel_idx,
-                      struct mbo *mbo);
-       int (*poison_channel)(struct most_interface *iface, int channel_idx);
-       void (*request_netinfo)(struct most_interface *iface, int channel_idx,
-                               void (*on_netinfo)(struct most_interface *iface,
-                                                  unsigned char link_stat,
-                                                  unsigned char *mac_addr));
-       void *priv;
-};
-
-/**
- * struct most_aim - identifies MOST device driver to mostcore
- * @name: Driver name
- * @probe_channel: function for core to notify driver about channel connection
- * @disconnect_channel: callback function to disconnect a certain channel
- * @rx_completion: completion handler for received packets
- * @tx_completion: completion handler for transmitted packets
- * @context: context pointer to be used by mostcore
- */
-struct most_aim {
-       const char *name;
-       int (*probe_channel)(struct most_interface *iface, int channel_idx,
-                            struct most_channel_config *cfg,
-                            struct kobject *parent, char *name);
-       int (*disconnect_channel)(struct most_interface *iface,
-                                 int channel_idx);
-       int (*rx_completion)(struct mbo *mbo);
-       int (*tx_completion)(struct most_interface *iface, int channel_idx);
-       void *context;
-};
-
-/**
- * most_register_interface - Registers instance of the interface.
- * @iface: Pointer to the interface instance description.
- *
- * Returns a pointer to the kobject of the generated instance.
- *
- * Note: HDM has to ensure that any reference held on the kobj is
- * released before deregistering the interface.
- */
-struct kobject *most_register_interface(struct most_interface *iface);
-
-/**
- * Deregisters instance of the interface.
- * @intf_instance Pointer to the interface instance description.
- */
-void most_deregister_interface(struct most_interface *iface);
-void most_submit_mbo(struct mbo *mbo);
-
-/**
- * most_stop_enqueue - prevents core from enqueing MBOs
- * @iface: pointer to interface
- * @channel_idx: channel index
- */
-void most_stop_enqueue(struct most_interface *iface, int channel_idx);
-
-/**
- * most_resume_enqueue - allow core to enqueue MBOs again
- * @iface: pointer to interface
- * @channel_idx: channel index
- *
- * This clears the enqueue halt flag and enqueues all MBOs currently
- * in wait fifo.
- */
-void most_resume_enqueue(struct most_interface *iface, int channel_idx);
-int most_register_aim(struct most_aim *aim);
-int most_deregister_aim(struct most_aim *aim);
-struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
-                        struct most_aim *);
-void most_put_mbo(struct mbo *mbo);
-int channel_has_mbo(struct most_interface *iface, int channel_idx,
-                   struct most_aim *aim);
-int most_start_channel(struct most_interface *iface, int channel_idx,
-                      struct most_aim *);
-int most_stop_channel(struct most_interface *iface, int channel_idx,
-                     struct most_aim *);
-
-#endif /* MOST_CORE_H_ */
diff --git a/drivers/staging/most/net/Kconfig b/drivers/staging/most/net/Kconfig
new file mode 100644 (file)
index 0000000..795330b
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# MOST Networking configuration
+#
+
+config MOST_NET
+       tristate "Net"
+       depends on NET
+
+       ---help---
+         Say Y here if you want to commumicate via a networking device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called most_net.
diff --git a/drivers/staging/most/net/Makefile b/drivers/staging/most/net/Makefile
new file mode 100644 (file)
index 0000000..54500aa
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_NET) += most_net.o
+
+most_net-objs := net.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c
new file mode 100644 (file)
index 0000000..30d816b
--- /dev/null
@@ -0,0 +1,562 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * net.c - Networking component for Mostcore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include "most/core.h"
+
+#define MEP_HDR_LEN 8
+#define MDP_HDR_LEN 16
+#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)
+
+#define PMHL 5
+
+#define PMS_TELID_UNSEGM_MAMAC 0x0A
+#define PMS_FIFONO_MDP         0x01
+#define PMS_FIFONO_MEP         0x04
+#define PMS_MSGTYPE_DATA       0x04
+#define PMS_DEF_PRIO           0
+#define MEP_DEF_RETRY          15
+
+#define PMS_FIFONO_MASK                0x07
+#define PMS_FIFONO_SHIFT       3
+#define PMS_RETRY_SHIFT                4
+#define PMS_TELID_MASK         0x0F
+#define PMS_TELID_SHIFT                4
+
+#define HB(value)              ((u8)((u16)(value) >> 8))
+#define LB(value)              ((u8)(value))
+
+#define EXTRACT_BIT_SET(bitset_name, value) \
+       (((value) >> bitset_name##_SHIFT) & bitset_name##_MASK)
+
+#define PMS_IS_MEP(buf, len) \
+       ((len) > MEP_HDR_LEN && \
+        EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP)
+
+static inline bool pms_is_mamac(char *buf, u32 len)
+{
+       return (len > MDP_HDR_LEN &&
+               EXTRACT_BIT_SET(PMS_FIFONO, buf[3]) == PMS_FIFONO_MDP &&
+               EXTRACT_BIT_SET(PMS_TELID, buf[14]) == PMS_TELID_UNSEGM_MAMAC);
+}
+
+struct net_dev_channel {
+       bool linked;
+       int ch_id;
+};
+
+struct net_dev_context {
+       struct most_interface *iface;
+       bool is_mamac;
+       struct net_device *dev;
+       struct net_dev_channel rx;
+       struct net_dev_channel tx;
+       struct list_head list;
+};
+
+static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
+static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */
+static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */
+static struct core_component comp;
+
+static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
+{
+       u8 *buff = mbo->virt_address;
+       const u8 broadcast[] = { 0x03, 0xFF };
+       const u8 *dest_addr = skb->data + 4;
+       const u8 *eth_type = skb->data + 12;
+       unsigned int payload_len = skb->len - ETH_HLEN;
+       unsigned int mdp_len = payload_len + MDP_HDR_LEN;
+
+       if (mbo->buffer_length < mdp_len) {
+               pr_err("drop: too small buffer! (%d for %d)\n",
+                      mbo->buffer_length, mdp_len);
+               return -EINVAL;
+       }
+
+       if (skb->len < ETH_HLEN) {
+               pr_err("drop: too small packet! (%d)\n", skb->len);
+               return -EINVAL;
+       }
+
+       if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF)
+               dest_addr = broadcast;
+
+       *buff++ = HB(mdp_len - 2);
+       *buff++ = LB(mdp_len - 2);
+
+       *buff++ = PMHL;
+       *buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
+       *buff++ = PMS_DEF_PRIO;
+       *buff++ = dest_addr[0];
+       *buff++ = dest_addr[1];
+       *buff++ = 0x00;
+
+       *buff++ = HB(payload_len + 6);
+       *buff++ = LB(payload_len + 6);
+
+       /* end of FPH here */
+
+       *buff++ = eth_type[0];
+       *buff++ = eth_type[1];
+       *buff++ = 0;
+       *buff++ = 0;
+
+       *buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len);
+       *buff++ = LB(payload_len);
+
+       memcpy(buff, skb->data + ETH_HLEN, payload_len);
+       mbo->buffer_length = mdp_len;
+       return 0;
+}
+
+static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
+{
+       u8 *buff = mbo->virt_address;
+       unsigned int mep_len = skb->len + MEP_HDR_LEN;
+
+       if (mbo->buffer_length < mep_len) {
+               pr_err("drop: too small buffer! (%d for %d)\n",
+                      mbo->buffer_length, mep_len);
+               return -EINVAL;
+       }
+
+       *buff++ = HB(mep_len - 2);
+       *buff++ = LB(mep_len - 2);
+
+       *buff++ = PMHL;
+       *buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
+       *buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO;
+       *buff++ = 0;
+       *buff++ = 0;
+       *buff++ = 0;
+
+       memcpy(buff, skb->data, skb->len);
+       mbo->buffer_length = mep_len;
+       return 0;
+}
+
+static int most_nd_set_mac_address(struct net_device *dev, void *p)
+{
+       struct net_dev_context *nd = netdev_priv(dev);
+       int err = eth_mac_addr(dev, p);
+
+       if (err)
+               return err;
+
+       nd->is_mamac =
+               (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
+                dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);
+
+       /*
+        * Set default MTU for the given packet type.
+        * It is still possible to change MTU using ip tools afterwards.
+        */
+       dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN;
+
+       return 0;
+}
+
+static void on_netinfo(struct most_interface *iface,
+                      unsigned char link_stat, unsigned char *mac_addr);
+
+static int most_nd_open(struct net_device *dev)
+{
+       struct net_dev_context *nd = netdev_priv(dev);
+       int ret = 0;
+
+       mutex_lock(&probe_disc_mt);
+
+       if (most_start_channel(nd->iface, nd->rx.ch_id, &comp)) {
+               netdev_err(dev, "most_start_channel() failed\n");
+               ret = -EBUSY;
+               goto unlock;
+       }
+
+       if (most_start_channel(nd->iface, nd->tx.ch_id, &comp)) {
+               netdev_err(dev, "most_start_channel() failed\n");
+               most_stop_channel(nd->iface, nd->rx.ch_id, &comp);
+               ret = -EBUSY;
+               goto unlock;
+       }
+
+       netif_carrier_off(dev);
+       if (is_valid_ether_addr(dev->dev_addr))
+               netif_dormant_off(dev);
+       else
+               netif_dormant_on(dev);
+       netif_wake_queue(dev);
+       if (nd->iface->request_netinfo)
+               nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo);
+
+unlock:
+       mutex_unlock(&probe_disc_mt);
+       return ret;
+}
+
+static int most_nd_stop(struct net_device *dev)
+{
+       struct net_dev_context *nd = netdev_priv(dev);
+
+       netif_stop_queue(dev);
+       if (nd->iface->request_netinfo)
+               nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL);
+       most_stop_channel(nd->iface, nd->rx.ch_id, &comp);
+       most_stop_channel(nd->iface, nd->tx.ch_id, &comp);
+
+       return 0;
+}
+
+static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
+                                     struct net_device *dev)
+{
+       struct net_dev_context *nd = netdev_priv(dev);
+       struct mbo *mbo;
+       int ret;
+
+       mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &comp);
+
+       if (!mbo) {
+               netif_stop_queue(dev);
+               dev->stats.tx_fifo_errors++;
+               return NETDEV_TX_BUSY;
+       }
+
+       if (nd->is_mamac)
+               ret = skb_to_mamac(skb, mbo);
+       else
+               ret = skb_to_mep(skb, mbo);
+
+       if (ret) {
+               most_put_mbo(mbo);
+               dev->stats.tx_dropped++;
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+
+       most_submit_mbo(mbo);
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += skb->len;
+       kfree_skb(skb);
+       return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops most_nd_ops = {
+       .ndo_open = most_nd_open,
+       .ndo_stop = most_nd_stop,
+       .ndo_start_xmit = most_nd_start_xmit,
+       .ndo_set_mac_address = most_nd_set_mac_address,
+};
+
+static void most_nd_setup(struct net_device *dev)
+{
+       ether_setup(dev);
+       dev->netdev_ops = &most_nd_ops;
+}
+
+static struct net_dev_context *get_net_dev(struct most_interface *iface)
+{
+       struct net_dev_context *nd;
+
+       list_for_each_entry(nd, &net_devices, list)
+               if (nd->iface == iface)
+                       return nd;
+       return NULL;
+}
+
+static struct net_dev_context *get_net_dev_hold(struct most_interface *iface)
+{
+       struct net_dev_context *nd;
+       unsigned long flags;
+
+       spin_lock_irqsave(&list_lock, flags);
+       nd = get_net_dev(iface);
+       if (nd && nd->rx.linked && nd->tx.linked)
+               dev_hold(nd->dev);
+       else
+               nd = NULL;
+       spin_unlock_irqrestore(&list_lock, flags);
+       return nd;
+}
+
+static int comp_probe_channel(struct most_interface *iface, int channel_idx,
+                             struct most_channel_config *ccfg, char *name)
+{
+       struct net_dev_context *nd;
+       struct net_dev_channel *ch;
+       struct net_device *dev;
+       unsigned long flags;
+       int ret = 0;
+
+       if (!iface)
+               return -EINVAL;
+
+       if (ccfg->data_type != MOST_CH_ASYNC)
+               return -EINVAL;
+
+       mutex_lock(&probe_disc_mt);
+       nd = get_net_dev(iface);
+       if (!nd) {
+               dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d",
+                                  NET_NAME_UNKNOWN, most_nd_setup);
+               if (!dev) {
+                       ret = -ENOMEM;
+                       goto unlock;
+               }
+
+               nd = netdev_priv(dev);
+               nd->iface = iface;
+               nd->dev = dev;
+
+               spin_lock_irqsave(&list_lock, flags);
+               list_add(&nd->list, &net_devices);
+               spin_unlock_irqrestore(&list_lock, flags);
+
+               ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
+       } else {
+               ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
+               if (ch->linked) {
+                       pr_err("direction is allocated\n");
+                       ret = -EINVAL;
+                       goto unlock;
+               }
+
+               if (register_netdev(nd->dev)) {
+                       pr_err("register_netdev() failed\n");
+                       ret = -EINVAL;
+                       goto unlock;
+               }
+       }
+       ch->ch_id = channel_idx;
+       ch->linked = true;
+
+unlock:
+       mutex_unlock(&probe_disc_mt);
+       return ret;
+}
+
+static int comp_disconnect_channel(struct most_interface *iface,
+                                  int channel_idx)
+{
+       struct net_dev_context *nd;
+       struct net_dev_channel *ch;
+       unsigned long flags;
+       int ret = 0;
+
+       mutex_lock(&probe_disc_mt);
+       nd = get_net_dev(iface);
+       if (!nd) {
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       if (nd->rx.linked && channel_idx == nd->rx.ch_id) {
+               ch = &nd->rx;
+       } else if (nd->tx.linked && channel_idx == nd->tx.ch_id) {
+               ch = &nd->tx;
+       } else {
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       if (nd->rx.linked && nd->tx.linked) {
+               spin_lock_irqsave(&list_lock, flags);
+               ch->linked = false;
+               spin_unlock_irqrestore(&list_lock, flags);
+
+               /*
+                * do not call most_stop_channel() here, because channels are
+                * going to be closed in ndo_stop() after unregister_netdev()
+                */
+               unregister_netdev(nd->dev);
+       } else {
+               spin_lock_irqsave(&list_lock, flags);
+               list_del(&nd->list);
+               spin_unlock_irqrestore(&list_lock, flags);
+
+               free_netdev(nd->dev);
+       }
+
+unlock:
+       mutex_unlock(&probe_disc_mt);
+       return ret;
+}
+
+static int comp_resume_tx_channel(struct most_interface *iface,
+                                 int channel_idx)
+{
+       struct net_dev_context *nd;
+
+       nd = get_net_dev_hold(iface);
+       if (!nd)
+               return 0;
+
+       if (nd->tx.ch_id != channel_idx)
+               goto put_nd;
+
+       netif_wake_queue(nd->dev);
+
+put_nd:
+       dev_put(nd->dev);
+       return 0;
+}
+
+static int comp_rx_data(struct mbo *mbo)
+{
+       const u32 zero = 0;
+       struct net_dev_context *nd;
+       char *buf = mbo->virt_address;
+       u32 len = mbo->processed_length;
+       struct sk_buff *skb;
+       struct net_device *dev;
+       unsigned int skb_len;
+       int ret = 0;
+
+       nd = get_net_dev_hold(mbo->ifp);
+       if (!nd)
+               return -EIO;
+
+       if (nd->rx.ch_id != mbo->hdm_channel_id) {
+               ret = -EIO;
+               goto put_nd;
+       }
+
+       dev = nd->dev;
+
+       if (nd->is_mamac) {
+               if (!pms_is_mamac(buf, len)) {
+                       ret = -EIO;
+                       goto put_nd;
+               }
+
+               skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
+       } else {
+               if (!PMS_IS_MEP(buf, len)) {
+                       ret = -EIO;
+                       goto put_nd;
+               }
+
+               skb = dev_alloc_skb(len - MEP_HDR_LEN);
+       }
+
+       if (!skb) {
+               dev->stats.rx_dropped++;
+               pr_err_once("drop packet: no memory for skb\n");
+               goto out;
+       }
+
+       skb->dev = dev;
+
+       if (nd->is_mamac) {
+               /* dest */
+               ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr);
+
+               /* src */
+               skb_put_data(skb, &zero, 4);
+               skb_put_data(skb, buf + 5, 2);
+
+               /* eth type */
+               skb_put_data(skb, buf + 10, 2);
+
+               buf += MDP_HDR_LEN;
+               len -= MDP_HDR_LEN;
+       } else {
+               buf += MEP_HDR_LEN;
+               len -= MEP_HDR_LEN;
+       }
+
+       skb_put_data(skb, buf, len);
+       skb->protocol = eth_type_trans(skb, dev);
+       skb_len = skb->len;
+       if (netif_rx(skb) == NET_RX_SUCCESS) {
+               dev->stats.rx_packets++;
+               dev->stats.rx_bytes += skb_len;
+       } else {
+               dev->stats.rx_dropped++;
+       }
+
+out:
+       most_put_mbo(mbo);
+
+put_nd:
+       dev_put(nd->dev);
+       return ret;
+}
+
+static struct core_component comp = {
+       .name = "net",
+       .probe_channel = comp_probe_channel,
+       .disconnect_channel = comp_disconnect_channel,
+       .tx_completion = comp_resume_tx_channel,
+       .rx_completion = comp_rx_data,
+};
+
+static int __init most_net_init(void)
+{
+       spin_lock_init(&list_lock);
+       mutex_init(&probe_disc_mt);
+       return most_register_component(&comp);
+}
+
+static void __exit most_net_exit(void)
+{
+       most_deregister_component(&comp);
+}
+
+/**
+ * on_netinfo - callback for HDM to be informed about HW's MAC
+ * @param iface - most interface instance
+ * @param link_stat - link status
+ * @param mac_addr - MAC address
+ */
+static void on_netinfo(struct most_interface *iface,
+                      unsigned char link_stat, unsigned char *mac_addr)
+{
+       struct net_dev_context *nd;
+       struct net_device *dev;
+       const u8 *m = mac_addr;
+
+       nd = get_net_dev_hold(iface);
+       if (!nd)
+               return;
+
+       dev = nd->dev;
+
+       if (link_stat)
+               netif_carrier_on(dev);
+       else
+               netif_carrier_off(dev);
+
+       if (m && is_valid_ether_addr(m)) {
+               if (!is_valid_ether_addr(dev->dev_addr)) {
+                       netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n",
+                                   m[0], m[1], m[2], m[3], m[4], m[5]);
+                       ether_addr_copy(dev->dev_addr, m);
+                       netif_dormant_off(dev);
+               } else if (!ether_addr_equal(dev->dev_addr, m)) {
+                       netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n",
+                                   m[0], m[1], m[2], m[3], m[4], m[5]);
+               }
+       }
+
+       dev_put(nd->dev);
+}
+
+module_init(most_net_init);
+module_exit(most_net_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("Networking Component Module for Mostcore");
diff --git a/drivers/staging/most/sound/Kconfig b/drivers/staging/most/sound/Kconfig
new file mode 100644 (file)
index 0000000..115262a
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# MOST ALSA configuration
+#
+
+config MOST_SOUND
+       tristate "Sound"
+       depends on SND
+       select SND_PCM
+       ---help---
+         Say Y here if you want to commumicate via ALSA/sound devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called most_sound.
diff --git a/drivers/staging/most/sound/Makefile b/drivers/staging/most/sound/Makefile
new file mode 100644 (file)
index 0000000..eee8774
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_SOUND) += most_sound.o
+
+most_sound-objs := sound.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c
new file mode 100644 (file)
index 0000000..83cec21
--- /dev/null
@@ -0,0 +1,758 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * sound.c - Sound component for Mostcore
+ *
+ * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <most/core.h>
+
+#define DRIVER_NAME "sound"
+
+static struct list_head dev_list;
+static struct core_component comp;
+
+/**
+ * struct channel - private structure to keep channel specific data
+ * @substream: stores the substream structure
+ * @iface: interface for which the channel belongs to
+ * @cfg: channel configuration
+ * @card: registered sound card
+ * @list: list for private use
+ * @id: channel index
+ * @period_pos: current period position (ring buffer)
+ * @buffer_pos: current buffer position (ring buffer)
+ * @is_stream_running: identifies whether a stream is running or not
+ * @opened: set when the stream is opened
+ * @playback_task: playback thread
+ * @playback_waitq: waitq used by playback thread
+ */
+struct channel {
+       struct snd_pcm_substream *substream;
+       struct snd_pcm_hardware pcm_hardware;
+       struct most_interface *iface;
+       struct most_channel_config *cfg;
+       struct snd_card *card;
+       struct list_head list;
+       int id;
+       unsigned int period_pos;
+       unsigned int buffer_pos;
+       bool is_stream_running;
+
+       struct task_struct *playback_task;
+       wait_queue_head_t playback_waitq;
+
+       void (*copy_fn)(void *alsa, void *most, unsigned int bytes);
+};
+
+#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
+                      SNDRV_PCM_INFO_MMAP_VALID | \
+                      SNDRV_PCM_INFO_BATCH | \
+                      SNDRV_PCM_INFO_INTERLEAVED | \
+                      SNDRV_PCM_INFO_BLOCK_TRANSFER)
+
+#define swap16(val) ( \
+       (((u16)(val) << 8) & (u16)0xFF00) | \
+       (((u16)(val) >> 8) & (u16)0x00FF))
+
+#define swap32(val) ( \
+       (((u32)(val) << 24) & (u32)0xFF000000) | \
+       (((u32)(val) <<  8) & (u32)0x00FF0000) | \
+       (((u32)(val) >>  8) & (u32)0x0000FF00) | \
+       (((u32)(val) >> 24) & (u32)0x000000FF))
+
+static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes)
+{
+       unsigned int i = 0;
+
+       while (i < (bytes / 2)) {
+               dest[i] = swap16(source[i]);
+               i++;
+       }
+}
+
+static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes)
+{
+       unsigned int i = 0;
+
+       while (i < bytes - 2) {
+               dest[i] = source[i + 2];
+               dest[i + 1] = source[i + 1];
+               dest[i + 2] = source[i];
+               i += 3;
+       }
+}
+
+static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes)
+{
+       unsigned int i = 0;
+
+       while (i < bytes / 4) {
+               dest[i] = swap32(source[i]);
+               i++;
+       }
+}
+
+static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes)
+{
+       memcpy(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy16(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy24(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy32(most, alsa, bytes);
+}
+
+static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes)
+{
+       memcpy(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy16(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy24(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy32(alsa, most, bytes);
+}
+
+/**
+ * get_channel - get pointer to channel
+ * @iface: interface structure
+ * @channel_id: channel ID
+ *
+ * This traverses the channel list and returns the channel matching the
+ * ID and interface.
+ *
+ * Returns pointer to channel on success or NULL otherwise.
+ */
+static struct channel *get_channel(struct most_interface *iface,
+                                  int channel_id)
+{
+       struct channel *channel, *tmp;
+
+       list_for_each_entry_safe(channel, tmp, &dev_list, list) {
+               if ((channel->iface == iface) && (channel->id == channel_id))
+                       return channel;
+       }
+
+       return NULL;
+}
+
+/**
+ * copy_data - implements data copying function
+ * @channel: channel
+ * @mbo: MBO from core
+ *
+ * Copy data from/to ring buffer to/from MBO and update the buffer position
+ */
+static bool copy_data(struct channel *channel, struct mbo *mbo)
+{
+       struct snd_pcm_runtime *const runtime = channel->substream->runtime;
+       unsigned int const frame_bytes = channel->cfg->subbuffer_size;
+       unsigned int const buffer_size = runtime->buffer_size;
+       unsigned int frames;
+       unsigned int fr0;
+
+       if (channel->cfg->direction & MOST_CH_RX)
+               frames = mbo->processed_length / frame_bytes;
+       else
+               frames = mbo->buffer_length / frame_bytes;
+       fr0 = min(buffer_size - channel->buffer_pos, frames);
+
+       channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes,
+                        mbo->virt_address,
+                        fr0 * frame_bytes);
+
+       if (frames > fr0) {
+               /* wrap around at end of ring buffer */
+               channel->copy_fn(runtime->dma_area,
+                                mbo->virt_address + fr0 * frame_bytes,
+                                (frames - fr0) * frame_bytes);
+       }
+
+       channel->buffer_pos += frames;
+       if (channel->buffer_pos >= buffer_size)
+               channel->buffer_pos -= buffer_size;
+       channel->period_pos += frames;
+       if (channel->period_pos >= runtime->period_size) {
+               channel->period_pos -= runtime->period_size;
+               return true;
+       }
+
+       return false;
+}
+
+/**
+ * playback_thread - function implements the playback thread
+ * @data: private data
+ *
+ * Thread which does the playback functionality in a loop. It waits for a free
+ * MBO from mostcore for a particular channel and copy the data from ring buffer
+ * to MBO. Submit the MBO back to mostcore, after copying the data.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int playback_thread(void *data)
+{
+       struct channel *const channel = data;
+
+       while (!kthread_should_stop()) {
+               struct mbo *mbo = NULL;
+               bool period_elapsed = false;
+
+               wait_event_interruptible(
+                       channel->playback_waitq,
+                       kthread_should_stop() ||
+                       (channel->is_stream_running &&
+                        (mbo = most_get_mbo(channel->iface, channel->id,
+                                            &comp))));
+               if (!mbo)
+                       continue;
+
+               if (channel->is_stream_running)
+                       period_elapsed = copy_data(channel, mbo);
+               else
+                       memset(mbo->virt_address, 0, mbo->buffer_length);
+
+               most_submit_mbo(mbo);
+               if (period_elapsed)
+                       snd_pcm_period_elapsed(channel->substream);
+       }
+
+       return 0;
+}
+
+/**
+ * pcm_open - implements open callback function for PCM middle layer
+ * @substream: pointer to ALSA PCM substream
+ *
+ * This is called when a PCM substream is opened. At least, the function should
+ * initialize the runtime->hw record.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_open(struct snd_pcm_substream *substream)
+{
+       struct channel *channel = substream->private_data;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct most_channel_config *cfg = channel->cfg;
+
+       channel->substream = substream;
+
+       if (cfg->direction == MOST_CH_TX) {
+               channel->playback_task = kthread_run(playback_thread, channel,
+                                                    "most_audio_playback");
+               if (IS_ERR(channel->playback_task)) {
+                       pr_err("Couldn't start thread\n");
+                       return PTR_ERR(channel->playback_task);
+               }
+       }
+
+       if (most_start_channel(channel->iface, channel->id, &comp)) {
+               pr_err("most_start_channel() failed!\n");
+               if (cfg->direction == MOST_CH_TX)
+                       kthread_stop(channel->playback_task);
+               return -EBUSY;
+       }
+
+       runtime->hw = channel->pcm_hardware;
+       return 0;
+}
+
+/**
+ * pcm_close - implements close callback function for PCM middle layer
+ * @substream: sub-stream pointer
+ *
+ * Obviously, this is called when a PCM substream is closed. Any private
+ * instance for a PCM substream allocated in the open callback will be
+ * released here.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_close(struct snd_pcm_substream *substream)
+{
+       struct channel *channel = substream->private_data;
+
+       if (channel->cfg->direction == MOST_CH_TX)
+               kthread_stop(channel->playback_task);
+       most_stop_channel(channel->iface, channel->id, &comp);
+
+       return 0;
+}
+
+/**
+ * pcm_hw_params - implements hw_params callback function for PCM middle layer
+ * @substream: sub-stream pointer
+ * @hw_params: contains the hardware parameters set by the application
+ *
+ * This is called when the hardware parameters is set by the application, that
+ * is, once when the buffer size, the period size, the format, etc. are defined
+ * for the PCM substream. Many hardware setups should be done is this callback,
+ * including the allocation of buffers.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_hw_params(struct snd_pcm_substream *substream,
+                        struct snd_pcm_hw_params *hw_params)
+{
+       struct channel *channel = substream->private_data;
+
+       if ((params_channels(hw_params) > channel->pcm_hardware.channels_max) ||
+           (params_channels(hw_params) < channel->pcm_hardware.channels_min)) {
+               pr_err("Requested number of channels not supported.\n");
+               return -EINVAL;
+       }
+       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                               params_buffer_bytes(hw_params));
+}
+
+/**
+ * pcm_hw_free - implements hw_free callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This is called to release the resources allocated via hw_params.
+ * This function will be always called before the close callback is called.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+/**
+ * pcm_prepare - implements prepare callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This callback is called when the PCM is "prepared". Format rate, sample rate,
+ * etc., can be set here. This callback can be called many times at each setup.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct channel *channel = substream->private_data;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct most_channel_config *cfg = channel->cfg;
+       int width = snd_pcm_format_physical_width(runtime->format);
+
+       channel->copy_fn = NULL;
+
+       if (cfg->direction == MOST_CH_TX) {
+               if (snd_pcm_format_big_endian(runtime->format) || width == 8)
+                       channel->copy_fn = alsa_to_most_memcpy;
+               else if (width == 16)
+                       channel->copy_fn = alsa_to_most_copy16;
+               else if (width == 24)
+                       channel->copy_fn = alsa_to_most_copy24;
+               else if (width == 32)
+                       channel->copy_fn = alsa_to_most_copy32;
+       } else {
+               if (snd_pcm_format_big_endian(runtime->format) || width == 8)
+                       channel->copy_fn = most_to_alsa_memcpy;
+               else if (width == 16)
+                       channel->copy_fn = most_to_alsa_copy16;
+               else if (width == 24)
+                       channel->copy_fn = most_to_alsa_copy24;
+               else if (width == 32)
+                       channel->copy_fn = most_to_alsa_copy32;
+       }
+
+       if (!channel->copy_fn) {
+               pr_err("unsupported format\n");
+               return -EINVAL;
+       }
+
+       channel->period_pos = 0;
+       channel->buffer_pos = 0;
+
+       return 0;
+}
+
+/**
+ * pcm_trigger - implements trigger callback function for PCM middle layer
+ * @substream: substream pointer
+ * @cmd: action to perform
+ *
+ * This is called when the PCM is started, stopped or paused. The action will be
+ * specified in the second argument, SNDRV_PCM_TRIGGER_XXX
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct channel *channel = substream->private_data;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               channel->is_stream_running = true;
+               wake_up_interruptible(&channel->playback_waitq);
+               return 0;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+               channel->is_stream_running = false;
+               return 0;
+
+       default:
+               pr_info("%s(), invalid\n", __func__);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * pcm_pointer - implements pointer callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This callback is called when the PCM middle layer inquires the current
+ * hardware position on the buffer. The position must be returned in frames,
+ * ranging from 0 to buffer_size-1.
+ */
+static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct channel *channel = substream->private_data;
+
+       return channel->buffer_pos;
+}
+
+/**
+ * Initialization of struct snd_pcm_ops
+ */
+static const struct snd_pcm_ops pcm_ops = {
+       .open       = pcm_open,
+       .close      = pcm_close,
+       .ioctl      = snd_pcm_lib_ioctl,
+       .hw_params  = pcm_hw_params,
+       .hw_free    = pcm_hw_free,
+       .prepare    = pcm_prepare,
+       .trigger    = pcm_trigger,
+       .pointer    = pcm_pointer,
+       .page       = snd_pcm_lib_get_vmalloc_page,
+       .mmap       = snd_pcm_lib_mmap_vmalloc,
+};
+
+static int split_arg_list(char *buf, char **card_name, char **pcm_format)
+{
+       *card_name = strsep(&buf, ".");
+       if (!*card_name)
+               return -EIO;
+       *pcm_format = strsep(&buf, ".\n");
+       if (!*pcm_format)
+               return -EIO;
+       return 0;
+}
+
+static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw,
+                              char *pcm_format,
+                              struct most_channel_config *cfg)
+{
+       pcm_hw->info = MOST_PCM_INFO;
+       pcm_hw->rates = SNDRV_PCM_RATE_48000;
+       pcm_hw->rate_min = 48000;
+       pcm_hw->rate_max = 48000;
+       pcm_hw->buffer_bytes_max = cfg->num_buffers * cfg->buffer_size;
+       pcm_hw->period_bytes_min = cfg->buffer_size;
+       pcm_hw->period_bytes_max = cfg->buffer_size;
+       pcm_hw->periods_min = 1;
+       pcm_hw->periods_max = cfg->num_buffers;
+
+       if (!strcmp(pcm_format, "1x8")) {
+               if (cfg->subbuffer_size != 1)
+                       goto error;
+               pr_info("PCM format is 8-bit mono\n");
+               pcm_hw->channels_min = 1;
+               pcm_hw->channels_max = 1;
+               pcm_hw->formats = SNDRV_PCM_FMTBIT_S8;
+       } else if (!strcmp(pcm_format, "2x16")) {
+               if (cfg->subbuffer_size != 4)
+                       goto error;
+               pr_info("PCM format is 16-bit stereo\n");
+               pcm_hw->channels_min = 2;
+               pcm_hw->channels_max = 2;
+               pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE |
+                                 SNDRV_PCM_FMTBIT_S16_BE;
+       } else if (!strcmp(pcm_format, "2x24")) {
+               if (cfg->subbuffer_size != 6)
+                       goto error;
+               pr_info("PCM format is 24-bit stereo\n");
+               pcm_hw->channels_min = 2;
+               pcm_hw->channels_max = 2;
+               pcm_hw->formats = SNDRV_PCM_FMTBIT_S24_3LE |
+                                 SNDRV_PCM_FMTBIT_S24_3BE;
+       } else if (!strcmp(pcm_format, "2x32")) {
+               if (cfg->subbuffer_size != 8)
+                       goto error;
+               pr_info("PCM format is 32-bit stereo\n");
+               pcm_hw->channels_min = 2;
+               pcm_hw->channels_max = 2;
+               pcm_hw->formats = SNDRV_PCM_FMTBIT_S32_LE |
+                                 SNDRV_PCM_FMTBIT_S32_BE;
+       } else if (!strcmp(pcm_format, "6x16")) {
+               if (cfg->subbuffer_size != 12)
+                       goto error;
+               pr_info("PCM format is 16-bit 5.1 multi channel\n");
+               pcm_hw->channels_min = 6;
+               pcm_hw->channels_max = 6;
+               pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE |
+                                 SNDRV_PCM_FMTBIT_S16_BE;
+       } else {
+               pr_err("PCM format %s not supported\n", pcm_format);
+               return -EIO;
+       }
+       return 0;
+error:
+       pr_err("Audio resolution doesn't fit subbuffer size\n");
+       return -EINVAL;
+}
+
+/**
+ * audio_probe_channel - probe function of the driver module
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ * @cfg: pointer to actual channel configuration
+ * @arg_list: string that provides the name of the device to be created in /dev
+ *           plus the desired audio resolution
+ *
+ * Creates sound card, pcm device, sets pcm ops and registers sound card.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_probe_channel(struct most_interface *iface, int channel_id,
+                              struct most_channel_config *cfg,
+                              char *arg_list)
+{
+       struct channel *channel;
+       struct snd_card *card;
+       struct snd_pcm *pcm;
+       int playback_count = 0;
+       int capture_count = 0;
+       int ret;
+       int direction;
+       char *card_name;
+       char *pcm_format;
+
+       if (!iface)
+               return -EINVAL;
+
+       if (cfg->data_type != MOST_CH_SYNC) {
+               pr_err("Incompatible channel type\n");
+               return -EINVAL;
+       }
+
+       if (get_channel(iface, channel_id)) {
+               pr_err("channel (%s:%d) is already linked\n",
+                      iface->description, channel_id);
+               return -EINVAL;
+       }
+
+       if (cfg->direction == MOST_CH_TX) {
+               playback_count = 1;
+               direction = SNDRV_PCM_STREAM_PLAYBACK;
+       } else {
+               capture_count = 1;
+               direction = SNDRV_PCM_STREAM_CAPTURE;
+       }
+
+       ret = split_arg_list(arg_list, &card_name, &pcm_format);
+       if (ret < 0) {
+               pr_info("PCM format missing\n");
+               return ret;
+       }
+
+       ret = snd_card_new(NULL, -1, card_name, THIS_MODULE,
+                          sizeof(*channel), &card);
+       if (ret < 0)
+               return ret;
+
+       channel = card->private_data;
+       channel->card = card;
+       channel->cfg = cfg;
+       channel->iface = iface;
+       channel->id = channel_id;
+       init_waitqueue_head(&channel->playback_waitq);
+
+       ret = audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg);
+       if (ret)
+               goto err_free_card;
+
+       snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME);
+       snprintf(card->shortname, sizeof(card->shortname), "Microchip MOST:%d",
+                card->number);
+       snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d",
+                card->shortname, iface->description, channel_id);
+
+       ret = snd_pcm_new(card, card_name, 0, playback_count,
+                         capture_count, &pcm);
+       if (ret < 0)
+               goto err_free_card;
+
+       pcm->private_data = channel;
+
+       snd_pcm_set_ops(pcm, direction, &pcm_ops);
+
+       ret = snd_card_register(card);
+       if (ret < 0)
+               goto err_free_card;
+
+       list_add_tail(&channel->list, &dev_list);
+
+       return 0;
+
+err_free_card:
+       snd_card_free(card);
+       return ret;
+}
+
+/**
+ * audio_disconnect_channel - function to disconnect a channel
+ * @iface: pointer to interface instance
+ * @channel_id: channel index
+ *
+ * This frees allocated memory and removes the sound card from ALSA
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_disconnect_channel(struct most_interface *iface,
+                                   int channel_id)
+{
+       struct channel *channel;
+
+       channel = get_channel(iface, channel_id);
+       if (!channel) {
+               pr_err("sound_disconnect_channel(), invalid channel %d\n",
+                      channel_id);
+               return -EINVAL;
+       }
+
+       list_del(&channel->list);
+       snd_card_free(channel->card);
+
+       return 0;
+}
+
+/**
+ * audio_rx_completion - completion handler for rx channels
+ * @mbo: pointer to buffer object that has completed
+ *
+ * This searches for the channel this MBO belongs to and copy the data from MBO
+ * to ring buffer
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_rx_completion(struct mbo *mbo)
+{
+       struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
+       bool period_elapsed = false;
+
+       if (!channel) {
+               pr_err("sound_rx_completion(), invalid channel %d\n",
+                      mbo->hdm_channel_id);
+               return -EINVAL;
+       }
+
+       if (channel->is_stream_running)
+               period_elapsed = copy_data(channel, mbo);
+
+       most_put_mbo(mbo);
+
+       if (period_elapsed)
+               snd_pcm_period_elapsed(channel->substream);
+
+       return 0;
+}
+
+/**
+ * audio_tx_completion - completion handler for tx channels
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ *
+ * This searches the channel that belongs to this combination of interface
+ * pointer and channel ID and wakes a process sitting in the wait queue of
+ * this channel.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_tx_completion(struct most_interface *iface, int channel_id)
+{
+       struct channel *channel = get_channel(iface, channel_id);
+
+       if (!channel) {
+               pr_err("sound_tx_completion(), invalid channel %d\n",
+                      channel_id);
+               return -EINVAL;
+       }
+
+       wake_up_interruptible(&channel->playback_waitq);
+
+       return 0;
+}
+
+/**
+ * Initialization of the struct core_component
+ */
+static struct core_component comp = {
+       .name = DRIVER_NAME,
+       .probe_channel = audio_probe_channel,
+       .disconnect_channel = audio_disconnect_channel,
+       .rx_completion = audio_rx_completion,
+       .tx_completion = audio_tx_completion,
+};
+
+static int __init audio_init(void)
+{
+       pr_info("init()\n");
+
+       INIT_LIST_HEAD(&dev_list);
+
+       return most_register_component(&comp);
+}
+
+static void __exit audio_exit(void)
+{
+       struct channel *channel, *tmp;
+
+       pr_info("exit()\n");
+
+       list_for_each_entry_safe(channel, tmp, &dev_list, list) {
+               list_del(&channel->list);
+               snd_card_free(channel->card);
+       }
+
+       most_deregister_component(&comp);
+}
+
+module_init(audio_init);
+module_exit(audio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("Sound Component Module for Mostcore");
diff --git a/drivers/staging/most/usb/Kconfig b/drivers/staging/most/usb/Kconfig
new file mode 100644 (file)
index 0000000..ebbdb57
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# MOST USB configuration
+#
+
+config MOST_USB
+       tristate "USB"
+       depends on USB && NET
+       ---help---
+         Say Y here if you want to connect via USB to network tranceiver.
+         This device driver depends on the networking AIM.
+
+         To compile this driver as a module, choose M here: the
+         module will be called most_usb.
diff --git a/drivers/staging/most/usb/Makefile b/drivers/staging/most/usb/Makefile
new file mode 100644 (file)
index 0000000..18d28cb
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_USB) += most_usb.o
+
+most_usb-objs := usb.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c
new file mode 100644 (file)
index 0000000..31f184c
--- /dev/null
@@ -0,0 +1,1192 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * usb.c - Hardware dependent module for USB
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/uaccess.h>
+#include "most/core.h"
+
+#define USB_MTU                        512
+#define NO_ISOCHRONOUS_URB     0
+#define AV_PACKETS_PER_XACT    2
+#define BUF_CHAIN_SIZE         0xFFFF
+#define MAX_NUM_ENDPOINTS      30
+#define MAX_SUFFIX_LEN         10
+#define MAX_STRING_LEN         80
+#define MAX_BUF_SIZE           0xFFFF
+
+#define USB_VENDOR_ID_SMSC     0x0424  /* VID: SMSC */
+#define USB_DEV_ID_BRDG                0xC001  /* PID: USB Bridge */
+#define USB_DEV_ID_OS81118     0xCF18  /* PID: USB OS81118 */
+#define USB_DEV_ID_OS81119     0xCF19  /* PID: USB OS81119 */
+#define USB_DEV_ID_OS81210     0xCF30  /* PID: USB OS81210 */
+/* DRCI Addresses */
+#define DRCI_REG_NI_STATE      0x0100
+#define DRCI_REG_PACKET_BW     0x0101
+#define DRCI_REG_NODE_ADDR     0x0102
+#define DRCI_REG_NODE_POS      0x0103
+#define DRCI_REG_MEP_FILTER    0x0140
+#define DRCI_REG_HASH_TBL0     0x0141
+#define DRCI_REG_HASH_TBL1     0x0142
+#define DRCI_REG_HASH_TBL2     0x0143
+#define DRCI_REG_HASH_TBL3     0x0144
+#define DRCI_REG_HW_ADDR_HI    0x0145
+#define DRCI_REG_HW_ADDR_MI    0x0146
+#define DRCI_REG_HW_ADDR_LO    0x0147
+#define DRCI_REG_BASE          0x1100
+#define DRCI_COMMAND           0x02
+#define DRCI_READ_REQ          0xA0
+#define DRCI_WRITE_REQ         0xA1
+
+/**
+ * struct most_dci_obj - Direct Communication Interface
+ * @kobj:position in sysfs
+ * @usb_device: pointer to the usb device
+ * @reg_addr: register address for arbitrary DCI access
+ */
+struct most_dci_obj {
+       struct device dev;
+       struct usb_device *usb_device;
+       u16 reg_addr;
+};
+
+#define to_dci_obj(p) container_of(p, struct most_dci_obj, dev)
+
+struct most_dev;
+
+struct clear_hold_work {
+       struct work_struct ws;
+       struct most_dev *mdev;
+       unsigned int channel;
+       int pipe;
+};
+
+#define to_clear_hold_work(w) container_of(w, struct clear_hold_work, ws)
+
+/**
+ * struct most_dev - holds all usb interface specific stuff
+ * @usb_device: pointer to usb device
+ * @iface: hardware interface
+ * @cap: channel capabilities
+ * @conf: channel configuration
+ * @dci: direct communication interface of hardware
+ * @ep_address: endpoint address table
+ * @description: device description
+ * @suffix: suffix for channel name
+ * @channel_lock: synchronize channel access
+ * @padding_active: indicates channel uses padding
+ * @is_channel_healthy: health status table of each channel
+ * @busy_urbs: list of anchored items
+ * @io_mutex: synchronize I/O with disconnect
+ * @link_stat_timer: timer for link status reports
+ * @poll_work_obj: work for polling link status
+ */
+struct most_dev {
+       struct usb_device *usb_device;
+       struct most_interface iface;
+       struct most_channel_capability *cap;
+       struct most_channel_config *conf;
+       struct most_dci_obj *dci;
+       u8 *ep_address;
+       char description[MAX_STRING_LEN];
+       char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN];
+       spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */
+       bool padding_active[MAX_NUM_ENDPOINTS];
+       bool is_channel_healthy[MAX_NUM_ENDPOINTS];
+       struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS];
+       struct usb_anchor *busy_urbs;
+       struct mutex io_mutex;
+       struct timer_list link_stat_timer;
+       struct work_struct poll_work_obj;
+       void (*on_netinfo)(struct most_interface *most_iface,
+                          unsigned char link_state, unsigned char *addrs);
+};
+
+#define to_mdev(d) container_of(d, struct most_dev, iface)
+#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj)
+
+static void wq_clear_halt(struct work_struct *wq_obj);
+static void wq_netinfo(struct work_struct *wq_obj);
+
+/**
+ * drci_rd_reg - read a DCI register
+ * @dev: usb device
+ * @reg: register address
+ * @buf: buffer to store data
+ *
+ * This is reads data from INIC's direct register communication interface
+ */
+static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf)
+{
+       int retval;
+       __le16 *dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL);
+       u8 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+
+       if (!dma_buf)
+               return -ENOMEM;
+
+       retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                                DRCI_READ_REQ, req_type,
+                                0x0000,
+                                reg, dma_buf, sizeof(*dma_buf), 5 * HZ);
+       *buf = le16_to_cpu(*dma_buf);
+       kfree(dma_buf);
+
+       return retval;
+}
+
+/**
+ * drci_wr_reg - write a DCI register
+ * @dev: usb device
+ * @reg: register address
+ * @data: data to write
+ *
+ * This is writes data to INIC's direct register communication interface
+ */
+static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data)
+{
+       return usb_control_msg(dev,
+                              usb_sndctrlpipe(dev, 0),
+                              DRCI_WRITE_REQ,
+                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              data,
+                              reg,
+                              NULL,
+                              0,
+                              5 * HZ);
+}
+
+static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep)
+{
+       return drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep * 16, 1);
+}
+
+/**
+ * get_stream_frame_size - calculate frame size of current configuration
+ * @cfg: channel configuration
+ */
+static unsigned int get_stream_frame_size(struct most_channel_config *cfg)
+{
+       unsigned int frame_size = 0;
+       unsigned int sub_size = cfg->subbuffer_size;
+
+       if (!sub_size) {
+               pr_warn("Misconfig: Subbuffer size zero.\n");
+               return frame_size;
+       }
+       switch (cfg->data_type) {
+       case MOST_CH_ISOC:
+               frame_size = AV_PACKETS_PER_XACT * sub_size;
+               break;
+       case MOST_CH_SYNC:
+               if (cfg->packets_per_xact == 0) {
+                       pr_warn("Misconfig: Packets per XACT zero\n");
+                       frame_size = 0;
+               } else if (cfg->packets_per_xact == 0xFF) {
+                       frame_size = (USB_MTU / sub_size) * sub_size;
+               } else {
+                       frame_size = cfg->packets_per_xact * sub_size;
+               }
+               break;
+       default:
+               pr_warn("Query frame size of non-streaming channel\n");
+               break;
+       }
+       return frame_size;
+}
+
+/**
+ * hdm_poison_channel - mark buffers of this channel as invalid
+ * @iface: pointer to the interface
+ * @channel: channel ID
+ *
+ * This unlinks all URBs submitted to the HCD,
+ * calls the associated completion function of the core and removes
+ * them from the list.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int hdm_poison_channel(struct most_interface *iface, int channel)
+{
+       struct most_dev *mdev = to_mdev(iface);
+       unsigned long flags;
+       spinlock_t *lock; /* temp. lock */
+
+       if (unlikely(!iface)) {
+               dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n");
+               return -EIO;
+       }
+       if (unlikely(channel < 0 || channel >= iface->num_channels)) {
+               dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n");
+               return -ECHRNG;
+       }
+
+       lock = mdev->channel_lock + channel;
+       spin_lock_irqsave(lock, flags);
+       mdev->is_channel_healthy[channel] = false;
+       spin_unlock_irqrestore(lock, flags);
+
+       cancel_work_sync(&mdev->clear_work[channel].ws);
+
+       mutex_lock(&mdev->io_mutex);
+       usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
+       if (mdev->padding_active[channel])
+               mdev->padding_active[channel] = false;
+
+       if (mdev->conf[channel].data_type == MOST_CH_ASYNC) {
+               del_timer_sync(&mdev->link_stat_timer);
+               cancel_work_sync(&mdev->poll_work_obj);
+       }
+       mutex_unlock(&mdev->io_mutex);
+       return 0;
+}
+
+/**
+ * hdm_add_padding - add padding bytes
+ * @mdev: most device
+ * @channel: channel ID
+ * @mbo: buffer object
+ *
+ * This inserts the INIC hardware specific padding bytes into a streaming
+ * channel's buffer
+ */
+static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
+{
+       struct most_channel_config *conf = &mdev->conf[channel];
+       unsigned int frame_size = get_stream_frame_size(conf);
+       unsigned int j, num_frames;
+
+       if (!frame_size)
+               return -EIO;
+       num_frames = mbo->buffer_length / frame_size;
+
+       if (num_frames < 1) {
+               dev_err(&mdev->usb_device->dev,
+                       "Missed minimal transfer unit.\n");
+               return -EIO;
+       }
+
+       for (j = num_frames - 1; j > 0; j--)
+               memmove(mbo->virt_address + j * USB_MTU,
+                       mbo->virt_address + j * frame_size,
+                       frame_size);
+       mbo->buffer_length = num_frames * USB_MTU;
+       return 0;
+}
+
+/**
+ * hdm_remove_padding - remove padding bytes
+ * @mdev: most device
+ * @channel: channel ID
+ * @mbo: buffer object
+ *
+ * This takes the INIC hardware specific padding bytes off a streaming
+ * channel's buffer.
+ */
+static int hdm_remove_padding(struct most_dev *mdev, int channel,
+                             struct mbo *mbo)
+{
+       struct most_channel_config *const conf = &mdev->conf[channel];
+       unsigned int frame_size = get_stream_frame_size(conf);
+       unsigned int j, num_frames;
+
+       if (!frame_size)
+               return -EIO;
+       num_frames = mbo->processed_length / USB_MTU;
+
+       for (j = 1; j < num_frames; j++)
+               memmove(mbo->virt_address + frame_size * j,
+                       mbo->virt_address + USB_MTU * j,
+                       frame_size);
+
+       mbo->processed_length = frame_size * num_frames;
+       return 0;
+}
+
+/**
+ * hdm_write_completion - completion function for submitted Tx URBs
+ * @urb: the URB that has been completed
+ *
+ * This checks the status of the completed URB. In case the URB has been
+ * unlinked before, it is immediately freed. On any other error the MBO
+ * transfer flag is set. On success it frees allocated resources and calls
+ * the completion function.
+ *
+ * Context: interrupt!
+ */
+static void hdm_write_completion(struct urb *urb)
+{
+       struct mbo *mbo = urb->context;
+       struct most_dev *mdev = to_mdev(mbo->ifp);
+       unsigned int channel = mbo->hdm_channel_id;
+       struct device *dev = &mdev->usb_device->dev;
+       spinlock_t *lock = mdev->channel_lock + channel;
+       unsigned long flags;
+
+       spin_lock_irqsave(lock, flags);
+
+       mbo->processed_length = 0;
+       mbo->status = MBO_E_INVAL;
+       if (likely(mdev->is_channel_healthy[channel])) {
+               switch (urb->status) {
+               case 0:
+               case -ESHUTDOWN:
+                       mbo->processed_length = urb->actual_length;
+                       mbo->status = MBO_SUCCESS;
+                       break;
+               case -EPIPE:
+                       dev_warn(dev, "Broken OUT pipe detected\n");
+                       mdev->is_channel_healthy[channel] = false;
+                       mdev->clear_work[channel].pipe = urb->pipe;
+                       schedule_work(&mdev->clear_work[channel].ws);
+                       break;
+               case -ENODEV:
+               case -EPROTO:
+                       mbo->status = MBO_E_CLOSE;
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(lock, flags);
+
+       if (likely(mbo->complete))
+               mbo->complete(mbo);
+       usb_free_urb(urb);
+}
+
+/**
+ * hdm_read_completion - completion function for submitted Rx URBs
+ * @urb: the URB that has been completed
+ *
+ * This checks the status of the completed URB. In case the URB has been
+ * unlinked before it is immediately freed. On any other error the MBO transfer
+ * flag is set. On success it frees allocated resources, removes
+ * padding bytes -if necessary- and calls the completion function.
+ *
+ * Context: interrupt!
+ *
+ * **************************************************************************
+ *                   Error codes returned by in urb->status
+ *                   or in iso_frame_desc[n].status (for ISO)
+ * *************************************************************************
+ *
+ * USB device drivers may only test urb status values in completion handlers.
+ * This is because otherwise there would be a race between HCDs updating
+ * these values on one CPU, and device drivers testing them on another CPU.
+ *
+ * A transfer's actual_length may be positive even when an error has been
+ * reported.  That's because transfers often involve several packets, so that
+ * one or more packets could finish before an error stops further endpoint I/O.
+ *
+ * For isochronous URBs, the urb status value is non-zero only if the URB is
+ * unlinked, the device is removed, the host controller is disabled or the total
+ * transferred length is less than the requested length and the URB_SHORT_NOT_OK
+ * flag is set.  Completion handlers for isochronous URBs should only see
+ * urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO.
+ * Individual frame descriptor status fields may report more status codes.
+ *
+ *
+ * 0                   Transfer completed successfully
+ *
+ * -ENOENT             URB was synchronously unlinked by usb_unlink_urb
+ *
+ * -EINPROGRESS                URB still pending, no results yet
+ *                     (That is, if drivers see this it's a bug.)
+ *
+ * -EPROTO (*, **)     a) bitstuff error
+ *                     b) no response packet received within the
+ *                        prescribed bus turn-around time
+ *                     c) unknown USB error
+ *
+ * -EILSEQ (*, **)     a) CRC mismatch
+ *                     b) no response packet received within the
+ *                        prescribed bus turn-around time
+ *                     c) unknown USB error
+ *
+ *                     Note that often the controller hardware does not
+ *                     distinguish among cases a), b), and c), so a
+ *                     driver cannot tell whether there was a protocol
+ *                     error, a failure to respond (often caused by
+ *                     device disconnect), or some other fault.
+ *
+ * -ETIME (**)         No response packet received within the prescribed
+ *                     bus turn-around time.  This error may instead be
+ *                     reported as -EPROTO or -EILSEQ.
+ *
+ * -ETIMEDOUT          Synchronous USB message functions use this code
+ *                     to indicate timeout expired before the transfer
+ *                     completed, and no other error was reported by HC.
+ *
+ * -EPIPE (**)         Endpoint stalled.  For non-control endpoints,
+ *                     reset this status with usb_clear_halt().
+ *
+ * -ECOMM              During an IN transfer, the host controller
+ *                     received data from an endpoint faster than it
+ *                     could be written to system memory
+ *
+ * -ENOSR              During an OUT transfer, the host controller
+ *                     could not retrieve data from system memory fast
+ *                     enough to keep up with the USB data rate
+ *
+ * -EOVERFLOW (*)      The amount of data returned by the endpoint was
+ *                     greater than either the max packet size of the
+ *                     endpoint or the remaining buffer size.  "Babble".
+ *
+ * -EREMOTEIO          The data read from the endpoint did not fill the
+ *                     specified buffer, and URB_SHORT_NOT_OK was set in
+ *                     urb->transfer_flags.
+ *
+ * -ENODEV             Device was removed.  Often preceded by a burst of
+ *                     other errors, since the hub driver doesn't detect
+ *                     device removal events immediately.
+ *
+ * -EXDEV              ISO transfer only partially completed
+ *                     (only set in iso_frame_desc[n].status, not urb->status)
+ *
+ * -EINVAL             ISO madness, if this happens: Log off and go home
+ *
+ * -ECONNRESET         URB was asynchronously unlinked by usb_unlink_urb
+ *
+ * -ESHUTDOWN          The device or host controller has been disabled due
+ *                     to some problem that could not be worked around,
+ *                     such as a physical disconnect.
+ *
+ *
+ * (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate
+ * hardware problems such as bad devices (including firmware) or cables.
+ *
+ * (**) This is also one of several codes that different kinds of host
+ * controller use to indicate a transfer has failed because of device
+ * disconnect.  In the interval before the hub driver starts disconnect
+ * processing, devices may receive such fault reports for every request.
+ *
+ * See <https://www.kernel.org/doc/Documentation/driver-api/usb/error-codes.rst>
+ */
+static void hdm_read_completion(struct urb *urb)
+{
+       struct mbo *mbo = urb->context;
+       struct most_dev *mdev = to_mdev(mbo->ifp);
+       unsigned int channel = mbo->hdm_channel_id;
+       struct device *dev = &mdev->usb_device->dev;
+       spinlock_t *lock = mdev->channel_lock + channel;
+       unsigned long flags;
+
+       spin_lock_irqsave(lock, flags);
+
+       mbo->processed_length = 0;
+       mbo->status = MBO_E_INVAL;
+       if (likely(mdev->is_channel_healthy[channel])) {
+               switch (urb->status) {
+               case 0:
+               case -ESHUTDOWN:
+                       mbo->processed_length = urb->actual_length;
+                       mbo->status = MBO_SUCCESS;
+                       if (mdev->padding_active[channel] &&
+                           hdm_remove_padding(mdev, channel, mbo)) {
+                               mbo->processed_length = 0;
+                               mbo->status = MBO_E_INVAL;
+                       }
+                       break;
+               case -EPIPE:
+                       dev_warn(dev, "Broken IN pipe detected\n");
+                       mdev->is_channel_healthy[channel] = false;
+                       mdev->clear_work[channel].pipe = urb->pipe;
+                       schedule_work(&mdev->clear_work[channel].ws);
+                       break;
+               case -ENODEV:
+               case -EPROTO:
+                       mbo->status = MBO_E_CLOSE;
+                       break;
+               case -EOVERFLOW:
+                       dev_warn(dev, "Babble on IN pipe detected\n");
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(lock, flags);
+
+       if (likely(mbo->complete))
+               mbo->complete(mbo);
+       usb_free_urb(urb);
+}
+
+/**
+ * hdm_enqueue - receive a buffer to be used for data transfer
+ * @iface: interface to enqueue to
+ * @channel: ID of the channel
+ * @mbo: pointer to the buffer object
+ *
+ * This allocates a new URB and fills it according to the channel
+ * that is being used for transmission of data. Before the URB is
+ * submitted it is stored in the private anchor list.
+ *
+ * Returns 0 on success. On any error the URB is freed and a error code
+ * is returned.
+ *
+ * Context: Could in _some_ cases be interrupt!
+ */
+static int hdm_enqueue(struct most_interface *iface, int channel,
+                      struct mbo *mbo)
+{
+       struct most_dev *mdev;
+       struct most_channel_config *conf;
+       struct device *dev;
+       int retval = 0;
+       struct urb *urb;
+       unsigned long length;
+       void *virt_address;
+
+       if (unlikely(!iface || !mbo))
+               return -EIO;
+       if (unlikely(iface->num_channels <= channel || channel < 0))
+               return -ECHRNG;
+
+       mdev = to_mdev(iface);
+       conf = &mdev->conf[channel];
+       dev = &mdev->usb_device->dev;
+
+       if (!mdev->usb_device)
+               return -ENODEV;
+
+       urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC);
+       if (!urb)
+               return -ENOMEM;
+
+       if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] &&
+           hdm_add_padding(mdev, channel, mbo)) {
+               retval = -EIO;
+               goto _error;
+       }
+
+       urb->transfer_dma = mbo->bus_address;
+       virt_address = mbo->virt_address;
+       length = mbo->buffer_length;
+
+       if (conf->direction & MOST_CH_TX) {
+               usb_fill_bulk_urb(urb, mdev->usb_device,
+                                 usb_sndbulkpipe(mdev->usb_device,
+                                                 mdev->ep_address[channel]),
+                                 virt_address,
+                                 length,
+                                 hdm_write_completion,
+                                 mbo);
+               if (conf->data_type != MOST_CH_ISOC)
+                       urb->transfer_flags |= URB_ZERO_PACKET;
+       } else {
+               usb_fill_bulk_urb(urb, mdev->usb_device,
+                                 usb_rcvbulkpipe(mdev->usb_device,
+                                                 mdev->ep_address[channel]),
+                                 virt_address,
+                                 length + conf->extra_len,
+                                 hdm_read_completion,
+                                 mbo);
+       }
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       usb_anchor_urb(urb, &mdev->busy_urbs[channel]);
+
+       retval = usb_submit_urb(urb, GFP_KERNEL);
+       if (retval) {
+               dev_err(dev, "URB submit failed with error %d.\n", retval);
+               goto _error_1;
+       }
+       return 0;
+
+_error_1:
+       usb_unanchor_urb(urb);
+_error:
+       usb_free_urb(urb);
+       return retval;
+}
+
+/**
+ * hdm_configure_channel - receive channel configuration from core
+ * @iface: interface
+ * @channel: channel ID
+ * @conf: structure that holds the configuration information
+ *
+ * The attached network interface controller (NIC) supports a padding mode
+ * to avoid short packets on USB, hence increasing the performance due to a
+ * lower interrupt load. This mode is default for synchronous data and can
+ * be switched on for isochronous data. In case padding is active the
+ * driver needs to know the frame size of the payload in order to calculate
+ * the number of bytes it needs to pad when transmitting or to cut off when
+ * receiving data.
+ *
+ */
+static int hdm_configure_channel(struct most_interface *iface, int channel,
+                                struct most_channel_config *conf)
+{
+       unsigned int num_frames;
+       unsigned int frame_size;
+       struct most_dev *mdev = to_mdev(iface);
+       struct device *dev = &mdev->usb_device->dev;
+
+       mdev->is_channel_healthy[channel] = true;
+       mdev->clear_work[channel].channel = channel;
+       mdev->clear_work[channel].mdev = mdev;
+       INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt);
+
+       if (unlikely(!iface || !conf)) {
+               dev_err(dev, "Bad interface or config pointer.\n");
+               return -EINVAL;
+       }
+       if (unlikely(channel < 0 || channel >= iface->num_channels)) {
+               dev_err(dev, "Channel ID out of range.\n");
+               return -EINVAL;
+       }
+       if (!conf->num_buffers || !conf->buffer_size) {
+               dev_err(dev, "Misconfig: buffer size or #buffers zero.\n");
+               return -EINVAL;
+       }
+
+       if (conf->data_type != MOST_CH_SYNC &&
+           !(conf->data_type == MOST_CH_ISOC &&
+             conf->packets_per_xact != 0xFF)) {
+               mdev->padding_active[channel] = false;
+               /*
+                * Since the NIC's padding mode is not going to be
+                * used, we can skip the frame size calculations and
+                * move directly on to exit.
+                */
+               goto exit;
+       }
+
+       mdev->padding_active[channel] = true;
+
+       frame_size = get_stream_frame_size(conf);
+       if (frame_size == 0 || frame_size > USB_MTU) {
+               dev_warn(dev, "Misconfig: frame size wrong\n");
+               return -EINVAL;
+       }
+
+       num_frames = conf->buffer_size / frame_size;
+
+       if (conf->buffer_size % frame_size) {
+               u16 old_size = conf->buffer_size;
+
+               conf->buffer_size = num_frames * frame_size;
+               dev_warn(dev, "%s: fixed buffer size (%d -> %d)\n",
+                        mdev->suffix[channel], old_size, conf->buffer_size);
+       }
+
+       /* calculate extra length to comply w/ HW padding */
+       conf->extra_len = num_frames * (USB_MTU - frame_size);
+
+exit:
+       mdev->conf[channel] = *conf;
+       if (conf->data_type == MOST_CH_ASYNC) {
+               u16 ep = mdev->ep_address[channel];
+
+               if (start_sync_ep(mdev->usb_device, ep) < 0)
+                       dev_warn(dev, "sync for ep%02x failed", ep);
+       }
+       return 0;
+}
+
+/**
+ * hdm_request_netinfo - request network information
+ * @iface: pointer to interface
+ * @channel: channel ID
+ *
+ * This is used as trigger to set up the link status timer that
+ * polls for the NI state of the INIC every 2 seconds.
+ *
+ */
+static void hdm_request_netinfo(struct most_interface *iface, int channel,
+                               void (*on_netinfo)(struct most_interface *,
+                                                  unsigned char,
+                                                  unsigned char *))
+{
+       struct most_dev *mdev;
+
+       BUG_ON(!iface);
+       mdev = to_mdev(iface);
+       mdev->on_netinfo = on_netinfo;
+       if (!on_netinfo)
+               return;
+
+       mdev->link_stat_timer.expires = jiffies + HZ;
+       mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires);
+}
+
+/**
+ * link_stat_timer_handler - schedule work obtaining mac address and link status
+ * @data: pointer to USB device instance
+ *
+ * The handler runs in interrupt context. That's why we need to defer the
+ * tasks to a work queue.
+ */
+static void link_stat_timer_handler(struct timer_list *t)
+{
+       struct most_dev *mdev = from_timer(mdev, t, link_stat_timer);
+
+       schedule_work(&mdev->poll_work_obj);
+       mdev->link_stat_timer.expires = jiffies + (2 * HZ);
+       add_timer(&mdev->link_stat_timer);
+}
+
+/**
+ * wq_netinfo - work queue function to deliver latest networking information
+ * @wq_obj: object that holds data for our deferred work to do
+ *
+ * This retrieves the network interface status of the USB INIC
+ */
+static void wq_netinfo(struct work_struct *wq_obj)
+{
+       struct most_dev *mdev = to_mdev_from_work(wq_obj);
+       struct usb_device *usb_device = mdev->usb_device;
+       struct device *dev = &usb_device->dev;
+       u16 hi, mi, lo, link;
+       u8 hw_addr[6];
+
+       if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) {
+               dev_err(dev, "Vendor request 'hw_addr_hi' failed\n");
+               return;
+       }
+
+       if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) {
+               dev_err(dev, "Vendor request 'hw_addr_mid' failed\n");
+               return;
+       }
+
+       if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) {
+               dev_err(dev, "Vendor request 'hw_addr_low' failed\n");
+               return;
+       }
+
+       if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) {
+               dev_err(dev, "Vendor request 'link status' failed\n");
+               return;
+       }
+
+       hw_addr[0] = hi >> 8;
+       hw_addr[1] = hi;
+       hw_addr[2] = mi >> 8;
+       hw_addr[3] = mi;
+       hw_addr[4] = lo >> 8;
+       hw_addr[5] = lo;
+
+       if (mdev->on_netinfo)
+               mdev->on_netinfo(&mdev->iface, link, hw_addr);
+}
+
+/**
+ * wq_clear_halt - work queue function
+ * @wq_obj: work_struct object to execute
+ *
+ * This sends a clear_halt to the given USB pipe.
+ */
+static void wq_clear_halt(struct work_struct *wq_obj)
+{
+       struct clear_hold_work *clear_work = to_clear_hold_work(wq_obj);
+       struct most_dev *mdev = clear_work->mdev;
+       unsigned int channel = clear_work->channel;
+       int pipe = clear_work->pipe;
+
+       mutex_lock(&mdev->io_mutex);
+       most_stop_enqueue(&mdev->iface, channel);
+       usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
+       if (usb_clear_halt(mdev->usb_device, pipe))
+               dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n");
+
+       /* If the functional Stall condition has been set on an
+        * asynchronous rx channel, we need to clear the tx channel
+        * too, since the hardware runs its clean-up sequence on both
+        * channels, as they are physically one on the network.
+        *
+        * The USB interface that exposes the asynchronous channels
+        * contains always two endpoints, and two only.
+        */
+       if (mdev->conf[channel].data_type == MOST_CH_ASYNC &&
+           mdev->conf[channel].direction == MOST_CH_RX) {
+               int peer = 1 - channel;
+               int snd_pipe = usb_sndbulkpipe(mdev->usb_device,
+                                              mdev->ep_address[peer]);
+               usb_clear_halt(mdev->usb_device, snd_pipe);
+       }
+       mdev->is_channel_healthy[channel] = true;
+       most_resume_enqueue(&mdev->iface, channel);
+       mutex_unlock(&mdev->io_mutex);
+}
+
+/**
+ * hdm_usb_fops - file operation table for USB driver
+ */
+static const struct file_operations hdm_usb_fops = {
+       .owner = THIS_MODULE,
+};
+
+/**
+ * usb_device_id - ID table for HCD device probing
+ */
+static const struct usb_device_id usbid[] = {
+       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), },
+       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), },
+       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), },
+       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81210), },
+       { } /* Terminating entry */
+};
+
+struct regs {
+       const char *name;
+       u16 reg;
+};
+
+static const struct regs ro_regs[] = {
+       { "ni_state", DRCI_REG_NI_STATE },
+       { "packet_bandwidth", DRCI_REG_PACKET_BW },
+       { "node_address", DRCI_REG_NODE_ADDR },
+       { "node_position", DRCI_REG_NODE_POS },
+};
+
+static const struct regs rw_regs[] = {
+       { "mep_filter", DRCI_REG_MEP_FILTER },
+       { "mep_hash0", DRCI_REG_HASH_TBL0 },
+       { "mep_hash1", DRCI_REG_HASH_TBL1 },
+       { "mep_hash2", DRCI_REG_HASH_TBL2 },
+       { "mep_hash3", DRCI_REG_HASH_TBL3 },
+       { "mep_eui48_hi", DRCI_REG_HW_ADDR_HI },
+       { "mep_eui48_mi", DRCI_REG_HW_ADDR_MI },
+       { "mep_eui48_lo", DRCI_REG_HW_ADDR_LO },
+};
+
+static int get_stat_reg_addr(const struct regs *regs, int size,
+                            const char *name, u16 *reg_addr)
+{
+       int i;
+
+       for (i = 0; i < size; i++) {
+               if (!strcmp(name, regs[i].name)) {
+                       *reg_addr = regs[i].reg;
+                       return 0;
+               }
+       }
+       return -EFAULT;
+}
+
+#define get_static_reg_addr(regs, name, reg_addr) \
+       get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr)
+
+static ssize_t value_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       const char *name = attr->attr.name;
+       struct most_dci_obj *dci_obj = to_dci_obj(dev);
+       u16 val;
+       u16 reg_addr;
+       int err;
+
+       if (!strcmp(name, "arb_address"))
+               return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr);
+
+       if (!strcmp(name, "arb_value"))
+               reg_addr = dci_obj->reg_addr;
+       else if (get_static_reg_addr(ro_regs, name, &reg_addr) &&
+                get_static_reg_addr(rw_regs, name, &reg_addr))
+               return -EFAULT;
+
+       err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val);
+       if (err < 0)
+               return err;
+
+       return snprintf(buf, PAGE_SIZE, "%04x\n", val);
+}
+
+static ssize_t value_store(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       u16 val;
+       u16 reg_addr;
+       const char *name = attr->attr.name;
+       struct most_dci_obj *dci_obj = to_dci_obj(dev);
+       struct usb_device *usb_dev = dci_obj->usb_device;
+       int err = kstrtou16(buf, 16, &val);
+
+       if (err)
+               return err;
+
+       if (!strcmp(name, "arb_address")) {
+               dci_obj->reg_addr = val;
+               return count;
+       }
+
+       if (!strcmp(name, "arb_value"))
+               err = drci_wr_reg(usb_dev, dci_obj->reg_addr, val);
+       else if (!strcmp(name, "sync_ep"))
+               err = start_sync_ep(usb_dev, val);
+       else if (!get_static_reg_addr(rw_regs, name, &reg_addr))
+               err = drci_wr_reg(usb_dev, reg_addr, val);
+       else
+               return -EFAULT;
+
+       if (err < 0)
+               return err;
+
+       return count;
+}
+
+static DEVICE_ATTR(ni_state, 0444, value_show, NULL);
+static DEVICE_ATTR(packet_bandwidth, 0444, value_show, NULL);
+static DEVICE_ATTR(node_address, 0444, value_show, NULL);
+static DEVICE_ATTR(node_position, 0444, value_show, NULL);
+static DEVICE_ATTR(sync_ep, 0200, NULL, value_store);
+static DEVICE_ATTR(mep_filter, 0644, value_show, value_store);
+static DEVICE_ATTR(mep_hash0, 0644, value_show, value_store);
+static DEVICE_ATTR(mep_hash1, 0644, value_show, value_store);
+static DEVICE_ATTR(mep_hash2, 0644, value_show, value_store);
+static DEVICE_ATTR(mep_hash3, 0644, value_show, value_store);
+static DEVICE_ATTR(mep_eui48_hi, 0644, value_show, value_store);
+static DEVICE_ATTR(mep_eui48_mi, 0644, value_show, value_store);
+static DEVICE_ATTR(mep_eui48_lo, 0644, value_show, value_store);
+static DEVICE_ATTR(arb_address, 0644, value_show, value_store);
+static DEVICE_ATTR(arb_value, 0644, value_show, value_store);
+
+static struct attribute *dci_attrs[] = {
+       &dev_attr_ni_state.attr,
+       &dev_attr_packet_bandwidth.attr,
+       &dev_attr_node_address.attr,
+       &dev_attr_node_position.attr,
+       &dev_attr_sync_ep.attr,
+       &dev_attr_mep_filter.attr,
+       &dev_attr_mep_hash0.attr,
+       &dev_attr_mep_hash1.attr,
+       &dev_attr_mep_hash2.attr,
+       &dev_attr_mep_hash3.attr,
+       &dev_attr_mep_eui48_hi.attr,
+       &dev_attr_mep_eui48_mi.attr,
+       &dev_attr_mep_eui48_lo.attr,
+       &dev_attr_arb_address.attr,
+       &dev_attr_arb_value.attr,
+       NULL,
+};
+
+static struct attribute_group dci_attr_group = {
+       .attrs = dci_attrs,
+};
+
+static const struct attribute_group *dci_attr_groups[] = {
+       &dci_attr_group,
+       NULL,
+};
+
+/**
+ * hdm_probe - probe function of USB device driver
+ * @interface: Interface of the attached USB device
+ * @id: Pointer to the USB ID table.
+ *
+ * This allocates and initializes the device instance, adds the new
+ * entry to the internal list, scans the USB descriptors and registers
+ * the interface with the core.
+ * Additionally, the DCI objects are created and the hardware is sync'd.
+ *
+ * Return 0 on success. In case of an error a negative number is returned.
+ */
+static int
+hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+       struct usb_host_interface *usb_iface_desc = interface->cur_altsetting;
+       struct usb_device *usb_dev = interface_to_usbdev(interface);
+       struct device *dev = &usb_dev->dev;
+       struct most_dev *mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       unsigned int i;
+       unsigned int num_endpoints;
+       struct most_channel_capability *tmp_cap;
+       struct usb_endpoint_descriptor *ep_desc;
+       int ret = 0;
+
+       if (!mdev)
+               goto exit_ENOMEM;
+
+       usb_set_intfdata(interface, mdev);
+       num_endpoints = usb_iface_desc->desc.bNumEndpoints;
+       mutex_init(&mdev->io_mutex);
+       INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
+       timer_setup(&mdev->link_stat_timer, link_stat_timer_handler, 0);
+
+       mdev->usb_device = usb_dev;
+       mdev->link_stat_timer.expires = jiffies + (2 * HZ);
+
+       mdev->iface.mod = hdm_usb_fops.owner;
+       mdev->iface.interface = ITYPE_USB;
+       mdev->iface.configure = hdm_configure_channel;
+       mdev->iface.request_netinfo = hdm_request_netinfo;
+       mdev->iface.enqueue = hdm_enqueue;
+       mdev->iface.poison_channel = hdm_poison_channel;
+       mdev->iface.description = mdev->description;
+       mdev->iface.num_channels = num_endpoints;
+
+       snprintf(mdev->description, sizeof(mdev->description),
+                "usb_device %d-%s:%d.%d",
+                usb_dev->bus->busnum,
+                usb_dev->devpath,
+                usb_dev->config->desc.bConfigurationValue,
+                usb_iface_desc->desc.bInterfaceNumber);
+
+       mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL);
+       if (!mdev->conf)
+               goto exit_free;
+
+       mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL);
+       if (!mdev->cap)
+               goto exit_free1;
+
+       mdev->iface.channel_vector = mdev->cap;
+       mdev->ep_address =
+               kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
+       if (!mdev->ep_address)
+               goto exit_free2;
+
+       mdev->busy_urbs =
+               kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL);
+       if (!mdev->busy_urbs)
+               goto exit_free3;
+
+       tmp_cap = mdev->cap;
+       for (i = 0; i < num_endpoints; i++) {
+               ep_desc = &usb_iface_desc->endpoint[i].desc;
+               mdev->ep_address[i] = ep_desc->bEndpointAddress;
+               mdev->padding_active[i] = false;
+               mdev->is_channel_healthy[i] = true;
+
+               snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x",
+                        mdev->ep_address[i]);
+
+               tmp_cap->name_suffix = &mdev->suffix[i][0];
+               tmp_cap->buffer_size_packet = MAX_BUF_SIZE;
+               tmp_cap->buffer_size_streaming = MAX_BUF_SIZE;
+               tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE;
+               tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE;
+               tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
+                                    MOST_CH_ISOC | MOST_CH_SYNC;
+               if (usb_endpoint_dir_in(ep_desc))
+                       tmp_cap->direction = MOST_CH_RX;
+               else
+                       tmp_cap->direction = MOST_CH_TX;
+               tmp_cap++;
+               init_usb_anchor(&mdev->busy_urbs[i]);
+               spin_lock_init(&mdev->channel_lock[i]);
+       }
+       dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n",
+                  le16_to_cpu(usb_dev->descriptor.idVendor),
+                  le16_to_cpu(usb_dev->descriptor.idProduct),
+                  usb_dev->bus->busnum,
+                  usb_dev->devnum);
+
+       dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n",
+                  usb_dev->bus->busnum,
+                  usb_dev->devpath,
+                  usb_dev->config->desc.bConfigurationValue,
+                  usb_iface_desc->desc.bInterfaceNumber);
+
+       ret = most_register_interface(&mdev->iface);
+       if (ret)
+               goto exit_free4;
+
+       mutex_lock(&mdev->io_mutex);
+       if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 ||
+           le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 ||
+           le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) {
+               mdev->dci = kzalloc(sizeof(*mdev->dci), GFP_KERNEL);
+               if (!mdev->dci) {
+                       mutex_unlock(&mdev->io_mutex);
+                       most_deregister_interface(&mdev->iface);
+                       ret = -ENOMEM;
+                       goto exit_free4;
+               }
+
+               mdev->dci->dev.init_name = "dci";
+               mdev->dci->dev.parent = &mdev->iface.dev;
+               mdev->dci->dev.groups = dci_attr_groups;
+               if (device_register(&mdev->dci->dev)) {
+                       mutex_unlock(&mdev->io_mutex);
+                       most_deregister_interface(&mdev->iface);
+                       ret = -ENOMEM;
+                       goto exit_free5;
+               }
+               mdev->dci->usb_device = mdev->usb_device;
+       }
+       mutex_unlock(&mdev->io_mutex);
+       return 0;
+exit_free5:
+       kfree(mdev->dci);
+exit_free4:
+       kfree(mdev->busy_urbs);
+exit_free3:
+       kfree(mdev->ep_address);
+exit_free2:
+       kfree(mdev->cap);
+exit_free1:
+       kfree(mdev->conf);
+exit_free:
+       kfree(mdev);
+exit_ENOMEM:
+       if (ret == 0 || ret == -ENOMEM) {
+               ret = -ENOMEM;
+               dev_err(dev, "out of memory\n");
+       }
+       return ret;
+}
+
+/**
+ * hdm_disconnect - disconnect function of USB device driver
+ * @interface: Interface of the attached USB device
+ *
+ * This deregisters the interface with the core, removes the kernel timer
+ * and frees resources.
+ *
+ * Context: hub kernel thread
+ */
+static void hdm_disconnect(struct usb_interface *interface)
+{
+       struct most_dev *mdev = usb_get_intfdata(interface);
+
+       mutex_lock(&mdev->io_mutex);
+       usb_set_intfdata(interface, NULL);
+       mdev->usb_device = NULL;
+       mutex_unlock(&mdev->io_mutex);
+
+       del_timer_sync(&mdev->link_stat_timer);
+       cancel_work_sync(&mdev->poll_work_obj);
+
+       device_unregister(&mdev->dci->dev);
+       kfree(mdev->dci);
+       most_deregister_interface(&mdev->iface);
+
+       kfree(mdev->busy_urbs);
+       kfree(mdev->cap);
+       kfree(mdev->conf);
+       kfree(mdev->ep_address);
+       kfree(mdev);
+}
+
+static struct usb_driver hdm_usb = {
+       .name = "hdm_usb",
+       .id_table = usbid,
+       .probe = hdm_probe,
+       .disconnect = hdm_disconnect,
+};
+
+module_usb_driver(hdm_usb);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("HDM_4_USB");
diff --git a/drivers/staging/most/video/Kconfig b/drivers/staging/most/video/Kconfig
new file mode 100644 (file)
index 0000000..ce6af4f
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# MOST V4L2 configuration
+#
+
+config MOST_VIDEO
+       tristate "Video"
+       depends on VIDEO_V4L2
+       ---help---
+         Say Y here if you want to commumicate via Video 4 Linux.
+
+         To compile this driver as a module, choose M here: the
+         module will be called most_video.
diff --git a/drivers/staging/most/video/Makefile b/drivers/staging/most/video/Makefile
new file mode 100644 (file)
index 0000000..1c8e520
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_VIDEO) += most_video.o
+
+most_video-objs := video.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c
new file mode 100644 (file)
index 0000000..ef23e85
--- /dev/null
@@ -0,0 +1,609 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * video.c - V4L2 component for Mostcore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+
+#include "most/core.h"
+
+#define V4L2_CMP_MAX_INPUT  1
+
+static struct core_component comp;
+
+struct most_video_dev {
+       struct most_interface *iface;
+       int ch_idx;
+       struct list_head list;
+       bool mute;
+
+       struct list_head pending_mbos;
+       spinlock_t list_lock;
+
+       struct v4l2_device v4l2_dev;
+       atomic_t access_ref;
+       struct video_device *vdev;
+       unsigned int ctrl_input;
+
+       struct mutex lock;
+
+       wait_queue_head_t wait_data;
+};
+
+struct comp_fh {
+       /* must be the first field of this struct! */
+       struct v4l2_fh fh;
+       struct most_video_dev *mdev;
+       u32 offs;
+};
+
+static struct list_head video_devices = LIST_HEAD_INIT(video_devices);
+static struct spinlock list_lock;
+
+static inline bool data_ready(struct most_video_dev *mdev)
+{
+       return !list_empty(&mdev->pending_mbos);
+}
+
+static inline struct mbo *get_top_mbo(struct most_video_dev *mdev)
+{
+       return list_first_entry(&mdev->pending_mbos, struct mbo, list);
+}
+
+static int comp_vdev_open(struct file *filp)
+{
+       int ret;
+       struct video_device *vdev = video_devdata(filp);
+       struct most_video_dev *mdev = video_drvdata(filp);
+       struct comp_fh *fh;
+
+       v4l2_info(&mdev->v4l2_dev, "comp_vdev_open()\n");
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (!fh)
+               return -ENOMEM;
+
+       if (!atomic_inc_and_test(&mdev->access_ref)) {
+               v4l2_err(&mdev->v4l2_dev, "too many clients\n");
+               ret = -EBUSY;
+               goto err_dec;
+       }
+
+       fh->mdev = mdev;
+       v4l2_fh_init(&fh->fh, vdev);
+       filp->private_data = fh;
+
+       v4l2_fh_add(&fh->fh);
+
+       ret = most_start_channel(mdev->iface, mdev->ch_idx, &comp);
+       if (ret) {
+               v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n");
+               goto err_rm;
+       }
+
+       return 0;
+
+err_rm:
+       v4l2_fh_del(&fh->fh);
+       v4l2_fh_exit(&fh->fh);
+
+err_dec:
+       atomic_dec(&mdev->access_ref);
+       kfree(fh);
+       return ret;
+}
+
+static int comp_vdev_close(struct file *filp)
+{
+       struct comp_fh *fh = filp->private_data;
+       struct most_video_dev *mdev = fh->mdev;
+       struct mbo *mbo, *tmp;
+
+       v4l2_info(&mdev->v4l2_dev, "comp_vdev_close()\n");
+
+       /*
+        * We need to put MBOs back before we call most_stop_channel()
+        * to deallocate MBOs.
+        * From the other hand mostcore still calling rx_completion()
+        * to deliver MBOs until most_stop_channel() is called.
+        * Use mute to work around this issue.
+        * This must be implemented in core.
+        */
+
+       spin_lock_irq(&mdev->list_lock);
+       mdev->mute = true;
+       list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) {
+               list_del(&mbo->list);
+               spin_unlock_irq(&mdev->list_lock);
+               most_put_mbo(mbo);
+               spin_lock_irq(&mdev->list_lock);
+       }
+       spin_unlock_irq(&mdev->list_lock);
+       most_stop_channel(mdev->iface, mdev->ch_idx, &comp);
+       mdev->mute = false;
+
+       v4l2_fh_del(&fh->fh);
+       v4l2_fh_exit(&fh->fh);
+
+       atomic_dec(&mdev->access_ref);
+       kfree(fh);
+       return 0;
+}
+
+static ssize_t comp_vdev_read(struct file *filp, char __user *buf,
+                             size_t count, loff_t *pos)
+{
+       struct comp_fh *fh = filp->private_data;
+       struct most_video_dev *mdev = fh->mdev;
+       int ret = 0;
+
+       if (*pos)
+               return -ESPIPE;
+
+       if (!mdev)
+               return -ENODEV;
+
+       /* wait for the first buffer */
+       if (!(filp->f_flags & O_NONBLOCK)) {
+               if (wait_event_interruptible(mdev->wait_data, data_ready(mdev)))
+                       return -ERESTARTSYS;
+       }
+
+       if (!data_ready(mdev))
+               return -EAGAIN;
+
+       while (count > 0 && data_ready(mdev)) {
+               struct mbo *const mbo = get_top_mbo(mdev);
+               int const rem = mbo->processed_length - fh->offs;
+               int const cnt = rem < count ? rem : count;
+
+               if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) {
+                       v4l2_err(&mdev->v4l2_dev, "read: copy_to_user failed\n");
+                       if (!ret)
+                               ret = -EFAULT;
+                       return ret;
+               }
+
+               fh->offs += cnt;
+               count -= cnt;
+               buf += cnt;
+               ret += cnt;
+
+               if (cnt >= rem) {
+                       fh->offs = 0;
+                       spin_lock_irq(&mdev->list_lock);
+                       list_del(&mbo->list);
+                       spin_unlock_irq(&mdev->list_lock);
+                       most_put_mbo(mbo);
+               }
+       }
+       return ret;
+}
+
+static __poll_t comp_vdev_poll(struct file *filp, poll_table *wait)
+{
+       struct comp_fh *fh = filp->private_data;
+       struct most_video_dev *mdev = fh->mdev;
+       __poll_t mask = 0;
+
+       /* only wait if no data is available */
+       if (!data_ready(mdev))
+               poll_wait(filp, &mdev->wait_data, wait);
+       if (data_ready(mdev))
+               mask |= POLLIN | POLLRDNORM;
+
+       return mask;
+}
+
+static void comp_set_format_struct(struct v4l2_format *f)
+{
+       f->fmt.pix.width = 8;
+       f->fmt.pix.height = 8;
+       f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage = 188 * 2;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       f->fmt.pix.priv = 0;
+}
+
+static int comp_set_format(struct most_video_dev *mdev, unsigned int cmd,
+                          struct v4l2_format *format)
+{
+       if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG)
+               return -EINVAL;
+
+       if (cmd == VIDIOC_TRY_FMT)
+               return 0;
+
+       comp_set_format_struct(format);
+
+       return 0;
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct comp_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n");
+
+       strlcpy(cap->driver, "v4l2_component", sizeof(cap->driver));
+       strlcpy(cap->card, "MOST", sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+                "%s", mdev->iface->description);
+
+       cap->capabilities =
+               V4L2_CAP_READWRITE |
+               V4L2_CAP_TUNER |
+               V4L2_CAP_VIDEO_CAPTURE;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       struct comp_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index);
+
+       if (f->index)
+               return -EINVAL;
+
+       strcpy(f->description, "MPEG");
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       f->flags = V4L2_FMT_FLAG_COMPRESSED;
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct comp_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n");
+
+       comp_set_format_struct(f);
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct comp_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       return comp_set_format(mdev, VIDIOC_TRY_FMT, f);
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct comp_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       return comp_set_format(mdev, VIDIOC_S_FMT, f);
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct comp_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n");
+
+       *norm = V4L2_STD_UNKNOWN;
+       return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                            struct v4l2_input *input)
+{
+       struct comp_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       if (input->index >= V4L2_CMP_MAX_INPUT)
+               return -EINVAL;
+
+       strcpy(input->name, "MOST Video");
+       input->type |= V4L2_INPUT_TYPE_CAMERA;
+       input->audioset = 0;
+
+       input->std = mdev->vdev->tvnorms;
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct comp_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+       *i = mdev->ctrl_input;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
+{
+       struct comp_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index);
+
+       if (index >= V4L2_CMP_MAX_INPUT)
+               return -EINVAL;
+       mdev->ctrl_input = index;
+       return 0;
+}
+
+static const struct v4l2_file_operations comp_fops = {
+       .owner      = THIS_MODULE,
+       .open       = comp_vdev_open,
+       .release    = comp_vdev_close,
+       .read       = comp_vdev_read,
+       .poll       = comp_vdev_poll,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap            = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
+       .vidioc_g_std               = vidioc_g_std,
+       .vidioc_enum_input          = vidioc_enum_input,
+       .vidioc_g_input             = vidioc_g_input,
+       .vidioc_s_input             = vidioc_s_input,
+};
+
+static const struct video_device comp_videodev_template = {
+       .fops = &comp_fops,
+       .release = video_device_release,
+       .ioctl_ops = &video_ioctl_ops,
+       .tvnorms = V4L2_STD_UNKNOWN,
+};
+
+/**************************************************************************/
+
+static struct most_video_dev *get_comp_dev(
+       struct most_interface *iface, int channel_idx)
+{
+       struct most_video_dev *mdev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&list_lock, flags);
+       list_for_each_entry(mdev, &video_devices, list) {
+               if (mdev->iface == iface && mdev->ch_idx == channel_idx) {
+                       spin_unlock_irqrestore(&list_lock, flags);
+                       return mdev;
+               }
+       }
+       spin_unlock_irqrestore(&list_lock, flags);
+       return NULL;
+}
+
+static int comp_rx_data(struct mbo *mbo)
+{
+       unsigned long flags;
+       struct most_video_dev *mdev =
+               get_comp_dev(mbo->ifp, mbo->hdm_channel_id);
+
+       if (!mdev)
+               return -EIO;
+
+       spin_lock_irqsave(&mdev->list_lock, flags);
+       if (unlikely(mdev->mute)) {
+               spin_unlock_irqrestore(&mdev->list_lock, flags);
+               return -EIO;
+       }
+
+       list_add_tail(&mbo->list, &mdev->pending_mbos);
+       spin_unlock_irqrestore(&mdev->list_lock, flags);
+       wake_up_interruptible(&mdev->wait_data);
+       return 0;
+}
+
+static int comp_register_videodev(struct most_video_dev *mdev)
+{
+       int ret;
+
+       v4l2_info(&mdev->v4l2_dev, "comp_register_videodev()\n");
+
+       init_waitqueue_head(&mdev->wait_data);
+
+       /* allocate and fill v4l2 video struct */
+       mdev->vdev = video_device_alloc();
+       if (!mdev->vdev)
+               return -ENOMEM;
+
+       /* Fill the video capture device struct */
+       *mdev->vdev = comp_videodev_template;
+       mdev->vdev->v4l2_dev = &mdev->v4l2_dev;
+       mdev->vdev->lock = &mdev->lock;
+       snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s",
+                mdev->v4l2_dev.name);
+
+       /* Register the v4l2 device */
+       video_set_drvdata(mdev->vdev, mdev);
+       ret = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1);
+       if (ret) {
+               v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n",
+                        ret);
+               video_device_release(mdev->vdev);
+       }
+
+       return ret;
+}
+
+static void comp_unregister_videodev(struct most_video_dev *mdev)
+{
+       v4l2_info(&mdev->v4l2_dev, "comp_unregister_videodev()\n");
+
+       video_unregister_device(mdev->vdev);
+}
+
+static void comp_v4l2_dev_release(struct v4l2_device *v4l2_dev)
+{
+       struct most_video_dev *mdev =
+               container_of(v4l2_dev, struct most_video_dev, v4l2_dev);
+
+       v4l2_device_unregister(v4l2_dev);
+       kfree(mdev);
+}
+
+static int comp_probe_channel(struct most_interface *iface, int channel_idx,
+                             struct most_channel_config *ccfg, char *name)
+{
+       int ret;
+       struct most_video_dev *mdev = get_comp_dev(iface, channel_idx);
+
+       pr_info("comp_probe_channel(%s)\n", name);
+
+       if (mdev) {
+               pr_err("channel already linked\n");
+               return -EEXIST;
+       }
+
+       if (ccfg->direction != MOST_CH_RX) {
+               pr_err("wrong direction, expect rx\n");
+               return -EINVAL;
+       }
+
+       if (ccfg->data_type != MOST_CH_SYNC &&
+           ccfg->data_type != MOST_CH_ISOC) {
+               pr_err("wrong channel type, expect sync or isoc\n");
+               return -EINVAL;
+       }
+
+       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       if (!mdev)
+               return -ENOMEM;
+
+       mutex_init(&mdev->lock);
+       atomic_set(&mdev->access_ref, -1);
+       spin_lock_init(&mdev->list_lock);
+       INIT_LIST_HEAD(&mdev->pending_mbos);
+       mdev->iface = iface;
+       mdev->ch_idx = channel_idx;
+       mdev->v4l2_dev.release = comp_v4l2_dev_release;
+
+       /* Create the v4l2_device */
+       strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name));
+       ret = v4l2_device_register(NULL, &mdev->v4l2_dev);
+       if (ret) {
+               pr_err("v4l2_device_register() failed\n");
+               kfree(mdev);
+               return ret;
+       }
+
+       ret = comp_register_videodev(mdev);
+       if (ret)
+               goto err_unreg;
+
+       spin_lock_irq(&list_lock);
+       list_add(&mdev->list, &video_devices);
+       spin_unlock_irq(&list_lock);
+       v4l2_info(&mdev->v4l2_dev, "comp_probe_channel() done\n");
+       return 0;
+
+err_unreg:
+       v4l2_device_disconnect(&mdev->v4l2_dev);
+       v4l2_device_put(&mdev->v4l2_dev);
+       return ret;
+}
+
+static int comp_disconnect_channel(struct most_interface *iface,
+                                  int channel_idx)
+{
+       struct most_video_dev *mdev = get_comp_dev(iface, channel_idx);
+
+       if (!mdev) {
+               pr_err("no such channel is linked\n");
+               return -ENOENT;
+       }
+
+       v4l2_info(&mdev->v4l2_dev, "comp_disconnect_channel()\n");
+
+       spin_lock_irq(&list_lock);
+       list_del(&mdev->list);
+       spin_unlock_irq(&list_lock);
+
+       comp_unregister_videodev(mdev);
+       v4l2_device_disconnect(&mdev->v4l2_dev);
+       v4l2_device_put(&mdev->v4l2_dev);
+       return 0;
+}
+
+static struct core_component comp_info = {
+       .name = "video",
+       .probe_channel = comp_probe_channel,
+       .disconnect_channel = comp_disconnect_channel,
+       .rx_completion = comp_rx_data,
+};
+
+static int __init comp_init(void)
+{
+       spin_lock_init(&list_lock);
+       return most_register_component(&comp);
+}
+
+static void __exit comp_exit(void)
+{
+       struct most_video_dev *mdev, *tmp;
+
+       /*
+        * As the mostcore currently doesn't call disconnect_channel()
+        * for linked channels while we call most_deregister_component()
+        * we simulate this call here.
+        * This must be fixed in core.
+        */
+       spin_lock_irq(&list_lock);
+       list_for_each_entry_safe(mdev, tmp, &video_devices, list) {
+               list_del(&mdev->list);
+               spin_unlock_irq(&list_lock);
+
+               comp_unregister_videodev(mdev);
+               v4l2_device_disconnect(&mdev->v4l2_dev);
+               v4l2_device_put(&mdev->v4l2_dev);
+               spin_lock_irq(&list_lock);
+       }
+       spin_unlock_irq(&list_lock);
+
+       most_deregister_component(&comp_info);
+       BUG_ON(!list_empty(&video_devices));
+}
+
+module_init(comp_init);
+module_exit(comp_exit);
+
+MODULE_DESCRIPTION("V4L2 Component Module for Mostcore");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ncpfs/Kconfig b/drivers/staging/ncpfs/Kconfig
new file mode 100644 (file)
index 0000000..c931cf2
--- /dev/null
@@ -0,0 +1,108 @@
+#
+# NCP Filesystem configuration
+#
+config NCP_FS
+       tristate "NCP file system support (to mount NetWare volumes)"
+       depends on IPX!=n || INET
+       help
+         NCP (NetWare Core Protocol) is a protocol that runs over IPX and is
+         used by Novell NetWare clients to talk to file servers.  It is to
+         IPX what NFS is to TCP/IP, if that helps.  Saying Y here allows you
+         to mount NetWare file server volumes and to access them just like
+         any other Unix directory.  For details, please read the file
+         <file:Documentation/filesystems/ncpfs.txt> in the kernel source and
+         the IPX-HOWTO from <http://www.tldp.org/docs.html#howto>.
+
+         You do not have to say Y here if you want your Linux box to act as a
+         file *server* for Novell NetWare clients.
+
+         General information about how to connect Linux, Windows machines and
+         Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
+
+         To compile this as a module, choose M here: the module will be called
+         ncpfs.  Say N unless you are connected to a Novell network.
+
+config NCPFS_PACKET_SIGNING
+       bool "Packet signatures"
+       depends on NCP_FS
+       help
+         NCP allows packets to be signed for stronger security. If you want
+         security, say Y.  Normal users can leave it off.  To be able to use
+         packet signing you must use ncpfs > 2.0.12.
+
+config NCPFS_IOCTL_LOCKING
+       bool "Proprietary file locking"
+       depends on NCP_FS
+       help
+         Allows locking of records on remote volumes.  Say N unless you have
+         special applications which are able to utilize this locking scheme.
+
+config NCPFS_STRONG
+       bool "Clear remove/delete inhibit when needed"
+       depends on NCP_FS
+       help
+         Allows manipulation of files flagged as Delete or Rename Inhibit.
+         To use this feature you must mount volumes with the ncpmount
+         parameter "-s" (ncpfs-2.0.12 and newer).  Say Y unless you are not
+         mounting volumes with -f 444.
+
+config NCPFS_NFS_NS
+       bool "Use NFS namespace if available"
+       depends on NCP_FS
+       help
+         Allows you to utilize NFS namespace on NetWare servers.  It brings
+         you case sensitive filenames.  Say Y.  You can disable it at
+         mount-time with the `-N nfs' parameter of ncpmount.
+
+config NCPFS_OS2_NS
+       bool "Use LONG (OS/2) namespace if available"
+       depends on NCP_FS
+       help
+         Allows you to utilize OS2/LONG namespace on NetWare servers.
+         Filenames in this namespace are limited to 255 characters, they are
+         case insensitive, and case in names is preserved.  Say Y.  You can
+         disable it at mount time with the -N os2 parameter of ncpmount.
+
+config NCPFS_SMALLDOS
+       bool "Lowercase DOS filenames"
+       depends on NCP_FS
+       ---help---
+         If you say Y here, every filename on a NetWare server volume using
+         the OS2/LONG namespace and created under DOS or on a volume using
+         DOS namespace will be converted to lowercase characters.
+         Saying N here will give you these filenames in uppercase.
+
+         This is only a cosmetic option since the OS2/LONG namespace is case
+         insensitive. The only major reason for this option is backward
+         compatibility when moving from DOS to OS2/LONG namespace support.
+         Long filenames (created by Win95) will not be affected.
+
+         This option does not solve the problem that filenames appear
+         differently under Linux and under Windows, since Windows does an
+         additional conversions on the client side. You can achieve similar
+         effects by saying Y to "Allow using of Native Language Support"
+         below.
+
+config NCPFS_NLS
+       bool "Use Native Language Support"
+       depends on NCP_FS
+       select NLS
+       help
+         Allows you to use codepages and I/O charsets for file name
+         translation between the server file system and input/output. This
+         may be useful, if you want to access the server with other operating
+         systems, e.g. Windows 95. See also NLS for more Information.
+
+         To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer.
+
+config NCPFS_EXTRAS
+       bool "Enable symbolic links and execute flags"
+       depends on NCP_FS
+       help
+         This enables the use of symbolic links and an execute permission
+         bit on NCPFS. The file server need not have long name space or NFS
+         name space loaded for these to work.
+
+         To use the new attributes, it is recommended to use the flags
+         '-f 600 -d 755' on the ncpmount command line.
+
diff --git a/drivers/staging/ncpfs/Makefile b/drivers/staging/ncpfs/Makefile
new file mode 100644 (file)
index 0000000..66fe5f8
--- /dev/null
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the linux ncp filesystem routines.
+#
+
+obj-$(CONFIG_NCP_FS) += ncpfs.o
+
+ncpfs-y      := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \
+               ncpsign_kernel.o getopt.o
+
+ncpfs-$(CONFIG_NCPFS_EXTRAS)   += symlink.o
+ncpfs-$(CONFIG_NCPFS_NFS_NS)   += symlink.o
+
+# If you want debugging output, please uncomment the following line
+# ccflags-y := -DDEBUG_NCP=1
+
+CFLAGS_ncplib_kernel.o := -finline-functions
diff --git a/drivers/staging/ncpfs/TODO b/drivers/staging/ncpfs/TODO
new file mode 100644 (file)
index 0000000..9b6d38b
--- /dev/null
@@ -0,0 +1,4 @@
+The ncpfs code will be removed soon from the kernel tree as it is old and
+obsolete and broken.
+
+Don't worry about fixing up anything here, it's not needed.
diff --git a/drivers/staging/ncpfs/dir.c b/drivers/staging/ncpfs/dir.c
new file mode 100644 (file)
index 0000000..0c57c5c
--- /dev/null
@@ -0,0 +1,1232 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  dir.c
+ *
+ *  Copyright (C) 1995, 1996 by Volker Lendecke
+ *  Modified for big endian by J.F. Chadima and David S. Miller
+ *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *  Modified 1998, 1999 Wolfram Pienkoss for NLS
+ *  Modified 1999 Wolfram Pienkoss for directory caching
+ *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
+ *
+ */
+
+
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <linux/stat.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/namei.h>
+#include <linux/uaccess.h>
+#include <asm/byteorder.h>
+
+#include "ncp_fs.h"
+
+static void ncp_read_volume_list(struct file *, struct dir_context *,
+                               struct ncp_cache_control *);
+static void ncp_do_readdir(struct file *, struct dir_context *,
+                               struct ncp_cache_control *);
+
+static int ncp_readdir(struct file *, struct dir_context *);
+
+static int ncp_create(struct inode *, struct dentry *, umode_t, bool);
+static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int);
+static int ncp_unlink(struct inode *, struct dentry *);
+static int ncp_mkdir(struct inode *, struct dentry *, umode_t);
+static int ncp_rmdir(struct inode *, struct dentry *);
+static int ncp_rename(struct inode *, struct dentry *,
+                     struct inode *, struct dentry *, unsigned int);
+static int ncp_mknod(struct inode * dir, struct dentry *dentry,
+                    umode_t mode, dev_t rdev);
+#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
+extern int ncp_symlink(struct inode *, struct dentry *, const char *);
+#else
+#define ncp_symlink NULL
+#endif
+                     
+const struct file_operations ncp_dir_operations =
+{
+       .llseek         = generic_file_llseek,
+       .read           = generic_read_dir,
+       .iterate        = ncp_readdir,
+       .unlocked_ioctl = ncp_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ncp_compat_ioctl,
+#endif
+};
+
+const struct inode_operations ncp_dir_inode_operations =
+{
+       .create         = ncp_create,
+       .lookup         = ncp_lookup,
+       .unlink         = ncp_unlink,
+       .symlink        = ncp_symlink,
+       .mkdir          = ncp_mkdir,
+       .rmdir          = ncp_rmdir,
+       .mknod          = ncp_mknod,
+       .rename         = ncp_rename,
+       .setattr        = ncp_notify_change,
+};
+
+/*
+ * Dentry operations routines
+ */
+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 *,
+               unsigned int, const char *, const struct qstr *);
+static int ncp_delete_dentry(const struct dentry *);
+static void ncp_d_prune(struct dentry *dentry);
+
+const struct dentry_operations ncp_dentry_operations =
+{
+       .d_revalidate   = ncp_lookup_validate,
+       .d_hash         = ncp_hash_dentry,
+       .d_compare      = ncp_compare_dentry,
+       .d_delete       = ncp_delete_dentry,
+       .d_prune        = ncp_d_prune,
+};
+
+#define ncp_namespace(i)       (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
+
+static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
+{
+#ifdef CONFIG_NCPFS_SMALLDOS
+       int ns = ncp_namespace(i);
+
+       if ((ns == NW_NS_DOS)
+#ifdef CONFIG_NCPFS_OS2_NS
+               || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
+#endif /* CONFIG_NCPFS_OS2_NS */
+          )
+               return 0;
+#endif /* CONFIG_NCPFS_SMALLDOS */
+       return 1;
+}
+
+#define ncp_preserve_case(i)   (ncp_namespace(i) != NW_NS_DOS)
+
+static inline int ncp_case_sensitive(const struct inode *i)
+{
+#ifdef CONFIG_NCPFS_NFS_NS
+       return ncp_namespace(i) == NW_NS_NFS;
+#else
+       return 0;
+#endif /* CONFIG_NCPFS_NFS_NS */
+}
+
+/*
+ * Note: leave the hash unchanged if the directory
+ * is case-sensitive.
+ */
+static int 
+ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
+{
+       struct inode *inode = d_inode_rcu(dentry);
+
+       if (!inode)
+               return 0;
+
+       if (!ncp_case_sensitive(inode)) {
+               struct nls_table *t;
+               unsigned long hash;
+               int i;
+
+               t = NCP_IO_TABLE(dentry->d_sb);
+               hash = init_name_hash(dentry);
+               for (i=0; i<this->len ; i++)
+                       hash = partial_name_hash(ncp_tolower(t, this->name[i]),
+                                                                       hash);
+               this->hash = end_name_hash(hash);
+       }
+       return 0;
+}
+
+static int
+ncp_compare_dentry(const struct dentry *dentry,
+               unsigned int len, const char *str, const struct qstr *name)
+{
+       struct inode *pinode;
+
+       if (len != name->len)
+               return 1;
+
+       pinode = d_inode_rcu(dentry->d_parent);
+       if (!pinode)
+               return 1;
+
+       if (ncp_case_sensitive(pinode))
+               return strncmp(str, name->name, len);
+
+       return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
+}
+
+/*
+ * This is the callback from dput() when d_count is going to 0.
+ * We use this to unhash dentries with bad inodes.
+ * Closing files can be safely postponed until iput() - it's done there anyway.
+ */
+static int
+ncp_delete_dentry(const struct dentry * dentry)
+{
+       struct inode *inode = d_inode(dentry);
+
+       if (inode) {
+               if (is_bad_inode(inode))
+                       return 1;
+       } else
+       {
+       /* N.B. Unhash negative dentries? */
+       }
+       return 0;
+}
+
+static inline int
+ncp_single_volume(struct ncp_server *server)
+{
+       return (server->m.mounted_vol[0] != '\0');
+}
+
+static inline int ncp_is_server_root(struct inode *inode)
+{
+       return !ncp_single_volume(NCP_SERVER(inode)) &&
+               is_root_inode(inode);
+}
+
+
+/*
+ * This is the callback when the dcache has a lookup hit.
+ */
+
+
+#ifdef CONFIG_NCPFS_STRONG
+/* try to delete a readonly file (NW R bit set) */
+
+static int
+ncp_force_unlink(struct inode *dir, struct dentry* dentry)
+{
+        int res=0x9c,res2;
+       struct nw_modify_dos_info info;
+       __le32 old_nwattr;
+       struct inode *inode;
+
+       memset(&info, 0, sizeof(info));
+       
+        /* remove the Read-Only flag on the NW server */
+       inode = d_inode(dentry);
+
+       old_nwattr = NCP_FINFO(inode)->nwattr;
+       info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
+       res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
+       if (res2)
+               goto leave_me;
+
+        /* now try again the delete operation */
+        res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
+
+        if (res)  /* delete failed, set R bit again */
+        {
+               info.attributes = old_nwattr;
+               res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
+               if (res2)
+                        goto leave_me;
+        }
+leave_me:
+        return(res);
+}
+#endif /* CONFIG_NCPFS_STRONG */
+
+#ifdef CONFIG_NCPFS_STRONG
+static int
+ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
+                 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
+{
+       struct nw_modify_dos_info info;
+        int res=0x90,res2;
+       struct inode *old_inode = d_inode(old_dentry);
+       __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
+       __le32 new_nwattr = 0; /* shut compiler warning */
+       int old_nwattr_changed = 0;
+       int new_nwattr_changed = 0;
+
+       memset(&info, 0, sizeof(info));
+       
+        /* remove the Read-Only flag on the NW server */
+
+       info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+       res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
+       if (!res2)
+               old_nwattr_changed = 1;
+       if (new_dentry && d_really_is_positive(new_dentry)) {
+               new_nwattr = NCP_FINFO(d_inode(new_dentry))->nwattr;
+               info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+               res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
+               if (!res2)
+                       new_nwattr_changed = 1;
+       }
+        /* now try again the rename operation */
+       /* but only if something really happened */
+       if (new_nwattr_changed || old_nwattr_changed) {
+               res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
+                                                   old_dir, _old_name,
+                                                   new_dir, _new_name);
+       } 
+       if (res)
+               goto leave_me;
+       /* file was successfully renamed, so:
+          do not set attributes on old file - it no longer exists
+          copy attributes from old file to new */
+       new_nwattr_changed = old_nwattr_changed;
+       new_nwattr = old_nwattr;
+       old_nwattr_changed = 0;
+       
+leave_me:;
+       if (old_nwattr_changed) {
+               info.attributes = old_nwattr;
+               res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
+               /* ignore errors */
+       }
+       if (new_nwattr_changed) {
+               info.attributes = new_nwattr;
+               res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
+               /* ignore errors */
+       }
+        return(res);
+}
+#endif /* CONFIG_NCPFS_STRONG */
+
+
+static int
+ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
+{
+       struct ncp_server *server;
+       struct dentry *parent;
+       struct inode *dir;
+       struct ncp_entry_info finfo;
+       int res, val = 0, len;
+       __u8 __name[NCP_MAXPATHLEN + 1];
+
+       if (dentry == dentry->d_sb->s_root)
+               return 1;
+
+       if (flags & LOOKUP_RCU)
+               return -ECHILD;
+
+       parent = dget_parent(dentry);
+       dir = d_inode(parent);
+
+       if (d_really_is_negative(dentry))
+               goto finished;
+
+       server = NCP_SERVER(dir);
+
+       /*
+        * Inspired by smbfs:
+        * The default validation is based on dentry age:
+        * We set the max age at mount time.  (But each
+        * successful server lookup renews the timestamp.)
+        */
+       val = NCP_TEST_AGE(server, dentry);
+       if (val)
+               goto finished;
+
+       ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n",
+               dentry, NCP_GET_AGE(dentry));
+
+       len = sizeof(__name);
+       if (ncp_is_server_root(dir)) {
+               res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+                                dentry->d_name.len, 1);
+               if (!res) {
+                       res = ncp_lookup_volume(server, __name, &(finfo.i));
+                       if (!res)
+                               ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
+               }
+       } else {
+               res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+                                dentry->d_name.len, !ncp_preserve_case(dir));
+               if (!res)
+                       res = ncp_obtain_info(server, dir, __name, &(finfo.i));
+       }
+       finfo.volume = finfo.i.volNumber;
+       ncp_dbg(2, "looked for %pd/%s, res=%d\n",
+               dentry->d_parent, __name, res);
+       /*
+        * If we didn't find it, or if it has a different dirEntNum to
+        * what we remember, it's not valid any more.
+        */
+       if (!res) {
+               struct inode *inode = d_inode(dentry);
+
+               inode_lock(inode);
+               if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
+                       ncp_new_dentry(dentry);
+                       val=1;
+               } else
+                       ncp_dbg(2, "found, but dirEntNum changed\n");
+
+               ncp_update_inode2(inode, &finfo);
+               inode_unlock(inode);
+       }
+
+finished:
+       ncp_dbg(2, "result=%d\n", val);
+       dput(parent);
+       return val;
+}
+
+static time_t ncp_obtain_mtime(struct dentry *dentry)
+{
+       struct inode *inode = d_inode(dentry);
+       struct ncp_server *server = NCP_SERVER(inode);
+       struct nw_info_struct i;
+
+       if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
+               return 0;
+
+       if (ncp_obtain_info(server, inode, NULL, &i))
+               return 0;
+
+       return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
+}
+
+static inline void
+ncp_invalidate_dircache_entries(struct dentry *parent)
+{
+       struct ncp_server *server = NCP_SERVER(d_inode(parent));
+       struct dentry *dentry;
+
+       spin_lock(&parent->d_lock);
+       list_for_each_entry(dentry, &parent->d_subdirs, d_child) {
+               dentry->d_fsdata = NULL;
+               ncp_age_dentry(server, dentry);
+       }
+       spin_unlock(&parent->d_lock);
+}
+
+static int ncp_readdir(struct file *file, struct dir_context *ctx)
+{
+       struct dentry *dentry = file->f_path.dentry;
+       struct inode *inode = d_inode(dentry);
+       struct page *page = NULL;
+       struct ncp_server *server = NCP_SERVER(inode);
+       union  ncp_dir_cache *cache = NULL;
+       struct ncp_cache_control ctl;
+       int result, mtime_valid = 0;
+       time_t mtime = 0;
+
+       ctl.page  = NULL;
+       ctl.cache = NULL;
+
+       ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos);
+
+       result = -EIO;
+       /* Do not generate '.' and '..' when server is dead. */
+       if (!ncp_conn_valid(server))
+               goto out;
+
+       result = 0;
+       if (!dir_emit_dots(file, ctx))
+               goto out;
+
+       page = grab_cache_page(&inode->i_data, 0);
+       if (!page)
+               goto read_really;
+
+       ctl.cache = cache = kmap(page);
+       ctl.head  = cache->head;
+
+       if (!PageUptodate(page) || !ctl.head.eof)
+               goto init_cache;
+
+       if (ctx->pos == 2) {
+               if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
+                       goto init_cache;
+
+               mtime = ncp_obtain_mtime(dentry);
+               mtime_valid = 1;
+               if ((!mtime) || (mtime != ctl.head.mtime))
+                       goto init_cache;
+       }
+
+       if (ctx->pos > ctl.head.end)
+               goto finished;
+
+       ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2);
+       ctl.ofs  = ctl.fpos / NCP_DIRCACHE_SIZE;
+       ctl.idx  = ctl.fpos % NCP_DIRCACHE_SIZE;
+
+       for (;;) {
+               if (ctl.ofs != 0) {
+                       ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
+                       if (!ctl.page)
+                               goto invalid_cache;
+                       ctl.cache = kmap(ctl.page);
+                       if (!PageUptodate(ctl.page))
+                               goto invalid_cache;
+               }
+               while (ctl.idx < NCP_DIRCACHE_SIZE) {
+                       struct dentry *dent;
+                       bool over;
+
+                       spin_lock(&dentry->d_lock);
+                       if (!(NCP_FINFO(inode)->flags & NCPI_DIR_CACHE)) { 
+                               spin_unlock(&dentry->d_lock);
+                               goto invalid_cache;
+                       }
+                       dent = ctl.cache->dentry[ctl.idx];
+                       if (unlikely(!lockref_get_not_dead(&dent->d_lockref))) {
+                               spin_unlock(&dentry->d_lock);
+                               goto invalid_cache;
+                       }
+                       spin_unlock(&dentry->d_lock);
+                       if (d_really_is_negative(dent)) {
+                               dput(dent);
+                               goto invalid_cache;
+                       }
+                       over = !dir_emit(ctx, dent->d_name.name,
+                                       dent->d_name.len,
+                                       d_inode(dent)->i_ino, DT_UNKNOWN);
+                       dput(dent);
+                       if (over)
+                               goto finished;
+                       ctx->pos += 1;
+                       ctl.idx += 1;
+                       if (ctx->pos > ctl.head.end)
+                               goto finished;
+               }
+               if (ctl.page) {
+                       kunmap(ctl.page);
+                       SetPageUptodate(ctl.page);
+                       unlock_page(ctl.page);
+                       put_page(ctl.page);
+                       ctl.page = NULL;
+               }
+               ctl.idx  = 0;
+               ctl.ofs += 1;
+       }
+invalid_cache:
+       if (ctl.page) {
+               kunmap(ctl.page);
+               unlock_page(ctl.page);
+               put_page(ctl.page);
+               ctl.page = NULL;
+       }
+       ctl.cache = cache;
+init_cache:
+       ncp_invalidate_dircache_entries(dentry);
+       if (!mtime_valid) {
+               mtime = ncp_obtain_mtime(dentry);
+               mtime_valid = 1;
+       }
+       ctl.head.mtime = mtime;
+       ctl.head.time = jiffies;
+       ctl.head.eof = 0;
+       ctl.fpos = 2;
+       ctl.ofs = 0;
+       ctl.idx = NCP_DIRCACHE_START;
+       ctl.filled = 0;
+       ctl.valid  = 1;
+read_really:
+       spin_lock(&dentry->d_lock);
+       NCP_FINFO(inode)->flags |= NCPI_DIR_CACHE;
+       spin_unlock(&dentry->d_lock);
+       if (ncp_is_server_root(inode)) {
+               ncp_read_volume_list(file, ctx, &ctl);
+       } else {
+               ncp_do_readdir(file, ctx, &ctl);
+       }
+       ctl.head.end = ctl.fpos - 1;
+       ctl.head.eof = ctl.valid;
+finished:
+       if (ctl.page) {
+               kunmap(ctl.page);
+               SetPageUptodate(ctl.page);
+               unlock_page(ctl.page);
+               put_page(ctl.page);
+       }
+       if (page) {
+               cache->head = ctl.head;
+               kunmap(page);
+               SetPageUptodate(page);
+               unlock_page(page);
+               put_page(page);
+       }
+out:
+       return result;
+}
+
+static void ncp_d_prune(struct dentry *dentry)
+{
+       if (!dentry->d_fsdata)  /* not referenced from page cache */
+               return;
+       NCP_FINFO(d_inode(dentry->d_parent))->flags &= ~NCPI_DIR_CACHE;
+}
+
+static int
+ncp_fill_cache(struct file *file, struct dir_context *ctx,
+               struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
+               int inval_childs)
+{
+       struct dentry *newdent, *dentry = file->f_path.dentry;
+       struct inode *dir = d_inode(dentry);
+       struct ncp_cache_control ctl = *ctrl;
+       struct qstr qname;
+       int valid = 0;
+       int hashed = 0;
+       ino_t ino = 0;
+       __u8 __name[NCP_MAXPATHLEN + 1];
+
+       qname.len = sizeof(__name);
+       if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
+                       entry->i.entryName, entry->i.nameLen,
+                       !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
+               return 1; /* I'm not sure */
+
+       qname.name = __name;
+
+       newdent = d_hash_and_lookup(dentry, &qname);
+       if (IS_ERR(newdent))
+               goto end_advance;
+       if (!newdent) {
+               newdent = d_alloc(dentry, &qname);
+               if (!newdent)
+                       goto end_advance;
+       } else {
+               hashed = 1;
+
+               /* If case sensitivity changed for this volume, all entries below this one
+                  should be thrown away.  This entry itself is not affected, as its case
+                  sensitivity is controlled by its own parent. */
+               if (inval_childs)
+                       shrink_dcache_parent(newdent);
+
+               /*
+                * NetWare's OS2 namespace is case preserving yet case
+                * insensitive.  So we update dentry's name as received from
+                * server. Parent dir's i_mutex is locked because we're in
+                * readdir.
+                */
+               dentry_update_name_case(newdent, &qname);
+       }
+
+       if (d_really_is_negative(newdent)) {
+               struct inode *inode;
+
+               entry->opened = 0;
+               entry->ino = iunique(dir->i_sb, 2);
+               inode = ncp_iget(dir->i_sb, entry);
+               if (inode) {
+                       d_instantiate(newdent, inode);
+                       if (!hashed)
+                               d_rehash(newdent);
+               } else {
+                       spin_lock(&dentry->d_lock);
+                       NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE;
+                       spin_unlock(&dentry->d_lock);
+               }
+       } else {
+               struct inode *inode = d_inode(newdent);
+
+               inode_lock_nested(inode, I_MUTEX_CHILD);
+               ncp_update_inode2(inode, entry);
+               inode_unlock(inode);
+       }
+
+       if (ctl.idx >= NCP_DIRCACHE_SIZE) {
+               if (ctl.page) {
+                       kunmap(ctl.page);
+                       SetPageUptodate(ctl.page);
+                       unlock_page(ctl.page);
+                       put_page(ctl.page);
+               }
+               ctl.cache = NULL;
+               ctl.idx  -= NCP_DIRCACHE_SIZE;
+               ctl.ofs  += 1;
+               ctl.page  = grab_cache_page(&dir->i_data, ctl.ofs);
+               if (ctl.page)
+                       ctl.cache = kmap(ctl.page);
+       }
+       if (ctl.cache) {
+               if (d_really_is_positive(newdent)) {
+                       newdent->d_fsdata = newdent;
+                       ctl.cache->dentry[ctl.idx] = newdent;
+                       ino = d_inode(newdent)->i_ino;
+                       ncp_new_dentry(newdent);
+               }
+               valid = 1;
+       }
+       dput(newdent);
+end_advance:
+       if (!valid)
+               ctl.valid = 0;
+       if (!ctl.filled && (ctl.fpos == ctx->pos)) {
+               if (!ino)
+                       ino = iunique(dir->i_sb, 2);
+               ctl.filled = !dir_emit(ctx, qname.name, qname.len,
+                                    ino, DT_UNKNOWN);
+               if (!ctl.filled)
+                       ctx->pos += 1;
+       }
+       ctl.fpos += 1;
+       ctl.idx  += 1;
+       *ctrl = ctl;
+       return (ctl.valid || !ctl.filled);
+}
+
+static void
+ncp_read_volume_list(struct file *file, struct dir_context *ctx,
+                       struct ncp_cache_control *ctl)
+{
+       struct inode *inode = file_inode(file);
+       struct ncp_server *server = NCP_SERVER(inode);
+       struct ncp_volume_info info;
+       struct ncp_entry_info entry;
+       int i;
+
+       ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->pos);
+
+       for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
+               int inval_dentry;
+
+               if (ncp_get_volume_info_with_number(server, i, &info) != 0)
+                       return;
+               if (!strlen(info.volume_name))
+                       continue;
+
+               ncp_dbg(1, "found vol: %s\n", info.volume_name);
+
+               if (ncp_lookup_volume(server, info.volume_name,
+                                       &entry.i)) {
+                       ncp_dbg(1, "could not lookup vol %s\n",
+                               info.volume_name);
+                       continue;
+               }
+               inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
+               entry.volume = entry.i.volNumber;
+               if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry))
+                       return;
+       }
+}
+
+static void
+ncp_do_readdir(struct file *file, struct dir_context *ctx,
+                                               struct ncp_cache_control *ctl)
+{
+       struct inode *dir = file_inode(file);
+       struct ncp_server *server = NCP_SERVER(dir);
+       struct nw_search_sequence seq;
+       struct ncp_entry_info entry;
+       int err;
+       void* buf;
+       int more;
+       size_t bufsize;
+
+       ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos);
+       ncp_vdbg("init %pD, volnum=%d, dirent=%u\n",
+                file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
+
+       err = ncp_initialize_search(server, dir, &seq);
+       if (err) {
+               ncp_dbg(1, "init failed, err=%d\n", err);
+               return;
+       }
+       /* We MUST NOT use server->buffer_size handshaked with server if we are
+          using UDP, as for UDP server uses max. buffer size determined by
+          MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 
+          So we use 128KB, just to be sure, as there is no way how to know
+          this value in advance. */
+       bufsize = 131072;
+       buf = vmalloc(bufsize);
+       if (!buf)
+               return;
+       do {
+               int cnt;
+               char* rpl;
+               size_t rpls;
+
+               err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
+               if (err)                /* Error */
+                       break;
+               if (!cnt)               /* prevent endless loop */
+                       break;
+               while (cnt--) {
+                       size_t onerpl;
+                       
+                       if (rpls < offsetof(struct nw_info_struct, entryName))
+                               break;  /* short packet */
+                       ncp_extract_file_info(rpl, &entry.i);
+                       onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
+                       if (rpls < onerpl)
+                               break;  /* short packet */
+                       (void)ncp_obtain_nfs_info(server, &entry.i);
+                       rpl += onerpl;
+                       rpls -= onerpl;
+                       entry.volume = entry.i.volNumber;
+                       if (!ncp_fill_cache(file, ctx, ctl, &entry, 0))
+                               break;
+               }
+       } while (more);
+       vfree(buf);
+       return;
+}
+
+int ncp_conn_logged_in(struct super_block *sb)
+{
+       struct ncp_server* server = NCP_SBP(sb);
+       int result;
+
+       if (ncp_single_volume(server)) {
+               int len;
+               struct dentry* dent;
+               __u32 volNumber;
+               __le32 dirEntNum;
+               __le32 DosDirNum;
+               __u8 __name[NCP_MAXPATHLEN + 1];
+
+               len = sizeof(__name);
+               result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
+                                   strlen(server->m.mounted_vol), 1);
+               if (result)
+                       goto out;
+               result = -ENOENT;
+               if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
+                       ncp_vdbg("%s not found\n", server->m.mounted_vol);
+                       goto out;
+               }
+               dent = sb->s_root;
+               if (dent) {
+                       struct inode* ino = d_inode(dent);
+                       if (ino) {
+                               ncp_update_known_namespace(server, volNumber, NULL);
+                               NCP_FINFO(ino)->volNumber = volNumber;
+                               NCP_FINFO(ino)->dirEntNum = dirEntNum;
+                               NCP_FINFO(ino)->DosDirNum = DosDirNum;
+                               result = 0;
+                       } else {
+                               ncp_dbg(1, "d_inode(sb->s_root) == NULL!\n");
+                       }
+               } else {
+                       ncp_dbg(1, "sb->s_root == NULL!\n");
+               }
+       } else
+               result = 0;
+
+out:
+       return result;
+}
+
+static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+{
+       struct ncp_server *server = NCP_SERVER(dir);
+       struct inode *inode = NULL;
+       struct ncp_entry_info finfo;
+       int error, res, len;
+       __u8 __name[NCP_MAXPATHLEN + 1];
+
+       error = -EIO;
+       if (!ncp_conn_valid(server))
+               goto finished;
+
+       ncp_vdbg("server lookup for %pd2\n", dentry);
+
+       len = sizeof(__name);
+       if (ncp_is_server_root(dir)) {
+               res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+                                dentry->d_name.len, 1);
+               if (!res)
+                       res = ncp_lookup_volume(server, __name, &(finfo.i));
+               if (!res)
+                       ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
+       } else {
+               res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+                                dentry->d_name.len, !ncp_preserve_case(dir));
+               if (!res)
+                       res = ncp_obtain_info(server, dir, __name, &(finfo.i));
+       }
+       ncp_vdbg("looked for %pd2, res=%d\n", dentry, res);
+       /*
+        * If we didn't find an entry, make a negative dentry.
+        */
+       if (res)
+               goto add_entry;
+
+       /*
+        * Create an inode for the entry.
+        */
+       finfo.opened = 0;
+       finfo.ino = iunique(dir->i_sb, 2);
+       finfo.volume = finfo.i.volNumber;
+       error = -EACCES;
+       inode = ncp_iget(dir->i_sb, &finfo);
+
+       if (inode) {
+               ncp_new_dentry(dentry);
+add_entry:
+               d_add(dentry, inode);
+               error = 0;
+       }
+
+finished:
+       ncp_vdbg("result=%d\n", error);
+       return ERR_PTR(error);
+}
+
+/*
+ * This code is common to create, mkdir, and mknod.
+ */
+static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
+                       struct ncp_entry_info *finfo)
+{
+       struct inode *inode;
+       int error = -EINVAL;
+
+       finfo->ino = iunique(dir->i_sb, 2);
+       inode = ncp_iget(dir->i_sb, finfo);
+       if (!inode)
+               goto out_close;
+       d_instantiate(dentry,inode);
+       error = 0;
+out:
+       return error;
+
+out_close:
+       ncp_vdbg("%pd2 failed, closing file\n", dentry);
+       ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
+       goto out;
+}
+
+int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
+                  dev_t rdev, __le32 attributes)
+{
+       struct ncp_server *server = NCP_SERVER(dir);
+       struct ncp_entry_info finfo;
+       int error, result, len;
+       int opmode;
+       __u8 __name[NCP_MAXPATHLEN + 1];
+       
+       ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode);
+
+       ncp_age_dentry(server, dentry);
+       len = sizeof(__name);
+       error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+                          dentry->d_name.len, !ncp_preserve_case(dir));
+       if (error)
+               goto out;
+
+       error = -EACCES;
+       
+       if (S_ISREG(mode) && 
+           (server->m.flags & NCP_MOUNT_EXTRAS) && 
+           (mode & S_IXUGO))
+               attributes |= aSYSTEM | aSHARED;
+       
+       result = ncp_open_create_file_or_subdir(server, dir, __name,
+                               OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
+                               attributes, AR_READ | AR_WRITE, &finfo);
+       opmode = O_RDWR;
+       if (result) {
+               result = ncp_open_create_file_or_subdir(server, dir, __name,
+                               OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
+                               attributes, AR_WRITE, &finfo);
+               if (result) {
+                       if (result == 0x87)
+                               error = -ENAMETOOLONG;
+                       else if (result < 0)
+                               error = result;
+                       ncp_dbg(1, "%pd2 failed\n", dentry);
+                       goto out;
+               }
+               opmode = O_WRONLY;
+       }
+       finfo.access = opmode;
+       if (ncp_is_nfs_extras(server, finfo.volume)) {
+               finfo.i.nfs.mode = mode;
+               finfo.i.nfs.rdev = new_encode_dev(rdev);
+               if (ncp_modify_nfs_info(server, finfo.volume,
+                                       finfo.i.dirEntNum,
+                                       mode, new_encode_dev(rdev)) != 0)
+                       goto out;
+       }
+
+       error = ncp_instantiate(dir, dentry, &finfo);
+out:
+       return error;
+}
+
+static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+               bool excl)
+{
+       return ncp_create_new(dir, dentry, mode, 0, 0);
+}
+
+static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+       struct ncp_entry_info finfo;
+       struct ncp_server *server = NCP_SERVER(dir);
+       int error, len;
+       __u8 __name[NCP_MAXPATHLEN + 1];
+
+       ncp_dbg(1, "making %pd2\n", dentry);
+
+       ncp_age_dentry(server, dentry);
+       len = sizeof(__name);
+       error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+                          dentry->d_name.len, !ncp_preserve_case(dir));
+       if (error)
+               goto out;
+
+       error = ncp_open_create_file_or_subdir(server, dir, __name,
+                                          OC_MODE_CREATE, aDIR,
+                                          cpu_to_le16(0xffff),
+                                          &finfo);
+       if (error == 0) {
+               if (ncp_is_nfs_extras(server, finfo.volume)) {
+                       mode |= S_IFDIR;
+                       finfo.i.nfs.mode = mode;
+                       if (ncp_modify_nfs_info(server,
+                                               finfo.volume,
+                                               finfo.i.dirEntNum,
+                                               mode, 0) != 0)
+                               goto out;
+               }
+               error = ncp_instantiate(dir, dentry, &finfo);
+       } else if (error > 0) {
+               error = -EACCES;
+       }
+out:
+       return error;
+}
+
+static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
+{
+       struct ncp_server *server = NCP_SERVER(dir);
+       int error, result, len;
+       __u8 __name[NCP_MAXPATHLEN + 1];
+
+       ncp_dbg(1, "removing %pd2\n", dentry);
+
+       len = sizeof(__name);
+       error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+                          dentry->d_name.len, !ncp_preserve_case(dir));
+       if (error)
+               goto out;
+
+       result = ncp_del_file_or_subdir(server, dir, __name);
+       switch (result) {
+               case 0x00:
+                       error = 0;
+                       break;
+               case 0x85:      /* unauthorized to delete file */
+               case 0x8A:      /* unauthorized to delete file */
+                       error = -EACCES;
+                       break;
+               case 0x8F:
+               case 0x90:      /* read only */
+                       error = -EPERM;
+                       break;
+               case 0x9F:      /* in use by another client */
+                       error = -EBUSY;
+                       break;
+               case 0xA0:      /* directory not empty */
+                       error = -ENOTEMPTY;
+                       break;
+               case 0xFF:      /* someone deleted file */
+                       error = -ENOENT;
+                       break;
+               default:
+                       error = result < 0 ? result : -EACCES;
+                       break;
+               }
+out:
+       return error;
+}
+
+static int ncp_unlink(struct inode *dir, struct dentry *dentry)
+{
+       struct inode *inode = d_inode(dentry);
+       struct ncp_server *server;
+       int error;
+
+       server = NCP_SERVER(dir);
+       ncp_dbg(1, "unlinking %pd2\n", dentry);
+       
+       /*
+        * Check whether to close the file ...
+        */
+       if (inode) {
+               ncp_vdbg("closing file\n");
+               ncp_make_closed(inode);
+       }
+
+       error = ncp_del_file_or_subdir2(server, dentry);
+#ifdef CONFIG_NCPFS_STRONG
+       /* 9C is Invalid path.. It should be 8F, 90 - read only, but
+          it is not :-( */
+       if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
+               error = ncp_force_unlink(dir, dentry);
+       }
+#endif
+       switch (error) {
+               case 0x00:
+                       ncp_dbg(1, "removed %pd2\n", dentry);
+                       break;
+               case 0x85:
+               case 0x8A:
+                       error = -EACCES;
+                       break;
+               case 0x8D:      /* some files in use */
+               case 0x8E:      /* all files in use */
+                       error = -EBUSY;
+                       break;
+               case 0x8F:      /* some read only */
+               case 0x90:      /* all read only */
+               case 0x9C:      /* !!! returned when in-use or read-only by NW4 */
+                       error = -EPERM;
+                       break;
+               case 0xFF:
+                       error = -ENOENT;
+                       break;
+               default:
+                       error = error < 0 ? error : -EACCES;
+                       break;
+       }
+       return error;
+}
+
+static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
+                     struct inode *new_dir, struct dentry *new_dentry,
+                     unsigned int flags)
+{
+       struct ncp_server *server = NCP_SERVER(old_dir);
+       int error;
+       int old_len, new_len;
+       __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
+
+       if (flags)
+               return -EINVAL;
+
+       ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry);
+
+       ncp_age_dentry(server, old_dentry);
+       ncp_age_dentry(server, new_dentry);
+
+       old_len = sizeof(__old_name);
+       error = ncp_io2vol(server, __old_name, &old_len,
+                          old_dentry->d_name.name, old_dentry->d_name.len,
+                          !ncp_preserve_case(old_dir));
+       if (error)
+               goto out;
+
+       new_len = sizeof(__new_name);
+       error = ncp_io2vol(server, __new_name, &new_len,
+                          new_dentry->d_name.name, new_dentry->d_name.len,
+                          !ncp_preserve_case(new_dir));
+       if (error)
+               goto out;
+
+       error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
+                                                     new_dir, __new_name);
+#ifdef CONFIG_NCPFS_STRONG
+       if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
+                       server->m.flags & NCP_MOUNT_STRONG) {   /* RO */
+               error = ncp_force_rename(old_dir, old_dentry, __old_name,
+                                        new_dir, new_dentry, __new_name);
+       }
+#endif
+       switch (error) {
+               case 0x00:
+                       ncp_dbg(1, "renamed %pd -> %pd\n",
+                               old_dentry, new_dentry);
+                       ncp_d_prune(old_dentry);
+                       ncp_d_prune(new_dentry);
+                       break;
+               case 0x9E:
+                       error = -ENAMETOOLONG;
+                       break;
+               case 0xFF:
+                       error = -ENOENT;
+                       break;
+               default:
+                       error = error < 0 ? error : -EACCES;
+                       break;
+       }
+out:
+       return error;
+}
+
+static int ncp_mknod(struct inode * dir, struct dentry *dentry,
+                    umode_t mode, dev_t rdev)
+{
+       if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
+               ncp_dbg(1, "mode = 0%ho\n", mode);
+               return ncp_create_new(dir, dentry, mode, rdev, 0);
+       }
+       return -EPERM; /* Strange, but true */
+}
+
+/* The following routines are taken directly from msdos-fs */
+
+/* Linear day numbers of the respective 1sts in non-leap years. */
+
+static int day_n[] =
+{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
+/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
+
+static int utc2local(int time)
+{
+       return time - sys_tz.tz_minuteswest * 60;
+}
+
+static int local2utc(int time)
+{
+       return time + sys_tz.tz_minuteswest * 60;
+}
+
+/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
+int
+ncp_date_dos2unix(__le16 t, __le16 d)
+{
+       unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
+       int month, year, secs;
+
+       /* first subtract and mask after that... Otherwise, if
+          date == 0, bad things happen */
+       month = ((date >> 5) - 1) & 15;
+       year = date >> 9;
+       secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
+               86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 
+               year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
+       /* days since 1.1.70 plus 80's leap day */
+       return local2utc(secs);
+}
+
+
+/* Convert linear UNIX date to a MS-DOS time/date pair. */
+void
+ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
+{
+       int day, year, nl_day, month;
+
+       unix_date = utc2local(unix_date);
+       *time = cpu_to_le16(
+               (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
+               (((unix_date / 3600) % 24) << 11));
+       day = unix_date / 86400 - 3652;
+       year = day / 365;
+       if ((year + 3) / 4 + 365 * year > day)
+               year--;
+       day -= (year + 3) / 4 + 365 * year;
+       if (day == 59 && !(year & 3)) {
+               nl_day = day;
+               month = 2;
+       } else {
+               nl_day = (year & 3) || day <= 59 ? day : day - 1;
+               for (month = 1; month < 12; month++)
+                       if (day_n[month] > nl_day)
+                               break;
+       }
+       *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
+}
diff --git a/drivers/staging/ncpfs/file.c b/drivers/staging/ncpfs/file.c
new file mode 100644 (file)
index 0000000..8f8cc03
--- /dev/null
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  file.c
+ *
+ *  Copyright (C) 1995, 1996 by Volker Lendecke
+ *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/uaccess.h>
+
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+
+#include "ncp_fs.h"
+
+static int ncp_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+       return file_write_and_wait_range(file, start, end);
+}
+
+/*
+ * Open a file with the specified read/write mode.
+ */
+int ncp_make_open(struct inode *inode, int right)
+{
+       int error;
+       int access;
+
+       error = -EINVAL;
+       if (!inode) {
+               pr_err("%s: got NULL inode\n", __func__);
+               goto out;
+       }
+
+       ncp_dbg(1, "opened=%d, volume # %u, dir entry # %u\n",
+               atomic_read(&NCP_FINFO(inode)->opened), 
+               NCP_FINFO(inode)->volNumber, 
+               NCP_FINFO(inode)->dirEntNum);
+       error = -EACCES;
+       mutex_lock(&NCP_FINFO(inode)->open_mutex);
+       if (!atomic_read(&NCP_FINFO(inode)->opened)) {
+               struct ncp_entry_info finfo;
+               int result;
+
+               /* tries max. rights */
+               finfo.access = O_RDWR;
+               result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
+                                       inode, NULL, OC_MODE_OPEN,
+                                       0, AR_READ | AR_WRITE, &finfo);
+               if (!result)
+                       goto update;
+               /* RDWR did not succeeded, try readonly or writeonly as requested */
+               switch (right) {
+                       case O_RDONLY:
+                               finfo.access = O_RDONLY;
+                               result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
+                                       inode, NULL, OC_MODE_OPEN,
+                                       0, AR_READ, &finfo);
+                               break;
+                       case O_WRONLY:
+                               finfo.access = O_WRONLY;
+                               result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
+                                       inode, NULL, OC_MODE_OPEN,
+                                       0, AR_WRITE, &finfo);
+                               break;
+               }
+               if (result) {
+                       ncp_vdbg("failed, result=%d\n", result);
+                       goto out_unlock;
+               }
+               /*
+                * Update the inode information.
+                */
+       update:
+               ncp_update_inode(inode, &finfo);
+               atomic_set(&NCP_FINFO(inode)->opened, 1);
+       }
+
+       access = NCP_FINFO(inode)->access;
+       ncp_vdbg("file open, access=%x\n", access);
+       if (access == right || access == O_RDWR) {
+               atomic_inc(&NCP_FINFO(inode)->opened);
+               error = 0;
+       }
+
+out_unlock:
+       mutex_unlock(&NCP_FINFO(inode)->open_mutex);
+out:
+       return error;
+}
+
+static ssize_t
+ncp_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = file_inode(file);
+       size_t already_read = 0;
+       off_t pos = iocb->ki_pos;
+       size_t bufsize;
+       int error;
+       void *freepage;
+       size_t freelen;
+
+       ncp_dbg(1, "enter %pD2\n", file);
+
+       if (!iov_iter_count(to))
+               return 0;
+       if (pos > inode->i_sb->s_maxbytes)
+               return 0;
+       iov_iter_truncate(to, inode->i_sb->s_maxbytes - pos);
+
+       error = ncp_make_open(inode, O_RDONLY);
+       if (error) {
+               ncp_dbg(1, "open failed, error=%d\n", error);
+               return error;
+       }
+
+       bufsize = NCP_SERVER(inode)->buffer_size;
+
+       error = -EIO;
+       freelen = ncp_read_bounce_size(bufsize);
+       freepage = vmalloc(freelen);
+       if (!freepage)
+               goto outrel;
+       error = 0;
+       /* First read in as much as possible for each bufsize. */
+       while (iov_iter_count(to)) {
+               int read_this_time;
+               size_t to_read = min_t(size_t,
+                                    bufsize - (pos % bufsize),
+                                    iov_iter_count(to));
+
+               error = ncp_read_bounce(NCP_SERVER(inode),
+                               NCP_FINFO(inode)->file_handle,
+                               pos, to_read, to, &read_this_time, 
+                               freepage, freelen);
+               if (error) {
+                       error = -EIO;   /* NW errno -> Linux errno */
+                       break;
+               }
+               pos += read_this_time;
+               already_read += read_this_time;
+
+               if (read_this_time != to_read)
+                       break;
+       }
+       vfree(freepage);
+
+       iocb->ki_pos = pos;
+
+       file_accessed(file);
+
+       ncp_dbg(1, "exit %pD2\n", file);
+outrel:
+       ncp_inode_close(inode);         
+       return already_read ? already_read : error;
+}
+
+static ssize_t
+ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = file_inode(file);
+       size_t already_written = 0;
+       size_t bufsize;
+       int errno;
+       void *bouncebuffer;
+       off_t pos;
+
+       ncp_dbg(1, "enter %pD2\n", file);
+       errno = generic_write_checks(iocb, from);
+       if (errno <= 0)
+               return errno;
+
+       errno = ncp_make_open(inode, O_WRONLY);
+       if (errno) {
+               ncp_dbg(1, "open failed, error=%d\n", errno);
+               return errno;
+       }
+       bufsize = NCP_SERVER(inode)->buffer_size;
+
+       errno = file_update_time(file);
+       if (errno)
+               goto outrel;
+
+       bouncebuffer = vmalloc(bufsize);
+       if (!bouncebuffer) {
+               errno = -EIO;   /* -ENOMEM */
+               goto outrel;
+       }
+       pos = iocb->ki_pos;
+       while (iov_iter_count(from)) {
+               int written_this_time;
+               size_t to_write = min_t(size_t,
+                                     bufsize - (pos % bufsize),
+                                     iov_iter_count(from));
+
+               if (!copy_from_iter_full(bouncebuffer, to_write, from)) {
+                       errno = -EFAULT;
+                       break;
+               }
+               if (ncp_write_kernel(NCP_SERVER(inode), 
+                   NCP_FINFO(inode)->file_handle,
+                   pos, to_write, bouncebuffer, &written_this_time) != 0) {
+                       errno = -EIO;
+                       break;
+               }
+               pos += written_this_time;
+               already_written += written_this_time;
+
+               if (written_this_time != to_write)
+                       break;
+       }
+       vfree(bouncebuffer);
+
+       iocb->ki_pos = pos;
+
+       if (pos > i_size_read(inode)) {
+               inode_lock(inode);
+               if (pos > i_size_read(inode))
+                       i_size_write(inode, pos);
+               inode_unlock(inode);
+       }
+       ncp_dbg(1, "exit %pD2\n", file);
+outrel:
+       ncp_inode_close(inode);         
+       return already_written ? already_written : errno;
+}
+
+static int ncp_release(struct inode *inode, struct file *file) {
+       if (ncp_make_closed(inode)) {
+               ncp_dbg(1, "failed to close\n");
+       }
+       return 0;
+}
+
+const struct file_operations ncp_file_operations =
+{
+       .llseek         = generic_file_llseek,
+       .read_iter      = ncp_file_read_iter,
+       .write_iter     = ncp_file_write_iter,
+       .unlocked_ioctl = ncp_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ncp_compat_ioctl,
+#endif
+       .mmap           = ncp_mmap,
+       .release        = ncp_release,
+       .fsync          = ncp_fsync,
+};
+
+const struct inode_operations ncp_file_inode_operations =
+{
+       .setattr        = ncp_notify_change,
+};
diff --git a/drivers/staging/ncpfs/getopt.c b/drivers/staging/ncpfs/getopt.c
new file mode 100644 (file)
index 0000000..5c941be
--- /dev/null
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * getopt.c
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/errno.h>
+
+#include "getopt.h"
+
+/**
+ *     ncp_getopt - option parser
+ *     @caller: name of the caller, for error messages
+ *     @options: the options string
+ *     @opts: an array of &struct option entries controlling parser operations
+ *     @optopt: output; will contain the current option
+ *     @optarg: output; will contain the value (if one exists)
+ *     @value: output; may be NULL; will be overwritten with the integer value
+ *             of the current argument.
+ *
+ *     Helper to parse options on the format used by mount ("a=b,c=d,e,f").
+ *     Returns opts->val if a matching entry in the 'opts' array is found,
+ *     0 when no more tokens are found, -1 if an error is encountered.
+ */
+int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts,
+              char **optopt, char **optarg, unsigned long *value)
+{
+       char *token;
+       char *val;
+
+       do {
+               if ((token = strsep(options, ",")) == NULL)
+                       return 0;
+       } while (*token == '\0');
+       if (optopt)
+               *optopt = token;
+
+       if ((val = strchr (token, '=')) != NULL) {
+               *val++ = 0;
+       }
+       *optarg = val;
+       for (; opts->name; opts++) {
+               if (!strcmp(opts->name, token)) {
+                       if (!val) {
+                               if (opts->has_arg & OPT_NOPARAM) {
+                                       return opts->val;
+                               }
+                               pr_info("%s: the %s option requires an argument\n",
+                                       caller, token);
+                               return -EINVAL;
+                       }
+                       if (opts->has_arg & OPT_INT) {
+                               int rc = kstrtoul(val, 0, value);
+
+                               if (rc) {
+                                       pr_info("%s: invalid numeric value in %s=%s\n",
+                                               caller, token, val);
+                                       return rc;
+                               }
+                               return opts->val;
+                       }
+                       if (opts->has_arg & OPT_STRING) {
+                               return opts->val;
+                       }
+                       pr_info("%s: unexpected argument %s to the %s option\n",
+                               caller, val, token);
+                       return -EINVAL;
+               }
+       }
+       pr_info("%s: Unrecognized mount option %s\n", caller, token);
+       return -EOPNOTSUPP;
+}
diff --git a/drivers/staging/ncpfs/getopt.h b/drivers/staging/ncpfs/getopt.h
new file mode 100644 (file)
index 0000000..30f0da3
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_GETOPT_H
+#define _LINUX_GETOPT_H
+
+#define OPT_NOPARAM    1
+#define OPT_INT                2
+#define OPT_STRING     4
+struct ncp_option {
+       const char *name;
+       unsigned int has_arg;
+       int val;
+};
+
+extern int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts,
+                     char **optopt, char **optarg, unsigned long *value);
+
+#endif /* _LINUX_GETOPT_H */
diff --git a/drivers/staging/ncpfs/inode.c b/drivers/staging/ncpfs/inode.c
new file mode 100644 (file)
index 0000000..bb41161
--- /dev/null
@@ -0,0 +1,1067 @@
+/*
+ *  inode.c
+ *
+ *  Copyright (C) 1995, 1996 by Volker Lendecke
+ *  Modified for big endian by J.F. Chadima and David S. Miller
+ *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *  Modified 1998 Wolfram Pienkoss for NLS
+ *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+
+#include <linux/uaccess.h>
+#include <asm/byteorder.h>
+
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/vfs.h>
+#include <linux/mount.h>
+#include <linux/seq_file.h>
+#include <linux/sched/signal.h>
+#include <linux/namei.h>
+
+#include <net/sock.h>
+
+#include "ncp_fs.h"
+#include "getopt.h"
+
+#define NCP_DEFAULT_FILE_MODE 0600
+#define NCP_DEFAULT_DIR_MODE 0700
+#define NCP_DEFAULT_TIME_OUT 10
+#define NCP_DEFAULT_RETRY_COUNT 20
+
+static void ncp_evict_inode(struct inode *);
+static void ncp_put_super(struct super_block *);
+static int  ncp_statfs(struct dentry *, struct kstatfs *);
+static int  ncp_show_options(struct seq_file *, struct dentry *);
+
+static struct kmem_cache * ncp_inode_cachep;
+
+static struct inode *ncp_alloc_inode(struct super_block *sb)
+{
+       struct ncp_inode_info *ei;
+
+       ei = kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
+       if (!ei)
+               return NULL;
+       return &ei->vfs_inode;
+}
+
+static void ncp_i_callback(struct rcu_head *head)
+{
+       struct inode *inode = container_of(head, struct inode, i_rcu);
+       kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
+}
+
+static void ncp_destroy_inode(struct inode *inode)
+{
+       call_rcu(&inode->i_rcu, ncp_i_callback);
+}
+
+static void init_once(void *foo)
+{
+       struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
+
+       mutex_init(&ei->open_mutex);
+       inode_init_once(&ei->vfs_inode);
+}
+
+static int init_inodecache(void)
+{
+       ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
+                                            sizeof(struct ncp_inode_info),
+                                            0, (SLAB_RECLAIM_ACCOUNT|
+                                               SLAB_MEM_SPREAD|SLAB_ACCOUNT),
+                                            init_once);
+       if (ncp_inode_cachep == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+static void destroy_inodecache(void)
+{
+       /*
+        * Make sure all delayed rcu free inodes are flushed before we
+        * destroy cache.
+        */
+       rcu_barrier();
+       kmem_cache_destroy(ncp_inode_cachep);
+}
+
+static int ncp_remount(struct super_block *sb, int *flags, char* data)
+{
+       sync_filesystem(sb);
+       *flags |= SB_NODIRATIME;
+       return 0;
+}
+
+static const struct super_operations ncp_sops =
+{
+       .alloc_inode    = ncp_alloc_inode,
+       .destroy_inode  = ncp_destroy_inode,
+       .drop_inode     = generic_delete_inode,
+       .evict_inode    = ncp_evict_inode,
+       .put_super      = ncp_put_super,
+       .statfs         = ncp_statfs,
+       .remount_fs     = ncp_remount,
+       .show_options   = ncp_show_options,
+};
+
+/*
+ * Fill in the ncpfs-specific information in the inode.
+ */
+static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
+{
+       NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
+       NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
+       NCP_FINFO(inode)->volNumber = nwinfo->volume;
+}
+
+void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
+{
+       ncp_update_dirent(inode, nwinfo);
+       NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
+       NCP_FINFO(inode)->access = nwinfo->access;
+       memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
+                       sizeof(nwinfo->file_handle));
+       ncp_dbg(1, "updated %s, volnum=%d, dirent=%u\n",
+               nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
+               NCP_FINFO(inode)->dirEntNum);
+}
+
+static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
+{
+       /* NFS namespace mode overrides others if it's set. */
+       ncp_dbg(1, "(%s) nfs.mode=0%o\n", nwi->entryName, nwi->nfs.mode);
+       if (nwi->nfs.mode) {
+               /* XXX Security? */
+               inode->i_mode = nwi->nfs.mode;
+       }
+
+       inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
+
+       inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
+       inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
+       inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
+       inode->i_atime.tv_nsec = 0;
+       inode->i_mtime.tv_nsec = 0;
+       inode->i_ctime.tv_nsec = 0;
+}
+
+static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
+{
+       struct nw_info_struct *nwi = &nwinfo->i;
+       struct ncp_server *server = NCP_SERVER(inode);
+
+       if (nwi->attributes & aDIR) {
+               inode->i_mode = server->m.dir_mode;
+               /* for directories dataStreamSize seems to be some
+                  Object ID ??? */
+               i_size_write(inode, NCP_BLOCK_SIZE);
+       } else {
+               u32 size;
+
+               inode->i_mode = server->m.file_mode;
+               size = le32_to_cpu(nwi->dataStreamSize);
+               i_size_write(inode, size);
+#ifdef CONFIG_NCPFS_EXTRAS
+               if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
+                && (nwi->attributes & aSHARED)) {
+                       switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
+                               case aHIDDEN:
+                                       if (server->m.flags & NCP_MOUNT_SYMLINKS) {
+                                               if (/* (size >= NCP_MIN_SYMLINK_SIZE)
+                                                && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
+                                                       inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
+                                                       NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
+                                                       break;
+                                               }
+                                       }
+                                       /* FALLTHROUGH */
+                               case 0:
+                                       if (server->m.flags & NCP_MOUNT_EXTRAS)
+                                               inode->i_mode |= S_IRUGO;
+                                       break;
+                               case aSYSTEM:
+                                       if (server->m.flags & NCP_MOUNT_EXTRAS)
+                                               inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
+                                       break;
+                               /* case aSYSTEM|aHIDDEN: */
+                               default:
+                                       /* reserved combination */
+                                       break;
+                       }
+               }
+#endif
+       }
+       if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
+}
+
+void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
+{
+       NCP_FINFO(inode)->flags = 0;
+       if (!atomic_read(&NCP_FINFO(inode)->opened)) {
+               NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
+               ncp_update_attrs(inode, nwinfo);
+       }
+
+       ncp_update_dates(inode, &nwinfo->i);
+       ncp_update_dirent(inode, nwinfo);
+}
+
+/*
+ * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
+ */
+static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
+{
+       struct ncp_server *server = NCP_SERVER(inode);
+
+       NCP_FINFO(inode)->flags = 0;
+       
+       ncp_update_attrs(inode, nwinfo);
+
+       ncp_dbg(2, "inode->i_mode = %u\n", inode->i_mode);
+
+       set_nlink(inode, 1);
+       inode->i_uid = server->m.uid;
+       inode->i_gid = server->m.gid;
+
+       ncp_update_dates(inode, &nwinfo->i);
+       ncp_update_inode(inode, nwinfo);
+}
+
+#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
+static const struct inode_operations ncp_symlink_inode_operations = {
+       .get_link       = page_get_link,
+       .setattr        = ncp_notify_change,
+};
+#endif
+
+/*
+ * Get a new inode.
+ */
+struct inode * 
+ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
+{
+       struct inode *inode;
+
+       if (info == NULL) {
+               pr_err("%s: info is NULL\n", __func__);
+               return NULL;
+       }
+
+       inode = new_inode(sb);
+       if (inode) {
+               atomic_set(&NCP_FINFO(inode)->opened, info->opened);
+
+               inode->i_ino = info->ino;
+               ncp_set_attr(inode, info);
+               if (S_ISREG(inode->i_mode)) {
+                       inode->i_op = &ncp_file_inode_operations;
+                       inode->i_fop = &ncp_file_operations;
+               } else if (S_ISDIR(inode->i_mode)) {
+                       inode->i_op = &ncp_dir_inode_operations;
+                       inode->i_fop = &ncp_dir_operations;
+#ifdef CONFIG_NCPFS_NFS_NS
+               } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
+                       init_special_inode(inode, inode->i_mode,
+                               new_decode_dev(info->i.nfs.rdev));
+#endif
+#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
+               } else if (S_ISLNK(inode->i_mode)) {
+                       inode->i_op = &ncp_symlink_inode_operations;
+                       inode_nohighmem(inode);
+                       inode->i_data.a_ops = &ncp_symlink_aops;
+#endif
+               } else {
+                       make_bad_inode(inode);
+               }
+               insert_inode_hash(inode);
+       } else
+               pr_err("%s: iget failed!\n", __func__);
+       return inode;
+}
+
+static void
+ncp_evict_inode(struct inode *inode)
+{
+       truncate_inode_pages_final(&inode->i_data);
+       clear_inode(inode);
+
+       if (S_ISDIR(inode->i_mode)) {
+               ncp_dbg(2, "put directory %ld\n", inode->i_ino);
+       }
+
+       if (ncp_make_closed(inode) != 0) {
+               /* We can't do anything but complain. */
+               pr_err("%s: could not close\n", __func__);
+       }
+}
+
+static void ncp_stop_tasks(struct ncp_server *server) {
+       struct sock* sk = server->ncp_sock->sk;
+
+       lock_sock(sk);
+       sk->sk_error_report = server->error_report;
+       sk->sk_data_ready   = server->data_ready;
+       sk->sk_write_space  = server->write_space;
+       release_sock(sk);
+       del_timer_sync(&server->timeout_tm);
+
+       flush_work(&server->rcv.tq);
+       if (sk->sk_socket->type == SOCK_STREAM)
+               flush_work(&server->tx.tq);
+       else
+               flush_work(&server->timeout_tq);
+}
+
+static int  ncp_show_options(struct seq_file *seq, struct dentry *root)
+{
+       struct ncp_server *server = NCP_SBP(root->d_sb);
+       unsigned int tmp;
+
+       if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID))
+               seq_printf(seq, ",uid=%u",
+                          from_kuid_munged(&init_user_ns, server->m.uid));
+       if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID))
+               seq_printf(seq, ",gid=%u",
+                          from_kgid_munged(&init_user_ns, server->m.gid));
+       if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID))
+               seq_printf(seq, ",owner=%u",
+                          from_kuid_munged(&init_user_ns, server->m.mounted_uid));
+       tmp = server->m.file_mode & S_IALLUGO;
+       if (tmp != NCP_DEFAULT_FILE_MODE)
+               seq_printf(seq, ",mode=0%o", tmp);
+       tmp = server->m.dir_mode & S_IALLUGO;
+       if (tmp != NCP_DEFAULT_DIR_MODE)
+               seq_printf(seq, ",dirmode=0%o", tmp);
+       if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
+               tmp = server->m.time_out * 100 / HZ;
+               seq_printf(seq, ",timeout=%u", tmp);
+       }
+       if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
+               seq_printf(seq, ",retry=%u", server->m.retry_count);
+       if (server->m.flags != 0)
+               seq_printf(seq, ",flags=%lu", server->m.flags);
+       if (server->m.wdog_pid != NULL)
+               seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
+
+       return 0;
+}
+
+static const struct ncp_option ncp_opts[] = {
+       { "uid",        OPT_INT,        'u' },
+       { "gid",        OPT_INT,        'g' },
+       { "owner",      OPT_INT,        'o' },
+       { "mode",       OPT_INT,        'm' },
+       { "dirmode",    OPT_INT,        'd' },
+       { "timeout",    OPT_INT,        't' },
+       { "retry",      OPT_INT,        'r' },
+       { "flags",      OPT_INT,        'f' },
+       { "wdogpid",    OPT_INT,        'w' },
+       { "ncpfd",      OPT_INT,        'n' },
+       { "infofd",     OPT_INT,        'i' },  /* v5 */
+       { "version",    OPT_INT,        'v' },
+       { NULL,         0,              0 } };
+
+static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
+       int optval;
+       char *optarg;
+       unsigned long optint;
+       int version = 0;
+       int ret;
+
+       data->flags = 0;
+       data->int_flags = 0;
+       data->mounted_uid = GLOBAL_ROOT_UID;
+       data->wdog_pid = NULL;
+       data->ncp_fd = ~0;
+       data->time_out = NCP_DEFAULT_TIME_OUT;
+       data->retry_count = NCP_DEFAULT_RETRY_COUNT;
+       data->uid = GLOBAL_ROOT_UID;
+       data->gid = GLOBAL_ROOT_GID;
+       data->file_mode = NCP_DEFAULT_FILE_MODE;
+       data->dir_mode = NCP_DEFAULT_DIR_MODE;
+       data->info_fd = -1;
+       data->mounted_vol[0] = 0;
+       
+       while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
+               ret = optval;
+               if (ret < 0)
+                       goto err;
+               switch (optval) {
+                       case 'u':
+                               data->uid = make_kuid(current_user_ns(), optint);
+                               if (!uid_valid(data->uid)) {
+                                       ret = -EINVAL;
+                                       goto err;
+                               }
+                               break;
+                       case 'g':
+                               data->gid = make_kgid(current_user_ns(), optint);
+                               if (!gid_valid(data->gid)) {
+                                       ret = -EINVAL;
+                                       goto err;
+                               }
+                               break;
+                       case 'o':
+                               data->mounted_uid = make_kuid(current_user_ns(), optint);
+                               if (!uid_valid(data->mounted_uid)) {
+                                       ret = -EINVAL;
+                                       goto err;
+                               }
+                               break;
+                       case 'm':
+                               data->file_mode = optint;
+                               break;
+                       case 'd':
+                               data->dir_mode = optint;
+                               break;
+                       case 't':
+                               data->time_out = optint;
+                               break;
+                       case 'r':
+                               data->retry_count = optint;
+                               break;
+                       case 'f':
+                               data->flags = optint;
+                               break;
+                       case 'w':
+                               data->wdog_pid = find_get_pid(optint);
+                               break;
+                       case 'n':
+                               data->ncp_fd = optint;
+                               break;
+                       case 'i':
+                               data->info_fd = optint;
+                               break;
+                       case 'v':
+                               ret = -ECHRNG;
+                               if (optint < NCP_MOUNT_VERSION_V4)
+                                       goto err;
+                               if (optint > NCP_MOUNT_VERSION_V5)
+                                       goto err;
+                               version = optint;
+                               break;
+                       
+               }
+       }
+       return 0;
+err:
+       put_pid(data->wdog_pid);
+       data->wdog_pid = NULL;
+       return ret;
+}
+
+static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
+{
+       struct ncp_mount_data_kernel data;
+       struct ncp_server *server;
+       struct inode *root_inode;
+       struct socket *sock;
+       int error;
+       int default_bufsize;
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+       int options;
+#endif
+       struct ncp_entry_info finfo;
+
+       memset(&data, 0, sizeof(data));
+       server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
+       if (!server)
+               return -ENOMEM;
+       sb->s_fs_info = server;
+
+       error = -EFAULT;
+       if (raw_data == NULL)
+               goto out;
+       switch (*(int*)raw_data) {
+               case NCP_MOUNT_VERSION:
+                       {
+                               struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
+
+                               data.flags = md->flags;
+                               data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
+                               data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
+                               data.wdog_pid = find_get_pid(md->wdog_pid);
+                               data.ncp_fd = md->ncp_fd;
+                               data.time_out = md->time_out;
+                               data.retry_count = md->retry_count;
+                               data.uid = make_kuid(current_user_ns(), md->uid);
+                               data.gid = make_kgid(current_user_ns(), md->gid);
+                               data.file_mode = md->file_mode;
+                               data.dir_mode = md->dir_mode;
+                               data.info_fd = -1;
+                               memcpy(data.mounted_vol, md->mounted_vol,
+                                       NCP_VOLNAME_LEN+1);
+                       }
+                       break;
+               case NCP_MOUNT_VERSION_V4:
+                       {
+                               struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
+
+                               data.flags = md->flags;
+                               data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
+                               data.wdog_pid = find_get_pid(md->wdog_pid);
+                               data.ncp_fd = md->ncp_fd;
+                               data.time_out = md->time_out;
+                               data.retry_count = md->retry_count;
+                               data.uid = make_kuid(current_user_ns(), md->uid);
+                               data.gid = make_kgid(current_user_ns(), md->gid);
+                               data.file_mode = md->file_mode;
+                               data.dir_mode = md->dir_mode;
+                               data.info_fd = -1;
+                       }
+                       break;
+               default:
+                       error = -ECHRNG;
+                       if (memcmp(raw_data, "vers", 4) == 0) {
+                               error = ncp_parse_options(&data, raw_data);
+                       }
+                       if (error)
+                               goto out;
+                       break;
+       }
+       error = -EINVAL;
+       if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) ||
+           !gid_valid(data.gid))
+               goto out;
+       sock = sockfd_lookup(data.ncp_fd, &error);
+       if (!sock)
+               goto out;
+
+       if (sock->type == SOCK_STREAM)
+               default_bufsize = 0xF000;
+       else
+               default_bufsize = 1024;
+
+       sb->s_flags |= SB_NODIRATIME;   /* probably even noatime */
+       sb->s_maxbytes = 0xFFFFFFFFU;
+       sb->s_blocksize = 1024; /* Eh...  Is this correct? */
+       sb->s_blocksize_bits = 10;
+       sb->s_magic = NCP_SUPER_MAGIC;
+       sb->s_op = &ncp_sops;
+       sb->s_d_op = &ncp_dentry_operations;
+
+       server = NCP_SBP(sb);
+       memset(server, 0, sizeof(*server));
+
+       error = super_setup_bdi(sb);
+       if (error)
+               goto out_fput;
+
+       server->ncp_sock = sock;
+       
+       if (data.info_fd != -1) {
+               struct socket *info_sock = sockfd_lookup(data.info_fd, &error);
+               if (!info_sock)
+                       goto out_fput;
+               server->info_sock = info_sock;
+               error = -EBADFD;
+               if (info_sock->type != SOCK_STREAM)
+                       goto out_fput2;
+       }
+
+/*     server->lock = 0;       */
+       mutex_init(&server->mutex);
+       server->packet = NULL;
+/*     server->buffer_size = 0;        */
+/*     server->conn_status = 0;        */
+/*     server->root_dentry = NULL;     */
+/*     server->root_setuped = 0;       */
+       mutex_init(&server->root_setup_lock);
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+/*     server->sign_wanted = 0;        */
+/*     server->sign_active = 0;        */
+#endif
+       init_rwsem(&server->auth_rwsem);
+       server->auth.auth_type = NCP_AUTH_NONE;
+/*     server->auth.object_name_len = 0;       */
+/*     server->auth.object_name = NULL;        */
+/*     server->auth.object_type = 0;           */
+/*     server->priv.len = 0;                   */
+/*     server->priv.data = NULL;               */
+
+       server->m = data;
+       /* Although anything producing this is buggy, it happens
+          now because of PATH_MAX changes.. */
+       if (server->m.time_out < 1) {
+               server->m.time_out = 10;
+               pr_info("You need to recompile your ncpfs utils..\n");
+       }
+       server->m.time_out = server->m.time_out * HZ / 100;
+       server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
+       server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
+
+#ifdef CONFIG_NCPFS_NLS
+       /* load the default NLS charsets */
+       server->nls_vol = load_nls_default();
+       server->nls_io = load_nls_default();
+#endif /* CONFIG_NCPFS_NLS */
+
+       atomic_set(&server->dentry_ttl, 0);     /* no caching */
+
+       INIT_LIST_HEAD(&server->tx.requests);
+       mutex_init(&server->rcv.creq_mutex);
+       server->tx.creq         = NULL;
+       server->rcv.creq        = NULL;
+
+       timer_setup(&server->timeout_tm, ncpdgram_timeout_call, 0);
+#undef NCP_PACKET_SIZE
+#define NCP_PACKET_SIZE 131072
+       error = -ENOMEM;
+       server->packet_size = NCP_PACKET_SIZE;
+       server->packet = vmalloc(NCP_PACKET_SIZE);
+       if (server->packet == NULL)
+               goto out_nls;
+       server->txbuf = vmalloc(NCP_PACKET_SIZE);
+       if (server->txbuf == NULL)
+               goto out_packet;
+       server->rxbuf = vmalloc(NCP_PACKET_SIZE);
+       if (server->rxbuf == NULL)
+               goto out_txbuf;
+
+       lock_sock(sock->sk);
+       server->data_ready      = sock->sk->sk_data_ready;
+       server->write_space     = sock->sk->sk_write_space;
+       server->error_report    = sock->sk->sk_error_report;
+       sock->sk->sk_user_data  = server;
+       sock->sk->sk_data_ready   = ncp_tcp_data_ready;
+       sock->sk->sk_error_report = ncp_tcp_error_report;
+       if (sock->type == SOCK_STREAM) {
+               server->rcv.ptr = (unsigned char*)&server->rcv.buf;
+               server->rcv.len = 10;
+               server->rcv.state = 0;
+               INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
+               INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
+               sock->sk->sk_write_space = ncp_tcp_write_space;
+       } else {
+               INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
+               INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
+       }
+       release_sock(sock->sk);
+
+       ncp_lock_server(server);
+       error = ncp_connect(server);
+       ncp_unlock_server(server);
+       if (error < 0)
+               goto out_rxbuf;
+       ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb));
+
+       error = -EMSGSIZE;      /* -EREMOTESIDEINCOMPATIBLE */
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+       if (ncp_negotiate_size_and_options(server, default_bufsize,
+               NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
+       {
+               if (options != NCP_DEFAULT_OPTIONS)
+               {
+                       if (ncp_negotiate_size_and_options(server, 
+                               default_bufsize,
+                               options & 2, 
+                               &(server->buffer_size), &options) != 0)
+                               
+                       {
+                               goto out_disconnect;
+                       }
+               }
+               ncp_lock_server(server);
+               if (options & 2)
+                       server->sign_wanted = 1;
+               ncp_unlock_server(server);
+       }
+       else 
+#endif /* CONFIG_NCPFS_PACKET_SIGNING */
+       if (ncp_negotiate_buffersize(server, default_bufsize,
+                                    &(server->buffer_size)) != 0)
+               goto out_disconnect;
+       ncp_dbg(1, "bufsize = %d\n", server->buffer_size);
+
+       memset(&finfo, 0, sizeof(finfo));
+       finfo.i.attributes      = aDIR;
+       finfo.i.dataStreamSize  = 0;    /* ignored */
+       finfo.i.dirEntNum       = 0;
+       finfo.i.DosDirNum       = 0;
+#ifdef CONFIG_NCPFS_SMALLDOS
+       finfo.i.NSCreator       = NW_NS_DOS;
+#endif
+       finfo.volume            = NCP_NUMBER_OF_VOLUMES;
+       /* set dates of mountpoint to Jan 1, 1986; 00:00 */
+       finfo.i.creationTime    = finfo.i.modifyTime
+                               = cpu_to_le16(0x0000);
+       finfo.i.creationDate    = finfo.i.modifyDate
+                               = finfo.i.lastAccessDate
+                               = cpu_to_le16(0x0C21);
+       finfo.i.nameLen         = 0;
+       finfo.i.entryName[0]    = '\0';
+
+       finfo.opened            = 0;
+       finfo.ino               = 2;    /* tradition */
+
+       server->name_space[finfo.volume] = NW_NS_DOS;
+
+       error = -ENOMEM;
+        root_inode = ncp_iget(sb, &finfo);
+        if (!root_inode)
+               goto out_disconnect;
+       ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
+       sb->s_root = d_make_root(root_inode);
+        if (!sb->s_root)
+               goto out_disconnect;
+       return 0;
+
+out_disconnect:
+       ncp_lock_server(server);
+       ncp_disconnect(server);
+       ncp_unlock_server(server);
+out_rxbuf:
+       ncp_stop_tasks(server);
+       vfree(server->rxbuf);
+out_txbuf:
+       vfree(server->txbuf);
+out_packet:
+       vfree(server->packet);
+out_nls:
+#ifdef CONFIG_NCPFS_NLS
+       unload_nls(server->nls_io);
+       unload_nls(server->nls_vol);
+#endif
+       mutex_destroy(&server->rcv.creq_mutex);
+       mutex_destroy(&server->root_setup_lock);
+       mutex_destroy(&server->mutex);
+out_fput2:
+       if (server->info_sock)
+               sockfd_put(server->info_sock);
+out_fput:
+       sockfd_put(sock);
+out:
+       put_pid(data.wdog_pid);
+       sb->s_fs_info = NULL;
+       kfree(server);
+       return error;
+}
+
+static void delayed_free(struct rcu_head *p)
+{
+       struct ncp_server *server = container_of(p, struct ncp_server, rcu);
+#ifdef CONFIG_NCPFS_NLS
+       /* unload the NLS charsets */
+       unload_nls(server->nls_vol);
+       unload_nls(server->nls_io);
+#endif /* CONFIG_NCPFS_NLS */
+       kfree(server);
+}
+
+static void ncp_put_super(struct super_block *sb)
+{
+       struct ncp_server *server = NCP_SBP(sb);
+
+       ncp_lock_server(server);
+       ncp_disconnect(server);
+       ncp_unlock_server(server);
+
+       ncp_stop_tasks(server);
+
+       mutex_destroy(&server->rcv.creq_mutex);
+       mutex_destroy(&server->root_setup_lock);
+       mutex_destroy(&server->mutex);
+
+       if (server->info_sock)
+               sockfd_put(server->info_sock);
+       sockfd_put(server->ncp_sock);
+       kill_pid(server->m.wdog_pid, SIGTERM, 1);
+       put_pid(server->m.wdog_pid);
+
+       kfree(server->priv.data);
+       kfree(server->auth.object_name);
+       vfree(server->rxbuf);
+       vfree(server->txbuf);
+       vfree(server->packet);
+       call_rcu(&server->rcu, delayed_free);
+}
+
+static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+       struct dentry* d;
+       struct inode* i;
+       struct ncp_inode_info* ni;
+       struct ncp_server* s;
+       struct ncp_volume_info vi;
+       struct super_block *sb = dentry->d_sb;
+       int err;
+       __u8 dh;
+       
+       d = sb->s_root;
+       if (!d) {
+               goto dflt;
+       }
+       i = d_inode(d);
+       if (!i) {
+               goto dflt;
+       }
+       ni = NCP_FINFO(i);
+       if (!ni) {
+               goto dflt;
+       }
+       s = NCP_SBP(sb);
+       if (!s) {
+               goto dflt;
+       }
+       if (!s->m.mounted_vol[0]) {
+               goto dflt;
+       }
+
+       err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
+       if (err) {
+               goto dflt;
+       }
+       err = ncp_get_directory_info(s, dh, &vi);
+       ncp_dirhandle_free(s, dh);
+       if (err) {
+               goto dflt;
+       }
+       buf->f_type = NCP_SUPER_MAGIC;
+       buf->f_bsize = vi.sectors_per_block * 512;
+       buf->f_blocks = vi.total_blocks;
+       buf->f_bfree = vi.free_blocks;
+       buf->f_bavail = vi.free_blocks;
+       buf->f_files = vi.total_dir_entries;
+       buf->f_ffree = vi.available_dir_entries;
+       buf->f_namelen = 12;
+       return 0;
+
+       /* We cannot say how much disk space is left on a mounted
+          NetWare Server, because free space is distributed over
+          volumes, and the current user might have disk quotas. So
+          free space is not that simple to determine. Our decision
+          here is to err conservatively. */
+
+dflt:;
+       buf->f_type = NCP_SUPER_MAGIC;
+       buf->f_bsize = NCP_BLOCK_SIZE;
+       buf->f_blocks = 0;
+       buf->f_bfree = 0;
+       buf->f_bavail = 0;
+       buf->f_namelen = 12;
+       return 0;
+}
+
+int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
+{
+       struct inode *inode = d_inode(dentry);
+       int result = 0;
+       __le32 info_mask;
+       struct nw_modify_dos_info info;
+       struct ncp_server *server;
+
+       result = -EIO;
+
+       server = NCP_SERVER(inode);
+       if (!server)    /* How this could happen? */
+               goto out;
+
+       result = -EPERM;
+       if (IS_DEADDIR(d_inode(dentry)))
+               goto out;
+
+       /* ageing the dentry to force validation */
+       ncp_age_dentry(server, dentry);
+
+       result = setattr_prepare(dentry, attr);
+       if (result < 0)
+               goto out;
+
+       result = -EPERM;
+       if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid))
+               goto out;
+
+       if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid))
+               goto out;
+
+       if (((attr->ia_valid & ATTR_MODE) &&
+            (attr->ia_mode &
+             ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
+               goto out;
+
+       info_mask = 0;
+       memset(&info, 0, sizeof(info));
+
+#if 1 
+        if ((attr->ia_valid & ATTR_MODE) != 0)
+        {
+               umode_t newmode = attr->ia_mode;
+
+               info_mask |= DM_ATTRIBUTES;
+
+                if (S_ISDIR(inode->i_mode)) {
+                       newmode &= server->m.dir_mode;
+               } else {
+#ifdef CONFIG_NCPFS_EXTRAS                     
+                       if (server->m.flags & NCP_MOUNT_EXTRAS) {
+                               /* any non-default execute bit set */
+                               if (newmode & ~server->m.file_mode & S_IXUGO)
+                                       info.attributes |= aSHARED | aSYSTEM;
+                               /* read for group/world and not in default file_mode */
+                               else if (newmode & ~server->m.file_mode & S_IRUGO)
+                                       info.attributes |= aSHARED;
+                       } else
+#endif
+                               newmode &= server->m.file_mode;                 
+                }
+                if (newmode & S_IWUGO)
+                       info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+                else
+                       info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+
+#ifdef CONFIG_NCPFS_NFS_NS
+               if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
+                       result = ncp_modify_nfs_info(server,
+                                                    NCP_FINFO(inode)->volNumber,
+                                                    NCP_FINFO(inode)->dirEntNum,
+                                                    attr->ia_mode, 0);
+                       if (result != 0)
+                               goto out;
+                       info.attributes &= ~(aSHARED | aSYSTEM);
+                       {
+                               /* mark partial success */
+                               struct iattr tmpattr;
+                               
+                               tmpattr.ia_valid = ATTR_MODE;
+                               tmpattr.ia_mode = attr->ia_mode;
+
+                               setattr_copy(inode, &tmpattr);
+                               mark_inode_dirty(inode);
+                       }
+               }
+#endif
+        }
+#endif
+
+       /* Do SIZE before attributes, otherwise mtime together with size does not work...
+        */
+       if ((attr->ia_valid & ATTR_SIZE) != 0) {
+               int written;
+
+               ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size);
+
+               if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
+                       result = -EACCES;
+                       goto out;
+               }
+               ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
+                         attr->ia_size, 0, "", &written);
+
+               /* According to ndir, the changes only take effect after
+                  closing the file */
+               ncp_inode_close(inode);
+               result = ncp_make_closed(inode);
+               if (result)
+                       goto out;
+
+               if (attr->ia_size != i_size_read(inode)) {
+                       truncate_setsize(inode, attr->ia_size);
+                       mark_inode_dirty(inode);
+               }
+       }
+       if ((attr->ia_valid & ATTR_CTIME) != 0) {
+               info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
+               ncp_date_unix2dos(attr->ia_ctime.tv_sec,
+                            &info.creationTime, &info.creationDate);
+       }
+       if ((attr->ia_valid & ATTR_MTIME) != 0) {
+               info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
+               ncp_date_unix2dos(attr->ia_mtime.tv_sec,
+                                 &info.modifyTime, &info.modifyDate);
+       }
+       if ((attr->ia_valid & ATTR_ATIME) != 0) {
+               __le16 dummy;
+               info_mask |= (DM_LAST_ACCESS_DATE);
+               ncp_date_unix2dos(attr->ia_atime.tv_sec,
+                                 &dummy, &info.lastAccessDate);
+       }
+       if (info_mask != 0) {
+               result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
+                                     inode, info_mask, &info);
+               if (result != 0) {
+                       if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
+                               /* NetWare seems not to allow this. I
+                                  do not know why. So, just tell the
+                                  user everything went fine. This is
+                                  a terrible hack, but I do not know
+                                  how to do this correctly. */
+                               result = 0;
+                       } else
+                               goto out;
+               }
+#ifdef CONFIG_NCPFS_STRONG             
+               if ((!result) && (info_mask & DM_ATTRIBUTES))
+                       NCP_FINFO(inode)->nwattr = info.attributes;
+#endif
+       }
+       if (result)
+               goto out;
+
+       setattr_copy(inode, attr);
+       mark_inode_dirty(inode);
+
+out:
+       if (result > 0)
+               result = -EACCES;
+       return result;
+}
+
+static struct dentry *ncp_mount(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *data)
+{
+       return mount_nodev(fs_type, flags, data, ncp_fill_super);
+}
+
+static struct file_system_type ncp_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "ncpfs",
+       .mount          = ncp_mount,
+       .kill_sb        = kill_anon_super,
+       .fs_flags       = FS_BINARY_MOUNTDATA,
+};
+MODULE_ALIAS_FS("ncpfs");
+
+static int __init init_ncp_fs(void)
+{
+       int err;
+       ncp_dbg(1, "called\n");
+
+       err = init_inodecache();
+       if (err)
+               goto out1;
+       err = register_filesystem(&ncp_fs_type);
+       if (err)
+               goto out;
+       return 0;
+out:
+       destroy_inodecache();
+out1:
+       return err;
+}
+
+static void __exit exit_ncp_fs(void)
+{
+       ncp_dbg(1, "called\n");
+       unregister_filesystem(&ncp_fs_type);
+       destroy_inodecache();
+}
+
+module_init(init_ncp_fs)
+module_exit(exit_ncp_fs)
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ncpfs/ioctl.c b/drivers/staging/ncpfs/ioctl.c
new file mode 100644 (file)
index 0000000..d378b98
--- /dev/null
@@ -0,0 +1,923 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  ioctl.c
+ *
+ *  Copyright (C) 1995, 1996 by Volker Lendecke
+ *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *  Modified 1998, 1999 Wolfram Pienkoss for NLS
+ *
+ */
+
+#include <linux/capability.h>
+#include <linux/compat.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/mount.h>
+#include <linux/slab.h>
+#include <linux/highuid.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/cred.h>
+
+#include <linux/uaccess.h>
+
+#include "ncp_fs.h"
+
+/* maximum limit for ncp_objectname_ioctl */
+#define NCP_OBJECT_NAME_MAX_LEN        4096
+/* maximum limit for ncp_privatedata_ioctl */
+#define NCP_PRIVATE_DATA_MAX_LEN 8192
+/* maximum negotiable packet size */
+#define NCP_PACKET_SIZE_INTERNAL 65536
+
+static int
+ncp_get_fs_info(struct ncp_server * server, struct inode *inode,
+               struct ncp_fs_info __user *arg)
+{
+       struct ncp_fs_info info;
+
+       if (copy_from_user(&info, arg, sizeof(info)))
+               return -EFAULT;
+
+       if (info.version != NCP_GET_FS_INFO_VERSION) {
+               ncp_dbg(1, "info.version invalid: %d\n", info.version);
+               return -EINVAL;
+       }
+       /* TODO: info.addr = server->m.serv_addr; */
+       SET_UID(info.mounted_uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid));
+       info.connection         = server->connection;
+       info.buffer_size        = server->buffer_size;
+       info.volume_number      = NCP_FINFO(inode)->volNumber;
+       info.directory_id       = NCP_FINFO(inode)->DosDirNum;
+
+       if (copy_to_user(arg, &info, sizeof(info)))
+               return -EFAULT;
+       return 0;
+}
+
+static int
+ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode,
+                  struct ncp_fs_info_v2 __user * arg)
+{
+       struct ncp_fs_info_v2 info2;
+
+       if (copy_from_user(&info2, arg, sizeof(info2)))
+               return -EFAULT;
+
+       if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
+               ncp_dbg(1, "info.version invalid: %d\n", info2.version);
+               return -EINVAL;
+       }
+       info2.mounted_uid   = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
+       info2.connection    = server->connection;
+       info2.buffer_size   = server->buffer_size;
+       info2.volume_number = NCP_FINFO(inode)->volNumber;
+       info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
+       info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
+
+       if (copy_to_user(arg, &info2, sizeof(info2)))
+               return -EFAULT;
+       return 0;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_ncp_objectname_ioctl
+{
+       s32             auth_type;
+       u32             object_name_len;
+       compat_caddr_t  object_name;    /* a userspace data, in most cases user name */
+};
+
+struct compat_ncp_fs_info_v2 {
+       s32 version;
+       u32 mounted_uid;
+       u32 connection;
+       u32 buffer_size;
+
+       u32 volume_number;
+       u32 directory_id;
+
+       u32 dummy1;
+       u32 dummy2;
+       u32 dummy3;
+};
+
+struct compat_ncp_ioctl_request {
+       u32 function;
+       u32 size;
+       compat_caddr_t data;
+};
+
+struct compat_ncp_privatedata_ioctl
+{
+       u32             len;
+       compat_caddr_t  data;           /* ~1000 for NDS */
+};
+
+#define NCP_IOC_GET_FS_INFO_V2_32      _IOWR('n', 4, struct compat_ncp_fs_info_v2)
+#define NCP_IOC_NCPREQUEST_32          _IOR('n', 1, struct compat_ncp_ioctl_request)
+#define NCP_IOC_GETOBJECTNAME_32       _IOWR('n', 9, struct compat_ncp_objectname_ioctl)
+#define NCP_IOC_SETOBJECTNAME_32       _IOR('n', 9, struct compat_ncp_objectname_ioctl)
+#define NCP_IOC_GETPRIVATEDATA_32      _IOWR('n', 10, struct compat_ncp_privatedata_ioctl)
+#define NCP_IOC_SETPRIVATEDATA_32      _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
+
+static int
+ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode,
+                  struct compat_ncp_fs_info_v2 __user * arg)
+{
+       struct compat_ncp_fs_info_v2 info2;
+
+       if (copy_from_user(&info2, arg, sizeof(info2)))
+               return -EFAULT;
+
+       if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
+               ncp_dbg(1, "info.version invalid: %d\n", info2.version);
+               return -EINVAL;
+       }
+       info2.mounted_uid   = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
+       info2.connection    = server->connection;
+       info2.buffer_size   = server->buffer_size;
+       info2.volume_number = NCP_FINFO(inode)->volNumber;
+       info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
+       info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
+
+       if (copy_to_user(arg, &info2, sizeof(info2)))
+               return -EFAULT;
+       return 0;
+}
+#endif
+
+#define NCP_IOC_GETMOUNTUID16          _IOW('n', 2, u16)
+#define NCP_IOC_GETMOUNTUID32          _IOW('n', 2, u32)
+#define NCP_IOC_GETMOUNTUID64          _IOW('n', 2, u64)
+
+#ifdef CONFIG_NCPFS_NLS
+/* Here we are select the iocharset and the codepage for NLS.
+ * Thanks Petr Vandrovec for idea and many hints.
+ */
+static int
+ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
+{
+       struct ncp_nls_ioctl user;
+       struct nls_table *codepage;
+       struct nls_table *iocharset;
+       struct nls_table *oldset_io;
+       struct nls_table *oldset_cp;
+       int utf8;
+       int err;
+
+       if (copy_from_user(&user, arg, sizeof(user)))
+               return -EFAULT;
+
+       codepage = NULL;
+       user.codepage[NCP_IOCSNAME_LEN] = 0;
+       if (!user.codepage[0] || !strcmp(user.codepage, "default"))
+               codepage = load_nls_default();
+       else {
+               codepage = load_nls(user.codepage);
+               if (!codepage) {
+                       return -EBADRQC;
+               }
+       }
+
+       iocharset = NULL;
+       user.iocharset[NCP_IOCSNAME_LEN] = 0;
+       if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
+               iocharset = load_nls_default();
+               utf8 = 0;
+       } else if (!strcmp(user.iocharset, "utf8")) {
+               iocharset = load_nls_default();
+               utf8 = 1;
+       } else {
+               iocharset = load_nls(user.iocharset);
+               if (!iocharset) {
+                       unload_nls(codepage);
+                       return -EBADRQC;
+               }
+               utf8 = 0;
+       }
+
+       mutex_lock(&server->root_setup_lock);
+       if (server->root_setuped) {
+               oldset_cp = codepage;
+               oldset_io = iocharset;
+               err = -EBUSY;
+       } else {
+               if (utf8)
+                       NCP_SET_FLAG(server, NCP_FLAG_UTF8);
+               else
+                       NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+               oldset_cp = server->nls_vol;
+               server->nls_vol = codepage;
+               oldset_io = server->nls_io;
+               server->nls_io = iocharset;
+               err = 0;
+       }
+       mutex_unlock(&server->root_setup_lock);
+       unload_nls(oldset_cp);
+       unload_nls(oldset_io);
+
+       return err;
+}
+
+static int
+ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
+{
+       struct ncp_nls_ioctl user;
+       int len;
+
+       memset(&user, 0, sizeof(user));
+       mutex_lock(&server->root_setup_lock);
+       if (server->nls_vol && server->nls_vol->charset) {
+               len = strlen(server->nls_vol->charset);
+               if (len > NCP_IOCSNAME_LEN)
+                       len = NCP_IOCSNAME_LEN;
+               strncpy(user.codepage, server->nls_vol->charset, len);
+               user.codepage[len] = 0;
+       }
+
+       if (NCP_IS_FLAG(server, NCP_FLAG_UTF8))
+               strcpy(user.iocharset, "utf8");
+       else if (server->nls_io && server->nls_io->charset) {
+               len = strlen(server->nls_io->charset);
+               if (len > NCP_IOCSNAME_LEN)
+                       len = NCP_IOCSNAME_LEN;
+               strncpy(user.iocharset, server->nls_io->charset, len);
+               user.iocharset[len] = 0;
+       }
+       mutex_unlock(&server->root_setup_lock);
+
+       if (copy_to_user(arg, &user, sizeof(user)))
+               return -EFAULT;
+       return 0;
+}
+#endif /* CONFIG_NCPFS_NLS */
+
+static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg)
+{
+       struct ncp_server *server = NCP_SERVER(inode);
+       int result;
+       struct ncp_ioctl_request request;
+       char* bouncebuffer;
+       void __user *argp = (void __user *)arg;
+
+       switch (cmd) {
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_NCPREQUEST_32:
+#endif
+       case NCP_IOC_NCPREQUEST:
+#ifdef CONFIG_COMPAT
+               if (cmd == NCP_IOC_NCPREQUEST_32) {
+                       struct compat_ncp_ioctl_request request32;
+                       if (copy_from_user(&request32, argp, sizeof(request32)))
+                               return -EFAULT;
+                       request.function = request32.function;
+                       request.size = request32.size;
+                       request.data = compat_ptr(request32.data);
+               } else
+#endif
+               if (copy_from_user(&request, argp, sizeof(request)))
+                       return -EFAULT;
+
+               if ((request.function > 255)
+                   || (request.size >
+                 NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
+                       return -EINVAL;
+               }
+               bouncebuffer = vmalloc(NCP_PACKET_SIZE_INTERNAL);
+               if (!bouncebuffer)
+                       return -ENOMEM;
+               if (copy_from_user(bouncebuffer, request.data, request.size)) {
+                       vfree(bouncebuffer);
+                       return -EFAULT;
+               }
+               ncp_lock_server(server);
+
+               /* FIXME: We hack around in the server's structures
+                  here to be able to use ncp_request */
+
+               server->has_subfunction = 0;
+               server->current_size = request.size;
+               memcpy(server->packet, bouncebuffer, request.size);
+
+               result = ncp_request2(server, request.function,
+                       bouncebuffer, NCP_PACKET_SIZE_INTERNAL);
+               if (result < 0)
+                       result = -EIO;
+               else
+                       result = server->reply_size;
+               ncp_unlock_server(server);
+               ncp_dbg(1, "copy %d bytes\n", result);
+               if (result >= 0)
+                       if (copy_to_user(request.data, bouncebuffer, result))
+                               result = -EFAULT;
+               vfree(bouncebuffer);
+               return result;
+
+       case NCP_IOC_CONN_LOGGED_IN:
+
+               if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
+                       return -EINVAL;
+               mutex_lock(&server->root_setup_lock);
+               if (server->root_setuped)
+                       result = -EBUSY;
+               else {
+                       result = ncp_conn_logged_in(inode->i_sb);
+                       if (result == 0)
+                               server->root_setuped = 1;
+               }
+               mutex_unlock(&server->root_setup_lock);
+               return result;
+
+       case NCP_IOC_GET_FS_INFO:
+               return ncp_get_fs_info(server, inode, argp);
+
+       case NCP_IOC_GET_FS_INFO_V2:
+               return ncp_get_fs_info_v2(server, inode, argp);
+
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_GET_FS_INFO_V2_32:
+               return ncp_get_compat_fs_info_v2(server, inode, argp);
+#endif
+       /* we have too many combinations of CONFIG_COMPAT,
+        * CONFIG_64BIT and CONFIG_UID16, so just handle
+        * any of the possible ioctls */
+       case NCP_IOC_GETMOUNTUID16:
+               {
+                       u16 uid;
+
+                       SET_UID(uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid));
+                       if (put_user(uid, (u16 __user *)argp))
+                               return -EFAULT;
+                       return 0;
+               }
+       case NCP_IOC_GETMOUNTUID32:
+       {
+               uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
+               if (put_user(uid, (u32 __user *)argp))
+                       return -EFAULT;
+               return 0;
+       }
+       case NCP_IOC_GETMOUNTUID64:
+       {
+               uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
+               if (put_user(uid, (u64 __user *)argp))
+                       return -EFAULT;
+               return 0;
+       }
+       case NCP_IOC_GETROOT:
+               {
+                       struct ncp_setroot_ioctl sr;
+
+                       result = -EACCES;
+                       mutex_lock(&server->root_setup_lock);
+                       if (server->m.mounted_vol[0]) {
+                               struct dentry* dentry = inode->i_sb->s_root;
+
+                               if (dentry) {
+                                       struct inode* s_inode = d_inode(dentry);
+
+                                       if (s_inode) {
+                                               sr.volNumber = NCP_FINFO(s_inode)->volNumber;
+                                               sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum;
+                                               sr.namespace = server->name_space[sr.volNumber];
+                                               result = 0;
+                                       } else
+                                               ncp_dbg(1, "d_inode(s_root)==NULL\n");
+                               } else
+                                       ncp_dbg(1, "s_root==NULL\n");
+                       } else {
+                               sr.volNumber = -1;
+                               sr.namespace = 0;
+                               sr.dirEntNum = 0;
+                               result = 0;
+                       }
+                       mutex_unlock(&server->root_setup_lock);
+                       if (!result && copy_to_user(argp, &sr, sizeof(sr)))
+                               result = -EFAULT;
+                       return result;
+               }
+
+       case NCP_IOC_SETROOT:
+               {
+                       struct ncp_setroot_ioctl sr;
+                       __u32 vnum;
+                       __le32 de;
+                       __le32 dosde;
+                       struct dentry* dentry;
+
+                       if (copy_from_user(&sr, argp, sizeof(sr)))
+                               return -EFAULT;
+                       mutex_lock(&server->root_setup_lock);
+                       if (server->root_setuped)
+                               result = -EBUSY;
+                       else {
+                               if (sr.volNumber < 0) {
+                                       server->m.mounted_vol[0] = 0;
+                                       vnum = NCP_NUMBER_OF_VOLUMES;
+                                       de = 0;
+                                       dosde = 0;
+                                       result = 0;
+                               } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
+                                       result = -EINVAL;
+                               } else if (ncp_mount_subdir(server, sr.volNumber,
+                                                       sr.namespace, sr.dirEntNum,
+                                                       &vnum, &de, &dosde)) {
+                                       result = -ENOENT;
+                               } else
+                                       result = 0;
+
+                               if (result == 0) {
+                                       dentry = inode->i_sb->s_root;
+                                       if (dentry) {
+                                               struct inode* s_inode = d_inode(dentry);
+
+                                               if (s_inode) {
+                                                       NCP_FINFO(s_inode)->volNumber = vnum;
+                                                       NCP_FINFO(s_inode)->dirEntNum = de;
+                                                       NCP_FINFO(s_inode)->DosDirNum = dosde;
+                                                       server->root_setuped = 1;
+                                               } else {
+                                                       ncp_dbg(1, "d_inode(s_root)==NULL\n");
+                                                       result = -EIO;
+                                               }
+                                       } else {
+                                               ncp_dbg(1, "s_root==NULL\n");
+                                               result = -EIO;
+                                       }
+                               }
+                       }
+                       mutex_unlock(&server->root_setup_lock);
+
+                       return result;
+               }
+
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+       case NCP_IOC_SIGN_INIT:
+               {
+                       struct ncp_sign_init sign;
+
+                       if (argp)
+                               if (copy_from_user(&sign, argp, sizeof(sign)))
+                                       return -EFAULT;
+                       ncp_lock_server(server);
+                       mutex_lock(&server->rcv.creq_mutex);
+                       if (argp) {
+                               if (server->sign_wanted) {
+                                       memcpy(server->sign_root,sign.sign_root,8);
+                                       memcpy(server->sign_last,sign.sign_last,16);
+                                       server->sign_active = 1;
+                               }
+                               /* ignore when signatures not wanted */
+                       } else {
+                               server->sign_active = 0;
+                       }
+                       mutex_unlock(&server->rcv.creq_mutex);
+                       ncp_unlock_server(server);
+                       return 0;
+               }
+
+        case NCP_IOC_SIGN_WANTED:
+               {
+                       int state;
+
+                       ncp_lock_server(server);
+                       state = server->sign_wanted;
+                       ncp_unlock_server(server);
+                       if (put_user(state, (int __user *)argp))
+                               return -EFAULT;
+                       return 0;
+               }
+
+       case NCP_IOC_SET_SIGN_WANTED:
+               {
+                       int newstate;
+
+                       /* get only low 8 bits... */
+                       if (get_user(newstate, (unsigned char __user *)argp))
+                               return -EFAULT;
+                       result = 0;
+                       ncp_lock_server(server);
+                       if (server->sign_active) {
+                               /* cannot turn signatures OFF when active */
+                               if (!newstate)
+                                       result = -EINVAL;
+                       } else {
+                               server->sign_wanted = newstate != 0;
+                       }
+                       ncp_unlock_server(server);
+                       return result;
+               }
+
+#endif /* CONFIG_NCPFS_PACKET_SIGNING */
+
+#ifdef CONFIG_NCPFS_IOCTL_LOCKING
+       case NCP_IOC_LOCKUNLOCK:
+               {
+                       struct ncp_lock_ioctl    rqdata;
+
+                       if (copy_from_user(&rqdata, argp, sizeof(rqdata)))
+                               return -EFAULT;
+                       if (rqdata.origin != 0)
+                               return -EINVAL;
+                       /* check for cmd */
+                       switch (rqdata.cmd) {
+                               case NCP_LOCK_EX:
+                               case NCP_LOCK_SH:
+                                               if (rqdata.timeout < 0)
+                                                       return -EINVAL;
+                                               if (rqdata.timeout == 0)
+                                                       rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT;
+                                               else if (rqdata.timeout > NCP_LOCK_MAX_TIMEOUT)
+                                                       rqdata.timeout = NCP_LOCK_MAX_TIMEOUT;
+                                               break;
+                               case NCP_LOCK_LOG:
+                                               rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT;      /* has no effect */
+                               case NCP_LOCK_CLEAR:
+                                               break;
+                               default:
+                                               return -EINVAL;
+                       }
+                       /* locking needs both read and write access */
+                       if ((result = ncp_make_open(inode, O_RDWR)) != 0)
+                       {
+                               return result;
+                       }
+                       result = -EISDIR;
+                       if (!S_ISREG(inode->i_mode))
+                               goto outrel;
+                       if (rqdata.cmd == NCP_LOCK_CLEAR)
+                       {
+                               result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
+                                                       NCP_FINFO(inode)->file_handle,
+                                                       rqdata.offset,
+                                                       rqdata.length);
+                               if (result > 0) result = 0;     /* no such lock */
+                       }
+                       else
+                       {
+                               int lockcmd;
+
+                               switch (rqdata.cmd)
+                               {
+                                       case NCP_LOCK_EX:  lockcmd=1; break;
+                                       case NCP_LOCK_SH:  lockcmd=3; break;
+                                       default:           lockcmd=0; break;
+                               }
+                               result = ncp_LogPhysicalRecord(NCP_SERVER(inode),
+                                                       NCP_FINFO(inode)->file_handle,
+                                                       lockcmd,
+                                                       rqdata.offset,
+                                                       rqdata.length,
+                                                       rqdata.timeout);
+                               if (result > 0) result = -EAGAIN;
+                       }
+outrel:
+                       ncp_inode_close(inode);
+                       return result;
+               }
+#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
+
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_GETOBJECTNAME_32:
+               {
+                       struct compat_ncp_objectname_ioctl user;
+                       size_t outl;
+
+                       if (copy_from_user(&user, argp, sizeof(user)))
+                               return -EFAULT;
+                       down_read(&server->auth_rwsem);
+                       user.auth_type = server->auth.auth_type;
+                       outl = user.object_name_len;
+                       user.object_name_len = server->auth.object_name_len;
+                       if (outl > user.object_name_len)
+                               outl = user.object_name_len;
+                       result = 0;
+                       if (outl) {
+                               if (copy_to_user(compat_ptr(user.object_name),
+                                                server->auth.object_name,
+                                                outl))
+                                       result = -EFAULT;
+                       }
+                       up_read(&server->auth_rwsem);
+                       if (!result && copy_to_user(argp, &user, sizeof(user)))
+                               result = -EFAULT;
+                       return result;
+               }
+#endif
+
+       case NCP_IOC_GETOBJECTNAME:
+               {
+                       struct ncp_objectname_ioctl user;
+                       size_t outl;
+
+                       if (copy_from_user(&user, argp, sizeof(user)))
+                               return -EFAULT;
+                       down_read(&server->auth_rwsem);
+                       user.auth_type = server->auth.auth_type;
+                       outl = user.object_name_len;
+                       user.object_name_len = server->auth.object_name_len;
+                       if (outl > user.object_name_len)
+                               outl = user.object_name_len;
+                       result = 0;
+                       if (outl) {
+                               if (copy_to_user(user.object_name,
+                                                server->auth.object_name,
+                                                outl))
+                                       result = -EFAULT;
+                       }
+                       up_read(&server->auth_rwsem);
+                       if (!result && copy_to_user(argp, &user, sizeof(user)))
+                               result = -EFAULT;
+                       return result;
+               }
+
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_SETOBJECTNAME_32:
+#endif
+       case NCP_IOC_SETOBJECTNAME:
+               {
+                       struct ncp_objectname_ioctl user;
+                       void* newname;
+                       void* oldname;
+                       size_t oldnamelen;
+                       void* oldprivate;
+                       size_t oldprivatelen;
+
+#ifdef CONFIG_COMPAT
+                       if (cmd == NCP_IOC_SETOBJECTNAME_32) {
+                               struct compat_ncp_objectname_ioctl user32;
+                               if (copy_from_user(&user32, argp, sizeof(user32)))
+                                       return -EFAULT;
+                               user.auth_type = user32.auth_type;
+                               user.object_name_len = user32.object_name_len;
+                               user.object_name = compat_ptr(user32.object_name);
+                       } else
+#endif
+                       if (copy_from_user(&user, argp, sizeof(user)))
+                               return -EFAULT;
+
+                       if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
+                               return -ENOMEM;
+                       if (user.object_name_len) {
+                               newname = memdup_user(user.object_name,
+                                                     user.object_name_len);
+                               if (IS_ERR(newname))
+                                       return PTR_ERR(newname);
+                       } else {
+                               newname = NULL;
+                       }
+                       down_write(&server->auth_rwsem);
+                       oldname = server->auth.object_name;
+                       oldnamelen = server->auth.object_name_len;
+                       oldprivate = server->priv.data;
+                       oldprivatelen = server->priv.len;
+                       server->auth.auth_type = user.auth_type;
+                       server->auth.object_name_len = user.object_name_len;
+                       server->auth.object_name = newname;
+                       server->priv.len = 0;
+                       server->priv.data = NULL;
+                       up_write(&server->auth_rwsem);
+                       kfree(oldprivate);
+                       kfree(oldname);
+                       return 0;
+               }
+
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_GETPRIVATEDATA_32:
+#endif
+       case NCP_IOC_GETPRIVATEDATA:
+               {
+                       struct ncp_privatedata_ioctl user;
+                       size_t outl;
+
+#ifdef CONFIG_COMPAT
+                       if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
+                               struct compat_ncp_privatedata_ioctl user32;
+                               if (copy_from_user(&user32, argp, sizeof(user32)))
+                                       return -EFAULT;
+                               user.len = user32.len;
+                               user.data = compat_ptr(user32.data);
+                       } else
+#endif
+                       if (copy_from_user(&user, argp, sizeof(user)))
+                               return -EFAULT;
+
+                       down_read(&server->auth_rwsem);
+                       outl = user.len;
+                       user.len = server->priv.len;
+                       if (outl > user.len) outl = user.len;
+                       result = 0;
+                       if (outl) {
+                               if (copy_to_user(user.data,
+                                                server->priv.data,
+                                                outl))
+                                       result = -EFAULT;
+                       }
+                       up_read(&server->auth_rwsem);
+                       if (result)
+                               return result;
+#ifdef CONFIG_COMPAT
+                       if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
+                               struct compat_ncp_privatedata_ioctl user32;
+                               user32.len = user.len;
+                               user32.data = (unsigned long) user.data;
+                               if (copy_to_user(argp, &user32, sizeof(user32)))
+                                       return -EFAULT;
+                       } else
+#endif
+                       if (copy_to_user(argp, &user, sizeof(user)))
+                               return -EFAULT;
+
+                       return 0;
+               }
+
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_SETPRIVATEDATA_32:
+#endif
+       case NCP_IOC_SETPRIVATEDATA:
+               {
+                       struct ncp_privatedata_ioctl user;
+                       void* new;
+                       void* old;
+                       size_t oldlen;
+
+#ifdef CONFIG_COMPAT
+                       if (cmd == NCP_IOC_SETPRIVATEDATA_32) {
+                               struct compat_ncp_privatedata_ioctl user32;
+                               if (copy_from_user(&user32, argp, sizeof(user32)))
+                                       return -EFAULT;
+                               user.len = user32.len;
+                               user.data = compat_ptr(user32.data);
+                       } else
+#endif
+                       if (copy_from_user(&user, argp, sizeof(user)))
+                               return -EFAULT;
+
+                       if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
+                               return -ENOMEM;
+                       if (user.len) {
+                               new = memdup_user(user.data, user.len);
+                               if (IS_ERR(new))
+                                       return PTR_ERR(new);
+                       } else {
+                               new = NULL;
+                       }
+                       down_write(&server->auth_rwsem);
+                       old = server->priv.data;
+                       oldlen = server->priv.len;
+                       server->priv.len = user.len;
+                       server->priv.data = new;
+                       up_write(&server->auth_rwsem);
+                       kfree(old);
+                       return 0;
+               }
+
+#ifdef CONFIG_NCPFS_NLS
+       case NCP_IOC_SETCHARSETS:
+               return ncp_set_charsets(server, argp);
+
+       case NCP_IOC_GETCHARSETS:
+               return ncp_get_charsets(server, argp);
+
+#endif /* CONFIG_NCPFS_NLS */
+
+       case NCP_IOC_SETDENTRYTTL:
+               {
+                       u_int32_t user;
+
+                       if (copy_from_user(&user, argp, sizeof(user)))
+                               return -EFAULT;
+                       /* 20 secs at most... */
+                       if (user > 20000)
+                               return -EINVAL;
+                       user = (user * HZ) / 1000;
+                       atomic_set(&server->dentry_ttl, user);
+                       return 0;
+               }
+
+       case NCP_IOC_GETDENTRYTTL:
+               {
+                       u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ;
+                       if (copy_to_user(argp, &user, sizeof(user)))
+                               return -EFAULT;
+                       return 0;
+               }
+
+       }
+       return -EINVAL;
+}
+
+long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       struct inode *inode = file_inode(filp);
+       struct ncp_server *server = NCP_SERVER(inode);
+       kuid_t uid = current_uid();
+       int need_drop_write = 0;
+       long ret;
+
+       switch (cmd) {
+       case NCP_IOC_SETCHARSETS:
+       case NCP_IOC_CONN_LOGGED_IN:
+       case NCP_IOC_SETROOT:
+               if (!capable(CAP_SYS_ADMIN)) {
+                       ret = -EPERM;
+                       goto out;
+               }
+               break;
+       }
+       if (!uid_eq(server->m.mounted_uid, uid)) {
+               switch (cmd) {
+               /*
+                * Only mount owner can issue these ioctls.  Information
+                * necessary to authenticate to other NDS servers are
+                * stored here.
+                */
+               case NCP_IOC_GETOBJECTNAME:
+               case NCP_IOC_SETOBJECTNAME:
+               case NCP_IOC_GETPRIVATEDATA:
+               case NCP_IOC_SETPRIVATEDATA:
+#ifdef CONFIG_COMPAT
+               case NCP_IOC_GETOBJECTNAME_32:
+               case NCP_IOC_SETOBJECTNAME_32:
+               case NCP_IOC_GETPRIVATEDATA_32:
+               case NCP_IOC_SETPRIVATEDATA_32:
+#endif
+                       ret = -EACCES;
+                       goto out;
+               /*
+                * These require write access on the inode if user id
+                * does not match.  Note that they do not write to the
+                * file...  But old code did mnt_want_write, so I keep
+                * it as is.  Of course not for mountpoint owner, as
+                * that breaks read-only mounts altogether as ncpmount
+                * needs working NCP_IOC_NCPREQUEST and
+                * NCP_IOC_GET_FS_INFO.  Some of these codes (setdentryttl,
+                * signinit, setsignwanted) should be probably restricted
+                * to owner only, or even more to CAP_SYS_ADMIN).
+                */
+               case NCP_IOC_GET_FS_INFO:
+               case NCP_IOC_GET_FS_INFO_V2:
+               case NCP_IOC_NCPREQUEST:
+               case NCP_IOC_SETDENTRYTTL:
+               case NCP_IOC_SIGN_INIT:
+               case NCP_IOC_LOCKUNLOCK:
+               case NCP_IOC_SET_SIGN_WANTED:
+#ifdef CONFIG_COMPAT
+               case NCP_IOC_GET_FS_INFO_V2_32:
+               case NCP_IOC_NCPREQUEST_32:
+#endif
+                       ret = mnt_want_write_file(filp);
+                       if (ret)
+                               goto out;
+                       need_drop_write = 1;
+                       ret = inode_permission(inode, MAY_WRITE);
+                       if (ret)
+                               goto outDropWrite;
+                       break;
+               /*
+                * Read access required.
+                */
+               case NCP_IOC_GETMOUNTUID16:
+               case NCP_IOC_GETMOUNTUID32:
+               case NCP_IOC_GETMOUNTUID64:
+               case NCP_IOC_GETROOT:
+               case NCP_IOC_SIGN_WANTED:
+                       ret = inode_permission(inode, MAY_READ);
+                       if (ret)
+                               goto out;
+                       break;
+               /*
+                * Anybody can read these.
+                */
+               case NCP_IOC_GETCHARSETS:
+               case NCP_IOC_GETDENTRYTTL:
+               default:
+               /* Three codes below are protected by CAP_SYS_ADMIN above. */
+               case NCP_IOC_SETCHARSETS:
+               case NCP_IOC_CONN_LOGGED_IN:
+               case NCP_IOC_SETROOT:
+                       break;
+               }
+       }
+       ret = __ncp_ioctl(inode, cmd, arg);
+outDropWrite:
+       if (need_drop_write)
+               mnt_drop_write_file(filp);
+out:
+       return ret;
+}
+
+#ifdef CONFIG_COMPAT
+long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       long ret;
+
+       arg = (unsigned long) compat_ptr(arg);
+       ret = ncp_ioctl(file, cmd, arg);
+       return ret;
+}
+#endif
diff --git a/drivers/staging/ncpfs/mmap.c b/drivers/staging/ncpfs/mmap.c
new file mode 100644 (file)
index 0000000..a5c5cf2
--- /dev/null
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  mmap.c
+ *
+ *  Copyright (C) 1995, 1996 by Volker Lendecke
+ *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *
+ */
+
+#include <linux/stat.h>
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/shm.h>
+#include <linux/errno.h>
+#include <linux/mman.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/memcontrol.h>
+
+#include <linux/uaccess.h>
+
+#include "ncp_fs.h"
+
+/*
+ * Fill in the supplied page for mmap
+ * XXX: how are we excluding truncate/invalidate here? Maybe need to lock
+ * page?
+ */
+static int ncp_file_mmap_fault(struct vm_fault *vmf)
+{
+       struct inode *inode = file_inode(vmf->vma->vm_file);
+       char *pg_addr;
+       unsigned int already_read;
+       unsigned int count;
+       int bufsize;
+       int pos; /* XXX: loff_t ? */
+
+       /*
+        * ncpfs has nothing against high pages as long
+        * as recvmsg and memset works on it
+        */
+       vmf->page = alloc_page(GFP_HIGHUSER);
+       if (!vmf->page)
+               return VM_FAULT_OOM;
+       pg_addr = kmap(vmf->page);
+       pos = vmf->pgoff << PAGE_SHIFT;
+
+       count = PAGE_SIZE;
+       /* what we can read in one go */
+       bufsize = NCP_SERVER(inode)->buffer_size;
+
+       already_read = 0;
+       if (ncp_make_open(inode, O_RDONLY) >= 0) {
+               while (already_read < count) {
+                       int read_this_time;
+                       int to_read;
+
+                       to_read = bufsize - (pos % bufsize);
+
+                       to_read = min_t(unsigned int, to_read, count - already_read);
+
+                       if (ncp_read_kernel(NCP_SERVER(inode),
+                                    NCP_FINFO(inode)->file_handle,
+                                    pos, to_read,
+                                    pg_addr + already_read,
+                                    &read_this_time) != 0) {
+                               read_this_time = 0;
+                       }
+                       pos += read_this_time;
+                       already_read += read_this_time;
+
+                       if (read_this_time < to_read) {
+                               break;
+                       }
+               }
+               ncp_inode_close(inode);
+
+       }
+
+       if (already_read < PAGE_SIZE)
+               memset(pg_addr + already_read, 0, PAGE_SIZE - already_read);
+       flush_dcache_page(vmf->page);
+       kunmap(vmf->page);
+
+       /*
+        * If I understand ncp_read_kernel() properly, the above always
+        * fetches from the network, here the analogue of disk.
+        * -- nyc
+        */
+       count_vm_event(PGMAJFAULT);
+       count_memcg_event_mm(vmf->vma->vm_mm, PGMAJFAULT);
+       return VM_FAULT_MAJOR;
+}
+
+static const struct vm_operations_struct ncp_file_mmap =
+{
+       .fault = ncp_file_mmap_fault,
+};
+
+
+/* This is used for a general mmap of a ncp file */
+int ncp_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct inode *inode = file_inode(file);
+       
+       ncp_dbg(1, "called\n");
+
+       if (!ncp_conn_valid(NCP_SERVER(inode)))
+               return -EIO;
+
+       /* only PAGE_COW or read-only supported now */
+       if (vma->vm_flags & VM_SHARED)
+               return -EINVAL;
+       /* we do not support files bigger than 4GB... We eventually 
+          supports just 4GB... */
+       if (vma_pages(vma) + vma->vm_pgoff
+          > (1U << (32 - PAGE_SHIFT)))
+               return -EFBIG;
+
+       vma->vm_ops = &ncp_file_mmap;
+       file_accessed(file);
+       return 0;
+}
diff --git a/drivers/staging/ncpfs/ncp_fs.h b/drivers/staging/ncpfs/ncp_fs.h
new file mode 100644 (file)
index 0000000..bdd262b
--- /dev/null
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/ncp_fs.h>
+#include "ncp_fs_i.h"
+#include "ncp_fs_sb.h"
+
+#undef NCPFS_PARANOIA
+#ifdef NCPFS_PARANOIA
+#define ncp_vdbg(fmt, ...)                                     \
+       pr_debug(fmt, ##__VA_ARGS__)
+#else
+#define ncp_vdbg(fmt, ...)                                     \
+do {                                                           \
+       if (0)                                                  \
+               pr_debug(fmt, ##__VA_ARGS__);                   \
+} while (0)
+#endif
+
+#ifndef DEBUG_NCP
+#define DEBUG_NCP 0
+#endif
+
+#if DEBUG_NCP > 0 && !defined(DEBUG)
+#define DEBUG
+#endif
+
+#define ncp_dbg(level, fmt, ...)                               \
+do {                                                           \
+       if (level <= DEBUG_NCP)                                 \
+               pr_debug(fmt, ##__VA_ARGS__);                   \
+} while (0)
+
+#define NCP_MAX_RPC_TIMEOUT (6*HZ)
+
+
+struct ncp_entry_info {
+       struct nw_info_struct   i;
+       ino_t                   ino;
+       int                     opened;
+       int                     access;
+       unsigned int            volume;
+       __u8                    file_handle[6];
+};
+
+static inline struct ncp_server *NCP_SBP(const struct super_block *sb)
+{
+       return sb->s_fs_info;
+}
+
+#define NCP_SERVER(inode)      NCP_SBP((inode)->i_sb)
+static inline struct ncp_inode_info *NCP_FINFO(const struct inode *inode)
+{
+       return container_of(inode, struct ncp_inode_info, vfs_inode);
+}
+
+/* linux/fs/ncpfs/inode.c */
+int ncp_notify_change(struct dentry *, struct iattr *);
+struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *);
+void ncp_update_inode(struct inode *, struct ncp_entry_info *);
+void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
+
+/* linux/fs/ncpfs/dir.c */
+extern const struct inode_operations ncp_dir_inode_operations;
+extern const struct file_operations ncp_dir_operations;
+extern const struct dentry_operations ncp_dentry_operations;
+int ncp_conn_logged_in(struct super_block *);
+int ncp_date_dos2unix(__le16 time, __le16 date);
+void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date);
+
+/* linux/fs/ncpfs/ioctl.c */
+long ncp_ioctl(struct file *, unsigned int, unsigned long);
+long ncp_compat_ioctl(struct file *, unsigned int, unsigned long);
+
+/* linux/fs/ncpfs/sock.c */
+int ncp_request2(struct ncp_server *server, int function,
+       void* reply, int max_reply_size);
+static inline int ncp_request(struct ncp_server *server, int function) {
+       return ncp_request2(server, function, server->packet, server->packet_size);
+}
+int ncp_connect(struct ncp_server *server);
+int ncp_disconnect(struct ncp_server *server);
+void ncp_lock_server(struct ncp_server *server);
+void ncp_unlock_server(struct ncp_server *server);
+
+/* linux/fs/ncpfs/symlink.c */
+#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
+extern const struct address_space_operations ncp_symlink_aops;
+int ncp_symlink(struct inode*, struct dentry*, const char*);
+#endif
+
+/* linux/fs/ncpfs/file.c */
+extern const struct inode_operations ncp_file_inode_operations;
+extern const struct file_operations ncp_file_operations;
+int ncp_make_open(struct inode *, int);
+
+/* linux/fs/ncpfs/mmap.c */
+int ncp_mmap(struct file *, struct vm_area_struct *);
+
+/* linux/fs/ncpfs/ncplib_kernel.c */
+int ncp_make_closed(struct inode *);
+
+#include "ncplib_kernel.h"
diff --git a/drivers/staging/ncpfs/ncp_fs_i.h b/drivers/staging/ncpfs/ncp_fs_i.h
new file mode 100644 (file)
index 0000000..3432baf
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  ncp_fs_i.h
+ *
+ *  Copyright (C) 1995 Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_NCP_FS_I
+#define _LINUX_NCP_FS_I
+
+/*
+ * This is the ncpfs part of the inode structure. This must contain
+ * all the information we need to work with an inode after creation.
+ */
+struct ncp_inode_info {
+       __le32  dirEntNum;
+       __le32  DosDirNum;
+       __u8    volNumber;
+       __le32  nwattr;
+       struct mutex open_mutex;
+       atomic_t        opened;
+       int     access;
+       int     flags;
+#define NCPI_KLUDGE_SYMLINK    0x0001
+#define NCPI_DIR_CACHE         0x0002
+       __u8    file_handle[6];
+       struct inode vfs_inode;
+};
+
+#endif /* _LINUX_NCP_FS_I */
diff --git a/drivers/staging/ncpfs/ncp_fs_sb.h b/drivers/staging/ncpfs/ncp_fs_sb.h
new file mode 100644 (file)
index 0000000..f06cde4
--- /dev/null
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  ncp_fs_sb.h
+ *
+ *  Copyright (C) 1995, 1996 by Volker Lendecke
+ *
+ */
+
+#ifndef _NCP_FS_SB
+#define _NCP_FS_SB
+
+#include <linux/types.h>
+#include <linux/ncp_mount.h>
+#include <linux/net.h>
+#include <linux/mutex.h>
+#include <linux/backing-dev.h>
+#include <linux/workqueue.h>
+
+#define NCP_DEFAULT_OPTIONS 0          /* 2 for packet signatures */
+
+struct sock;
+
+struct ncp_mount_data_kernel {
+       unsigned long    flags;         /* NCP_MOUNT_* flags */
+       unsigned int     int_flags;     /* internal flags */
+#define NCP_IMOUNT_LOGGEDIN_POSSIBLE   0x0001
+       kuid_t           mounted_uid;   /* Who may umount() this filesystem? */
+       struct pid      *wdog_pid;      /* Who cares for our watchdog packets? */
+       unsigned int     ncp_fd;        /* The socket to the ncp port */
+       unsigned int     time_out;      /* How long should I wait after
+                                          sending a NCP request? */
+       unsigned int     retry_count;   /* And how often should I retry? */
+       unsigned char    mounted_vol[NCP_VOLNAME_LEN + 1];
+       kuid_t           uid;
+       kgid_t           gid;
+       umode_t          file_mode;
+       umode_t          dir_mode;
+       int              info_fd;
+};
+
+struct ncp_server {
+       struct rcu_head rcu;
+       struct ncp_mount_data_kernel m; /* Nearly all of the mount data is of
+                                          interest for us later, so we store
+                                          it completely. */
+
+       __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2];
+
+       struct socket *ncp_sock;/* ncp socket */
+       struct socket *info_sock;
+
+       u8 sequence;
+       u8 task;
+       u16 connection;         /* Remote connection number */
+
+       u8 completion;          /* Status message from server */
+       u8 conn_status;         /* Bit 4 = 1 ==> Server going down, no
+                                  requests allowed anymore.
+                                  Bit 0 = 1 ==> Server is down. */
+
+       int buffer_size;        /* Negotiated bufsize */
+
+       int reply_size;         /* Size of last reply */
+
+       int packet_size;
+       unsigned char *packet;  /* Here we prepare requests and
+                                  receive replies */
+       unsigned char *txbuf;   /* Storage for current request */
+       unsigned char *rxbuf;   /* Storage for reply to current request */
+
+       int lock;               /* To prevent mismatch in protocols. */
+       struct mutex mutex;
+
+       int current_size;       /* for packet preparation */
+       int has_subfunction;
+       int ncp_reply_size;
+
+       int root_setuped;
+       struct mutex root_setup_lock;
+
+       /* info for packet signing */
+       int sign_wanted;        /* 1=Server needs signed packets */
+       int sign_active;        /* 0=don't do signing, 1=do */
+       char sign_root[8];      /* generated from password and encr. key */
+       char sign_last[16];     
+
+       /* Authentication info: NDS or BINDERY, username */
+       struct {
+               int     auth_type;
+               size_t  object_name_len;
+               void*   object_name;
+               int     object_type;
+       } auth;
+       /* Password info */
+       struct {
+               size_t  len;
+               void*   data;
+       } priv;
+       struct rw_semaphore auth_rwsem;
+
+       /* nls info: codepage for volume and charset for I/O */
+       struct nls_table *nls_vol;
+       struct nls_table *nls_io;
+
+       /* maximum age in jiffies */
+       atomic_t dentry_ttl;
+
+       /* miscellaneous */
+       unsigned int flags;
+
+       spinlock_t requests_lock;       /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */
+
+       void (*data_ready)(struct sock* sk);
+       void (*error_report)(struct sock* sk);
+       void (*write_space)(struct sock* sk);   /* STREAM mode only */
+       struct {
+               struct work_struct tq;          /* STREAM/DGRAM: data/error ready */
+               struct ncp_request_reply* creq; /* STREAM/DGRAM: awaiting reply from this request */
+               struct mutex creq_mutex;        /* DGRAM only: lock accesses to rcv.creq */
+
+               unsigned int state;             /* STREAM only: receiver state */
+               struct {
+                       __u32 magic __packed;
+                       __u32 len __packed;
+                       __u16 type __packed;
+                       __u16 p1 __packed;
+                       __u16 p2 __packed;
+                       __u16 p3 __packed;
+                       __u16 type2 __packed;
+               } buf;                          /* STREAM only: temporary buffer */
+               unsigned char* ptr;             /* STREAM only: pointer to data */
+               size_t len;                     /* STREAM only: length of data to receive */
+       } rcv;
+       struct {
+               struct list_head requests;      /* STREAM only: queued requests */
+               struct work_struct tq;          /* STREAM only: transmitter ready */
+               struct ncp_request_reply* creq; /* STREAM only: currently transmitted entry */
+       } tx;
+       struct timer_list timeout_tm;           /* DGRAM only: timeout timer */
+       struct work_struct timeout_tq;          /* DGRAM only: associated queue, we run timers from process context */
+       int timeout_last;                       /* DGRAM only: current timeout length */
+       int timeout_retries;                    /* DGRAM only: retries left */
+       struct {
+               size_t len;
+               __u8 data[128];
+       } unexpected_packet;
+};
+
+extern void ncp_tcp_rcv_proc(struct work_struct *work);
+extern void ncp_tcp_tx_proc(struct work_struct *work);
+extern void ncpdgram_rcv_proc(struct work_struct *work);
+extern void ncpdgram_timeout_proc(struct work_struct *work);
+extern void ncpdgram_timeout_call(struct timer_list *t);
+extern void ncp_tcp_data_ready(struct sock* sk);
+extern void ncp_tcp_write_space(struct sock* sk);
+extern void ncp_tcp_error_report(struct sock* sk);
+
+#define NCP_FLAG_UTF8  1
+
+#define NCP_CLR_FLAG(server, flag)     ((server)->flags &= ~(flag))
+#define NCP_SET_FLAG(server, flag)     ((server)->flags |= (flag))
+#define NCP_IS_FLAG(server, flag)      ((server)->flags & (flag))
+
+static inline int ncp_conn_valid(struct ncp_server *server)
+{
+       return ((server->conn_status & 0x11) == 0);
+}
+
+static inline void ncp_invalidate_conn(struct ncp_server *server)
+{
+       server->conn_status |= 0x01;
+}
+
+#endif
diff --git a/drivers/staging/ncpfs/ncplib_kernel.c b/drivers/staging/ncpfs/ncplib_kernel.c
new file mode 100644 (file)
index 0000000..804adfe
--- /dev/null
@@ -0,0 +1,1322 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  ncplib_kernel.c
+ *
+ *  Copyright (C) 1995, 1996 by Volker Lendecke
+ *  Modified for big endian by J.F. Chadima and David S. Miller
+ *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *  Modified 1999 Wolfram Pienkoss for NLS
+ *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "ncp_fs.h"
+
+static inline void assert_server_locked(struct ncp_server *server)
+{
+       if (server->lock == 0) {
+               ncp_dbg(1, "server not locked!\n");
+       }
+}
+
+static void ncp_add_byte(struct ncp_server *server, __u8 x)
+{
+       assert_server_locked(server);
+       *(__u8 *) (&(server->packet[server->current_size])) = x;
+       server->current_size += 1;
+       return;
+}
+
+static void ncp_add_word(struct ncp_server *server, __le16 x)
+{
+       assert_server_locked(server);
+       put_unaligned(x, (__le16 *) (&(server->packet[server->current_size])));
+       server->current_size += 2;
+       return;
+}
+
+static void ncp_add_be16(struct ncp_server *server, __u16 x)
+{
+       assert_server_locked(server);
+       put_unaligned(cpu_to_be16(x), (__be16 *) (&(server->packet[server->current_size])));
+       server->current_size += 2;
+}
+
+static void ncp_add_dword(struct ncp_server *server, __le32 x)
+{
+       assert_server_locked(server);
+       put_unaligned(x, (__le32 *) (&(server->packet[server->current_size])));
+       server->current_size += 4;
+       return;
+}
+
+static void ncp_add_be32(struct ncp_server *server, __u32 x)
+{
+       assert_server_locked(server);
+       put_unaligned(cpu_to_be32(x), (__be32 *)(&(server->packet[server->current_size])));
+       server->current_size += 4;
+}
+
+static inline void ncp_add_dword_lh(struct ncp_server *server, __u32 x) {
+       ncp_add_dword(server, cpu_to_le32(x));
+}
+
+static void ncp_add_mem(struct ncp_server *server, const void *source, int size)
+{
+       assert_server_locked(server);
+       memcpy(&(server->packet[server->current_size]), source, size);
+       server->current_size += size;
+       return;
+}
+
+static void ncp_add_pstring(struct ncp_server *server, const char *s)
+{
+       int len = strlen(s);
+       assert_server_locked(server);
+       if (len > 255) {
+               ncp_dbg(1, "string too long: %s\n", s);
+               len = 255;
+       }
+       ncp_add_byte(server, len);
+       ncp_add_mem(server, s, len);
+       return;
+}
+
+static inline void ncp_init_request(struct ncp_server *server)
+{
+       ncp_lock_server(server);
+
+       server->current_size = sizeof(struct ncp_request_header);
+       server->has_subfunction = 0;
+}
+
+static inline void ncp_init_request_s(struct ncp_server *server, int subfunction)
+{
+       ncp_lock_server(server);
+       
+       server->current_size = sizeof(struct ncp_request_header) + 2;
+       ncp_add_byte(server, subfunction);
+
+       server->has_subfunction = 1;
+}
+
+static inline char *
+ncp_reply_data(struct ncp_server *server, int offset)
+{
+       return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
+}
+
+static inline u8 BVAL(const void *data)
+{
+       return *(const u8 *)data;
+}
+
+static u8 ncp_reply_byte(struct ncp_server *server, int offset)
+{
+       return *(const u8 *)ncp_reply_data(server, offset);
+}
+
+static inline u16 WVAL_LH(const void *data)
+{
+       return get_unaligned_le16(data);
+}
+
+static u16
+ncp_reply_le16(struct ncp_server *server, int offset)
+{
+       return get_unaligned_le16(ncp_reply_data(server, offset));
+}
+
+static u16
+ncp_reply_be16(struct ncp_server *server, int offset)
+{
+       return get_unaligned_be16(ncp_reply_data(server, offset));
+}
+
+static inline u32 DVAL_LH(const void *data)
+{
+       return get_unaligned_le32(data);
+}
+
+static __le32
+ncp_reply_dword(struct ncp_server *server, int offset)
+{
+       return get_unaligned((__le32 *)ncp_reply_data(server, offset));
+}
+
+static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) {
+       return le32_to_cpu(ncp_reply_dword(server, offset));
+}
+
+int
+ncp_negotiate_buffersize(struct ncp_server *server, int size, int *target)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_be16(server, size);
+
+       if ((result = ncp_request(server, 33)) != 0) {
+               ncp_unlock_server(server);
+               return result;
+       }
+       *target = min_t(unsigned int, ncp_reply_be16(server, 0), size);
+
+       ncp_unlock_server(server);
+       return 0;
+}
+
+
+/* options: 
+ *     bit 0   ipx checksum
+ *     bit 1   packet signing
+ */
+int
+ncp_negotiate_size_and_options(struct ncp_server *server, 
+       int size, int options, int *ret_size, int *ret_options) {
+       int result;
+
+       /* there is minimum */
+       if (size < NCP_BLOCK_SIZE) size = NCP_BLOCK_SIZE;
+
+       ncp_init_request(server);
+       ncp_add_be16(server, size);
+       ncp_add_byte(server, options);
+       
+       if ((result = ncp_request(server, 0x61)) != 0)
+       {
+               ncp_unlock_server(server);
+               return result;
+       }
+
+       /* NCP over UDP returns 0 (!!!) */
+       result = ncp_reply_be16(server, 0);
+       if (result >= NCP_BLOCK_SIZE)
+               size = min(result, size);
+       *ret_size = size;
+       *ret_options = ncp_reply_byte(server, 4);
+
+       ncp_unlock_server(server);
+       return 0;
+}
+
+int ncp_get_volume_info_with_number(struct ncp_server* server,
+                            int n, struct ncp_volume_info* target) {
+       int result;
+       int len;
+
+       ncp_init_request_s(server, 44);
+       ncp_add_byte(server, n);
+
+       if ((result = ncp_request(server, 22)) != 0) {
+               goto out;
+       }
+       target->total_blocks = ncp_reply_dword_lh(server, 0);
+       target->free_blocks = ncp_reply_dword_lh(server, 4);
+       target->purgeable_blocks = ncp_reply_dword_lh(server, 8);
+       target->not_yet_purgeable_blocks = ncp_reply_dword_lh(server, 12);
+       target->total_dir_entries = ncp_reply_dword_lh(server, 16);
+       target->available_dir_entries = ncp_reply_dword_lh(server, 20);
+       target->sectors_per_block = ncp_reply_byte(server, 28);
+
+       memset(&(target->volume_name), 0, sizeof(target->volume_name));
+
+       result = -EIO;
+       len = ncp_reply_byte(server, 29);
+       if (len > NCP_VOLNAME_LEN) {
+               ncp_dbg(1, "volume name too long: %d\n", len);
+               goto out;
+       }
+       memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
+       result = 0;
+out:
+       ncp_unlock_server(server);
+       return result;
+}
+
+int ncp_get_directory_info(struct ncp_server* server, __u8 n, 
+                          struct ncp_volume_info* target) {
+       int result;
+       int len;
+
+       ncp_init_request_s(server, 45);
+       ncp_add_byte(server, n);
+
+       if ((result = ncp_request(server, 22)) != 0) {
+               goto out;
+       }
+       target->total_blocks = ncp_reply_dword_lh(server, 0);
+       target->free_blocks = ncp_reply_dword_lh(server, 4);
+       target->purgeable_blocks = 0;
+       target->not_yet_purgeable_blocks = 0;
+       target->total_dir_entries = ncp_reply_dword_lh(server, 8);
+       target->available_dir_entries = ncp_reply_dword_lh(server, 12);
+       target->sectors_per_block = ncp_reply_byte(server, 20);
+
+       memset(&(target->volume_name), 0, sizeof(target->volume_name));
+
+       result = -EIO;
+       len = ncp_reply_byte(server, 21);
+       if (len > NCP_VOLNAME_LEN) {
+               ncp_dbg(1, "volume name too long: %d\n", len);
+               goto out;
+       }
+       memcpy(&(target->volume_name), ncp_reply_data(server, 22), len);
+       result = 0;
+out:
+       ncp_unlock_server(server);
+       return result;
+}
+
+int
+ncp_close_file(struct ncp_server *server, const char *file_id)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 0);
+       ncp_add_mem(server, file_id, 6);
+
+       result = ncp_request(server, 66);
+       ncp_unlock_server(server);
+       return result;
+}
+
+int
+ncp_make_closed(struct inode *inode)
+{
+       int err;
+
+       err = 0;
+       mutex_lock(&NCP_FINFO(inode)->open_mutex);
+       if (atomic_read(&NCP_FINFO(inode)->opened) == 1) {
+               atomic_set(&NCP_FINFO(inode)->opened, 0);
+               err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle);
+
+               if (!err)
+                       ncp_vdbg("volnum=%d, dirent=%u, error=%d\n",
+                                NCP_FINFO(inode)->volNumber,
+                                NCP_FINFO(inode)->dirEntNum, err);
+       }
+       mutex_unlock(&NCP_FINFO(inode)->open_mutex);
+       return err;
+}
+
+static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
+                               __le32 dir_base, int have_dir_base, 
+                               const char *path)
+{
+       ncp_add_byte(server, vol_num);
+       ncp_add_dword(server, dir_base);
+       if (have_dir_base != 0) {
+               ncp_add_byte(server, 1);        /* dir_base */
+       } else {
+               ncp_add_byte(server, 0xff);     /* no handle */
+       }
+       if (path != NULL) {
+               ncp_add_byte(server, 1);        /* 1 component */
+               ncp_add_pstring(server, path);
+       } else {
+               ncp_add_byte(server, 0);
+       }
+}
+
+int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __le32 dirent,
+                       __u8* dirhandle) {
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 12);               /* subfunction */
+       ncp_add_byte(server, NW_NS_DOS);
+       ncp_add_byte(server, 0);
+       ncp_add_word(server, 0);
+       ncp_add_handle_path(server, volnum, dirent, 1, NULL);
+       if ((result = ncp_request(server, 87)) == 0) {
+               *dirhandle = ncp_reply_byte(server, 0);
+       }
+       ncp_unlock_server(server);
+       return result;
+}
+
+int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) {
+       int result;
+       
+       ncp_init_request_s(server, 20);
+       ncp_add_byte(server, dirhandle);
+       result = ncp_request(server, 22);
+       ncp_unlock_server(server);
+       return result;
+}
+
+void ncp_extract_file_info(const void *structure, struct nw_info_struct *target)
+{
+       const __u8 *name_len;
+       const int info_struct_size = offsetof(struct nw_info_struct, nameLen);
+
+       memcpy(target, structure, info_struct_size);
+       name_len = structure + info_struct_size;
+       target->nameLen = *name_len;
+       memcpy(target->entryName, name_len + 1, *name_len);
+       target->entryName[*name_len] = '\0';
+       target->volNumber = le32_to_cpu(target->volNumber);
+       return;
+}
+
+#ifdef CONFIG_NCPFS_NFS_NS
+static inline void ncp_extract_nfs_info(const unsigned char *structure,
+                                struct nw_nfs_info *target)
+{
+       target->mode = DVAL_LH(structure);
+       target->rdev = DVAL_LH(structure + 8);
+}
+#endif
+
+int ncp_obtain_nfs_info(struct ncp_server *server,
+                       struct nw_info_struct *target)
+
+{
+       int result = 0;
+#ifdef CONFIG_NCPFS_NFS_NS
+       __u32 volnum = target->volNumber;
+
+       if (ncp_is_nfs_extras(server, volnum)) {
+               ncp_init_request(server);
+               ncp_add_byte(server, 19);       /* subfunction */
+               ncp_add_byte(server, server->name_space[volnum]);
+               ncp_add_byte(server, NW_NS_NFS);
+               ncp_add_byte(server, 0);
+               ncp_add_byte(server, volnum);
+               ncp_add_dword(server, target->dirEntNum);
+               /* We must retrieve both nlinks and rdev, otherwise some server versions
+                  report zeroes instead of valid data */
+               ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV);
+
+               if ((result = ncp_request(server, 87)) == 0) {
+                       ncp_extract_nfs_info(ncp_reply_data(server, 0), &target->nfs);
+                       ncp_dbg(1, "(%s) mode=0%o, rdev=0x%x\n",
+                               target->entryName, target->nfs.mode,
+                               target->nfs.rdev);
+               } else {
+                       target->nfs.mode = 0;
+                       target->nfs.rdev = 0;
+               }
+               ncp_unlock_server(server);
+
+       } else
+#endif
+       {
+               target->nfs.mode = 0;
+               target->nfs.rdev = 0;
+       }
+       return result;
+}
+
+/*
+ * Returns information for a (one-component) name relative to
+ * the specified directory.
+ */
+int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path,
+                       struct nw_info_struct *target)
+{
+       __u8  volnum = NCP_FINFO(dir)->volNumber;
+       __le32 dirent = NCP_FINFO(dir)->dirEntNum;
+       int result;
+
+       if (target == NULL) {
+               pr_err("%s: invalid call\n", __func__);
+               return -EINVAL;
+       }
+       ncp_init_request(server);
+       ncp_add_byte(server, 6);        /* subfunction */
+       ncp_add_byte(server, server->name_space[volnum]);
+       ncp_add_byte(server, server->name_space[volnum]); /* N.B. twice ?? */
+       ncp_add_word(server, cpu_to_le16(0x8006));      /* get all */
+       ncp_add_dword(server, RIM_ALL);
+       ncp_add_handle_path(server, volnum, dirent, 1, path);
+
+       if ((result = ncp_request(server, 87)) != 0)
+               goto out;
+       ncp_extract_file_info(ncp_reply_data(server, 0), target);
+       ncp_unlock_server(server);
+       
+       result = ncp_obtain_nfs_info(server, target);
+       return result;
+
+out:
+       ncp_unlock_server(server);
+       return result;
+}
+
+#ifdef CONFIG_NCPFS_NFS_NS
+static int
+ncp_obtain_DOS_dir_base(struct ncp_server *server,
+               __u8 ns, __u8 volnum, __le32 dirent,
+               const char *path, /* At most 1 component */
+               __le32 *DOS_dir_base)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 6); /* subfunction */
+       ncp_add_byte(server, ns);
+       ncp_add_byte(server, ns);
+       ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
+       ncp_add_dword(server, RIM_DIRECTORY);
+       ncp_add_handle_path(server, volnum, dirent, 1, path);
+
+       if ((result = ncp_request(server, 87)) == 0)
+       {
+               if (DOS_dir_base) *DOS_dir_base=ncp_reply_dword(server, 0x34);
+       }
+       ncp_unlock_server(server);
+       return result;
+}
+#endif /* CONFIG_NCPFS_NFS_NS */
+
+static inline int
+ncp_get_known_namespace(struct ncp_server *server, __u8 volume)
+{
+#if defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS)
+       int result;
+       __u8 *namespace;
+       __u16 no_namespaces;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 24);       /* Subfunction: Get Name Spaces Loaded */
+       ncp_add_word(server, 0);
+       ncp_add_byte(server, volume);
+
+       if ((result = ncp_request(server, 87)) != 0) {
+               ncp_unlock_server(server);
+               return NW_NS_DOS; /* not result ?? */
+       }
+
+       result = NW_NS_DOS;
+       no_namespaces = ncp_reply_le16(server, 0);
+       namespace = ncp_reply_data(server, 2);
+
+       while (no_namespaces > 0) {
+               ncp_dbg(1, "found %d on %d\n", *namespace, volume);
+
+#ifdef CONFIG_NCPFS_NFS_NS
+               if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS)) 
+               {
+                       result = NW_NS_NFS;
+                       break;
+               }
+#endif /* CONFIG_NCPFS_NFS_NS */
+#ifdef CONFIG_NCPFS_OS2_NS
+               if ((*namespace == NW_NS_OS2) && !(server->m.flags&NCP_MOUNT_NO_OS2))
+               {
+                       result = NW_NS_OS2;
+               }
+#endif /* CONFIG_NCPFS_OS2_NS */
+               namespace += 1;
+               no_namespaces -= 1;
+       }
+       ncp_unlock_server(server);
+       return result;
+#else  /* neither OS2 nor NFS - only DOS */
+       return NW_NS_DOS;
+#endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
+}
+
+int
+ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns)
+{
+       int ns = ncp_get_known_namespace(server, volume);
+
+       if (ret_ns)
+               *ret_ns = ns;
+
+       ncp_dbg(1, "namespace[%d] = %d\n", volume, server->name_space[volume]);
+
+       if (server->name_space[volume] == ns)
+               return 0;
+       server->name_space[volume] = ns;
+       return 1;
+}
+
+static int
+ncp_ObtainSpecificDirBase(struct ncp_server *server,
+               __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
+               const char *path, /* At most 1 component */
+               __le32 *dirEntNum, __le32 *DosDirNum)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 6); /* subfunction */
+       ncp_add_byte(server, nsSrc);
+       ncp_add_byte(server, nsDst);
+       ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
+       ncp_add_dword(server, RIM_ALL);
+       ncp_add_handle_path(server, vol_num, dir_base, 1, path);
+
+       if ((result = ncp_request(server, 87)) != 0)
+       {
+               ncp_unlock_server(server);
+               return result;
+       }
+
+       if (dirEntNum)
+               *dirEntNum = ncp_reply_dword(server, 0x30);
+       if (DosDirNum)
+               *DosDirNum = ncp_reply_dword(server, 0x34);
+       ncp_unlock_server(server);
+       return 0;
+}
+
+int
+ncp_mount_subdir(struct ncp_server *server,
+                __u8 volNumber, __u8 srcNS, __le32 dirEntNum,
+                __u32* volume, __le32* newDirEnt, __le32* newDosEnt)
+{
+       int dstNS;
+       int result;
+
+       ncp_update_known_namespace(server, volNumber, &dstNS);
+       if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, 
+                                     dirEntNum, NULL, newDirEnt, newDosEnt)) != 0)
+       {
+               return result;
+       }
+       *volume = volNumber;
+       server->m.mounted_vol[1] = 0;
+       server->m.mounted_vol[0] = 'X';
+       return 0;
+}
+
+int 
+ncp_get_volume_root(struct ncp_server *server,
+                   const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent)
+{
+       int result;
+
+       ncp_dbg(1, "looking up vol %s\n", volname);
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 22);       /* Subfunction: Generate dir handle */
+       ncp_add_byte(server, 0);        /* DOS namespace */
+       ncp_add_byte(server, 0);        /* reserved */
+       ncp_add_byte(server, 0);        /* reserved */
+       ncp_add_byte(server, 0);        /* reserved */
+
+       ncp_add_byte(server, 0);        /* faked volume number */
+       ncp_add_dword(server, 0);       /* faked dir_base */
+       ncp_add_byte(server, 0xff);     /* Don't have a dir_base */
+       ncp_add_byte(server, 1);        /* 1 path component */
+       ncp_add_pstring(server, volname);
+
+       if ((result = ncp_request(server, 87)) != 0) {
+               ncp_unlock_server(server);
+               return result;
+       }
+       *dirent = *dosdirent = ncp_reply_dword(server, 4);
+       *volume = ncp_reply_byte(server, 8);
+       ncp_unlock_server(server);
+       return 0;
+}
+
+int
+ncp_lookup_volume(struct ncp_server *server,
+                 const char *volname, struct nw_info_struct *target)
+{
+       int result;
+
+       memset(target, 0, sizeof(*target));
+       result = ncp_get_volume_root(server, volname,
+                       &target->volNumber, &target->dirEntNum, &target->DosDirNum);
+       if (result) {
+               return result;
+       }
+       ncp_update_known_namespace(server, target->volNumber, NULL);
+       target->nameLen = strlen(volname);
+       memcpy(target->entryName, volname, target->nameLen+1);
+       target->attributes = aDIR;
+       /* set dates to Jan 1, 1986  00:00 */
+       target->creationTime = target->modifyTime = cpu_to_le16(0x0000);
+       target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21);
+       target->nfs.mode = 0;
+       return 0;
+}
+
+int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server,
+                                           struct inode *dir,
+                                           const char *path,
+                                           __le32 info_mask,
+                                           const struct nw_modify_dos_info *info)
+{
+       __u8  volnum = NCP_FINFO(dir)->volNumber;
+       __le32 dirent = NCP_FINFO(dir)->dirEntNum;
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 7);        /* subfunction */
+       ncp_add_byte(server, server->name_space[volnum]);
+       ncp_add_byte(server, 0);        /* reserved */
+       ncp_add_word(server, cpu_to_le16(0x8006));      /* search attribs: all */
+
+       ncp_add_dword(server, info_mask);
+       ncp_add_mem(server, info, sizeof(*info));
+       ncp_add_handle_path(server, volnum, dirent, 1, path);
+
+       result = ncp_request(server, 87);
+       ncp_unlock_server(server);
+       return result;
+}
+
+int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
+                                      struct inode *dir,
+                                      __le32 info_mask,
+                                      const struct nw_modify_dos_info *info)
+{
+       return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL,
+               info_mask, info);
+}
+
+#ifdef CONFIG_NCPFS_NFS_NS
+int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
+                              __u32 mode, __u32 rdev)
+
+{
+       int result = 0;
+
+       ncp_init_request(server);
+       if (server->name_space[volnum] == NW_NS_NFS) {
+               ncp_add_byte(server, 25);       /* subfunction */
+               ncp_add_byte(server, server->name_space[volnum]);
+               ncp_add_byte(server, NW_NS_NFS);
+               ncp_add_byte(server, volnum);
+               ncp_add_dword(server, dirent);
+               /* we must always operate on both nlinks and rdev, otherwise
+                  rdev is not set */
+               ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV);
+               ncp_add_dword_lh(server, mode);
+               ncp_add_dword_lh(server, 1);    /* nlinks */
+               ncp_add_dword_lh(server, rdev);
+               result = ncp_request(server, 87);
+       }
+       ncp_unlock_server(server);
+       return result;
+}
+#endif
+
+
+static int
+ncp_DeleteNSEntry(struct ncp_server *server,
+                 __u8 have_dir_base, __u8 volnum, __le32 dirent,
+                 const char* name, __u8 ns, __le16 attr)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 8);        /* subfunction */
+       ncp_add_byte(server, ns);
+       ncp_add_byte(server, 0);        /* reserved */
+       ncp_add_word(server, attr);     /* search attribs: all */
+       ncp_add_handle_path(server, volnum, dirent, have_dir_base, name);
+
+       result = ncp_request(server, 87);
+       ncp_unlock_server(server);
+       return result;
+}
+
+int
+ncp_del_file_or_subdir2(struct ncp_server *server,
+                       struct dentry *dentry)
+{
+       struct inode *inode = d_inode(dentry);
+       __u8  volnum;
+       __le32 dirent;
+
+       if (!inode) {
+               return 0xFF;    /* Any error */
+       }
+       volnum = NCP_FINFO(inode)->volNumber;
+       dirent = NCP_FINFO(inode)->DosDirNum;
+       return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
+}
+
+int
+ncp_del_file_or_subdir(struct ncp_server *server,
+                      struct inode *dir, const char *name)
+{
+       __u8  volnum = NCP_FINFO(dir)->volNumber;
+       __le32 dirent = NCP_FINFO(dir)->dirEntNum;
+       int name_space;
+
+       name_space = server->name_space[volnum];
+#ifdef CONFIG_NCPFS_NFS_NS
+       if (name_space == NW_NS_NFS)
+       {
+               int result;
+               result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent);
+               if (result) return result;
+               name = NULL;
+               name_space = NW_NS_DOS;
+       }
+#endif /* CONFIG_NCPFS_NFS_NS */
+       return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006));
+}
+
+static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
+{
+       __le16 *dest = (__le16 *) ret;
+       dest[1] = cpu_to_le16(v0);
+       dest[2] = cpu_to_le16(v1);
+       dest[0] = cpu_to_le16(v0 + 1);
+       return;
+}
+
+/* If both dir and name are NULL, then in target there's already a
+   looked-up entry that wants to be opened. */
+int ncp_open_create_file_or_subdir(struct ncp_server *server,
+                                  struct inode *dir, const char *name,
+                                  int open_create_mode,
+                                  __le32 create_attributes,
+                                  __le16 desired_acc_rights,
+                                  struct ncp_entry_info *target)
+{
+       __le16 search_attribs = cpu_to_le16(0x0006);
+       __u8  volnum;
+       __le32 dirent;
+       int result;
+
+       volnum = NCP_FINFO(dir)->volNumber;
+       dirent = NCP_FINFO(dir)->dirEntNum;
+
+       if ((create_attributes & aDIR) != 0) {
+               search_attribs |= cpu_to_le16(0x8000);
+       }
+       ncp_init_request(server);
+       ncp_add_byte(server, 1);        /* subfunction */
+       ncp_add_byte(server, server->name_space[volnum]);
+       ncp_add_byte(server, open_create_mode);
+       ncp_add_word(server, search_attribs);
+       ncp_add_dword(server, RIM_ALL);
+       ncp_add_dword(server, create_attributes);
+       /* The desired acc rights seem to be the inherited rights mask
+          for directories */
+       ncp_add_word(server, desired_acc_rights);
+       ncp_add_handle_path(server, volnum, dirent, 1, name);
+
+       if ((result = ncp_request(server, 87)) != 0)
+               goto out;
+       if (!(create_attributes & aDIR))
+               target->opened = 1;
+
+       /* in target there's a new finfo to fill */
+       ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
+       target->volume = target->i.volNumber;
+       ConvertToNWfromDWORD(ncp_reply_le16(server, 0),
+                            ncp_reply_le16(server, 2),
+                            target->file_handle);
+       
+       ncp_unlock_server(server);
+
+       (void)ncp_obtain_nfs_info(server, &(target->i));
+       return 0;
+
+out:
+       ncp_unlock_server(server);
+       return result;
+}
+
+int
+ncp_initialize_search(struct ncp_server *server, struct inode *dir,
+                       struct nw_search_sequence *target)
+{
+       __u8  volnum = NCP_FINFO(dir)->volNumber;
+       __le32 dirent = NCP_FINFO(dir)->dirEntNum;
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 2);        /* subfunction */
+       ncp_add_byte(server, server->name_space[volnum]);
+       ncp_add_byte(server, 0);        /* reserved */
+       ncp_add_handle_path(server, volnum, dirent, 1, NULL);
+
+       result = ncp_request(server, 87);
+       if (result)
+               goto out;
+       memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
+
+out:
+       ncp_unlock_server(server);
+       return result;
+}
+
+int ncp_search_for_fileset(struct ncp_server *server,
+                          struct nw_search_sequence *seq,
+                          int* more,
+                          int* cnt,
+                          char* buffer,
+                          size_t bufsize,
+                          char** rbuf,
+                          size_t* rsize)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 20);
+       ncp_add_byte(server, server->name_space[seq->volNumber]);
+       ncp_add_byte(server, 0);                /* datastream */
+       ncp_add_word(server, cpu_to_le16(0x8006));
+       ncp_add_dword(server, RIM_ALL);
+       ncp_add_word(server, cpu_to_le16(32767));       /* max returned items */
+       ncp_add_mem(server, seq, 9);
+#ifdef CONFIG_NCPFS_NFS_NS
+       if (server->name_space[seq->volNumber] == NW_NS_NFS) {
+               ncp_add_byte(server, 0);        /* 0 byte pattern */
+       } else 
+#endif
+       {
+               ncp_add_byte(server, 2);        /* 2 byte pattern */
+               ncp_add_byte(server, 0xff);     /* following is a wildcard */
+               ncp_add_byte(server, '*');
+       }
+       result = ncp_request2(server, 87, buffer, bufsize);
+       if (result) {
+               ncp_unlock_server(server);
+               return result;
+       }
+       if (server->ncp_reply_size < 12) {
+               ncp_unlock_server(server);
+               return 0xFF;
+       }
+       *rsize = server->ncp_reply_size - 12;
+       ncp_unlock_server(server);
+       buffer = buffer + sizeof(struct ncp_reply_header);
+       *rbuf = buffer + 12;
+       *cnt = WVAL_LH(buffer + 10);
+       *more = BVAL(buffer + 9);
+       memcpy(seq, buffer, 9);
+       return 0;
+}
+
+static int
+ncp_RenameNSEntry(struct ncp_server *server,
+                 struct inode *old_dir, const char *old_name, __le16 old_type,
+                 struct inode *new_dir, const char *new_name)
+{
+       int result = -EINVAL;
+
+       if ((old_dir == NULL) || (old_name == NULL) ||
+           (new_dir == NULL) || (new_name == NULL))
+               goto out;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 4);        /* subfunction */
+       ncp_add_byte(server, server->name_space[NCP_FINFO(old_dir)->volNumber]);
+       ncp_add_byte(server, 1);        /* rename flag */
+       ncp_add_word(server, old_type); /* search attributes */
+
+       /* source Handle Path */
+       ncp_add_byte(server, NCP_FINFO(old_dir)->volNumber);
+       ncp_add_dword(server, NCP_FINFO(old_dir)->dirEntNum);
+       ncp_add_byte(server, 1);
+       ncp_add_byte(server, 1);        /* 1 source component */
+
+       /* dest Handle Path */
+       ncp_add_byte(server, NCP_FINFO(new_dir)->volNumber);
+       ncp_add_dword(server, NCP_FINFO(new_dir)->dirEntNum);
+       ncp_add_byte(server, 1);
+       ncp_add_byte(server, 1);        /* 1 destination component */
+
+       /* source path string */
+       ncp_add_pstring(server, old_name);
+       /* dest path string */
+       ncp_add_pstring(server, new_name);
+
+       result = ncp_request(server, 87);
+       ncp_unlock_server(server);
+out:
+       return result;
+}
+
+int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
+                               struct inode *old_dir, const char *old_name,
+                               struct inode *new_dir, const char *new_name)
+{
+        int result;
+        __le16 old_type = cpu_to_le16(0x06);
+
+/* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */
+       result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
+                                          new_dir, new_name);
+        if (result == 0xFF)    /* File Not Found, try directory */
+       {
+               old_type = cpu_to_le16(0x16);
+               result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
+                                                  new_dir, new_name);
+       }
+       if (result != 0x92) return result;      /* All except NO_FILES_RENAMED */
+       result = ncp_del_file_or_subdir(server, new_dir, new_name);
+       if (result != 0) return -EACCES;
+       result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
+                                          new_dir, new_name);
+       return result;
+}
+       
+
+/* We have to transfer to/from user space */
+int
+ncp_read_kernel(struct ncp_server *server, const char *file_id,
+            __u32 offset, __u16 to_read, char *target, int *bytes_read)
+{
+       const char *source;
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 0);
+       ncp_add_mem(server, file_id, 6);
+       ncp_add_be32(server, offset);
+       ncp_add_be16(server, to_read);
+
+       if ((result = ncp_request(server, 72)) != 0) {
+               goto out;
+       }
+       *bytes_read = ncp_reply_be16(server, 0);
+       source = ncp_reply_data(server, 2 + (offset & 1));
+
+       memcpy(target, source, *bytes_read);
+out:
+       ncp_unlock_server(server);
+       return result;
+}
+
+/* There is a problem... egrep and some other silly tools do:
+       x = mmap(NULL, MAP_PRIVATE, PROT_READ|PROT_WRITE, <ncpfs fd>, 32768);
+       read(<ncpfs fd>, x, 32768);
+   Now copying read result by copy_to_user causes pagefault. This pagefault
+   could not be handled because of server was locked due to read. So we have
+   to use temporary buffer. So ncp_unlock_server must be done before
+   copy_to_user (and for write, copy_from_user must be done before 
+   ncp_init_request... same applies for send raw packet ioctl). Because of
+   file is normally read in bigger chunks, caller provides kmalloced 
+   (vmalloced) chunk of memory with size >= to_read...
+ */
+int
+ncp_read_bounce(struct ncp_server *server, const char *file_id,
+        __u32 offset, __u16 to_read, struct iov_iter *to,
+        int *bytes_read, void *bounce, __u32 bufsize)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 0);
+       ncp_add_mem(server, file_id, 6);
+       ncp_add_be32(server, offset);
+       ncp_add_be16(server, to_read);
+       result = ncp_request2(server, 72, bounce, bufsize);
+       ncp_unlock_server(server);
+       if (!result) {
+               int len = get_unaligned_be16((char *)bounce +
+                         sizeof(struct ncp_reply_header));
+               result = -EIO;
+               if (len <= to_read) {
+                       char* source;
+
+                       source = (char*)bounce + 
+                                sizeof(struct ncp_reply_header) + 2 + 
+                                (offset & 1);
+                       *bytes_read = len;
+                       result = 0;
+                       if (copy_to_iter(source, len, to) != len)
+                               result = -EFAULT;
+               }
+       }
+       return result;
+}
+
+int
+ncp_write_kernel(struct ncp_server *server, const char *file_id,
+                __u32 offset, __u16 to_write,
+                const char *source, int *bytes_written)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 0);
+       ncp_add_mem(server, file_id, 6);
+       ncp_add_be32(server, offset);
+       ncp_add_be16(server, to_write);
+       ncp_add_mem(server, source, to_write);
+       
+       if ((result = ncp_request(server, 73)) == 0)
+               *bytes_written = to_write;
+       ncp_unlock_server(server);
+       return result;
+}
+
+#ifdef CONFIG_NCPFS_IOCTL_LOCKING
+int
+ncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id,
+         __u8 locktype, __u32 offset, __u32 length, __u16 timeout)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, locktype);
+       ncp_add_mem(server, file_id, 6);
+       ncp_add_be32(server, offset);
+       ncp_add_be32(server, length);
+       ncp_add_be16(server, timeout);
+
+       if ((result = ncp_request(server, 0x1A)) != 0)
+       {
+               ncp_unlock_server(server);
+               return result;
+       }
+       ncp_unlock_server(server);
+       return 0;
+}
+
+int
+ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id,
+         __u32 offset, __u32 length)
+{
+       int result;
+
+       ncp_init_request(server);
+       ncp_add_byte(server, 0);        /* who knows... lanalyzer says that */
+       ncp_add_mem(server, file_id, 6);
+       ncp_add_be32(server, offset);
+       ncp_add_be32(server, length);
+
+       if ((result = ncp_request(server, 0x1E)) != 0)
+       {
+               ncp_unlock_server(server);
+               return result;
+       }
+       ncp_unlock_server(server);
+       return 0;
+}
+#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
+
+#ifdef CONFIG_NCPFS_NLS
+/* This are the NLS conversion routines with inspirations and code parts
+ * from the vfat file system and hints from Petr Vandrovec.
+ */
+
+int
+ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen,
+               const unsigned char *iname, unsigned int ilen, int cc)
+{
+       struct nls_table *in = server->nls_io;
+       struct nls_table *out = server->nls_vol;
+       unsigned char *vname_start;
+       unsigned char *vname_end;
+       const unsigned char *iname_end;
+
+       iname_end = iname + ilen;
+       vname_start = vname;
+       vname_end = vname + *vlen - 1;
+
+       while (iname < iname_end) {
+               int chl;
+               wchar_t ec;
+
+               if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
+                       int k;
+                       unicode_t u;
+
+                       k = utf8_to_utf32(iname, iname_end - iname, &u);
+                       if (k < 0 || u > MAX_WCHAR_T)
+                               return -EINVAL;
+                       iname += k;
+                       ec = u;
+               } else {
+                       if (*iname == NCP_ESC) {
+                               int k;
+
+                               if (iname_end - iname < 5)
+                                       goto nospec;
+
+                               ec = 0;
+                               for (k = 1; k < 5; k++) {
+                                       unsigned char nc;
+
+                                       nc = iname[k] - '0';
+                                       if (nc >= 10) {
+                                               nc -= 'A' - '0' - 10;
+                                               if ((nc < 10) || (nc > 15)) {
+                                                       goto nospec;
+                                               }
+                                       }
+                                       ec = (ec << 4) | nc;
+                               }
+                               iname += 5;
+                       } else {
+nospec:;                       
+                               if ( (chl = in->char2uni(iname, iname_end - iname, &ec)) < 0)
+                                       return chl;
+                               iname += chl;
+                       }
+               }
+
+               /* unitoupper should be here! */
+
+               chl = out->uni2char(ec, vname, vname_end - vname);
+               if (chl < 0)
+                       return chl;
+
+               /* this is wrong... */
+               if (cc) {
+                       int chi;
+
+                       for (chi = 0; chi < chl; chi++){
+                               vname[chi] = ncp_toupper(out, vname[chi]);
+                       }
+               }
+               vname += chl;
+       }
+
+       *vname = 0;
+       *vlen = vname - vname_start;
+       return 0;
+}
+
+int
+ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen,
+               const unsigned char *vname, unsigned int vlen, int cc)
+{
+       struct nls_table *in = server->nls_vol;
+       struct nls_table *out = server->nls_io;
+       const unsigned char *vname_end;
+       unsigned char *iname_start;
+       unsigned char *iname_end;
+       unsigned char *vname_cc;
+       int err;
+
+       vname_cc = NULL;
+
+       if (cc) {
+               int i;
+
+               /* this is wrong! */
+               vname_cc = kmalloc(vlen, GFP_KERNEL);
+               if (!vname_cc)
+                       return -ENOMEM;
+               for (i = 0; i < vlen; i++)
+                       vname_cc[i] = ncp_tolower(in, vname[i]);
+               vname = vname_cc;
+       }
+
+       iname_start = iname;
+       iname_end = iname + *ilen - 1;
+       vname_end = vname + vlen;
+
+       while (vname < vname_end) {
+               wchar_t ec;
+               int chl;
+
+               if ( (chl = in->char2uni(vname, vname_end - vname, &ec)) < 0) {
+                       err = chl;
+                       goto quit;
+               }
+               vname += chl;
+
+               /* unitolower should be here! */
+
+               if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
+                       int k;
+
+                       k = utf32_to_utf8(ec, iname, iname_end - iname);
+                       if (k < 0) {
+                               err = -ENAMETOOLONG;
+                               goto quit;
+                       }
+                       iname += k;
+               } else {
+                       if ( (chl = out->uni2char(ec, iname, iname_end - iname)) >= 0) {
+                               iname += chl;
+                       } else {
+                               int k;
+
+                               if (iname_end - iname < 5) {
+                                       err = -ENAMETOOLONG;
+                                       goto quit;
+                               }
+                               *iname = NCP_ESC;
+                               for (k = 4; k > 0; k--) {
+                                       unsigned char v;
+                                       
+                                       v = (ec & 0xF) + '0';
+                                       if (v > '9') {
+                                               v += 'A' - '9' - 1;
+                                       }
+                                       iname[k] = v;
+                                       ec >>= 4;
+                               }
+                               iname += 5;
+                       }
+               }
+       }
+
+       *iname = 0;
+       *ilen = iname - iname_start;
+       err = 0;
+quit:;
+       if (cc)
+               kfree(vname_cc);
+       return err;
+}
+
+#else
+
+int
+ncp__io2vol(unsigned char *vname, unsigned int *vlen,
+               const unsigned char *iname, unsigned int ilen, int cc)
+{
+       int i;
+
+       if (*vlen <= ilen)
+               return -ENAMETOOLONG;
+
+       if (cc)
+               for (i = 0; i < ilen; i++) {
+                       *vname = toupper(*iname);
+                       vname++;
+                       iname++;
+               }
+       else {
+               memmove(vname, iname, ilen);
+               vname += ilen;
+       }
+
+       *vlen = ilen;
+       *vname = 0;
+       return 0;
+}
+
+int
+ncp__vol2io(unsigned char *iname, unsigned int *ilen,
+               const unsigned char *vname, unsigned int vlen, int cc)
+{
+       int i;
+
+       if (*ilen <= vlen)
+               return -ENAMETOOLONG;
+
+       if (cc)
+               for (i = 0; i < vlen; i++) {
+                       *iname = tolower(*vname);
+                       iname++;
+                       vname++;
+               }
+       else {
+               memmove(iname, vname, vlen);
+               iname += vlen;
+       }
+
+       *ilen = vlen;
+       *iname = 0;
+       return 0;
+}
+
+#endif
diff --git a/drivers/staging/ncpfs/ncplib_kernel.h b/drivers/staging/ncpfs/ncplib_kernel.h
new file mode 100644 (file)
index 0000000..aaae8aa
--- /dev/null
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  ncplib_kernel.h
+ *
+ *  Copyright (C) 1995, 1996 by Volker Lendecke
+ *  Modified for big endian by J.F. Chadima and David S. Miller
+ *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *  Modified 1998, 1999 Wolfram Pienkoss for NLS
+ *  Modified 1999 Wolfram Pienkoss for directory caching
+ *
+ */
+
+#ifndef _NCPLIB_H
+#define _NCPLIB_H
+
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/pagemap.h>
+
+#include <linux/uaccess.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include <asm/string.h>
+
+#ifdef CONFIG_NCPFS_NLS
+#include <linux/nls.h>
+#else
+#include <linux/ctype.h>
+#endif /* CONFIG_NCPFS_NLS */
+
+#define NCP_MIN_SYMLINK_SIZE   8
+#define NCP_MAX_SYMLINK_SIZE   512
+
+#define NCP_BLOCK_SHIFT                9
+#define NCP_BLOCK_SIZE         (1 << (NCP_BLOCK_SHIFT))
+
+int ncp_negotiate_buffersize(struct ncp_server *, int, int *);
+int ncp_negotiate_size_and_options(struct ncp_server *server, int size,
+                         int options, int *ret_size, int *ret_options);
+
+int ncp_get_volume_info_with_number(struct ncp_server* server, int n,
+                                   struct ncp_volume_info *target);
+
+int ncp_get_directory_info(struct ncp_server* server, __u8 dirhandle,
+                          struct ncp_volume_info* target);
+
+int ncp_close_file(struct ncp_server *, const char *);
+static inline int ncp_read_bounce_size(__u32 size) {
+       return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8;
+};
+int ncp_read_bounce(struct ncp_server *, const char *, __u32, __u16, 
+               struct iov_iter *, int *, void *bounce, __u32 bouncelen);
+int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, 
+               char *, int *);
+int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16,
+               const char *, int *);
+
+static inline void ncp_inode_close(struct inode *inode) {
+       atomic_dec(&NCP_FINFO(inode)->opened);
+}
+
+void ncp_extract_file_info(const void* src, struct nw_info_struct* target);
+int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *,
+               struct nw_info_struct *target);
+int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
+int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns);
+int ncp_get_volume_root(struct ncp_server *server, const char *volname,
+                       __u32 *volume, __le32 *dirent, __le32 *dosdirent);
+int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *);
+int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *,
+        __le32, const struct nw_modify_dos_info *info);
+int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *,
+        const char* path, __le32, const struct nw_modify_dos_info *info);
+int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent,
+                       __u32 mode, __u32 rdev);
+
+int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
+int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *);
+int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *,
+                               int, __le32, __le16, struct ncp_entry_info *);
+
+int ncp_initialize_search(struct ncp_server *, struct inode *,
+                     struct nw_search_sequence *target);
+int ncp_search_for_fileset(struct ncp_server *server,
+                          struct nw_search_sequence *seq,
+                          int* more, int* cnt,
+                          char* buffer, size_t bufsize,
+                          char** rbuf, size_t* rsize);
+
+int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
+                             struct inode *, const char *, struct inode *, const char *);
+
+
+int
+ncp_LogPhysicalRecord(struct ncp_server *server,
+                     const char *file_id, __u8 locktype,
+                     __u32 offset, __u32 length, __u16 timeout);
+
+#ifdef CONFIG_NCPFS_IOCTL_LOCKING
+int
+ncp_ClearPhysicalRecord(struct ncp_server *server,
+                       const char *file_id,
+                       __u32 offset, __u32 length);
+#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
+
+int
+ncp_mount_subdir(struct ncp_server *, __u8, __u8, __le32,
+                __u32* volume, __le32* dirent, __le32* dosdirent);
+int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __le32 dirent, __u8 *dirhandle);
+int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle);
+
+int ncp_create_new(struct inode *dir, struct dentry *dentry,
+                          umode_t mode, dev_t rdev, __le32 attributes);
+
+static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int volnum) {
+#ifdef CONFIG_NCPFS_NFS_NS
+       return (server->m.flags & NCP_MOUNT_NFS_EXTRAS) &&
+              (server->name_space[volnum] == NW_NS_NFS);
+#else
+       return 0;
+#endif
+}
+
+#ifdef CONFIG_NCPFS_NLS
+
+int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *,
+                               const unsigned char *, unsigned int, int);
+int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *,
+                               const unsigned char *, unsigned int, int);
+
+#define NCP_ESC                        ':'
+#define NCP_IO_TABLE(sb)       (NCP_SBP(sb)->nls_io)
+#define ncp_tolower(t, c)      nls_tolower(t, c)
+#define ncp_toupper(t, c)      nls_toupper(t, c)
+#define ncp_strnicmp(t, s1, s2, len) \
+       nls_strnicmp(t, s1, s2, len)
+#define ncp_io2vol(S,m,i,n,k,U)        ncp__io2vol(S,m,i,n,k,U)
+#define ncp_vol2io(S,m,i,n,k,U)        ncp__vol2io(S,m,i,n,k,U)
+
+#else
+
+int ncp__io2vol(unsigned char *, unsigned int *,
+                               const unsigned char *, unsigned int, int);
+int ncp__vol2io(unsigned char *, unsigned int *,
+                               const unsigned char *, unsigned int, int);
+
+#define NCP_IO_TABLE(sb)       NULL
+#define ncp_tolower(t, c)      tolower(c)
+#define ncp_toupper(t, c)      toupper(c)
+#define ncp_io2vol(S,m,i,n,k,U)        ncp__io2vol(m,i,n,k,U)
+#define ncp_vol2io(S,m,i,n,k,U)        ncp__vol2io(m,i,n,k,U)
+
+
+static inline int ncp_strnicmp(const struct nls_table *t,
+               const unsigned char *s1, const unsigned char *s2, int len)
+{
+       while (len--) {
+               if (tolower(*s1++) != tolower(*s2++))
+                       return 1;
+       }
+
+       return 0;
+}
+
+#endif /* CONFIG_NCPFS_NLS */
+
+#define NCP_GET_AGE(dentry)    (jiffies - (dentry)->d_time)
+#define NCP_MAX_AGE(server)    atomic_read(&(server)->dentry_ttl)
+#define NCP_TEST_AGE(server,dentry)    (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server))
+
+static inline void
+ncp_age_dentry(struct ncp_server* server, struct dentry* dentry)
+{
+       dentry->d_time = jiffies - NCP_MAX_AGE(server);
+}
+
+static inline void
+ncp_new_dentry(struct dentry* dentry)
+{
+       dentry->d_time = jiffies;
+}
+
+struct ncp_cache_head {
+       time_t          mtime;
+       unsigned long   time;   /* cache age */
+       unsigned long   end;    /* last valid fpos in cache */
+       int             eof;
+};
+
+#define NCP_DIRCACHE_SIZE      ((int)(PAGE_SIZE/sizeof(struct dentry *)))
+union ncp_dir_cache {
+       struct ncp_cache_head   head;
+       struct dentry           *dentry[NCP_DIRCACHE_SIZE];
+};
+
+#define NCP_FIRSTCACHE_SIZE    ((int)((NCP_DIRCACHE_SIZE * \
+       sizeof(struct dentry *) - sizeof(struct ncp_cache_head)) / \
+       sizeof(struct dentry *)))
+
+#define NCP_DIRCACHE_START     (NCP_DIRCACHE_SIZE - NCP_FIRSTCACHE_SIZE)
+
+struct ncp_cache_control {
+       struct  ncp_cache_head          head;
+       struct  page                    *page;
+       union   ncp_dir_cache           *cache;
+       unsigned long                   fpos, ofs;
+       int                             filled, valid, idx;
+};
+
+#endif /* _NCPLIB_H */
diff --git a/drivers/staging/ncpfs/ncpsign_kernel.c b/drivers/staging/ncpfs/ncpsign_kernel.c
new file mode 100644 (file)
index 0000000..8085b1a
--- /dev/null
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  ncpsign_kernel.c
+ *
+ *  Arne de Bruijn (arne@knoware.nl), 1997
+ *
+ */
+
+
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+
+#include <linux/string.h>
+#include <linux/ncp.h>
+#include <linux/bitops.h>
+#include "ncp_fs.h"
+#include "ncpsign_kernel.h"
+
+/* i386: 32-bit, little endian, handles mis-alignment */
+#ifdef __i386__
+#define GET_LE32(p) (*(const int *)(p))
+#define PUT_LE32(p,v) { *(int *)(p)=v; }
+#else
+/* from include/ncplib.h */
+#define BVAL(buf,pos) (((const __u8 *)(buf))[pos])
+#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
+#define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val))
+
+static inline __u16
+WVAL_LH(const __u8 * buf, int pos)
+{
+       return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8;
+}
+static inline __u32
+DVAL_LH(const __u8 * buf, int pos)
+{
+       return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16;
+}
+static inline void
+WSET_LH(__u8 * buf, int pos, __u16 val)
+{
+       BSET(buf, pos, val & 0xff);
+       BSET(buf, pos + 1, val >> 8);
+}
+static inline void
+DSET_LH(__u8 * buf, int pos, __u32 val)
+{
+       WSET_LH(buf, pos, val & 0xffff);
+       WSET_LH(buf, pos + 2, val >> 16);
+}
+
+#define GET_LE32(p) DVAL_LH(p,0)
+#define PUT_LE32(p,v) DSET_LH(p,0,v)
+#endif
+
+static void nwsign(char *r_data1, char *r_data2, char *outdata) {
+ int i;
+ unsigned int w0,w1,w2,w3;
+ static int rbit[4]={0, 2, 1, 3};
+#ifdef __i386__
+ unsigned int *data2=(unsigned int *)r_data2;
+#else
+ unsigned int data2[16];
+ for (i=0;i<16;i++)
+  data2[i]=GET_LE32(r_data2+(i<<2));
+#endif 
+ w0=GET_LE32(r_data1);
+ w1=GET_LE32(r_data1+4);
+ w2=GET_LE32(r_data1+8);
+ w3=GET_LE32(r_data1+12);
+ for (i=0;i<16;i+=4) {
+  w0=rol32(w0 + ((w1 & w2) | ((~w1) & w3)) + data2[i+0],3);
+  w3=rol32(w3 + ((w0 & w1) | ((~w0) & w2)) + data2[i+1],7);
+  w2=rol32(w2 + ((w3 & w0) | ((~w3) & w1)) + data2[i+2],11);
+  w1=rol32(w1 + ((w2 & w3) | ((~w2) & w0)) + data2[i+3],19);
+ }
+ for (i=0;i<4;i++) {
+  w0=rol32(w0 + (((w2 | w3) & w1) | (w2 & w3)) + 0x5a827999 + data2[i+0],3);
+  w3=rol32(w3 + (((w1 | w2) & w0) | (w1 & w2)) + 0x5a827999 + data2[i+4],5);
+  w2=rol32(w2 + (((w0 | w1) & w3) | (w0 & w1)) + 0x5a827999 + data2[i+8],9);
+  w1=rol32(w1 + (((w3 | w0) & w2) | (w3 & w0)) + 0x5a827999 + data2[i+12],13);
+ }
+ for (i=0;i<4;i++) {
+  w0=rol32(w0 + ((w1 ^ w2) ^ w3) + 0x6ed9eba1 + data2[rbit[i]+0],3);
+  w3=rol32(w3 + ((w0 ^ w1) ^ w2) + 0x6ed9eba1 + data2[rbit[i]+8],9);
+  w2=rol32(w2 + ((w3 ^ w0) ^ w1) + 0x6ed9eba1 + data2[rbit[i]+4],11);
+  w1=rol32(w1 + ((w2 ^ w3) ^ w0) + 0x6ed9eba1 + data2[rbit[i]+12],15);
+ }
+ PUT_LE32(outdata,(w0+GET_LE32(r_data1)) & 0xffffffff);
+ PUT_LE32(outdata+4,(w1+GET_LE32(r_data1+4)) & 0xffffffff);
+ PUT_LE32(outdata+8,(w2+GET_LE32(r_data1+8)) & 0xffffffff);
+ PUT_LE32(outdata+12,(w3+GET_LE32(r_data1+12)) & 0xffffffff);
+}
+
+/* Make a signature for the current packet and add it at the end of the */
+/* packet. */
+void __sign_packet(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, void *sign_buff) {
+       unsigned char data[64];
+
+       memcpy(data, server->sign_root, 8);
+       *(__u32*)(data + 8) = totalsize;
+       if (size < 52) {
+               memcpy(data + 12, packet, size);
+               memset(data + 12 + size, 0, 52 - size);
+       } else {
+               memcpy(data + 12, packet, 52);
+       }
+       nwsign(server->sign_last, data, server->sign_last);
+       memcpy(sign_buff, server->sign_last, 8);
+}
+
+int sign_verify_reply(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, const void *sign_buff) {
+       unsigned char data[64];
+       unsigned char hash[16];
+
+       memcpy(data, server->sign_root, 8);
+       *(__u32*)(data + 8) = totalsize;
+       if (size < 52) {
+               memcpy(data + 12, packet, size);
+               memset(data + 12 + size, 0, 52 - size);
+       } else {
+               memcpy(data + 12, packet, 52);
+       }
+       nwsign(server->sign_last, data, hash);
+       return memcmp(sign_buff, hash, 8);
+}
+
+#endif /* CONFIG_NCPFS_PACKET_SIGNING */
+
diff --git a/drivers/staging/ncpfs/ncpsign_kernel.h b/drivers/staging/ncpfs/ncpsign_kernel.h
new file mode 100644 (file)
index 0000000..57ff0a0
--- /dev/null
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  ncpsign_kernel.h
+ *
+ *  Arne de Bruijn (arne@knoware.nl), 1997
+ *
+ */
+#ifndef _NCPSIGN_KERNEL_H
+#define _NCPSIGN_KERNEL_H
+
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+void __sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff);
+int sign_verify_reply(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, const void *sign_buff);
+#endif
+
+static inline size_t sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff) {
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+       if (server->sign_active) {
+               __sign_packet(server, data, size, totalsize, sign_buff);
+               return 8;
+       }
+#endif
+       return 0;
+}
+
+#endif
diff --git a/drivers/staging/ncpfs/sock.c b/drivers/staging/ncpfs/sock.c
new file mode 100644 (file)
index 0000000..4c13174
--- /dev/null
@@ -0,0 +1,855 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  linux/fs/ncpfs/sock.c
+ *
+ *  Copyright (C) 1992, 1993  Rick Sladkey
+ *
+ *  Modified 1995, 1996 by Volker Lendecke to be usable for ncp
+ *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <linux/socket.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/sched/signal.h>
+#include <linux/uaccess.h>
+#include <linux/in.h>
+#include <linux/net.h>
+#include <linux/mm.h>
+#include <linux/netdevice.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <net/scm.h>
+#include <net/sock.h>
+#include <linux/ipx.h>
+#include <linux/poll.h>
+#include <linux/file.h>
+
+#include "ncp_fs.h"
+
+#include "ncpsign_kernel.h"
+
+static int _recv(struct socket *sock, void *buf, int size, unsigned flags)
+{
+       struct msghdr msg = {NULL, };
+       struct kvec iov = {buf, size};
+       iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, size);
+       return sock_recvmsg(sock, &msg, flags);
+}
+
+static int _send(struct socket *sock, const void *buff, int len)
+{
+       struct msghdr msg = { .msg_flags = 0 };
+       struct kvec vec = {.iov_base = (void *)buff, .iov_len = len};
+       iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &vec, 1, len);
+       return sock_sendmsg(sock, &msg);
+}
+
+struct ncp_request_reply {
+       struct list_head req;
+       wait_queue_head_t wq;
+       atomic_t refs;
+       unsigned char* reply_buf;
+       size_t datalen;
+       int result;
+       enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status;
+       struct iov_iter from;
+       struct kvec tx_iov[3];
+       u_int16_t tx_type;
+       u_int32_t sign[6];
+};
+
+static inline struct ncp_request_reply* ncp_alloc_req(void)
+{
+       struct ncp_request_reply *req;
+
+       req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL);
+       if (!req)
+               return NULL;
+
+       init_waitqueue_head(&req->wq);
+       atomic_set(&req->refs, (1));
+       req->status = RQ_IDLE;
+
+       return req;
+}
+
+static void ncp_req_get(struct ncp_request_reply *req)
+{
+       atomic_inc(&req->refs);
+}
+
+static void ncp_req_put(struct ncp_request_reply *req)
+{
+       if (atomic_dec_and_test(&req->refs))
+               kfree(req);
+}
+
+void ncp_tcp_data_ready(struct sock *sk)
+{
+       struct ncp_server *server = sk->sk_user_data;
+
+       server->data_ready(sk);
+       schedule_work(&server->rcv.tq);
+}
+
+void ncp_tcp_error_report(struct sock *sk)
+{
+       struct ncp_server *server = sk->sk_user_data;
+       
+       server->error_report(sk);
+       schedule_work(&server->rcv.tq);
+}
+
+void ncp_tcp_write_space(struct sock *sk)
+{
+       struct ncp_server *server = sk->sk_user_data;
+       
+       /* We do not need any locking: we first set tx.creq, and then we do sendmsg,
+          not vice versa... */
+       server->write_space(sk);
+       if (server->tx.creq)
+               schedule_work(&server->tx.tq);
+}
+
+void ncpdgram_timeout_call(struct timer_list *t)
+{
+       struct ncp_server *server = from_timer(server, t, timeout_tm);
+
+       schedule_work(&server->timeout_tq);
+}
+
+static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result)
+{
+       req->result = result;
+       if (req->status != RQ_ABANDONED)
+               memcpy(req->reply_buf, server->rxbuf, req->datalen);
+       req->status = RQ_DONE;
+       wake_up_all(&req->wq);
+       ncp_req_put(req);
+}
+
+static void __abort_ncp_connection(struct ncp_server *server)
+{
+       struct ncp_request_reply *req;
+
+       ncp_invalidate_conn(server);
+       del_timer(&server->timeout_tm);
+       while (!list_empty(&server->tx.requests)) {
+               req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
+               
+               list_del_init(&req->req);
+               ncp_finish_request(server, req, -EIO);
+       }
+       req = server->rcv.creq;
+       if (req) {
+               server->rcv.creq = NULL;
+               ncp_finish_request(server, req, -EIO);
+               server->rcv.ptr = NULL;
+               server->rcv.state = 0;
+       }
+       req = server->tx.creq;
+       if (req) {
+               server->tx.creq = NULL;
+               ncp_finish_request(server, req, -EIO);
+       }
+}
+
+static inline int get_conn_number(struct ncp_reply_header *rp)
+{
+       return rp->conn_low | (rp->conn_high << 8);
+}
+
+static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
+{
+       /* If req is done, we got signal, but we also received answer... */
+       switch (req->status) {
+               case RQ_IDLE:
+               case RQ_DONE:
+                       break;
+               case RQ_QUEUED:
+                       list_del_init(&req->req);
+                       ncp_finish_request(server, req, err);
+                       break;
+               case RQ_INPROGRESS:
+                       req->status = RQ_ABANDONED;
+                       break;
+               case RQ_ABANDONED:
+                       break;
+       }
+}
+
+static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
+{
+       mutex_lock(&server->rcv.creq_mutex);
+       __ncp_abort_request(server, req, err);
+       mutex_unlock(&server->rcv.creq_mutex);
+}
+
+static inline void __ncptcp_abort(struct ncp_server *server)
+{
+       __abort_ncp_connection(server);
+}
+
+static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req)
+{
+       struct msghdr msg = { .msg_iter = req->from, .msg_flags = MSG_DONTWAIT };
+       return sock_sendmsg(sock, &msg);
+}
+
+static void __ncptcp_try_send(struct ncp_server *server)
+{
+       struct ncp_request_reply *rq;
+       struct msghdr msg = { .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT };
+       int result;
+
+       rq = server->tx.creq;
+       if (!rq)
+               return;
+
+       msg.msg_iter = rq->from;
+       result = sock_sendmsg(server->ncp_sock, &msg);
+
+       if (result == -EAGAIN)
+               return;
+
+       if (result < 0) {
+               pr_err("tcp: Send failed: %d\n", result);
+               __ncp_abort_request(server, rq, result);
+               return;
+       }
+       if (!msg_data_left(&msg)) {
+               server->rcv.creq = rq;
+               server->tx.creq = NULL;
+               return;
+       }
+       rq->from = msg.msg_iter;
+}
+
+static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h)
+{
+       req->status = RQ_INPROGRESS;
+       h->conn_low = server->connection;
+       h->conn_high = server->connection >> 8;
+       h->sequence = ++server->sequence;
+}
+       
+static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req)
+{
+       size_t signlen, len = req->tx_iov[1].iov_len;
+       struct ncp_request_header *h = req->tx_iov[1].iov_base;
+       
+       ncp_init_header(server, req, h);
+       signlen = sign_packet(server,
+                       req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, 
+                       len - sizeof(struct ncp_request_header) + 1,
+                       cpu_to_le32(len), req->sign);
+       if (signlen) {
+               /* NCP over UDP appends signature */
+               req->tx_iov[2].iov_base = req->sign;
+               req->tx_iov[2].iov_len = signlen;
+       }
+       iov_iter_kvec(&req->from, WRITE | ITER_KVEC,
+                       req->tx_iov + 1, signlen ? 2 : 1, len + signlen);
+       server->rcv.creq = req;
+       server->timeout_last = server->m.time_out;
+       server->timeout_retries = server->m.retry_count;
+       ncpdgram_send(server->ncp_sock, req);
+       mod_timer(&server->timeout_tm, jiffies + server->m.time_out);
+}
+
+#define NCP_TCP_XMIT_MAGIC     (0x446D6454)
+#define NCP_TCP_XMIT_VERSION   (1)
+#define NCP_TCP_RCVD_MAGIC     (0x744E6350)
+
+static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
+{
+       size_t signlen, len = req->tx_iov[1].iov_len;
+       struct ncp_request_header *h = req->tx_iov[1].iov_base;
+
+       ncp_init_header(server, req, h);
+       signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
+                       len - sizeof(struct ncp_request_header) + 1,
+                       cpu_to_be32(len + 24), req->sign + 4) + 16;
+
+       req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC);
+       req->sign[1] = htonl(len + signlen);
+       req->sign[2] = htonl(NCP_TCP_XMIT_VERSION);
+       req->sign[3] = htonl(req->datalen + 8);
+       /* NCP over TCP prepends signature */
+       req->tx_iov[0].iov_base = req->sign;
+       req->tx_iov[0].iov_len = signlen;
+       iov_iter_kvec(&req->from, WRITE | ITER_KVEC,
+                       req->tx_iov, 2, len + signlen);
+
+       server->tx.creq = req;
+       __ncptcp_try_send(server);
+}
+
+static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
+{
+       /* we copy the data so that we do not depend on the caller
+          staying alive */
+       memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len);
+       req->tx_iov[1].iov_base = server->txbuf;
+
+       if (server->ncp_sock->type == SOCK_STREAM)
+               ncptcp_start_request(server, req);
+       else
+               ncpdgram_start_request(server, req);
+}
+
+static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req)
+{
+       mutex_lock(&server->rcv.creq_mutex);
+       if (!ncp_conn_valid(server)) {
+               mutex_unlock(&server->rcv.creq_mutex);
+               pr_err("tcp: Server died\n");
+               return -EIO;
+       }
+       ncp_req_get(req);
+       if (server->tx.creq || server->rcv.creq) {
+               req->status = RQ_QUEUED;
+               list_add_tail(&req->req, &server->tx.requests);
+               mutex_unlock(&server->rcv.creq_mutex);
+               return 0;
+       }
+       __ncp_start_request(server, req);
+       mutex_unlock(&server->rcv.creq_mutex);
+       return 0;
+}
+
+static void __ncp_next_request(struct ncp_server *server)
+{
+       struct ncp_request_reply *req;
+
+       server->rcv.creq = NULL;
+       if (list_empty(&server->tx.requests)) {
+               return;
+       }
+       req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
+       list_del_init(&req->req);
+       __ncp_start_request(server, req);
+}
+
+static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len)
+{
+       if (server->info_sock) {
+               struct msghdr msg = { .msg_flags = MSG_NOSIGNAL };
+               __be32 hdr[2] = {cpu_to_be32(len + 8), cpu_to_be32(id)};
+               struct kvec iov[2] = {
+                       {.iov_base = hdr, .iov_len = 8},
+                       {.iov_base = (void *)data, .iov_len = len},
+               };
+
+               iov_iter_kvec(&msg.msg_iter, ITER_KVEC | WRITE,
+                               iov, 2, len + 8);
+
+               sock_sendmsg(server->info_sock, &msg);
+       }
+}
+
+void ncpdgram_rcv_proc(struct work_struct *work)
+{
+       struct ncp_server *server =
+               container_of(work, struct ncp_server, rcv.tq);
+       struct socket* sock;
+       
+       sock = server->ncp_sock;
+       
+       while (1) {
+               struct ncp_reply_header reply;
+               int result;
+
+               result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT);
+               if (result < 0) {
+                       break;
+               }
+               if (result >= sizeof(reply)) {
+                       struct ncp_request_reply *req;
+       
+                       if (reply.type == NCP_WATCHDOG) {
+                               unsigned char buf[10];
+
+                               if (server->connection != get_conn_number(&reply)) {
+                                       goto drop;
+                               }
+                               result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
+                               if (result < 0) {
+                                       ncp_dbg(1, "recv failed with %d\n", result);
+                                       continue;
+                               }
+                               if (result < 10) {
+                                       ncp_dbg(1, "too short (%u) watchdog packet\n", result);
+                                       continue;
+                               }
+                               if (buf[9] != '?') {
+                                       ncp_dbg(1, "bad signature (%02X) in watchdog packet\n", buf[9]);
+                                       continue;
+                               }
+                               buf[9] = 'Y';
+                               _send(sock, buf, sizeof(buf));
+                               continue;
+                       }
+                       if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
+                               result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
+                               if (result < 0) {
+                                       continue;
+                               }
+                               info_server(server, 0, server->unexpected_packet.data, result);
+                               continue;
+                       }
+                       mutex_lock(&server->rcv.creq_mutex);
+                       req = server->rcv.creq;
+                       if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && 
+                                       server->connection == get_conn_number(&reply)))) {
+                               if (reply.type == NCP_POSITIVE_ACK) {
+                                       server->timeout_retries = server->m.retry_count;
+                                       server->timeout_last = NCP_MAX_RPC_TIMEOUT;
+                                       mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
+                               } else if (reply.type == NCP_REPLY) {
+                                       result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT);
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+                                       if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
+                                               if (result < 8 + 8) {
+                                                       result = -EIO;
+                                               } else {
+                                                       unsigned int hdrl;
+                                                       
+                                                       result -= 8;
+                                                       hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
+                                                       if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) {
+                                                               pr_info("Signature violation\n");
+                                                               result = -EIO;
+                                                       }
+                                               }
+                                       }
+#endif
+                                       del_timer(&server->timeout_tm);
+                                       server->rcv.creq = NULL;
+                                       ncp_finish_request(server, req, result);
+                                       __ncp_next_request(server);
+                                       mutex_unlock(&server->rcv.creq_mutex);
+                                       continue;
+                               }
+                       }
+                       mutex_unlock(&server->rcv.creq_mutex);
+               }
+drop:;         
+               _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT);
+       }
+}
+
+static void __ncpdgram_timeout_proc(struct ncp_server *server)
+{
+       /* If timer is pending, we are processing another request... */
+       if (!timer_pending(&server->timeout_tm)) {
+               struct ncp_request_reply* req;
+               
+               req = server->rcv.creq;
+               if (req) {
+                       int timeout;
+                       
+                       if (server->m.flags & NCP_MOUNT_SOFT) {
+                               if (server->timeout_retries-- == 0) {
+                                       __ncp_abort_request(server, req, -ETIMEDOUT);
+                                       return;
+                               }
+                       }
+                       /* Ignore errors */
+                       ncpdgram_send(server->ncp_sock, req);
+                       timeout = server->timeout_last << 1;
+                       if (timeout > NCP_MAX_RPC_TIMEOUT) {
+                               timeout = NCP_MAX_RPC_TIMEOUT;
+                       }
+                       server->timeout_last = timeout;
+                       mod_timer(&server->timeout_tm, jiffies + timeout);
+               }
+       }
+}
+
+void ncpdgram_timeout_proc(struct work_struct *work)
+{
+       struct ncp_server *server =
+               container_of(work, struct ncp_server, timeout_tq);
+       mutex_lock(&server->rcv.creq_mutex);
+       __ncpdgram_timeout_proc(server);
+       mutex_unlock(&server->rcv.creq_mutex);
+}
+
+static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len)
+{
+       int result;
+       
+       if (buffer) {
+               result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT);
+       } else {
+               static unsigned char dummy[1024];
+                       
+               if (len > sizeof(dummy)) {
+                       len = sizeof(dummy);
+               }
+               result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT);
+       }
+       if (result < 0) {
+               return result;
+       }
+       if (result > len) {
+               pr_err("tcp: bug in recvmsg (%u > %zu)\n", result, len);
+               return -EIO;                    
+       }
+       return result;
+}      
+
+static int __ncptcp_rcv_proc(struct ncp_server *server)
+{
+       /* We have to check the result, so store the complete header */
+       while (1) {
+               int result;
+               struct ncp_request_reply *req;
+               int datalen;
+               int type;
+
+               while (server->rcv.len) {
+                       result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len);
+                       if (result == -EAGAIN) {
+                               return 0;
+                       }
+                       if (result <= 0) {
+                               req = server->rcv.creq;
+                               if (req) {
+                                       __ncp_abort_request(server, req, -EIO);
+                               } else {
+                                       __ncptcp_abort(server);
+                               }
+                               if (result < 0) {
+                                       pr_err("tcp: error in recvmsg: %d\n", result);
+                               } else {
+                                       ncp_dbg(1, "tcp: EOF\n");
+                               }
+                               return -EIO;
+                       }
+                       if (server->rcv.ptr) {
+                               server->rcv.ptr += result;
+                       }
+                       server->rcv.len -= result;
+               }
+               switch (server->rcv.state) {
+                       case 0:
+                               if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
+                                       pr_err("tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
+                                       __ncptcp_abort(server);
+                                       return -EIO;
+                               }
+                               datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
+                               if (datalen < 10) {
+                                       pr_err("tcp: Unexpected reply len %d\n", datalen);
+                                       __ncptcp_abort(server);
+                                       return -EIO;
+                               }
+#ifdef CONFIG_NCPFS_PACKET_SIGNING                             
+                               if (server->sign_active) {
+                                       if (datalen < 18) {
+                                               pr_err("tcp: Unexpected reply len %d\n", datalen);
+                                               __ncptcp_abort(server);
+                                               return -EIO;
+                                       }
+                                       server->rcv.buf.len = datalen - 8;
+                                       server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1;
+                                       server->rcv.len = 8;
+                                       server->rcv.state = 4;
+                                       break;
+                               }
+#endif                         
+                               type = ntohs(server->rcv.buf.type);
+#ifdef CONFIG_NCPFS_PACKET_SIGNING                             
+cont:;                         
+#endif
+                               if (type != NCP_REPLY) {
+                                       if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
+                                               *(__u16*)(server->unexpected_packet.data) = htons(type);
+                                               server->unexpected_packet.len = datalen - 8;
+
+                                               server->rcv.state = 5;
+                                               server->rcv.ptr = server->unexpected_packet.data + 2;
+                                               server->rcv.len = datalen - 10;
+                                               break;
+                                       }                                       
+                                       ncp_dbg(1, "tcp: Unexpected NCP type %02X\n", type);
+skipdata2:;
+                                       server->rcv.state = 2;
+skipdata:;
+                                       server->rcv.ptr = NULL;
+                                       server->rcv.len = datalen - 10;
+                                       break;
+                               }
+                               req = server->rcv.creq;
+                               if (!req) {
+                                       ncp_dbg(1, "Reply without appropriate request\n");
+                                       goto skipdata2;
+                               }
+                               if (datalen > req->datalen + 8) {
+                                       pr_err("tcp: Unexpected reply len %d (expected at most %zd)\n", datalen, req->datalen + 8);
+                                       server->rcv.state = 3;
+                                       goto skipdata;
+                               }
+                               req->datalen = datalen - 8;
+                               ((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY;
+                               server->rcv.ptr = server->rxbuf + 2;
+                               server->rcv.len = datalen - 10;
+                               server->rcv.state = 1;
+                               break;
+#ifdef CONFIG_NCPFS_PACKET_SIGNING                             
+                       case 4:
+                               datalen = server->rcv.buf.len;
+                               type = ntohs(server->rcv.buf.type2);
+                               goto cont;
+#endif
+                       case 1:
+                               req = server->rcv.creq;
+                               if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
+                                       if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) {
+                                               pr_err("tcp: Bad sequence number\n");
+                                               __ncp_abort_request(server, req, -EIO);
+                                               return -EIO;
+                                       }
+                                       if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) {
+                                               pr_err("tcp: Connection number mismatch\n");
+                                               __ncp_abort_request(server, req, -EIO);
+                                               return -EIO;
+                                       }
+                               }
+#ifdef CONFIG_NCPFS_PACKET_SIGNING                             
+                               if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
+                                       if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
+                                               pr_err("tcp: Signature violation\n");
+                                               __ncp_abort_request(server, req, -EIO);
+                                               return -EIO;
+                                       }
+                               }
+#endif                         
+                               ncp_finish_request(server, req, req->datalen);
+                       nextreq:;
+                               __ncp_next_request(server);
+                       case 2:
+                       next:;
+                               server->rcv.ptr = (unsigned char*)&server->rcv.buf;
+                               server->rcv.len = 10;
+                               server->rcv.state = 0;
+                               break;
+                       case 3:
+                               ncp_finish_request(server, server->rcv.creq, -EIO);
+                               goto nextreq;
+                       case 5:
+                               info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
+                               goto next;
+               }
+       }
+}
+
+void ncp_tcp_rcv_proc(struct work_struct *work)
+{
+       struct ncp_server *server =
+               container_of(work, struct ncp_server, rcv.tq);
+
+       mutex_lock(&server->rcv.creq_mutex);
+       __ncptcp_rcv_proc(server);
+       mutex_unlock(&server->rcv.creq_mutex);
+}
+
+void ncp_tcp_tx_proc(struct work_struct *work)
+{
+       struct ncp_server *server =
+               container_of(work, struct ncp_server, tx.tq);
+       
+       mutex_lock(&server->rcv.creq_mutex);
+       __ncptcp_try_send(server);
+       mutex_unlock(&server->rcv.creq_mutex);
+}
+
+static int do_ncp_rpc_call(struct ncp_server *server, int size,
+               unsigned char* reply_buf, int max_reply_size)
+{
+       int result;
+       struct ncp_request_reply *req;
+
+       req = ncp_alloc_req();
+       if (!req)
+               return -ENOMEM;
+
+       req->reply_buf = reply_buf;
+       req->datalen = max_reply_size;
+       req->tx_iov[1].iov_base = server->packet;
+       req->tx_iov[1].iov_len = size;
+       req->tx_type = *(u_int16_t*)server->packet;
+
+       result = ncp_add_request(server, req);
+       if (result < 0)
+               goto out;
+
+       if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) {
+               ncp_abort_request(server, req, -EINTR);
+               result = -EINTR;
+               goto out;
+       }
+
+       result = req->result;
+
+out:
+       ncp_req_put(req);
+
+       return result;
+}
+
+/*
+ * We need the server to be locked here, so check!
+ */
+
+static int ncp_do_request(struct ncp_server *server, int size,
+               void* reply, int max_reply_size)
+{
+       int result;
+
+       if (server->lock == 0) {
+               pr_err("Server not locked!\n");
+               return -EIO;
+       }
+       if (!ncp_conn_valid(server)) {
+               return -EIO;
+       }
+       {
+               sigset_t old_set;
+               unsigned long mask, flags;
+
+               spin_lock_irqsave(&current->sighand->siglock, flags);
+               old_set = current->blocked;
+               if (current->flags & PF_EXITING)
+                       mask = 0;
+               else
+                       mask = sigmask(SIGKILL);
+               if (server->m.flags & NCP_MOUNT_INTR) {
+                       /* FIXME: This doesn't seem right at all.  So, like,
+                          we can't handle SIGINT and get whatever to stop?
+                          What if we've blocked it ourselves?  What about
+                          alarms?  Why, in fact, are we mucking with the
+                          sigmask at all? -- r~ */
+                       if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL)
+                               mask |= sigmask(SIGINT);
+                       if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL)
+                               mask |= sigmask(SIGQUIT);
+               }
+               siginitsetinv(&current->blocked, mask);
+               recalc_sigpending();
+               spin_unlock_irqrestore(&current->sighand->siglock, flags);
+               
+               result = do_ncp_rpc_call(server, size, reply, max_reply_size);
+
+               spin_lock_irqsave(&current->sighand->siglock, flags);
+               current->blocked = old_set;
+               recalc_sigpending();
+               spin_unlock_irqrestore(&current->sighand->siglock, flags);
+       }
+
+       ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result);
+
+       return result;
+}
+
+/* ncp_do_request assures that at least a complete reply header is
+ * received. It assumes that server->current_size contains the ncp
+ * request size
+ */
+int ncp_request2(struct ncp_server *server, int function, 
+               void* rpl, int size)
+{
+       struct ncp_request_header *h;
+       struct ncp_reply_header* reply = rpl;
+       int result;
+
+       h = (struct ncp_request_header *) (server->packet);
+       if (server->has_subfunction != 0) {
+               *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2);
+       }
+       h->type = NCP_REQUEST;
+       /*
+        * The server shouldn't know or care what task is making a
+        * request, so we always use the same task number.
+        */
+       h->task = 2; /* (current->pid) & 0xff; */
+       h->function = function;
+
+       result = ncp_do_request(server, server->current_size, reply, size);
+       if (result < 0) {
+               ncp_dbg(1, "ncp_request_error: %d\n", result);
+               goto out;
+       }
+       server->completion = reply->completion_code;
+       server->conn_status = reply->connection_state;
+       server->reply_size = result;
+       server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
+
+       result = reply->completion_code;
+
+       if (result != 0)
+               ncp_vdbg("completion code=%x\n", result);
+out:
+       return result;
+}
+
+int ncp_connect(struct ncp_server *server)
+{
+       struct ncp_request_header *h;
+       int result;
+
+       server->connection = 0xFFFF;
+       server->sequence = 255;
+
+       h = (struct ncp_request_header *) (server->packet);
+       h->type = NCP_ALLOC_SLOT_REQUEST;
+       h->task         = 2; /* see above */
+       h->function     = 0;
+
+       result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
+       if (result < 0)
+               goto out;
+       server->connection = h->conn_low + (h->conn_high * 256);
+       result = 0;
+out:
+       return result;
+}
+
+int ncp_disconnect(struct ncp_server *server)
+{
+       struct ncp_request_header *h;
+
+       h = (struct ncp_request_header *) (server->packet);
+       h->type = NCP_DEALLOC_SLOT_REQUEST;
+       h->task         = 2; /* see above */
+       h->function     = 0;
+
+       return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
+}
+
+void ncp_lock_server(struct ncp_server *server)
+{
+       mutex_lock(&server->mutex);
+       if (server->lock)
+               pr_warn("%s: was locked!\n", __func__);
+       server->lock = 1;
+}
+
+void ncp_unlock_server(struct ncp_server *server)
+{
+       if (!server->lock) {
+               pr_warn("%s: was not locked!\n", __func__);
+               return;
+       }
+       server->lock = 0;
+       mutex_unlock(&server->mutex);
+}
diff --git a/drivers/staging/ncpfs/symlink.c b/drivers/staging/ncpfs/symlink.c
new file mode 100644 (file)
index 0000000..b6e16da
--- /dev/null
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  linux/fs/ncpfs/symlink.c
+ *
+ *  Code for allowing symbolic links on NCPFS (i.e. NetWare)
+ *  Symbolic links are not supported on native NetWare, so we use an
+ *  infrequently-used flag (Sh) and store a two-word magic header in
+ *  the file to make sure we don't accidentally use a non-link file
+ *  as a link.
+ *
+ *  When using the NFS namespace, we set the mode to indicate a symlink and
+ *  don't bother with the magic numbers.
+ *
+ *  from linux/fs/ext2/symlink.c
+ *
+ *  Copyright (C) 1998-99, Frank A. Vorstenbosch
+ *
+ *  ncpfs symlink handling code
+ *  NLS support (c) 1999 Petr Vandrovec
+ *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
+ *
+ */
+
+
+#include <linux/uaccess.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/stat.h>
+#include "ncp_fs.h"
+
+/* these magic numbers must appear in the symlink file -- this makes it a bit
+   more resilient against the magic attributes being set on random files. */
+
+#define NCP_SYMLINK_MAGIC0     cpu_to_le32(0x6c6d7973)     /* "symlnk->" */
+#define NCP_SYMLINK_MAGIC1     cpu_to_le32(0x3e2d6b6e)
+
+/* ----- read a symbolic link ------------------------------------------ */
+
+static int ncp_symlink_readpage(struct file *file, struct page *page)
+{
+       struct inode *inode = page->mapping->host;
+       int error, length, len;
+       char *link, *rawlink;
+       char *buf = kmap(page);
+
+       error = -ENOMEM;
+       rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
+       if (!rawlink)
+               goto fail;
+
+       if (ncp_make_open(inode,O_RDONLY))
+               goto failEIO;
+
+       error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
+                         0,NCP_MAX_SYMLINK_SIZE,rawlink,&length);
+
+       ncp_inode_close(inode);
+       /* Close file handle if no other users... */
+       ncp_make_closed(inode);
+       if (error)
+               goto failEIO;
+
+       if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) {
+               if (length<NCP_MIN_SYMLINK_SIZE || 
+                   ((__le32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
+                   ((__le32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
+                       goto failEIO;
+               link = rawlink + 8;
+               length -= 8;
+       } else {
+               link = rawlink;
+       }
+
+       len = NCP_MAX_SYMLINK_SIZE;
+       error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link, length, 0);
+       kfree(rawlink);
+       if (error)
+               goto fail;
+       SetPageUptodate(page);
+       kunmap(page);
+       unlock_page(page);
+       return 0;
+
+failEIO:
+       error = -EIO;
+       kfree(rawlink);
+fail:
+       SetPageError(page);
+       kunmap(page);
+       unlock_page(page);
+       return error;
+}
+
+/*
+ * symlinks can't do much...
+ */
+const struct address_space_operations ncp_symlink_aops = {
+       .readpage       = ncp_symlink_readpage,
+};
+       
+/* ----- create a new symbolic link -------------------------------------- */
+int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
+       struct inode *inode;
+       char *rawlink;
+       int length, err, i, outlen;
+       int kludge;
+       umode_t mode;
+       __le32 attr;
+       unsigned int hdr;
+
+       ncp_dbg(1, "dir=%p, dentry=%p, symname=%s\n", dir, dentry, symname);
+
+       if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber))
+               kludge = 0;
+       else
+#ifdef CONFIG_NCPFS_EXTRAS
+       if (NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS)
+               kludge = 1;
+       else
+#endif
+       /* EPERM is returned by VFS if symlink procedure does not exist */
+               return -EPERM;
+  
+       rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
+       if (!rawlink)
+               return -ENOMEM;
+
+       if (kludge) {
+               mode = 0;
+               attr = aSHARED | aHIDDEN;
+               ((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
+               ((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
+               hdr = 8;
+       } else {
+               mode = S_IFLNK | S_IRWXUGO;
+               attr = 0;
+               hdr = 0;
+       }                       
+
+       length = strlen(symname);
+       /* map to/from server charset, do not touch upper/lower case as
+          symlink can point out of ncp filesystem */
+       outlen = NCP_MAX_SYMLINK_SIZE - hdr;
+       err = ncp_io2vol(NCP_SERVER(dir), rawlink + hdr, &outlen, symname, length, 0);
+       if (err)
+               goto failfree;
+
+       outlen += hdr;
+
+       err = -EIO;
+       if (ncp_create_new(dir,dentry,mode,0,attr)) {
+               goto failfree;
+       }
+
+       inode=d_inode(dentry);
+
+       if (ncp_make_open(inode, O_WRONLY))
+               goto failfree;
+
+       if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 
+                            0, outlen, rawlink, &i) || i!=outlen) {
+               goto fail;
+       }
+
+       ncp_inode_close(inode);
+       ncp_make_closed(inode);
+       kfree(rawlink);
+       return 0;
+fail:;
+       ncp_inode_close(inode);
+       ncp_make_closed(inode);
+failfree:;
+       kfree(rawlink);
+       return err;
+}
+
+/* ----- EOF ----- */
index 7008c96bdbbeeed625edbe5c7298614043ea50b9..ac58e87e6a4ebcf4d2a2583b00ddb2837e0cb752 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * drivers/input/keyboard/tegra-nvec.c
  *
@@ -5,19 +6,6 @@
  * embedded controller
  *
  * Copyright (c) 2009, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see http://www.gnu.org/licenses
  */
 
 static unsigned short code_tab_102us[] = {
index 4ff8f47385daed8114ddd2a9745f5102556b1f8b..52054a528723f8d54b0ae88bfcd4d9389ed9565b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * NVEC: NVIDIA compliant embedded controller interface
  *
@@ -7,11 +8,6 @@
  *           Ilya Petrov <ilya.muromec@gmail.com>
  *           Marc Dietrich <marvin24@gmx.de>
  *           Julian Andres Klode <jak@jak-linux.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 
 #include <linux/kernel.h>
index aa7c70ef94f5f7d51017c0b63491f5c8ac88f794..25efcdfa4f201153cd0a1718cff53d9943dc3192 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * NVEC: NVIDIA compliant embedded controller interface
  *
@@ -7,11 +8,6 @@
  *           Ilya Petrov <ilya.muromec@gmail.com>
  *           Marc Dietrich <marvin24@gmx.de>
  *           Julian Andres Klode <jak@jak-linux.org>
- *
- * 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 __LINUX_MFD_NVEC
index a01f486621eb60c22c7f4cbccb929743b6204a69..01dbb66f7e9a478b7c6eb77d4a8caa256f0fb639 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * nvec_kbd: keyboard driver for a NVIDIA compliant embedded controller
  *
@@ -5,11 +6,6 @@
  *
  * Authors:  Pierre-Hugues Husson <phhusson@free.fr>
  *           Marc Dietrich <marvin24@gmx.de>
- *
- * 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/module.h>
index 51dbeeb3320e744ce0d83b54fd9666b027bdb668..8b4da95081c8934a0f5f6a7abb243fb0cd23442d 100644 (file)
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * nvec_paz00: OEM specific driver for Compal PAZ00 based devices
  *
  * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
  *
  * Authors:  Ilya Petrov <ilya.muromec@gmail.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 
 #include <linux/module.h>
index 3b144a9ea055ff85e3c1eaa3b13643ae77a7f403..0e861c4bfcbfa0d103ac9f59e1e0dacdfcbec61c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * nvec_power: power supply driver for a NVIDIA compliant embedded controller
  *
@@ -5,11 +6,6 @@
  *
  * Authors:  Ilya Petrov <ilya.muromec@gmail.com>
  *           Marc Dietrich <marvin24@gmx.de>
- *
- * 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/module.h>
index 3b7bce3ffd1912143bb823e04d42ba14188f9f03..45db29262a9c4173bae944e4be9601c68bcfdcf3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * nvec_ps2: mouse driver for a NVIDIA compliant embedded controller
  *
@@ -6,11 +7,6 @@
  * Authors:  Pierre-Hugues Husson <phhusson@free.fr>
  *           Ilya Petrov <ilya.muromec@gmail.com>
  *           Marc Dietrich <marvin24@gmx.de>
- *
- * 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/module.h>
index 8ca17210d9171d720af4528adcb7ef6f13ca6830..3887cf5f1e84fa3051f6c388e5961385422638c3 100644 (file)
@@ -1,6 +1,4 @@
-# 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.
+# SPDX-License-Identifier: GPL-2.0
 #
 # Copyright (C) 2005-2009 Cavium Networks
 #
index 07bd2b87f6a0fec7e9acdcd156d1584aa2e885fa..1e114422993ac73f982f7cce925275dd7fdc80c9 100644 (file)
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file 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.
  */
 
 /*
index 691e4a51ace43197766e55f9aca471918270b2ec..f67f950438873a764f45f66ec3b96819189ef1a8 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
  */
 
 #include <linux/kernel.h>
index 5ed8483fc24d178215fd66d72c846987fc268005..e3771d48c49b87b51938d18cf700bf85f5d1b6a6 100644 (file)
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
  */
 
 #include <linux/module.h>
index d6172e4dace57db4b5ba043ac0ff1a9fcde33233..0d26c4a93ec1593f3117610857633148dd18cf51 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2010 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
  */
 
 #include <linux/kernel.h>
index 62d07c426f89fd2840bba32f4547053812d9ed9d..692dcdb7154dae37644fd39eab7642673a8ea1fc 100644 (file)
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file 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.
  */
 
 int cvm_oct_mem_fill_fpa(int pool, int size, int elements);
index 4e7304210bb91ee257fe077d43d6878e5e26a660..c15376d33891f7bb6c2b456c3e2a4a084bce4b02 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
  */
 
 #include <linux/kernel.h>
index 1a44291318ee8d49d35cac6f328c93b8324afe0f..5e271245273c7fb70cb65b2b616e49860d173692 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2010 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
  */
 
 #include <linux/module.h>
index 315a63d7094f51c89fa5707e39363162abefd46d..096553d8fc99e54758f4ad243b274e857da47d32 100644 (file)
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file 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 <asm/octeon/cvmx-fau.h>
index 7424dc45ad39fd7e94c482fe84edca7de7b480a9..a4a8f094e2b44847a34dfbad700b401dc7f36b35 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file 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/phy.h>
index 063dcd07557b2f45d1e77414e95e93ccafd3b6be..01efdf2a2c2032382cec17c0d8cff7b45c3336f4 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
  */
 
 #include <linux/kernel.h>
index 31f35025d19eccacee992584bc5b68e107d39411..df3441b815bba926d508eb1dc2079c6e63ab7cf0 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2010 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
  */
 
 #include <linux/module.h>
index 84848e4c1664219b610fbf9bf192597b11b70116..78936e9b33b0abd53d1aec2be1bb363e3e5ed5ab 100644 (file)
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file 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.
  */
 
 int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev);
index cb5540dc0e9dfaeebca4dd82c7a9d9e5f71edd23..31a82873e15c4dade65a238b6aba3cb6f914403c 100644 (file)
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file 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 <asm/octeon/cvmx-pip.h>
index 429e24adfcf5a8f7f71e2fe09bcc2c688d131962..9b15c9ed844b1eeec311439d5dc02be57451cc93 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
  */
 
 #include <linux/platform_device.h>
index 9c3f453adaa09a027fb56199b0cbaf14657a895e..4a07e7f43d128cb6903891ad6fcbd399b61e0e61 100644 (file)
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * This file is based on code from OCTEON SDK by Cavium Networks.
  *
  * Copyright (c) 2003-2010 Cavium Networks
- *
- * This file 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.
  */
 
 /*
index 82bffd911435d937501c07a9d7840030c4a35362..2744c9f0920eeaaf69a1e5cf54e1936e46b864db 100644 (file)
@@ -393,7 +393,8 @@ static void dcon_set_source_sync(struct dcon_priv *dcon, int arg)
 }
 
 static ssize_t dcon_mode_show(struct device *dev,
-       struct device_attribute *attr, char *buf)
+                             struct device_attribute *attr,
+                             char *buf)
 {
        struct dcon_priv *dcon = dev_get_drvdata(dev);
 
@@ -401,7 +402,8 @@ static ssize_t dcon_mode_show(struct device *dev,
 }
 
 static ssize_t dcon_sleep_show(struct device *dev,
-       struct device_attribute *attr, char *buf)
+                              struct device_attribute *attr,
+                              char *buf)
 {
        struct dcon_priv *dcon = dev_get_drvdata(dev);
 
@@ -409,7 +411,8 @@ static ssize_t dcon_sleep_show(struct device *dev,
 }
 
 static ssize_t dcon_freeze_show(struct device *dev,
-       struct device_attribute *attr, char *buf)
+                               struct device_attribute *attr,
+                               char *buf)
 {
        struct dcon_priv *dcon = dev_get_drvdata(dev);
 
@@ -417,7 +420,8 @@ static ssize_t dcon_freeze_show(struct device *dev,
 }
 
 static ssize_t dcon_mono_show(struct device *dev,
-       struct device_attribute *attr, char *buf)
+                             struct device_attribute *attr,
+                             char *buf)
 {
        struct dcon_priv *dcon = dev_get_drvdata(dev);
 
@@ -425,13 +429,15 @@ static ssize_t dcon_mono_show(struct device *dev,
 }
 
 static ssize_t dcon_resumeline_show(struct device *dev,
-       struct device_attribute *attr, char *buf)
+                                   struct device_attribute *attr,
+                                   char *buf)
 {
        return sprintf(buf, "%d\n", resumeline);
 }
 
 static ssize_t dcon_mono_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
+                              struct device_attribute *attr,
+                              const char *buf, size_t count)
 {
        unsigned long enable_mono;
        int rc;
@@ -446,7 +452,8 @@ static ssize_t dcon_mono_store(struct device *dev,
 }
 
 static ssize_t dcon_freeze_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
 {
        struct dcon_priv *dcon = dev_get_drvdata(dev);
        unsigned long output;
@@ -474,7 +481,8 @@ static ssize_t dcon_freeze_store(struct device *dev,
 }
 
 static ssize_t dcon_resumeline_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
 {
        unsigned short rl;
        int rc;
@@ -490,7 +498,8 @@ static ssize_t dcon_resumeline_store(struct device *dev,
 }
 
 static ssize_t dcon_sleep_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
 {
        unsigned long output;
        int ret;
@@ -641,7 +650,8 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
        /* Add the backlight device for the DCON */
        dcon_bl_props.brightness = dcon->bl_val;
        dcon->bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev,
-               dcon, &dcon_bl_ops, &dcon_bl_props);
+                                                dcon, &dcon_bl_ops,
+                                                &dcon_bl_props);
        if (IS_ERR(dcon->bl_dev)) {
                dev_err(&client->dev, "cannot register backlight dev (%ld)\n",
                        PTR_ERR(dcon->bl_dev));
index 8fbde5d3b4a682b301f5c3c00bed28c255abb9d3..fa89bb97c7b06718ef2ea232ddc3ff213dd77b82 100644 (file)
 #define DCON_REG_ID             0
 #define DCON_REG_MODE           1
 
-#define MODE_PASSTHRU  (1<<0)
-#define MODE_SLEEP     (1<<1)
-#define MODE_SLEEP_AUTO        (1<<2)
-#define MODE_BL_ENABLE (1<<3)
-#define MODE_BLANK     (1<<4)
-#define MODE_CSWIZZLE  (1<<5)
-#define MODE_COL_AA    (1<<6)
-#define MODE_MONO_LUMA (1<<7)
-#define MODE_SCAN_INT  (1<<8)
-#define MODE_CLOCKDIV  (1<<9)
-#define MODE_DEBUG     (1<<14)
-#define MODE_SELFTEST  (1<<15)
+#define MODE_PASSTHRU  BIT(0)
+#define MODE_SLEEP     BIT(1)
+#define MODE_SLEEP_AUTO        BIT(2)
+#define MODE_BL_ENABLE BIT(3)
+#define MODE_BLANK     BIT(4)
+#define MODE_CSWIZZLE  BIT(5)
+#define MODE_COL_AA    BIT(6)
+#define MODE_MONO_LUMA BIT(7)
+#define MODE_SCAN_INT  BIT(8)
+#define MODE_CLOCKDIV  BIT(9)
+#define MODE_DEBUG     BIT(14)
+#define MODE_SELFTEST  BIT(15)
 
 #define DCON_REG_HRES          0x2
 #define DCON_REG_HTOTAL                0x3
 #define DCON_REG_MEM_OPT_B     0x42
 
 /* Load Delay Locked Loop (DLL) settings for clock delay */
-#define MEM_DLL_CLOCK_DELAY    (1<<0)
+#define MEM_DLL_CLOCK_DELAY    BIT(0)
 /* Memory controller power down function */
-#define MEM_POWER_DOWN         (1<<8)
+#define MEM_POWER_DOWN         BIT(8)
 /* Memory controller software reset */
-#define MEM_SOFT_RESET         (1<<0)
+#define MEM_SOFT_RESET         BIT(0)
 
 /* Status values */
 
index 0c5a10c69401df08d19c2a006831a70ef0a3c88b..633c58ce24eef258edaaca8e1f2e438a4ddfaa60 100644 (file)
@@ -69,7 +69,7 @@ static int dcon_init_xo_1(struct dcon_priv *dcon)
        gpio_direction_input(OLPC_GPIO_DCON_IRQ);
        gpio_direction_input(OLPC_GPIO_DCON_BLANK);
        gpio_direction_output(OLPC_GPIO_DCON_LOAD,
-                       dcon->curr_src == DCON_SOURCE_CPU);
+                             dcon->curr_src == DCON_SOURCE_CPU);
 
        /* Set up the interrupt mappings */
 
index 004b5027a934dca2376310229651e86fbcaf9b87..61fad96818c28c5db6411172f1858316ec0dbde4 100644 (file)
@@ -3,22 +3,22 @@
 /plugin/;
 
 / {
-        compatible = "bcm,bcm2835", "bcm,bcm2708", "bcm,bcm2709";
-
-        fragment@0 {
-                target = <&spi0>;
-                __overlay__ {
-                        status = "okay";
-
-                        spidev@0{
-                                status = "disabled";
-                        };
-
-                        spidev@1{
-                                status = "disabled";
-                        };
-                };
-        };
+       compatible = "bcm,bcm2835", "bcm,bcm2708", "bcm,bcm2709";
+
+       fragment@0 {
+               target = <&spi0>;
+               __overlay__ {
+                       status = "okay";
+
+                       spidev@0{
+                               status = "disabled";
+                       };
+
+                       spidev@1{
+                               status = "disabled";
+                       };
+               };
+       };
 
        fragment@1 {
                target = <&gpio>;
index 245fef33d6882d8249e25b6d3ebeb8ac87a2b794..7d9dc2244848d6f3051c96f8f0bbb4d62363d06d 100644 (file)
@@ -69,8 +69,8 @@ PI433_IOC_WR_TX_CFG - set the transmission parameters
 PI433_IOC_RD_RX_CFG - get the receiving parameters from the driver
 PI433_IOC_WR_RX_CFG - set the receiving parameters
 
-The tx configuration is transfered via struct pi433_tx_cfg, the parameterset for transmission.
-It is devided into two sections: rf parameters and packet format.
+The tx configuration is transferred via struct pi433_tx_cfg, the parameterset for transmission.
+It is divided into two sections: rf parameters and packet format.
 
 rf params:
        frequency
@@ -110,9 +110,9 @@ rf params:
                ramp12          - amp ramps up in 12us
                ramp10          - amp ramps up in 10us
        tx_start_condition
-               fifoLevel       - transmission starts, if fifo is filled to
+               fifo_level      - transmission starts, if fifo is filled to
                                  threshold level
-               fifoNotEmpty    - transmission starts, as soon as there is one
+               fifo_not_empty  - transmission starts, as soon as there is one
                                  byte in internal fifo
        repetitions
                This gives the option, to send a telegram multiple times. Default: 1
@@ -200,11 +200,11 @@ rf params:
                sets the gain of the low noise amp
                automatic       - lna gain is determined by an agc
                max             - lna gain is set to maximum
-               maxMinus6       - lna gain is set to  6db below max
-               maxMinus12      - lna gain is set to 12db below max
-               maxMinus24      - lna gain is set to 24db below max
-               maxMinus36      - lna gain is set to 36db below max
-               maxMinus48      - lna gain is set to 48db below max
+               max_minus_6     - lna gain is set to  6db below max
+               max_minus_12    - lna gain is set to 12db below max
+               max_minus_24    - lna gain is set to 24db below max
+               max_minus_36    - lna gain is set to 36db below max
+               max_minus_48    - lna gain is set to 48db below max
        bw_mantisse
                sets the bandwidth of the channel filter - part one: mantisse.
                mantisse16      - mantisse is set to 16
index 2a205c6173dc3db377d1146047bf59afa40684f2..edcd7e798f99afd6501f2f03729d774bebb70e13 100644 (file)
 #include <linux/wait.h>
 #include <linux/spi/spi.h>
 #ifdef CONFIG_COMPAT
-#include <asm/compat.h>
+#include <linux/compat.h>
 #endif
 
 #include "pi433_if.h"
 #include "rf69.h"
 
-
-#define N_PI433_MINORS                 (1U << MINORBITS) /*32*/        /* ... up to 256 */
+#define N_PI433_MINORS                 BIT(MINORBITS) /*32*/   /* ... up to 256 */
 #define MAX_MSG_SIZE                   900     /* min: FIFO_SIZE! */
 #define MSG_FIFO_SIZE                  65536   /* 65536 = 2^16  */
 #define NUM_DIO                                2
@@ -79,7 +78,7 @@ struct pi433_device {
        struct device           *dev;
        struct cdev             *cdev;
        struct spi_device       *spi;
-       unsigned                users;
+       unsigned int            users;
 
        /* irq related values */
        struct gpio_desc        *gpiod[NUM_DIO];
@@ -121,32 +120,20 @@ struct pi433_instance {
 
 /*-------------------------------------------------------------------------*/
 
-/* macro for checked access of registers of radio module */
-#define SET_CHECKED(retval) \
-       if (retval < 0) \
-               return retval;
-
-/*-------------------------------------------------------------------------*/
-
 /* GPIO interrupt handlers */
 static irqreturn_t DIO0_irq_handler(int irq, void *dev_id)
 {
        struct pi433_device *device = dev_id;
 
-       if      (device->irq_state[DIO0] == DIO_PacketSent)
-       {
+       if (device->irq_state[DIO0] == DIO_PACKET_SENT) {
                device->free_in_fifo = FIFO_SIZE;
                dev_dbg(device->dev, "DIO0 irq: Packet sent\n");
                wake_up_interruptible(&device->fifo_wait_queue);
-       }
-       else if (device->irq_state[DIO0] == DIO_Rssi_DIO0)
-       {
+       } else if (device->irq_state[DIO0] == DIO_RSSI_DIO0) {
                dev_dbg(device->dev, "DIO0 irq: RSSI level over threshold\n");
                wake_up_interruptible(&device->rx_wait_queue);
-       }
-       else if (device->irq_state[DIO0] == DIO_PayloadReady)
-       {
-               dev_dbg(device->dev, "DIO0 irq: PayloadReady\n");
+       } else if (device->irq_state[DIO0] == DIO_PAYLOAD_READY) {
+               dev_dbg(device->dev, "DIO0 irq: Payload ready\n");
                device->free_in_fifo = 0;
                wake_up_interruptible(&device->fifo_wait_queue);
        }
@@ -158,14 +145,13 @@ static irqreturn_t DIO1_irq_handler(int irq, void *dev_id)
 {
        struct pi433_device *device = dev_id;
 
-       if      (device->irq_state[DIO1] == DIO_FifoNotEmpty_DIO1)
-       {
+       if (device->irq_state[DIO1] == DIO_FIFO_NOT_EMPTY_DIO1) {
                device->free_in_fifo = FIFO_SIZE;
-       }
-       else if (device->irq_state[DIO1] == DIO_FifoLevel)
-       {
-               if (device->rx_active)  device->free_in_fifo = FIFO_THRESHOLD - 1;
-               else                    device->free_in_fifo = FIFO_SIZE - FIFO_THRESHOLD - 1;
+       } else if (device->irq_state[DIO1] == DIO_FIFO_LEVEL) {
+               if (device->rx_active)
+                       device->free_in_fifo = FIFO_THRESHOLD - 1;
+               else
+                       device->free_in_fifo = FIFO_SIZE - FIFO_THRESHOLD - 1;
        }
        dev_dbg(device->dev,
                "DIO1 irq: %d bytes free in fifo\n", device->free_in_fifo);
@@ -183,30 +169,56 @@ rf69_set_rx_cfg(struct pi433_device *dev, struct pi433_rx_cfg *rx_cfg)
        int payload_length;
 
        /* receiver config */
-       SET_CHECKED(rf69_set_frequency  (dev->spi, rx_cfg->frequency));
-       SET_CHECKED(rf69_set_bit_rate   (dev->spi, rx_cfg->bit_rate));
-       SET_CHECKED(rf69_set_modulation (dev->spi, rx_cfg->modulation));
-       SET_CHECKED(rf69_set_antenna_impedance   (dev->spi, rx_cfg->antenna_impedance));
-       SET_CHECKED(rf69_set_rssi_threshold      (dev->spi, rx_cfg->rssi_threshold));
-       SET_CHECKED(rf69_set_ook_threshold_dec   (dev->spi, rx_cfg->thresholdDecrement));
-       SET_CHECKED(rf69_set_bandwidth           (dev->spi, rx_cfg->bw_mantisse, rx_cfg->bw_exponent));
-       SET_CHECKED(rf69_set_bandwidth_during_afc(dev->spi, rx_cfg->bw_mantisse, rx_cfg->bw_exponent));
-       SET_CHECKED(rf69_set_dagc                (dev->spi, rx_cfg->dagc));
+       ret = rf69_set_frequency(dev->spi, rx_cfg->frequency);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_bit_rate(dev->spi, rx_cfg->bit_rate);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_modulation(dev->spi, rx_cfg->modulation);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_antenna_impedance(dev->spi, rx_cfg->antenna_impedance);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_rssi_threshold(dev->spi, rx_cfg->rssi_threshold);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_ook_threshold_dec(dev->spi, rx_cfg->threshold_decrement);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_bandwidth(dev->spi, rx_cfg->bw_mantisse, rx_cfg->bw_exponent);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_bandwidth_during_afc(dev->spi, rx_cfg->bw_mantisse, rx_cfg->bw_exponent);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_dagc(dev->spi, rx_cfg->dagc);
+       if (ret < 0)
+               return ret;
 
        dev->rx_bytes_to_drop = rx_cfg->bytes_to_drop;
 
        /* packet config */
        /* enable */
-       SET_CHECKED(rf69_set_sync_enable(dev->spi, rx_cfg->enable_sync));
-       if (rx_cfg->enable_sync == optionOn)
-       {
-               SET_CHECKED(rf69_set_fifo_fill_condition(dev->spi, afterSyncInterrupt));
-       }
-       else
-       {
-               SET_CHECKED(rf69_set_fifo_fill_condition(dev->spi, always));
+       if (rx_cfg->enable_sync == OPTION_ON) {
+               ret = rf69_enable_sync(dev->spi);
+               if (ret < 0)
+                       return ret;
+
+               ret = rf69_set_fifo_fill_condition(dev->spi, afterSyncInterrupt);
+               if (ret < 0)
+                       return ret;
+       } else {
+               ret = rf69_disable_sync(dev->spi);
+               if (ret < 0)
+                       return ret;
+
+               ret = rf69_set_fifo_fill_condition(dev->spi, always);
+               if (ret < 0)
+                       return ret;
        }
-       if (rx_cfg->enable_length_byte == optionOn) {
+       if (rx_cfg->enable_length_byte == OPTION_ON) {
                ret = rf69_set_packet_format(dev->spi, packetLengthVar);
                if (ret < 0)
                        return ret;
@@ -215,36 +227,56 @@ rf69_set_rx_cfg(struct pi433_device *dev, struct pi433_rx_cfg *rx_cfg)
                if (ret < 0)
                        return ret;
        }
-       SET_CHECKED(rf69_set_adressFiltering(dev->spi, rx_cfg->enable_address_filtering));
-       SET_CHECKED(rf69_set_crc_enable     (dev->spi, rx_cfg->enable_crc));
+       ret = rf69_set_adressFiltering(dev->spi, rx_cfg->enable_address_filtering);
+       if (ret < 0)
+               return ret;
 
-       /* lengths */
-       SET_CHECKED(rf69_set_sync_size(dev->spi, rx_cfg->sync_length));
-       if (rx_cfg->enable_length_byte == optionOn)
-       {
-               SET_CHECKED(rf69_set_payload_length(dev->spi, 0xff));
+       if (rx_cfg->enable_crc == OPTION_ON) {
+               ret = rf69_enable_crc(dev->spi);
+               if (ret < 0)
+                       return ret;
+       } else {
+               ret = rf69_disable_crc(dev->spi);
+               if (ret < 0)
+                       return ret;
        }
-       else if (rx_cfg->fixed_message_length != 0)
-       {
+
+       /* lengths */
+       ret = rf69_set_sync_size(dev->spi, rx_cfg->sync_length);
+       if (ret < 0)
+               return ret;
+       if (rx_cfg->enable_length_byte == OPTION_ON) {
+               ret = rf69_set_payload_length(dev->spi, 0xff);
+               if (ret < 0)
+                       return ret;
+       } else if (rx_cfg->fixed_message_length != 0) {
                payload_length = rx_cfg->fixed_message_length;
-               if (rx_cfg->enable_length_byte  == optionOn) payload_length++;
-               if (rx_cfg->enable_address_filtering != filteringOff) payload_length++;
-               SET_CHECKED(rf69_set_payload_length(dev->spi, payload_length));
-       }
-       else
-       {
-               SET_CHECKED(rf69_set_payload_length(dev->spi, 0));
+               if (rx_cfg->enable_length_byte  == OPTION_ON)
+                       payload_length++;
+               if (rx_cfg->enable_address_filtering != filteringOff)
+                       payload_length++;
+               ret = rf69_set_payload_length(dev->spi, payload_length);
+               if (ret < 0)
+                       return ret;
+       } else {
+               ret = rf69_set_payload_length(dev->spi, 0);
+               if (ret < 0)
+                       return ret;
        }
 
        /* values */
-       if (rx_cfg->enable_sync == optionOn)
-       {
-               SET_CHECKED(rf69_set_sync_values(dev->spi, rx_cfg->sync_pattern));
+       if (rx_cfg->enable_sync == OPTION_ON) {
+               ret = rf69_set_sync_values(dev->spi, rx_cfg->sync_pattern);
+               if (ret < 0)
+                       return ret;
        }
-       if (rx_cfg->enable_address_filtering != filteringOff)
-       {
-               SET_CHECKED(rf69_set_node_address     (dev->spi, rx_cfg->node_address));
-               SET_CHECKED(rf69_set_broadcast_address(dev->spi, rx_cfg->broadcast_address));
+       if (rx_cfg->enable_address_filtering != filteringOff) {
+               ret = rf69_set_node_address(dev->spi, rx_cfg->node_address);
+               if (ret < 0)
+                       return ret;
+               ret = rf69_set_broadcast_address(dev->spi, rx_cfg->broadcast_address);
+               if (ret < 0)
+                       return ret;
        }
 
        return 0;
@@ -255,25 +287,50 @@ rf69_set_tx_cfg(struct pi433_device *dev, struct pi433_tx_cfg *tx_cfg)
 {
        int ret;
 
-       SET_CHECKED(rf69_set_frequency  (dev->spi, tx_cfg->frequency));
-       SET_CHECKED(rf69_set_bit_rate   (dev->spi, tx_cfg->bit_rate));
-       SET_CHECKED(rf69_set_modulation (dev->spi, tx_cfg->modulation));
-       SET_CHECKED(rf69_set_deviation  (dev->spi, tx_cfg->dev_frequency));
-       SET_CHECKED(rf69_set_pa_ramp    (dev->spi, tx_cfg->pa_ramp));
-       SET_CHECKED(rf69_set_modulation_shaping(dev->spi, tx_cfg->modShaping));
-       SET_CHECKED(rf69_set_tx_start_condition(dev->spi, tx_cfg->tx_start_condition));
+       ret = rf69_set_frequency(dev->spi, tx_cfg->frequency);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_bit_rate(dev->spi, tx_cfg->bit_rate);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_modulation(dev->spi, tx_cfg->modulation);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_deviation(dev->spi, tx_cfg->dev_frequency);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_pa_ramp(dev->spi, tx_cfg->pa_ramp);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_modulation_shaping(dev->spi, tx_cfg->mod_shaping);
+       if (ret < 0)
+               return ret;
+       ret = rf69_set_tx_start_condition(dev->spi, tx_cfg->tx_start_condition);
+       if (ret < 0)
+               return ret;
 
        /* packet format enable */
-       if (tx_cfg->enable_preamble == optionOn)
-       {
-               SET_CHECKED(rf69_set_preamble_length(dev->spi, tx_cfg->preamble_length));
+       if (tx_cfg->enable_preamble == OPTION_ON) {
+               ret = rf69_set_preamble_length(dev->spi, tx_cfg->preamble_length);
+               if (ret < 0)
+                       return ret;
+       } else {
+               ret = rf69_set_preamble_length(dev->spi, 0);
+               if (ret < 0)
+                       return ret;
        }
-       else
-       {
-               SET_CHECKED(rf69_set_preamble_length(dev->spi, 0));
+
+       if (tx_cfg->enable_sync == OPTION_ON) {
+               ret = rf69_enable_sync(dev->spi);
+               if (ret < 0)
+                       return ret;
+       } else {
+               ret = rf69_disable_sync(dev->spi);
+               if (ret < 0)
+                       return ret;
        }
-       SET_CHECKED(rf69_set_sync_enable  (dev->spi, tx_cfg->enable_sync));
-       if (tx_cfg->enable_length_byte == optionOn) {
+
+       if (tx_cfg->enable_length_byte == OPTION_ON) {
                ret = rf69_set_packet_format(dev->spi, packetLengthVar);
                if (ret < 0)
                        return ret;
@@ -282,12 +339,25 @@ rf69_set_tx_cfg(struct pi433_device *dev, struct pi433_tx_cfg *tx_cfg)
                if (ret < 0)
                        return ret;
        }
-       SET_CHECKED(rf69_set_crc_enable   (dev->spi, tx_cfg->enable_crc));
+
+       if (tx_cfg->enable_crc == OPTION_ON) {
+               ret = rf69_enable_crc(dev->spi);
+               if (ret < 0)
+                       return ret;
+       } else {
+               ret = rf69_disable_crc(dev->spi);
+               if (ret < 0)
+                       return ret;
+       }
 
        /* configure sync, if enabled */
-       if (tx_cfg->enable_sync == optionOn) {
-               SET_CHECKED(rf69_set_sync_size(dev->spi, tx_cfg->sync_length));
-               SET_CHECKED(rf69_set_sync_values(dev->spi, tx_cfg->sync_pattern));
+       if (tx_cfg->enable_sync == OPTION_ON) {
+               ret = rf69_set_sync_size(dev->spi, tx_cfg->sync_length);
+               if (ret < 0)
+                       return ret;
+               ret = rf69_set_sync_values(dev->spi, tx_cfg->sync_pattern);
+               if (ret < 0)
+                       return ret;
        }
 
        return 0;
@@ -306,43 +376,51 @@ pi433_start_rx(struct pi433_device *dev)
 
        /* setup for receiving */
        retval = rf69_set_rx_cfg(dev, &dev->rx_cfg);
-       if (retval) return retval;
+       if (retval)
+               return retval;
 
        /* setup rssi irq */
-       SET_CHECKED(rf69_set_dio_mapping(dev->spi, DIO0, DIO_Rssi_DIO0));
-       dev->irq_state[DIO0] = DIO_Rssi_DIO0;
+       retval = rf69_set_dio_mapping(dev->spi, DIO0, DIO_RSSI_DIO0);
+       if (retval < 0)
+               return retval;
+       dev->irq_state[DIO0] = DIO_RSSI_DIO0;
        irq_set_irq_type(dev->irq_num[DIO0], IRQ_TYPE_EDGE_RISING);
 
        /* setup fifo level interrupt */
-       SET_CHECKED(rf69_set_fifo_threshold(dev->spi, FIFO_SIZE - FIFO_THRESHOLD));
-       SET_CHECKED(rf69_set_dio_mapping(dev->spi, DIO1, DIO_FifoLevel));
-       dev->irq_state[DIO1] = DIO_FifoLevel;
+       retval = rf69_set_fifo_threshold(dev->spi, FIFO_SIZE - FIFO_THRESHOLD);
+       if (retval < 0)
+               return retval;
+       retval = rf69_set_dio_mapping(dev->spi, DIO1, DIO_FIFO_LEVEL);
+       if (retval < 0)
+               return retval;
+       dev->irq_state[DIO1] = DIO_FIFO_LEVEL;
        irq_set_irq_type(dev->irq_num[DIO1], IRQ_TYPE_EDGE_RISING);
 
        /* set module to receiving mode */
-       SET_CHECKED(rf69_set_mode(dev->spi, receive));
+       retval = rf69_set_mode(dev->spi, receive);
+       if (retval < 0)
+               return retval;
 
        return 0;
 }
 
-
 /*-------------------------------------------------------------------------*/
 
 static int
 pi433_receive(void *data)
 {
        struct pi433_device *dev = data;
-       struct spi_device *spi = dev->spi; /* needed for SET_CHECKED */
+       struct spi_device *spi = dev->spi;
        int bytes_to_read, bytes_total;
        int retval;
 
        dev->interrupt_rx_allowed = false;
 
        /* wait for any tx to finish */
-       dev_dbg(dev->dev,"rx: going to wait for any tx to finish");
+       dev_dbg(dev->dev, "rx: going to wait for any tx to finish");
        retval = wait_event_interruptible(dev->rx_wait_queue, !dev->tx_active);
-       if(retval) /* wait was interrupted */
-       {
+       if (retval) {
+               /* wait was interrupted */
                dev->interrupt_rx_allowed = true;
                wake_up_interruptible(&dev->tx_wait_queue);
                return retval;
@@ -359,8 +437,7 @@ pi433_receive(void *data)
                return retval;
 
        /* now check RSSI, if low wait for getting high (RSSI interrupt) */
-       while ( !rf69_get_flag(dev->spi, rssiExceededThreshold) )
-       {
+       while (!rf69_get_flag(dev->spi, rssiExceededThreshold)) {
                /* allow tx to interrupt us while waiting for high RSSI */
                dev->interrupt_rx_allowed = true;
                wake_up_interruptible(&dev->tx_wait_queue);
@@ -368,43 +445,43 @@ pi433_receive(void *data)
                /* wait for RSSI level to become high */
                dev_dbg(dev->dev, "rx: going to wait for high RSSI level");
                retval = wait_event_interruptible(dev->rx_wait_queue,
-                                                 rf69_get_flag(dev->spi,
-                                                               rssiExceededThreshold));
-               if (retval) goto abort; /* wait was interrupted */
+                                                 rf69_get_flag(dev->spi,
+                                                               rssiExceededThreshold));
+               if (retval) /* wait was interrupted */
+                       goto abort;
                dev->interrupt_rx_allowed = false;
 
                /* cross check for ongoing tx */
-               if (!dev->tx_active) break;
+               if (!dev->tx_active)
+                       break;
        }
 
        /* configure payload ready irq */
-       SET_CHECKED(rf69_set_dio_mapping(spi, DIO0, DIO_PayloadReady));
-       dev->irq_state[DIO0] = DIO_PayloadReady;
+       retval = rf69_set_dio_mapping(spi, DIO0, DIO_PAYLOAD_READY);
+       if (retval < 0)
+               goto abort;
+       dev->irq_state[DIO0] = DIO_PAYLOAD_READY;
        irq_set_irq_type(dev->irq_num[DIO0], IRQ_TYPE_EDGE_RISING);
 
        /* fixed or unlimited length? */
-       if (dev->rx_cfg.fixed_message_length != 0)
-       {
-               if (dev->rx_cfg.fixed_message_length > dev->rx_buffer_size)
-               {
+       if (dev->rx_cfg.fixed_message_length != 0) {
+               if (dev->rx_cfg.fixed_message_length > dev->rx_buffer_size) {
                        retval = -1;
                        goto abort;
                }
                bytes_total = dev->rx_cfg.fixed_message_length;
-               dev_dbg(dev->dev,"rx: msg len set to %d by fixed length", bytes_total);
-       }
-       else
-       {
+               dev_dbg(dev->dev, "rx: msg len set to %d by fixed length", bytes_total);
+       } else {
                bytes_total = dev->rx_buffer_size;
                dev_dbg(dev->dev, "rx: msg len set to %d as requested by read", bytes_total);
        }
 
        /* length byte enabled? */
-       if (dev->rx_cfg.enable_length_byte == optionOn)
-       {
+       if (dev->rx_cfg.enable_length_byte == OPTION_ON) {
                retval = wait_event_interruptible(dev->fifo_wait_queue,
                                                  dev->free_in_fifo < FIFO_SIZE);
-               if (retval) goto abort; /* wait was interrupted */
+               if (retval) /* wait was interrupted */
+                       goto abort;
 
                rf69_read_fifo(spi, (u8 *)&bytes_total, 1);
                if (bytes_total > dev->rx_buffer_size) {
@@ -416,15 +493,15 @@ pi433_receive(void *data)
        }
 
        /* address byte enabled? */
-       if (dev->rx_cfg.enable_address_filtering != filteringOff)
-       {
+       if (dev->rx_cfg.enable_address_filtering != filteringOff) {
                u8 dummy;
 
                bytes_total--;
 
                retval = wait_event_interruptible(dev->fifo_wait_queue,
                                                  dev->free_in_fifo < FIFO_SIZE);
-               if (retval) goto abort; /* wait was interrupted */
+               if (retval) /* wait was interrupted */
+                       goto abort;
 
                rf69_read_fifo(spi, &dummy, 1);
                dev->free_in_fifo++;
@@ -432,13 +509,12 @@ pi433_receive(void *data)
        }
 
        /* get payload */
-       while (dev->rx_position < bytes_total)
-       {
-               if ( !rf69_get_flag(dev->spi, payloadReady) )
-               {
+       while (dev->rx_position < bytes_total) {
+               if (!rf69_get_flag(dev->spi, payload_ready)) {
                        retval = wait_event_interruptible(dev->fifo_wait_queue,
                                                          dev->free_in_fifo < FIFO_SIZE);
-                       if (retval) goto abort; /* wait was interrupted */
+                       if (retval) /* wait was interrupted */
+                               goto abort;
                }
 
                /* need to drop bytes or acquire? */
@@ -447,14 +523,15 @@ pi433_receive(void *data)
                else
                        bytes_to_read = bytes_total - dev->rx_position;
 
-
                /* access the fifo */
                if (bytes_to_read > FIFO_SIZE - dev->free_in_fifo)
                        bytes_to_read = FIFO_SIZE - dev->free_in_fifo;
                retval = rf69_read_fifo(spi,
                                        &dev->rx_buffer[dev->rx_position],
                                        bytes_to_read);
-               if (retval) goto abort; /* read failed */
+               if (retval) /* read failed */
+                       goto abort;
+
                dev->free_in_fifo += bytes_to_read;
 
                /* adjust status vars */
@@ -464,11 +541,11 @@ pi433_receive(void *data)
                        dev->rx_position += bytes_to_read;
        }
 
-
        /* rx done, wait was interrupted or error occurred */
 abort:
        dev->interrupt_rx_allowed = true;
-       SET_CHECKED(rf69_set_mode(dev->spi, standby));
+       if (rf69_set_mode(dev->spi, standby))
+               pr_err("rf69_set_mode(): radio module failed to go standby\n");
        wake_up_interruptible(&dev->tx_wait_queue);
 
        if (retval)
@@ -481,22 +558,20 @@ static int
 pi433_tx_thread(void *data)
 {
        struct pi433_device *device = data;
-       struct spi_device *spi = device->spi; /* needed for SET_CHECKED */
+       struct spi_device *spi = device->spi;
        struct pi433_tx_cfg tx_cfg;
-       u8     *buffer = device->buffer;
        size_t size;
        bool   rx_interrupted = false;
        int    position, repetitions;
        int    retval;
 
-       while (1)
-       {
+       while (1) {
                /* wait for fifo to be populated or for request to terminate*/
                dev_dbg(device->dev, "thread: going to wait for new messages");
                wait_event_interruptible(device->tx_wait_queue,
-                                        ( !kfifo_is_empty(&device->tx_fifo) ||
-                                           kthread_should_stop() ));
-               if ( kthread_should_stop() )
+                                        (!kfifo_is_empty(&device->tx_fifo) ||
+                                         kthread_should_stop()));
+               if (kthread_should_stop())
                        return 0;
 
                /* get data from fifo in the following order:
@@ -508,14 +583,14 @@ pi433_tx_thread(void *data)
 
                retval = kfifo_out(&device->tx_fifo, &tx_cfg, sizeof(tx_cfg));
                if (retval != sizeof(tx_cfg)) {
-                       dev_dbg(device->dev, "reading tx_cfg from fifo failed: got %d byte(s), expected %d", retval, (unsigned int)sizeof(tx_cfg) );
+                       dev_dbg(device->dev, "reading tx_cfg from fifo failed: got %d byte(s), expected %d", retval, (unsigned int)sizeof(tx_cfg));
                        mutex_unlock(&device->tx_fifo_lock);
                        continue;
                }
 
                retval = kfifo_out(&device->tx_fifo, &size, sizeof(size_t));
                if (retval != sizeof(size_t)) {
-                       dev_dbg(device->dev, "reading msg size from fifo failed: got %d, expected %d", retval, (unsigned int)sizeof(size_t) );
+                       dev_dbg(device->dev, "reading msg size from fifo failed: got %d, expected %d", retval, (unsigned int)sizeof(size_t));
                        mutex_unlock(&device->tx_fifo_lock);
                        continue;
                }
@@ -525,27 +600,27 @@ pi433_tx_thread(void *data)
                        size = tx_cfg.fixed_message_length;
 
                /* increase size, if len byte is requested */
-               if (tx_cfg.enable_length_byte == optionOn)
+               if (tx_cfg.enable_length_byte == OPTION_ON)
                        size++;
 
                /* increase size, if adr byte is requested */
-               if (tx_cfg.enable_address_byte == optionOn)
+               if (tx_cfg.enable_address_byte == OPTION_ON)
                        size++;
 
                /* prime buffer */
-               memset(buffer, 0, size);
+               memset(device->buffer, 0, size);
                position = 0;
 
                /* add length byte, if requested */
-               if (tx_cfg.enable_length_byte  == optionOn)
-                       buffer[position++] = size-1; /* according to spec length byte itself must be excluded from the length calculation */
+               if (tx_cfg.enable_length_byte  == OPTION_ON)
+                       device->buffer[position++] = size - 1; /* according to spec length byte itself must be excluded from the length calculation */
 
                /* add adr byte, if requested */
-               if (tx_cfg.enable_address_byte == optionOn)
-                       buffer[position++] = tx_cfg.address_byte;
+               if (tx_cfg.enable_address_byte == OPTION_ON)
+                       device->buffer[position++] = tx_cfg.address_byte;
 
                /* finally get message data from fifo */
-               retval = kfifo_out(&device->tx_fifo, &buffer[position], sizeof(buffer)-position );
+               retval = kfifo_out(&device->tx_fifo, &device->buffer[position], sizeof(device->buffer) - position);
                dev_dbg(device->dev, "read %d message byte(s) from fifo queue.", retval);
                mutex_unlock(&device->tx_fifo_lock);
 
@@ -557,7 +632,7 @@ pi433_tx_thread(void *data)
                 */
                wait_event_interruptible(device->tx_wait_queue,
                                         !device->rx_active ||
-                                         device->interrupt_rx_allowed == true);
+                                         device->interrupt_rx_allowed);
 
                /* prevent race conditions
                 * irq will be reenabled after tx config is set
@@ -565,91 +640,107 @@ pi433_tx_thread(void *data)
                disable_irq(device->irq_num[DIO0]);
                device->tx_active = true;
 
-               if (device->rx_active && rx_interrupted == false)
-               {
+               if (device->rx_active && !rx_interrupted) {
                        /* rx is currently waiting for a telegram;
                         * we need to set the radio module to standby
                         */
-                       SET_CHECKED(rf69_set_mode(device->spi, standby));
+                       retval = rf69_set_mode(device->spi, standby);
+                       if (retval < 0)
+                               return retval;
                        rx_interrupted = true;
                }
 
                /* clear fifo, set fifo threshold, set payload length */
-               SET_CHECKED(rf69_set_mode(spi, standby)); /* this clears the fifo */
-               SET_CHECKED(rf69_set_fifo_threshold(spi, FIFO_THRESHOLD));
-               if (tx_cfg.enable_length_byte == optionOn)
-               {
-                       SET_CHECKED(rf69_set_payload_length(spi, size * tx_cfg.repetitions));
-               }
-               else
-               {
-                       SET_CHECKED(rf69_set_payload_length(spi, 0));
+               retval = rf69_set_mode(spi, standby); /* this clears the fifo */
+               if (retval < 0)
+                       return retval;
+               retval = rf69_set_fifo_threshold(spi, FIFO_THRESHOLD);
+               if (retval < 0)
+                       return retval;
+               if (tx_cfg.enable_length_byte == OPTION_ON) {
+                       retval = rf69_set_payload_length(spi, size * tx_cfg.repetitions);
+                       if (retval < 0)
+                               return retval;
+               } else {
+                       retval = rf69_set_payload_length(spi, 0);
+                       if (retval < 0)
+                               return retval;
                }
 
                /* configure the rf chip */
-               rf69_set_tx_cfg(device, &tx_cfg);
+               retval = rf69_set_tx_cfg(device, &tx_cfg);
+               if (retval < 0)
+                       return retval;
 
                /* enable fifo level interrupt */
-               SET_CHECKED(rf69_set_dio_mapping(spi, DIO1, DIO_FifoLevel));
-               device->irq_state[DIO1] = DIO_FifoLevel;
+               retval = rf69_set_dio_mapping(spi, DIO1, DIO_FIFO_LEVEL);
+               if (retval < 0)
+                       return retval;
+               device->irq_state[DIO1] = DIO_FIFO_LEVEL;
                irq_set_irq_type(device->irq_num[DIO1], IRQ_TYPE_EDGE_FALLING);
 
                /* enable packet sent interrupt */
-               SET_CHECKED(rf69_set_dio_mapping(spi, DIO0, DIO_PacketSent));
-               device->irq_state[DIO0] = DIO_PacketSent;
+               retval = rf69_set_dio_mapping(spi, DIO0, DIO_PACKET_SENT);
+               if (retval < 0)
+                       return retval;
+               device->irq_state[DIO0] = DIO_PACKET_SENT;
                irq_set_irq_type(device->irq_num[DIO0], IRQ_TYPE_EDGE_RISING);
                enable_irq(device->irq_num[DIO0]); /* was disabled by rx active check */
 
                /* enable transmission */
-               SET_CHECKED(rf69_set_mode(spi, transmit));
+               retval = rf69_set_mode(spi, transmit);
+               if (retval < 0)
+                       return retval;
 
                /* transfer this msg (and repetitions) to chip fifo */
                device->free_in_fifo = FIFO_SIZE;
                position = 0;
                repetitions = tx_cfg.repetitions;
-               while( (repetitions > 0) && (size > position) )
-               {
-                       if ( (size - position) > device->free_in_fifo)
-                       {       /* msg to big for fifo - take a part */
+               while ((repetitions > 0) && (size > position)) {
+                       if ((size - position) > device->free_in_fifo) {
+                               /* msg to big for fifo - take a part */
                                int temp = device->free_in_fifo;
                                device->free_in_fifo = 0;
                                rf69_write_fifo(spi,
-                                               &buffer[position],
-                                               temp);
-                               position +=temp;
-                       }
-                       else
-                       {       /* msg fits into fifo - take all */
+                                               &device->buffer[position],
+                                               temp);
+                               position += temp;
+                       } else {
+                               /* msg fits into fifo - take all */
                                device->free_in_fifo -= size;
                                repetitions--;
                                rf69_write_fifo(spi,
-                                               &buffer[position],
-                                               (size - position) );
+                                               &device->buffer[position],
+                                               (size - position));
                                position = 0; /* reset for next repetition */
                        }
 
                        retval = wait_event_interruptible(device->fifo_wait_queue,
                                                          device->free_in_fifo > 0);
-                       if (retval) { printk("ABORT\n"); goto abort; }
+                       if (retval) {
+                               dev_dbg(device->dev, "ABORT\n");
+                               goto abort;
+                       }
                }
 
                /* we are done. Wait for packet to get sent */
                dev_dbg(device->dev, "thread: wait for packet to get sent/fifo to be empty");
                wait_event_interruptible(device->fifo_wait_queue,
                                         device->free_in_fifo == FIFO_SIZE ||
-                                        kthread_should_stop() );
-               if ( kthread_should_stop() )    printk("ABORT\n");
-
+                                        kthread_should_stop());
+               if (kthread_should_stop())
+                       dev_dbg(device->dev, "ABORT\n");
 
                /* STOP_TRANSMISSION */
                dev_dbg(device->dev, "thread: Packet sent. Set mode to stby.");
-               SET_CHECKED(rf69_set_mode(spi, standby));
+               retval = rf69_set_mode(spi, standby);
+               if (retval < 0)
+                       return retval;
 
                /* everything sent? */
                if (kfifo_is_empty(&device->tx_fifo)) {
 abort:
-                       if (rx_interrupted)
-                       {
+                       if (rx_interrupted) {
                                rx_interrupted = false;
                                pi433_start_rx(device);
                        }
@@ -678,16 +769,13 @@ pi433_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos)
 
        /* just one read request at a time */
        mutex_lock(&device->rx_lock);
-       if (device->rx_active)
-       {
+       if (device->rx_active) {
                mutex_unlock(&device->rx_lock);
                return -EAGAIN;
        }
-       else
-       {
-               device->rx_active = true;
-               mutex_unlock(&device->rx_lock);
-       }
+
+       device->rx_active = true;
+       mutex_unlock(&device->rx_lock);
 
        /* start receiving */
        /* will block until something was received*/
@@ -709,14 +797,14 @@ pi433_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos)
        return bytes_received;
 }
 
-
 static ssize_t
 pi433_write(struct file *filp, const char __user *buf,
-               size_t count, loff_t *f_pos)
+           size_t count, loff_t *f_pos)
 {
        struct pi433_instance   *instance;
        struct pi433_device     *device;
-       int                     copied, retval;
+       int                     retval;
+       unsigned int            copied;
 
        instance = filp->private_data;
        device = instance->device;
@@ -732,11 +820,11 @@ pi433_write(struct file *filp, const char __user *buf,
         */
        mutex_lock(&device->tx_fifo_lock);
        retval = kfifo_in(&device->tx_fifo, &instance->tx_cfg, sizeof(instance->tx_cfg));
-       if ( retval != sizeof(instance->tx_cfg) )
+       if (retval != sizeof(instance->tx_cfg))
                goto abort;
 
-       retval = kfifo_in (&device->tx_fifo, &count, sizeof(size_t));
-       if ( retval != sizeof(size_t) )
+       retval = kfifo_in(&device->tx_fifo, &count, sizeof(size_t));
+       if (retval != sizeof(size_t))
                goto abort;
 
        retval = kfifo_from_user(&device->tx_fifo, buf, count, &copied);
@@ -749,7 +837,7 @@ pi433_write(struct file *filp, const char __user *buf,
        wake_up_interruptible(&device->tx_wait_queue);
        dev_dbg(device->dev, "write: generated new msg with %d bytes.", copied);
 
-       return 0;
+       return copied;
 
 abort:
        dev_dbg(device->dev, "write to fifo failed: 0x%x", retval);
@@ -758,7 +846,6 @@ abort:
        return -EAGAIN;
 }
 
-
 static long
 pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
@@ -777,23 +864,23 @@ pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        instance = filp->private_data;
        device = instance->device;
 
-       if (device == NULL)
+       if (!device)
                return -ESHUTDOWN;
 
        switch (cmd) {
        case PI433_IOC_RD_TX_CFG:
                if (copy_to_user(argp, &instance->tx_cfg,
-                                       sizeof(struct pi433_tx_cfg)))
+                                sizeof(struct pi433_tx_cfg)))
                        return -EFAULT;
                break;
        case PI433_IOC_WR_TX_CFG:
                if (copy_from_user(&instance->tx_cfg, argp,
-                                       sizeof(struct pi433_tx_cfg)))
+                                  sizeof(struct pi433_tx_cfg)))
                        return -EFAULT;
                break;
        case PI433_IOC_RD_RX_CFG:
                if (copy_to_user(argp, &device->rx_cfg,
-                                       sizeof(struct pi433_rx_cfg)))
+                                sizeof(struct pi433_rx_cfg)))
                        return -EFAULT;
                break;
        case PI433_IOC_WR_RX_CFG:
@@ -806,7 +893,7 @@ pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                }
 
                if (copy_from_user(&device->rx_cfg, argp,
-                                       sizeof(struct pi433_rx_cfg))) {
+                                  sizeof(struct pi433_rx_cfg))) {
                        mutex_unlock(&device->rx_lock);
                        return -EFAULT;
                }
@@ -847,10 +934,8 @@ static int pi433_open(struct inode *inode, struct file *filp)
 
        if (!device->rx_buffer) {
                device->rx_buffer = kmalloc(MAX_MSG_SIZE, GFP_KERNEL);
-               if (!device->rx_buffer) {
-                       dev_dbg(device->dev, "open/ENOMEM\n");
+               if (!device->rx_buffer)
                        return -ENOMEM;
-               }
        }
 
        device->users++;
@@ -889,19 +974,18 @@ static int pi433_release(struct inode *inode, struct file *filp)
        if (!device->users) {
                kfree(device->rx_buffer);
                device->rx_buffer = NULL;
-               if (device->spi == NULL)
+               if (!device->spi)
                        kfree(device);
        }
 
        return 0;
 }
 
-
 /*-------------------------------------------------------------------------*/
 
 static int setup_GPIOs(struct pi433_device *device)
 {
-       char    name[5];
+       char    name[5];
        int     retval;
        int     i;
        const irq_handler_t DIO_irq_handler[NUM_DIO] = {
@@ -909,8 +993,7 @@ static int setup_GPIOs(struct pi433_device *device)
                DIO1_irq_handler
        };
 
-       for (i=0; i<NUM_DIO; i++)
-       {
+       for (i = 0; i < NUM_DIO; i++) {
                /* "construct" name and get the gpio descriptor */
                snprintf(name, sizeof(name), "DIO%d", i);
                device->gpiod[i] = gpiod_get(&device->spi->dev, name, 0 /*GPIOD_IN*/);
@@ -923,24 +1006,21 @@ static int setup_GPIOs(struct pi433_device *device)
                if (device->gpiod[i] == ERR_PTR(-EBUSY))
                        dev_dbg(&device->spi->dev, "%s is busy.", name);
 
-               if ( IS_ERR(device->gpiod[i]) )
-               {
+               if (IS_ERR(device->gpiod[i])) {
                        retval = PTR_ERR(device->gpiod[i]);
                        /* release already allocated gpios */
-                       for (i--; i>=0; i--)
-                       {
+                       for (i--; i >= 0; i--) {
                                free_irq(device->irq_num[i], device);
                                gpiod_put(device->gpiod[i]);
                        }
                        return retval;
                }
 
-
                /* configure the pin */
                gpiod_unexport(device->gpiod[i]);
                retval = gpiod_direction_input(device->gpiod[i]);
-               if (retval) return retval;
-
+               if (retval)
+                       return retval;
 
                /* configure irq */
                device->irq_num[i] = gpiod_to_irq(device->gpiod[i]);
@@ -967,16 +1047,14 @@ static void free_GPIOs(struct pi433_device *device)
 {
        int i;
 
-       for (i=0; i<NUM_DIO; i++)
-       {
+       for (i = 0; i < NUM_DIO; i++) {
                /* check if gpiod is valid */
-               if ( IS_ERR(device->gpiod[i]) )
+               if (IS_ERR(device->gpiod[i]))
                        continue;
 
                free_irq(device->irq_num[i], device);
                gpiod_put(device->gpiod[i]);
        }
-       return;
 }
 
 static int pi433_get_minor(struct pi433_device *device)
@@ -989,7 +1067,7 @@ static int pi433_get_minor(struct pi433_device *device)
                device->minor = retval;
                retval = 0;
        } else if (retval == -ENOSPC) {
-               dev_err(device->dev, "too many pi433 devices\n");
+               dev_err(&device->spi->dev, "too many pi433 devices\n");
                retval = -EINVAL;
        }
        mutex_unlock(&minor_lock);
@@ -1002,6 +1080,7 @@ static void pi433_free_minor(struct pi433_device *dev)
        idr_remove(&pi433_idr, dev->minor);
        mutex_unlock(&minor_lock);
 }
+
 /*-------------------------------------------------------------------------*/
 
 static const struct file_operations pi433_fops = {
@@ -1032,17 +1111,14 @@ static int pi433_probe(struct spi_device *spi)
        /* spi->max_speed_hz = 10000000;  1MHz already set by device tree overlay */
 
        retval = spi_setup(spi);
-       if (retval)
-       {
+       if (retval) {
                dev_dbg(&spi->dev, "configuration of SPI interface failed!\n");
                return retval;
        }
-       else
-       {
-               dev_dbg(&spi->dev,
-                       "spi interface setup: mode 0x%2x, %d bits per word, %dhz max speed",
-                       spi->mode, spi->bits_per_word, spi->max_speed_hz);
-       }
+
+       dev_dbg(&spi->dev,
+               "spi interface setup: mode 0x%2x, %d bits per word, %dhz max speed",
+               spi->mode, spi->bits_per_word, spi->max_speed_hz);
 
        /* Ping the chip by reading the version register */
        retval = spi_w8r8(spi, 0x10);
@@ -1089,27 +1165,32 @@ static int pi433_probe(struct spi_device *spi)
        }
 
        /* setup the radio module */
-       SET_CHECKED(rf69_set_mode               (spi, standby));
-       SET_CHECKED(rf69_set_data_mode          (spi, packet));
-       SET_CHECKED(rf69_set_amplifier_0        (spi, optionOn));
-       SET_CHECKED(rf69_set_amplifier_1        (spi, optionOff));
-       SET_CHECKED(rf69_set_amplifier_2        (spi, optionOff));
-       SET_CHECKED(rf69_set_output_power_level (spi, 13));
-       SET_CHECKED(rf69_set_antenna_impedance  (spi, fiftyOhm));
-
-       /* start tx thread */
-       device->tx_task_struct = kthread_run(pi433_tx_thread,
-                                            device,
-                                            "pi433_tx_task");
-       if (IS_ERR(device->tx_task_struct)) {
-               dev_dbg(device->dev, "start of send thread failed");
-               goto send_thread_failed;
-       }
+       retval = rf69_set_mode(spi, standby);
+       if (retval < 0)
+               goto minor_failed;
+       retval = rf69_set_data_mode(spi, DATAMODUL_MODE_PACKET);
+       if (retval < 0)
+               goto minor_failed;
+       retval = rf69_enable_amplifier(spi, MASK_PALEVEL_PA0);
+       if (retval < 0)
+               goto minor_failed;
+       retval = rf69_disable_amplifier(spi, MASK_PALEVEL_PA1);
+       if (retval < 0)
+               goto minor_failed;
+       retval = rf69_disable_amplifier(spi, MASK_PALEVEL_PA2);
+       if (retval < 0)
+               goto minor_failed;
+       retval = rf69_set_output_power_level(spi, 13);
+       if (retval < 0)
+               goto minor_failed;
+       retval = rf69_set_antenna_impedance(spi, fiftyOhm);
+       if (retval < 0)
+               goto minor_failed;
 
        /* determ minor number */
        retval = pi433_get_minor(device);
        if (retval) {
-               dev_dbg(device->dev, "get of minor number failed");
+               dev_dbg(&spi->dev, "get of minor number failed");
                goto minor_failed;
        }
 
@@ -1119,19 +1200,29 @@ static int pi433_probe(struct spi_device *spi)
                                    &spi->dev,
                                    device->devt,
                                    device,
-                                   "pi433");
+                                   "pi433.%d",
+                                   device->minor);
        if (IS_ERR(device->dev)) {
                pr_err("pi433: device register failed\n");
                retval = PTR_ERR(device->dev);
                goto device_create_failed;
-       }
-       else {
+       } else {
                dev_dbg(device->dev,
                        "created device for major %d, minor %d\n",
                        MAJOR(pi433_dev),
                        device->minor);
        }
 
+       /* start tx thread */
+       device->tx_task_struct = kthread_run(pi433_tx_thread,
+                                            device,
+                                            "pi433.%d_tx_task",
+                                            device->minor);
+       if (IS_ERR(device->tx_task_struct)) {
+               dev_dbg(device->dev, "start of send thread failed");
+               goto send_thread_failed;
+       }
+
        /* create cdev */
        device->cdev = cdev_alloc();
        device->cdev->owner = THIS_MODULE;
@@ -1148,12 +1239,12 @@ static int pi433_probe(struct spi_device *spi)
        return 0;
 
 cdev_failed:
+       kthread_stop(device->tx_task_struct);
+send_thread_failed:
        device_destroy(pi433_class, device->devt);
 device_create_failed:
        pi433_free_minor(device);
 minor_failed:
-       kthread_stop(device->tx_task_struct);
-send_thread_failed:
        free_GPIOs(device);
 GPIO_failed:
        kfree(device);
@@ -1230,14 +1321,16 @@ static int __init pi433_init(void)
 
        pi433_class = class_create(THIS_MODULE, "pi433");
        if (IS_ERR(pi433_class)) {
-               unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name);
+               unregister_chrdev(MAJOR(pi433_dev),
+                                 pi433_spi_driver.driver.name);
                return PTR_ERR(pi433_class);
        }
 
        status = spi_register_driver(&pi433_spi_driver);
        if (status < 0) {
                class_destroy(pi433_class);
-               unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name);
+               unregister_chrdev(MAJOR(pi433_dev),
+                                 pi433_spi_driver.driver.name);
        }
 
        return status;
index e6ed3cd9b2e2c9b4dc4096afd6238d81ab4e081f..7314f69af198075db62d79b2136984530f449f85 100644 (file)
 
 /*---------------------------------------------------------------------------*/
 
-
-/*---------------------------------------------------------------------------*/
+enum option_on_off {
+       OPTION_OFF,
+       OPTION_ON
+};
 
 /* IOCTL structs and commands */
 
  *
  * NOTE: struct layout is the same in 64bit and 32bit userspace.
  */
-#define PI433_TX_CFG_IOCTL_NR  0
-struct pi433_tx_cfg
-{
+#define PI433_TX_CFG_IOCTL_NR  0
+struct pi433_tx_cfg {
        __u32                   frequency;
        __u16                   bit_rate;
        __u32                   dev_frequency;
        enum modulation         modulation;
-       enum modShaping         modShaping;
+       enum mod_shaping        mod_shaping;
 
        enum paRamp             pa_ramp;
 
@@ -72,13 +73,12 @@ struct pi433_tx_cfg
 
        __u16                   repetitions;
 
-
        /* packet format */
-       enum optionOnOff        enable_preamble;
-       enum optionOnOff        enable_sync;
-       enum optionOnOff        enable_length_byte;
-       enum optionOnOff        enable_address_byte;
-       enum optionOnOff        enable_crc;
+       enum option_on_off      enable_preamble;
+       enum option_on_off      enable_sync;
+       enum option_on_off      enable_length_byte;
+       enum option_on_off      enable_address_byte;
+       enum option_on_off      enable_crc;
 
        __u16                   preamble_length;
        __u8                    sync_length;
@@ -88,7 +88,6 @@ struct pi433_tx_cfg
        __u8                    address_byte;
 };
 
-
 /**
  * struct pi433_rx_config - describes the configuration of the radio module for sending
  * @frequency:
@@ -107,7 +106,7 @@ struct pi433_tx_cfg
  *
  * NOTE: struct layout is the same in 64bit and 32bit userspace.
  */
-#define PI433_RX_CFG_IOCTL_NR  1
+#define PI433_RX_CFG_IOCTL_NR  1
 struct pi433_rx_cfg {
        __u32                   frequency;
        __u16                   bit_rate;
@@ -116,20 +115,18 @@ struct pi433_rx_cfg {
        enum modulation         modulation;
 
        __u8                    rssi_threshold;
-       enum thresholdDecrement thresholdDecrement;
+       enum thresholdDecrement threshold_decrement;
        enum antennaImpedance   antenna_impedance;
        enum lnaGain            lna_gain;
        enum mantisse           bw_mantisse;    /* normal: 0x50 */
        __u8                    bw_exponent;    /* during AFC: 0x8b */
        enum dagc               dagc;
 
-
-
        /* packet format */
-       enum optionOnOff        enable_sync;
-       enum optionOnOff        enable_length_byte;       /* should be used in combination with sync, only */
+       enum option_on_off      enable_sync;
+       enum option_on_off      enable_length_byte;       /* should be used in combination with sync, only */
        enum addressFiltering   enable_address_filtering; /* operational with sync, only */
-       enum optionOnOff        enable_crc;               /* only operational, if sync on and fixed length or length byte is used */
+       enum option_on_off      enable_crc;               /* only operational, if sync on and fixed length or length byte is used */
 
        __u8                    sync_length;
        __u8                    fixed_message_length;
@@ -140,7 +137,6 @@ struct pi433_rx_cfg {
        __u8                    broadcast_address;
 };
 
-
 #define PI433_IOC_MAGIC                        'r'
 
 #define PI433_IOC_RD_TX_CFG    _IOR(PI433_IOC_MAGIC, PI433_TX_CFG_IOCTL_NR, char[sizeof(struct pi433_tx_cfg)])
index 12c9df9cddde22bea46650ededda1ed4d3e057ae..7ccdff6ae213b613ae44d24c9fa53402cc30b529 100644 (file)
 #include "rf69_registers.h"
 
 #define F_OSC    32000000 /* in Hz */
-#define FIFO_SIZE 66      /* in byte */
+#define FIFO_SIZE 66      /* in byte */
 
 /*-------------------------------------------------------------------------*/
 
-#define READ_REG(x)    rf69_read_reg (spi, x)
-#define WRITE_REG(x, y)        rf69_write_reg(spi, x, y)
+static u8 rf69_read_reg(struct spi_device *spi, u8 addr)
+{
+       int retval;
+
+       retval = spi_w8r8(spi, addr);
+
+#ifdef DEBUG_VALUES
+       if (retval < 0)
+               /* should never happen, since we already checked,
+                * that module is connected. Therefore no error
+                * handling, just an optional error message...
+                */
+               dev_dbg(&spi->dev, "read 0x%x FAILED\n", addr);
+       else
+               dev_dbg(&spi->dev, "read 0x%x from reg 0x%x\n", retval, addr);
+#endif
+
+       return retval;
+}
+
+static int rf69_write_reg(struct spi_device *spi, u8 addr, u8 value)
+{
+       int retval;
+       char buffer[2];
+
+       buffer[0] = addr | WRITE_BIT;
+       buffer[1] = value;
+
+       retval = spi_write(spi, &buffer, 2);
+
+#ifdef DEBUG_VALUES
+       if (retval < 0)
+               /* should never happen, since we already checked,
+                * that module is connected. Therefore no error
+                * handling, just an optional error message...
+                */
+               dev_dbg(&spi->dev, "write 0x%x to 0x%x FAILED\n", value, addr);
+       else
+               dev_dbg(&spi->dev, "wrote 0x%x to reg 0x%x\n", value, addr);
+#endif
+
+       return retval;
+}
 
 /*-------------------------------------------------------------------------*/
 
-int rf69_set_mode(struct spi_device *spi, enum mode mode)
+static int rf69_set_bit(struct spi_device *spi, u8 reg, u8 mask)
+{
+       u8 tmp;
+
+       tmp = rf69_read_reg(spi, reg);
+       tmp = tmp | mask;
+       return rf69_write_reg(spi, reg, tmp);
+}
+
+static int rf69_clear_bit(struct spi_device *spi, u8 reg, u8 mask)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: mode");
-       #endif
+       u8 tmp;
 
+       tmp = rf69_read_reg(spi, reg);
+       tmp = tmp & ~mask;
+       return rf69_write_reg(spi, reg, tmp);
+}
+
+static inline int rf69_read_mod_write(struct spi_device *spi, u8 reg, u8 mask, u8 value)
+{
+       u8 tmp;
+
+       tmp = rf69_read_reg(spi, reg);
+       tmp = (tmp & ~mask) | value;
+       return rf69_write_reg(spi, reg, tmp);
+}
+
+/*-------------------------------------------------------------------------*/
+
+int rf69_set_mode(struct spi_device *spi, enum mode mode)
+{
        switch (mode) {
-       case transmit:    return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_TRANSMIT);
-       case receive:     return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_RECEIVE);
-       case synthesizer: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_SYNTHESIZER);
-       case standby:     return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_STANDBY);
-       case mode_sleep:  return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_SLEEP);
+       case transmit:
+               return rf69_read_mod_write(spi, REG_OPMODE, MASK_OPMODE_MODE, OPMODE_MODE_TRANSMIT);
+       case receive:
+               return rf69_read_mod_write(spi, REG_OPMODE, MASK_OPMODE_MODE, OPMODE_MODE_RECEIVE);
+       case synthesizer:
+               return rf69_read_mod_write(spi, REG_OPMODE, MASK_OPMODE_MODE, OPMODE_MODE_SYNTHESIZER);
+       case standby:
+               return rf69_read_mod_write(spi, REG_OPMODE, MASK_OPMODE_MODE, OPMODE_MODE_STANDBY);
+       case mode_sleep:
+               return rf69_read_mod_write(spi, REG_OPMODE, MASK_OPMODE_MODE, OPMODE_MODE_SLEEP);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
@@ -58,82 +129,75 @@ int rf69_set_mode(struct spi_device *spi, enum mode mode)
        // we are using packet mode, so this check is not really needed
        // but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode
        //while (_mode == RF69_MODE_SLEEP && (READ_REG(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady
-
 }
 
-int rf69_set_data_mode(struct spi_device *spi, enum dataMode dataMode)
+int rf69_set_data_mode(struct spi_device *spi, u8 data_mode)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: data mode");
-       #endif
-
-       switch (dataMode) {
-       case packet:            return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_PACKET);
-       case continuous:        return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_CONTINUOUS);
-       case continuousNoSync:  return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_CONTINUOUS_NOSYNC);
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
+       return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODE, data_mode);
 }
 
 int rf69_set_modulation(struct spi_device *spi, enum modulation modulation)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: modulation");
-       #endif
-
        switch (modulation) {
-       case OOK:   return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_TYPE) | DATAMODUL_MODULATION_TYPE_OOK);
-       case FSK:   return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_TYPE) | DATAMODUL_MODULATION_TYPE_FSK);
+       case OOK:
+               return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODULATION_TYPE, DATAMODUL_MODULATION_TYPE_OOK);
+       case FSK:
+               return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODULATION_TYPE, DATAMODUL_MODULATION_TYPE_FSK);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
        }
 }
 
-enum modulation rf69_get_modulation(struct spi_device *spi)
+static enum modulation rf69_get_modulation(struct spi_device *spi)
 {
        u8 currentValue;
 
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "get: mode");
-       #endif
-
-       currentValue = READ_REG(REG_DATAMODUL);
+       currentValue = rf69_read_reg(spi, REG_DATAMODUL);
 
        switch (currentValue & MASK_DATAMODUL_MODULATION_TYPE) {
-       case DATAMODUL_MODULATION_TYPE_OOK: return OOK;
-       case DATAMODUL_MODULATION_TYPE_FSK: return FSK;
-       default:                            return undefined;
+       case DATAMODUL_MODULATION_TYPE_OOK:
+               return OOK;
+       case DATAMODUL_MODULATION_TYPE_FSK:
+               return FSK;
+       default:
+               return UNDEF;
        }
 }
 
-int rf69_set_modulation_shaping(struct spi_device *spi, enum modShaping modShaping)
+int rf69_set_modulation_shaping(struct spi_device *spi,
+                               enum mod_shaping mod_shaping)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: mod shaping");
-       #endif
-
-       if (rf69_get_modulation(spi) == FSK) {
-               switch (modShaping) {
-               case shapingOff: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_NONE);
-               case shaping1_0: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_1_0);
-               case shaping0_5: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_0_3);
-               case shaping0_3: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_0_5);
+       switch (rf69_get_modulation(spi)) {
+       case FSK:
+               switch (mod_shaping) {
+               case SHAPING_OFF:
+                       return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODULATION_SHAPE, DATAMODUL_MODULATION_SHAPE_NONE);
+               case SHAPING_1_0:
+                       return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODULATION_SHAPE, DATAMODUL_MODULATION_SHAPE_1_0);
+               case SHAPING_0_5:
+                       return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODULATION_SHAPE, DATAMODUL_MODULATION_SHAPE_0_5);
+               case SHAPING_0_3:
+                       return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODULATION_SHAPE, DATAMODUL_MODULATION_SHAPE_0_3);
                default:
                        dev_dbg(&spi->dev, "set: illegal input param");
                        return -EINVAL;
                }
-       } else {
-               switch (modShaping) {
-               case shapingOff: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_NONE);
-               case shapingBR:  return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_BR);
-               case shaping2BR: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_2BR);
+       case OOK:
+               switch (mod_shaping) {
+               case SHAPING_OFF:
+                       return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODULATION_SHAPE, DATAMODUL_MODULATION_SHAPE_NONE);
+               case SHAPING_BR:
+                       return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODULATION_SHAPE, DATAMODUL_MODULATION_SHAPE_BR);
+               case SHAPING_2BR:
+                       return rf69_read_mod_write(spi, REG_DATAMODUL, MASK_DATAMODUL_MODULATION_SHAPE, DATAMODUL_MODULATION_SHAPE_2BR);
                default:
                        dev_dbg(&spi->dev, "set: illegal input param");
                        return -EINVAL;
                }
+       default:
+               dev_dbg(&spi->dev, "set: modulation undefined");
+               return -EINVAL;
        }
 }
 
@@ -145,10 +209,6 @@ int rf69_set_bit_rate(struct spi_device *spi, u16 bitRate)
        u8 msb;
        u8 lsb;
 
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: bit rate");
-       #endif
-
        // check input value
        bitRate_min = F_OSC / 8388608; // 8388608 = 2^23;
        if (bitRate < bitRate_min) {
@@ -159,15 +219,14 @@ int rf69_set_bit_rate(struct spi_device *spi, u16 bitRate)
        // calculate reg settings
        bitRate_reg = (F_OSC / bitRate);
 
-       msb = (bitRate_reg&0xff00)   >>  8;
-       lsb = (bitRate_reg&0xff);
+       msb = (bitRate_reg & 0xff00) >> 8;
+       lsb = (bitRate_reg & 0xff);
 
        // transmit to RF 69
-       retval = WRITE_REG(REG_BITRATE_MSB, msb);
+       retval = rf69_write_reg(spi, REG_BITRATE_MSB, msb);
        if (retval)
                return retval;
-
-       retval = WRITE_REG(REG_BITRATE_LSB, lsb);
+       retval = rf69_write_reg(spi, REG_BITRATE_LSB, lsb);
        if (retval)
                return retval;
 
@@ -177,18 +236,14 @@ int rf69_set_bit_rate(struct spi_device *spi, u16 bitRate)
 int rf69_set_deviation(struct spi_device *spi, u32 deviation)
 {
        int retval;
-//     u32 f_max; TODO: Abhängigkeit von Bitrate beachten!!
        u64 f_reg;
        u64 f_step;
        u8 msb;
        u8 lsb;
        u64 factor = 1000000; // to improve precision of calculation
 
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: deviation");
-       #endif
-
-       if (deviation < 600 || deviation > 500000) { //TODO: Abhängigkeit von Bitrate beachten!!
+       // TODO: Dependency to bitrate
+       if (deviation < 600 || deviation > 500000) {
                dev_dbg(&spi->dev, "set_deviation: illegal input param");
                return -EINVAL;
        }
@@ -201,8 +256,8 @@ int rf69_set_deviation(struct spi_device *spi, u32 deviation)
        f_reg = deviation * factor;
        do_div(f_reg, f_step);
 
-       msb = (f_reg&0xff00)   >>  8;
-       lsb = (f_reg&0xff);
+       msb = (f_reg & 0xff00) >> 8;
+       lsb = (f_reg & 0xff);
 
        // check msb
        if (msb & ~FDEVMASB_MASK) {
@@ -211,11 +266,10 @@ int rf69_set_deviation(struct spi_device *spi, u32 deviation)
        }
 
        // write to chip
-       retval = WRITE_REG(REG_FDEV_MSB, msb);
+       retval = rf69_write_reg(spi, REG_FDEV_MSB, msb);
        if (retval)
                return retval;
-
-       retval = WRITE_REG(REG_FDEV_LSB, lsb);
+       retval = rf69_write_reg(spi, REG_FDEV_LSB, lsb);
        if (retval)
                return retval;
 
@@ -233,10 +287,6 @@ int rf69_set_frequency(struct spi_device *spi, u32 frequency)
        u8 lsb;
        u64 factor = 1000000; // to improve precision of calculation
 
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: frequency");
-       #endif
-
        // calculat f step
        f_step = F_OSC * factor;
        do_div(f_step, 524288); //  524288 = 2^19
@@ -252,78 +302,38 @@ int rf69_set_frequency(struct spi_device *spi, u32 frequency)
        f_reg = frequency * factor;
        do_div(f_reg, f_step);
 
-       msb = (f_reg&0xff0000) >> 16;
-       mid = (f_reg&0xff00)   >>  8;
-       lsb = (f_reg&0xff);
+       msb = (f_reg & 0xff0000) >> 16;
+       mid = (f_reg & 0xff00)   >>  8;
+       lsb = (f_reg & 0xff);
 
        // write to chip
-       retval = WRITE_REG(REG_FRF_MSB, msb);
+       retval = rf69_write_reg(spi, REG_FRF_MSB, msb);
        if (retval)
                return retval;
-
-       retval = WRITE_REG(REG_FRF_MID, mid);
+       retval = rf69_write_reg(spi, REG_FRF_MID, mid);
        if (retval)
                return retval;
-
-       retval = WRITE_REG(REG_FRF_LSB, lsb);
+       retval = rf69_write_reg(spi, REG_FRF_LSB, lsb);
        if (retval)
                return retval;
 
        return 0;
 }
 
-int rf69_set_amplifier_0(struct spi_device *spi, enum optionOnOff optionOnOff)
+int rf69_enable_amplifier(struct spi_device *spi, u8 amplifier_mask)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: amp #0");
-       #endif
-
-       switch (optionOnOff) {
-       case optionOn:  return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) |  MASK_PALEVEL_PA0));
-       case optionOff: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) & ~MASK_PALEVEL_PA0));
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
-}
-
-int rf69_set_amplifier_1(struct spi_device *spi, enum optionOnOff optionOnOff)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: amp #1");
-       #endif
-
-       switch (optionOnOff) {
-       case optionOn:  return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) |  MASK_PALEVEL_PA1));
-       case optionOff: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) & ~MASK_PALEVEL_PA1));
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
+       return rf69_set_bit(spi, REG_PALEVEL, amplifier_mask);
 }
 
-int rf69_set_amplifier_2(struct spi_device *spi, enum optionOnOff optionOnOff)
+int rf69_disable_amplifier(struct spi_device *spi, u8 amplifier_mask)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: amp #2");
-       #endif
-
-       switch (optionOnOff) {
-       case optionOn:  return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) |  MASK_PALEVEL_PA2));
-       case optionOff: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) & ~MASK_PALEVEL_PA2));
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
+       return rf69_clear_bit(spi, REG_PALEVEL, amplifier_mask);
 }
 
 int rf69_set_output_power_level(struct spi_device *spi, u8 powerLevel)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: power level");
-       #endif
-
-       powerLevel += 18; // TODO Abhängigkeit von PA0,1,2 setting
+       // TODO: Dependency to PA0,1,2 setting
+       powerLevel += 18;
 
        // check input value
        if (powerLevel > 0x1f) {
@@ -332,32 +342,44 @@ int rf69_set_output_power_level(struct spi_device *spi, u8 powerLevel)
        }
 
        // write value
-       return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) & ~MASK_PALEVEL_OUTPUT_POWER) | powerLevel);
+       return rf69_read_mod_write(spi, REG_PALEVEL, MASK_PALEVEL_OUTPUT_POWER, powerLevel);
 }
 
 int rf69_set_pa_ramp(struct spi_device *spi, enum paRamp paRamp)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: pa ramp");
-       #endif
-
        switch (paRamp) {
-       case ramp3400:  return WRITE_REG(REG_PARAMP, PARAMP_3400);
-       case ramp2000:  return WRITE_REG(REG_PARAMP, PARAMP_2000);
-       case ramp1000:  return WRITE_REG(REG_PARAMP, PARAMP_1000);
-       case ramp500:   return WRITE_REG(REG_PARAMP, PARAMP_500);
-       case ramp250:   return WRITE_REG(REG_PARAMP, PARAMP_250);
-       case ramp125:   return WRITE_REG(REG_PARAMP, PARAMP_125);
-       case ramp100:   return WRITE_REG(REG_PARAMP, PARAMP_100);
-       case ramp62:    return WRITE_REG(REG_PARAMP, PARAMP_62);
-       case ramp50:    return WRITE_REG(REG_PARAMP, PARAMP_50);
-       case ramp40:    return WRITE_REG(REG_PARAMP, PARAMP_40);
-       case ramp31:    return WRITE_REG(REG_PARAMP, PARAMP_31);
-       case ramp25:    return WRITE_REG(REG_PARAMP, PARAMP_25);
-       case ramp20:    return WRITE_REG(REG_PARAMP, PARAMP_20);
-       case ramp15:    return WRITE_REG(REG_PARAMP, PARAMP_15);
-       case ramp12:    return WRITE_REG(REG_PARAMP, PARAMP_12);
-       case ramp10:    return WRITE_REG(REG_PARAMP, PARAMP_10);
+       case ramp3400:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_3400);
+       case ramp2000:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_2000);
+       case ramp1000:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_1000);
+       case ramp500:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_500);
+       case ramp250:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_250);
+       case ramp125:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_125);
+       case ramp100:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_100);
+       case ramp62:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_62);
+       case ramp50:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_50);
+       case ramp40:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_40);
+       case ramp31:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_31);
+       case ramp25:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_25);
+       case ramp20:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_20);
+       case ramp15:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_15);
+       case ramp12:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_12);
+       case ramp10:
+               return rf69_write_reg(spi, REG_PARAMP, PARAMP_10);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
@@ -366,13 +388,11 @@ int rf69_set_pa_ramp(struct spi_device *spi, enum paRamp paRamp)
 
 int rf69_set_antenna_impedance(struct spi_device *spi, enum antennaImpedance antennaImpedance)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: antenna impedance");
-       #endif
-
        switch (antennaImpedance) {
-       case fiftyOhm:      return WRITE_REG(REG_LNA, (READ_REG(REG_LNA) & ~MASK_LNA_ZIN));
-       case twohundretOhm: return WRITE_REG(REG_LNA, (READ_REG(REG_LNA) |  MASK_LNA_ZIN));
+       case fiftyOhm:
+               return rf69_clear_bit(spi, REG_LNA, MASK_LNA_ZIN);
+       case twohundretOhm:
+               return rf69_set_bit(spi, REG_LNA, MASK_LNA_ZIN);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
@@ -381,81 +401,27 @@ int rf69_set_antenna_impedance(struct spi_device *spi, enum antennaImpedance ant
 
 int rf69_set_lna_gain(struct spi_device *spi, enum lnaGain lnaGain)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: lna gain");
-       #endif
-
        switch (lnaGain) {
-       case automatic:  return WRITE_REG(REG_LNA, ((READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_AUTO));
-       case max:        return WRITE_REG(REG_LNA, ((READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX));
-       case maxMinus6:  return WRITE_REG(REG_LNA, ((READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_6));
-       case maxMinus12: return WRITE_REG(REG_LNA, ((READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_12));
-       case maxMinus24: return WRITE_REG(REG_LNA, ((READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_24));
-       case maxMinus36: return WRITE_REG(REG_LNA, ((READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_36));
-       case maxMinus48: return WRITE_REG(REG_LNA, ((READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_48));
+       case automatic:
+               return rf69_read_mod_write(spi, REG_LNA, MASK_LNA_GAIN, LNA_GAIN_AUTO);
+       case max:
+               return rf69_read_mod_write(spi, REG_LNA, MASK_LNA_GAIN, LNA_GAIN_MAX);
+       case max_minus_6:
+               return rf69_read_mod_write(spi, REG_LNA, MASK_LNA_GAIN, LNA_GAIN_MAX_MINUS_6);
+       case max_minus_12:
+               return rf69_read_mod_write(spi, REG_LNA, MASK_LNA_GAIN, LNA_GAIN_MAX_MINUS_12);
+       case max_minus_24:
+               return rf69_read_mod_write(spi, REG_LNA, MASK_LNA_GAIN, LNA_GAIN_MAX_MINUS_24);
+       case max_minus_36:
+               return rf69_read_mod_write(spi, REG_LNA, MASK_LNA_GAIN, LNA_GAIN_MAX_MINUS_36);
+       case max_minus_48:
+               return rf69_read_mod_write(spi, REG_LNA, MASK_LNA_GAIN, LNA_GAIN_MAX_MINUS_48);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
        }
 }
 
-enum lnaGain rf69_get_lna_gain(struct spi_device *spi)
-{
-       u8 currentValue;
-
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "get: lna gain");
-       #endif
-
-       currentValue = READ_REG(REG_LNA);
-
-       switch (currentValue & MASK_LNA_CURRENT_GAIN >> 3) { // improvement: change 3 to define
-       case LNA_GAIN_AUTO:         return automatic;
-       case LNA_GAIN_MAX:          return max;
-       case LNA_GAIN_MAX_MINUS_6:  return maxMinus6;
-       case LNA_GAIN_MAX_MINUS_12: return maxMinus12;
-       case LNA_GAIN_MAX_MINUS_24: return maxMinus24;
-       case LNA_GAIN_MAX_MINUS_36: return maxMinus36;
-       case LNA_GAIN_MAX_MINUS_48: return maxMinus48;
-       default:                    return undefined;
-       }
-}
-
-int rf69_set_dc_cut_off_frequency_intern(struct spi_device *spi, u8 reg, enum dccPercent dccPercent)
-{
-       switch (dccPercent) {
-       case dcc16Percent:      return WRITE_REG(reg, ((READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_16_PERCENT));
-       case dcc8Percent:       return WRITE_REG(reg, ((READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_8_PERCENT));
-       case dcc4Percent:       return WRITE_REG(reg, ((READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_4_PERCENT));
-       case dcc2Percent:       return WRITE_REG(reg, ((READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_2_PERCENT));
-       case dcc1Percent:       return WRITE_REG(reg, ((READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_1_PERCENT));
-       case dcc0_5Percent:     return WRITE_REG(reg, ((READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_0_5_PERCENT));
-       case dcc0_25Percent:    return WRITE_REG(reg, ((READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_0_25_PERCENT));
-       case dcc0_125Percent:   return WRITE_REG(reg, ((READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_0_125_PERCENT));
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
-}
-
-int rf69_set_dc_cut_off_frequency(struct spi_device *spi, enum dccPercent dccPercent)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: cut off freq");
-       #endif
-
-       return rf69_set_dc_cut_off_frequency_intern(spi, REG_RXBW, dccPercent);
-}
-
-int rf69_set_dc_cut_off_frequency_during_afc(struct spi_device *spi, enum dccPercent dccPercent)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: cut off freq during afc");
-       #endif
-
-       return rf69_set_dc_cut_off_frequency_intern(spi, REG_AFCBW, dccPercent);
-}
-
 static int rf69_set_bandwidth_intern(struct spi_device *spi, u8 reg,
                                     enum mantisse mantisse, u8 exponent)
 {
@@ -475,7 +441,7 @@ static int rf69_set_bandwidth_intern(struct spi_device *spi, u8 reg,
        }
 
        // read old value
-       newValue = READ_REG(reg);
+       newValue = rf69_read_reg(spi, reg);
 
        // "delete" mantisse and exponent = just keep the DCC setting
        newValue = newValue & MASK_BW_DCC_FREQ;
@@ -497,79 +463,38 @@ static int rf69_set_bandwidth_intern(struct spi_device *spi, u8 reg,
        newValue = newValue | exponent;
 
        // write back
-       return WRITE_REG(reg, newValue);
+       return rf69_write_reg(spi, reg, newValue);
 }
 
 int rf69_set_bandwidth(struct spi_device *spi, enum mantisse mantisse, u8 exponent)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: band width");
-       #endif
-
        return rf69_set_bandwidth_intern(spi, REG_RXBW, mantisse, exponent);
 }
 
 int rf69_set_bandwidth_during_afc(struct spi_device *spi, enum mantisse mantisse, u8 exponent)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: band width during afc");
-       #endif
-
        return rf69_set_bandwidth_intern(spi, REG_AFCBW, mantisse, exponent);
 }
 
-int rf69_set_ook_threshold_type(struct spi_device *spi, enum thresholdType thresholdType)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: threshold type");
-       #endif
-
-       switch (thresholdType) {
-       case fixed:     return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESTYPE) | OOKPEAK_THRESHTYPE_FIXED));
-       case peak:      return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESTYPE) | OOKPEAK_THRESHTYPE_PEAK));
-       case average:   return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESTYPE) | OOKPEAK_THRESHTYPE_AVERAGE));
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
-}
-
-int rf69_set_ook_threshold_step(struct spi_device *spi, enum thresholdStep thresholdStep)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: threshold step");
-       #endif
-
-       switch (thresholdStep) {
-       case step_0_5db: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_0_5_DB));
-       case step_1_0db: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_1_0_DB));
-       case step_1_5db: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_1_5_DB));
-       case step_2_0db: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_2_0_DB));
-       case step_3_0db: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_3_0_DB));
-       case step_4_0db: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_4_0_DB));
-       case step_5_0db: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_5_0_DB));
-       case step_6_0db: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_6_0_DB));
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
-}
-
 int rf69_set_ook_threshold_dec(struct spi_device *spi, enum thresholdDecrement thresholdDecrement)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: threshold decrement");
-       #endif
-
        switch (thresholdDecrement) {
-       case dec_every8th: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_EVERY_8TH));
-       case dec_every4th: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_EVERY_4TH));
-       case dec_every2nd: return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_EVERY_2ND));
-       case dec_once:     return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_ONCE));
-       case dec_twice:    return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_TWICE));
-       case dec_4times:   return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_4_TIMES));
-       case dec_8times:   return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_8_TIMES));
-       case dec_16times:  return WRITE_REG(REG_OOKPEAK, ((READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_16_TIMES));
+       case dec_every8th:
+               return rf69_read_mod_write(spi, REG_OOKPEAK, MASK_OOKPEAK_THRESDEC, OOKPEAK_THRESHDEC_EVERY_8TH);
+       case dec_every4th:
+               return rf69_read_mod_write(spi, REG_OOKPEAK, MASK_OOKPEAK_THRESDEC, OOKPEAK_THRESHDEC_EVERY_4TH);
+       case dec_every2nd:
+               return rf69_read_mod_write(spi, REG_OOKPEAK, MASK_OOKPEAK_THRESDEC, OOKPEAK_THRESHDEC_EVERY_2ND);
+       case dec_once:
+               return rf69_read_mod_write(spi, REG_OOKPEAK, MASK_OOKPEAK_THRESDEC, OOKPEAK_THRESHDEC_ONCE);
+       case dec_twice:
+               return rf69_read_mod_write(spi, REG_OOKPEAK, MASK_OOKPEAK_THRESDEC, OOKPEAK_THRESHDEC_TWICE);
+       case dec_4times:
+               return rf69_read_mod_write(spi, REG_OOKPEAK, MASK_OOKPEAK_THRESDEC, OOKPEAK_THRESHDEC_4_TIMES);
+       case dec_8times:
+               return rf69_read_mod_write(spi, REG_OOKPEAK, MASK_OOKPEAK_THRESDEC, OOKPEAK_THRESHDEC_8_TIMES);
+       case dec_16times:
+               return rf69_read_mod_write(spi, REG_OOKPEAK, MASK_OOKPEAK_THRESDEC, OOKPEAK_THRESHDEC_16_TIMES);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
@@ -583,10 +508,6 @@ int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value)
        u8 regaddr;
        u8 regValue;
 
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: DIO mapping");
-       #endif
-
        switch (DIONumber) {
        case 0:
                mask = MASK_DIO0; shift = SHIFT_DIO0; regaddr = REG_DIOMAPPING1;
@@ -607,95 +528,66 @@ int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value)
                mask = MASK_DIO5; shift = SHIFT_DIO5; regaddr = REG_DIOMAPPING2;
                break;
        default:
-               dev_dbg(&spi->dev, "set: illegal input param");
+       dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
        }
 
        // read reg
-       regValue = READ_REG(regaddr);
+       regValue = rf69_read_reg(spi, regaddr);
        // delete old value
        regValue = regValue & ~mask;
        // add new value
        regValue = regValue | value << shift;
        // write back
-       return WRITE_REG(regaddr, regValue);
+       return rf69_write_reg(spi, regaddr, regValue);
 }
 
 bool rf69_get_flag(struct spi_device *spi, enum flag flag)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "get: flag");
-       #endif
-
-       switch (flag) {
-       case modeSwitchCompleted:     return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_MODE_READY);
-       case readyToReceive:          return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_RX_READY);
-       case readyToSend:             return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_TX_READY);
-       case pllLocked:               return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_PLL_LOCK);
-       case rssiExceededThreshold:   return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_RSSI);
-       case timeout:                 return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_TIMEOUT);
-       case automode:                return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_AUTOMODE);
-       case syncAddressMatch:        return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_SYNC_ADDRESS_MATCH);
-       case fifoFull:                return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_FULL);
-/*     case fifoNotEmpty:            return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_NOT_EMPTY); */
-       case fifoEmpty:               return !(READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_NOT_EMPTY);
-       case fifoLevelBelowThreshold: return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_LEVEL);
-       case fifoOverrun:             return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_OVERRUN);
-       case packetSent:              return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_PACKET_SENT);
-       case payloadReady:            return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_PAYLOAD_READY);
-       case crcOk:                   return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_CRC_OK);
-       case batteryLow:              return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_LOW_BAT);
-       default:                      return false;
-       }
-}
-
-int rf69_reset_flag(struct spi_device *spi, enum flag flag)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "reset: flag");
-       #endif
-
        switch (flag) {
-       case rssiExceededThreshold: return WRITE_REG(REG_IRQFLAGS1, MASK_IRQFLAGS1_RSSI);
-       case syncAddressMatch:      return WRITE_REG(REG_IRQFLAGS1, MASK_IRQFLAGS1_SYNC_ADDRESS_MATCH);
-       case fifoOverrun:           return WRITE_REG(REG_IRQFLAGS2, MASK_IRQFLAGS2_FIFO_OVERRUN);
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
+       case modeSwitchCompleted:
+               return (rf69_read_reg(spi, REG_IRQFLAGS1) & MASK_IRQFLAGS1_MODE_READY);
+       case readyToReceive:
+               return (rf69_read_reg(spi, REG_IRQFLAGS1) & MASK_IRQFLAGS1_RX_READY);
+       case readyToSend:
+               return (rf69_read_reg(spi, REG_IRQFLAGS1) & MASK_IRQFLAGS1_TX_READY);
+       case pllLocked:
+               return (rf69_read_reg(spi, REG_IRQFLAGS1) & MASK_IRQFLAGS1_PLL_LOCK);
+       case rssiExceededThreshold:
+               return (rf69_read_reg(spi, REG_IRQFLAGS1) & MASK_IRQFLAGS1_RSSI);
+       case timeout:
+               return (rf69_read_reg(spi, REG_IRQFLAGS1) & MASK_IRQFLAGS1_TIMEOUT);
+       case automode:
+               return (rf69_read_reg(spi, REG_IRQFLAGS1) & MASK_IRQFLAGS1_AUTOMODE);
+       case syncAddressMatch:
+               return (rf69_read_reg(spi, REG_IRQFLAGS1) & MASK_IRQFLAGS1_SYNC_ADDRESS_MATCH);
+       case fifo_full:
+               return (rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_FULL);
+/*     case fifo_not_empty:
+ *             return (rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_NOT_EMPTY); */
+       case fifo_empty:
+               return !(rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_NOT_EMPTY);
+       case fifo_level_below_threshold:
+               return (rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_LEVEL);
+       case fifo_overrun:
+               return (rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_OVERRUN);
+       case packetSent:
+               return (rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_PACKET_SENT);
+       case payload_ready:
+               return (rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_PAYLOAD_READY);
+       case crcOk:
+               return (rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_CRC_OK);
+       case batteryLow:
+               return (rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_LOW_BAT);
+       default:                         return false;
        }
 }
 
 int rf69_set_rssi_threshold(struct spi_device *spi, u8 threshold)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: rssi threshold");
-       #endif
-
        /* no value check needed - u8 exactly matches register size */
 
-       return WRITE_REG(REG_RSSITHRESH, threshold);
-}
-
-int rf69_set_rx_start_timeout(struct spi_device *spi, u8 timeout)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: start timeout");
-       #endif
-
-       /* no value check needed - u8 exactly matches register size */
-
-       return WRITE_REG(REG_RXTIMEOUT1, timeout);
-}
-
-int rf69_set_rssi_timeout(struct spi_device *spi, u8 timeout)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: rssi timeout");
-       #endif
-
-       /* no value check needed - u8 exactly matches register size */
-
-       return WRITE_REG(REG_RXTIMEOUT2, timeout);
+       return rf69_write_reg(spi, REG_RSSITHRESH, threshold);
 }
 
 int rf69_set_preamble_length(struct spi_device *spi, u16 preambleLength)
@@ -703,47 +595,38 @@ int rf69_set_preamble_length(struct spi_device *spi, u16 preambleLength)
        int retval;
        u8 msb, lsb;
 
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: preamble length");
-       #endif
-
        /* no value check needed - u16 exactly matches register size */
 
        /* calculate reg settings */
-       msb = (preambleLength&0xff00)   >>  8;
-       lsb = (preambleLength&0xff);
+       msb = (preambleLength & 0xff00) >> 8;
+       lsb = (preambleLength & 0xff);
 
        /* transmit to chip */
-       retval = WRITE_REG(REG_PREAMBLE_MSB, msb);
+       retval = rf69_write_reg(spi, REG_PREAMBLE_MSB, msb);
        if (retval)
                return retval;
-       return WRITE_REG(REG_PREAMBLE_LSB, lsb);
+       retval = rf69_write_reg(spi, REG_PREAMBLE_LSB, lsb);
+
+       return retval;
 }
 
-int rf69_set_sync_enable(struct spi_device *spi, enum optionOnOff optionOnOff)
+int rf69_enable_sync(struct spi_device *spi)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: sync enable");
-       #endif
-
-       switch (optionOnOff) {
-       case optionOn:  return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) |  MASK_SYNC_CONFIG_SYNC_ON));
-       case optionOff: return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_SYNC_ON));
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
+       return rf69_set_bit(spi, REG_SYNC_CONFIG, MASK_SYNC_CONFIG_SYNC_ON);
 }
 
-int rf69_set_fifo_fill_condition(struct spi_device *spi, enum fifoFillCondition fifoFillCondition)
+int rf69_disable_sync(struct spi_device *spi)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: fifo fill condition");
-       #endif
+       return rf69_clear_bit(spi, REG_SYNC_CONFIG, MASK_SYNC_CONFIG_SYNC_ON);
+}
 
-       switch (fifoFillCondition) {
-       case always:             return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) |  MASK_SYNC_CONFIG_FIFO_FILL_CONDITION));
-       case afterSyncInterrupt: return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_FIFO_FILL_CONDITION));
+int rf69_set_fifo_fill_condition(struct spi_device *spi, enum fifo_fill_condition fifo_fill_condition)
+{
+       switch (fifo_fill_condition) {
+       case always:
+               return rf69_set_bit(spi, REG_SYNC_CONFIG, MASK_SYNC_CONFIG_FIFO_FILL_CONDITION);
+       case afterSyncInterrupt:
+               return rf69_clear_bit(spi, REG_SYNC_CONFIG, MASK_SYNC_CONFIG_FIFO_FILL_CONDITION);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
@@ -752,10 +635,6 @@ int rf69_set_fifo_fill_condition(struct spi_device *spi, enum fifoFillCondition
 
 int rf69_set_sync_size(struct spi_device *spi, u8 syncSize)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: sync size");
-       #endif
-
        // check input value
        if (syncSize > 0x07) {
                dev_dbg(&spi->dev, "set: illegal input param");
@@ -763,136 +642,85 @@ int rf69_set_sync_size(struct spi_device *spi, u8 syncSize)
        }
 
        // write value
-       return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_SYNC_SIZE) | (syncSize << 3));
-}
-
-int rf69_set_sync_tolerance(struct spi_device *spi, u8 syncTolerance)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: sync tolerance");
-       #endif
-
-       // check input value
-       if (syncTolerance > 0x07) {
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
-
-       // write value
-       return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_SYNC_SIZE) | syncTolerance);
+       return rf69_read_mod_write(spi, REG_SYNC_CONFIG, MASK_SYNC_CONFIG_SYNC_SIZE, (syncSize << 3));
 }
 
 int rf69_set_sync_values(struct spi_device *spi, u8 syncValues[8])
 {
        int retval = 0;
 
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: sync values");
-       #endif
-
-       retval += WRITE_REG(REG_SYNCVALUE1, syncValues[0]);
-       retval += WRITE_REG(REG_SYNCVALUE2, syncValues[1]);
-       retval += WRITE_REG(REG_SYNCVALUE3, syncValues[2]);
-       retval += WRITE_REG(REG_SYNCVALUE4, syncValues[3]);
-       retval += WRITE_REG(REG_SYNCVALUE5, syncValues[4]);
-       retval += WRITE_REG(REG_SYNCVALUE6, syncValues[5]);
-       retval += WRITE_REG(REG_SYNCVALUE7, syncValues[6]);
-       retval += WRITE_REG(REG_SYNCVALUE8, syncValues[7]);
+       retval += rf69_write_reg(spi, REG_SYNCVALUE1, syncValues[0]);
+       retval += rf69_write_reg(spi, REG_SYNCVALUE2, syncValues[1]);
+       retval += rf69_write_reg(spi, REG_SYNCVALUE3, syncValues[2]);
+       retval += rf69_write_reg(spi, REG_SYNCVALUE4, syncValues[3]);
+       retval += rf69_write_reg(spi, REG_SYNCVALUE5, syncValues[4]);
+       retval += rf69_write_reg(spi, REG_SYNCVALUE6, syncValues[5]);
+       retval += rf69_write_reg(spi, REG_SYNCVALUE7, syncValues[6]);
+       retval += rf69_write_reg(spi, REG_SYNCVALUE8, syncValues[7]);
 
        return retval;
 }
 
 int rf69_set_packet_format(struct spi_device *spi, enum packetFormat packetFormat)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: packet format");
-       #endif
-
        switch (packetFormat) {
-       case packetLengthVar: return WRITE_REG(REG_PACKETCONFIG1, (READ_REG(REG_PACKETCONFIG1) |  MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE));
-       case packetLengthFix: return WRITE_REG(REG_PACKETCONFIG1, (READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE));
+       case packetLengthVar:
+               return rf69_set_bit(spi, REG_PACKETCONFIG1, MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE);
+       case packetLengthFix:
+               return rf69_clear_bit(spi, REG_PACKETCONFIG1, MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
        }
 }
 
-int rf69_set_crc_enable(struct spi_device *spi, enum optionOnOff optionOnOff)
+int rf69_enable_crc(struct spi_device *spi)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: crc enable");
-       #endif
+       return rf69_set_bit(spi, REG_PACKETCONFIG1, MASK_PACKETCONFIG1_CRC_ON);
+}
 
-       switch (optionOnOff) {
-       case optionOn:  return WRITE_REG(REG_PACKETCONFIG1, (READ_REG(REG_PACKETCONFIG1) |  MASK_PACKETCONFIG1_CRC_ON));
-       case optionOff: return WRITE_REG(REG_PACKETCONFIG1, (READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_CRC_ON));
-       default:
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
+int rf69_disable_crc(struct spi_device *spi)
+{
+       return rf69_clear_bit(spi, REG_PACKETCONFIG1, MASK_PACKETCONFIG1_CRC_ON);
 }
 
 int rf69_set_adressFiltering(struct spi_device *spi, enum addressFiltering addressFiltering)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: address filtering");
-       #endif
-
        switch (addressFiltering) {
-       case filteringOff:           return WRITE_REG(REG_PACKETCONFIG1, ((READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_ADDRESSFILTERING) | PACKETCONFIG1_ADDRESSFILTERING_OFF));
-       case nodeAddress:            return WRITE_REG(REG_PACKETCONFIG1, ((READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_ADDRESSFILTERING) | PACKETCONFIG1_ADDRESSFILTERING_NODE));
-       case nodeOrBroadcastAddress: return WRITE_REG(REG_PACKETCONFIG1, ((READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_ADDRESSFILTERING) | PACKETCONFIG1_ADDRESSFILTERING_NODEBROADCAST));
+       case filteringOff:
+               return rf69_read_mod_write(spi, REG_PACKETCONFIG1, MASK_PACKETCONFIG1_ADDRESSFILTERING, PACKETCONFIG1_ADDRESSFILTERING_OFF);
+       case nodeAddress:
+               return rf69_read_mod_write(spi, REG_PACKETCONFIG1, MASK_PACKETCONFIG1_ADDRESSFILTERING, PACKETCONFIG1_ADDRESSFILTERING_NODE);
+       case nodeOrBroadcastAddress:
+               return rf69_read_mod_write(spi, REG_PACKETCONFIG1, MASK_PACKETCONFIG1_ADDRESSFILTERING, PACKETCONFIG1_ADDRESSFILTERING_NODEBROADCAST);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
        }
 }
 
-int rf69_set_payload_length(struct spi_device *spi, u8 payloadLength)
+int rf69_set_payload_length(struct spi_device *spi, u8 payload_length)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: payload length");
-       #endif
-
-       return WRITE_REG(REG_PAYLOAD_LENGTH, payloadLength);
-}
-
-u8  rf69_get_payload_length(struct spi_device *spi)
-{
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "get: payload length");
-       #endif
-
-       return (u8) READ_REG(REG_PAYLOAD_LENGTH);
+       return rf69_write_reg(spi, REG_PAYLOAD_LENGTH, payload_length);
 }
 
 int rf69_set_node_address(struct spi_device *spi, u8 nodeAddress)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: node address");
-       #endif
-
-       return WRITE_REG(REG_NODEADRS, nodeAddress);
+       return rf69_write_reg(spi, REG_NODEADRS, nodeAddress);
 }
 
 int rf69_set_broadcast_address(struct spi_device *spi, u8 broadcastAddress)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: broadcast address");
-       #endif
-
-       return WRITE_REG(REG_BROADCASTADRS, broadcastAddress);
+       return rf69_write_reg(spi, REG_BROADCASTADRS, broadcastAddress);
 }
 
 int rf69_set_tx_start_condition(struct spi_device *spi, enum txStartCondition txStartCondition)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: start condition");
-       #endif
-
        switch (txStartCondition) {
-       case fifoLevel:    return WRITE_REG(REG_FIFO_THRESH, (READ_REG(REG_FIFO_THRESH) & ~MASK_FIFO_THRESH_TXSTART));
-       case fifoNotEmpty: return WRITE_REG(REG_FIFO_THRESH, (READ_REG(REG_FIFO_THRESH) |  MASK_FIFO_THRESH_TXSTART));
+       case fifo_level:
+               return rf69_clear_bit(spi, REG_FIFO_THRESH, MASK_FIFO_THRESH_TXSTART);
+       case fifo_not_empty:
+               return rf69_set_bit(spi, REG_FIFO_THRESH, MASK_FIFO_THRESH_TXSTART);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
@@ -903,35 +731,32 @@ int rf69_set_fifo_threshold(struct spi_device *spi, u8 threshold)
 {
        int retval;
 
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: fifo threshold");
-       #endif
-
-       // check input value
+       /* check input value */
        if (threshold & 0x80) {
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
        }
 
-       // write value
-       retval = WRITE_REG(REG_FIFO_THRESH, (READ_REG(REG_FIFO_THRESH) & ~MASK_FIFO_THRESH_VALUE) | threshold);
+       /* write value */
+       retval = rf69_read_mod_write(spi, REG_FIFO_THRESH, MASK_FIFO_THRESH_VALUE, threshold);
        if (retval)
                return retval;
 
-       // access the fifo to activate new threshold
-       return rf69_read_fifo(spi, (u8 *)&retval, 1); // retval used as buffer
+       /* access the fifo to activate new threshold
+        * retval (mis-) used as buffer here
+        */
+       return rf69_read_fifo(spi, (u8 *)&retval, 1);
 }
 
 int rf69_set_dagc(struct spi_device *spi, enum dagc dagc)
 {
-       #ifdef DEBUG
-               dev_dbg(&spi->dev, "set: dagc");
-       #endif
-
        switch (dagc) {
-       case normalMode:                 return WRITE_REG(REG_TESTDAGC, DAGC_NORMAL);
-       case improve:                    return WRITE_REG(REG_TESTDAGC, DAGC_IMPROVED_LOWBETA0);
-       case improve4LowModulationIndex: return WRITE_REG(REG_TESTDAGC, DAGC_IMPROVED_LOWBETA1);
+       case normalMode:
+               return rf69_write_reg(spi, REG_TESTDAGC, DAGC_NORMAL);
+       case improve:
+               return rf69_write_reg(spi, REG_TESTDAGC, DAGC_IMPROVED_LOWBETA0);
+       case improve4LowModulationIndex:
+               return rf69_write_reg(spi, REG_TESTDAGC, DAGC_IMPROVED_LOWBETA1);
        default:
                dev_dbg(&spi->dev, "set: illegal input param");
                return -EINVAL;
@@ -940,19 +765,17 @@ int rf69_set_dagc(struct spi_device *spi, enum dagc dagc)
 
 /*-------------------------------------------------------------------------*/
 
-int rf69_read_fifo (struct spi_device *spi, u8 *buffer, unsigned int size)
+int rf69_read_fifo(struct spi_device *spi, u8 *buffer, unsigned int size)
 {
-       #ifdef DEBUG_FIFO_ACCESS
-               int i;
-       #endif
+#ifdef DEBUG_FIFO_ACCESS
+       int i;
+#endif
        struct spi_transfer transfer;
        u8 local_buffer[FIFO_SIZE + 1];
        int retval;
 
        if (size > FIFO_SIZE) {
-               #ifdef DEBUG
-                       dev_dbg(&spi->dev, "read fifo: passed in buffer bigger then internal buffer \n");
-               #endif
+               dev_dbg(&spi->dev, "read fifo: passed in buffer bigger then internal buffer\n");
                return -EMSGSIZE;
        }
 
@@ -961,97 +784,41 @@ int rf69_read_fifo (struct spi_device *spi, u8 *buffer, unsigned int size)
        memset(&transfer, 0, sizeof(transfer));
        transfer.tx_buf = local_buffer;
        transfer.rx_buf = local_buffer;
-       transfer.len    = size+1;
+       transfer.len    = size + 1;
 
        retval = spi_sync_transfer(spi, &transfer, 1);
 
-       #ifdef DEBUG_FIFO_ACCESS
-               for (i = 0; i < size; i++)
-                       dev_dbg(&spi->dev, "%d - 0x%x\n", i, local_buffer[i+1]);
-       #endif
+#ifdef DEBUG_FIFO_ACCESS
+       for (i = 0; i < size; i++)
+               dev_dbg(&spi->dev, "%d - 0x%x\n", i, local_buffer[i + 1]);
+#endif
 
-       memcpy(buffer, &local_buffer[1], size);  // TODO: ohne memcopy wäre schöner
+       memcpy(buffer, &local_buffer[1], size);
 
        return retval;
 }
 
 int rf69_write_fifo(struct spi_device *spi, u8 *buffer, unsigned int size)
 {
-       #ifdef DEBUG_FIFO_ACCESS
-               int i;
-       #endif
+#ifdef DEBUG_FIFO_ACCESS
+       int i;
+#endif
        char spi_address = REG_FIFO | WRITE_BIT;
        u8 local_buffer[FIFO_SIZE + 1];
 
        if (size > FIFO_SIZE) {
-               #ifdef DEBUG
-                       dev_dbg(&spi->dev, "read fifo: passed in buffer bigger then internal buffer \n");
-               #endif
+               dev_dbg(&spi->dev, "read fifo: passed in buffer bigger then internal buffer\n");
                return -EMSGSIZE;
        }
 
        local_buffer[0] = spi_address;
-       memcpy(&local_buffer[1], buffer, size);  // TODO: ohne memcopy wäre schöner
+       memcpy(&local_buffer[1], buffer, size);
 
-       #ifdef DEBUG_FIFO_ACCESS
-               for (i = 0; i < size; i++)
-                       dev_dbg(&spi->dev, "0x%x\n", buffer[i]);
-       #endif
+#ifdef DEBUG_FIFO_ACCESS
+       for (i = 0; i < size; i++)
+               dev_dbg(&spi->dev, "0x%x\n", buffer[i]);
+#endif
 
-       return spi_write (spi, local_buffer, size + 1);
+       return spi_write(spi, local_buffer, size + 1);
 }
 
-/*-------------------------------------------------------------------------*/
-
-u8 rf69_read_reg(struct spi_device *spi, u8 addr)
-{
-       int retval;
-
-       retval = spi_w8r8(spi, addr);
-
-       #ifdef DEBUG_VALUES
-               if (retval < 0)
-                       /* should never happen, since we already checked,
-                        * that module is connected. Therefore no error
-                        * handling, just an optional error message...
-                        */
-                       dev_dbg(&spi->dev, "read 0x%x FAILED\n",
-                               addr);
-               else
-                       dev_dbg(&spi->dev, "read 0x%x from reg 0x%x\n",
-                               retval,
-                               addr);
-       #endif
-
-       return retval;
-}
-
-int rf69_write_reg(struct spi_device *spi, u8 addr, u8 value)
-{
-       int retval;
-       char buffer[2];
-
-       buffer[0] = addr | WRITE_BIT;
-       buffer[1] = value;
-
-       retval = spi_write(spi, &buffer, 2);
-
-       #ifdef DEBUG_VALUES
-               if (retval < 0)
-                       /* should never happen, since we already checked,
-                        * that module is connected. Therefore no error
-                        * handling, just an optional error message...
-                        */
-                       dev_dbg(&spi->dev, "write 0x%x to 0x%x FAILED\n",
-                               value,
-                               addr);
-               else
-                       dev_dbg(&spi->dev, "wrote 0x%x to reg 0x%x\n",
-                               value,
-                               addr);
-       #endif
-
-       return retval;
-}
-
-
index 5c0c95628f2fd58854e9742b274da6172cb50b44..09d221b8b6df4fc00305e6567c6a70406da9beae 100644 (file)
 #define FIFO_THRESHOLD 15              /* in byte */
 
 int rf69_set_mode(struct spi_device *spi, enum mode mode);
-int rf69_set_data_mode(struct spi_device *spi, enum dataMode dataMode);
+int rf69_set_data_mode(struct spi_device *spi, u8 data_mode);
 int rf69_set_modulation(struct spi_device *spi, enum modulation modulation);
-enum modulation rf69_get_modulation(struct spi_device *spi);
-int rf69_set_modulation_shaping(struct spi_device *spi, enum modShaping modShaping);
+int rf69_set_modulation_shaping(struct spi_device *spi, enum mod_shaping mod_shaping);
 int rf69_set_bit_rate(struct spi_device *spi, u16 bitRate);
 int rf69_set_deviation(struct spi_device *spi, u32 deviation);
 int rf69_set_frequency(struct spi_device *spi, u32 frequency);
-int rf69_set_amplifier_0(struct spi_device *spi, enum optionOnOff optionOnOff);
-int rf69_set_amplifier_1(struct spi_device *spi, enum optionOnOff optionOnOff);
-int rf69_set_amplifier_2(struct spi_device *spi, enum optionOnOff optionOnOff);
+int rf69_enable_amplifier(struct spi_device *spi, u8 amplifier_mask);
+int rf69_disable_amplifier(struct spi_device *spi, u8 amplifier_mask);
 int rf69_set_output_power_level(struct spi_device *spi, u8 powerLevel);
 int rf69_set_pa_ramp(struct spi_device *spi, enum paRamp paRamp);
 int rf69_set_antenna_impedance(struct spi_device *spi, enum antennaImpedance antennaImpedance);
 int rf69_set_lna_gain(struct spi_device *spi, enum lnaGain lnaGain);
-enum lnaGain rf69_get_lna_gain(struct spi_device *spi);
-int rf69_set_dc_cut_off_frequency_intern(struct spi_device *spi, u8 reg, enum dccPercent dccPercent);
-int rf69_set_dc_cut_off_frequency(struct spi_device *spi, enum dccPercent dccPercent);
-int rf69_set_dc_cut_off_frequency_during_afc(struct spi_device *spi, enum dccPercent dccPercent);
 int rf69_set_bandwidth(struct spi_device *spi, enum mantisse mantisse, u8 exponent);
 int rf69_set_bandwidth_during_afc(struct spi_device *spi, enum mantisse mantisse, u8 exponent);
-int rf69_set_ook_threshold_type(struct spi_device *spi, enum thresholdType thresholdType);
-int rf69_set_ook_threshold_step(struct spi_device *spi, enum thresholdStep thresholdStep);
 int rf69_set_ook_threshold_dec(struct spi_device *spi, enum thresholdDecrement thresholdDecrement);
 int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value);
 bool rf69_get_flag(struct spi_device *spi, enum flag flag);
-int rf69_reset_flag(struct spi_device *spi, enum flag flag);
 int rf69_set_rssi_threshold(struct spi_device *spi, u8 threshold);
-int rf69_set_rx_start_timeout(struct spi_device *spi, u8 timeout);
-int rf69_set_rssi_timeout(struct spi_device *spi, u8 timeout);
 int rf69_set_preamble_length(struct spi_device *spi, u16 preambleLength);
-int rf69_set_sync_enable(struct spi_device *spi, enum optionOnOff optionOnOff);
-int rf69_set_fifo_fill_condition(struct spi_device *spi, enum fifoFillCondition fifoFillCondition);
+int rf69_enable_sync(struct spi_device *spi);
+int rf69_disable_sync(struct spi_device *spi);
+int rf69_set_fifo_fill_condition(struct spi_device *spi, enum fifo_fill_condition fifo_fill_condition);
 int rf69_set_sync_size(struct spi_device *spi, u8 sync_size);
-int rf69_set_sync_tolerance(struct spi_device *spi, u8 syncTolerance);
 int rf69_set_sync_values(struct spi_device *spi, u8 syncValues[8]);
 int rf69_set_packet_format(struct spi_device *spi, enum packetFormat packetFormat);
-int rf69_set_crc_enable(struct spi_device *spi, enum optionOnOff optionOnOff);
+int rf69_enable_crc(struct spi_device *spi);
+int rf69_disable_crc(struct spi_device *spi);
 int rf69_set_adressFiltering(struct spi_device *spi, enum addressFiltering addressFiltering);
-int rf69_set_payload_length(struct spi_device *spi, u8 payloadLength);
-u8  rf69_get_payload_length(struct spi_device *spi);
+int rf69_set_payload_length(struct spi_device *spi, u8 payload_length);
 int rf69_set_node_address(struct spi_device *spi, u8 nodeAddress);
 int rf69_set_broadcast_address(struct spi_device *spi, u8 broadcastAddress);
 int rf69_set_tx_start_condition(struct spi_device *spi, enum txStartCondition txStartCondition);
 int rf69_set_fifo_threshold(struct spi_device *spi, u8 threshold);
 int rf69_set_dagc(struct spi_device *spi, enum dagc dagc);
 
-int rf69_read_fifo (struct spi_device *spi, u8 *buffer, unsigned int size);
+int rf69_read_fifo(struct spi_device *spi, u8 *buffer, unsigned int size);
 int rf69_write_fifo(struct spi_device *spi, u8 *buffer, unsigned int size);
 
-u8  rf69_read_reg (struct spi_device *spi, u8 addr);
-int rf69_write_reg(struct spi_device *spi, u8 addr, u8 value);
-
-
 #endif
index fbfb59bd3f3dcc14bc2861f713e766d93122b937..03440cfa957ceb24af637785255d852ce9f9121f 100644 (file)
 #ifndef RF69_ENUM_H
 #define RF69_ENUM_H
 
-enum optionOnOff
-{
-    optionOff,
-    optionOn
+enum mode {
+       mode_sleep,
+       standby,
+       synthesizer,
+       transmit,
+       receive
+};
+
+enum modulation {
+       OOK,
+       FSK,
+       UNDEF
+};
+
+enum mod_shaping {
+       SHAPING_OFF,
+       SHAPING_1_0,
+       SHAPING_0_5,
+       SHAPING_0_3,
+       SHAPING_BR,
+       SHAPING_2BR
+};
+
+enum paRamp {
+       ramp3400,
+       ramp2000,
+       ramp1000,
+       ramp500,
+       ramp250,
+       ramp125,
+       ramp100,
+       ramp62,
+       ramp50,
+       ramp40,
+       ramp31,
+       ramp25,
+       ramp20,
+       ramp15,
+       ramp12,
+       ramp10
+};
+
+enum antennaImpedance {
+       fiftyOhm,
+       twohundretOhm
+};
+
+enum lnaGain {
+       automatic,
+       max,
+       max_minus_6,
+       max_minus_12,
+       max_minus_24,
+       max_minus_36,
+       max_minus_48,
+       undefined
+};
+
+enum mantisse {
+       mantisse16,
+       mantisse20,
+       mantisse24
+};
+
+enum thresholdDecrement {
+       dec_every8th,
+       dec_every4th,
+       dec_every2nd,
+       dec_once,
+       dec_twice,
+       dec_4times,
+       dec_8times,
+       dec_16times
+};
+
+enum flag {
+       modeSwitchCompleted,
+       readyToReceive,
+       readyToSend,
+       pllLocked,
+       rssiExceededThreshold,
+       timeout,
+       automode,
+       syncAddressMatch,
+       fifo_full,
+//     fifo_not_empty, collision with next enum; replaced by following enum...
+       fifo_empty,
+       fifo_level_below_threshold,
+       fifo_overrun,
+       packetSent,
+       payload_ready,
+       crcOk,
+       batteryLow
+};
+
+enum fifo_fill_condition {
+       afterSyncInterrupt,
+       always
+};
+
+enum packetFormat {
+       packetLengthFix,
+       packetLengthVar
+};
+
+enum txStartCondition {
+       fifo_level,
+       fifo_not_empty
+};
+
+enum addressFiltering {
+       filteringOff,
+       nodeAddress,
+       nodeOrBroadcastAddress
+};
+
+enum dagc {
+       normalMode,
+       improve,
+       improve4LowModulationIndex
 };
 
-enum mode
-{
-    mode_sleep,
-    standby,
-    synthesizer,
-    transmit,
-    receive
-};
-
-enum dataMode
-{
-    packet,
-    continuous,
-    continuousNoSync
-};
-
-enum modulation
-{
-    OOK,
-    FSK
-};
-
-enum modShaping
-{
-    shapingOff,
-    shaping1_0,
-    shaping0_5,
-    shaping0_3,
-    shapingBR,
-    shaping2BR
-};
-
-enum paRamp
-{
-    ramp3400,
-    ramp2000,
-    ramp1000,
-    ramp500,
-    ramp250,
-    ramp125,
-    ramp100,
-    ramp62,
-    ramp50,
-    ramp40,
-    ramp31,
-    ramp25,
-    ramp20,
-    ramp15,
-    ramp12,
-    ramp10
-};
-
-enum antennaImpedance
-{
-    fiftyOhm,
-    twohundretOhm
-};
-
-enum lnaGain
-{
-    automatic,
-    max,
-    maxMinus6,
-    maxMinus12,
-    maxMinus24,
-    maxMinus36,
-    maxMinus48,
-    undefined
-};
-
-enum dccPercent
-{
-    dcc16Percent,
-    dcc8Percent,
-    dcc4Percent,
-    dcc2Percent,
-    dcc1Percent,
-    dcc0_5Percent,
-    dcc0_25Percent,
-    dcc0_125Percent
-};
-
-enum mantisse
-{
-    mantisse16,
-    mantisse20,
-    mantisse24
-};
-
-enum thresholdType
-{
-    fixed,
-    peak,
-    average
-};
-
-enum thresholdStep
-{
-    step_0_5db,
-    step_1_0db,
-    step_1_5db,
-    step_2_0db,
-    step_3_0db,
-    step_4_0db,
-    step_5_0db,
-    step_6_0db
-};
-
-enum thresholdDecrement
-{
-    dec_every8th,
-    dec_every4th,
-    dec_every2nd,
-    dec_once,
-    dec_twice,
-    dec_4times,
-    dec_8times,
-    dec_16times
-};
-
-enum flag
-{
-    modeSwitchCompleted,
-    readyToReceive,
-    readyToSend,
-    pllLocked,
-    rssiExceededThreshold,
-    timeout,
-    automode,
-    syncAddressMatch,
-    fifoFull,
-//    fifoNotEmpty, collision with next enum; replaced by following enum...
-    fifoEmpty,
-    fifoLevelBelowThreshold,
-    fifoOverrun,
-    packetSent,
-    payloadReady,
-    crcOk,
-    batteryLow
-};
-
-enum fifoFillCondition
-{
-    afterSyncInterrupt,
-    always
-};
-
-enum packetFormat
-{
-    packetLengthFix,
-    packetLengthVar
-};
-
-enum txStartCondition
-{
-    fifoLevel,
-    fifoNotEmpty
-};
-
-enum addressFiltering
-{
-    filteringOff,
-    nodeAddress,
-    nodeOrBroadcastAddress
-};
-
-enum dagc
-{
-    normalMode,
-    improve,
-    improve4LowModulationIndex
-};
-
-
 #endif
index 6335d42142fe960a848f8348bb1b81f7304fed1c..33fd91518bb025bbdec0ce1953398343d49b81c0 100644 (file)
 #define  MASK_PALEVEL_PA2                      0x20
 #define  MASK_PALEVEL_OUTPUT_POWER             0x1F
 
-
-
 // RegPaRamp
 #define  PARAMP_3400                           0x00
 #define  PARAMP_2000                           0x01
 #define  LNA_GAIN_MAX_MINUS_36                 0x05
 #define  LNA_GAIN_MAX_MINUS_48                 0x06
 
-
 /* RegRxBw (0x19) and RegAfcBw (0x1A) */
 #define  MASK_BW_DCC_FREQ                      0xE0
 #define  MASK_BW_MANTISSE                      0x18
 #define  BW_MANT_20                            0x08
 #define  BW_MANT_24                            0x10 /* default */
 
-
 /* RegOokPeak (0x1B) */
 #define  MASK_OOKPEAK_THRESTYPE                        0xc0
 #define  MASK_OOKPEAK_THRESSTEP                        0x38
 #define  DIO5                                  5
 
 /* DIO Mapping values (packet mode) */
-#define  DIO_ModeReady_DIO4                    0x00
-#define  DIO_ModeReady_DIO5                    0x03
-#define  DIO_ClkOut                            0x00
-#define  DIO_Data                              0x01
-#define  DIO_TimeOut_DIO1                      0x03
-#define  DIO_TimeOut_DIO4                      0x00
-#define  DIO_Rssi_DIO0                         0x03
-#define  DIO_Rssi_DIO3_4                       0x01
-#define  DIO_RxReady                           0x02
-#define  DIO_PLLLock                           0x03
-#define  DIO_TxReady                           0x01
-#define  DIO_FifoFull_DIO1                     0x01
-#define  DIO_FifoFull_DIO3                     0x00
-#define  DIO_SyncAddress                       0x02
-#define  DIO_FifoNotEmpty_DIO1                 0x02
-#define  DIO_FifoNotEmpty_FIO2                 0x00
-#define  DIO_Automode                          0x04
-#define  DIO_FifoLevel                         0x00
-#define  DIO_CrcOk                             0x00
-#define  DIO_PayloadReady                      0x01
-#define  DIO_PacketSent                                0x00
-#define  DIO_Dclk                              0x00
+#define  DIO_MODE_READY_DIO4                   0x00
+#define  DIO_MODE_READY_DIO5                   0x03
+#define  DIO_CLK_OUT                           0x00
+#define  DIO_DATA                              0x01
+#define  DIO_TIMEOUT_DIO1                      0x03
+#define  DIO_TIMEOUT_DIO4                      0x00
+#define  DIO_RSSI_DIO0                         0x03
+#define  DIO_RSSI_DIO3_4                       0x01
+#define  DIO_RX_READY                          0x02
+#define  DIO_PLL_LOCK                          0x03
+#define  DIO_TX_READY                          0x01
+#define  DIO_FIFO_FULL_DIO1                    0x01
+#define  DIO_FIFO_FULL_DIO3                    0x00
+#define  DIO_SYNC_ADDRESS                      0x02
+#define  DIO_FIFO_NOT_EMPTY_DIO1               0x02
+#define  DIO_FIFO_NOT_EMPTY_FIO2               0x00
+#define  DIO_AUTOMODE                          0x04
+#define  DIO_FIFO_LEVEL                                0x00
+#define  DIO_CRC_OK                            0x00
+#define  DIO_PAYLOAD_READY                     0x01
+#define  DIO_PACKET_SENT                       0x00
+#define  DIO_DCLK                              0x00
 
 /* RegDioMapping2 CLK_OUT part */
 #define  MASK_DIOMAPPING2_CLK_OUT              0x07
index d73e9bdc80cc28c80382181016ef1ca375f0279f..bcb6919bb7d502a8e3fdda52b647254993be7b67 100644 (file)
@@ -5395,14 +5395,14 @@ u8 set_tx_beacon_cmd(struct adapter *padapter)
        int len_diff = 0;
 
 
-       ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+       ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
        if (!ph2c) {
                res = _FAIL;
                goto exit;
        }
 
        ptxBeacon_parm = kmemdup(&(pmlmeinfo->network),
-                               sizeof(struct wlan_bssid_ex), GFP_KERNEL);
+                               sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
        if (ptxBeacon_parm == NULL) {
                kfree(ph2c);
                res = _FAIL;
index 2867864bbfbe9286c65aa485aa48fe3e1566599d..e6867eea3530d98ce4ff9a16b2a6cac8fd319bfc 100644 (file)
@@ -22,7 +22,7 @@
 u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers,
                            struct wl_pwr_cfg pwrseqcmd[])
 {
-       struct wl_pwr_cfg pwrcfgcmd = {0};
+       struct wl_pwr_cfg pwrcfgcmd;
        u8 poll_bit = false;
        u32 aryidx = 0;
        u8 value = 0;
index 7bc9cb131bcc191d18f84662ea1a8c9578b655e8..30f72d220af16db55a1ec68fd0a62dbafd511433 100644 (file)
@@ -1317,7 +1317,6 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
        bool bToOtherSTA = false;
        int ret = 0, i = 0;
 
-       hdr = (struct rtllib_hdr_4addr *)skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
        type = WLAN_FC_GET_TYPE(fc);
        stype = WLAN_FC_GET_STYPE(fc);
index c2b9ffba354a560d965edc2c6b9e4ac8a434d858..919231fec09cba4dacab0e4c18b64c4ca385c145 100644 (file)
@@ -1968,7 +1968,7 @@ void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee)
 
 static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time)
 {
-       int timeout = ieee->ps_timeout;
+       int timeout;
        u8 dtim;
        struct rt_pwr_save_ctrl *pPSC = &(ieee->PowerSaveControl);
 
index 64b13a5da3cb3283a0296fe3ce83d1bf30219beb..ba284bfb3b6da1d146a99e00e57eff5ac42c02d3 100644 (file)
@@ -11,7 +11,7 @@ void Dot11d_Init(struct ieee80211_device *ieee)
 
        pDot11dInfo->State = DOT11D_STATE_NONE;
        pDot11dInfo->CountryIeLen = 0;
-       memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
+       memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
        memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
        RESET_CIE_WATCHDOG(ieee);
 
index cbf8eb4a049d879595d349122eb48785baaff1a0..37a610d05ad2a35d3fa59caafa7a70893ace925e 100644 (file)
@@ -110,12 +110,12 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee,
          hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr;
          tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
          tid = UP2AC(tid);
-         tid ++;
+         tid++;
        } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
          hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr;
          tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
          tid = UP2AC(tid);
-         tid ++;
+         tid++;
        } else {
          tid = 0;
        }
@@ -177,12 +177,12 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
          hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr;
          tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
          tid = UP2AC(tid);
-         tid ++;
+         tid++;
        } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
          hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr;
          tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
          tid = UP2AC(tid);
-         tid ++;
+         tid++;
        } else {
          tid = 0;
        }
@@ -434,12 +434,12 @@ static int is_duplicate_packet(struct ieee80211_device *ieee,
          hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)header;
          tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
          tid = UP2AC(tid);
-         tid ++;
+         tid++;
        } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
          hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)header;
          tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
          tid = UP2AC(tid);
-         tid ++;
+         tid++;
        } else { // no QoS
          tid = 0;
        }
index f56fdc7a4b614bd5732bfe9fac96017a43d49346..25c186a8bde3d78653bcf726d3541124ad037657 100644 (file)
@@ -1725,7 +1725,7 @@ static void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
 static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
                                    u32 *time_l)
 {
-       int timeout = ieee->ps_timeout;
+       int timeout;
        u8 dtim;
        /*if(ieee->ps == IEEE80211_PS_DISABLED ||
                ieee->iw_mode != IW_MODE_INFRA ||
index 09f66b386e44640f7f1542ef87494fa16b8a9ca6..3c300f7b6a622c1c35b2e59be03956d5d052aa35 100644 (file)
@@ -4998,7 +4998,7 @@ fail:
        kfree(priv->pFirmware);
        priv->pFirmware = NULL;
        rtl8192_usb_deleteendpoints(dev);
-       mdelay(10);
+       msleep(10);
        free_ieee80211(dev);
 
        RT_TRACE(COMP_ERR, "wlan driver load failed\n");
index de832b0b5eecf350b648be32302b629f6e3f3a1d..2a3f0746ee2c66a68915b1759cde57443168b654 100644 (file)
@@ -336,7 +336,6 @@ uint rtl8712_hal_init(struct _adapter *padapter)
                    r8712_read32(padapter, RCR));
        val32 = r8712_read32(padapter, RCR);
        r8712_write32(padapter, RCR, (val32 | BIT(25))); /* Append PHY status */
-       val32 = 0;
        val32 = r8712_read32(padapter, 0x10250040);
        r8712_write32(padapter,  0x10250040, (val32 & 0x00FFFFFF));
        /* for usb rx aggregation */
index 33e82a9dd4627e8e7690b0fad453160c57f26ff5..987270395635907a78945c80ec429bb0b4be57fb 100644 (file)
@@ -169,12 +169,13 @@ int r8712_generate_ie(struct registry_priv *pregistrypriv)
        int sz = 0, rate_len;
        struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
        u8 *ie = pdev_network->IEs;
+       u16 beaconPeriod = (u16)pdev_network->Configuration.BeaconPeriod;
 
        /*timestamp will be inserted by hardware*/
        sz += 8;
        ie += sz;
        /*beacon interval : 2bytes*/
-       *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);
+       *(__le16 *)ie = cpu_to_le16(beaconPeriod);
        sz += 2;
        ie += 2;
        /*capability info*/
@@ -221,7 +222,8 @@ unsigned char *r8712_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit)
                pbuf = r8712_get_ie(pbuf, _WPA_IE_ID_, &len, limit);
                if (pbuf) {
                        /*check if oui matches...*/
-                       if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type)))
+                       if (memcmp((pbuf + 2), wpa_oui_type,
+                                  sizeof(wpa_oui_type)))
                                goto check_next_ie;
                        /*check version...*/
                        memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16));
index 95caf8df9a1347d442353fb1e27479b078306a6f..e7df5d7986fc867101336a14b0a34914e4e8e832 100644 (file)
@@ -238,10 +238,13 @@ static u32 start_drv_threads(struct _adapter *padapter)
 
 void r8712_stop_drv_threads(struct _adapter *padapter)
 {
+       struct completion *completion =
+               &padapter->cmdpriv.terminate_cmdthread_comp;
+
        /*Below is to terminate r8712_cmd_thread & event_thread...*/
        complete(&padapter->cmdpriv.cmd_queue_comp);
        if (padapter->cmdThread)
-               wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp);
+               wait_for_completion_interruptible(completion);
        padapter->cmdpriv.cmd_seq = 1;
 }
 
index 3c88994fdfcd92f09fc2e84bc7dcf44f9da290cd..9c8e0c50a8047543bac8b9cdfb580ce57f632769 100644 (file)
@@ -321,10 +321,13 @@ int r8712_cmd_thread(void *context)
        void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
        struct _adapter *padapter = context;
        struct  cmd_priv        *pcmdpriv = &(padapter->cmdpriv);
+       struct completion *cmd_queue_comp =
+               &pcmdpriv->cmd_queue_comp;
+       struct mutex *pwctrl_lock = &padapter->pwrctrlpriv.mutex_lock;
 
        allow_signal(SIGTERM);
        while (1) {
-               if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp))
+               if (wait_for_completion_interruptible(cmd_queue_comp))
                        break;
                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
                        break;
@@ -343,6 +346,7 @@ _next:
                if (pcmd) { /* if pcmd != NULL, cmd will be handled by f/w */
                        struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
                        u8 blnPending = 0;
+                       u16 cmdcode = pcmd->cmdcode;
 
                        pcmdpriv->cmd_issued_cnt++;
                        cmdsz = round_up(pcmd->cmdsz, 8);
@@ -387,20 +391,18 @@ _next:
                        r8712_write_mem(padapter, RTL8712_DMA_H2CCMD, wr_sz,
                                        (u8 *)pdesc);
                        pcmdpriv->cmd_seq++;
-                       if (pcmd->cmdcode == GEN_CMD_CODE(_CreateBss)) {
+                       if (cmdcode == GEN_CMD_CODE(_CreateBss)) {
                                pcmd->res = H2C_SUCCESS;
-                               pcmd_callback = cmd_callback[pcmd->
-                                               cmdcode].callback;
+                               pcmd_callback = cmd_callback[cmdcode].callback;
                                if (pcmd_callback)
                                        pcmd_callback(padapter, pcmd);
                                continue;
                        }
-                       if (pcmd->cmdcode == GEN_CMD_CODE(_SetPwrMode)) {
+                       if (cmdcode == GEN_CMD_CODE(_SetPwrMode)) {
                                if (padapter->pwrctrlpriv.bSleep) {
-                                       mutex_lock(&padapter->
-                                                      pwrctrlpriv.mutex_lock);
+                                       mutex_lock(pwctrl_lock);
                                        r8712_set_rpwm(padapter, PS_STATE_S2);
-                                       mutex_unlock(&padapter->pwrctrlpriv.mutex_lock);
+                                       mutex_unlock(pwctrl_lock);
                                }
                        }
                        r8712_free_cmd_obj(pcmd);
index 8f555e6e1b3fcd370a031757b1c1cadd6b20c4b4..4264cd341f031e7b7f2648d725df3ee368b1f1da 100644 (file)
@@ -899,6 +899,7 @@ static void process_link_qual(struct _adapter *padapter,
 {
        u32     last_evm = 0, tmpVal;
        struct rx_pkt_attrib *pattrib;
+       struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
 
        if (prframe == NULL || padapter == NULL)
                return;
@@ -907,27 +908,18 @@ static void process_link_qual(struct _adapter *padapter,
                /*
                 * 1. Record the general EVM to the sliding window.
                 */
-               if (padapter->recvpriv.signal_qual_data.total_num++ >=
-                                 PHY_LINKQUALITY_SLID_WIN_MAX) {
-                       padapter->recvpriv.signal_qual_data.total_num =
-                                 PHY_LINKQUALITY_SLID_WIN_MAX;
-                       last_evm = padapter->recvpriv.signal_qual_data.elements
-                                 [padapter->recvpriv.signal_qual_data.index];
-                       padapter->recvpriv.signal_qual_data.total_val -=
-                                 last_evm;
+               if (sqd->total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX) {
+                       sqd->total_num = PHY_LINKQUALITY_SLID_WIN_MAX;
+                       last_evm = sqd->elements[sqd->index];
+                       sqd->total_val -= last_evm;
                }
-               padapter->recvpriv.signal_qual_data.total_val +=
-                         pattrib->signal_qual;
-               padapter->recvpriv.signal_qual_data.elements[padapter->
-                         recvpriv.signal_qual_data.index++] =
-                         pattrib->signal_qual;
-               if (padapter->recvpriv.signal_qual_data.index >=
-                   PHY_LINKQUALITY_SLID_WIN_MAX)
-                       padapter->recvpriv.signal_qual_data.index = 0;
+               sqd->total_val += pattrib->signal_qual;
+               sqd->elements[sqd->index++] = pattrib->signal_qual;
+               if (sqd->index >= PHY_LINKQUALITY_SLID_WIN_MAX)
+                       sqd->index = 0;
 
                /* <1> Showed on UI for user, in percentage. */
-               tmpVal = padapter->recvpriv.signal_qual_data.total_val /
-                        padapter->recvpriv.signal_qual_data.total_num;
+               tmpVal = sqd->total_val / sqd->total_num;
                padapter->recvpriv.signal = (u8)tmpVal;
        }
 }
@@ -936,25 +928,18 @@ static void process_rssi(struct _adapter *padapter, union recv_frame *prframe)
 {
        u32 last_rssi, tmp_val;
        struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+       struct smooth_rssi_data *ssd = &padapter->recvpriv.signal_strength_data;
 
-       if (padapter->recvpriv.signal_strength_data.total_num++ >=
-           PHY_RSSI_SLID_WIN_MAX) {
-               padapter->recvpriv.signal_strength_data.total_num =
-                        PHY_RSSI_SLID_WIN_MAX;
-               last_rssi = padapter->recvpriv.signal_strength_data.elements
-                           [padapter->recvpriv.signal_strength_data.index];
-               padapter->recvpriv.signal_strength_data.total_val -= last_rssi;
+       if (ssd->total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
+               ssd->total_num = PHY_RSSI_SLID_WIN_MAX;
+               last_rssi = ssd->elements[ssd->index];
+               ssd->total_val -= last_rssi;
        }
-       padapter->recvpriv.signal_strength_data.total_val +=
-                       pattrib->signal_strength;
-       padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.
-                       signal_strength_data.index++] =
-                       pattrib->signal_strength;
-       if (padapter->recvpriv.signal_strength_data.index >=
-           PHY_RSSI_SLID_WIN_MAX)
-               padapter->recvpriv.signal_strength_data.index = 0;
-       tmp_val = padapter->recvpriv.signal_strength_data.total_val /
-                 padapter->recvpriv.signal_strength_data.total_num;
+       ssd->total_val += pattrib->signal_strength;
+       ssd->elements[ssd->index++] = pattrib->signal_strength;
+       if (ssd->index >= PHY_RSSI_SLID_WIN_MAX)
+               ssd->index = 0;
+       tmp_val = ssd->total_val / ssd->total_num;
        padapter->recvpriv.rssi = (s8)translate2dbm(padapter, (u8)tmp_val);
 }
 
index 42d014007764e4f61939c7dcc04ebb324fd2d82c..fb64c2891e22016164a606cb4aecd0cc5dd77cd8 100644 (file)
@@ -573,7 +573,8 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
                }
        } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
                /* offset 4 */
-               ptxdesc->txdw1 |= cpu_to_le32((0x05) & 0x1f);/*CAM_ID(MAC_ID), default=5;*/
+               /* CAM_ID(MAC_ID), default=5; */
+               ptxdesc->txdw1 |= cpu_to_le32((0x05) & 0x1f);
                qsel = (uint)(pattrib->qsel & 0x0000001f);
                ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
                ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/* Non-QoS */
index a424f447a72522fa48ddaddfd5bbb369fe16a2f5..620cee8b851448d1ae3c201053d00304c8349ddb 100644 (file)
@@ -455,8 +455,8 @@ u8 r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
        struct qos_priv         *pqospriv = &pmlmepriv->qospriv;
        struct security_priv    *psecuritypriv = &padapter->securitypriv;
        struct registry_priv    *pregistrypriv = &padapter->registrypriv;
-       enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->
-                                               network.InfrastructureMode;
+       enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode =
+               pnetwork->network.InfrastructureMode;
 
        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
@@ -862,22 +862,22 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter,
        pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
        pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
        pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
-       pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork->
-                                       Configuration.ATIMWindow);
-       pnetwork->Configuration.DSConfig = le32_to_cpu(pnetwork->
-                                       Configuration.DSConfig);
-       pnetwork->Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork->
-                                       Configuration.FHConfig.DwellTime);
-       pnetwork->Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork->
-                                       Configuration.FHConfig.HopPattern);
-       pnetwork->Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork->
-                                       Configuration.FHConfig.HopSet);
-       pnetwork->Configuration.FHConfig.Length = le32_to_cpu(pnetwork->
-                                       Configuration.FHConfig.Length);
-       pnetwork->Configuration.Length = le32_to_cpu(pnetwork->
-                                       Configuration.Length);
-       pnetwork->InfrastructureMode = le32_to_cpu(pnetwork->
-                                          InfrastructureMode);
+       pnetwork->Configuration.ATIMWindow =
+               le32_to_cpu(pnetwork->Configuration.ATIMWindow);
+       pnetwork->Configuration.DSConfig =
+               le32_to_cpu(pnetwork->Configuration.DSConfig);
+       pnetwork->Configuration.FHConfig.DwellTime =
+               le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
+       pnetwork->Configuration.FHConfig.HopPattern =
+               le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
+       pnetwork->Configuration.FHConfig.HopSet =
+               le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
+       pnetwork->Configuration.FHConfig.Length =
+               le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
+       pnetwork->Configuration.Length =
+               le32_to_cpu(pnetwork->Configuration.Length);
+       pnetwork->InfrastructureMode =
+               le32_to_cpu(pnetwork->InfrastructureMode);
        pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
 #endif
        spin_lock_irqsave(&pmlmepriv->lock, irqL);
index e30a5be5f318c62ebc62d617385ffa832d2a054e..c3ff7c3e6681e3e328e6a6b788d5888dfc7187ef 100644 (file)
@@ -114,23 +114,27 @@ static inline void handle_pairwise_key(struct sta_info *psta,
 static inline void handle_group_key(struct ieee_param *param,
                                    struct _adapter *padapter)
 {
+       union Keytype *gk = padapter->securitypriv.XGrpKey;
+       union Keytype *gtk = padapter->securitypriv.XGrptxmickey;
+       union Keytype *grk = padapter->securitypriv.XGrprxmickey;
+
        if (param->u.crypt.idx > 0 &&
            param->u.crypt.idx < 3) {
                /* group key idx is 1 or 2 */
-               memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
-                       idx - 1].skey, param->u.crypt.key,
-                       (param->u.crypt.key_len > 16 ? 16 :
-                        param->u.crypt.key_len));
-               memcpy(padapter->securitypriv.XGrptxmickey[param->
-                       u.crypt.idx - 1].skey, &(param->u.crypt.key[16]), 8);
-               memcpy(padapter->securitypriv. XGrprxmickey[param->
-                       u.crypt.idx - 1].skey, &(param->u.crypt.key[24]), 8);
+               memcpy(gk[param->u.crypt.idx - 1].skey,
+                      param->u.crypt.key,
+                      (param->u.crypt.key_len > 16 ? 16 :
+                       param->u.crypt.key_len));
+               memcpy(gtk[param->u.crypt.idx - 1].skey,
+                      &param->u.crypt.key[16], 8);
+               memcpy(grk[param->u.crypt.idx - 1].skey,
+                      &param->u.crypt.key[24], 8);
                padapter->securitypriv.binstallGrpkey = true;
                r8712_set_key(padapter, &padapter->securitypriv,
                        param->u.crypt.idx);
                if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
-                       if (padapter->registrypriv.power_mgnt != padapter->
-                           pwrctrlpriv.pwr_mode)
+                       if (padapter->registrypriv.power_mgnt !=
+                           padapter->pwrctrlpriv.pwr_mode)
                                mod_timer(&padapter->mlmepriv.dhcp_timer,
                                          jiffies + msecs_to_jiffies(60000));
                }
@@ -216,9 +220,9 @@ static noinline_for_stack char *translate_scan(struct _adapter *padapter,
 
                if (dsconfig >= 1 && dsconfig <= sizeof(
                    ieee80211_wlan_frequencies) / sizeof(long))
-                       iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
-                                      pnetwork->network.Configuration.
-                                      DSConfig - 1] * 100000);
+                       iwe.u.freq.m =
+                               (s32)(ieee80211_wlan_frequencies
+                                     [dsconfig - 1] * 100000);
                else
                        iwe.u.freq.m = 0;
        }
@@ -425,9 +429,9 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
                                ret = -EOPNOTSUPP;
                                goto exit;
                        }
-                       memcpy(&(psecuritypriv->DefKey[wep_key_idx].
-                               skey[0]), pwep->KeyMaterial,
-                               pwep->KeyLength);
+                       memcpy(&psecuritypriv->DefKey[wep_key_idx].skey[0],
+                              pwep->KeyMaterial,
+                              pwep->KeyLength);
                        psecuritypriv->DefKeylen[wep_key_idx] =
                                pwep->KeyLength;
                        r8712_set_key(padapter, psecuritypriv, wep_key_idx);
@@ -437,6 +441,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
        if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
                struct sta_info *psta, *pbcmc_sta;
                struct sta_priv *pstapriv = &padapter->stapriv;
+               struct security_priv *spriv = &padapter->securitypriv;
 
                if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
                    WIFI_MP_STATE)) { /* sta mode */
@@ -444,12 +449,11 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
                                                 get_bssid(pmlmepriv));
                        if (psta) {
                                psta->ieee8021x_blocked = false;
-                               if ((padapter->securitypriv.ndisencryptstatus ==
-                                   Ndis802_11Encryption2Enabled) ||
-                                   (padapter->securitypriv.ndisencryptstatus ==
-                                   Ndis802_11Encryption3Enabled))
-                                       psta->XPrivacy = padapter->
-                                           securitypriv.PrivacyAlgrthm;
+                               if (spriv->ndisencryptstatus ==
+                                   Ndis802_11Encryption2Enabled ||
+                                   spriv->ndisencryptstatus ==
+                                   Ndis802_11Encryption3Enabled)
+                                       psta->XPrivacy = spriv->PrivacyAlgrthm;
                                if (param->u.crypt.set_tx == 1)
                                        handle_pairwise_key(psta, param,
                                                            padapter);
@@ -459,13 +463,12 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
                        pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
                        if (pbcmc_sta) {
                                pbcmc_sta->ieee8021x_blocked = false;
-                               if ((padapter->securitypriv.ndisencryptstatus ==
-                                   Ndis802_11Encryption2Enabled) ||
-                                   (padapter->securitypriv.ndisencryptstatus ==
-                                   Ndis802_11Encryption3Enabled))
+                               if (spriv->ndisencryptstatus ==
+                                   Ndis802_11Encryption2Enabled ||
+                                   spriv->ndisencryptstatus ==
+                                   Ndis802_11Encryption3Enabled)
                                        pbcmc_sta->XPrivacy =
-                                         padapter->securitypriv.
-                                         PrivacyAlgrthm;
+                                               spriv->PrivacyAlgrthm;
                        }
                }
        }
@@ -763,6 +766,7 @@ static int r871x_wx_set_pmkid(struct net_device *dev,
        struct _adapter *padapter = netdev_priv(dev);
        struct security_priv *psecuritypriv = &padapter->securitypriv;
        struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
+       struct RT_PMKID_LIST *pl = psecuritypriv->PMKIDList;
        u8 strZeroMacAddress[ETH_ALEN] = {0x00};
        u8 strIssueBssid[ETH_ALEN] = {0x00};
        u8 j, blInserted = false;
@@ -787,16 +791,14 @@ static int r871x_wx_set_pmkid(struct net_device *dev,
                blInserted = false;
                /* overwrite PMKID */
                for (j = 0; j < NUM_PMKID_CACHE; j++) {
-                       if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
-                           strIssueBssid, ETH_ALEN)) {
+                       if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
                                /* BSSID is matched, the same AP => rewrite
                                 * with new PMKID.
                                 */
                                netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
                                            __func__);
-                               memcpy(psecuritypriv->PMKIDList[j].PMKID,
-                                       pPMK->pmkid, IW_PMKID_LEN);
-                               psecuritypriv->PMKIDList[j].bUsed = true;
+                               memcpy(pl[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
+                               pl[j].bUsed = true;
                                psecuritypriv->PMKIDIndex = j + 1;
                                blInserted = true;
                                break;
@@ -806,12 +808,11 @@ static int r871x_wx_set_pmkid(struct net_device *dev,
                        /* Find a new entry */
                        netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
                                    __func__, psecuritypriv->PMKIDIndex);
-                       memcpy(psecuritypriv->PMKIDList[psecuritypriv->
-                               PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
-                       memcpy(psecuritypriv->PMKIDList[psecuritypriv->
-                               PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
-                       psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
-                               bUsed = true;
+                       memcpy(pl[psecuritypriv->PMKIDIndex].Bssid,
+                              strIssueBssid, ETH_ALEN);
+                       memcpy(pl[psecuritypriv->PMKIDIndex].PMKID,
+                              pPMK->pmkid, IW_PMKID_LEN);
+                       pl[psecuritypriv->PMKIDIndex].bUsed = true;
                        psecuritypriv->PMKIDIndex++;
                        if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
                                psecuritypriv->PMKIDIndex = 0;
@@ -820,13 +821,12 @@ static int r871x_wx_set_pmkid(struct net_device *dev,
        case IW_PMKSA_REMOVE:
                intReturn = true;
                for (j = 0; j < NUM_PMKID_CACHE; j++) {
-                       if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
-                           strIssueBssid, ETH_ALEN)) {
+                       if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
                                /* BSSID is matched, the same AP => Remove
                                 * this PMKID information and reset it.
                                 */
-                               eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
-                               psecuritypriv->PMKIDList[j].bUsed = false;
+                               eth_zero_addr(pl[j].Bssid);
+                               pl[j].bUsed = false;
                                break;
                        }
                }
@@ -1598,6 +1598,7 @@ static int r8711_wx_get_enc(struct net_device *dev,
        struct _adapter *padapter = netdev_priv(dev);
        struct iw_point *erq = &(wrqu->encoding);
        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
+       union Keytype *dk = padapter->securitypriv.DefKey;
 
        if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
                if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
@@ -1624,9 +1625,8 @@ static int r8711_wx_get_enc(struct net_device *dev,
        case Ndis802_11Encryption1Enabled:
                erq->length = padapter->securitypriv.DefKeylen[key];
                if (erq->length) {
-                       memcpy(keybuf, padapter->securitypriv.DefKey[
-                               key].skey, padapter->securitypriv.
-                               DefKeylen[key]);
+                       memcpy(keybuf, dk[key].skey,
+                              padapter->securitypriv.DefKeylen[key]);
                        erq->flags |= IW_ENCODE_ENABLED;
                        if (padapter->securitypriv.ndisauthtype ==
                            Ndis802_11AuthModeOpen)
@@ -1719,12 +1719,12 @@ static int r871x_wx_set_auth(struct net_device *dev,
                 */
                if (padapter->securitypriv.ndisencryptstatus ==
                    Ndis802_11Encryption1Enabled) {
-                               /* it means init value, or using wep,
-                                * ndisencryptstatus =
-                                *      Ndis802_11Encryption1Enabled,
-                                * then it needn't reset it;
-                                */
-                               break;
+                       /* it means init value, or using wep,
+                        * ndisencryptstatus =
+                        *      Ndis802_11Encryption1Enabled,
+                        * then it needn't reset it;
+                        */
+                       break;
                }
 
                if (paramval) {
@@ -1853,7 +1853,7 @@ static int dummy(struct net_device *dev,
                struct iw_request_info *a,
                union iwreq_data *wrqu, char *b)
 {
-       return -ENOSYS;
+       return -EINVAL;
 }
 
 static int r8711_drvext_hdl(struct net_device *dev,
index 8a5ced4fa9d3ab8bc44d1674334a749c791966e4..f4a53df7f2c1a2cb5a6438b0235cf7b120f5990c 100644 (file)
@@ -55,6 +55,7 @@ static u8 do_join(struct _adapter *padapter)
        u8 *pibss = NULL;
        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
        struct  __queue *queue  = &(pmlmepriv->scanned_queue);
+       int ret;
 
        phead = &queue->queue;
        plist = phead->next;
@@ -74,45 +75,42 @@ static u8 do_join(struct _adapter *padapter)
                if (!pmlmepriv->sitesurveyctrl.traffic_busy)
                        r8712_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid);
                return true;
-       } else {
-               int ret;
+       }
 
-               ret = r8712_select_and_join_from_scan(pmlmepriv);
-               if (ret == _SUCCESS) {
-                       mod_timer(&pmlmepriv->assoc_timer,
-                                 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+       ret = r8712_select_and_join_from_scan(pmlmepriv);
+       if (ret == _SUCCESS) {
+               mod_timer(&pmlmepriv->assoc_timer,
+                         jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+       } else {
+               if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+                       /* submit r8712_createbss_cmd to change to an
+                        * ADHOC_MASTER pmlmepriv->lock has been
+                        * acquired by caller...
+                        */
+                       struct wlan_bssid_ex *pdev_network =
+                               &(padapter->registrypriv.dev_network);
+                       pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
+                       pibss = padapter->registrypriv.dev_network.MacAddress;
+                       memcpy(&pdev_network->Ssid,
+                              &pmlmepriv->assoc_ssid,
+                              sizeof(struct ndis_802_11_ssid));
+                       r8712_update_registrypriv_dev_network(padapter);
+                       r8712_generate_random_ibss(pibss);
+                       if (r8712_createbss_cmd(padapter) != _SUCCESS)
+                               return false;
+                       pmlmepriv->to_join = false;
                } else {
-                       if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
-                               /* submit r8712_createbss_cmd to change to an
-                                * ADHOC_MASTER pmlmepriv->lock has been
-                                * acquired by caller...
-                                */
-                               struct wlan_bssid_ex *pdev_network =
-                                       &(padapter->registrypriv.dev_network);
-                               pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
-                               pibss = padapter->registrypriv.dev_network.
-                                       MacAddress;
-                               memcpy(&pdev_network->Ssid,
-                                       &pmlmepriv->assoc_ssid,
-                                       sizeof(struct ndis_802_11_ssid));
-                               r8712_update_registrypriv_dev_network(padapter);
-                               r8712_generate_random_ibss(pibss);
-                               if (r8712_createbss_cmd(padapter) != _SUCCESS)
-                                       return false;
-                               pmlmepriv->to_join = false;
-                       } else {
-                               /* can't associate ; reset under-linking */
-                               if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
-                                       pmlmepriv->fw_state ^=
-                                                            _FW_UNDER_LINKING;
-                               /* when set_ssid/set_bssid for do_join(), but
-                                * there are no desired bss in scanning queue
-                                * we try to issue sitesurvey first
-                                */
-                               if (!pmlmepriv->sitesurveyctrl.traffic_busy)
-                                       r8712_sitesurvey_cmd(padapter,
-                                                      &pmlmepriv->assoc_ssid);
-                       }
+                       /* can't associate ; reset under-linking */
+                       if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
+                               pmlmepriv->fw_state ^=
+                                       _FW_UNDER_LINKING;
+                       /* when set_ssid/set_bssid for do_join(), but
+                        * there are no desired bss in scanning queue
+                        * we try to issue sitesurvey first
+                        */
+                       if (!pmlmepriv->sitesurveyctrl.traffic_busy)
+                               r8712_sitesurvey_cmd(padapter,
+                                                    &pmlmepriv->assoc_ssid);
                }
        }
        return true;
index 111c809afc51ab2ccfd25f89910315147a27ddc2..78245080e32860bfa5765054d97286e4247701d6 100644 (file)
@@ -319,6 +319,7 @@ static void update_network(struct wlan_bssid_ex *dst,
                           struct _adapter *padapter)
 {
        u32 last_evm = 0, tmpVal;
+       struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
 
        if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
            is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
@@ -326,17 +327,13 @@ static void update_network(struct wlan_bssid_ex *dst,
                    PHY_LINKQUALITY_SLID_WIN_MAX) {
                        padapter->recvpriv.signal_qual_data.total_num =
                                   PHY_LINKQUALITY_SLID_WIN_MAX;
-                       last_evm = padapter->recvpriv.signal_qual_data.
-                                  elements[padapter->recvpriv.
-                                  signal_qual_data.index];
+                       last_evm = sqd->elements[sqd->index];
                        padapter->recvpriv.signal_qual_data.total_val -=
                                 last_evm;
                }
                padapter->recvpriv.signal_qual_data.total_val += src->Rssi;
 
-               padapter->recvpriv.signal_qual_data.
-                         elements[padapter->recvpriv.signal_qual_data.
-                         index++] = src->Rssi;
+               sqd->elements[sqd->index++] = src->Rssi;
                if (padapter->recvpriv.signal_qual_data.index >=
                    PHY_LINKQUALITY_SLID_WIN_MAX)
                        padapter->recvpriv.signal_qual_data.index = 0;
index b21f28140f532b12e47db753e7adc3086f8c6fa8..918947f3815167a2170c578b6711fd1da09c60e2 100644 (file)
@@ -55,7 +55,8 @@
                                                 * single-tone
                                                 */
 #define        WIFI_MP_CTX_BACKGROUND_PENDING  0x00080000 /* pending in cont, tx
-                                                   * background due to out of skb
+                                                   * background due
+                                                   * to out of skb
                                                    */
 #define        WIFI_MP_CTX_CCK_HW      0x00100000      /* in continuous tx*/
 #define        WIFI_MP_CTX_CCK_CS      0x00200000      /* in cont, tx with carrier
index 3c10a2c848c8f577fc9a8dce5edc5e29e152042f..ba208a2e1e4ee48d33e13a9ca7261b5098aaa16b 100644 (file)
@@ -541,7 +541,7 @@ void r8712_SetSingleCarrierTx(struct _adapter *pAdapter, u8 bStart)
 
 void r8712_SetSingleToneTx(struct _adapter *pAdapter, u8 bStart)
 {
-       u8 rfPath = pAdapter->mppriv.curr_rfpath;
+       u8 rfPath;
 
        switch (pAdapter->mppriv.antenna_tx) {
        case ANTENNA_B:
index 56d36f6f9c462a05b0d3b84fbc02b1dba3302dcf..7bc74d7d8a3a49f08812942bdb5e9b3b716edb6d 100644 (file)
@@ -165,7 +165,7 @@ void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe)
 {      /* exclude ICV */
        unsigned char   crc[4];
        struct arc4context  mycontext;
-       u32 curfragnum, length, keylength;
+       u32 curfragnum, length, keylength, pki;
        u8 *pframe, *payload, *iv;    /*,*wepkey*/
        u8 wepkey[16];
        struct  pkt_attrib  *pattrib = &((struct xmit_frame *)
@@ -178,8 +178,8 @@ void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe)
        pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
        /*start to encrypt each fragment*/
        if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) {
-               keylength = psecuritypriv->DefKeylen[psecuritypriv->
-                           PrivacyKeyIndex];
+               pki = psecuritypriv->PrivacyKeyIndex;
+               keylength = psecuritypriv->DefKeylen[pki];
                for (curfragnum = 0; curfragnum < pattrib->nr_frags;
                     curfragnum++) {
                        iv = pframe + pattrib->hdrlen;
@@ -189,9 +189,10 @@ void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe)
                                keylength);
                        payload = pframe + pattrib->iv_len + pattrib->hdrlen;
                        if ((curfragnum + 1) == pattrib->nr_frags) {
-                               length = pattrib->last_txcmdsz - pattrib->
-                                        hdrlen - pattrib->iv_len -
-                                        pattrib->icv_len;
+                               length = pattrib->last_txcmdsz -
+                                       pattrib->hdrlen -
+                                       pattrib->iv_len -
+                                       pattrib->icv_len;
                                *((__le32 *)crc) = cpu_to_le32(getcrc32(
                                                payload, length));
                                arcfour_init(&mycontext, wepkey, 3 + keylength);
@@ -606,8 +607,8 @@ u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe)
                                GET_TKIP_PN(iv, txpn);
                                pnl = (u16)(txpn.val);
                                pnh = (u32)(txpn.val >> 16);
-                               phase1((u16 *)&ttkey[0], prwskey, &pattrib->
-                                      ta[0], pnh);
+                               phase1((u16 *)&ttkey[0], prwskey,
+                                      &pattrib->ta[0], pnh);
                                phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0],
                                       pnl);
                                if ((curfragnum + 1) == pattrib->nr_frags) {
@@ -997,8 +998,9 @@ static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, sint a4_exists,
 /* Builds the last MIC header block from        */
 /* header fields.                               */
 /************************************************/
-static void construct_ctr_preload(u8 *ctr_preload, sint a4_exists, sint qc_exists,
-                          u8 *mpdu, u8 *pn_vector, sint c)
+static void construct_ctr_preload(u8 *ctr_preload,
+                                 sint a4_exists, sint qc_exists,
+                                 u8 *mpdu, u8 *pn_vector, sint c)
 {
        sint i;
 
@@ -1067,16 +1069,16 @@ static sint aes_cipher(u8 *key, uint    hdrlen,
        if ((frtype == WIFI_DATA_CFACK) ||
             (frtype == WIFI_DATA_CFPOLL) ||
             (frtype == WIFI_DATA_CFACKPOLL)) {
-                       qc_exists = 1;
-                       if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
-                               hdrlen += 2;
+               qc_exists = 1;
+               if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
+                       hdrlen += 2;
        } else if ((frsubtype == 0x08) ||
                   (frsubtype == 0x09) ||
                   (frsubtype == 0x0a) ||
                   (frsubtype == 0x0b)) {
-                       if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
-                               hdrlen += 2;
-                       qc_exists = 1;
+               if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
+                       hdrlen += 2;
+               qc_exists = 1;
        } else {
                qc_exists = 0;
        }
@@ -1184,15 +1186,15 @@ u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe)
                                                 pattrib->hdrlen -
                                                 pattrib->iv_len -
                                                 pattrib->icv_len;
-                                       aes_cipher(prwskey, pattrib->
-                                                 hdrlen, pframe, length);
+                                       aes_cipher(prwskey, pattrib->hdrlen,
+                                                  pframe, length);
                                } else {
                                        length = pxmitpriv->frag_len -
                                                 pattrib->hdrlen -
                                                 pattrib->iv_len -
                                                 pattrib->icv_len;
-                                       aes_cipher(prwskey, pattrib->
-                                                  hdrlen, pframe, length);
+                                       aes_cipher(prwskey, pattrib->hdrlen,
+                                                  pframe, length);
                                        pframe += pxmitpriv->frag_len;
                                        pframe = (u8 *)RND4((addr_t)(pframe));
                                }
@@ -1405,7 +1407,7 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe)
 void r8712_use_tkipkey_handler(struct timer_list *t)
 {
        struct _adapter *padapter =
-                from_timer(padapter, t, securitypriv.tkip_timer);
+               from_timer(padapter, t, securitypriv.tkip_timer);
 
        padapter->securitypriv.busetkipkey = true;
 }
index 441e76b8959db98489e28ef878db0753588467a5..6d12a96fa65f2f0f00011c184664ae1bf0660349 100644 (file)
@@ -145,7 +145,7 @@ static unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
                        break;
                }
        } else {
-          pipe = 0;
+               pipe = 0;
        }
        return pipe;
 }
index 9ac2dea6dff1cfb3dc1a1255532c76b9d0b5ae85..af0a9e0a00dfd2a4da3fed50fa472cbc4cfd5947 100644 (file)
@@ -846,9 +846,7 @@ u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
 
        psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
        if (psecnetwork == NULL) {
-               if (pcmd != NULL)
-                       kfree(pcmd);
-
+               kfree(pcmd);
                res = _FAIL;
 
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n"));
index c16e147d8adcb431347872dbf1012660de04cac0..a99a863be656aeb5a0588c5ff2790bf280450ff2 100644 (file)
@@ -1052,7 +1052,7 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB)
 
        /*  Check failed */
        regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
-       regEA4 = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord);;
+       regEA4 = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord);
 
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,  ("0xeac = 0x%x\n", regEAC));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea4 = 0x%x, 0xeac = 0x%x\n", regEA4, regEAC));
index f4619768a99fbe5e679da61a54005e29d9d89816..334d680b9b1cddf5c7170b481f5616bdee6e34fa 100644 (file)
@@ -50,7 +50,7 @@ u8 HalPwrSeqCmdParsing(
        WLAN_PWR_CFG PwrSeqCmd[]
 )
 {
-       WLAN_PWR_CFG PwrCfgCmd = {0};
+       WLAN_PWR_CFG PwrCfgCmd;
        u8 bPollingBit = false;
        u32 AryIdx = 0;
        u8 value = 0;
index e6787c22e00b68ba0a92f22dbf2b2f6b071b7869..93d6cc4787060b0b6d803302be3f9c62dc568490 100644 (file)
@@ -66,8 +66,7 @@ u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 Band, u8 RfPath,
                        DBG_871X("Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n",
                                         RateSection, RfPath, TxNum);
                        break;
-
-               };
+               }
        } else if (Band == BAND_ON_5G) {
                switch (RateSection) {
                case OFDM:
@@ -101,7 +100,7 @@ u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 Band, u8 RfPath,
                        DBG_871X("Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n",
                                         RateSection, RfPath, TxNum);
                        break;
-               };
+               }
        } else
                DBG_871X("Invalid Band %d in PHY_GetTxPowerByRateBase()\n", Band);
 
@@ -161,7 +160,7 @@ phy_SetTxPowerByRateBase(
                        DBG_871X("Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in phy_SetTxPowerByRateBase()\n",
                                         RateSection, RfPath, TxNum);
                        break;
-               };
+               }
        } else if (Band == BAND_ON_5G) {
                switch (RateSection) {
                case OFDM:
@@ -195,7 +194,7 @@ phy_SetTxPowerByRateBase(
                        DBG_871X("Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in phy_SetTxPowerByRateBase()\n",
                                         RateSection, RfPath, TxNum);
                        break;
-               };
+               }
        } else
                DBG_871X("Invalid Band %d in phy_SetTxPowerByRateBase()\n", Band);
 }
@@ -336,7 +335,7 @@ u8 PHY_GetRateSectionIndexOfTxPowerByRate(
                default:
                        DBG_871X("Invalid RegAddr 0x3%x in PHY_GetRateSectionIndexOfTxPowerByRate()", RegAddr);
                        break;
-               };
+               }
        }
 
        return index;
@@ -726,7 +725,7 @@ PHY_GetRateValuesOfTxPowerByRate(
        default:
                DBG_871X("Invalid RegAddr 0x%x in %s()\n", RegAddr, __func__);
                break;
-       };
+       }
 }
 
 static void PHY_StoreTxPowerByRateNew(
@@ -1474,8 +1473,7 @@ u8 PHY_GetRateIndexOfTxPowerByRate(u8 Rate)
        default:
                DBG_871X("Invalid rate 0x%x in %s\n", Rate, __func__);
                break;
-       };
-
+       }
        return index;
 }
 
index 21ec890fd60c8a51a868857ef63a919bf87c5fe5..e34d133075c0bd0281ecf004ad8c5e9b6a624abb 100644 (file)
@@ -153,7 +153,7 @@ static u32 phy_RFSerialRead_8723B(
        NewOffset = Offset;
 
        if (eRFPath == RF_PATH_A) {
-               tmplong2 = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord);;
+               tmplong2 = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord);
                tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset<<23) | bLSSIReadEdge;  /* T65 RF */
                PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord, tmplong2&(~bLSSIReadEdge));
        } else {
index 9a4c24861947dbb8a333d2ecaf66c45040865acd..ab2ff53a8e57e1b5498622e214c4ce4999b1fb99 100644 (file)
 /*  Creadted by Roger, 2011.01.31. */
 /*  */
 static void HalSdioGetCmdAddr8723BSdio(
-       struct adapter *padapter,
-       u8 DeviceID,
-       u32 Addr,
-       u32 *pCmdAddr
+       struct adapter *adapter,
+       u8 device_id,
+       u32 addr,
+       u32 *cmdaddr
 )
 {
-       switch (DeviceID) {
+       switch (device_id) {
        case SDIO_LOCAL_DEVICE_ID:
-               *pCmdAddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (Addr & SDIO_LOCAL_MSK));
+               *cmdaddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (addr & SDIO_LOCAL_MSK));
                break;
 
        case WLAN_IOREG_DEVICE_ID:
-               *pCmdAddr = ((WLAN_IOREG_DEVICE_ID << 13) | (Addr & WLAN_IOREG_MSK));
+               *cmdaddr = ((WLAN_IOREG_DEVICE_ID << 13) | (addr & WLAN_IOREG_MSK));
                break;
 
        case WLAN_TX_HIQ_DEVICE_ID:
-               *pCmdAddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
+               *cmdaddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
                break;
 
        case WLAN_TX_MIQ_DEVICE_ID:
-               *pCmdAddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
+               *cmdaddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
                break;
 
        case WLAN_TX_LOQ_DEVICE_ID:
-               *pCmdAddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
+               *cmdaddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
                break;
 
        case WLAN_RX0FF_DEVICE_ID:
-               *pCmdAddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (Addr & WLAN_RX0FF_MSK));
+               *cmdaddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (addr & WLAN_RX0FF_MSK));
                break;
 
        default:
@@ -66,64 +66,64 @@ static void HalSdioGetCmdAddr8723BSdio(
 
 static u8 get_deviceid(u32 addr)
 {
-       u8 devideId;
-       u16 pseudoId;
+       u8 devide_id;
+       u16 pseudo_id;
 
 
-       pseudoId = (u16)(addr >> 16);
-       switch (pseudoId) {
+       pseudo_id = (u16)(addr >> 16);
+       switch (pseudo_id) {
        case 0x1025:
-               devideId = SDIO_LOCAL_DEVICE_ID;
+               devide_id = SDIO_LOCAL_DEVICE_ID;
                break;
 
        case 0x1026:
-               devideId = WLAN_IOREG_DEVICE_ID;
+               devide_id = WLAN_IOREG_DEVICE_ID;
                break;
 
 /*             case 0x1027: */
-/*                     devideId = SDIO_FIRMWARE_FIFO; */
+/*                     devide_id = SDIO_FIRMWARE_FIFO; */
 /*                     break; */
 
        case 0x1031:
-               devideId = WLAN_TX_HIQ_DEVICE_ID;
+               devide_id = WLAN_TX_HIQ_DEVICE_ID;
                break;
 
        case 0x1032:
-               devideId = WLAN_TX_MIQ_DEVICE_ID;
+               devide_id = WLAN_TX_MIQ_DEVICE_ID;
                break;
 
        case 0x1033:
-               devideId = WLAN_TX_LOQ_DEVICE_ID;
+               devide_id = WLAN_TX_LOQ_DEVICE_ID;
                break;
 
        case 0x1034:
-               devideId = WLAN_RX0FF_DEVICE_ID;
+               devide_id = WLAN_RX0FF_DEVICE_ID;
                break;
 
        default:
-/*                     devideId = (u8)((addr >> 13) & 0xF); */
-               devideId = WLAN_IOREG_DEVICE_ID;
+/*                     devide_id = (u8)((addr >> 13) & 0xF); */
+               devide_id = WLAN_IOREG_DEVICE_ID;
                break;
        }
 
-       return devideId;
+       return devide_id;
 }
 
 /*
  * Ref:
  *HalSdioGetCmdAddr8723BSdio()
  */
-static u32 _cvrt2ftaddr(const u32 addr, u8 *pdeviceId, u16 *poffset)
+static u32 _cvrt2ftaddr(const u32 addr, u8 *pdevice_id, u16 *poffset)
 {
-       u8 deviceId;
+       u8 device_id;
        u16 offset;
        u32 ftaddr;
 
 
-       deviceId = get_deviceid(addr);
+       device_id = get_deviceid(addr);
        offset = 0;
 
-       switch (deviceId) {
+       switch (device_id) {
        case SDIO_LOCAL_DEVICE_ID:
                offset = addr & SDIO_LOCAL_MSK;
                break;
@@ -140,47 +140,44 @@ static u32 _cvrt2ftaddr(const u32 addr, u8 *pdeviceId, u16 *poffset)
 
        case WLAN_IOREG_DEVICE_ID:
        default:
-               deviceId = WLAN_IOREG_DEVICE_ID;
+               device_id = WLAN_IOREG_DEVICE_ID;
                offset = addr & WLAN_IOREG_MSK;
                break;
        }
-       ftaddr = (deviceId << 13) | offset;
+       ftaddr = (device_id << 13) | offset;
 
-       if (pdeviceId)
-               *pdeviceId = deviceId;
+       if (pdevice_id)
+               *pdevice_id = device_id;
        if (poffset)
                *poffset = offset;
 
        return ftaddr;
 }
 
-static u8 sdio_read8(struct intf_hdl *pintfhdl, u32 addr)
+static u8 sdio_read8(struct intf_hdl *intfhdl, u32 addr)
 {
        u32 ftaddr;
-       u8 val;
-
        ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
-       val = sd_read8(pintfhdl, ftaddr, NULL);
-       return val;
+
+       return sd_read8(intfhdl, ftaddr, NULL);
 }
 
-static u16 sdio_read16(struct intf_hdl *pintfhdl, u32 addr)
+static u16 sdio_read16(struct intf_hdl *intfhdl, u32 addr)
 {
        u32 ftaddr;
-       u16 val;
        __le16 le_tmp;
 
        ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
-       sd_cmd52_read(pintfhdl, ftaddr, 2, (u8 *)&le_tmp);
-       val = le16_to_cpu(le_tmp);
-       return val;
+       sd_cmd52_read(intfhdl, ftaddr, 2, (u8 *)&le_tmp);
+
+       return le16_to_cpu(le_tmp);
 }
 
-static u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr)
+static u32 sdio_read32(struct intf_hdl *intfhdl, u32 addr)
 {
-       struct adapter *padapter;
-       u8 bMacPwrCtrlOn;
-       u8 deviceId;
+       struct adapter *adapter;
+       u8 mac_pwr_ctrl_on;
+       u8 device_id;
        u16 offset;
        u32 ftaddr;
        u8 shift;
@@ -188,21 +185,20 @@ static u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr)
        s32 err;
        __le32 le_tmp;
 
-       padapter = pintfhdl->padapter;
-       ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
+       adapter = intfhdl->padapter;
+       ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
 
-       rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+       rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
        if (
-               ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
-               (false == bMacPwrCtrlOn) ||
-               (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
+               ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
+               (!mac_pwr_ctrl_on) ||
+               (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
        ) {
-               err = sd_cmd52_read(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
+               err = sd_cmd52_read(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
 #ifdef SDIO_DEBUG_IO
                if (!err) {
 #endif
-                       val = le32_to_cpu(le_tmp);
-                       return val;
+                       return le32_to_cpu(le_tmp);
 #ifdef SDIO_DEBUG_IO
                }
 
@@ -214,191 +210,184 @@ static u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr)
        /*  4 bytes alignment */
        shift = ftaddr & 0x3;
        if (shift == 0) {
-               val = sd_read32(pintfhdl, ftaddr, NULL);
+               val = sd_read32(intfhdl, ftaddr, NULL);
        } else {
-               u8 *ptmpbuf;
+               u8 *tmpbuf;
 
-               ptmpbuf = rtw_malloc(8);
-               if (NULL == ptmpbuf) {
+               tmpbuf = rtw_malloc(8);
+               if (!tmpbuf) {
                        DBG_8192C(KERN_ERR "%s: Allocate memory FAIL!(size =8) addr = 0x%x\n", __func__, addr);
                        return SDIO_ERR_VAL32;
                }
 
                ftaddr &= ~(u16)0x3;
-               sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
-               memcpy(&le_tmp, ptmpbuf+shift, 4);
+               sd_read(intfhdl, ftaddr, 8, tmpbuf);
+               memcpy(&le_tmp, tmpbuf+shift, 4);
                val = le32_to_cpu(le_tmp);
 
-               kfree(ptmpbuf);
+               kfree(tmpbuf);
        }
        return val;
 }
 
-static s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
+static s32 sdio_readN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf)
 {
-       struct adapter *padapter;
-       u8 bMacPwrCtrlOn;
-       u8 deviceId;
+       struct adapter *adapter;
+       u8 mac_pwr_ctrl_on;
+       u8 device_id;
        u16 offset;
        u32 ftaddr;
        u8 shift;
        s32 err;
 
-       padapter = pintfhdl->padapter;
+       adapter = intfhdl->padapter;
        err = 0;
 
-       ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
+       ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
 
-       rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+       rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
        if (
-               ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
-               (false == bMacPwrCtrlOn) ||
-               (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
-       ) {
-               err = sd_cmd52_read(pintfhdl, ftaddr, cnt, pbuf);
-               return err;
-       }
+               ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
+               (!mac_pwr_ctrl_on) ||
+               (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
+       )
+               return sd_cmd52_read(intfhdl, ftaddr, cnt, buf);
 
        /*  4 bytes alignment */
        shift = ftaddr & 0x3;
        if (shift == 0) {
-               err = sd_read(pintfhdl, ftaddr, cnt, pbuf);
+               err = sd_read(intfhdl, ftaddr, cnt, buf);
        } else {
-               u8 *ptmpbuf;
+               u8 *tmpbuf;
                u32 n;
 
                ftaddr &= ~(u16)0x3;
                n = cnt + shift;
-               ptmpbuf = rtw_malloc(n);
-               if (NULL == ptmpbuf)
+               tmpbuf = rtw_malloc(n);
+               if (!tmpbuf)
                        return -1;
 
-               err = sd_read(pintfhdl, ftaddr, n, ptmpbuf);
+               err = sd_read(intfhdl, ftaddr, n, tmpbuf);
                if (!err)
-                       memcpy(pbuf, ptmpbuf+shift, cnt);
-               kfree(ptmpbuf);
+                       memcpy(buf, tmpbuf+shift, cnt);
+               kfree(tmpbuf);
        }
        return err;
 }
 
-static s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
+static s32 sdio_write8(struct intf_hdl *intfhdl, u32 addr, u8 val)
 {
        u32 ftaddr;
        s32 err;
 
        ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
-       sd_write8(pintfhdl, ftaddr, val, &err);
+       sd_write8(intfhdl, ftaddr, val, &err);
 
        return err;
 }
 
-static s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
+static s32 sdio_write16(struct intf_hdl *intfhdl, u32 addr, u16 val)
 {
        u32 ftaddr;
-       s32 err;
        __le16 le_tmp;
 
        ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
        le_tmp = cpu_to_le16(val);
-       err = sd_cmd52_write(pintfhdl, ftaddr, 2, (u8 *)&le_tmp);
-
-       return err;
+       return sd_cmd52_write(intfhdl, ftaddr, 2, (u8 *)&le_tmp);
 }
 
-static s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
+static s32 sdio_write32(struct intf_hdl *intfhdl, u32 addr, u32 val)
 {
-       struct adapter *padapter;
-       u8 bMacPwrCtrlOn;
-       u8 deviceId;
+       struct adapter *adapter;
+       u8 mac_pwr_ctrl_on;
+       u8 device_id;
        u16 offset;
        u32 ftaddr;
        u8 shift;
        s32 err;
        __le32 le_tmp;
 
-       padapter = pintfhdl->padapter;
+       adapter = intfhdl->padapter;
        err = 0;
 
-       ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
+       ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
 
-       rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+       rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
        if (
-               ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
-               (!bMacPwrCtrlOn) ||
-               (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
+               ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
+               (!mac_pwr_ctrl_on) ||
+               (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
        ) {
                le_tmp = cpu_to_le32(val);
-               err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
-               return err;
+
+               return sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
        }
 
        /*  4 bytes alignment */
        shift = ftaddr & 0x3;
        if (shift == 0) {
-               sd_write32(pintfhdl, ftaddr, val, &err);
+               sd_write32(intfhdl, ftaddr, val, &err);
        } else {
                le_tmp = cpu_to_le32(val);
-               err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
+               err = sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
        }
        return err;
 }
 
-static s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
+static s32 sdio_writeN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf)
 {
-       struct adapter *padapter;
-       u8 bMacPwrCtrlOn;
-       u8 deviceId;
+       struct adapter *adapter;
+       u8 mac_pwr_ctrl_on;
+       u8 device_id;
        u16 offset;
        u32 ftaddr;
        u8 shift;
        s32 err;
 
-       padapter = pintfhdl->padapter;
+       adapter = intfhdl->padapter;
        err = 0;
 
-       ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
+       ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
 
-       rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+       rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
        if (
-               ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
-               (false == bMacPwrCtrlOn) ||
-               (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
-       ) {
-               err = sd_cmd52_write(pintfhdl, ftaddr, cnt, pbuf);
-               return err;
-       }
+               ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
+               (!mac_pwr_ctrl_on) ||
+               (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
+       )
+               return sd_cmd52_write(intfhdl, ftaddr, cnt, buf);
 
        shift = ftaddr & 0x3;
        if (shift == 0) {
-               err = sd_write(pintfhdl, ftaddr, cnt, pbuf);
+               err = sd_write(intfhdl, ftaddr, cnt, buf);
        } else {
-               u8 *ptmpbuf;
+               u8 *tmpbuf;
                u32 n;
 
                ftaddr &= ~(u16)0x3;
                n = cnt + shift;
-               ptmpbuf = rtw_malloc(n);
-               if (NULL == ptmpbuf)
+               tmpbuf = rtw_malloc(n);
+               if (!tmpbuf)
                        return -1;
-               err = sd_read(pintfhdl, ftaddr, 4, ptmpbuf);
+               err = sd_read(intfhdl, ftaddr, 4, tmpbuf);
                if (err) {
-                       kfree(ptmpbuf);
+                       kfree(tmpbuf);
                        return err;
                }
-               memcpy(ptmpbuf+shift, pbuf, cnt);
-               err = sd_write(pintfhdl, ftaddr, n, ptmpbuf);
-               kfree(ptmpbuf);
+               memcpy(tmpbuf+shift, buf, cnt);
+               err = sd_write(intfhdl, ftaddr, n, tmpbuf);
+               kfree(tmpbuf);
        }
        return err;
 }
 
-static u8 sdio_f0_read8(struct intf_hdl *pintfhdl, u32 addr)
+static u8 sdio_f0_read8(struct intf_hdl *intfhdl, u32 addr)
 {
-       return sd_f0_read8(pintfhdl, addr, NULL);
+       return sd_f0_read8(intfhdl, addr, NULL);
 }
 
 static void sdio_read_mem(
-       struct intf_hdl *pintfhdl,
+       struct intf_hdl *intfhdl,
        u32 addr,
        u32 cnt,
        u8 *rmem
@@ -406,18 +395,18 @@ static void sdio_read_mem(
 {
        s32 err;
 
-       err = sdio_readN(pintfhdl, addr, cnt, rmem);
+       err = sdio_readN(intfhdl, addr, cnt, rmem);
        /* TODO: Report error is err not zero */
 }
 
 static void sdio_write_mem(
-       struct intf_hdl *pintfhdl,
+       struct intf_hdl *intfhdl,
        u32 addr,
        u32 cnt,
        u8 *wmem
 )
 {
-       sdio_writeN(pintfhdl, addr, cnt, wmem);
+       sdio_writeN(intfhdl, addr, cnt, wmem);
 }
 
 /*
@@ -427,7 +416,7 @@ static void sdio_write_mem(
  *and make sure data transfer will be done in one command.
  *
  * Parameters:
- *pintfhdl     a pointer of intf_hdl
+ *intfhdl      a pointer of intf_hdl
  *addr         port ID
  *cnt                  size to read
  *rmem         address to put data
@@ -437,15 +426,15 @@ static void sdio_write_mem(
  *_FAIL(0)             Fail
  */
 static u32 sdio_read_port(
-       struct intf_hdl *pintfhdl,
+       struct intf_hdl *intfhdl,
        u32 addr,
        u32 cnt,
        u8 *mem
 )
 {
-       struct adapter *padapter;
+       struct adapter *adapter;
        PSDIO_DATA psdio;
-       struct hal_com_data *phal;
+       struct hal_com_data *hal;
        u32 oldcnt;
 #ifdef SDIO_DYNAMIC_ALLOC_MEM
        u8 *oldmem;
@@ -453,33 +442,18 @@ static u32 sdio_read_port(
        s32 err;
 
 
-       padapter = pintfhdl->padapter;
-       psdio = &adapter_to_dvobj(padapter)->intf_data;
-       phal = GET_HAL_DATA(padapter);
+       adapter = intfhdl->padapter;
+       psdio = &adapter_to_dvobj(adapter)->intf_data;
+       hal = GET_HAL_DATA(adapter);
 
-       HalSdioGetCmdAddr8723BSdio(padapter, addr, phal->SdioRxFIFOCnt++, &addr);
+       HalSdioGetCmdAddr8723BSdio(adapter, addr, hal->SdioRxFIFOCnt++, &addr);
 
        oldcnt = cnt;
        if (cnt > psdio->block_transfer_len)
                cnt = _RND(cnt, psdio->block_transfer_len);
 /*     cnt = sdio_align_size(cnt); */
 
-       if (oldcnt != cnt) {
-#ifdef SDIO_DYNAMIC_ALLOC_MEM
-               oldmem = mem;
-               mem = rtw_malloc(cnt);
-               if (mem == NULL) {
-                       DBG_8192C(KERN_WARNING "%s: allocate memory %d bytes fail!\n", __func__, cnt);
-                       mem = oldmem;
-                       oldmem == NULL;
-               }
-#else
-               /*  in this case, caller should gurante the buffer is big enough */
-               /*  to receive data after alignment */
-#endif
-       }
-
-       err = _sd_read(pintfhdl, addr, cnt, mem);
+       err = _sd_read(intfhdl, addr, cnt, mem);
 
 #ifdef SDIO_DYNAMIC_ALLOC_MEM
        if ((oldcnt != cnt) && (oldmem)) {
@@ -500,7 +474,7 @@ static u32 sdio_read_port(
  *and make sure data could be written in one command.
  *
  * Parameters:
- *pintfhdl     a pointer of intf_hdl
+ *intfhdl      a pointer of intf_hdl
  *addr         port ID
  *cnt                  size to write
  *wmem         data pointer to write
@@ -510,33 +484,33 @@ static u32 sdio_read_port(
  *_FAIL(0)             Fail
  */
 static u32 sdio_write_port(
-       struct intf_hdl *pintfhdl,
+       struct intf_hdl *intfhdl,
        u32 addr,
        u32 cnt,
        u8 *mem
 )
 {
-       struct adapter *padapter;
+       struct adapter *adapter;
        PSDIO_DATA psdio;
        s32 err;
        struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
 
-       padapter = pintfhdl->padapter;
-       psdio = &adapter_to_dvobj(padapter)->intf_data;
+       adapter = intfhdl->padapter;
+       psdio = &adapter_to_dvobj(adapter)->intf_data;
 
-       if (padapter->hw_init_completed == false) {
-               DBG_871X("%s [addr = 0x%x cnt =%d] padapter->hw_init_completed == false\n", __func__, addr, cnt);
+       if (!adapter->hw_init_completed) {
+               DBG_871X("%s [addr = 0x%x cnt =%d] adapter->hw_init_completed == false\n", __func__, addr, cnt);
                return _FAIL;
        }
 
        cnt = _RND4(cnt);
-       HalSdioGetCmdAddr8723BSdio(padapter, addr, cnt >> 2, &addr);
+       HalSdioGetCmdAddr8723BSdio(adapter, addr, cnt >> 2, &addr);
 
        if (cnt > psdio->block_transfer_len)
                cnt = _RND(cnt, psdio->block_transfer_len);
 /*     cnt = sdio_align_size(cnt); */
 
-       err = sd_write(pintfhdl, addr, cnt, xmitbuf->pdata);
+       err = sd_write(intfhdl, addr, cnt, xmitbuf->pdata);
 
        rtw_sctx_done_err(
                &xmitbuf->sctx,
@@ -548,61 +522,59 @@ static u32 sdio_write_port(
        return _SUCCESS;
 }
 
-void sdio_set_intf_ops(struct adapter *padapter, struct _io_ops *pops)
+void sdio_set_intf_ops(struct adapter *adapter, struct _io_ops *ops)
 {
-       pops->_read8 = &sdio_read8;
-       pops->_read16 = &sdio_read16;
-       pops->_read32 = &sdio_read32;
-       pops->_read_mem = &sdio_read_mem;
-       pops->_read_port = &sdio_read_port;
-
-       pops->_write8 = &sdio_write8;
-       pops->_write16 = &sdio_write16;
-       pops->_write32 = &sdio_write32;
-       pops->_writeN = &sdio_writeN;
-       pops->_write_mem = &sdio_write_mem;
-       pops->_write_port = &sdio_write_port;
-
-       pops->_sd_f0_read8 = sdio_f0_read8;
+       ops->_read8 = &sdio_read8;
+       ops->_read16 = &sdio_read16;
+       ops->_read32 = &sdio_read32;
+       ops->_read_mem = &sdio_read_mem;
+       ops->_read_port = &sdio_read_port;
+
+       ops->_write8 = &sdio_write8;
+       ops->_write16 = &sdio_write16;
+       ops->_write32 = &sdio_write32;
+       ops->_writeN = &sdio_writeN;
+       ops->_write_mem = &sdio_write_mem;
+       ops->_write_port = &sdio_write_port;
+
+       ops->_sd_f0_read8 = sdio_f0_read8;
 }
 
 /*
  * Todo: align address to 4 bytes.
  */
 static s32 _sdio_local_read(
-       struct adapter *padapter,
+       struct adapter *adapter,
        u32 addr,
        u32 cnt,
-       u8 *pbuf
+       u8 *buf
 )
 {
-       struct intf_hdl *pintfhdl;
-       u8 bMacPwrCtrlOn;
+       struct intf_hdl *intfhdl;
+       u8 mac_pwr_ctrl_on;
        s32 err;
-       u8 *ptmpbuf;
+       u8 *tmpbuf;
        u32 n;
 
 
-       pintfhdl = &padapter->iopriv.intf;
+       intfhdl = &adapter->iopriv.intf;
 
-       HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+       HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
 
-       rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
-       if (false == bMacPwrCtrlOn) {
-               err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
-               return err;
-       }
+       rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+       if (!mac_pwr_ctrl_on)
+               return _sd_cmd52_read(intfhdl, addr, cnt, buf);
 
        n = RND4(cnt);
-       ptmpbuf = rtw_malloc(n);
-       if (!ptmpbuf)
+       tmpbuf = rtw_malloc(n);
+       if (!tmpbuf)
                return (-1);
 
-       err = _sd_read(pintfhdl, addr, n, ptmpbuf);
+       err = _sd_read(intfhdl, addr, n, tmpbuf);
        if (!err)
-               memcpy(pbuf, ptmpbuf, cnt);
+               memcpy(buf, tmpbuf, cnt);
 
-       kfree(ptmpbuf);
+       kfree(tmpbuf);
 
        return err;
 }
@@ -611,41 +583,39 @@ static s32 _sdio_local_read(
  * Todo: align address to 4 bytes.
  */
 s32 sdio_local_read(
-       struct adapter *padapter,
+       struct adapter *adapter,
        u32 addr,
        u32 cnt,
-       u8 *pbuf
+       u8 *buf
 )
 {
-       struct intf_hdl *pintfhdl;
-       u8 bMacPwrCtrlOn;
+       struct intf_hdl *intfhdl;
+       u8 mac_pwr_ctrl_on;
        s32 err;
-       u8 *ptmpbuf;
+       u8 *tmpbuf;
        u32 n;
 
-       pintfhdl = &padapter->iopriv.intf;
+       intfhdl = &adapter->iopriv.intf;
 
-       HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+       HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
 
-       rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+       rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
        if (
-               (false == bMacPwrCtrlOn) ||
-               (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
-       ) {
-               err = sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
-               return err;
-       }
+               (!mac_pwr_ctrl_on) ||
+               (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
+       )
+               return sd_cmd52_read(intfhdl, addr, cnt, buf);
 
        n = RND4(cnt);
-       ptmpbuf = rtw_malloc(n);
-       if (!ptmpbuf)
+       tmpbuf = rtw_malloc(n);
+       if (!tmpbuf)
                return (-1);
 
-       err = sd_read(pintfhdl, addr, n, ptmpbuf);
+       err = sd_read(intfhdl, addr, n, tmpbuf);
        if (!err)
-               memcpy(pbuf, ptmpbuf, cnt);
+               memcpy(buf, tmpbuf, cnt);
 
-       kfree(ptmpbuf);
+       kfree(tmpbuf);
 
        return err;
 }
@@ -654,16 +624,16 @@ s32 sdio_local_read(
  * Todo: align address to 4 bytes.
  */
 s32 sdio_local_write(
-       struct adapter *padapter,
+       struct adapter *adapter,
        u32 addr,
        u32 cnt,
-       u8 *pbuf
+       u8 *buf
 )
 {
-       struct intf_hdl *pintfhdl;
-       u8 bMacPwrCtrlOn;
+       struct intf_hdl *intfhdl;
+       u8 mac_pwr_ctrl_on;
        s32 err;
-       u8 *ptmpbuf;
+       u8 *tmpbuf;
 
        if (addr & 0x3)
                DBG_8192C("%s, address must be 4 bytes alignment\n", __func__);
@@ -671,101 +641,99 @@ s32 sdio_local_write(
        if (cnt  & 0x3)
                DBG_8192C("%s, size must be the multiple of 4\n", __func__);
 
-       pintfhdl = &padapter->iopriv.intf;
+       intfhdl = &adapter->iopriv.intf;
 
-       HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+       HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
 
-       rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+       rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
        if (
-               (false == bMacPwrCtrlOn) ||
-               (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
-       ) {
-               err = sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
-               return err;
-       }
+               (!mac_pwr_ctrl_on) ||
+               (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
+       )
+               return sd_cmd52_write(intfhdl, addr, cnt, buf);
 
-       ptmpbuf = rtw_malloc(cnt);
-       if (!ptmpbuf)
+       tmpbuf = rtw_malloc(cnt);
+       if (!tmpbuf)
                return (-1);
 
-       memcpy(ptmpbuf, pbuf, cnt);
+       memcpy(tmpbuf, buf, cnt);
 
-       err = sd_write(pintfhdl, addr, cnt, ptmpbuf);
+       err = sd_write(intfhdl, addr, cnt, tmpbuf);
 
-       kfree(ptmpbuf);
+       kfree(tmpbuf);
 
        return err;
 }
 
-u8 SdioLocalCmd52Read1Byte(struct adapter *padapter, u32 addr)
+u8 SdioLocalCmd52Read1Byte(struct adapter *adapter, u32 addr)
 {
        u8 val = 0;
-       struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
+       struct intf_hdl *intfhdl = &adapter->iopriv.intf;
 
-       HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
-       sd_cmd52_read(pintfhdl, addr, 1, &val);
+       HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+       sd_cmd52_read(intfhdl, addr, 1, &val);
 
        return val;
 }
 
-static u16 SdioLocalCmd52Read2Byte(struct adapter *padapter, u32 addr)
+static u16 SdioLocalCmd52Read2Byte(struct adapter *adapter, u32 addr)
 {
        __le16 val = 0;
-       struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
+       struct intf_hdl *intfhdl = &adapter->iopriv.intf;
 
-       HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
-       sd_cmd52_read(pintfhdl, addr, 2, (u8 *)&val);
+       HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+       sd_cmd52_read(intfhdl, addr, 2, (u8 *)&val);
 
        return le16_to_cpu(val);
 }
 
-static u32 SdioLocalCmd53Read4Byte(struct adapter *padapter, u32 addr)
+static u32 SdioLocalCmd53Read4Byte(struct adapter *adapter, u32 addr)
 {
 
-       u8 bMacPwrCtrlOn;
+       u8 mac_pwr_ctrl_on;
        u32 val = 0;
-       struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
+       struct intf_hdl *intfhdl = &adapter->iopriv.intf;
        __le32 le_tmp;
 
-       HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
-       rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
-       if (!bMacPwrCtrlOn || adapter_to_pwrctl(padapter)->bFwCurrentInPSMode) {
-               sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&le_tmp);
+       HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+       rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
+       if (!mac_pwr_ctrl_on || adapter_to_pwrctl(adapter)->bFwCurrentInPSMode) {
+               sd_cmd52_read(intfhdl, addr, 4, (u8 *)&le_tmp);
                val = le32_to_cpu(le_tmp);
        } else {
-               val = sd_read32(pintfhdl, addr, NULL);
+               val = sd_read32(intfhdl, addr, NULL);
        }
        return val;
 }
 
-void SdioLocalCmd52Write1Byte(struct adapter *padapter, u32 addr, u8 v)
+void SdioLocalCmd52Write1Byte(struct adapter *adapter, u32 addr, u8 v)
 {
-       struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
+       struct intf_hdl *intfhdl = &adapter->iopriv.intf;
 
-       HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
-       sd_cmd52_write(pintfhdl, addr, 1, &v);
+       HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+       sd_cmd52_write(intfhdl, addr, 1, &v);
 }
 
-static void SdioLocalCmd52Write4Byte(struct adapter *padapter, u32 addr, u32 v)
+static void SdioLocalCmd52Write4Byte(struct adapter *adapter, u32 addr, u32 v)
 {
-       struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
+       struct intf_hdl *intfhdl = &adapter->iopriv.intf;
        __le32 le_tmp;
 
-       HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
+       HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
        le_tmp = cpu_to_le32(v);
-       sd_cmd52_write(pintfhdl, addr, 4, (u8 *)&le_tmp);
+       sd_cmd52_write(intfhdl, addr, 4, (u8 *)&le_tmp);
 }
 
-static s32 ReadInterrupt8723BSdio(struct adapter *padapter, u32 *phisr)
+static s32 ReadInterrupt8723BSdio(struct adapter *adapter, u32 *phisr)
 {
        u32 hisr, himr;
        u8 val8, hisr_len;
 
 
-       if (phisr == NULL)
+       if (!phisr)
                return false;
 
-       himr = GET_HAL_DATA(padapter)->sdio_himr;
+       himr = GET_HAL_DATA(adapter)->sdio_himr;
 
        /*  decide how many bytes need to be read */
        hisr_len = 0;
@@ -777,7 +745,7 @@ static s32 ReadInterrupt8723BSdio(struct adapter *padapter, u32 *phisr)
        hisr = 0;
        while (hisr_len != 0) {
                hisr_len--;
-               val8 = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR+hisr_len);
+               val8 = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HISR+hisr_len);
                hisr |= (val8 << (8*hisr_len));
        }
 
@@ -795,13 +763,13 @@ static s32 ReadInterrupt8723BSdio(struct adapter *padapter, u32 *phisr)
 /*  */
 /*     Created by Roger, 2011.02.11. */
 /*  */
-void InitInterrupt8723BSdio(struct adapter *padapter)
+void InitInterrupt8723BSdio(struct adapter *adapter)
 {
-       struct hal_com_data *pHalData;
+       struct hal_com_data *haldata;
 
 
-       pHalData = GET_HAL_DATA(padapter);
-       pHalData->sdio_himr = (u32)(            \
+       haldata = GET_HAL_DATA(adapter);
+       haldata->sdio_himr = (u32)(             \
                                                                SDIO_HIMR_RX_REQUEST_MSK                        |
                                                                SDIO_HIMR_AVAL_MSK                                      |
 /*                                                             SDIO_HIMR_TXERR_MSK                             | */
@@ -829,14 +797,14 @@ void InitInterrupt8723BSdio(struct adapter *padapter)
 /*  */
 /*     Created by Roger, 2011.08.03. */
 /*  */
-void InitSysInterrupt8723BSdio(struct adapter *padapter)
+void InitSysInterrupt8723BSdio(struct adapter *adapter)
 {
-       struct hal_com_data *pHalData;
+       struct hal_com_data *haldata;
 
 
-       pHalData = GET_HAL_DATA(padapter);
+       haldata = GET_HAL_DATA(adapter);
 
-       pHalData->SysIntrMask = (               \
+       haldata->SysIntrMask = (                \
 /*                                                     HSIMR_GPIO12_0_INT_EN                   | */
 /*                                                     HSIMR_SPS_OCP_INT_EN                    | */
 /*                                                     HSIMR_RON_INT_EN                                | */
@@ -855,20 +823,19 @@ void InitSysInterrupt8723BSdio(struct adapter *padapter)
 /*  */
 /*     Created by Roger, 2011.02.11. */
 /*  */
-void ClearInterrupt8723BSdio(struct adapter *padapter)
+void clearinterrupt8723bsdio(struct adapter *adapter)
 {
-       struct hal_com_data *pHalData;
+       struct hal_com_data *haldata;
        u8 *clear;
 
-
-       if (true == padapter->bSurpriseRemoved)
+       if (adapter->bSurpriseRemoved)
                return;
 
-       pHalData = GET_HAL_DATA(padapter);
+       haldata = GET_HAL_DATA(adapter);
        clear = rtw_zmalloc(4);
 
        /*  Clear corresponding HISR Content if needed */
-       *(__le32 *)clear = cpu_to_le32(pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR);
+       *(__le32 *)clear = cpu_to_le32(haldata->sdio_hisr & MASK_SDIO_HISR_CLEAR);
        if (*(__le32 *)clear) {
                /*  Perform write one clear operation */
                sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
@@ -888,16 +855,16 @@ void ClearInterrupt8723BSdio(struct adapter *padapter)
 /*  */
 /*     Created by Roger, 2011.02.11. */
 /*  */
-void EnableInterrupt8723BSdio(struct adapter *padapter)
+void EnableInterrupt8723BSdio(struct adapter *adapter)
 {
-       struct hal_com_data *pHalData;
+       struct hal_com_data *haldata;
        __le32 himr;
        u32 tmp;
 
-       pHalData = GET_HAL_DATA(padapter);
+       haldata = GET_HAL_DATA(adapter);
 
-       himr = cpu_to_le32(pHalData->sdio_himr);
-       sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
+       himr = cpu_to_le32(haldata->sdio_himr);
+       sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
 
        RT_TRACE(
                _module_hci_ops_c_,
@@ -905,13 +872,13 @@ void EnableInterrupt8723BSdio(struct adapter *padapter)
                (
                        "%s: enable SDIO HIMR = 0x%08X\n",
                        __func__,
-                       pHalData->sdio_himr
+                       haldata->sdio_himr
                )
        );
 
        /*  Update current system IMR settings */
-       tmp = rtw_read32(padapter, REG_HSIMR);
-       rtw_write32(padapter, REG_HSIMR, tmp | pHalData->SysIntrMask);
+       tmp = rtw_read32(adapter, REG_HSIMR);
+       rtw_write32(adapter, REG_HSIMR, tmp | haldata->SysIntrMask);
 
        RT_TRACE(
                _module_hci_ops_c_,
@@ -919,7 +886,7 @@ void EnableInterrupt8723BSdio(struct adapter *padapter)
                (
                        "%s: enable HSIMR = 0x%08X\n",
                        __func__,
-                       pHalData->SysIntrMask
+                       haldata->SysIntrMask
                )
        );
 
@@ -928,7 +895,7 @@ void EnableInterrupt8723BSdio(struct adapter *padapter)
        /*  So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
        /*  2011.10.19. */
        /*  */
-       rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
+       rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
 }
 
 /*  */
@@ -940,12 +907,12 @@ void EnableInterrupt8723BSdio(struct adapter *padapter)
 /*  */
 /*     Created by Roger, 2011.02.11. */
 /*  */
-void DisableInterrupt8723BSdio(struct adapter *padapter)
+void DisableInterrupt8723BSdio(struct adapter *adapter)
 {
        __le32 himr;
 
        himr = cpu_to_le32(SDIO_HIMR_DISABLED);
-       sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
+       sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
 }
 
 /*  */
@@ -957,27 +924,27 @@ void DisableInterrupt8723BSdio(struct adapter *padapter)
 /*  */
 /*     Created by Isaac, 2013.09.10. */
 /*  */
-u8 CheckIPSStatus(struct adapter *padapter)
+u8 CheckIPSStatus(struct adapter *adapter)
 {
        DBG_871X(
                "%s(): Read 0x100 = 0x%02x 0x86 = 0x%02x\n",
                __func__,
-               rtw_read8(padapter, 0x100),
-               rtw_read8(padapter, 0x86)
+               rtw_read8(adapter, 0x100),
+               rtw_read8(adapter, 0x86)
        );
 
-       if (rtw_read8(padapter, 0x100) == 0xEA)
+       if (rtw_read8(adapter, 0x100) == 0xEA)
                return true;
        else
                return false;
 }
 
-static struct recv_buf *sd_recv_rxfifo(struct adapter *padapter, u32 size)
+static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size)
 {
        u32 readsize, ret;
-       u8 *preadbuf;
-       struct recv_priv *precvpriv;
-       struct recv_buf *precvbuf;
+       u8 *readbuf;
+       struct recv_priv *recv_priv;
+       struct recv_buf *recvbuf;
 
 
        /*  Patch for some SDIO Host 4 bytes issue */
@@ -985,37 +952,37 @@ static struct recv_buf *sd_recv_rxfifo(struct adapter *padapter, u32 size)
        readsize = RND4(size);
 
        /* 3 1. alloc recvbuf */
-       precvpriv = &padapter->recvpriv;
-       precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
-       if (precvbuf == NULL) {
+       recv_priv = &adapter->recvpriv;
+       recvbuf = rtw_dequeue_recvbuf(&recv_priv->free_recv_buf_queue);
+       if (!recvbuf) {
                DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__);
                return NULL;
        }
 
        /* 3 2. alloc skb */
-       if (precvbuf->pskb == NULL) {
+       if (!recvbuf->pskb) {
                SIZE_PTR tmpaddr = 0;
                SIZE_PTR alignment = 0;
 
-               precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
+               recvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
 
-               if (precvbuf->pskb) {
-                       precvbuf->pskb->dev = padapter->pnetdev;
+               if (recvbuf->pskb) {
+                       recvbuf->pskb->dev = adapter->pnetdev;
 
-                       tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
+                       tmpaddr = (SIZE_PTR)recvbuf->pskb->data;
                        alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
-                       skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
+                       skb_reserve(recvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
                }
 
-               if (precvbuf->pskb == NULL) {
+               if (!recvbuf->pskb) {
                        DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, readsize);
                        return NULL;
                }
        }
 
        /* 3 3. read data from rxfifo */
-       preadbuf = precvbuf->pskb->data;
-       ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
+       readbuf = recvbuf->pskb->data;
+       ret = sdio_read_port(&adapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, readbuf);
        if (ret == _FAIL) {
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __func__));
                return NULL;
@@ -1023,72 +990,72 @@ static struct recv_buf *sd_recv_rxfifo(struct adapter *padapter, u32 size)
 
 
        /* 3 4. init recvbuf */
-       precvbuf->len = size;
-       precvbuf->phead = precvbuf->pskb->head;
-       precvbuf->pdata = precvbuf->pskb->data;
-       skb_set_tail_pointer(precvbuf->pskb, size);
-       precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
-       precvbuf->pend = skb_end_pointer(precvbuf->pskb);
-
-       return precvbuf;
+       recvbuf->len = size;
+       recvbuf->phead = recvbuf->pskb->head;
+       recvbuf->pdata = recvbuf->pskb->data;
+       skb_set_tail_pointer(recvbuf->pskb, size);
+       recvbuf->ptail = skb_tail_pointer(recvbuf->pskb);
+       recvbuf->pend = skb_end_pointer(recvbuf->pskb);
+
+       return recvbuf;
 }
 
-static void sd_rxhandler(struct adapter *padapter, struct recv_buf *precvbuf)
+static void sd_rxhandler(struct adapter *adapter, struct recv_buf *recvbuf)
 {
-       struct recv_priv *precvpriv;
-       struct __queue *ppending_queue;
+       struct recv_priv *recv_priv;
+       struct __queue *pending_queue;
 
-       precvpriv = &padapter->recvpriv;
-       ppending_queue = &precvpriv->recv_buf_pending_queue;
+       recv_priv = &adapter->recvpriv;
+       pending_queue = &recv_priv->recv_buf_pending_queue;
 
        /* 3 1. enqueue recvbuf */
-       rtw_enqueue_recvbuf(precvbuf, ppending_queue);
+       rtw_enqueue_recvbuf(recvbuf, pending_queue);
 
        /* 3 2. schedule tasklet */
-       tasklet_schedule(&precvpriv->recv_tasklet);
+       tasklet_schedule(&recv_priv->recv_tasklet);
 }
 
-void sd_int_dpc(struct adapter *padapter)
+void sd_int_dpc(struct adapter *adapter)
 {
-       struct hal_com_data *phal;
+       struct hal_com_data *hal;
        struct dvobj_priv *dvobj;
-       struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
+       struct intf_hdl *intfhdl = &adapter->iopriv.intf;
        struct pwrctrl_priv *pwrctl;
 
 
-       phal = GET_HAL_DATA(padapter);
-       dvobj = adapter_to_dvobj(padapter);
+       hal = GET_HAL_DATA(adapter);
+       dvobj = adapter_to_dvobj(adapter);
        pwrctl = dvobj_to_pwrctl(dvobj);
 
-       if (phal->sdio_hisr & SDIO_HISR_AVAL) {
+       if (hal->sdio_hisr & SDIO_HISR_AVAL) {
                u8 freepage[4];
 
-               _sdio_local_read(padapter, SDIO_REG_FREE_TXPG, 4, freepage);
-               up(&(padapter->xmitpriv.xmit_sema));
+               _sdio_local_read(adapter, SDIO_REG_FREE_TXPG, 4, freepage);
+               up(&(adapter->xmitpriv.xmit_sema));
        }
 
-       if (phal->sdio_hisr & SDIO_HISR_CPWM1) {
+       if (hal->sdio_hisr & SDIO_HISR_CPWM1) {
                struct reportpwrstate_parm report;
 
                u8 bcancelled;
                _cancel_timer(&(pwrctl->pwr_rpwm_timer), &bcancelled);
 
-               report.state = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HCPWM1_8723B);
+               report.state = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HCPWM1_8723B);
 
-               /* cpwm_int_hdl(padapter, &report); */
+               /* cpwm_int_hdl(adapter, &report); */
                _set_workitem(&(pwrctl->cpwm_event));
        }
 
-       if (phal->sdio_hisr & SDIO_HISR_TXERR) {
+       if (hal->sdio_hisr & SDIO_HISR_TXERR) {
                u8 *status;
                u32 addr;
 
                status = rtw_malloc(4);
                if (status) {
                        addr = REG_TXDMA_STATUS;
-                       HalSdioGetCmdAddr8723BSdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
-                       _sd_read(pintfhdl, addr, 4, status);
-                       _sd_write(pintfhdl, addr, 4, status);
+                       HalSdioGetCmdAddr8723BSdio(adapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
+                       _sd_read(intfhdl, addr, 4, status);
+                       _sd_write(intfhdl, addr, 4, status);
                        DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32 *)status));
                        kfree(status);
                } else {
@@ -1096,71 +1063,71 @@ void sd_int_dpc(struct adapter *padapter)
                }
        }
 
-       if (phal->sdio_hisr & SDIO_HISR_TXBCNOK) {
+       if (hal->sdio_hisr & SDIO_HISR_TXBCNOK) {
                DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__);
        }
 
-       if (phal->sdio_hisr & SDIO_HISR_TXBCNERR) {
+       if (hal->sdio_hisr & SDIO_HISR_TXBCNERR) {
                DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__);
        }
 #ifndef CONFIG_C2H_PACKET_EN
-       if (phal->sdio_hisr & SDIO_HISR_C2HCMD) {
+       if (hal->sdio_hisr & SDIO_HISR_C2HCMD) {
                struct c2h_evt_hdr_88xx *c2h_evt;
 
                DBG_8192C("%s: C2H Command\n", __func__);
                c2h_evt = rtw_zmalloc(16);
                if (c2h_evt != NULL) {
-                       if (rtw_hal_c2h_evt_read(padapter, (u8 *)c2h_evt) == _SUCCESS) {
+                       if (rtw_hal_c2h_evt_read(adapter, (u8 *)c2h_evt) == _SUCCESS) {
                                if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) {
                                        /* Handle CCX report here */
-                                       rtw_hal_c2h_handler(padapter, (u8 *)c2h_evt);
+                                       rtw_hal_c2h_handler(adapter, (u8 *)c2h_evt);
                                        kfree((u8 *)c2h_evt);
                                } else {
-                                       rtw_c2h_wk_cmd(padapter, (u8 *)c2h_evt);
+                                       rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
                                }
                        }
                } else {
                        /* Error handling for malloc fail */
-                       if (rtw_cbuf_push(padapter->evtpriv.c2h_queue, NULL) != _SUCCESS)
+                       if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, NULL) != _SUCCESS)
                                DBG_871X("%s rtw_cbuf_push fail\n", __func__);
-                       _set_workitem(&padapter->evtpriv.c2h_wk);
+                       _set_workitem(&adapter->evtpriv.c2h_wk);
                }
        }
 #endif
 
-       if (phal->sdio_hisr & SDIO_HISR_RXFOVW) {
+       if (hal->sdio_hisr & SDIO_HISR_RXFOVW) {
                DBG_8192C("%s: Rx Overflow\n", __func__);
        }
 
-       if (phal->sdio_hisr & SDIO_HISR_RXERR) {
+       if (hal->sdio_hisr & SDIO_HISR_RXERR) {
                DBG_8192C("%s: Rx Error\n", __func__);
        }
 
-       if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
-               struct recv_buf *precvbuf;
+       if (hal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
+               struct recv_buf *recvbuf;
                int alloc_fail_time = 0;
                u32 hisr;
 
-/*             DBG_8192C("%s: RX Request, size =%d\n", __func__, phal->SdioRxFIFOSize); */
-               phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
+/*             DBG_8192C("%s: RX Request, size =%d\n", __func__, hal->SdioRxFIFOSize); */
+               hal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
                do {
-                       phal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(padapter, SDIO_REG_RX0_REQ_LEN);
-                       if (phal->SdioRxFIFOSize != 0) {
-                               precvbuf = sd_recv_rxfifo(padapter, phal->SdioRxFIFOSize);
-                               if (precvbuf)
-                                       sd_rxhandler(padapter, precvbuf);
+                       hal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(adapter, SDIO_REG_RX0_REQ_LEN);
+                       if (hal->SdioRxFIFOSize != 0) {
+                               recvbuf = sd_recv_rxfifo(adapter, hal->SdioRxFIFOSize);
+                               if (recvbuf)
+                                       sd_rxhandler(adapter, recvbuf);
                                else {
                                        alloc_fail_time++;
-                                       DBG_871X("precvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time);
+                                       DBG_871X("recvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time);
                                        if (alloc_fail_time >= 10)
                                                break;
                                }
-                               phal->SdioRxFIFOSize = 0;
+                               hal->SdioRxFIFOSize = 0;
                        } else
                                break;
 
                        hisr = 0;
-                       ReadInterrupt8723BSdio(padapter, &hisr);
+                       ReadInterrupt8723BSdio(adapter, &hisr);
                        hisr &= SDIO_HISR_RX_REQUEST;
                        if (!hisr)
                                break;
@@ -1172,38 +1139,37 @@ void sd_int_dpc(struct adapter *padapter)
        }
 }
 
-void sd_int_hdl(struct adapter *padapter)
+void sd_int_hdl(struct adapter *adapter)
 {
-       struct hal_com_data *phal;
+       struct hal_com_data *hal;
 
 
        if (
-               (padapter->bDriverStopped == true) ||
-               (padapter->bSurpriseRemoved == true)
+               (adapter->bDriverStopped) || (adapter->bSurpriseRemoved)
        )
                return;
 
-       phal = GET_HAL_DATA(padapter);
+       hal = GET_HAL_DATA(adapter);
 
-       phal->sdio_hisr = 0;
-       ReadInterrupt8723BSdio(padapter, &phal->sdio_hisr);
+       hal->sdio_hisr = 0;
+       ReadInterrupt8723BSdio(adapter, &hal->sdio_hisr);
 
-       if (phal->sdio_hisr & phal->sdio_himr) {
+       if (hal->sdio_hisr & hal->sdio_himr) {
                u32 v32;
 
-               phal->sdio_hisr &= phal->sdio_himr;
+               hal->sdio_hisr &= hal->sdio_himr;
 
                /*  clear HISR */
-               v32 = phal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
+               v32 = hal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
                if (v32) {
-                       SdioLocalCmd52Write4Byte(padapter, SDIO_REG_HISR, v32);
+                       SdioLocalCmd52Write4Byte(adapter, SDIO_REG_HISR, v32);
                }
 
-               sd_int_dpc(padapter);
+               sd_int_dpc(adapter);
        } else {
                RT_TRACE(_module_hci_ops_c_, _drv_err_,
                                ("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n",
-                               __func__, phal->sdio_hisr, phal->sdio_himr));
+                               __func__, hal->sdio_hisr, hal->sdio_himr));
        }
 }
 
@@ -1217,27 +1183,27 @@ void sd_int_hdl(struct adapter *padapter)
 /*  */
 /*     Created by Roger, 2011.01.28. */
 /*  */
-u8 HalQueryTxBufferStatus8723BSdio(struct adapter *padapter)
+u8 HalQueryTxBufferStatus8723BSdio(struct adapter *adapter)
 {
-       struct hal_com_data *phal;
-       u32 NumOfFreePage;
-       /* _irqL irql; */
+       struct hal_com_data *hal;
+       u32 numof_free_page;
+       /* _irql irql; */
 
 
-       phal = GET_HAL_DATA(padapter);
+       hal = GET_HAL_DATA(adapter);
 
-       NumOfFreePage = SdioLocalCmd53Read4Byte(padapter, SDIO_REG_FREE_TXPG);
+       numof_free_page = SdioLocalCmd53Read4Byte(adapter, SDIO_REG_FREE_TXPG);
 
        /* spin_lock_bh(&phal->SdioTxFIFOFreePageLock); */
-       memcpy(phal->SdioTxFIFOFreePage, &NumOfFreePage, 4);
+       memcpy(hal->SdioTxFIFOFreePage, &numof_free_page, 4);
        RT_TRACE(_module_hci_ops_c_, _drv_notice_,
                        ("%s: Free page for HIQ(%#x), MIDQ(%#x), LOWQ(%#x), PUBQ(%#x)\n",
                        __func__,
-                       phal->SdioTxFIFOFreePage[HI_QUEUE_IDX],
-                       phal->SdioTxFIFOFreePage[MID_QUEUE_IDX],
-                       phal->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
-                       phal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
-       /* spin_unlock_bh(&phal->SdioTxFIFOFreePageLock); */
+                       hal->SdioTxFIFOFreePage[HI_QUEUE_IDX],
+                       hal->SdioTxFIFOFreePage[MID_QUEUE_IDX],
+                       hal->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
+                       hal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
+       /* spin_unlock_bh(&hal->SdioTxFIFOFreePageLock); */
 
        return true;
 }
@@ -1246,19 +1212,19 @@ u8 HalQueryTxBufferStatus8723BSdio(struct adapter *padapter)
 /*     Description: */
 /*             Query SDIO Local register to get the current number of TX OQT Free Space. */
 /*  */
-u8 HalQueryTxOQTBufferStatus8723BSdio(struct adapter *padapter)
+u8 HalQueryTxOQTBufferStatus8723BSdio(struct adapter *adapter)
 {
-       struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
+       struct hal_com_data *haldata = GET_HAL_DATA(adapter);
 
-       pHalData->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_OQT_FREE_PG);
+       haldata->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_OQT_FREE_PG);
        return true;
 }
 
 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
-u8 RecvOnePkt(struct adapter *padapter, u32 size)
+u8 RecvOnePkt(struct adapter *adapter, u32 size)
 {
-       struct recv_buf *precvbuf;
-       struct dvobj_priv *psddev;
+       struct recv_buf *recvbuf;
+       struct dvobj_priv *sddev;
        PSDIO_DATA psdio_data;
        struct sdio_func *func;
 
@@ -1266,22 +1232,22 @@ u8 RecvOnePkt(struct adapter *padapter, u32 size)
 
        DBG_871X("+%s: size: %d+\n", __func__, size);
 
-       if (padapter == NULL) {
-               DBG_871X(KERN_ERR "%s: padapter is NULL!\n", __func__);
+       if (!adapter) {
+               DBG_871X(KERN_ERR "%s: adapter is NULL!\n", __func__);
                return false;
        }
 
-       psddev = adapter_to_dvobj(padapter);
-       psdio_data = &psddev->intf_data;
+       sddev = adapter_to_dvobj(adapter);
+       psdio_data = &sddev->intf_data;
        func = psdio_data->func;
 
        if (size) {
                sdio_claim_host(func);
-               precvbuf = sd_recv_rxfifo(padapter, size);
+               recvbuf = sd_recv_rxfifo(adapter, size);
 
-               if (precvbuf) {
+               if (recvbuf) {
                        /* printk("Completed Recv One Pkt.\n"); */
-                       sd_rxhandler(padapter, precvbuf);
+                       sd_rxhandler(adapter, recvbuf);
                        res = true;
                } else {
                        res = false;
index 3fca0c2d4c8da0d5d22b1cb5be5dd962e53d8841..cc18d0ad7d7b32ea2eab4bc2c04596e58f436161 100644 (file)
@@ -371,7 +371,7 @@ static char *translate_scan(struct adapter *padapter,
                u8 *wpsie_ptr = NULL;
                uint wps_ielen = 0;
 
-               u8 *ie_ptr = pnetwork->network.IEs + ie_offset;
+               u8 *ie_ptr;
                total_ielen = pnetwork->network.IELength - ie_offset;
 
                if (pnetwork->network.Reserved[0] == 2) { /*  Probe Request */
@@ -967,7 +967,7 @@ static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
                        break;
 
                default :
-                       ret = -EINVAL;;
+                       ret = -EINVAL;
                        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported \n", iw_operation_mode[wrqu->mode]));
                        goto exit;
        }
index cb3a29ae764b44a90a8a28b0562689d7f12b8eb5..b6b03950987bd163de922343da6b077ffa455baa 100644 (file)
@@ -6,16 +6,6 @@ config R8822BE
        This is the staging driver for Realtek RTL8822BE 802.11ac PCIe
        wireless network adapters.
 
-config RTLHALMAC_ST
-       tristate
-       depends on R8822BE
-       default m
-
-config RTLPHYDM_ST
-       tristate
-       depends on R8822BE
-       default m
-
 config RTLWIFI_DEBUG_ST
        boolean
        depends on R8822BE
index 52620b72cfa9098e87ca9195112284fb536ae60f..493011a54e644a9ce634aff0e551e4eac2700368 100644 (file)
@@ -800,7 +800,7 @@ static void halbtc_display_wifi_status(struct btc_coexist *btcoexist,
        u32 wifi_link_status = 0x0;
        bool bt_hs_on = false, under_ips = false, under_lps = false;
        bool low_power = false, dc_mode = false;
-       u8 wifi_chnl = 0, wifi_hs_chnl = 0, fw_ps_state;
+       u8 wifi_chnl = 0, wifi_hs_chnl = 0;
        u8 ap_num = 0;
 
        wifi_link_status = halbtc_get_wifi_link_status(btcoexist);
@@ -856,7 +856,6 @@ static void halbtc_display_wifi_status(struct btc_coexist *btcoexist,
        dc_mode = true; /*TODO*/
        under_ips = rtlpriv->psc.inactive_pwrstate == ERFOFF ? 1 : 0;
        under_lps = rtlpriv->psc.dot11_psmode == EACTIVE ? 0 : 1;
-       fw_ps_state = 0;
        low_power = 0; /*TODO*/
        seq_printf(m, "\n %-35s = %s%s%s%s",
                   "Power Status",
@@ -1644,26 +1643,9 @@ void exhalbtc_rf_status_notify(struct btc_coexist *btcoexist, u8 type)
 
 void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type)
 {
-       u8 stack_op_type;
-
        if (!halbtc_is_bt_coexist_available(btcoexist))
                return;
        btcoexist->statistics.cnt_stack_operation_notify++;
-       if (btcoexist->manual_control)
-               return;
-
-       if ((type == HCI_BT_OP_INQUIRY_START) ||
-           (type == HCI_BT_OP_PAGING_START) ||
-           (type == HCI_BT_OP_PAIRING_START)) {
-               stack_op_type = BTC_STACK_OP_INQ_PAGE_PAIR_START;
-       } else if ((type == HCI_BT_OP_INQUIRY_FINISH) ||
-                  (type == HCI_BT_OP_PAGING_SUCCESS) ||
-                  (type == HCI_BT_OP_PAGING_UNSUCCESS) ||
-                  (type == HCI_BT_OP_PAIRING_FINISH)) {
-               stack_op_type = BTC_STACK_OP_INQ_PAGE_PAIR_FINISH;
-       } else {
-               stack_op_type = BTC_STACK_OP_NONE;
-       }
 }
 
 void exhalbtc_halt_notify(struct btc_coexist *btcoexist)
index 9c8c907cb48e19b6198ea3876634fcc59b3e987d..ca1c9e36d97679dcd8f5dede19c5fa552eb79461 100644 (file)
@@ -181,7 +181,7 @@ void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index)
 
        u32 ul_command;
        u32 ul_content;
-       u32 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
+       u32 ul_enc_algo;
 
        switch (rtlpriv->sec.pairwise_enc_algorithm) {
        case WEP40_ENCRYPTION:
@@ -221,7 +221,7 @@ void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index)
 
        u32 ul_command;
        u32 ul_content;
-       u32 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
+       u32 ul_encalgo;
        u8 entry_i;
 
        switch (rtlpriv->sec.pairwise_enc_algorithm) {
index b00e51df984f343c7dab9062804ff29248fdd727..3ec0394982081ddc954c5b7aab7632268885fe81 100644 (file)
@@ -509,15 +509,13 @@ static int rtl_op_suspend(struct ieee80211_hw *hw,
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-       struct timeval ts;
 
        RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n");
        if (WARN_ON(!wow))
                return -EINVAL;
 
        /* to resolve s4 can not wake up*/
-       do_gettimeofday(&ts);
-       rtlhal->last_suspend_sec = ts.tv_sec;
+       rtlhal->last_suspend_sec = ktime_get_real_seconds();
 
        if ((ppsc->wo_wlan_mode & WAKE_ON_PATTERN_MATCH) && wow->n_patterns)
                _rtl_add_wowlan_patterns(hw, wow);
@@ -536,7 +534,6 @@ static int rtl_op_resume(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-       struct timeval ts;
 
        RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n");
        rtlhal->driver_is_goingto_unload = false;
@@ -544,8 +541,7 @@ static int rtl_op_resume(struct ieee80211_hw *hw)
        rtlhal->wake_from_pnp_sleep = true;
 
        /* to resovle s4 can not wake up*/
-       do_gettimeofday(&ts);
-       if (ts.tv_sec - rtlhal->last_suspend_sec < 5)
+       if (ktime_get_real_seconds() - rtlhal->last_suspend_sec < 5)
                return -1;
 
        rtl_op_start(hw);
@@ -1820,7 +1816,7 @@ bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
                              u8 faversion, u8 interface_type,
                              struct wlan_pwr_cfg pwrcfgcmd[])
 {
-       struct wlan_pwr_cfg cfg_cmd = {0};
+       struct wlan_pwr_cfg cfg_cmd;
        bool polling_bit = false;
        u32 ary_idx = 0;
        u8 value = 0;
index f45487122517451849c0c8a222e7369f295fca13..483ea85943c3d9406df6fada1219823585d3f596 100644 (file)
@@ -464,6 +464,8 @@ bool rtl8822b_halmac_cb_write_data_rsvd_page(struct rtl_priv *rtlpriv, u8 *buf,
        int count;
 
        skb = dev_alloc_skb(size);
+       if (!skb)
+               return false;
        memcpy((u8 *)skb_put(skb, size), buf, size);
 
        if (!_rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, BEACON_QUEUE))
index eb91c130b245cbf766d5d6e78c625a9216ac0891..ca0243fa2e664da19f776ef09b2698c2a16d94af 100644 (file)
@@ -1670,7 +1670,7 @@ struct rtl_hal {
        bool enter_pnp_sleep;
        bool wake_from_pnp_sleep;
        bool wow_enabled;
-       __kernel_time_t last_suspend_sec;
+       time64_t last_suspend_sec;
        u32 wowlan_fwsize;
        u8 *wowlan_firmware;
 
index 7cdce87f3051e1052f69c61a7a2db73c63714766..821256b95e2279068ce8dad366a277645bcc8798 100644 (file)
@@ -2821,6 +2821,7 @@ BUILD_FAIL:
 int reset_ms_card(struct rtsx_chip *chip)
 {
        struct ms_info *ms_card = &chip->ms_card;
+       int seg_no = ms_card->total_block / 512 - 1;
        int retval;
 
        memset(ms_card, 0, sizeof(struct ms_info));
@@ -2863,7 +2864,7 @@ int reset_ms_card(struct rtsx_chip *chip)
                /* Build table for the last segment,
                 * to check if L2P table block exists, erasing it
                 */
-               retval = ms_build_l2p_tbl(chip, ms_card->total_block / 512 - 1);
+               retval = ms_build_l2p_tbl(chip, seg_no);
                if (retval != STATUS_SUCCESS) {
                        rtsx_trace(chip);
                        return STATUS_FAIL;
index 89e2cfe7d1cc0ffdef1334ca73a59729ca69f70b..70e0b86231109d48554a51cbfbc465be382ceb3f 100644 (file)
@@ -275,23 +275,6 @@ static int rtsx_acquire_irq(struct rtsx_dev *dev)
        return 0;
 }
 
-int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val)
-{
-       struct pci_dev *pdev;
-       u8 data;
-       u8 devfn = (dev << 3) | func;
-
-       pdev = pci_get_bus_and_slot(bus, devfn);
-       if (!pdev)
-               return -1;
-
-       pci_read_config_byte(pdev, offset, &data);
-       if (val)
-               *val = data;
-
-       return 0;
-}
-
 #ifdef CONFIG_PM
 /*
  * power management
index 575e5734f2a5ca61e2313871103fa51d36b7b93f..62e467c5a6d777b843d00a6251bf4c2e6307bb27 100644 (file)
@@ -174,8 +174,6 @@ static inline void get_current_time(u8 *timeval_buf, int buf_len)
 /* struct scsi_cmnd transfer buffer access utilities */
 enum xfer_buf_dir      {TO_XFER_BUF, FROM_XFER_BUF};
 
-int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val);
-
 #define _MSG_TRACE
 
 #include "trace.h"
index 55764e16b93a9f1f2ba1e4018d34def2272e746d..900be444acf9a8a4f2ecc114a959cd72849f5b32 100644 (file)
 #define        SUPPORT_MAX_POWER_PERMANCE              0x10000000
 #define        SUPPORT_1V8                             0x01000000
 
-#define        SWTICH_NO_ERR           0x00
+#define        SWITCH_NO_ERR           0x00
 #define        CARD_NOT_EXIST          0x01
 #define        SPEC_NOT_SUPPORT        0x02
 #define        CHECK_MODE_ERR          0x03
index a3a877d90066f90a6c36f50a4c6b8c876030a432..f710ab15abfec7b82e190dcca71eb2fe47b1a56c 100644 (file)
@@ -6,8 +6,8 @@ TODO:
 - check on hardware effects of removal of USE_HW_I2C and USE_DVICHIP (these two
        are supposed to be sample code which is given here if someone wants to
        use those functionalities)
-- move it to drivers/video/fbdev
-- modify the code for drm framework
+- must be ported to the atomic kms framework in the drm subsystem (which will
+  give you a basic fbdev driver for free)
 
 Please send any patches to
        Greg Kroah-Hartman <greg@kroah.com>
index c787a74c4f9cd8e575983075f4a1865dd7854327..4b34a083f5cf7b17ba3994d8f7afbad1567212a7 100644 (file)
@@ -62,8 +62,6 @@ unsigned short sii164GetDeviceID(void)
        return deviceID;
 }
 
-
-
 /* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */
 
 /*
@@ -239,10 +237,6 @@ long sii164InitChip(unsigned char edgeSelect,
        return -1;
 }
 
-
-
-
-
 /* below sii164 function is not necessary */
 
 #ifdef SII164_FULL_FUNCTIONS
@@ -402,5 +396,3 @@ void sii164ClearInterrupt(void)
 #endif
 
 #endif
-
-
index 2e9a88cd6af31d22dce6382fb6502eb832085ca8..862e7bf27353e865c3d032e1a00632d801f8fba3 100644 (file)
@@ -12,7 +12,6 @@ enum sii164_hot_plug_mode {
        SII164_HOTPLUG_USE_HTPLG            /* Use Hot Plug detect bit. */
 };
 
-
 /* Silicon Image SiI164 chip prototype */
 long sii164InitChip(unsigned char edgeSelect,
                    unsigned char busSelect,
@@ -28,7 +27,6 @@ long sii164InitChip(unsigned char edgeSelect,
 unsigned short sii164GetVendorID(void);
 unsigned short sii164GetDeviceID(void);
 
-
 #ifdef SII164_FULL_FUNCTIONS
 void sii164ResetChip(void);
 char *sii164GetChipString(void);
index ffd114a6d09b622935ae08deac2b6d4962f68bc1..a8c79864ee4b3f41a483d6a688fb755999453bb6 100644 (file)
@@ -185,29 +185,29 @@ int hw_sm750_output_setMode(struct lynxfb_output *output,
                            struct fb_fix_screeninfo *fix)
 {
        int ret;
-       disp_output_t dispSet;
+       disp_output_t disp_set;
        int channel;
 
        ret = 0;
-       dispSet = 0;
+       disp_set = 0;
        channel = *output->channel;
 
        if (sm750_get_chip_type() != SM750LE) {
                if (channel == sm750_primary) {
                        pr_info("primary channel\n");
                        if (output->paths & sm750_panel)
-                               dispSet |= do_LCD1_PRI;
+                               disp_set |= do_LCD1_PRI;
                        if (output->paths & sm750_crt)
-                               dispSet |= do_CRT_PRI;
+                               disp_set |= do_CRT_PRI;
 
                } else {
                        pr_info("secondary channel\n");
                        if (output->paths & sm750_panel)
-                               dispSet |= do_LCD1_SEC;
+                               disp_set |= do_LCD1_SEC;
                        if (output->paths & sm750_crt)
-                               dispSet |= do_CRT_SEC;
+                               disp_set |= do_CRT_SEC;
                }
-               ddk750_setLogicalDispOut(dispSet);
+               ddk750_setLogicalDispOut(disp_set);
        } else {
                /* just open DISPLAY_CONTROL_750LE register bit 3:0 */
                u32 reg;
index 6137fa83c609e322e13e4aedd519ace37252fd32..461f131644a234a0425ea3f244e818ad31307e8c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/console.h>
 #include <linux/types.h>
 #include <linux/wait.h>
index 294c74b47224927db4541c40105b3d1b2b765db8..cd029968462f4006e595c42c8f909350f4c6775a 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /* fakekey.c
  * Functions for simulating keypresses.
  *
  * Copyright (C) 2010 the Speakup Team
- *
- * 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/types.h>
 #include <linux/slab.h>
index 4e6e5daba50c7ebbaf1df565e2967da1119cef3e..5f1bda37f86de5176bd9709cc1234ef464ac3ea4 100644 (file)
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /* speakup_keyhelp.c
  * help module for speakup
  *
  *written by David Borowski.
  *
  *  Copyright (C) 2003  David Borowski.
- *
- *  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/keyboard.h>
index ca85476e3ff76cb28140f6fddbe02c42e1c1d9c7..f1f90222186b1ec47bcbd95e04f7ffe4d46995c6 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Speakup kobject implementation
  *
index aae868509e1302958bfcf13a029bd790f61692ec..cf125905977655b947c61636815c02c1fa355096 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /* speakup.c
  * review functions for the speakup screen review package.
  * originally written by: Kirk Reiser and Andy Berdan.
@@ -6,16 +7,6 @@
  *
  ** Copyright (C) 1998  Kirk Reiser.
  *  Copyright (C) 2003  David Borowski.
- *
- *  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/kernel.h>
index 66061b5c34278b3015459c563316290013c7b44f..0ed1fefee0e9b3a1e3f9cfc3018d49833801e218 100644 (file)
@@ -64,13 +64,8 @@ int speakup_set_selection(struct tty_struct *tty)
        ps = spk_ys * vc->vc_size_row + (spk_xs << 1);
        pe = spk_ye * vc->vc_size_row + (spk_xe << 1);
 
-       if (ps > pe) {
-               /* make sel_start <= sel_end */
-               int tmp = ps;
-
-               ps = pe;
-               pe = tmp;
-       }
+       if (ps > pe)    /* make sel_start <= sel_end */
+               swap(ps, pe);
 
        if (spk_sel_cons != vc_cons[fg_console].d) {
                speakup_clear_selection();
index 9cfc8142a31878b522018c72084a23284f02298b..177a2988641c16ea4922ea3de6e0b0a7ee06df2e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 
index a041441766aa4df2f1943d681140c30379ddd9b3..28519754b2f0c8ec92811e1352e749884bc63692 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,15 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
  * this code is specificly written as a driver for the speakup screenreview
  * package and is not a general device driver.
  * This driver is for the Aicom Acent PC internal synthesizer.
index 43315849b7b67a0259e77eb597c09a305a507648..3a863dc61286ab2e0d30525d421a878f0b1e2003 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * this code is specificly written as a driver for the speakup screenreview
  * package and is not a general device driver.
  */
index dcf0c3b59fddaf30c36db92dfe734bf3083cee95..0877b4044c28d079ceb56cb84dd09e852c73ce6b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * this code is specificly written as a driver for the speakup screenreview
  * package and is not a general device driver.
  */
index 45b5721441bac3a525df4c1b032192e62433b4d0..e6a6a9665d8fc8ae79e70151bb8d48415a56a05f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * specificly written as a driver for the speakup screenreview
  * s not a general device driver.
  */
index 402b0fbfb94d044b219a22f4d3589b7525f1ec68..76dfa3f7c05864a2785e51ea2f7b300f05b68e41 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * this code is specificly written as a driver for the speakup screenreview
  * package and is not a general device driver.
  */
index 4310c2c276c4b06ae0f55b9abbe1381dc6f5ed54..3741c0fcf5bbebdd80afd639abbe265e6279630f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * specificly written as a driver for the speakup screenreview
  * s not a general device driver.
  */
index 7a8df7dc1e38c913aada3744dbc16c6d3427a5cb..303f393d3f2fdcbd0f316fe6204f6d145ba058f4 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * This is the DECtalk PC speakup driver
  *
  *      Copyright (c) 2003 David Borowski <david575@golden.net>
  *
  * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 #include <linux/jiffies.h>
 #include <linux/sched.h>
index 5d6a861c9b1e55e390d43581fc6a29dc463e55af..2ea22a2eb5f9a3179bc206539071ec75ed180376 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * specificly written as a driver for the speakup screenreview
  * s not a general device driver.
  */
index 8999e3eb5c2627e5e7b611bca8adda10792cdc26..f8cb83c9b82eb9c18fef2bb9a74dad402f246b1f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * specificly written as a driver for the speakup screenreview
  * package it's not a general device driver.
  * This driver is for the RC Systems DoubleTalk PC internal synthesizer.
index ea3b2911cab960a518c4742d84ef2d1d64a9f288..a30d60450bd5c971cf16a5f33586fa747ed08736 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -7,16 +8,6 @@
  * Copyright (C) 2003 David Borowski.
  * Copyright (C) 2007 Samuel Thibault.
  *
- * 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.
- *
  * specificly written as a driver for the speakup screenreview
  * s not a general device driver.
  */
index d3203f8fc3d04ca8666a65fb5e44e956b86f31aa..de76183932e17632313a33c0880fcd2e1b7a68d4 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * written by David Borowski
  *
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * specificly written as a driver for the speakup screenreview
  * package it's not a general device driver.
  * This driver is for the Keynote Gold internal synthesizer.
index 95efaab73813aba84ea0132c9d3d5786376432b9..3c59519a871f76248ae400e9f18adc6c720529ba 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * specificly written as a driver for the speakup screenreview
  * s not a general device driver.
  */
index 585c6aa124cd40bf4b79cadd35217a80de6aa121..0e74d09e18ea3e1db8f997c28c4f68e016c67c42 100644 (file)
@@ -1,20 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /* speakup_soft.c - speakup driver to register and make available
  * a user space device for software synthesizers.  written by: Kirk
  * Reiser <kirk@braille.uwo.ca>
  *
  * Copyright (C) 2003  Kirk Reiser.
  *
- * 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.
- *
- *
  * this code is specificly written as a driver for the speakup screenreview
  * package and is not a general device driver.
  */
index 1037aa0d085ad8f224cf445a70b268e28ed690a6..6e933bf1de2e2ecb8396c8a33e02297b27826b8d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * specificly written as a driver for the speakup screenreview
  * s not a general device driver.
  */
index e160034e4a6881fabb2ce7b6e7139a952338617f..a7326f226a5e9d63e25a86f791b05d383dab67ab 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  * this version considerably modified by David Borowski, david575@rogers.com
@@ -5,16 +6,6 @@
  * Copyright (C) 1998-99  Kirk Reiser.
  * Copyright (C) 2003 David Borowski.
  *
- * 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.
- *
  * specificly written as a driver for the speakup screenreview
  * s not a general device driver.
  */
index 046040ac074c63851e8b289d5a6bf0f05b31684d..00430437eb4c739e1704177e5b0138bc78a09e84 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /* spk_priv.h
  * review functions for the speakup screen review package.
  * originally written by: Kirk Reiser and Andy Berdan.
@@ -6,16 +7,6 @@
  *
  * Copyright (C) 1998  Kirk Reiser.
  * Copyright (C) 2003  David Borowski.
-
- * 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 _SPEAKUP_PRIVATE_H
 #define _SPEAKUP_PRIVATE_H
index c95b68ebd8e7ccb81e9270ccad5c310397e49967..cc99fcd1bc6e42ba95be1d87275eea745fd789c0 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /* spk_priv.h
  * review functions for the speakup screen review package.
  * originally written by: Kirk Reiser and Andy Berdan.
@@ -6,16 +7,6 @@
  *
  * Copyright (C) 1998  Kirk Reiser.
  * Copyright (C) 2003  David Borowski.
- *
- * 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 _SPEAKUP_KEYINFO_H
index 513cebbd161c6611dcd393aee848f600ca36ac1f..5aa3ffa3772de971744f55ef931797557ca8cbc1 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/types.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
index aac29c816d09a54e58257abae1fb42624fb51d7b..c06e6a810999bcd07fdac6040b7a64d97bf296fc 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/types.h>
 #include <linux/ctype.h>       /* for isdigit() and friends */
 #include <linux/fs.h>
index 8c64f1ada6e04b108b71613abc9dc16c0aaea7a9..2fc75e60fbac28c655ad84e1b65caa2f54f20809 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/kthread.h>
 #include <linux/wait.h>
 
index d37d24e266416c79d4494f015b3c7bcdd7f0e89a..321405532a8ea57132c4f924499b7c7509a73e1e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/ctype.h>
 #include "spk_types.h"
 #include "spk_priv.h"
index b6abaf79ef0b018094d2d9c03d61de13bc09d4f3..9bd4412356c9e4e5c414a5586b01d9bb264eaea1 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2015-2017 Google, Inc
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
  * USB Type-C Port Controller Interface.
  */
 
@@ -47,7 +38,7 @@ static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc)
 }
 
 static int tcpci_read16(struct tcpci *tcpci, unsigned int reg,
-                       unsigned int *val)
+                       u16 *val)
 {
        return regmap_raw_read(tcpci->regmap, reg, val, sizeof(u16));
 }
@@ -285,15 +276,15 @@ static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
                             const struct pd_message *msg)
 {
        struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       unsigned int reg, cnt, header;
+       u16 header = msg ? le16_to_cpu(msg->header) : 0;
+       unsigned int reg, cnt;
        int ret;
 
-       cnt = msg ? pd_header_cnt(msg->header) * 4 : 0;
+       cnt = msg ? pd_header_cnt(header) * 4 : 0;
        ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2);
        if (ret < 0)
                return ret;
 
-       header = msg ? msg->header : 0;
        ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
        if (ret < 0)
                return ret;
@@ -356,7 +347,7 @@ static int tcpci_init(struct tcpc_dev *tcpc)
 static irqreturn_t tcpci_irq(int irq, void *dev_id)
 {
        struct tcpci *tcpci = dev_id;
-       unsigned int status, reg;
+       u16 status;
 
        tcpci_read16(tcpci, TCPC_ALERT, &status);
 
@@ -372,6 +363,8 @@ static irqreturn_t tcpci_irq(int irq, void *dev_id)
                tcpm_cc_change(tcpci->port);
 
        if (status & TCPC_ALERT_POWER_STATUS) {
+               unsigned int reg;
+
                regmap_read(tcpci->regmap, TCPC_POWER_STATUS_MASK, &reg);
 
                /*
@@ -387,11 +380,12 @@ static irqreturn_t tcpci_irq(int irq, void *dev_id)
        if (status & TCPC_ALERT_RX_STATUS) {
                struct pd_message msg;
                unsigned int cnt;
+               u16 header;
 
                regmap_read(tcpci->regmap, TCPC_RX_BYTE_CNT, &cnt);
 
-               tcpci_read16(tcpci, TCPC_RX_HDR, &reg);
-               msg.header = reg;
+               tcpci_read16(tcpci, TCPC_RX_HDR, &header);
+               msg.header = cpu_to_le16(header);
 
                if (WARN_ON(cnt > sizeof(msg.payload)))
                        cnt = sizeof(msg.payload);
index 10b04c8723dad7f42a478c46ec6ab2120ab2dff2..fdfb06cc3b8602bdfe95276aa82b330eee519749 100644 (file)
@@ -1,16 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright 2015-2017 Google, Inc
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
  * USB Type-C Port Controller Interface.
  */
 
index 4f1f5e624604dc00ee0f29f1d298d31b6a47b361..c27dab3b610f1feddf3d15c0a41dd3bfbe5d3fce 100644 (file)
@@ -3,15 +3,11 @@
 #
 menuconfig UNISYSSPAR
        bool "Unisys SPAR driver support"
-       depends on X86_64 && !UML
-       select PCI
-       select ACPI
        ---help---
        Support for the Unisys SPAR drivers
 
 if UNISYSSPAR
 
-source "drivers/staging/unisys/visorbus/Kconfig"
 source "drivers/staging/unisys/visornic/Kconfig"
 source "drivers/staging/unisys/visorinput/Kconfig"
 source "drivers/staging/unisys/visorhba/Kconfig"
index 20eb098538d3fa9c3498c7e4df70232c994cf679..e45f44b6420247407f760eaaa16c64ada852c7bf 100644 (file)
@@ -1,7 +1,6 @@
 #
 # Makefile for Unisys SPAR drivers
 #
-obj-$(CONFIG_UNISYS_VISORBUS)          += visorbus/
 obj-$(CONFIG_UNISYS_VISORNIC)          += visornic/
 obj-$(CONFIG_UNISYS_VISORINPUT)                += visorinput/
 obj-$(CONFIG_UNISYS_VISORHBA)          += visorhba/
index 5cd407ca2251190ebc84e7a4751e8d91047d729d..45c785d80ce4706b592b941678fd26d96ae5ea17 100644 (file)
@@ -1,17 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2010 - 2016 UNISYS CORPORATION
  * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
  */
 
 #ifndef __IOCHANNEL_H__
@@ -43,8 +33,7 @@
 
 #include <linux/uuid.h>
 #include <linux/skbuff.h>
-
-#include "visorchannel.h"
+#include <linux/visorbus.h>
 
 /*
  * Must increment these whenever you insert or delete fields within this channel
diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h
deleted file mode 100644 (file)
index 1a0986b..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-/*
- *  This header file is to be included by other kernel mode components that
- *  implement a particular kind of visor_device.  Each of these other kernel
- *  mode components is called a visor device driver.  Refer to visortemplate
- *  for a minimal sample visor device driver.
- *
- *  There should be nothing in this file that is private to the visorbus
- *  bus implementation itself.
- */
-
-#ifndef __VISORBUS_H__
-#define __VISORBUS_H__
-
-#include <linux/device.h>
-
-#include "visorchannel.h"
-
-struct visorchipset_state {
-       u32 created:1;
-       u32 attached:1;
-       u32 configured:1;
-       u32 running:1;
-       /* Remaining bits in this 32-bit word are reserved. */
-};
-
-/**
- * struct visor_device - A device type for things "plugged" into the visorbus
- *                       bus
- * @visorchannel:              Points to the channel that the device is
- *                             associated with.
- * @channel_type_guid:         Identifies the channel type to the bus driver.
- * @device:                    Device struct meant for use by the bus driver
- *                             only.
- * @list_all:                  Used by the bus driver to enumerate devices.
- * @timer:                     Timer fired periodically to do interrupt-type
- *                             activity.
- * @being_removed:             Indicates that the device is being removed from
- *                             the bus. Private bus driver use only.
- * @visordriver_callback_lock: Used by the bus driver to lock when adding and
- *                             removing devices.
- * @pausing:                   Indicates that a change towards a paused state.
- *                             is in progress. Only modified by the bus driver.
- * @resuming:                  Indicates that a change towards a running state
- *                             is in progress. Only modified by the bus driver.
- * @chipset_bus_no:            Private field used by the bus driver.
- * @chipset_dev_no:            Private field used the bus driver.
- * @state:                     Used to indicate the current state of the
- *                             device.
- * @inst:                      Unique GUID for this instance of the device.
- * @name:                      Name of the device.
- * @pending_msg_hdr:           For private use by bus driver to respond to
- *                             hypervisor requests.
- * @vbus_hdr_info:             A pointer to header info. Private use by bus
- *                             driver.
- * @partition_guid:            Indicates client partion id. This should be the
- *                             same across all visor_devices in the current
- *                             guest. Private use by bus driver only.
- */
-struct visor_device {
-       struct visorchannel *visorchannel;
-       guid_t channel_type_guid;
-       /* These fields are for private use by the bus driver only. */
-       struct device device;
-       struct list_head list_all;
-       struct timer_list timer;
-       bool timer_active;
-       bool being_removed;
-       struct mutex visordriver_callback_lock; /* synchronize probe/remove */
-       bool pausing;
-       bool resuming;
-       u32 chipset_bus_no;
-       u32 chipset_dev_no;
-       struct visorchipset_state state;
-       guid_t inst;
-       u8 *name;
-       struct controlvm_message_header *pending_msg_hdr;
-       void *vbus_hdr_info;
-       guid_t partition_guid;
-       struct dentry *debugfs_dir;
-       struct dentry *debugfs_bus_info;
-};
-
-#define to_visor_device(x) container_of(x, struct visor_device, device)
-
-typedef void (*visorbus_state_complete_func) (struct visor_device *dev,
-                                             int status);
-
-/*
- * This struct describes a specific visor channel, by providing its GUID, name,
- * and sizes.
- */
-struct visor_channeltype_descriptor {
-       const guid_t guid;
-       const char *name;
-       u64 min_bytes;
-       u32 version;
-};
-
-/**
- * struct visor_driver - Information provided by each visor driver when it
- *                       registers with the visorbus driver
- * @name:              Name of the visor driver.
- * @owner:             The module owner.
- * @channel_types:     Types of channels handled by this driver, ending with
- *                     a zero GUID. Our specialized BUS.match() method knows
- *                     about this list, and uses it to determine whether this
- *                     driver will in fact handle a new device that it has
- *                     detected.
- * @probe:             Called when a new device comes online, by our probe()
- *                     function specified by driver.probe() (triggered
- *                     ultimately by some call to driver_register(),
- *                     bus_add_driver(), or driver_attach()).
- * @remove:            Called when a new device is removed, by our remove()
- *                     function specified by driver.remove() (triggered
- *                     ultimately by some call to device_release_driver()).
- * @channel_interrupt: Called periodically, whenever there is a possiblity
- *                     that "something interesting" may have happened to the
- *                     channel.
- * @pause:             Called to initiate a change of the device's state.  If
- *                     the return valu`e is < 0, there was an error and the
- *                     state transition will NOT occur.  If the return value
- *                     is >= 0, then the state transition was INITIATED
- *                     successfully, and complete_func() will be called (or
- *                     was just called) with the final status when either the
- *                     state transition fails or completes successfully.
- * @resume:            Behaves similar to pause.
- * @driver:            Private reference to the device driver. For use by bus
- *                     driver only.
- */
-struct visor_driver {
-       const char *name;
-       struct module *owner;
-       struct visor_channeltype_descriptor *channel_types;
-       int (*probe)(struct visor_device *dev);
-       void (*remove)(struct visor_device *dev);
-       void (*channel_interrupt)(struct visor_device *dev);
-       int (*pause)(struct visor_device *dev,
-                    visorbus_state_complete_func complete_func);
-       int (*resume)(struct visor_device *dev,
-                     visorbus_state_complete_func complete_func);
-
-       /* These fields are for private use by the bus driver only. */
-       struct device_driver driver;
-};
-
-#define to_visor_driver(x) (container_of(x, struct visor_driver, driver))
-
-int visor_check_channel(struct channel_header *ch, struct device *dev,
-                       const guid_t *expected_uuid, char *chname,
-                       u64 expected_min_bytes, u32 expected_version,
-                       u64 expected_signature);
-
-int visorbus_register_visor_driver(struct visor_driver *drv);
-void visorbus_unregister_visor_driver(struct visor_driver *drv);
-int visorbus_read_channel(struct visor_device *dev,
-                         unsigned long offset, void *dest,
-                         unsigned long nbytes);
-int visorbus_write_channel(struct visor_device *dev,
-                          unsigned long offset, void *src,
-                          unsigned long nbytes);
-int visorbus_enable_channel_interrupts(struct visor_device *dev);
-void visorbus_disable_channel_interrupts(struct visor_device *dev);
-
-int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
-                             void *msg);
-int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
-                             void *msg);
-bool visorchannel_signalempty(struct visorchannel *channel, u32 queue);
-const guid_t *visorchannel_get_guid(struct visorchannel *channel);
-
-#define BUS_ROOT_DEVICE UINT_MAX
-struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
-                                              struct visor_device *from);
-#endif
diff --git a/drivers/staging/unisys/include/visorchannel.h b/drivers/staging/unisys/include/visorchannel.h
deleted file mode 100644 (file)
index 3394574..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#ifndef __VISORCHANNEL_H__
-#define __VISORCHANNEL_H__
-
-#include <linux/types.h>
-#include <linux/uuid.h>
-
-#define VISOR_CHANNEL_SIGNATURE ('L' << 24 | 'N' << 16 | 'C' << 8 | 'E')
-
-/*
- * enum channel_serverstate
- * @CHANNELSRV_UNINITIALIZED: Channel is in an undefined state.
- * @CHANNELSRV_READY:        Channel has been initialized by server.
- */
-enum channel_serverstate {
-       CHANNELSRV_UNINITIALIZED = 0,
-       CHANNELSRV_READY = 1
-};
-
-/*
- * enum channel_clientstate
- * @CHANNELCLI_DETACHED:
- * @CHANNELCLI_DISABLED:  Client can see channel but is NOT allowed to use it
- *                       unless given TBD* explicit request
- *                       (should actually be < DETACHED).
- * @CHANNELCLI_ATTACHING: Legacy EFI client request for EFI server to attach.
- * @CHANNELCLI_ATTACHED:  Idle, but client may want to use channel any time.
- * @CHANNELCLI_BUSY:     Client either wants to use or is using channel.
- * @CHANNELCLI_OWNED:    "No worries" state - client can access channel
- *                       anytime.
- */
-enum channel_clientstate {
-       CHANNELCLI_DETACHED = 0,
-       CHANNELCLI_DISABLED = 1,
-       CHANNELCLI_ATTACHING = 2,
-       CHANNELCLI_ATTACHED = 3,
-       CHANNELCLI_BUSY = 4,
-       CHANNELCLI_OWNED = 5
-};
-
-/*
- * Values for VISOR_CHANNEL_PROTOCOL.Features: This define exists so that
- * a guest can look at the FeatureFlags in the io channel, and configure the
- * driver to use interrupts or not based on this setting. All feature bits for
- * all channels should be defined here. The io channel feature bits are defined
- * below.
- */
-#define VISOR_DRIVER_ENABLES_INTS (0x1ULL << 1)
-#define VISOR_CHANNEL_IS_POLLING (0x1ULL << 3)
-#define VISOR_IOVM_OK_DRIVER_DISABLING_INTS (0x1ULL << 4)
-#define VISOR_DRIVER_DISABLES_INTS (0x1ULL << 5)
-#define VISOR_DRIVER_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
-
-/*
- * struct channel_header - Common Channel Header
- * @signature:        Signature.
- * @legacy_state:      DEPRECATED - being replaced by.
- * @header_size:       sizeof(struct channel_header).
- * @size:             Total size of this channel in bytes.
- * @features:         Flags to modify behavior.
- * @chtype:           Channel type: data, bus, control, etc..
- * @partition_handle:  ID of guest partition.
- * @handle:           Device number of this channel in client.
- * @ch_space_offset:   Offset in bytes to channel specific area.
- * @version_id:               Struct channel_header Version ID.
- * @partition_index:   Index of guest partition.
- * @zone_uuid:        Guid of Channel's zone.
- * @cli_str_offset:    Offset from channel header to null-terminated
- *                    ClientString (0 if ClientString not present).
- * @cli_state_boot:    CHANNEL_CLIENTSTATE of pre-boot EFI client of this
- *                    channel.
- * @cmd_state_cli:     CHANNEL_COMMANDSTATE (overloaded in Windows drivers, see
- *                    ServerStateUp, ServerStateDown, etc).
- * @cli_state_os:      CHANNEL_CLIENTSTATE of Guest OS client of this channel.
- * @ch_characteristic: CHANNEL_CHARACTERISTIC_<xxx>.
- * @cmd_state_srv:     CHANNEL_COMMANDSTATE (overloaded in Windows drivers, see
- *                    ServerStateUp, ServerStateDown, etc).
- * @srv_state:        CHANNEL_SERVERSTATE.
- * @cli_error_boot:    Bits to indicate err states for boot clients, so err
- *                    messages can be throttled.
- * @cli_error_os:      Bits to indicate err states for OS clients, so err
- *                    messages can be throttled.
- * @filler:           Pad out to 128 byte cacheline.
- * @recover_channel:   Please add all new single-byte values below here.
- */
-struct channel_header {
-       u64 signature;
-       u32 legacy_state;
-       /* SrvState, CliStateBoot, and CliStateOS below */
-       u32 header_size;
-       u64 size;
-       u64 features;
-       guid_t chtype;
-       u64 partition_handle;
-       u64 handle;
-       u64 ch_space_offset;
-       u32 version_id;
-       u32 partition_index;
-       guid_t zone_guid;
-       u32 cli_str_offset;
-       u32 cli_state_boot;
-       u32 cmd_state_cli;
-       u32 cli_state_os;
-       u32 ch_characteristic;
-       u32 cmd_state_srv;
-       u32 srv_state;
-       u8 cli_error_boot;
-       u8 cli_error_os;
-       u8 filler[1];
-       u8 recover_channel;
-} __packed;
-
-#define VISOR_CHANNEL_ENABLE_INTS (0x1ULL << 0)
-
-/*
- * struct signal_queue_header - Subheader for the Signal Type variation of the
- *                              Common Channel.
- * @version:         SIGNAL_QUEUE_HEADER Version ID.
- * @chtype:          Queue type: storage, network.
- * @size:            Total size of this queue in bytes.
- * @sig_base_offset:  Offset to signal queue area.
- * @features:        Flags to modify behavior.
- * @num_sent:        Total # of signals placed in this queue.
- * @num_overflows:    Total # of inserts failed due to full queue.
- * @signal_size:      Total size of a signal for this queue.
- * @max_slots:        Max # of slots in queue, 1 slot is always empty.
- * @max_signals:      Max # of signals in queue (MaxSignalSlots-1).
- * @head:            Queue head signal #.
- * @num_received:     Total # of signals removed from this queue.
- * @tail:            Queue tail signal.
- * @reserved1:       Reserved field.
- * @reserved2:       Reserved field.
- * @client_queue:
- * @num_irq_received: Total # of Interrupts received. This is incremented by the
- *                   ISR in the guest windows driver.
- * @num_empty:       Number of times that visor_signal_remove is called and
- *                   returned Empty Status.
- * @errorflags:              Error bits set during SignalReinit to denote trouble with
- *                   client's fields.
- * @filler:          Pad out to 64 byte cacheline.
- */
-struct signal_queue_header {
-       /* 1st cache line */
-       u32 version;
-       u32 chtype;
-       u64 size;
-       u64 sig_base_offset;
-       u64 features;
-       u64 num_sent;
-       u64 num_overflows;
-       u32 signal_size;
-       u32 max_slots;
-       u32 max_signals;
-       u32 head;
-       /* 2nd cache line */
-       u64 num_received;
-       u32 tail;
-       u32 reserved1;
-       u64 reserved2;
-       u64 client_queue;
-       u64 num_irq_received;
-       u64 num_empty;
-       u32 errorflags;
-       u8 filler[12];
-} __packed;
-
-/* VISORCHANNEL Guids */
-/* {414815ed-c58c-11da-95a9-00e08161165f} */
-#define VISOR_VHBA_CHANNEL_GUID \
-       GUID_INIT(0x414815ed, 0xc58c, 0x11da, \
-                 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
-#define VISOR_VHBA_CHANNEL_GUID_STR \
-       "414815ed-c58c-11da-95a9-00e08161165f"
-#endif
diff --git a/drivers/staging/unisys/visorbus/Kconfig b/drivers/staging/unisys/visorbus/Kconfig
deleted file mode 100644 (file)
index 5113880..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Unisys visorbus configuration
-#
-
-config UNISYS_VISORBUS
-       tristate "Unisys visorbus driver"
-       depends on UNISYSSPAR
-       ---help---
-       The visorbus driver is a virtualized bus for the Unisys s-Par firmware.
-       Virtualized devices allow Linux guests on a system to share disks and
-       network cards that do not have SR-IOV support, and to be accessed using
-       the partition desktop application. The visorbus driver is required to
-       discover devices on an s-Par guest, and must be present for any other
-       s-Par guest driver to function correctly.
diff --git a/drivers/staging/unisys/visorbus/Makefile b/drivers/staging/unisys/visorbus/Makefile
deleted file mode 100644 (file)
index 784cdc1..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for Unisys visorbus
-#
-
-obj-$(CONFIG_UNISYS_VISORBUS)  += visorbus.o
-
-visorbus-y := visorbus_main.o
-visorbus-y += visorchannel.o
-visorbus-y += visorchipset.o
-
-ccflags-y += -Idrivers/staging/unisys/include
diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h
deleted file mode 100644 (file)
index 9ee9886..0000000
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#ifndef __CONTROLVMCHANNEL_H__
-#define __CONTROLVMCHANNEL_H__
-
-#include <linux/uuid.h>
-
-#include "visorchannel.h"
-
-/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */
-#define VISOR_CONTROLVM_CHANNEL_GUID \
-       GUID_INIT(0x2b3c2d10, 0x7ef5, 0x4ad8, \
-                 0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d)
-
-#define CONTROLVM_MESSAGE_MAX 64
-
-/*
- * Must increment this whenever you insert or delete fields within this channel
- * struct.  Also increment whenever you change the meaning of fields within this
- * channel struct so as to break pre-existing software. Note that you can
- * usually add fields to the END of the channel struct withOUT needing to
- * increment this.
- */
-#define VISOR_CONTROLVM_CHANNEL_VERSIONID 1
-
-/* Defines for various channel queues */
-#define CONTROLVM_QUEUE_REQUEST                0
-#define CONTROLVM_QUEUE_RESPONSE       1
-#define CONTROLVM_QUEUE_EVENT          2
-#define CONTROLVM_QUEUE_ACK            3
-
-/* Max num of messages stored during IOVM creation to be reused after crash */
-#define CONTROLVM_CRASHMSG_MAX 2
-
-/*
- * struct visor_segment_state
- * @enabled:   May enter other states.
- * @active:    Assigned to active partition.
- * @alive:     Configure message sent to service/server.
- * @revoked:   Similar to partition state ShuttingDown.
- * @allocated: Memory (device/port number) has been selected by Command.
- * @known:     Has been introduced to the service/guest partition.
- * @ready:     Service/Guest partition has responded to introduction.
- * @operating: Resource is configured and operating.
- * @reserved:  Natural alignment.
- *
- * Note: Don't use high bit unless we need to switch to ushort which is
- * non-compliant.
- */
-struct visor_segment_state  {
-       u16 enabled:1;
-       u16 active:1;
-       u16 alive:1;
-       u16 revoked:1;
-       u16 allocated:1;
-       u16 known:1;
-       u16 ready:1;
-       u16 operating:1;
-       u16 reserved:8;
-} __packed;
-
-static const struct visor_segment_state segment_state_running = {
-       1, 1, 1, 0, 1, 1, 1, 1
-};
-
-static const struct visor_segment_state segment_state_paused = {
-       1, 1, 1, 0, 1, 1, 1, 0
-};
-
-static const struct visor_segment_state segment_state_standby = {
-       1, 1, 0, 0, 1, 1, 1, 0
-};
-
-/*
- * enum controlvm_id
- * @CONTROLVM_INVALID:
- * @CONTROLVM_BUS_CREATE:              CP --> SP, GP.
- * @CONTROLVM_BUS_DESTROY:             CP --> SP, GP.
- * @CONTROLVM_BUS_CONFIGURE:           CP --> SP.
- * @CONTROLVM_BUS_CHANGESTATE:         CP --> SP, GP.
- * @CONTROLVM_BUS_CHANGESTATE_EVENT:   SP, GP --> CP.
- * @CONTROLVM_DEVICE_CREATE:           CP --> SP, GP.
- * @CONTROLVM_DEVICE_DESTROY:          CP --> SP, GP.
- * @CONTROLVM_DEVICE_CONFIGURE:                CP --> SP.
- * @CONTROLVM_DEVICE_CHANGESTATE:      CP --> SP, GP.
- * @CONTROLVM_DEVICE_CHANGESTATE_EVENT:        SP, GP --> CP.
- * @CONTROLVM_DEVICE_RECONFIGURE:      CP --> Boot.
- * @CONTROLVM_CHIPSET_INIT:            CP --> SP, GP.
- * @CONTROLVM_CHIPSET_STOP:            CP --> SP, GP.
- * @CONTROLVM_CHIPSET_READY:           CP --> SP.
- * @CONTROLVM_CHIPSET_SELFTEST:                CP --> SP.
- *
- * Ids for commands that may appear in either queue of a ControlVm channel.
- *
- * Commands that are initiated by the command partition (CP), by an IO or
- * console service partition (SP), or by a guest partition (GP) are:
- * - issued on the RequestQueue queue (q #0) in the ControlVm channel
- * - responded to on the ResponseQueue queue (q #1) in the ControlVm channel
- *
- * Events that are initiated by an IO or console service partition (SP) or
- * by a guest partition (GP) are:
- * - issued on the EventQueue queue (q #2) in the ControlVm channel
- * - responded to on the EventAckQueue queue (q #3) in the ControlVm channel
- */
-enum controlvm_id {
-       CONTROLVM_INVALID = 0,
-       /*
-        * SWITCH commands required Parameter: SwitchNumber.
-        * BUS commands required Parameter: BusNumber
-        */
-       CONTROLVM_BUS_CREATE = 0x101,
-       CONTROLVM_BUS_DESTROY = 0x102,
-       CONTROLVM_BUS_CONFIGURE = 0x104,
-       CONTROLVM_BUS_CHANGESTATE = 0x105,
-       CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106,
-       /* DEVICE commands required Parameter: BusNumber, DeviceNumber */
-       CONTROLVM_DEVICE_CREATE = 0x201,
-       CONTROLVM_DEVICE_DESTROY = 0x202,
-       CONTROLVM_DEVICE_CONFIGURE = 0x203,
-       CONTROLVM_DEVICE_CHANGESTATE = 0x204,
-       CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205,
-       CONTROLVM_DEVICE_RECONFIGURE = 0x206,
-       /* CHIPSET commands */
-       CONTROLVM_CHIPSET_INIT = 0x301,
-       CONTROLVM_CHIPSET_STOP = 0x302,
-       CONTROLVM_CHIPSET_READY = 0x304,
-       CONTROLVM_CHIPSET_SELFTEST = 0x305,
-};
-
-/*
- * struct irq_info
- * @reserved1:      Natural alignment purposes
- * @recv_irq_handle: Specifies interrupt handle. It is used to retrieve the
- *                  corresponding interrupt pin from Monitor; and the interrupt
- *                  pin is used to connect to the corresponding interrupt.
- *                  Used by IOPart-GP only.
- * @recv_irq_vector: Specifies interrupt vector. It, interrupt pin, and shared
- *                  are used to connect to the corresponding interrupt.
- *                  Used by IOPart-GP only.
- * @recv_irq_shared: Specifies if the recvInterrupt is shared.  It, interrupt
- *                  pin and vector are used to connect to 0 = not shared;
- *                  1 = shared the corresponding interrupt.
- *                  Used by IOPart-GP only.
- * @reserved:       Natural alignment purposes
- */
-struct irq_info {
-       u64 reserved1;
-       u64 recv_irq_handle;
-       u32 recv_irq_vector;
-       u8 recv_irq_shared;
-       u8 reserved[3];
-} __packed;
-
-/*
- * struct efi_visor_indication
- * @boot_to_fw_ui: Stop in UEFI UI
- * @clear_nvram:   Clear NVRAM
- * @clear_cmos:           Clear CMOS
- * @boot_to_tool:  Run install tool
- * @reserved:     Natural alignment
- */
-struct efi_visor_indication  {
-       u64 boot_to_fw_ui:1;
-       u64 clear_nvram:1;
-       u64 clear_cmos:1;
-       u64 boot_to_tool:1;
-       /* Remaining bits are available */
-       u64 reserved:60;
-} __packed;
-
-enum visor_chipset_feature {
-       VISOR_CHIPSET_FEATURE_REPLY = 0x00000001,
-       VISOR_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002,
-};
-
-/*
- * struct controlvm_message_header
- * @id:                       See CONTROLVM_ID.
- * @message_size:      Includes size of this struct + size of message.
- * @segment_index:     Index of segment containing Vm message/information.
- * @completion_status: Error status code or result of  message completion.
- * @struct flags:
- *     @failed:             =1 in a response to signify failure.
- *     @response_expected:  =1 in all messages that expect a response.
- *     @server:             =1 in all bus & device-related messages where the
- *                          message receiver is to act as the bus or device
- *                          server.
- *     @test_message:       =1 for testing use only (Control and Command
- *                          ignore this).
- *     @partial_completion: =1 if there are forthcoming responses/acks
- *                           associated with this message.
- *      @preserve:          =1 this is to let us know to preserve channel
- *                          contents.
- *     @writer_in_diag:     =1 the DiagWriter is active in the Diagnostic
- *                          Partition.
- *     @reserve:            Natural alignment.
- * @reserved:         Natural alignment.
- * @message_handle:    Identifies the particular message instance.
- * @payload_vm_offset: Offset of payload area from start of this instance.
- * @payload_max_bytes: Maximum bytes allocated in payload area of ControlVm
- *                    segment.
- * @payload_bytes:     Actual number of bytes of payload area to copy between
- *                    IO/Command. If non-zero, there is a payload to copy.
- *
- * This is the common structure that is at the beginning of every
- * ControlVm message (both commands and responses) in any ControlVm
- * queue.  Commands are easily distinguished from responses by
- * looking at the flags.response field.
- */
-struct controlvm_message_header  {
-       u32 id;
-       /*
-        * For requests, indicates the message type. For responses, indicates
-        * the type of message we are responding to.
-        */
-       u32 message_size;
-       u32 segment_index;
-       u32 completion_status;
-       struct  {
-               u32 failed:1;
-               u32 response_expected:1;
-               u32 server:1;
-               u32 test_message:1;
-               u32 partial_completion:1;
-               u32 preserve:1;
-               u32 writer_in_diag:1;
-               u32 reserve:25;
-       } __packed flags;
-       u32 reserved;
-       u64 message_handle;
-       u64 payload_vm_offset;
-       u32 payload_max_bytes;
-       u32 payload_bytes;
-} __packed;
-
-/*
- * struct controlvm_packet_device_create - For CONTROLVM_DEVICE_CREATE
- * @bus_no:        Bus # (0..n-1) from the msg receiver's end.
- * @dev_no:        Bus-relative (0..n-1) device number.
- * @channel_addr:   Guest physical address of the channel, which can be
- *                 dereferenced by the receiver of this ControlVm command.
- * @channel_bytes:  Specifies size of the channel in bytes.
- * @data_type_uuid: Specifies format of data in channel.
- * @dev_inst_uuid:  Instance guid for the device.
- * @irq_info intr:  Specifies interrupt information.
- */
-struct controlvm_packet_device_create  {
-       u32 bus_no;
-       u32 dev_no;
-       u64 channel_addr;
-       u64 channel_bytes;
-       guid_t data_type_guid;
-       guid_t dev_inst_guid;
-       struct irq_info intr;
-} __packed;
-
-/*
- * struct controlvm_packet_device_configure - For CONTROLVM_DEVICE_CONFIGURE
- * @bus_no: Bus number (0..n-1) from the msg receiver's perspective.
- * @dev_no: Bus-relative (0..n-1) device number.
- */
-struct controlvm_packet_device_configure  {
-       u32 bus_no;
-       u32 dev_no;
-} __packed;
-
-/* Total 128 bytes */
-struct controlvm_message_device_create {
-       struct controlvm_message_header header;
-       struct controlvm_packet_device_create packet;
-} __packed;
-
-/* Total 56 bytes */
-struct controlvm_message_device_configure  {
-       struct controlvm_message_header header;
-       struct controlvm_packet_device_configure packet;
-} __packed;
-
-/*
- * struct controlvm_message_packet - This is the format for a message in any
- *                                   ControlVm queue.
- * @struct create_bus:         For CONTROLVM_BUS_CREATE.
- *     @bus_no:             Bus # (0..n-1) from the msg receiver's perspective.
- *     @dev_count:          Indicates the max number of devices on this bus.
- *     @channel_addr:       Guest physical address of the channel, which can be
- *                          dereferenced by the receiver of this ControlVM
- *                          command.
- *     @channel_bytes:      Size of the channel.
- *     @bus_data_type_uuid: Indicates format of data in bus channel.
- *     @bus_inst_uuid:      Instance uuid for the bus.
- *
- * @struct destroy_bus:                For CONTROLVM_BUS_DESTROY.
- *     @bus_no: Bus # (0..n-1) from the msg receiver's perspective.
- *     @reserved: Natural alignment purposes.
- *
- * @struct configure_bus:      For CONTROLVM_BUS_CONFIGURE.
- *     @bus_no:              Bus # (0..n-1) from the receiver's perspective.
- *     @reserved1:           For alignment purposes.
- *     @guest_handle:        This is used to convert guest physical address to
- *                           physical address.
- *     @recv_bus_irq_handle: Specifies interrupt info. It is used by SP to
- *                           register to receive interrupts from the CP. This
- *                           interrupt is used for bus level notifications.
- *                           The corresponding sendBusInterruptHandle is kept
- *                           in CP.
- *
- * @struct create_device:      For CONTROLVM_DEVICE_CREATE.
- *
- * @struct destroy_device:     For CONTROLVM_DEVICE_DESTROY.
- *     @bus_no: Bus # (0..n-1) from the msg receiver's perspective.
- *     @dev_no: Bus-relative (0..n-1) device number.
- *
- * @struct configure_device:   For CONTROLVM_DEVICE_CONFIGURE.
- *
- * @struct reconfigure_device: For CONTROLVM_DEVICE_RECONFIGURE.
- *     @bus_no: Bus # (0..n-1) from the msg receiver's perspective.
- *     @dev_no: Bus-relative (0..n-1) device number.
- *
- * @struct bus_change_state:   For CONTROLVM_BUS_CHANGESTATE.
- *     @bus_no:
- *     @struct state:
- *     @reserved: Natural alignment purposes.
- *
- * @struct device_change_state:        For CONTROLVM_DEVICE_CHANGESTATE.
- *     @bus_no:
- *     @dev_no:
- *     @struct state:
- *     @struct flags:
- *             @phys_device: =1 if message is for a physical device.
- *             @reserved:    Natural alignment.
- *             @reserved1:   Natural alignment.
- *     @reserved:    Natural alignment purposes.
- *
- * @struct device_change_state_event:  For CONTROLVM_DEVICE_CHANGESTATE_EVENT.
- *     @bus_no:
- *     @dev_no:
- *     @struct state:
- *     @reserved:     Natural alignment purposes.
- *
- * @struct init_chipset:       For CONTROLVM_CHIPSET_INIT.
- *     @bus_count:       Indicates the max number of busses.
- *     @switch_count:    Indicates the max number of switches.
- *     @enum features:
- *     @platform_number:
- *
- * @struct chipset_selftest:   For CONTROLVM_CHIPSET_SELFTEST.
- *      @options: Reserved.
- *      @test:   Bit 0 set to run embedded selftest.
- *
- * @addr:   A physical address of something, that can be dereferenced by the
- *         receiver of this ControlVm command.
- *
- * @handle: A handle of something (depends on command id).
- */
-struct controlvm_message_packet  {
-       union  {
-               struct  {
-                       u32 bus_no;
-                       u32 dev_count;
-                       u64 channel_addr;
-                       u64 channel_bytes;
-                       guid_t bus_data_type_guid;
-                       guid_t bus_inst_guid;
-               } __packed create_bus;
-               struct  {
-                       u32 bus_no;
-                       u32 reserved;
-               } __packed destroy_bus;
-               struct  {
-                       u32 bus_no;
-                       u32 reserved1;
-                       u64 guest_handle;
-                       u64 recv_bus_irq_handle;
-               } __packed configure_bus;
-               struct controlvm_packet_device_create create_device;
-               struct  {
-                       u32 bus_no;
-                       u32 dev_no;
-               } __packed destroy_device;
-               struct controlvm_packet_device_configure configure_device;
-               struct  {
-                       u32 bus_no;
-                       u32 dev_no;
-               } __packed reconfigure_device;
-               struct  {
-                       u32 bus_no;
-                       struct visor_segment_state state;
-                       u8 reserved[2];
-               } __packed bus_change_state;
-               struct  {
-                       u32 bus_no;
-                       u32 dev_no;
-                       struct visor_segment_state state;
-                       struct  {
-                               u32 phys_device:1;
-                               u32 reserved:31;
-                               u32 reserved1;
-                       } __packed flags;
-                       u8 reserved[2];
-               } __packed device_change_state;
-               struct  {
-                       u32 bus_no;
-                       u32 dev_no;
-                       struct visor_segment_state state;
-                       u8 reserved[6];
-               } __packed device_change_state_event;
-               struct  {
-                       u32 bus_count;
-                       u32 switch_count;
-                       enum visor_chipset_feature features;
-                       u32 platform_number;
-               } __packed init_chipset;
-               struct  {
-                       u32 options;
-                       u32 test;
-               } __packed chipset_selftest;
-               u64 addr;
-               u64 handle;
-       };
-} __packed;
-
-/* All messages in any ControlVm queue have this layout. */
-struct controlvm_message {
-       struct controlvm_message_header hdr;
-       struct controlvm_message_packet cmd;
-} __packed;
-
-/*
- * struct visor_controlvm_channel
- * @struct header:
- * @gp_controlvm:                      Guest phys addr of this channel.
- * @gp_partition_tables:               Guest phys addr of partition tables.
- * @gp_diag_guest:                     Guest phys addr of diagnostic channel.
- * @gp_boot_romdisk:                   Guest phys addr of (read* only) Boot
- *                                     ROM disk.
- * @gp_boot_ramdisk:                   Guest phys addr of writable Boot RAM
- *                                     disk.
- * @gp_acpi_table:                     Guest phys addr of acpi table.
- * @gp_control_channel:                        Guest phys addr of control channel.
- * @gp_diag_romdisk:                   Guest phys addr of diagnostic ROM disk.
- * @gp_nvram:                          Guest phys addr of NVRAM channel.
- * @request_payload_offset:            Offset to request payload area.
- * @event_payload_offset:              Offset to event payload area.
- * @request_payload_bytes:             Bytes available in request payload area.
- * @event_payload_bytes:               Bytes available in event payload area.
- * @control_channel_bytes:
- * @nvram_channel_bytes:               Bytes in PartitionNvram segment.
- * @message_bytes:                     sizeof(CONTROLVM_MESSAGE).
- * @message_count:                     CONTROLVM_MESSAGE_MAX.
- * @gp_smbios_table:                   Guest phys addr of SMBIOS tables.
- * @gp_physical_smbios_table:          Guest phys addr of SMBIOS table.
- * @gp_reserved:                       VISOR_MAX_GUESTS_PER_SERVICE.
- * @virtual_guest_firmware_image_base: Guest physical address of EFI firmware
- *                                     image base.
- * @virtual_guest_firmware_entry_point:        Guest physical address of EFI firmware
- *                                     entry point.
- * @virtual_guest_firmware_image_size: Guest EFI firmware image size.
- * @virtual_guest_firmware_boot_base:  GPA = 1MB where EFI firmware image is
- *                                     copied to.
- * @virtual_guest_image_base:
- * @virtual_guest_image_size:
- * @prototype_control_channel_offset:
- * @virtual_guest_partition_handle:
- * @restore_action:                    Restore Action field to restore the
- *                                     guest partition.
- * @dump_action:                       For Windows guests it shows if the
- *                                     visordisk is in dump mode.
- * @nvram_fail_count:
- * @saved_crash_message_count:         = CONTROLVM_CRASHMSG_MAX.
- * @saved_crash_message_offset:                Offset to request payload area needed
- *                                     for crash dump.
- * @installation_error:                        Type of error encountered during
- *                                     installation.
- * @installation_text_id:              Id of string to display.
- * @installation_remaining_steps:      Number of remaining installation steps
- *                                     (for progress bars).
- * @tool_action:                       VISOR_TOOL_ACTIONS Installation Action
- *                                     field.
- * @reserved: Alignment.
- * @struct efi_visor_ind:
- * @sp_reserved:
- * @reserved2:                         Force signals to begin on 128-byte
- *                                     cache line.
- * @struct request_queue:              Guest partition uses this queue to send
- *                                     requests to Control.
- * @struct response_queue:             Control uses this queue to respond to
- *                                     service or guest partition request.
- * @struct event_queue:                        Control uses this queue to send events
- *                                     to guest partition.
- * @struct event_ack_queue:            Service or guest partition uses this
- *                                     queue to ack Control events.
- * @struct request_msg:                        Request fixed-size message pool -
- *                                     does not include payload.
- * @struct response_msg:               Response fixed-size message pool -
- *                                     does not include payload.
- * @struct event_msg:                  Event fixed-size message pool -
- *                                     does not include payload.
- * @struct event_ack_msg:              Ack fixed-size message pool -
- *                                     does not include payload.
- * @struct saved_crash_msg:            Message stored during IOVM creation to
- *                                     be reused after crash.
- */
-struct visor_controlvm_channel {
-       struct channel_header header;
-       u64 gp_controlvm;
-       u64 gp_partition_tables;
-       u64 gp_diag_guest;
-       u64 gp_boot_romdisk;
-       u64 gp_boot_ramdisk;
-       u64 gp_acpi_table;
-       u64 gp_control_channel;
-       u64 gp_diag_romdisk;
-       u64 gp_nvram;
-       u64 request_payload_offset;
-       u64 event_payload_offset;
-       u32 request_payload_bytes;
-       u32 event_payload_bytes;
-       u32 control_channel_bytes;
-       u32 nvram_channel_bytes;
-       u32 message_bytes;
-       u32 message_count;
-       u64 gp_smbios_table;
-       u64 gp_physical_smbios_table;
-       char gp_reserved[2688];
-       u64 virtual_guest_firmware_image_base;
-       u64 virtual_guest_firmware_entry_point;
-       u64 virtual_guest_firmware_image_size;
-       u64 virtual_guest_firmware_boot_base;
-       u64 virtual_guest_image_base;
-       u64 virtual_guest_image_size;
-       u64 prototype_control_channel_offset;
-       u64 virtual_guest_partition_handle;
-       u16 restore_action;
-       u16 dump_action;
-       u16 nvram_fail_count;
-       u16 saved_crash_message_count;
-       u32 saved_crash_message_offset;
-       u32 installation_error;
-       u32 installation_text_id;
-       u16 installation_remaining_steps;
-       u8 tool_action;
-       u8 reserved;
-       struct efi_visor_indication efi_visor_ind;
-       u32 sp_reserved;
-       u8 reserved2[28];
-       struct signal_queue_header request_queue;
-       struct signal_queue_header response_queue;
-       struct signal_queue_header event_queue;
-       struct signal_queue_header event_ack_queue;
-       struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX];
-       struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX];
-       struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX];
-       struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX];
-       struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX];
-} __packed;
-
-/*
- * struct visor_controlvm_parameters_header
- *
- * The following header will be located at the beginning of PayloadVmOffset for
- * various ControlVm commands. The receiver of a ControlVm command with a
- * PayloadVmOffset will dereference this address and then use connection_offset,
- * initiator_offset, and target_offset to get the location of UTF-8 formatted
- * strings that can be parsed to obtain command-specific information. The value
- * of total_length should equal PayloadBytes. The format of the strings at
- * PayloadVmOffset will take different forms depending on the message.
- */
-struct visor_controlvm_parameters_header {
-       u32 total_length;
-       u32 header_length;
-       u32 connection_offset;
-       u32 connection_length;
-       u32 initiator_offset;
-       u32 initiator_length;
-       u32 target_offset;
-       u32 target_length;
-       u32 client_offset;
-       u32 client_length;
-       u32 name_offset;
-       u32 name_length;
-       guid_t id;
-       u32 revision;
-       /* Natural alignment */
-       u32 reserved;
-} __packed;
-
-/* General Errors------------------------------------------------------[0-99] */
-#define CONTROLVM_RESP_SUCCESS                    0
-#define CONTROLVM_RESP_ALREADY_DONE               1
-#define CONTROLVM_RESP_IOREMAP_FAILED             2
-#define CONTROLVM_RESP_KMALLOC_FAILED             3
-#define CONTROLVM_RESP_ID_UNKNOWN                 4
-#define CONTROLVM_RESP_ID_INVALID_FOR_CLIENT      5
-/* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */
-#define CONTROLVM_RESP_CLIENT_SWITCHCOUNT_NONZERO  100
-#define CONTROLVM_RESP_EXPECTED_CHIPSET_INIT      101
-/* Maximum Limit----------------------------------------------------[200-299] */
-/* BUS_CREATE */
-#define CONTROLVM_RESP_ERROR_MAX_BUSES            201
-/* DEVICE_CREATE */
-#define CONTROLVM_RESP_ERROR_MAX_DEVICES          202
-/* Payload and Parameter Related------------------------------------[400-499] */
-/* SWITCH_ATTACHEXTPORT, DEVICE_CONFIGURE */
-#define CONTROLVM_RESP_PAYLOAD_INVALID            400
-/* Multiple */
-#define CONTROLVM_RESP_INITIATOR_PARAMETER_INVALID 401
-/* DEVICE_CONFIGURE */
-#define CONTROLVM_RESP_TARGET_PARAMETER_INVALID           402
-/* DEVICE_CONFIGURE */
-#define CONTROLVM_RESP_CLIENT_PARAMETER_INVALID           403
-/* Specified[Packet Structure] Value--------------------------------[500-599] */
-/* SWITCH_ATTACHINTPORT */
-/* BUS_CONFIGURE, DEVICE_CREATE, DEVICE_CONFIG, DEVICE_DESTROY */
-#define CONTROLVM_RESP_BUS_INVALID                500
-/* SWITCH_ATTACHINTPORT*/
-/* DEVICE_CREATE, DEVICE_CONFIGURE, DEVICE_DESTROY */
-#define CONTROLVM_RESP_DEVICE_INVALID             501
-/* DEVICE_CREATE, DEVICE_CONFIGURE */
-#define CONTROLVM_RESP_CHANNEL_INVALID            502
-/* Partition Driver Callback Interface------------------------------[600-699] */
-/* BUS_CREATE, BUS_DESTROY, DEVICE_CREATE, DEVICE_DESTROY */
-#define CONTROLVM_RESP_VIRTPCI_DRIVER_FAILURE     604
-/* Unable to invoke VIRTPCI callback. VIRTPCI Callback returned error. */
-/* BUS_CREATE, BUS_DESTROY, DEVICE_CREATE, DEVICE_DESTROY */
-#define CONTROLVM_RESP_VIRTPCI_DRIVER_CALLBACK_ERROR   605
-/* Generic device callback returned error. */
-/* SWITCH_ATTACHEXTPORT, SWITCH_DETACHEXTPORT, DEVICE_CONFIGURE */
-#define CONTROLVM_RESP_GENERIC_DRIVER_CALLBACK_ERROR   606
-/* Bus Related------------------------------------------------------[700-799] */
-/* BUS_DESTROY */
-#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED       700
-/* Channel Related--------------------------------------------------[800-899] */
-/* GET_CHANNELINFO, DEVICE_DESTROY */
-#define CONTROLVM_RESP_CHANNEL_TYPE_UNKNOWN           800
-/* DEVICE_CREATE */
-#define CONTROLVM_RESP_CHANNEL_SIZE_TOO_SMALL         801
-/* Chipset Shutdown Related---------------------------------------[1000-1099] */
-#define CONTROLVM_RESP_CHIPSET_SHUTDOWN_FAILED        1000
-#define CONTROLVM_RESP_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001
-/* Chipset Stop Related-------------------------------------------[1100-1199] */
-#define CONTROLVM_RESP_CHIPSET_STOP_FAILED_BUS        1100
-#define CONTROLVM_RESP_CHIPSET_STOP_FAILED_SWITCH      1101
-/* Device Related-------------------------------------------------[1400-1499] */
-#define CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT            1400
-
-/* __CONTROLVMCHANNEL_H__ */
-#endif
diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h
deleted file mode 100644 (file)
index 981b180..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#ifndef __VBUSCHANNEL_H__
-#define __VBUSCHANNEL_H__
-
-/*
- * The vbus channel is the channel area provided via the BUS_CREATE controlvm
- * message for each virtual bus.  This channel area is provided to both server
- * and client ends of the bus.  The channel header area is initialized by
- * the server, and the remaining information is filled in by the client.
- * We currently use this for the client to provide various information about
- * the client devices and client drivers for the server end to see.
- */
-
-#include <linux/uuid.h>
-#include "visorchannel.h"
-
-/* {193b331b-c58f-11da-95a9-00e08161165f} */
-#define VISOR_VBUS_CHANNEL_GUID                                                \
-       GUID_INIT(0x193b331b, 0xc58f, 0x11da,                           \
-                 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
-
-/*
- * Must increment this whenever you insert or delete fields within this channel
- * struct.  Also increment whenever you change the meaning of fields within this
- * channel struct so as to break pre-existing software.  Note that you can
- * usually add fields to the END of the channel struct withOUT needing to
- * increment this.
- */
-#define VISOR_VBUS_CHANNEL_VERSIONID 1
-
-/*
- * struct visor_vbus_deviceinfo
- * @devtype:  Short string identifying the device type.
- * @drvname:  Driver .sys file name.
- * @infostrs: Kernel vversion.
- * @reserved: Pad size to 256 bytes.
- *
- * An array of this struct is present in the channel area for each vbus. It is
- * filled in by the client side to provide info about the device and driver from
- * the client's perspective.
- */
-struct visor_vbus_deviceinfo {
-       u8 devtype[16];
-       u8 drvname[16];
-       u8 infostrs[96];
-       u8 reserved[128];
-} __packed;
-
-/*
- * struct visor_vbus_headerinfo
- * @struct_bytes:            Size of this struct in bytes.
- * @device_info_struct_bytes: Size of VISOR_VBUS_DEVICEINFO.
- * @dev_info_count:          Num of items in DevInfo member. This is the
- *                           allocated size.
- * @chp_info_offset:         Byte offset from beginning of this struct to the
- *                           ChpInfo struct.
- * @bus_info_offset:         Byte offset from beginning of this struct to the
- *                           BusInfo struct.
- * @dev_info_offset:         Byte offset from beginning of this struct to the
- *                           DevInfo array.
- * @reserved:                Natural alignment.
- */
-struct visor_vbus_headerinfo {
-       u32 struct_bytes;
-       u32 device_info_struct_bytes;
-       u32 dev_info_count;
-       u32 chp_info_offset;
-       u32 bus_info_offset;
-       u32 dev_info_offset;
-       u8 reserved[104];
-} __packed;
-
-/*
- * struct visor_vbus_channel
- * @channel_header: Initialized by server.
- * @hdr_info:      Initialized by server.
- * @chp_info:      Describes client chipset device and driver.
- * @bus_info:      Describes client bus device and driver.
- * @dev_info:      Describes client device and driver for each device on the
- *                 bus.
- */
-struct visor_vbus_channel {
-       struct channel_header channel_header;
-       struct visor_vbus_headerinfo hdr_info;
-       struct visor_vbus_deviceinfo chp_info;
-       struct visor_vbus_deviceinfo bus_info;
-       struct visor_vbus_deviceinfo dev_info[0];
-} __packed;
-
-#endif
diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c
deleted file mode 100644 (file)
index 6cb6eb0..0000000
+++ /dev/null
@@ -1,1243 +0,0 @@
-/*
- * Copyright ï¿½ 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#include <linux/ctype.h>
-#include <linux/debugfs.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/uuid.h>
-
-#include "visorbus.h"
-#include "visorbus_private.h"
-
-static const guid_t visor_vbus_channel_guid = VISOR_VBUS_CHANNEL_GUID;
-
-/* Display string that is guaranteed to be no longer the 99 characters */
-#define LINESIZE 99
-#define POLLJIFFIES_NORMALCHANNEL 10
-
-/* stores whether bus_registration was successful */
-static bool initialized;
-static struct dentry *visorbus_debugfs_dir;
-
-/*
- * DEVICE type attributes
- *
- * The modalias file will contain the guid of the device.
- */
-static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
-                            char *buf)
-{
-       struct visor_device *vdev;
-       const guid_t *guid;
-
-       vdev = to_visor_device(dev);
-       guid = visorchannel_get_guid(vdev->visorchannel);
-       return sprintf(buf, "visorbus:%pUl\n", guid);
-}
-static DEVICE_ATTR_RO(modalias);
-
-static struct attribute *visorbus_dev_attrs[] = {
-       &dev_attr_modalias.attr,
-       NULL,
-};
-
-ATTRIBUTE_GROUPS(visorbus_dev);
-
-/* filled in with info about parent chipset driver when we register with it */
-static struct visor_vbus_deviceinfo chipset_driverinfo;
-/* filled in with info about this driver, wrt it servicing client busses */
-static struct visor_vbus_deviceinfo clientbus_driverinfo;
-
-/* list of visor_device structs, linked via .list_all */
-static LIST_HEAD(list_all_bus_instances);
-/* list of visor_device structs, linked via .list_all */
-static LIST_HEAD(list_all_device_instances);
-
-/*
- * Generic function useful for validating any type of channel when it is
- * received by the client that will be accessing the channel.
- * Note that <logCtx> is only needed for callers in the EFI environment, and
- * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
- */
-int visor_check_channel(struct channel_header *ch, struct device *dev,
-                       const guid_t *expected_guid, char *chname,
-                       u64 expected_min_bytes, u32 expected_version,
-                       u64 expected_signature)
-{
-       if (!guid_is_null(expected_guid)) {
-               /* caller wants us to verify type GUID */
-               if (!guid_equal(&ch->chtype, expected_guid)) {
-                       dev_err(dev, "Channel mismatch on channel=%s(%pUL) field=type expected=%pUL actual=%pUL\n",
-                               chname, expected_guid, expected_guid,
-                               &ch->chtype);
-                       return 0;
-               }
-       }
-       /* verify channel size */
-       if (expected_min_bytes > 0) {
-               if (ch->size < expected_min_bytes) {
-                       dev_err(dev, "Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n",
-                               chname, expected_guid,
-                               (unsigned long long)expected_min_bytes,
-                               ch->size);
-                       return 0;
-               }
-       }
-       /* verify channel version */
-       if (expected_version > 0) {
-               if (ch->version_id != expected_version) {
-                       dev_err(dev, "Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8x\n",
-                               chname, expected_guid,
-                               (unsigned long)expected_version,
-                               ch->version_id);
-                       return 0;
-               }
-       }
-       /* verify channel signature */
-       if (expected_signature > 0) {
-               if (ch->signature != expected_signature) {
-                       dev_err(dev, "Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8Lx actual=0x%-8.8Lx\n",
-                               chname, expected_guid,  expected_signature,
-                               ch->signature);
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env)
-{
-       struct visor_device *dev;
-       const guid_t *guid;
-
-       dev = to_visor_device(xdev);
-       guid = visorchannel_get_guid(dev->visorchannel);
-       return add_uevent_var(env, "MODALIAS=visorbus:%pUl", guid);
-}
-
-/*
- * visorbus_match() - called automatically upon adding a visor_device
- *                    (device_add), or adding a visor_driver
- *                    (visorbus_register_visor_driver)
- * @xdev: struct device for the device being matched
- * @xdrv: struct device_driver for driver to match device against
- *
- * Return: 1 iff the provided driver can control the specified device
- */
-static int visorbus_match(struct device *xdev, struct device_driver *xdrv)
-{
-       const guid_t *channel_type;
-       int i;
-       struct visor_device *dev;
-       struct visor_driver *drv;
-       struct visorchannel *chan;
-
-       dev = to_visor_device(xdev);
-       channel_type = visorchannel_get_guid(dev->visorchannel);
-       drv = to_visor_driver(xdrv);
-       chan = dev->visorchannel;
-       if (!drv->channel_types)
-               return 0;
-       for (i = 0; !guid_is_null(&drv->channel_types[i].guid); i++)
-               if (guid_equal(&drv->channel_types[i].guid, channel_type) &&
-                   visor_check_channel(visorchannel_get_header(chan),
-                                       xdev,
-                                       &drv->channel_types[i].guid,
-                                       (char *)drv->channel_types[i].name,
-                                       drv->channel_types[i].min_bytes,
-                                       drv->channel_types[i].version,
-                                       VISOR_CHANNEL_SIGNATURE))
-                       return i + 1;
-       return 0;
-}
-
-/*
- * This describes the TYPE of bus.
- * (Don't confuse this with an INSTANCE of the bus.)
- */
-static struct bus_type visorbus_type = {
-       .name = "visorbus",
-       .match = visorbus_match,
-       .uevent = visorbus_uevent,
-       .dev_groups = visorbus_dev_groups,
-};
-
-struct visor_busdev {
-       u32 bus_no;
-       u32 dev_no;
-};
-
-static int match_visorbus_dev_by_id(struct device *dev, void *data)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-       struct visor_busdev *id = data;
-
-       if (vdev->chipset_bus_no == id->bus_no &&
-           vdev->chipset_dev_no == id->dev_no)
-               return 1;
-       return 0;
-}
-
-struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
-                                              struct visor_device *from)
-{
-       struct device *dev;
-       struct device *dev_start = NULL;
-       struct visor_busdev id = {
-               .bus_no = bus_no,
-               .dev_no = dev_no
-       };
-
-       if (from)
-               dev_start = &from->device;
-       dev = bus_find_device(&visorbus_type, dev_start, (void *)&id,
-                             match_visorbus_dev_by_id);
-       if (!dev)
-               return NULL;
-       return to_visor_device(dev);
-}
-
-/*
- * visorbus_release_busdevice() - called when device_unregister() is called for
- *                                the bus device instance, after all other tasks
- *                                involved with destroying the dev are complete
- * @xdev: struct device for the bus being released
- */
-static void visorbus_release_busdevice(struct device *xdev)
-{
-       struct visor_device *dev = dev_get_drvdata(xdev);
-
-       debugfs_remove(dev->debugfs_bus_info);
-       debugfs_remove_recursive(dev->debugfs_dir);
-       visorchannel_destroy(dev->visorchannel);
-       kfree(dev);
-}
-
-/*
- * visorbus_release_device() - called when device_unregister() is called for
- *                             each child device instance
- * @xdev: struct device for the visor device being released
- */
-static void visorbus_release_device(struct device *xdev)
-{
-       struct visor_device *dev = to_visor_device(xdev);
-
-       visorchannel_destroy(dev->visorchannel);
-       kfree(dev);
-}
-
-/*
- * BUS specific channel attributes to appear under
- * /sys/bus/visorbus<x>/dev<y>/channel
- */
-
-static ssize_t physaddr_show(struct device *dev, struct device_attribute *attr,
-                            char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-
-       return sprintf(buf, "0x%llx\n",
-                      visorchannel_get_physaddr(vdev->visorchannel));
-}
-static DEVICE_ATTR_RO(physaddr);
-
-static ssize_t nbytes_show(struct device *dev, struct device_attribute *attr,
-                          char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-
-       return sprintf(buf, "0x%lx\n",
-                      visorchannel_get_nbytes(vdev->visorchannel));
-}
-static DEVICE_ATTR_RO(nbytes);
-
-static ssize_t clientpartition_show(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-
-       return sprintf(buf, "0x%llx\n",
-                      visorchannel_get_clientpartition(vdev->visorchannel));
-}
-static DEVICE_ATTR_RO(clientpartition);
-
-static ssize_t typeguid_show(struct device *dev, struct device_attribute *attr,
-                            char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-       char typeid[LINESIZE];
-
-       return sprintf(buf, "%s\n",
-                      visorchannel_id(vdev->visorchannel, typeid));
-}
-static DEVICE_ATTR_RO(typeguid);
-
-static ssize_t zoneguid_show(struct device *dev, struct device_attribute *attr,
-                            char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-       char zoneid[LINESIZE];
-
-       return sprintf(buf, "%s\n",
-                      visorchannel_zoneid(vdev->visorchannel, zoneid));
-}
-static DEVICE_ATTR_RO(zoneguid);
-
-static ssize_t typename_show(struct device *dev, struct device_attribute *attr,
-                            char *buf)
-{
-       int i = 0;
-       struct bus_type *xbus = dev->bus;
-       struct device_driver *xdrv = dev->driver;
-       struct visor_driver *drv = NULL;
-
-       if (!xdrv)
-               return 0;
-       i = xbus->match(dev, xdrv);
-       if (!i)
-               return 0;
-       drv = to_visor_driver(xdrv);
-       return sprintf(buf, "%s\n", drv->channel_types[i - 1].name);
-}
-static DEVICE_ATTR_RO(typename);
-
-static struct attribute *channel_attrs[] = {
-       &dev_attr_physaddr.attr,
-       &dev_attr_nbytes.attr,
-       &dev_attr_clientpartition.attr,
-       &dev_attr_typeguid.attr,
-       &dev_attr_zoneguid.attr,
-       &dev_attr_typename.attr,
-       NULL
-};
-
-ATTRIBUTE_GROUPS(channel);
-
-/*
- *  BUS instance attributes
- *
- *  define & implement display of bus attributes under
- *  /sys/bus/visorbus/devices/visorbus<n>.
- */
-static ssize_t partition_handle_show(struct device *dev,
-                                    struct device_attribute *attr, char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-       u64 handle = visorchannel_get_clientpartition(vdev->visorchannel);
-
-       return sprintf(buf, "0x%llx\n", handle);
-}
-static DEVICE_ATTR_RO(partition_handle);
-
-static ssize_t partition_guid_show(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-
-       return sprintf(buf, "{%pUb}\n", &vdev->partition_guid);
-}
-static DEVICE_ATTR_RO(partition_guid);
-
-static ssize_t partition_name_show(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-
-       return sprintf(buf, "%s\n", vdev->name);
-}
-static DEVICE_ATTR_RO(partition_name);
-
-static ssize_t channel_addr_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-       u64 addr = visorchannel_get_physaddr(vdev->visorchannel);
-
-       return sprintf(buf, "0x%llx\n", addr);
-}
-static DEVICE_ATTR_RO(channel_addr);
-
-static ssize_t channel_bytes_show(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-       u64 nbytes = visorchannel_get_nbytes(vdev->visorchannel);
-
-       return sprintf(buf, "0x%llx\n", nbytes);
-}
-static DEVICE_ATTR_RO(channel_bytes);
-
-static ssize_t channel_id_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
-{
-       struct visor_device *vdev = to_visor_device(dev);
-       int len = 0;
-
-       visorchannel_id(vdev->visorchannel, buf);
-       len = strlen(buf);
-       buf[len++] = '\n';
-       return len;
-}
-static DEVICE_ATTR_RO(channel_id);
-
-static struct attribute *visorbus_attrs[] = {
-       &dev_attr_partition_handle.attr,
-       &dev_attr_partition_guid.attr,
-       &dev_attr_partition_name.attr,
-       &dev_attr_channel_addr.attr,
-       &dev_attr_channel_bytes.attr,
-       &dev_attr_channel_id.attr,
-       NULL
-};
-
-ATTRIBUTE_GROUPS(visorbus);
-
-/*
- *  BUS debugfs entries
- *
- *  define & implement display of debugfs attributes under
- *  /sys/kernel/debug/visorbus/visorbus<n>.
- */
-
-/*
- * vbuschannel_print_devinfo() - format a struct visor_vbus_deviceinfo
- *                               and write it to a seq_file
- * @devinfo: the struct visor_vbus_deviceinfo to format
- * @seq: seq_file to write to
- * @devix: the device index to be included in the output data, or -1 if no
- *         device index is to be included
- *
- * Reads @devInfo, and writes it in human-readable notation to @seq.
- */
-static void vbuschannel_print_devinfo(struct visor_vbus_deviceinfo *devinfo,
-                                     struct seq_file *seq, int devix)
-{
-       /* uninitialized vbus device entry */
-       if (!isprint(devinfo->devtype[0]))
-               return;
-       if (devix >= 0)
-               seq_printf(seq, "[%d]", devix);
-       else
-               /* vbus device entry is for bus or chipset */
-               seq_puts(seq, "   ");
-       /*
-        * Note: because the s-Par back-end is free to scribble in this area,
-        * we never assume '\0'-termination.
-        */
-       seq_printf(seq, "%-*.*s ", (int)sizeof(devinfo->devtype),
-                  (int)sizeof(devinfo->devtype), devinfo->devtype);
-       seq_printf(seq, "%-*.*s ", (int)sizeof(devinfo->drvname),
-                  (int)sizeof(devinfo->drvname), devinfo->drvname);
-       seq_printf(seq, "%.*s\n", (int)sizeof(devinfo->infostrs),
-                  devinfo->infostrs);
-}
-
-static int bus_info_debugfs_show(struct seq_file *seq, void *v)
-{
-       int i = 0;
-       unsigned long off;
-       struct visor_vbus_deviceinfo dev_info;
-       struct visor_device *vdev = seq->private;
-       struct visorchannel *channel = vdev->visorchannel;
-
-       if (!channel)
-               return 0;
-
-       seq_printf(seq,
-                  "Client device/driver info for %s partition (vbus #%u):\n",
-                  ((vdev->name) ? (char *)(vdev->name) : ""),
-                  vdev->chipset_bus_no);
-       if (visorchannel_read(channel,
-                             offsetof(struct visor_vbus_channel, chp_info),
-                             &dev_info, sizeof(dev_info)) >= 0)
-               vbuschannel_print_devinfo(&dev_info, seq, -1);
-       if (visorchannel_read(channel,
-                             offsetof(struct visor_vbus_channel, bus_info),
-                             &dev_info, sizeof(dev_info)) >= 0)
-               vbuschannel_print_devinfo(&dev_info, seq, -1);
-
-       off = offsetof(struct visor_vbus_channel, dev_info);
-       while (off + sizeof(dev_info) <= visorchannel_get_nbytes(channel)) {
-               if (visorchannel_read(channel, off, &dev_info,
-                                     sizeof(dev_info)) >= 0)
-                       vbuschannel_print_devinfo(&dev_info, seq, i);
-               off += sizeof(dev_info);
-               i++;
-       }
-       return 0;
-}
-
-static int bus_info_debugfs_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, bus_info_debugfs_show, inode->i_private);
-}
-
-static const struct file_operations bus_info_debugfs_fops = {
-       .owner = THIS_MODULE,
-       .open = bus_info_debugfs_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static void dev_periodic_work(struct timer_list *t)
-{
-       struct visor_device *dev = from_timer(dev, t, timer);
-       struct visor_driver *drv = to_visor_driver(dev->device.driver);
-
-       drv->channel_interrupt(dev);
-       mod_timer(&dev->timer, jiffies + POLLJIFFIES_NORMALCHANNEL);
-}
-
-static int dev_start_periodic_work(struct visor_device *dev)
-{
-       if (dev->being_removed || dev->timer_active)
-               return -EINVAL;
-
-       /* now up by at least 2 */
-       get_device(&dev->device);
-       dev->timer.expires = jiffies + POLLJIFFIES_NORMALCHANNEL;
-       add_timer(&dev->timer);
-       dev->timer_active = true;
-       return 0;
-}
-
-static void dev_stop_periodic_work(struct visor_device *dev)
-{
-       if (!dev->timer_active)
-               return;
-
-       del_timer_sync(&dev->timer);
-       dev->timer_active = false;
-       put_device(&dev->device);
-}
-
-/*
- * visordriver_remove_device() - handle visor device going away
- * @xdev: struct device for the visor device being removed
- *
- * This is called when device_unregister() is called for each child device
- * instance, to notify the appropriate visorbus function driver that the device
- * is going away, and to decrease the reference count of the device.
- *
- * Return: 0 iff successful
- */
-static int visordriver_remove_device(struct device *xdev)
-{
-       struct visor_device *dev = to_visor_device(xdev);
-       struct visor_driver *drv = to_visor_driver(xdev->driver);
-
-       mutex_lock(&dev->visordriver_callback_lock);
-       dev->being_removed = true;
-       drv->remove(dev);
-       mutex_unlock(&dev->visordriver_callback_lock);
-       dev_stop_periodic_work(dev);
-       put_device(&dev->device);
-       return 0;
-}
-
-/*
- * visorbus_unregister_visor_driver() - unregisters the provided driver
- * @drv: the driver to unregister
- *
- * A visor function driver calls this function to unregister the driver,
- * i.e., within its module_exit function.
- */
-void visorbus_unregister_visor_driver(struct visor_driver *drv)
-{
-       driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver);
-
-/*
- * visorbus_read_channel() - reads from the designated channel into
- *                           the provided buffer
- * @dev:    the device whose channel is read from
- * @offset: the offset into the channel at which reading starts
- * @dest:   the destination buffer that is written into from the channel
- * @nbytes: the number of bytes to read from the channel
- *
- * If receiving a message, use the visorchannel_signalremove() function instead.
- *
- * Return: integer indicating success (zero) or failure (non-zero)
- */
-int visorbus_read_channel(struct visor_device *dev, unsigned long offset,
-                         void *dest, unsigned long nbytes)
-{
-       return visorchannel_read(dev->visorchannel, offset, dest, nbytes);
-}
-EXPORT_SYMBOL_GPL(visorbus_read_channel);
-
-/*
- * visorbus_write_channel() - writes the provided buffer into the designated
- *                            channel
- * @dev:    the device whose channel is written to
- * @offset: the offset into the channel at which writing starts
- * @src:    the source buffer that is written into the channel
- * @nbytes: the number of bytes to write into the channel
- *
- * If sending a message, use the visorchannel_signalinsert() function instead.
- *
- * Return: integer indicating success (zero) or failure (non-zero)
- */
-int visorbus_write_channel(struct visor_device *dev, unsigned long offset,
-                          void *src, unsigned long nbytes)
-{
-       return visorchannel_write(dev->visorchannel, offset, src, nbytes);
-}
-EXPORT_SYMBOL_GPL(visorbus_write_channel);
-
-/*
- * visorbus_enable_channel_interrupts() - enables interrupts on the
- *                                        designated device
- * @dev: the device on which to enable interrupts
- *
- * Currently we don't yet have a real interrupt, so for now we just call the
- * interrupt function periodically via a timer.
- */
-int visorbus_enable_channel_interrupts(struct visor_device *dev)
-{
-       struct visor_driver *drv = to_visor_driver(dev->device.driver);
-
-       if (!drv->channel_interrupt) {
-               dev_err(&dev->device, "%s no interrupt function!\n", __func__);
-               return -ENOENT;
-       }
-
-       return dev_start_periodic_work(dev);
-}
-EXPORT_SYMBOL_GPL(visorbus_enable_channel_interrupts);
-
-/*
- * visorbus_disable_channel_interrupts() - disables interrupts on the
- *                                         designated device
- * @dev: the device on which to disable interrupts
- */
-void visorbus_disable_channel_interrupts(struct visor_device *dev)
-{
-       dev_stop_periodic_work(dev);
-}
-EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts);
-
-/*
- * create_visor_device() - create visor device as a result of receiving the
- *                         controlvm device_create message for a new device
- * @dev: a freshly-zeroed struct visor_device, containing only filled-in values
- *       for chipset_bus_no and chipset_dev_no, that will be initialized
- *
- * This is how everything starts from the device end.
- * This function is called when a channel first appears via a ControlVM
- * message.  In response, this function allocates a visor_device to correspond
- * to the new channel, and attempts to connect it the appropriate * driver. If
- * the appropriate driver is found, the visor_driver.probe() function for that
- * driver will be called, and will be passed the new * visor_device that we
- * just created.
- *
- * It's ok if the appropriate driver is not yet loaded, because in that case
- * the new device struct will just stick around in the bus' list of devices.
- * When the appropriate driver calls visorbus_register_visor_driver(), the
- * visor_driver.probe() for the new driver will be called with the new device.
- *
- * Return: 0 if successful, otherwise the negative value returned by
- *         device_add() indicating the reason for failure
- */
-int create_visor_device(struct visor_device *dev)
-{
-       int err;
-       u32 chipset_bus_no = dev->chipset_bus_no;
-       u32 chipset_dev_no = dev->chipset_dev_no;
-
-       mutex_init(&dev->visordriver_callback_lock);
-       dev->device.bus = &visorbus_type;
-       dev->device.groups = channel_groups;
-       device_initialize(&dev->device);
-       dev->device.release = visorbus_release_device;
-       /* keep a reference just for us (now 2) */
-       get_device(&dev->device);
-       timer_setup(&dev->timer, dev_periodic_work, 0);
-       /*
-        * bus_id must be a unique name with respect to this bus TYPE (NOT bus
-        * instance).  That's why we need to include the bus number within the
-        * name.
-        */
-       err = dev_set_name(&dev->device, "vbus%u:dev%u",
-                          chipset_bus_no, chipset_dev_no);
-       if (err)
-               goto err_put;
-       /*
-        * device_add does this:
-        *    bus_add_device(dev)
-        *    ->device_attach(dev)
-        *      ->for each driver drv registered on the bus that dev is on
-        *          if (dev.drv)  **  device already has a driver **
-        *            ** not sure we could ever get here... **
-        *          else
-        *            if (bus.match(dev,drv)) [visorbus_match]
-        *              dev.drv = drv
-        *              if (!drv.probe(dev))  [visordriver_probe_device]
-        *                dev.drv = NULL
-        *
-        * Note that device_add does NOT fail if no driver failed to claim the
-        * device.  The device will be linked onto bus_type.klist_devices
-        * regardless (use bus_for_each_dev).
-        */
-       err = device_add(&dev->device);
-       if (err < 0)
-               goto err_put;
-       list_add_tail(&dev->list_all, &list_all_device_instances);
-       dev->state.created = 1;
-       visorbus_response(dev, err, CONTROLVM_DEVICE_CREATE);
-       /* success: reference kept via unmatched get_device() */
-       return 0;
-
-err_put:
-       put_device(&dev->device);
-       dev_err(&dev->device, "Creating visor device failed. %d\n", err);
-       return err;
-}
-
-void remove_visor_device(struct visor_device *dev)
-{
-       list_del(&dev->list_all);
-       put_device(&dev->device);
-       if (dev->pending_msg_hdr)
-               visorbus_response(dev, 0, CONTROLVM_DEVICE_DESTROY);
-       device_unregister(&dev->device);
-}
-
-static int get_vbus_header_info(struct visorchannel *chan,
-                               struct device *dev,
-                               struct visor_vbus_headerinfo *hdr_info)
-{
-       int err;
-
-       if (!visor_check_channel(visorchannel_get_header(chan),
-                                dev,
-                                &visor_vbus_channel_guid,
-                                "vbus",
-                                sizeof(struct visor_vbus_channel),
-                                VISOR_VBUS_CHANNEL_VERSIONID,
-                                VISOR_CHANNEL_SIGNATURE))
-               return -EINVAL;
-
-       err = visorchannel_read(chan, sizeof(struct channel_header), hdr_info,
-                               sizeof(*hdr_info));
-       if (err < 0)
-               return err;
-       if (hdr_info->struct_bytes < sizeof(struct visor_vbus_headerinfo))
-               return -EINVAL;
-       if (hdr_info->device_info_struct_bytes <
-           sizeof(struct visor_vbus_deviceinfo))
-               return -EINVAL;
-       return 0;
-}
-
-/*
- * write_vbus_chp_info() - write the contents of <info> to the struct
- *                         visor_vbus_channel.chp_info
- * @chan:     indentifies the s-Par channel that will be updated
- * @hdr_info: used to find appropriate channel offset to write data
- * @info:     contains the information to write
- *
- * Writes chipset info into the channel memory to be used for diagnostic
- * purposes.
- *
- * Returns no value since this is debug information and not needed for
- * device functionality.
- */
-static void write_vbus_chp_info(struct visorchannel *chan,
-                               struct visor_vbus_headerinfo *hdr_info,
-                               struct visor_vbus_deviceinfo *info)
-{
-       int off;
-
-       if (hdr_info->chp_info_offset == 0)
-               return;
-
-       off = sizeof(struct channel_header) + hdr_info->chp_info_offset;
-       visorchannel_write(chan, off, info, sizeof(*info));
-}
-
-/*
- * write_vbus_bus_info() - write the contents of <info> to the struct
- *                         visor_vbus_channel.bus_info
- * @chan:     indentifies the s-Par channel that will be updated
- * @hdr_info: used to find appropriate channel offset to write data
- * @info:     contains the information to write
- *
- * Writes bus info into the channel memory to be used for diagnostic
- * purposes.
- *
- * Returns no value since this is debug information and not needed for
- * device functionality.
- */
-static void write_vbus_bus_info(struct visorchannel *chan,
-                               struct visor_vbus_headerinfo *hdr_info,
-                               struct visor_vbus_deviceinfo *info)
-{
-       int off;
-
-       if (hdr_info->bus_info_offset == 0)
-               return;
-
-       off = sizeof(struct channel_header) + hdr_info->bus_info_offset;
-       visorchannel_write(chan, off, info, sizeof(*info));
-}
-
-/*
- * write_vbus_dev_info() - write the contents of <info> to the struct
- *                         visor_vbus_channel.dev_info[<devix>]
- * @chan:     indentifies the s-Par channel that will be updated
- * @hdr_info: used to find appropriate channel offset to write data
- * @info:     contains the information to write
- * @devix:    the relative device number (0..n-1) of the device on the bus
- *
- * Writes device info into the channel memory to be used for diagnostic
- * purposes.
- *
- * Returns no value since this is debug information and not needed for
- * device functionality.
- */
-static void write_vbus_dev_info(struct visorchannel *chan,
-                               struct visor_vbus_headerinfo *hdr_info,
-                               struct visor_vbus_deviceinfo *info,
-                               unsigned int devix)
-{
-       int off;
-
-       if (hdr_info->dev_info_offset == 0)
-               return;
-       off = (sizeof(struct channel_header) + hdr_info->dev_info_offset) +
-             (hdr_info->device_info_struct_bytes * devix);
-       visorchannel_write(chan, off, info, sizeof(*info));
-}
-
-static void bus_device_info_init(
-               struct visor_vbus_deviceinfo *bus_device_info_ptr,
-               const char *dev_type, const char *drv_name)
-{
-       memset(bus_device_info_ptr, 0, sizeof(struct visor_vbus_deviceinfo));
-       snprintf(bus_device_info_ptr->devtype,
-                sizeof(bus_device_info_ptr->devtype),
-                "%s", (dev_type) ? dev_type : "unknownType");
-       snprintf(bus_device_info_ptr->drvname,
-                sizeof(bus_device_info_ptr->drvname),
-                "%s", (drv_name) ? drv_name : "unknownDriver");
-       snprintf(bus_device_info_ptr->infostrs,
-                sizeof(bus_device_info_ptr->infostrs), "kernel ver. %s",
-                utsname()->release);
-}
-
-/*
- * publish_vbus_dev_info() - for a child device just created on a client bus,
- *                          fill in information about the driver that is
- *                          controlling this device into the appropriate slot
- *                          within the vbus channel of the bus instance
- * @visordev: struct visor_device for the desired device
- */
-static void publish_vbus_dev_info(struct visor_device *visordev)
-{
-       int i;
-       struct visor_device *bdev;
-       struct visor_driver *visordrv;
-       u32 bus_no = visordev->chipset_bus_no;
-       u32 dev_no = visordev->chipset_dev_no;
-       struct visor_vbus_deviceinfo dev_info;
-       const char *chan_type_name = NULL;
-       struct visor_vbus_headerinfo *hdr_info;
-
-       if (!visordev->device.driver)
-               return;
-       bdev = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-       if (!bdev)
-               return;
-       hdr_info = (struct visor_vbus_headerinfo *)bdev->vbus_hdr_info;
-       if (!hdr_info)
-               return;
-       visordrv = to_visor_driver(visordev->device.driver);
-
-       /*
-        * Within the list of device types (by GUID) that the driver
-        * says it supports, find out which one of those types matches
-        * the type of this device, so that we can include the device
-        * type name
-        */
-       for (i = 0; visordrv->channel_types[i].name; i++) {
-               if (guid_equal(&visordrv->channel_types[i].guid,
-                              &visordev->channel_type_guid)) {
-                       chan_type_name = visordrv->channel_types[i].name;
-                       break;
-               }
-       }
-       bus_device_info_init(&dev_info, chan_type_name, visordrv->name);
-       write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no);
-       write_vbus_chp_info(bdev->visorchannel, hdr_info, &chipset_driverinfo);
-       write_vbus_bus_info(bdev->visorchannel, hdr_info,
-                           &clientbus_driverinfo);
-}
-
-/*
- * visordriver_probe_device() - handle new visor device coming online
- * @xdev: struct device for the visor device being probed
- *
- * This is called automatically upon adding a visor_device (device_add), or
- * adding a visor_driver (visorbus_register_visor_driver), but only after
- * visorbus_match() has returned 1 to indicate a successful match between
- * driver and device.
- *
- * If successful, a reference to the device will be held onto via get_device().
- *
- * Return: 0 if successful, meaning the function driver's probe() function
- *         was successful with this device, otherwise a negative errno
- *         value indicating failure reason
- */
-static int visordriver_probe_device(struct device *xdev)
-{
-       int err;
-       struct visor_driver *drv = to_visor_driver(xdev->driver);
-       struct visor_device *dev = to_visor_device(xdev);
-
-       mutex_lock(&dev->visordriver_callback_lock);
-       dev->being_removed = false;
-       err = drv->probe(dev);
-       if (err) {
-               mutex_unlock(&dev->visordriver_callback_lock);
-               return err;
-       }
-       /* success: reference kept via unmatched get_device() */
-       get_device(&dev->device);
-       publish_vbus_dev_info(dev);
-       mutex_unlock(&dev->visordriver_callback_lock);
-       return 0;
-}
-
-/*
- * visorbus_register_visor_driver() - registers the provided visor driver for
- *                                   handling one or more visor device
- *                                    types (channel_types)
- * @drv: the driver to register
- *
- * A visor function driver calls this function to register the driver. The
- * caller MUST fill in the following fields within the #drv structure:
- *     name, version, owner, channel_types, probe, remove
- *
- * Here's how the whole Linux bus / driver / device model works.
- *
- * At system start-up, the visorbus kernel module is loaded, which registers
- * visorbus_type as a bus type, using bus_register().
- *
- * All kernel modules that support particular device types on a
- * visorbus bus are loaded.  Each of these kernel modules calls
- * visorbus_register_visor_driver() in their init functions, passing a
- * visor_driver struct.  visorbus_register_visor_driver() in turn calls
- * register_driver(&visor_driver.driver).  This .driver member is
- * initialized with generic methods (like probe), whose sole responsibility
- * is to act as a broker for the real methods, which are within the
- * visor_driver struct.  (This is the way the subclass behavior is
- * implemented, since visor_driver is essentially a subclass of the
- * generic driver.)  Whenever a driver_register() happens, core bus code in
- * the kernel does (see device_attach() in drivers/base/dd.c):
- *
- *     for each dev associated with the bus (the bus that driver is on) that
- *     does not yet have a driver
- *         if bus.match(dev,newdriver) == yes_matched  ** .match specified
- *                                                ** during bus_register().
- *             newdriver.probe(dev)  ** for visor drivers, this will call
- *                   ** the generic driver.probe implemented in visorbus.c,
- *                   ** which in turn calls the probe specified within the
- *                   ** struct visor_driver (which was specified by the
- *                   ** actual device driver as part of
- *                   ** visorbus_register_visor_driver()).
- *
- * The above dance also happens when a new device appears.
- * So the question is, how are devices created within the system?
- * Basically, just call device_add(dev).  See pci_bus_add_devices().
- * pci_scan_device() shows an example of how to build a device struct.  It
- * returns the newly-created struct to pci_scan_single_device(), who adds it
- * to the list of devices at PCIBUS.devices.  That list of devices is what
- * is traversed by pci_bus_add_devices().
- *
- * Return: integer indicating success (zero) or failure (non-zero)
- */
-int visorbus_register_visor_driver(struct visor_driver *drv)
-{
-       /* can't register on a nonexistent bus */
-       if (!initialized)
-               return -ENODEV;
-       if (!drv->probe)
-               return -EINVAL;
-       if (!drv->remove)
-               return -EINVAL;
-       if (!drv->pause)
-               return -EINVAL;
-       if (!drv->resume)
-               return -EINVAL;
-
-       drv->driver.name = drv->name;
-       drv->driver.bus = &visorbus_type;
-       drv->driver.probe = visordriver_probe_device;
-       drv->driver.remove = visordriver_remove_device;
-       drv->driver.owner = drv->owner;
-       /*
-        * driver_register does this:
-        *   bus_add_driver(drv)
-        *   ->if (drv.bus)  ** (bus_type) **
-        *       driver_attach(drv)
-        *         for each dev with bus type of drv.bus
-        *           if (!dev.drv)  ** no driver assigned yet **
-        *             if (bus.match(dev,drv))  [visorbus_match]
-        *               dev.drv = drv
-        *               if (!drv.probe(dev))   [visordriver_probe_device]
-        *                 dev.drv = NULL
-        */
-       return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL_GPL(visorbus_register_visor_driver);
-
-/*
- * visorbus_create_instance() - create a device instance for the visorbus itself
- * @dev: struct visor_device indicating the bus instance
- *
- * Return: 0 for success, otherwise negative errno value indicating reason for
- *         failure
- */
-int visorbus_create_instance(struct visor_device *dev)
-{
-       int id = dev->chipset_bus_no;
-       int err;
-       struct visor_vbus_headerinfo *hdr_info;
-
-       hdr_info = kzalloc(sizeof(*hdr_info), GFP_KERNEL);
-       if (!hdr_info)
-               return -ENOMEM;
-       dev_set_name(&dev->device, "visorbus%d", id);
-       dev->device.bus = &visorbus_type;
-       dev->device.groups = visorbus_groups;
-       dev->device.release = visorbus_release_busdevice;
-       dev->debugfs_dir = debugfs_create_dir(dev_name(&dev->device),
-                                             visorbus_debugfs_dir);
-       dev->debugfs_bus_info = debugfs_create_file("client_bus_info", 0440,
-                                                   dev->debugfs_dir, dev,
-                                                   &bus_info_debugfs_fops);
-       dev_set_drvdata(&dev->device, dev);
-       err = get_vbus_header_info(dev->visorchannel, &dev->device, hdr_info);
-       if (err < 0)
-               goto err_debugfs_dir;
-       err = device_register(&dev->device);
-       if (err < 0)
-               goto err_debugfs_dir;
-       list_add_tail(&dev->list_all, &list_all_bus_instances);
-       dev->state.created = 1;
-       dev->vbus_hdr_info = (void *)hdr_info;
-       write_vbus_chp_info(dev->visorchannel, hdr_info, &chipset_driverinfo);
-       write_vbus_bus_info(dev->visorchannel, hdr_info, &clientbus_driverinfo);
-       visorbus_response(dev, err, CONTROLVM_BUS_CREATE);
-       return 0;
-
-err_debugfs_dir:
-       debugfs_remove_recursive(dev->debugfs_dir);
-       kfree(hdr_info);
-       dev_err(&dev->device, "%s failed: %d\n", __func__, err);
-       return err;
-}
-
-/*
- * visorbus_remove_instance() - remove a device instance for the visorbus itself
- * @dev: struct visor_device indentifying the bus to remove
- */
-void visorbus_remove_instance(struct visor_device *dev)
-{
-       /*
-        * Note that this will result in the release method for
-        * dev->dev being called, which will call
-        * visorbus_release_busdevice().  This has something to do with
-        * the put_device() done in device_unregister(), but I have never
-        * successfully been able to trace thru the code to see where/how
-        * release() gets called.  But I know it does.
-        */
-       kfree(dev->vbus_hdr_info);
-       list_del(&dev->list_all);
-       if (dev->pending_msg_hdr)
-               visorbus_response(dev, 0, CONTROLVM_BUS_DESTROY);
-       device_unregister(&dev->device);
-}
-
-/*
- * remove_all_visor_devices() - remove all child visorbus device instances
- */
-static void remove_all_visor_devices(void)
-{
-       struct list_head *listentry, *listtmp;
-
-       list_for_each_safe(listentry, listtmp, &list_all_device_instances) {
-               struct visor_device *dev;
-
-               dev = list_entry(listentry, struct visor_device, list_all);
-               remove_visor_device(dev);
-       }
-}
-
-/*
- * pause_state_change_complete() - the callback function to be called by a
- *                                 visorbus function driver when a
- *                                 pending "pause device" operation has
- *                                 completed
- * @dev: struct visor_device identifying the paused device
- * @status: 0 iff the pause state change completed successfully, otherwise
- *          a negative errno value indicating the reason for failure
- */
-static void pause_state_change_complete(struct visor_device *dev, int status)
-{
-       if (!dev->pausing)
-               return;
-
-       dev->pausing = false;
-       visorbus_device_changestate_response(dev, status,
-                                            segment_state_standby);
-}
-
-/*
- * resume_state_change_complete() - the callback function to be called by a
- *                                  visorbus function driver when a
- *                                  pending "resume device" operation has
- *                                  completed
- * @dev: struct visor_device identifying the resumed device
- * @status: 0 iff the resume state change completed successfully, otherwise
- *          a negative errno value indicating the reason for failure
- */
-static void resume_state_change_complete(struct visor_device *dev, int status)
-{
-       if (!dev->resuming)
-               return;
-
-       dev->resuming = false;
-       /*
-        * Notify the chipset driver that the resume is complete,
-        * which will presumably want to send some sort of response to
-        * the initiator.
-        */
-       visorbus_device_changestate_response(dev, status,
-                                            segment_state_running);
-}
-
-/*
- * visorchipset_initiate_device_pause_resume() - start a pause or resume
- *                                               operation for a visor device
- * @dev: struct visor_device identifying the device being paused or resumed
- * @is_pause: true to indicate pause operation, false to indicate resume
- *
- * Tell the subordinate function driver for a specific device to pause
- * or resume that device.  Success/failure result is returned asynchronously
- * via a callback function; see pause_state_change_complete() and
- * resume_state_change_complete().
- */
-static int visorchipset_initiate_device_pause_resume(struct visor_device *dev,
-                                                    bool is_pause)
-{
-       int err;
-       struct visor_driver *drv;
-
-       /* If no driver associated with the device nothing to pause/resume */
-       if (!dev->device.driver)
-               return 0;
-       if (dev->pausing || dev->resuming)
-               return -EBUSY;
-
-       drv = to_visor_driver(dev->device.driver);
-       if (is_pause) {
-               dev->pausing = true;
-               err = drv->pause(dev, pause_state_change_complete);
-       } else {
-               /*
-                * The vbus_dev_info structure in the channel was been cleared,
-                * make sure it is valid.
-                */
-               publish_vbus_dev_info(dev);
-               dev->resuming = true;
-               err = drv->resume(dev, resume_state_change_complete);
-       }
-       return err;
-}
-
-/*
- * visorchipset_device_pause() - start a pause operation for a visor device
- * @dev_info: struct visor_device identifying the device being paused
- *
- * Tell the subordinate function driver for a specific device to pause
- * that device.  Success/failure result is returned asynchronously
- * via a callback function; see pause_state_change_complete().
- */
-int visorchipset_device_pause(struct visor_device *dev_info)
-{
-       int err;
-
-       err = visorchipset_initiate_device_pause_resume(dev_info, true);
-       if (err < 0) {
-               dev_info->pausing = false;
-               return err;
-       }
-       return 0;
-}
-
-/*
- * visorchipset_device_resume() - start a resume operation for a visor device
- * @dev_info: struct visor_device identifying the device being resumed
- *
- * Tell the subordinate function driver for a specific device to resume
- * that device.  Success/failure result is returned asynchronously
- * via a callback function; see resume_state_change_complete().
- */
-int visorchipset_device_resume(struct visor_device *dev_info)
-{
-       int err;
-
-       err = visorchipset_initiate_device_pause_resume(dev_info, false);
-       if (err < 0) {
-               dev_info->resuming = false;
-               return err;
-       }
-       return 0;
-}
-
-int visorbus_init(void)
-{
-       int err;
-
-       visorbus_debugfs_dir = debugfs_create_dir("visorbus", NULL);
-       bus_device_info_init(&clientbus_driverinfo, "clientbus", "visorbus");
-       err = bus_register(&visorbus_type);
-       if (err < 0)
-               return err;
-       initialized = true;
-       bus_device_info_init(&chipset_driverinfo, "chipset", "visorchipset");
-       return 0;
-}
-
-void visorbus_exit(void)
-{
-       struct list_head *listentry, *listtmp;
-
-       remove_all_visor_devices();
-       list_for_each_safe(listentry, listtmp, &list_all_bus_instances) {
-               struct visor_device *dev;
-
-               dev = list_entry(listentry, struct visor_device, list_all);
-               visorbus_remove_instance(dev);
-       }
-       bus_unregister(&visorbus_type);
-       initialized = false;
-       debugfs_remove_recursive(visorbus_debugfs_dir);
-}
diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h
deleted file mode 100644 (file)
index 4a8b12d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#ifndef __VISORBUS_PRIVATE_H__
-#define __VISORBUS_PRIVATE_H__
-
-#include <linux/uuid.h>
-#include <linux/utsname.h>
-
-#include "controlvmchannel.h"
-#include "vbuschannel.h"
-#include "visorbus.h"
-
-struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
-                                              struct visor_device *from);
-int visorbus_create_instance(struct visor_device *dev);
-void visorbus_remove_instance(struct visor_device *bus_info);
-int create_visor_device(struct visor_device *dev_info);
-void remove_visor_device(struct visor_device *dev_info);
-int visorchipset_device_pause(struct visor_device *dev_info);
-int visorchipset_device_resume(struct visor_device *dev_info);
-void visorbus_response(struct visor_device *p, int response, int controlvm_id);
-void visorbus_device_changestate_response(struct visor_device *p, int response,
-                                         struct visor_segment_state state);
-int visorbus_init(void);
-void visorbus_exit(void);
-
-/* visorchannel access functions */
-struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
-                                        const guid_t *guid, bool needs_lock);
-void visorchannel_destroy(struct visorchannel *channel);
-int visorchannel_read(struct visorchannel *channel, ulong offset,
-                     void *dest, ulong nbytes);
-int visorchannel_write(struct visorchannel *channel, ulong offset,
-                      void *dest, ulong nbytes);
-u64 visorchannel_get_physaddr(struct visorchannel *channel);
-ulong visorchannel_get_nbytes(struct visorchannel *channel);
-char *visorchannel_id(struct visorchannel *channel, char *s);
-char *visorchannel_zoneid(struct visorchannel *channel, char *s);
-u64 visorchannel_get_clientpartition(struct visorchannel *channel);
-int visorchannel_set_clientpartition(struct visorchannel *channel,
-                                    u64 partition_handle);
-char *visorchannel_guid_id(const guid_t *guid, char *s);
-void *visorchannel_get_header(struct visorchannel *channel);
-#endif
diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c
deleted file mode 100644 (file)
index aae1607..0000000
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-/*
- *  This provides s-Par channel communication primitives, which are
- *  independent of the mechanism used to access the channel data.
- */
-
-#include <linux/uuid.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include "visorbus.h"
-#include "visorbus_private.h"
-#include "controlvmchannel.h"
-
-#define VISOR_DRV_NAME "visorchannel"
-
-#define VISOR_CONSOLEVIDEO_CHANNEL_GUID \
-       GUID_INIT(0x3cd6e705, 0xd6a2, 0x4aa5, \
-                 0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
-
-static const guid_t visor_video_guid = VISOR_CONSOLEVIDEO_CHANNEL_GUID;
-
-struct visorchannel {
-       u64 physaddr;
-       ulong nbytes;
-       void *mapped;
-       bool requested;
-       struct channel_header chan_hdr;
-       guid_t guid;
-       /*
-        * channel creator knows if more than one thread will be inserting or
-        * removing
-        */
-       bool needs_lock;
-       /* protect head writes in chan_hdr */
-       spinlock_t insert_lock;
-       /* protect tail writes in chan_hdr */
-       spinlock_t remove_lock;
-       guid_t type;
-       guid_t inst;
-};
-
-void visorchannel_destroy(struct visorchannel *channel)
-{
-       if (!channel)
-               return;
-
-       if (channel->mapped) {
-               memunmap(channel->mapped);
-               if (channel->requested)
-                       release_mem_region(channel->physaddr, channel->nbytes);
-       }
-       kfree(channel);
-}
-
-u64 visorchannel_get_physaddr(struct visorchannel *channel)
-{
-       return channel->physaddr;
-}
-
-ulong visorchannel_get_nbytes(struct visorchannel *channel)
-{
-       return channel->nbytes;
-}
-
-char *visorchannel_guid_id(const guid_t *guid, char *s)
-{
-       sprintf(s, "%pUL", guid);
-       return s;
-}
-
-char *visorchannel_id(struct visorchannel *channel, char *s)
-{
-       return visorchannel_guid_id(&channel->guid, s);
-}
-
-char *visorchannel_zoneid(struct visorchannel *channel, char *s)
-{
-       return visorchannel_guid_id(&channel->chan_hdr.zone_guid, s);
-}
-
-u64 visorchannel_get_clientpartition(struct visorchannel *channel)
-{
-       return channel->chan_hdr.partition_handle;
-}
-
-int visorchannel_set_clientpartition(struct visorchannel *channel,
-                                    u64 partition_handle)
-{
-       channel->chan_hdr.partition_handle = partition_handle;
-       return 0;
-}
-
-/**
- * visorchannel_get_guid() - queries the GUID of the designated channel
- * @channel: the channel to query
- *
- * Return: the GUID of the provided channel
- */
-const guid_t *visorchannel_get_guid(struct visorchannel *channel)
-{
-       return &channel->guid;
-}
-EXPORT_SYMBOL_GPL(visorchannel_get_guid);
-
-int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest,
-                     ulong nbytes)
-{
-       if (offset + nbytes > channel->nbytes)
-               return -EIO;
-
-       memcpy(dest, channel->mapped + offset, nbytes);
-       return 0;
-}
-
-int visorchannel_write(struct visorchannel *channel, ulong offset, void *dest,
-                      ulong nbytes)
-{
-       size_t chdr_size = sizeof(struct channel_header);
-       size_t copy_size;
-
-       if (offset + nbytes > channel->nbytes)
-               return -EIO;
-
-       if (offset < chdr_size) {
-               copy_size = min(chdr_size - offset, nbytes);
-               memcpy(((char *)(&channel->chan_hdr)) + offset,
-                      dest, copy_size);
-       }
-       memcpy(channel->mapped + offset, dest, nbytes);
-       return 0;
-}
-
-void *visorchannel_get_header(struct visorchannel *channel)
-{
-       return &channel->chan_hdr;
-}
-
-/*
- * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
- * channel header
- */
-static int sig_queue_offset(struct channel_header *chan_hdr, int q)
-{
-       return ((chan_hdr)->ch_space_offset +
-              ((q) * sizeof(struct signal_queue_header)));
-}
-
-/*
- * Return offset of a specific queue entry (data) from the beginning of a
- * channel header
- */
-static int sig_data_offset(struct channel_header *chan_hdr, int q,
-                          struct signal_queue_header *sig_hdr, int slot)
-{
-       return (sig_queue_offset(chan_hdr, q) + sig_hdr->sig_base_offset +
-              (slot * sig_hdr->signal_size));
-}
-
-/*
- * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back into
- * host memory
- */
-#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \
-       visorchannel_write(channel, \
-                          sig_queue_offset(&channel->chan_hdr, queue) + \
-                          offsetof(struct signal_queue_header, FIELD), \
-                          &((sig_hdr)->FIELD), \
-                          sizeof((sig_hdr)->FIELD))
-
-static int sig_read_header(struct visorchannel *channel, u32 queue,
-                          struct signal_queue_header *sig_hdr)
-{
-       if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
-               return -EINVAL;
-
-       /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
-       return visorchannel_read(channel,
-                                sig_queue_offset(&channel->chan_hdr, queue),
-                                sig_hdr, sizeof(struct signal_queue_header));
-}
-
-static int sig_read_data(struct visorchannel *channel, u32 queue,
-                        struct signal_queue_header *sig_hdr, u32 slot,
-                        void *data)
-{
-       int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
-                                                sig_hdr, slot);
-
-       return visorchannel_read(channel, signal_data_offset,
-                                data, sig_hdr->signal_size);
-}
-
-static int sig_write_data(struct visorchannel *channel, u32 queue,
-                         struct signal_queue_header *sig_hdr, u32 slot,
-                         void *data)
-{
-       int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
-                                                sig_hdr, slot);
-
-       return visorchannel_write(channel, signal_data_offset,
-                                 data, sig_hdr->signal_size);
-}
-
-static int signalremove_inner(struct visorchannel *channel, u32 queue,
-                             void *msg)
-{
-       struct signal_queue_header sig_hdr;
-       int error;
-
-       error = sig_read_header(channel, queue, &sig_hdr);
-       if (error)
-               return error;
-       /* No signals to remove; have caller try again. */
-       if (sig_hdr.head == sig_hdr.tail)
-               return -EAGAIN;
-       sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
-       error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg);
-       if (error)
-               return error;
-       sig_hdr.num_received++;
-       /*
-        * For each data field in SIGNAL_QUEUE_HEADER that was modified, update
-        * host memory. Required for channel sync.
-        */
-       mb();
-       error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail);
-       if (error)
-               return error;
-       error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received);
-       if (error)
-               return error;
-       return 0;
-}
-
-/**
- * visorchannel_signalremove() - removes a message from the designated
- *                               channel/queue
- * @channel: the channel the message will be removed from
- * @queue:   the queue the message will be removed from
- * @msg:     the message to remove
- *
- * Return: integer error code indicating the status of the removal
- */
-int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
-                             void *msg)
-{
-       int rc;
-       unsigned long flags;
-
-       if (channel->needs_lock) {
-               spin_lock_irqsave(&channel->remove_lock, flags);
-               rc = signalremove_inner(channel, queue, msg);
-               spin_unlock_irqrestore(&channel->remove_lock, flags);
-       } else {
-               rc = signalremove_inner(channel, queue, msg);
-       }
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalremove);
-
-static bool queue_empty(struct visorchannel *channel, u32 queue)
-{
-       struct signal_queue_header sig_hdr;
-
-       if (sig_read_header(channel, queue, &sig_hdr))
-               return true;
-       return (sig_hdr.head == sig_hdr.tail);
-}
-
-/**
- * visorchannel_signalempty() - checks if the designated channel/queue contains
- *                             any messages
- * @channel: the channel to query
- * @queue:   the queue in the channel to query
- *
- * Return: boolean indicating whether any messages in the designated
- *         channel/queue are present
- */
-bool visorchannel_signalempty(struct visorchannel *channel, u32 queue)
-{
-       bool rc;
-       unsigned long flags;
-
-       if (!channel->needs_lock)
-               return queue_empty(channel, queue);
-       spin_lock_irqsave(&channel->remove_lock, flags);
-       rc = queue_empty(channel, queue);
-       spin_unlock_irqrestore(&channel->remove_lock, flags);
-       return rc;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalempty);
-
-static int signalinsert_inner(struct visorchannel *channel, u32 queue,
-                             void *msg)
-{
-       struct signal_queue_header sig_hdr;
-       int err;
-
-       err = sig_read_header(channel, queue, &sig_hdr);
-       if (err)
-               return err;
-       sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots;
-       if (sig_hdr.head == sig_hdr.tail) {
-               sig_hdr.num_overflows++;
-               err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows);
-               if (err)
-                       return err;
-               return -EIO;
-       }
-       err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg);
-       if (err)
-               return err;
-       sig_hdr.num_sent++;
-       /*
-        * For each data field in SIGNAL_QUEUE_HEADER that was modified, update
-        * host memory. Required for channel sync.
-        */
-       mb();
-       err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head);
-       if (err)
-               return err;
-       err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent);
-       if (err)
-               return err;
-       return 0;
-}
-
-/*
- * visorchannel_create() - creates the struct visorchannel abstraction for a
- *                         data area in memory, but does NOT modify this data
- *                         area
- * @physaddr:      physical address of start of channel
- * @gfp:           gfp_t to use when allocating memory for the data struct
- * @guid:          GUID that identifies channel type;
- * @needs_lock:    must specify true if you have multiple threads of execution
- *                 that will be calling visorchannel methods of this
- *                 visorchannel at the same time
- *
- * Return: pointer to visorchannel that was created if successful,
- *         otherwise NULL
- */
-struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
-                                        const guid_t *guid, bool needs_lock)
-{
-       struct visorchannel *channel;
-       int err;
-       size_t size = sizeof(struct channel_header);
-
-       if (physaddr == 0)
-               return NULL;
-
-       channel = kzalloc(sizeof(*channel), gfp);
-       if (!channel)
-               return NULL;
-       channel->needs_lock = needs_lock;
-       spin_lock_init(&channel->insert_lock);
-       spin_lock_init(&channel->remove_lock);
-       /*
-        * Video driver constains the efi framebuffer so it will get a conflict
-        * resource when requesting its full mem region. Since we are only
-        * using the efi framebuffer for video we can ignore this. Remember that
-        * we haven't requested it so we don't try to release later on.
-        */
-       channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME);
-       if (!channel->requested && !guid_equal(guid, &visor_video_guid))
-               /* we only care about errors if this is not the video channel */
-               goto err_destroy_channel;
-       channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
-       if (!channel->mapped) {
-               release_mem_region(physaddr, size);
-               goto err_destroy_channel;
-       }
-       channel->physaddr = physaddr;
-       channel->nbytes = size;
-       err = visorchannel_read(channel, 0, &channel->chan_hdr, size);
-       if (err)
-               goto err_destroy_channel;
-       size = (ulong)channel->chan_hdr.size;
-       memunmap(channel->mapped);
-       if (channel->requested)
-               release_mem_region(channel->physaddr, channel->nbytes);
-       channel->mapped = NULL;
-       channel->requested = request_mem_region(channel->physaddr, size,
-                                               VISOR_DRV_NAME);
-       if (!channel->requested && !guid_equal(guid, &visor_video_guid))
-               /* we only care about errors if this is not the video channel */
-               goto err_destroy_channel;
-       channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB);
-       if (!channel->mapped) {
-               release_mem_region(channel->physaddr, size);
-               goto err_destroy_channel;
-       }
-       channel->nbytes = size;
-       guid_copy(&channel->guid, guid);
-       return channel;
-
-err_destroy_channel:
-       visorchannel_destroy(channel);
-       return NULL;
-}
-
-/**
- * visorchannel_signalinsert() - inserts a message into the designated
- *                               channel/queue
- * @channel: the channel the message will be added to
- * @queue:   the queue the message will be added to
- * @msg:     the message to insert
- *
- * Return: integer error code indicating the status of the insertion
- */
-int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
-                             void *msg)
-{
-       int rc;
-       unsigned long flags;
-
-       if (channel->needs_lock) {
-               spin_lock_irqsave(&channel->insert_lock, flags);
-               rc = signalinsert_inner(channel, queue, msg);
-               spin_unlock_irqrestore(&channel->insert_lock, flags);
-       } else {
-               rc = signalinsert_inner(channel, queue, msg);
-       }
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c
deleted file mode 100644 (file)
index fed554a..0000000
+++ /dev/null
@@ -1,1694 +0,0 @@
-/*
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#include <linux/acpi.h>
-#include <linux/crash_dump.h>
-
-#include "visorbus.h"
-#include "visorbus_private.h"
-
-/* {72120008-4AAB-11DC-8530-444553544200} */
-#define VISOR_SIOVM_GUID GUID_INIT(0x72120008, 0x4AAB, 0x11DC, 0x85, 0x30, \
-                                  0x44, 0x45, 0x53, 0x54, 0x42, 0x00)
-
-static const guid_t visor_vhba_channel_guid = VISOR_VHBA_CHANNEL_GUID;
-static const guid_t visor_siovm_guid = VISOR_SIOVM_GUID;
-static const guid_t visor_controlvm_channel_guid = VISOR_CONTROLVM_CHANNEL_GUID;
-
-#define POLLJIFFIES_CONTROLVM_FAST 1
-#define POLLJIFFIES_CONTROLVM_SLOW 100
-
-#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
-
-#define UNISYS_VISOR_LEAF_ID 0x40000000
-
-/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
-#define UNISYS_VISOR_ID_EBX 0x73696e55
-#define UNISYS_VISOR_ID_ECX 0x70537379
-#define UNISYS_VISOR_ID_EDX 0x34367261
-
-/*
- * When the controlvm channel is idle for at least MIN_IDLE_SECONDS, we switch
- * to slow polling mode. As soon as we get a controlvm message, we switch back
- * to fast polling mode.
- */
-#define MIN_IDLE_SECONDS 10
-
-struct parser_context {
-       unsigned long allocbytes;
-       unsigned long param_bytes;
-       u8 *curr;
-       unsigned long bytes_remaining;
-       bool byte_stream;
-       struct visor_controlvm_parameters_header data;
-};
-
-/* VMCALL_CONTROLVM_ADDR: Used by all guests, not just IO. */
-#define VMCALL_CONTROLVM_ADDR 0x0501
-
-enum vmcall_result {
-       VMCALL_RESULT_SUCCESS = 0,
-       VMCALL_RESULT_INVALID_PARAM = 1,
-       VMCALL_RESULT_DATA_UNAVAILABLE = 2,
-       VMCALL_RESULT_FAILURE_UNAVAILABLE = 3,
-       VMCALL_RESULT_DEVICE_ERROR = 4,
-       VMCALL_RESULT_DEVICE_NOT_READY = 5
-};
-
-/*
- * struct vmcall_io_controlvm_addr_params - Structure for IO VMCALLS. Has
- *                                         parameters to VMCALL_CONTROLVM_ADDR
- *                                         interface.
- * @address:      The Guest-relative physical address of the ControlVm channel.
- *                This VMCall fills this in with the appropriate address.
- *                Contents provided by this VMCALL (OUT).
- * @channel_bytes: The size of the ControlVm channel in bytes This VMCall fills
- *                this in with the appropriate address. Contents provided by
- *                this VMCALL (OUT).
- * @unused:       Unused Bytes in the 64-Bit Aligned Struct.
- */
-struct vmcall_io_controlvm_addr_params {
-       u64 address;
-       u32 channel_bytes;
-       u8 unused[4];
-} __packed;
-
-struct visorchipset_device {
-       struct acpi_device *acpi_device;
-       unsigned long poll_jiffies;
-       /* when we got our last controlvm message */
-       unsigned long most_recent_message_jiffies;
-       struct delayed_work periodic_controlvm_work;
-       struct visorchannel *controlvm_channel;
-       unsigned long controlvm_payload_bytes_buffered;
-       /*
-        * The following variables are used to handle the scenario where we are
-        * unable to offload the payload from a controlvm message due to memory
-        * requirements. In this scenario, we simply stash the controlvm
-        * message, then attempt to process it again the next time
-        * controlvm_periodic_work() runs.
-        */
-       struct controlvm_message controlvm_pending_msg;
-       bool controlvm_pending_msg_valid;
-       struct vmcall_io_controlvm_addr_params controlvm_params;
-};
-
-static struct visorchipset_device *chipset_dev;
-
-struct parahotplug_request {
-       struct list_head list;
-       int id;
-       unsigned long expiration;
-       struct controlvm_message msg;
-};
-
-/* prototypes for attributes */
-static ssize_t toolaction_show(struct device *dev,
-                              struct device_attribute *attr,
-                              char *buf)
-{
-       u8 tool_action = 0;
-       int err;
-
-       err = visorchannel_read(chipset_dev->controlvm_channel,
-                               offsetof(struct visor_controlvm_channel,
-                                        tool_action),
-                               &tool_action, sizeof(u8));
-       if (err)
-               return err;
-       return sprintf(buf, "%u\n", tool_action);
-}
-
-static ssize_t toolaction_store(struct device *dev,
-                               struct device_attribute *attr,
-                               const char *buf, size_t count)
-{
-       u8 tool_action;
-       int err;
-
-       if (kstrtou8(buf, 10, &tool_action))
-               return -EINVAL;
-       err = visorchannel_write(chipset_dev->controlvm_channel,
-                                offsetof(struct visor_controlvm_channel,
-                                         tool_action),
-                                &tool_action, sizeof(u8));
-       if (err)
-               return err;
-       return count;
-}
-static DEVICE_ATTR_RW(toolaction);
-
-static ssize_t boottotool_show(struct device *dev,
-                              struct device_attribute *attr,
-                              char *buf)
-{
-       struct efi_visor_indication efi_visor_indication;
-       int err;
-
-       err = visorchannel_read(chipset_dev->controlvm_channel,
-                               offsetof(struct visor_controlvm_channel,
-                                        efi_visor_ind),
-                               &efi_visor_indication,
-                               sizeof(struct efi_visor_indication));
-       if (err)
-               return err;
-       return sprintf(buf, "%u\n", efi_visor_indication.boot_to_tool);
-}
-
-static ssize_t boottotool_store(struct device *dev,
-                               struct device_attribute *attr,
-                               const char *buf, size_t count)
-{
-       int val, err;
-       struct efi_visor_indication efi_visor_indication;
-
-       if (kstrtoint(buf, 10, &val))
-               return -EINVAL;
-       efi_visor_indication.boot_to_tool = val;
-       err = visorchannel_write(chipset_dev->controlvm_channel,
-                                offsetof(struct visor_controlvm_channel,
-                                         efi_visor_ind),
-                                &(efi_visor_indication),
-                                sizeof(struct efi_visor_indication));
-       if (err)
-               return err;
-       return count;
-}
-static DEVICE_ATTR_RW(boottotool);
-
-static ssize_t error_show(struct device *dev, struct device_attribute *attr,
-                         char *buf)
-{
-       u32 error = 0;
-       int err;
-
-       err = visorchannel_read(chipset_dev->controlvm_channel,
-                               offsetof(struct visor_controlvm_channel,
-                                        installation_error),
-                               &error, sizeof(u32));
-       if (err)
-               return err;
-       return sprintf(buf, "%u\n", error);
-}
-
-static ssize_t error_store(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
-{
-       u32 error;
-       int err;
-
-       if (kstrtou32(buf, 10, &error))
-               return -EINVAL;
-       err = visorchannel_write(chipset_dev->controlvm_channel,
-                                offsetof(struct visor_controlvm_channel,
-                                         installation_error),
-                                &error, sizeof(u32));
-       if (err)
-               return err;
-       return count;
-}
-static DEVICE_ATTR_RW(error);
-
-static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
-                          char *buf)
-{
-       u32 text_id = 0;
-       int err;
-
-       err = visorchannel_read(chipset_dev->controlvm_channel,
-                               offsetof(struct visor_controlvm_channel,
-                                        installation_text_id),
-                               &text_id, sizeof(u32));
-       if (err)
-               return err;
-       return sprintf(buf, "%u\n", text_id);
-}
-
-static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
-                           const char *buf, size_t count)
-{
-       u32 text_id;
-       int err;
-
-       if (kstrtou32(buf, 10, &text_id))
-               return -EINVAL;
-       err = visorchannel_write(chipset_dev->controlvm_channel,
-                                offsetof(struct visor_controlvm_channel,
-                                         installation_text_id),
-                                &text_id, sizeof(u32));
-       if (err)
-               return err;
-       return count;
-}
-static DEVICE_ATTR_RW(textid);
-
-static ssize_t remaining_steps_show(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
-{
-       u16 remaining_steps = 0;
-       int err;
-
-       err = visorchannel_read(chipset_dev->controlvm_channel,
-                               offsetof(struct visor_controlvm_channel,
-                                        installation_remaining_steps),
-                               &remaining_steps, sizeof(u16));
-       if (err)
-               return err;
-       return sprintf(buf, "%hu\n", remaining_steps);
-}
-
-static ssize_t remaining_steps_store(struct device *dev,
-                                    struct device_attribute *attr,
-                                    const char *buf, size_t count)
-{
-       u16 remaining_steps;
-       int err;
-
-       if (kstrtou16(buf, 10, &remaining_steps))
-               return -EINVAL;
-       err = visorchannel_write(chipset_dev->controlvm_channel,
-                                offsetof(struct visor_controlvm_channel,
-                                         installation_remaining_steps),
-                                &remaining_steps, sizeof(u16));
-       if (err)
-               return err;
-       return count;
-}
-static DEVICE_ATTR_RW(remaining_steps);
-
-static void controlvm_init_response(struct controlvm_message *msg,
-                                   struct controlvm_message_header *msg_hdr,
-                                   int response)
-{
-       memset(msg, 0, sizeof(struct controlvm_message));
-       memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
-       msg->hdr.payload_bytes = 0;
-       msg->hdr.payload_vm_offset = 0;
-       msg->hdr.payload_max_bytes = 0;
-       if (response < 0) {
-               msg->hdr.flags.failed = 1;
-               msg->hdr.completion_status = (u32)(-response);
-       }
-}
-
-static int controlvm_respond_chipset_init(
-                               struct controlvm_message_header *msg_hdr,
-                               int response,
-                               enum visor_chipset_feature features)
-{
-       struct controlvm_message outmsg;
-
-       controlvm_init_response(&outmsg, msg_hdr, response);
-       outmsg.cmd.init_chipset.features = features;
-       return visorchannel_signalinsert(chipset_dev->controlvm_channel,
-                                        CONTROLVM_QUEUE_REQUEST, &outmsg);
-}
-
-static int chipset_init(struct controlvm_message *inmsg)
-{
-       static int chipset_inited;
-       enum visor_chipset_feature features = 0;
-       int rc = CONTROLVM_RESP_SUCCESS;
-       int res = 0;
-
-       if (chipset_inited) {
-               rc = -CONTROLVM_RESP_ALREADY_DONE;
-               res = -EIO;
-               goto out_respond;
-       }
-       chipset_inited = 1;
-       /*
-        * Set features to indicate we support parahotplug (if Command also
-        * supports it). Set the "reply" bit so Command knows this is a
-        * features-aware driver.
-        */
-       features = inmsg->cmd.init_chipset.features &
-                  VISOR_CHIPSET_FEATURE_PARA_HOTPLUG;
-       features |= VISOR_CHIPSET_FEATURE_REPLY;
-
-out_respond:
-       if (inmsg->hdr.flags.response_expected)
-               res = controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
-
-       return res;
-}
-
-static int controlvm_respond(struct controlvm_message_header *msg_hdr,
-                            int response, struct visor_segment_state *state)
-{
-       struct controlvm_message outmsg;
-
-       controlvm_init_response(&outmsg, msg_hdr, response);
-       if (outmsg.hdr.flags.test_message == 1)
-               return -EINVAL;
-       if (state) {
-               outmsg.cmd.device_change_state.state = *state;
-               outmsg.cmd.device_change_state.flags.phys_device = 1;
-       }
-       return visorchannel_signalinsert(chipset_dev->controlvm_channel,
-                                        CONTROLVM_QUEUE_REQUEST, &outmsg);
-}
-
-enum crash_obj_type {
-       CRASH_DEV,
-       CRASH_BUS,
-};
-
-static int save_crash_message(struct controlvm_message *msg,
-                             enum crash_obj_type cr_type)
-{
-       u32 local_crash_msg_offset;
-       u16 local_crash_msg_count;
-       int err;
-
-       err = visorchannel_read(chipset_dev->controlvm_channel,
-                               offsetof(struct visor_controlvm_channel,
-                                        saved_crash_message_count),
-                               &local_crash_msg_count, sizeof(u16));
-       if (err) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed to read message count\n");
-               return err;
-       }
-       if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "invalid number of messages\n");
-               return -EIO;
-       }
-       err = visorchannel_read(chipset_dev->controlvm_channel,
-                               offsetof(struct visor_controlvm_channel,
-                                        saved_crash_message_offset),
-                               &local_crash_msg_offset, sizeof(u32));
-       if (err) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed to read offset\n");
-               return err;
-       }
-       switch (cr_type) {
-       case CRASH_DEV:
-               local_crash_msg_offset += sizeof(struct controlvm_message);
-               err = visorchannel_write(chipset_dev->controlvm_channel,
-                                        local_crash_msg_offset, msg,
-                                        sizeof(struct controlvm_message));
-               if (err) {
-                       dev_err(&chipset_dev->acpi_device->dev,
-                               "failed to write dev msg\n");
-                       return err;
-               }
-               break;
-       case CRASH_BUS:
-               err = visorchannel_write(chipset_dev->controlvm_channel,
-                                        local_crash_msg_offset, msg,
-                                        sizeof(struct controlvm_message));
-               if (err) {
-                       dev_err(&chipset_dev->acpi_device->dev,
-                               "failed to write bus msg\n");
-                       return err;
-               }
-               break;
-       default:
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "Invalid crash_obj_type\n");
-               break;
-       }
-       return 0;
-}
-
-static int controlvm_responder(enum controlvm_id cmd_id,
-                              struct controlvm_message_header *pending_msg_hdr,
-                              int response)
-{
-       if (pending_msg_hdr->id != (u32)cmd_id)
-               return -EINVAL;
-
-       return controlvm_respond(pending_msg_hdr, response, NULL);
-}
-
-static int device_changestate_responder(enum controlvm_id cmd_id,
-                                       struct visor_device *p, int response,
-                                       struct visor_segment_state state)
-{
-       struct controlvm_message outmsg;
-
-       if (p->pending_msg_hdr->id != cmd_id)
-               return -EINVAL;
-
-       controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
-       outmsg.cmd.device_change_state.bus_no = p->chipset_bus_no;
-       outmsg.cmd.device_change_state.dev_no = p->chipset_dev_no;
-       outmsg.cmd.device_change_state.state = state;
-       return visorchannel_signalinsert(chipset_dev->controlvm_channel,
-                                        CONTROLVM_QUEUE_REQUEST, &outmsg);
-}
-
-static int visorbus_create(struct controlvm_message *inmsg)
-{
-       struct controlvm_message_packet *cmd = &inmsg->cmd;
-       struct controlvm_message_header *pmsg_hdr;
-       u32 bus_no = cmd->create_bus.bus_no;
-       struct visor_device *bus_info;
-       struct visorchannel *visorchannel;
-       int err;
-
-       bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-       if (bus_info && bus_info->state.created == 1) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed %s: already exists\n", __func__);
-               err = -EEXIST;
-               goto err_respond;
-       }
-       bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
-       if (!bus_info) {
-               err = -ENOMEM;
-               goto err_respond;
-       }
-       INIT_LIST_HEAD(&bus_info->list_all);
-       bus_info->chipset_bus_no = bus_no;
-       bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
-       if (guid_equal(&cmd->create_bus.bus_inst_guid, &visor_siovm_guid)) {
-               err = save_crash_message(inmsg, CRASH_BUS);
-               if (err)
-                       goto err_free_bus_info;
-       }
-       if (inmsg->hdr.flags.response_expected == 1) {
-               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
-               if (!pmsg_hdr) {
-                       err = -ENOMEM;
-                       goto err_free_bus_info;
-               }
-               memcpy(pmsg_hdr, &inmsg->hdr,
-                      sizeof(struct controlvm_message_header));
-               bus_info->pending_msg_hdr = pmsg_hdr;
-       }
-       visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
-                                          GFP_KERNEL,
-                                          &cmd->create_bus.bus_data_type_guid,
-                                          false);
-       if (!visorchannel) {
-               err = -ENOMEM;
-               goto err_free_pending_msg;
-       }
-       bus_info->visorchannel = visorchannel;
-       /* Response will be handled by visorbus_create_instance on success */
-       err = visorbus_create_instance(bus_info);
-       if (err)
-               goto err_destroy_channel;
-       return 0;
-
-err_destroy_channel:
-       visorchannel_destroy(visorchannel);
-
-err_free_pending_msg:
-       kfree(bus_info->pending_msg_hdr);
-
-err_free_bus_info:
-       kfree(bus_info);
-
-err_respond:
-       if (inmsg->hdr.flags.response_expected == 1)
-               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
-       return err;
-}
-
-static int visorbus_destroy(struct controlvm_message *inmsg)
-{
-       struct controlvm_message_header *pmsg_hdr;
-       u32 bus_no = inmsg->cmd.destroy_bus.bus_no;
-       struct visor_device *bus_info;
-       int err;
-
-       bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-       if (!bus_info) {
-               err = -ENODEV;
-               goto err_respond;
-       }
-       if (bus_info->state.created == 0) {
-               err = -ENOENT;
-               goto err_respond;
-       }
-       if (bus_info->pending_msg_hdr) {
-               /* only non-NULL if dev is still waiting on a response */
-               err = -EEXIST;
-               goto err_respond;
-       }
-       if (inmsg->hdr.flags.response_expected == 1) {
-               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
-               if (!pmsg_hdr) {
-                       err = -ENOMEM;
-                       goto err_respond;
-               }
-               memcpy(pmsg_hdr, &inmsg->hdr,
-                      sizeof(struct controlvm_message_header));
-               bus_info->pending_msg_hdr = pmsg_hdr;
-       }
-       /* Response will be handled by visorbus_remove_instance */
-       visorbus_remove_instance(bus_info);
-       return 0;
-
-err_respond:
-       if (inmsg->hdr.flags.response_expected == 1)
-               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
-       return err;
-}
-
-static const guid_t *parser_id_get(struct parser_context *ctx)
-{
-       return &ctx->data.id;
-}
-
-static void *parser_string_get(u8 *pscan, int nscan)
-{
-       int value_length;
-       void *value;
-
-       if (nscan == 0)
-               return NULL;
-
-       value_length = strnlen(pscan, nscan);
-       value = kzalloc(value_length + 1, GFP_KERNEL);
-       if (!value)
-               return NULL;
-       if (value_length > 0)
-               memcpy(value, pscan, value_length);
-       return value;
-}
-
-static void *parser_name_get(struct parser_context *ctx)
-{
-       struct visor_controlvm_parameters_header *phdr;
-
-       phdr = &ctx->data;
-       if (phdr->name_offset + phdr->name_length > ctx->param_bytes)
-               return NULL;
-       ctx->curr = (char *)&phdr + phdr->name_offset;
-       ctx->bytes_remaining = phdr->name_length;
-       return parser_string_get(ctx->curr, phdr->name_length);
-}
-
-static int visorbus_configure(struct controlvm_message *inmsg,
-                             struct parser_context *parser_ctx)
-{
-       struct controlvm_message_packet *cmd = &inmsg->cmd;
-       u32 bus_no;
-       struct visor_device *bus_info;
-       int err = 0;
-
-       bus_no = cmd->configure_bus.bus_no;
-       bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-       if (!bus_info) {
-               err = -EINVAL;
-               goto err_respond;
-       }
-       if (bus_info->state.created == 0) {
-               err = -EINVAL;
-               goto err_respond;
-       }
-       if (bus_info->pending_msg_hdr) {
-               err = -EIO;
-               goto err_respond;
-       }
-       err = visorchannel_set_clientpartition(bus_info->visorchannel,
-                                              cmd->configure_bus.guest_handle);
-       if (err)
-               goto err_respond;
-       if (parser_ctx) {
-               const guid_t *partition_guid = parser_id_get(parser_ctx);
-
-               guid_copy(&bus_info->partition_guid, partition_guid);
-               bus_info->name = parser_name_get(parser_ctx);
-       }
-       if (inmsg->hdr.flags.response_expected == 1)
-               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
-       return 0;
-
-err_respond:
-       dev_err(&chipset_dev->acpi_device->dev,
-               "%s exited with err: %d\n", __func__, err);
-       if (inmsg->hdr.flags.response_expected == 1)
-               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
-       return err;
-}
-
-static int visorbus_device_create(struct controlvm_message *inmsg)
-{
-       struct controlvm_message_packet *cmd = &inmsg->cmd;
-       struct controlvm_message_header *pmsg_hdr;
-       u32 bus_no = cmd->create_device.bus_no;
-       u32 dev_no = cmd->create_device.dev_no;
-       struct visor_device *dev_info;
-       struct visor_device *bus_info;
-       struct visorchannel *visorchannel;
-       int err;
-
-       bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-       if (!bus_info) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed to get bus by id: %d\n", bus_no);
-               err = -ENODEV;
-               goto err_respond;
-       }
-       if (bus_info->state.created == 0) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "bus not created, id: %d\n", bus_no);
-               err = -EINVAL;
-               goto err_respond;
-       }
-       dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
-       if (dev_info && dev_info->state.created == 1) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed to get bus by id: %d/%d\n", bus_no, dev_no);
-               err = -EEXIST;
-               goto err_respond;
-       }
-
-       dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
-       if (!dev_info) {
-               err = -ENOMEM;
-               goto err_respond;
-       }
-       dev_info->chipset_bus_no = bus_no;
-       dev_info->chipset_dev_no = dev_no;
-       guid_copy(&dev_info->inst, &cmd->create_device.dev_inst_guid);
-       dev_info->device.parent = &bus_info->device;
-       visorchannel = visorchannel_create(cmd->create_device.channel_addr,
-                                          GFP_KERNEL,
-                                          &cmd->create_device.data_type_guid,
-                                          true);
-       if (!visorchannel) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed to create visorchannel: %d/%d\n",
-                       bus_no, dev_no);
-               err = -ENOMEM;
-               goto err_free_dev_info;
-       }
-       dev_info->visorchannel = visorchannel;
-       guid_copy(&dev_info->channel_type_guid,
-                 &cmd->create_device.data_type_guid);
-       if (guid_equal(&cmd->create_device.data_type_guid,
-                      &visor_vhba_channel_guid)) {
-               err = save_crash_message(inmsg, CRASH_DEV);
-               if (err)
-                       goto err_destroy_visorchannel;
-       }
-       if (inmsg->hdr.flags.response_expected == 1) {
-               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
-               if (!pmsg_hdr) {
-                       err = -ENOMEM;
-                       goto err_destroy_visorchannel;
-               }
-               memcpy(pmsg_hdr, &inmsg->hdr,
-                      sizeof(struct controlvm_message_header));
-               dev_info->pending_msg_hdr = pmsg_hdr;
-       }
-       /* create_visor_device will send response */
-       err = create_visor_device(dev_info);
-       if (err)
-               goto err_destroy_visorchannel;
-
-       return 0;
-
-err_destroy_visorchannel:
-       visorchannel_destroy(visorchannel);
-
-err_free_dev_info:
-       kfree(dev_info);
-
-err_respond:
-       if (inmsg->hdr.flags.response_expected == 1)
-               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
-       return err;
-}
-
-static int visorbus_device_changestate(struct controlvm_message *inmsg)
-{
-       struct controlvm_message_packet *cmd = &inmsg->cmd;
-       struct controlvm_message_header *pmsg_hdr;
-       u32 bus_no = cmd->device_change_state.bus_no;
-       u32 dev_no = cmd->device_change_state.dev_no;
-       struct visor_segment_state state = cmd->device_change_state.state;
-       struct visor_device *dev_info;
-       int err = 0;
-
-       dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
-       if (!dev_info) {
-               err = -ENODEV;
-               goto err_respond;
-       }
-       if (dev_info->state.created == 0) {
-               err = -EINVAL;
-               goto err_respond;
-       }
-       if (dev_info->pending_msg_hdr) {
-               /* only non-NULL if dev is still waiting on a response */
-               err = -EIO;
-               goto err_respond;
-       }
-
-       if (inmsg->hdr.flags.response_expected == 1) {
-               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
-               if (!pmsg_hdr) {
-                       err = -ENOMEM;
-                       goto err_respond;
-               }
-               memcpy(pmsg_hdr, &inmsg->hdr,
-                      sizeof(struct controlvm_message_header));
-               dev_info->pending_msg_hdr = pmsg_hdr;
-       }
-       if (state.alive == segment_state_running.alive &&
-           state.operating == segment_state_running.operating)
-               /* Response will be sent from visorchipset_device_resume */
-               err = visorchipset_device_resume(dev_info);
-       /* ServerNotReady / ServerLost / SegmentStateStandby */
-       else if (state.alive == segment_state_standby.alive &&
-                state.operating == segment_state_standby.operating)
-               /*
-                * technically this is standby case where server is lost.
-                * Response will be sent from visorchipset_device_pause.
-                */
-               err = visorchipset_device_pause(dev_info);
-       if (err)
-               goto err_respond;
-       return 0;
-
-err_respond:
-       dev_err(&chipset_dev->acpi_device->dev, "failed: %d\n", err);
-       if (inmsg->hdr.flags.response_expected == 1)
-               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
-       return err;
-}
-
-static int visorbus_device_destroy(struct controlvm_message *inmsg)
-{
-       struct controlvm_message_packet *cmd = &inmsg->cmd;
-       struct controlvm_message_header *pmsg_hdr;
-       u32 bus_no = cmd->destroy_device.bus_no;
-       u32 dev_no = cmd->destroy_device.dev_no;
-       struct visor_device *dev_info;
-       int err;
-
-       dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
-       if (!dev_info) {
-               err = -ENODEV;
-               goto err_respond;
-       }
-       if (dev_info->state.created == 0) {
-               err = -EINVAL;
-               goto err_respond;
-       }
-       if (dev_info->pending_msg_hdr) {
-               /* only non-NULL if dev is still waiting on a response */
-               err = -EIO;
-               goto err_respond;
-       }
-       if (inmsg->hdr.flags.response_expected == 1) {
-               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
-               if (!pmsg_hdr) {
-                       err = -ENOMEM;
-                       goto err_respond;
-               }
-
-               memcpy(pmsg_hdr, &inmsg->hdr,
-                      sizeof(struct controlvm_message_header));
-               dev_info->pending_msg_hdr = pmsg_hdr;
-       }
-       kfree(dev_info->name);
-       remove_visor_device(dev_info);
-       return 0;
-
-err_respond:
-       if (inmsg->hdr.flags.response_expected == 1)
-               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
-       return err;
-}
-
-/*
- * The general parahotplug flow works as follows. The visorchipset receives
- * a DEVICE_CHANGESTATE message from Command specifying a physical device
- * to enable or disable. The CONTROLVM message handler calls
- * parahotplug_process_message, which then adds the message to a global list
- * and kicks off a udev event which causes a user level script to enable or
- * disable the specified device. The udev script then writes to
- * /sys/devices/platform/visorchipset/parahotplug, which causes the
- * parahotplug store functions to get called, at which point the
- * appropriate CONTROLVM message is retrieved from the list and responded to.
- */
-
-#define PARAHOTPLUG_TIMEOUT_MS 2000
-
-/*
- * parahotplug_next_id() - generate unique int to match an outstanding
- *                         CONTROLVM message with a udev script /sys
- *                         response
- *
- * Return: a unique integer value
- */
-static int parahotplug_next_id(void)
-{
-       static atomic_t id = ATOMIC_INIT(0);
-
-       return atomic_inc_return(&id);
-}
-
-/*
- * parahotplug_next_expiration() - returns the time (in jiffies) when a
- *                                 CONTROLVM message on the list should expire
- *                                 -- PARAHOTPLUG_TIMEOUT_MS in the future
- *
- * Return: expected expiration time (in jiffies)
- */
-static unsigned long parahotplug_next_expiration(void)
-{
-       return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
-}
-
-/*
- * parahotplug_request_create() - create a parahotplug_request, which is
- *                                basically a wrapper for a CONTROLVM_MESSAGE
- *                                that we can stick on a list
- * @msg: the message to insert in the request
- *
- * Return: the request containing the provided message
- */
-static struct parahotplug_request *parahotplug_request_create(
-                                               struct controlvm_message *msg)
-{
-       struct parahotplug_request *req;
-
-       req = kmalloc(sizeof(*req), GFP_KERNEL);
-       if (!req)
-               return NULL;
-       req->id = parahotplug_next_id();
-       req->expiration = parahotplug_next_expiration();
-       req->msg = *msg;
-       return req;
-}
-
-/*
- * parahotplug_request_destroy() - free a parahotplug_request
- * @req: the request to deallocate
- */
-static void parahotplug_request_destroy(struct parahotplug_request *req)
-{
-       kfree(req);
-}
-
-static LIST_HEAD(parahotplug_request_list);
-/* lock for above */
-static DEFINE_SPINLOCK(parahotplug_request_list_lock);
-
-/*
- * parahotplug_request_complete() - mark request as complete
- * @id:     the id of the request
- * @active: indicates whether the request is assigned to active partition
- *
- * Called from the /sys handler, which means the user script has
- * finished the enable/disable. Find the matching identifier, and
- * respond to the CONTROLVM message with success.
- *
- * Return: 0 on success or -EINVAL on failure
- */
-static int parahotplug_request_complete(int id, u16 active)
-{
-       struct list_head *pos;
-       struct list_head *tmp;
-       struct parahotplug_request *req;
-
-       spin_lock(&parahotplug_request_list_lock);
-       /* Look for a request matching "id". */
-       list_for_each_safe(pos, tmp, &parahotplug_request_list) {
-               req = list_entry(pos, struct parahotplug_request, list);
-               if (req->id == id) {
-                       /*
-                        * Found a match. Remove it from the list and
-                        * respond.
-                        */
-                       list_del(pos);
-                       spin_unlock(&parahotplug_request_list_lock);
-                       req->msg.cmd.device_change_state.state.active = active;
-                       if (req->msg.hdr.flags.response_expected)
-                               controlvm_respond(
-                                      &req->msg.hdr, CONTROLVM_RESP_SUCCESS,
-                                      &req->msg.cmd.device_change_state.state);
-                       parahotplug_request_destroy(req);
-                       return 0;
-               }
-       }
-       spin_unlock(&parahotplug_request_list_lock);
-       return -EINVAL;
-}
-
-/*
- * devicedisabled_store() - disables the hotplug device
- * @dev:   sysfs interface variable not utilized in this function
- * @attr:  sysfs interface variable not utilized in this function
- * @buf:   buffer containing the device id
- * @count: the size of the buffer
- *
- * The parahotplug/devicedisabled interface gets called by our support script
- * when an SR-IOV device has been shut down. The ID is passed to the script
- * and then passed back when the device has been removed.
- *
- * Return: the size of the buffer for success or negative for error
- */
-static ssize_t devicedisabled_store(struct device *dev,
-                                   struct device_attribute *attr,
-                                   const char *buf, size_t count)
-{
-       unsigned int id;
-       int err;
-
-       if (kstrtouint(buf, 10, &id))
-               return -EINVAL;
-       err = parahotplug_request_complete(id, 0);
-       if (err < 0)
-               return err;
-       return count;
-}
-static DEVICE_ATTR_WO(devicedisabled);
-
-/*
- * deviceenabled_store() - enables the hotplug device
- * @dev:   sysfs interface variable not utilized in this function
- * @attr:  sysfs interface variable not utilized in this function
- * @buf:   buffer containing the device id
- * @count: the size of the buffer
- *
- * The parahotplug/deviceenabled interface gets called by our support script
- * when an SR-IOV device has been recovered. The ID is passed to the script
- * and then passed back when the device has been brought back up.
- *
- * Return: the size of the buffer for success or negative for error
- */
-static ssize_t deviceenabled_store(struct device *dev,
-                                  struct device_attribute *attr,
-                                  const char *buf, size_t count)
-{
-       unsigned int id;
-
-       if (kstrtouint(buf, 10, &id))
-               return -EINVAL;
-       parahotplug_request_complete(id, 1);
-       return count;
-}
-static DEVICE_ATTR_WO(deviceenabled);
-
-static struct attribute *visorchipset_install_attrs[] = {
-       &dev_attr_toolaction.attr,
-       &dev_attr_boottotool.attr,
-       &dev_attr_error.attr,
-       &dev_attr_textid.attr,
-       &dev_attr_remaining_steps.attr,
-       NULL
-};
-
-static const struct attribute_group visorchipset_install_group = {
-       .name = "install",
-       .attrs = visorchipset_install_attrs
-};
-
-static struct attribute *visorchipset_parahotplug_attrs[] = {
-       &dev_attr_devicedisabled.attr,
-       &dev_attr_deviceenabled.attr,
-       NULL
-};
-
-static const struct attribute_group visorchipset_parahotplug_group = {
-       .name = "parahotplug",
-       .attrs = visorchipset_parahotplug_attrs
-};
-
-static const struct attribute_group *visorchipset_dev_groups[] = {
-       &visorchipset_install_group,
-       &visorchipset_parahotplug_group,
-       NULL
-};
-
-/*
- * parahotplug_request_kickoff() - initiate parahotplug request
- * @req: the request to initiate
- *
- * Cause uevent to run the user level script to do the disable/enable specified
- * in the parahotplug_request.
- */
-static int parahotplug_request_kickoff(struct parahotplug_request *req)
-{
-       struct controlvm_message_packet *cmd = &req->msg.cmd;
-       char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
-            env_func[40];
-       char *envp[] = { env_cmd, env_id, env_state, env_bus, env_dev,
-                        env_func, NULL
-       };
-
-       sprintf(env_cmd, "VISOR_PARAHOTPLUG=1");
-       sprintf(env_id, "VISOR_PARAHOTPLUG_ID=%d", req->id);
-       sprintf(env_state, "VISOR_PARAHOTPLUG_STATE=%d",
-               cmd->device_change_state.state.active);
-       sprintf(env_bus, "VISOR_PARAHOTPLUG_BUS=%d",
-               cmd->device_change_state.bus_no);
-       sprintf(env_dev, "VISOR_PARAHOTPLUG_DEVICE=%d",
-               cmd->device_change_state.dev_no >> 3);
-       sprintf(env_func, "VISOR_PARAHOTPLUG_FUNCTION=%d",
-               cmd->device_change_state.dev_no & 0x7);
-       return kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj,
-                                 KOBJ_CHANGE, envp);
-}
-
-/*
- * parahotplug_process_message() - enables or disables a PCI device by kicking
- *                                 off a udev script
- * @inmsg: the message indicating whether to enable or disable
- */
-static int parahotplug_process_message(struct controlvm_message *inmsg)
-{
-       struct parahotplug_request *req;
-       int err;
-
-       req = parahotplug_request_create(inmsg);
-       if (!req)
-               return -ENOMEM;
-       /*
-        * For enable messages, just respond with success right away, we don't
-        * need to wait to see if the enable was successful.
-        */
-       if (inmsg->cmd.device_change_state.state.active) {
-               err = parahotplug_request_kickoff(req);
-               if (err)
-                       goto err_respond;
-               controlvm_respond(&inmsg->hdr, CONTROLVM_RESP_SUCCESS,
-                                 &inmsg->cmd.device_change_state.state);
-               parahotplug_request_destroy(req);
-               return 0;
-       }
-       /*
-        * For disable messages, add the request to the request list before
-        * kicking off the udev script. It won't get responded to until the
-        * script has indicated it's done.
-        */
-       spin_lock(&parahotplug_request_list_lock);
-       list_add_tail(&req->list, &parahotplug_request_list);
-       spin_unlock(&parahotplug_request_list_lock);
-       err = parahotplug_request_kickoff(req);
-       if (err)
-               goto err_respond;
-       return 0;
-
-err_respond:
-       controlvm_respond(&inmsg->hdr, err,
-                         &inmsg->cmd.device_change_state.state);
-       return err;
-}
-
-/*
- * chipset_ready_uevent() - sends chipset_ready action
- *
- * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
- *
- * Return: 0 on success, negative on failure
- */
-static int chipset_ready_uevent(struct controlvm_message_header *msg_hdr)
-{
-       int res;
-
-       res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj, KOBJ_ONLINE);
-       if (msg_hdr->flags.response_expected)
-               controlvm_respond(msg_hdr, res, NULL);
-       return res;
-}
-
-/*
- * chipset_selftest_uevent() - sends chipset_selftest action
- *
- * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
- *
- * Return: 0 on success, negative on failure
- */
-static int chipset_selftest_uevent(struct controlvm_message_header *msg_hdr)
-{
-       char env_selftest[20];
-       char *envp[] = { env_selftest, NULL };
-       int res;
-
-       sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
-       res = kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj,
-                                KOBJ_CHANGE, envp);
-       if (msg_hdr->flags.response_expected)
-               controlvm_respond(msg_hdr, res, NULL);
-       return res;
-}
-
-/*
- * chipset_notready_uevent() - sends chipset_notready action
- *
- * Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
- *
- * Return: 0 on success, negative on failure
- */
-static int chipset_notready_uevent(struct controlvm_message_header *msg_hdr)
-{
-       int res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj,
-                                KOBJ_OFFLINE);
-
-       if (msg_hdr->flags.response_expected)
-               controlvm_respond(msg_hdr, res, NULL);
-       return res;
-}
-
-static int unisys_vmcall(unsigned long tuple, unsigned long param)
-{
-       int result = 0;
-       unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
-       unsigned long reg_ebx;
-       unsigned long reg_ecx;
-
-       reg_ebx = param & 0xFFFFFFFF;
-       reg_ecx = param >> 32;
-       cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx);
-       if (!(cpuid_ecx & 0x80000000))
-               return -EPERM;
-       __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
-                            "a"(tuple), "b"(reg_ebx), "c"(reg_ecx));
-       if (result)
-               goto error;
-       return 0;
-
-/* Need to convert from VMCALL error codes to Linux */
-error:
-       switch (result) {
-       case VMCALL_RESULT_INVALID_PARAM:
-               return -EINVAL;
-       case VMCALL_RESULT_DATA_UNAVAILABLE:
-               return -ENODEV;
-       default:
-               return -EFAULT;
-       }
-}
-
-static int controlvm_channel_create(struct visorchipset_device *dev)
-{
-       struct visorchannel *chan;
-       u64 addr;
-       int err;
-
-       err = unisys_vmcall(VMCALL_CONTROLVM_ADDR,
-                           virt_to_phys(&dev->controlvm_params));
-       if (err)
-               return err;
-       addr = dev->controlvm_params.address;
-       chan = visorchannel_create(addr, GFP_KERNEL,
-                                  &visor_controlvm_channel_guid, true);
-       if (!chan)
-               return -ENOMEM;
-       dev->controlvm_channel = chan;
-       return 0;
-}
-
-static void setup_crash_devices_work_queue(struct work_struct *work)
-{
-       struct controlvm_message local_crash_bus_msg;
-       struct controlvm_message local_crash_dev_msg;
-       struct controlvm_message msg;
-       u32 local_crash_msg_offset;
-       u16 local_crash_msg_count;
-
-       /* send init chipset msg */
-       msg.hdr.id = CONTROLVM_CHIPSET_INIT;
-       msg.cmd.init_chipset.bus_count = 23;
-       msg.cmd.init_chipset.switch_count = 0;
-       chipset_init(&msg);
-       /* get saved message count */
-       if (visorchannel_read(chipset_dev->controlvm_channel,
-                             offsetof(struct visor_controlvm_channel,
-                                      saved_crash_message_count),
-                             &local_crash_msg_count, sizeof(u16)) < 0) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed to read channel\n");
-               return;
-       }
-       if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
-               dev_err(&chipset_dev->acpi_device->dev, "invalid count\n");
-               return;
-       }
-       /* get saved crash message offset */
-       if (visorchannel_read(chipset_dev->controlvm_channel,
-                             offsetof(struct visor_controlvm_channel,
-                                      saved_crash_message_offset),
-                             &local_crash_msg_offset, sizeof(u32)) < 0) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed to read channel\n");
-               return;
-       }
-       /* read create device message for storage bus offset */
-       if (visorchannel_read(chipset_dev->controlvm_channel,
-                             local_crash_msg_offset,
-                             &local_crash_bus_msg,
-                             sizeof(struct controlvm_message)) < 0) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed to read channel\n");
-               return;
-       }
-       /* read create device message for storage device */
-       if (visorchannel_read(chipset_dev->controlvm_channel,
-                             local_crash_msg_offset +
-                             sizeof(struct controlvm_message),
-                             &local_crash_dev_msg,
-                             sizeof(struct controlvm_message)) < 0) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "failed to read channel\n");
-               return;
-       }
-       /* reuse IOVM create bus message */
-       if (!local_crash_bus_msg.cmd.create_bus.channel_addr) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "no valid create_bus message\n");
-               return;
-       }
-       visorbus_create(&local_crash_bus_msg);
-       /* reuse create device message for storage device */
-       if (!local_crash_dev_msg.cmd.create_device.channel_addr) {
-               dev_err(&chipset_dev->acpi_device->dev,
-                       "no valid create_device message\n");
-               return;
-       }
-       visorbus_device_create(&local_crash_dev_msg);
-}
-
-void visorbus_response(struct visor_device *bus_info, int response,
-                      int controlvm_id)
-{
-       if (!bus_info->pending_msg_hdr)
-               return;
-
-       controlvm_responder(controlvm_id, bus_info->pending_msg_hdr, response);
-       kfree(bus_info->pending_msg_hdr);
-       bus_info->pending_msg_hdr = NULL;
-}
-
-void visorbus_device_changestate_response(struct visor_device *dev_info,
-                                         int response,
-                                         struct visor_segment_state state)
-{
-       if (!dev_info->pending_msg_hdr)
-               return;
-
-       device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, dev_info,
-                                    response, state);
-       kfree(dev_info->pending_msg_hdr);
-       dev_info->pending_msg_hdr = NULL;
-}
-
-static void parser_done(struct parser_context *ctx)
-{
-       chipset_dev->controlvm_payload_bytes_buffered -= ctx->param_bytes;
-       kfree(ctx);
-}
-
-static struct parser_context *parser_init_stream(u64 addr, u32 bytes,
-                                                bool *retry)
-{
-       int allocbytes;
-       struct parser_context *ctx;
-       void *mapping;
-
-       *retry = false;
-       /* alloc an extra byte to ensure payload is \0 terminated */
-       allocbytes = bytes + 1 + (sizeof(struct parser_context) -
-                    sizeof(struct visor_controlvm_parameters_header));
-       if ((chipset_dev->controlvm_payload_bytes_buffered + bytes) >
-            MAX_CONTROLVM_PAYLOAD_BYTES) {
-               *retry = true;
-               return NULL;
-       }
-       ctx = kzalloc(allocbytes, GFP_KERNEL);
-       if (!ctx) {
-               *retry = true;
-               return NULL;
-       }
-       ctx->allocbytes = allocbytes;
-       ctx->param_bytes = bytes;
-       mapping = memremap(addr, bytes, MEMREMAP_WB);
-       if (!mapping)
-               goto err_finish_ctx;
-       memcpy(&ctx->data, mapping, bytes);
-       memunmap(mapping);
-       ctx->byte_stream = true;
-       chipset_dev->controlvm_payload_bytes_buffered += ctx->param_bytes;
-       return ctx;
-
-err_finish_ctx:
-       kfree(ctx);
-       return NULL;
-}
-
-/*
- * handle_command() - process a controlvm message
- * @inmsg:        the message to process
- * @channel_addr: address of the controlvm channel
- *
- * Return:
- *     0       - Successfully processed the message
- *     -EAGAIN - ControlVM message was not processed and should be retried
- *               reading the next controlvm message; a scenario where this can
- *               occur is when we need to throttle the allocation of memory in
- *               which to copy out controlvm payload data.
- *     < 0     - error: ControlVM message was processed but an error occurred.
- */
-static int handle_command(struct controlvm_message inmsg, u64 channel_addr)
-{
-       struct controlvm_message_packet *cmd = &inmsg.cmd;
-       u64 parm_addr;
-       u32 parm_bytes;
-       struct parser_context *parser_ctx = NULL;
-       struct controlvm_message ackmsg;
-       int err = 0;
-
-       /* create parsing context if necessary */
-       parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
-       parm_bytes = inmsg.hdr.payload_bytes;
-       /*
-        * Parameter and channel addresses within test messages actually lie
-        * within our OS-controlled memory. We need to know that, because it
-        * makes a difference in how we compute the virtual address.
-        */
-       if (parm_bytes) {
-               bool retry;
-
-               parser_ctx = parser_init_stream(parm_addr, parm_bytes, &retry);
-               if (!parser_ctx && retry)
-                       return -EAGAIN;
-       }
-       controlvm_init_response(&ackmsg, &inmsg.hdr, CONTROLVM_RESP_SUCCESS);
-       err = visorchannel_signalinsert(chipset_dev->controlvm_channel,
-                                       CONTROLVM_QUEUE_ACK, &ackmsg);
-       if (err)
-               return err;
-       switch (inmsg.hdr.id) {
-       case CONTROLVM_CHIPSET_INIT:
-               err = chipset_init(&inmsg);
-               break;
-       case CONTROLVM_BUS_CREATE:
-               err = visorbus_create(&inmsg);
-               break;
-       case CONTROLVM_BUS_DESTROY:
-               err = visorbus_destroy(&inmsg);
-               break;
-       case CONTROLVM_BUS_CONFIGURE:
-               err = visorbus_configure(&inmsg, parser_ctx);
-               break;
-       case CONTROLVM_DEVICE_CREATE:
-               err = visorbus_device_create(&inmsg);
-               break;
-       case CONTROLVM_DEVICE_CHANGESTATE:
-               if (cmd->device_change_state.flags.phys_device) {
-                       err = parahotplug_process_message(&inmsg);
-               } else {
-                       /*
-                        * save the hdr and cmd structures for later use when
-                        * sending back the response to Command
-                        */
-                       err = visorbus_device_changestate(&inmsg);
-                       break;
-               }
-               break;
-       case CONTROLVM_DEVICE_DESTROY:
-               err = visorbus_device_destroy(&inmsg);
-               break;
-       case CONTROLVM_DEVICE_CONFIGURE:
-               /* no op just send a respond that we passed */
-               if (inmsg.hdr.flags.response_expected)
-                       controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS,
-                                         NULL);
-               break;
-       case CONTROLVM_CHIPSET_READY:
-               err = chipset_ready_uevent(&inmsg.hdr);
-               break;
-       case CONTROLVM_CHIPSET_SELFTEST:
-               err = chipset_selftest_uevent(&inmsg.hdr);
-               break;
-       case CONTROLVM_CHIPSET_STOP:
-               err = chipset_notready_uevent(&inmsg.hdr);
-               break;
-       default:
-               err = -ENOMSG;
-               if (inmsg.hdr.flags.response_expected)
-                       controlvm_respond(&inmsg.hdr,
-                                         -CONTROLVM_RESP_ID_UNKNOWN, NULL);
-               break;
-       }
-       if (parser_ctx) {
-               parser_done(parser_ctx);
-               parser_ctx = NULL;
-       }
-       return err;
-}
-
-/*
- * read_controlvm_event() - retreives the next message from the
- *                          CONTROLVM_QUEUE_EVENT queue in the controlvm
- *                          channel
- * @msg: pointer to the retrieved message
- *
- * Return: 0 if valid message was retrieved or -error
- */
-static int read_controlvm_event(struct controlvm_message *msg)
-{
-       int err = visorchannel_signalremove(chipset_dev->controlvm_channel,
-                                           CONTROLVM_QUEUE_EVENT, msg);
-
-       if (err)
-               return err;
-       /* got a message */
-       if (msg->hdr.flags.test_message == 1)
-               return -EINVAL;
-       return 0;
-}
-
-/*
- * parahotplug_process_list() - remove any request from the list that's been on
- *                              there too long and respond with an error
- */
-static void parahotplug_process_list(void)
-{
-       struct list_head *pos;
-       struct list_head *tmp;
-
-       spin_lock(&parahotplug_request_list_lock);
-       list_for_each_safe(pos, tmp, &parahotplug_request_list) {
-               struct parahotplug_request *req =
-                   list_entry(pos, struct parahotplug_request, list);
-
-               if (!time_after_eq(jiffies, req->expiration))
-                       continue;
-               list_del(pos);
-               if (req->msg.hdr.flags.response_expected)
-                       controlvm_respond(
-                               &req->msg.hdr,
-                               CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT,
-                               &req->msg.cmd.device_change_state.state);
-               parahotplug_request_destroy(req);
-       }
-       spin_unlock(&parahotplug_request_list_lock);
-}
-
-static void controlvm_periodic_work(struct work_struct *work)
-{
-       struct controlvm_message inmsg;
-       int count = 0;
-       int err;
-
-       /* Drain the RESPONSE queue make it empty */
-       do {
-               err = visorchannel_signalremove(chipset_dev->controlvm_channel,
-                                               CONTROLVM_QUEUE_RESPONSE,
-                                               &inmsg);
-       } while ((!err) && (++count < CONTROLVM_MESSAGE_MAX));
-       if (err != -EAGAIN)
-               goto schedule_out;
-       if (chipset_dev->controlvm_pending_msg_valid) {
-               /*
-                * we throttled processing of a prior msg, so try to process
-                * it again rather than reading a new one
-                */
-               inmsg = chipset_dev->controlvm_pending_msg;
-               chipset_dev->controlvm_pending_msg_valid = false;
-               err = 0;
-       } else {
-               err = read_controlvm_event(&inmsg);
-       }
-       while (!err) {
-               chipset_dev->most_recent_message_jiffies = jiffies;
-               err = handle_command(inmsg,
-                                    visorchannel_get_physaddr
-                                    (chipset_dev->controlvm_channel));
-               if (err == -EAGAIN) {
-                       chipset_dev->controlvm_pending_msg = inmsg;
-                       chipset_dev->controlvm_pending_msg_valid = true;
-                       break;
-               }
-
-               err = read_controlvm_event(&inmsg);
-       }
-       /* parahotplug_worker */
-       parahotplug_process_list();
-
-/*
- * The controlvm messages are sent in a bulk. If we start receiving messages, we
- * want the polling to be fast. If we do not receive any message for
- * MIN_IDLE_SECONDS, we can slow down the polling.
- */
-schedule_out:
-       if (time_after(jiffies, chipset_dev->most_recent_message_jiffies +
-                               (HZ * MIN_IDLE_SECONDS))) {
-               /*
-                * it's been longer than MIN_IDLE_SECONDS since we processed
-                * our last controlvm message; slow down the polling
-                */
-               if (chipset_dev->poll_jiffies != POLLJIFFIES_CONTROLVM_SLOW)
-                       chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_SLOW;
-       } else {
-               if (chipset_dev->poll_jiffies != POLLJIFFIES_CONTROLVM_FAST)
-                       chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST;
-       }
-       schedule_delayed_work(&chipset_dev->periodic_controlvm_work,
-                             chipset_dev->poll_jiffies);
-}
-
-static int visorchipset_init(struct acpi_device *acpi_device)
-{
-       int err = -ENODEV;
-       struct visorchannel *controlvm_channel;
-
-       chipset_dev = kzalloc(sizeof(*chipset_dev), GFP_KERNEL);
-       if (!chipset_dev)
-               goto error;
-       err = controlvm_channel_create(chipset_dev);
-       if (err)
-               goto error_free_chipset_dev;
-       acpi_device->driver_data = chipset_dev;
-       chipset_dev->acpi_device = acpi_device;
-       chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST;
-       err = sysfs_create_groups(&chipset_dev->acpi_device->dev.kobj,
-                                 visorchipset_dev_groups);
-       if (err < 0)
-               goto error_destroy_channel;
-       controlvm_channel = chipset_dev->controlvm_channel;
-       if (!visor_check_channel(visorchannel_get_header(controlvm_channel),
-                                &chipset_dev->acpi_device->dev,
-                                &visor_controlvm_channel_guid,
-                                "controlvm",
-                                sizeof(struct visor_controlvm_channel),
-                                VISOR_CONTROLVM_CHANNEL_VERSIONID,
-                                VISOR_CHANNEL_SIGNATURE))
-               goto error_delete_groups;
-       /* if booting in a crash kernel */
-       if (is_kdump_kernel())
-               INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work,
-                                 setup_crash_devices_work_queue);
-       else
-               INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work,
-                                 controlvm_periodic_work);
-       chipset_dev->most_recent_message_jiffies = jiffies;
-       chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST;
-       schedule_delayed_work(&chipset_dev->periodic_controlvm_work,
-                             chipset_dev->poll_jiffies);
-       err = visorbus_init();
-       if (err < 0)
-               goto error_cancel_work;
-       return 0;
-
-error_cancel_work:
-       cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work);
-
-error_delete_groups:
-       sysfs_remove_groups(&chipset_dev->acpi_device->dev.kobj,
-                           visorchipset_dev_groups);
-
-error_destroy_channel:
-       visorchannel_destroy(chipset_dev->controlvm_channel);
-
-error_free_chipset_dev:
-       kfree(chipset_dev);
-
-error:
-       dev_err(&acpi_device->dev, "failed with error %d\n", err);
-       return err;
-}
-
-static int visorchipset_exit(struct acpi_device *acpi_device)
-{
-       visorbus_exit();
-       cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work);
-       sysfs_remove_groups(&chipset_dev->acpi_device->dev.kobj,
-                           visorchipset_dev_groups);
-       visorchannel_destroy(chipset_dev->controlvm_channel);
-       kfree(chipset_dev);
-       return 0;
-}
-
-static const struct acpi_device_id unisys_device_ids[] = {
-       {"PNP0A07", 0},
-       {"", 0},
-};
-
-static struct acpi_driver unisys_acpi_driver = {
-       .name = "unisys_acpi",
-       .class = "unisys_acpi_class",
-       .owner = THIS_MODULE,
-       .ids = unisys_device_ids,
-       .ops = {
-               .add = visorchipset_init,
-               .remove = visorchipset_exit,
-       },
-};
-
-MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
-
-static __init int visorutil_spar_detect(void)
-{
-       unsigned int eax, ebx, ecx, edx;
-
-       if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
-               /* check the ID */
-               cpuid(UNISYS_VISOR_LEAF_ID, &eax, &ebx, &ecx, &edx);
-               return  (ebx == UNISYS_VISOR_ID_EBX) &&
-                       (ecx == UNISYS_VISOR_ID_ECX) &&
-                       (edx == UNISYS_VISOR_ID_EDX);
-       }
-       return 0;
-}
-
-static int __init init_unisys(void)
-{
-       int result;
-
-       if (!visorutil_spar_detect())
-               return -ENODEV;
-       result = acpi_bus_register_driver(&unisys_acpi_driver);
-       if (result)
-               return -ENODEV;
-       pr_info("Unisys Visorchipset Driver Loaded.\n");
-       return 0;
-};
-
-static void __exit exit_unisys(void)
-{
-       acpi_bus_unregister_driver(&unisys_acpi_driver);
-}
-
-module_init(init_unisys);
-module_exit(exit_unisys);
-
-MODULE_AUTHOR("Unisys");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("s-Par visorbus driver for virtual device buses");
index 0bcd3acb7b0c8b30147ff2ae9d962ba569b5dd0f..167e98f8688e01008fe9be1f913a5de41a61ed0c 100644 (file)
@@ -1,17 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2012 - 2015 UNISYS CORPORATION
  * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
  */
 
 #include <linux/debugfs.h>
 #include <linux/idr.h>
 #include <linux/module.h>
 #include <linux/seq_file.h>
+#include <linux/visorbus.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 
-#include "visorbus.h"
 #include "iochannel.h"
 
 /* The Send and Receive Buffers of the IO Queue may both be full */
index 53975a09535f9651c90931759c192ee9f70a459d..67dac430ce0c28f27c6ce152f6ca77115b30b72c 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
  */
 
 #ifndef __SPAR_ULTRAINPUTREPORT_H__
index 450f003743c00af0d1fd8a3ceab3425253621cc5..d8048e48658ffb5f9872e4f8107104f282482509 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2011 - 2015 UNISYS CORPORATION
  * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
  */
 
 /*
@@ -25,8 +16,8 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/uuid.h>
+#include <linux/visorbus.h>
 
-#include "visorbus.h"
 #include "ultrainputreport.h"
 
 /* Keyboard channel {c73416d0-b0b8-44af-b304-9d2ae99f1b3d} */
index 6d8239163ba55452e0e7a4708b14bd7ebec5c785..92dceb557886b8f4971d33790d6cc3b8c960face 100644 (file)
@@ -1,15 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /* Copyright (c) 2012 - 2015 UNISYS CORPORATION
  * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
  */
 
 /* This driver lives in a spar partition, and registers to ethernet io
@@ -25,8 +16,8 @@
 #include <linux/kthread.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
+#include <linux/visorbus.h>
 
-#include "visorbus.h"
 #include "iochannel.h"
 
 #define VISORNIC_INFINITE_RSP_WAIT 0
index 8aed248db6e2330c08fe7c9f2673f9b2485b5e76..43c39eca4ae1498940f28e54f799943eb615f215 100644 (file)
@@ -170,7 +170,7 @@ static int vboxfb_create(struct drm_fb_helper *helper,
        drm_fb_helper_fill_var(info, &fbdev->helper, sizes->fb_width,
                               sizes->fb_height);
 
-       info->screen_base = bo->kmap.virtual;
+       info->screen_base = (char __iomem *)bo->kmap.virtual;
        info->screen_size = size;
 
 #ifdef CONFIG_DRM_KMS_FB_HELPER
index 80bd039fa08e9178e19ec876493f9cb64c324e88..973b3bcc04b1db2fffd1fe621734b903f1b3b399 100644 (file)
@@ -61,7 +61,7 @@ void vbox_enable_accel(struct vbox_private *vbox)
                if (vbox->vbva_info[i].vbva)
                        continue;
 
-               vbva = (void *)vbox->vbva_buffers + i * VBVA_MIN_BUFFER_SIZE;
+               vbva = (void __force *)vbox->vbva_buffers + i * VBVA_MIN_BUFFER_SIZE;
                if (!vbva_enable(&vbox->vbva_info[i],
                                 vbox->guest_pool, vbva, i)) {
                        /* very old host or driver error. */
index f484bb055df724fdf17e04e2a994dd74a8d7149b..ec468d5719b11212b52816fd5389d8638c3ab8f2 100644 (file)
@@ -1,16 +1,5 @@
-/*****************************************************************************
- * Copyright 2011 Broadcom Corporation.  All rights reserved.
- *
- * Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2011 Broadcom Corporation.  All rights reserved. */
 
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 7e68b3e28246eafa025a8b35ee397016f9e20593..5f7551fbf5cf77e415d6c2ea4152520522633da1 100644 (file)
@@ -1,16 +1,5 @@
-/*****************************************************************************
- * Copyright 2011 Broadcom Corporation.  All rights reserved.
- *
- * Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2011 Broadcom Corporation.  All rights reserved. */
 
 #include <linux/interrupt.h>
 #include <linux/slab.h>
index 3c6f1d91d22d91d89c206c38aa7f38d950895d53..a4a48f31f1a33c71944bf19f311565509441e4c6 100644 (file)
@@ -1,16 +1,5 @@
-/*****************************************************************************
- * Copyright 2011 Broadcom Corporation.  All rights reserved.
- *
- * Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2011 Broadcom Corporation.  All rights reserved. */
 
 #include <linux/device.h>
 #include <sound/core.h>
index 8f2d508183b29a8ab6a049c488174588b49979e3..045d577fe4f8b31b9c39be2bd33d035ece2aaffd 100644 (file)
@@ -1,16 +1,5 @@
-/*****************************************************************************
- * Copyright 2011 Broadcom Corporation.  All rights reserved.
- *
- * Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2011 Broadcom Corporation.  All rights reserved. */
 
 #include <linux/platform_device.h>
 
@@ -443,7 +432,6 @@ static struct platform_driver bcm2835_alsa0_driver = {
 #endif
        .driver = {
                .name = "bcm2835_audio",
-               .owner = THIS_MODULE,
                .of_match_table = snd_bcm2835_of_match_table,
        },
 };
index f1e43e45fd67a21205f10bd5052d2a21f776a4d4..dc6ec915f9f585c60e21ddb18869339a1d49ff7d 100644 (file)
@@ -1,16 +1,5 @@
-/*****************************************************************************
- * Copyright 2011 Broadcom Corporation.  All rights reserved.
- *
- * Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright 2011 Broadcom Corporation.  All rights reserved. */
 
 #ifndef __SOUND_ARM_BCM2835_H
 #define __SOUND_ARM_BCM2835_H
index da96f1bc25167b2f088e6fbe418d81169b8c3276..1a7f0884ac9ce61aa79c83eed584934060d0f8d1 100644 (file)
@@ -1,16 +1,5 @@
-/*****************************************************************************
- * Copyright 2011 Broadcom Corporation.  All rights reserved.
- *
- * Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *****************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright 2011 Broadcom Corporation.  All rights reserved. */
 
 #ifndef _VC_AUDIO_DEFS_H_
 #define _VC_AUDIO_DEFS_H_
index be936b8fe317599b132988f0a700ec7f7df15af6..d2262275a8700e3aba3d8a6c39eb28c6f6897da8 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
@@ -328,11 +325,9 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
                                pr_debug("Grab another frame");
                                vchiq_mmal_port_parameter_set(
                                        instance,
-                                       dev->capture.
-                                       camera_port,
+                                       dev->capture.camera_port,
                                        MMAL_PARAMETER_CAPTURE,
-                                       &dev->capture.
-                                       frame_count,
+                                       &dev->capture.frame_count,
                                        sizeof(dev->capture.frame_count));
                        }
                } else {
@@ -343,37 +338,17 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
                if (dev->capture.frame_count) {
                        if (dev->capture.vc_start_timestamp != -1 &&
                            pts != 0) {
-                               struct timeval timestamp;
+                               ktime_t timestamp;
                                s64 runtime_us = pts -
                                    dev->capture.vc_start_timestamp;
-                               u32 div = 0;
-                               u32 rem = 0;
-
-                               div =
-                                   div_u64_rem(runtime_us, USEC_PER_SEC, &rem);
-                               timestamp.tv_sec =
-                                   dev->capture.kernel_start_ts.tv_sec + div;
-                               timestamp.tv_usec =
-                                   dev->capture.kernel_start_ts.tv_usec + rem;
-
-                               if (timestamp.tv_usec >=
-                                   USEC_PER_SEC) {
-                                       timestamp.tv_sec++;
-                                       timestamp.tv_usec -=
-                                           USEC_PER_SEC;
-                               }
+                               timestamp = ktime_add_us(dev->capture.kernel_start_ts,
+                                                        runtime_us);
                                v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                                        "Convert start time %d.%06d and %llu "
-                                        "with offset %llu to %d.%06d\n",
-                                        (int)dev->capture.kernel_start_ts.
-                                        tv_sec,
-                                        (int)dev->capture.kernel_start_ts.
-                                        tv_usec,
+                                        "Convert start time %llu and %llu with offset %llu to %llu\n",
+                                        ktime_to_ns(dev->capture.kernel_start_ts),
                                         dev->capture.vc_start_timestamp, pts,
-                                        (int)timestamp.tv_sec,
-                                        (int)timestamp.tv_usec);
-                               buf->vb.vb2_buf.timestamp = timestamp.tv_sec * 1000000000ULL +
-                                       timestamp.tv_usec * 1000ULL;
+                                        ktime_to_ns(timestamp));
+                               buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
                        } else {
                                buf->vb.vb2_buf.timestamp = ktime_get_ns();
                        }
@@ -387,11 +362,9 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
                                         "Grab another frame as buffer has EOS");
                                vchiq_mmal_port_parameter_set(
                                        instance,
-                                       dev->capture.
-                                       camera_port,
+                                       dev->capture.camera_port,
                                        MMAL_PARAMETER_CAPTURE,
-                                       &dev->capture.
-                                       frame_count,
+                                       &dev->capture.frame_count,
                                        sizeof(dev->capture.frame_count));
                        }
                } else {
@@ -547,7 +520,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
                         "Start time %lld size %d\n",
                         dev->capture.vc_start_timestamp, parameter_size);
 
-       v4l2_get_timestamp(&dev->capture.kernel_start_ts);
+       dev->capture.kernel_start_ts = ktime_get();
 
        /* enable the camera port */
        dev->capture.port->cb_ctx = dev;
@@ -555,8 +528,8 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
            vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb);
        if (ret) {
                v4l2_err(&dev->v4l2_dev,
-                       "Failed to enable capture port - error %d. "
-                       "Disabling camera port again\n", ret);
+                       "Failed to enable capture port - error %d. Disabling camera port again\n",
+                       ret);
 
                vchiq_mmal_port_disable(dev->instance,
                                        dev->capture.camera_port);
@@ -1213,8 +1186,8 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
                                        port->current_buffer.size =
                                            (f->fmt.pix.sizeimage <
                                             (100 << 10))
-                                           ? (100 << 10) : f->fmt.pix.
-                                           sizeimage;
+                                           ? (100 << 10)
+                                           : f->fmt.pix.sizeimage;
                                }
                                v4l2_dbg(1, bcm2835_v4l2_debug,
                                         &dev->v4l2_dev,
index 404037476bc5119acb2f37dbd92900a3f8719bf9..2b5679eb5b4a7eb0e51067562b16b749dae52ba5 100644 (file)
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
@@ -92,7 +89,7 @@ struct bm2835_mmal_dev {
                /* VC start timestamp for streaming */
                s64         vc_start_timestamp;
                /* Kernel start timestamp for streaming */
-               struct timeval kernel_start_ts;
+               ktime_t kernel_start_ts;
 
                struct vchiq_mmal_port  *port; /* port being used for capture */
                /* camera port being used for capture */
index 77a5d6f4e1eb8fe4e2482bb62d429b04598a1759..0736214e142246f0c2d024e75c49468ea395ee35 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
index 840fd139e03315b5d9ac2d5742ab589bc6b17ade..800e4e7e5f96d7ffbe63b7630d0e7cabae2d26e9 100644 (file)
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
index e71d9600b2782ca0eee54b369411d42ab91567e6..129203597f917953901cfb23452c511fbb946c5c 100644 (file)
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
index 66e8a6edf628565aeb487662b0b503c0c562ac8a..ec8455639d497f39db2ec6ea7f2f659ad7e79c7b 100644 (file)
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
index 24b002e8df0cc31b2ff595844520623764805366..c9d6fbe25fe4869f79649b0cf391a1e1dc60a23e 100644 (file)
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
index 84a0f4b717ef36e0244da0e510534117fb44e5a0..dd4b4ce72081a2ab25d489a8687934ad7ba2845e 100644 (file)
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
index 5a1b2a7d8eb0eb2f06d17159ba730f4540b27b50..d1c57edbe2b890891f63078efc014fb635fafc3f 100644 (file)
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
index e7300229842db35ec4ad73448d9085fbc20035c2..1607bc4c0347657bbbe01b077643e758df1f6f4c 100644 (file)
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
index 6ea7fb0ea50e96bc7e864129f565639f2042a89c..a91ef6ea29ceba3fd7a56e81364df0f134476d6e 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
@@ -618,8 +615,8 @@ static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
        struct mmal_msg_context *msg_context;
        u32 handle;
 
-       pr_debug("buffer_to_host_cb: instance:%p msg:%p msg_len:%d\n",
-                instance, msg, msg_len);
+       pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
+                __func__, instance, msg, msg_len);
 
        if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
                handle = msg->u.buffer_from_host.drvbuf.client_context;
@@ -1360,8 +1357,7 @@ static int port_action_handle(struct vchiq_mmal_instance *instance,
 
        ret = -rmsg->u.port_action_reply.status;
 
-       pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)" \
-                " connect component:0x%x connect port:%d\n",
+       pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d) connect component:0x%x connect port:%d\n",
                 __func__,
                 ret, port->component->handle, port->handle,
                 port_action_type_names[action_type],
index db39900c9d91ef5e98e004895d8de793a7754998..b1f22b6dca109526c20e9c9f8627e73e395d22e6 100644 (file)
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Broadcom BM2835 V4L2 driver
  *
  * Copyright Â© 2013 Raspberry Pi (Trading) Ltd.
  *
- * 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.
- *
  * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  *          Dave Stevenson <dsteve@broadcom.com>
  *          Simon Mellor <simellor@broadcom.com>
index 315b49c1de3bb323f4383e4ba8acb3e3ded422b1..b59ef14890aa3a498e0356bde6f37a353e3f3b22 100644 (file)
@@ -224,8 +224,7 @@ vchiq_platform_get_arm_state(VCHIQ_STATE_T *state)
 
        platform_state   = (struct vchiq_2835_state *)state->platform_state;
 
-       if (!platform_state->inited)
-               BUG();
+       WARN_ON_ONCE(!platform_state->inited);
 
        return &platform_state->arm_state;
 }
@@ -485,8 +484,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
                                       __func__, actual_pages, num_pages);
 
                        /* This is probably due to the process being killed */
-                       while (actual_pages > 0)
-                       {
+                       while (actual_pages > 0) {
                                actual_pages--;
                                put_page(pages[actual_pages]);
                        }
index 411539f8ff8c74cade9946524293b40c549dd9be..c2c440009cac4cd24c28b661dd1286ef7053a5f5 100644 (file)
@@ -682,8 +682,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        if (user_service->close_pending &&
                                down_interruptible(&user_service->close_event))
                                status = VCHIQ_RETRY;
-               }
-               else
+               } else
                        ret = -EINVAL;
        } break;
 
@@ -708,8 +707,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        if (user_service->close_pending &&
                                down_interruptible(&user_service->close_event))
                                status = VCHIQ_RETRY;
-               }
-               else
+               } else
                        ret = -EINVAL;
        } break;
 
@@ -1171,8 +1169,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        USER_SERVICE_T *user_service =
                                (USER_SERVICE_T *)service->base.userdata;
                        close_delivered(user_service);
-               }
-               else
+               } else
                        ret = -EINVAL;
        } break;
 
@@ -1810,8 +1807,7 @@ vchiq_release(struct inode *inode, struct file *file)
                                instance->completion_remove &
                                (MAX_COMPLETIONS - 1)];
                        service = completion->service_userdata;
-                       if (completion->reason == VCHIQ_SERVICE_CLOSED)
-                       {
+                       if (completion->reason == VCHIQ_SERVICE_CLOSED) {
                                USER_SERVICE_T *user_service =
                                        service->base.userdata;
 
index ecff92bae2000d41f5f5062a323f414a56dd7e38..5d28fff46557ec262c5e9797dd4d80dcef6e7f4d 100644 (file)
@@ -66,8 +66,7 @@ struct vchiq_openack_payload {
        short version;
 };
 
-enum
-{
+enum {
        QMFLAGS_IS_BLOCKING     = (1 << 0),
        QMFLAGS_NO_MUTEX_LOCK   = (1 << 1),
        QMFLAGS_NO_MUTEX_UNLOCK = (1 << 2)
@@ -212,7 +211,8 @@ find_service_by_port(VCHIQ_STATE_T *state, int localport)
 
 VCHIQ_SERVICE_T *
 find_service_for_instance(VCHIQ_INSTANCE_T instance,
-       VCHIQ_SERVICE_HANDLE_T handle) {
+       VCHIQ_SERVICE_HANDLE_T handle)
+{
        VCHIQ_SERVICE_T *service;
 
        spin_lock(&service_spinlock);
@@ -235,7 +235,8 @@ find_service_for_instance(VCHIQ_INSTANCE_T instance,
 
 VCHIQ_SERVICE_T *
 find_closed_service_for_instance(VCHIQ_INSTANCE_T instance,
-       VCHIQ_SERVICE_HANDLE_T handle) {
+       VCHIQ_SERVICE_HANDLE_T handle)
+{
        VCHIQ_SERVICE_T *service;
 
        spin_lock(&service_spinlock);
index 34f746db19cd26f8a2511a596650fcdcc8a984fc..43c89a08bda9622b0d54b43c05c9e628b869f927 100644 (file)
@@ -64,11 +64,6 @@ static VCHIQ_STATUS_T
 vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
        unsigned int size, VCHIQ_BULK_DIR_T dir);
 
-/****************************************************************************
-*
-*   vchiq_initialise
-*
-***************************************************************************/
 #define VCHIQ_INIT_RETRIES 10
 VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out)
 {
@@ -80,7 +75,9 @@ VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out)
        vchiq_log_trace(vchiq_core_log_level, "%s called", __func__);
 
        /* VideoCore may not be ready due to boot up timing.
-          It may never be ready if kernel and firmware are mismatched, so don't block forever. */
+        * It may never be ready if kernel and firmware are mismatched,so don't
+        * block forever.
+        */
        for (i = 0; i < VCHIQ_INIT_RETRIES; i++) {
                state = vchiq_get_state();
                if (state)
@@ -93,7 +90,8 @@ VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out)
                goto failed;
        } else if (i > 0) {
                vchiq_log_warning(vchiq_core_log_level,
-                       "%s: videocore initialized after %d retries\n", __func__, i);
+                       "%s: videocore initialized after %d retries\n",
+                       __func__, i);
        }
 
        instance = kzalloc(sizeof(*instance), GFP_KERNEL);
@@ -120,12 +118,6 @@ failed:
 }
 EXPORT_SYMBOL(vchiq_initialise);
 
-/****************************************************************************
-*
-*   vchiq_shutdown
-*
-***************************************************************************/
-
 VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)
 {
        VCHIQ_STATUS_T status;
@@ -168,23 +160,11 @@ VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)
 }
 EXPORT_SYMBOL(vchiq_shutdown);
 
-/****************************************************************************
-*
-*   vchiq_is_connected
-*
-***************************************************************************/
-
 static int vchiq_is_connected(VCHIQ_INSTANCE_T instance)
 {
        return instance->connected;
 }
 
-/****************************************************************************
-*
-*   vchiq_connect
-*
-***************************************************************************/
-
 VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance)
 {
        VCHIQ_STATUS_T status;
@@ -214,12 +194,6 @@ failed:
 }
 EXPORT_SYMBOL(vchiq_connect);
 
-/****************************************************************************
-*
-*   vchiq_add_service
-*
-***************************************************************************/
-
 VCHIQ_STATUS_T vchiq_add_service(
        VCHIQ_INSTANCE_T              instance,
        const VCHIQ_SERVICE_PARAMS_T *params,
@@ -259,12 +233,6 @@ VCHIQ_STATUS_T vchiq_add_service(
 }
 EXPORT_SYMBOL(vchiq_add_service);
 
-/****************************************************************************
-*
-*   vchiq_open_service
-*
-***************************************************************************/
-
 VCHIQ_STATUS_T vchiq_open_service(
        VCHIQ_INSTANCE_T              instance,
        const VCHIQ_SERVICE_PARAMS_T *params,
@@ -414,8 +382,9 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
                        if ((bulk->data != data) ||
                                (bulk->size != size)) {
                                /* This is not a retry of the previous one.
-                               ** Cancel the signal when the transfer
-                               ** completes. */
+                                * Cancel the signal when the transfer
+                                * completes.
+                                */
                                spin_lock(&bulk_waiter_spinlock);
                                bulk->userdata = NULL;
                                spin_unlock(&bulk_waiter_spinlock);
@@ -441,7 +410,8 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
 
                if (bulk) {
                        /* Cancel the signal when the transfer
-                        ** completes. */
+                        * completes.
+                        */
                        spin_lock(&bulk_waiter_spinlock);
                        bulk->userdata = NULL;
                        spin_unlock(&bulk_waiter_spinlock);
index d465e1cf5db93e4b4f7691d1b2cccedc2a09e190..29984f9795c7ac00a0618959fcbd24492ed245e4 100644 (file)
@@ -800,8 +800,7 @@ int32_t vchi_get_peer_version(const VCHI_SERVICE_HANDLE_T handle, short *peer_ve
        int32_t ret = -1;
        struct shim_service *service = (struct shim_service *)handle;
 
-       if (service)
-       {
+       if (service) {
                VCHIQ_STATUS_T status;
 
                status = vchiq_get_peer_version(service->handle, peer_version);
index 4c8c6fa0a79feabe6efa0252a441df1c5bb30e01..3242dee8246faa7a141e518dd56990a1032ca274 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * VMEbus User access driver
  *
@@ -7,12 +8,6 @@
  * Based on work by:
  *   Tom Armistead and Ajit Prem
  *     Copyright 2004 Motorola Inc.
- *
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -573,7 +568,7 @@ static int vme_user_probe(struct vme_dev *vdev)
                 * by all windows.
                 */
                image[i].resource = vme_slave_request(vme_user_bridge,
-                       VME_A24, VME_SCT);
+                                                     VME_A24, VME_SCT);
                if (!image[i].resource) {
                        dev_warn(&vdev->dev,
                                 "Unable to allocate slave resource\n");
@@ -582,7 +577,8 @@ static int vme_user_probe(struct vme_dev *vdev)
                }
                image[i].size_buf = PCI_BUF_SIZE;
                image[i].kern_buf = vme_alloc_consistent(image[i].resource,
-                       image[i].size_buf, &image[i].pci_buf);
+                                                        image[i].size_buf,
+                                                        &image[i].pci_buf);
                if (!image[i].kern_buf) {
                        dev_warn(&vdev->dev,
                                 "Unable to allocate memory for buffer\n");
@@ -600,7 +596,8 @@ static int vme_user_probe(struct vme_dev *vdev)
        for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++) {
                /* XXX Need to properly request attributes */
                image[i].resource = vme_master_request(vme_user_bridge,
-                       VME_A32, VME_SCT, VME_D32);
+                                                      VME_A32, VME_SCT,
+                                                      VME_D32);
                if (!image[i].resource) {
                        dev_warn(&vdev->dev,
                                 "Unable to allocate master resource\n");
@@ -645,7 +642,8 @@ static int vme_user_probe(struct vme_dev *vdev)
 
                num = (type[i] == SLAVE_MINOR) ? i - (MASTER_MAX + 1) : i;
                image[i].device = device_create(vme_user_sysfs_class, NULL,
-                                       MKDEV(VME_MAJOR, i), NULL, name, num);
+                                               MKDEV(VME_MAJOR, i), NULL,
+                                               name, num);
                if (IS_ERR(image[i].device)) {
                        dev_info(&vdev->dev, "Error creating sysfs device\n");
                        err = PTR_ERR(image[i].device);
index 44dfa54213740446e85c289da5f2299198362b91..f0b16347342659d80100c2df516ba06dd7f6da1e 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: baseband.c
  *
  * Purpose: Implement functions to access baseband
index feaf222574ee73f63da515c59d98e5724447fba3..b8ee33dcb35225c1e40b776acd01fd9f9ab6fa1d 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: baseband.h
  *
  * Purpose: Implement functions to access baseband
index 14034e342aa648df43a204c5b2d4eaeac7ca9ecc..ea0a4b57852c2219191a75192e3e6792f059c9d6 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: card.c
  * Purpose: Provide functions to setup NIC operation mode
  * Functions:
index 1a04dbb57d425ef3b120f46e35b3064f6722886d..487039a64587dceccb527d6857f86d1cced4bde5 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: card.h
  *
  * Purpose: Provide functions to setup NIC operation mode
index ab89956511a00a5c3378d7ad68dc051ed97237e7..dec6f0f23b88234321f5a47468fe128ca572839b 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: channel.c
  *
  */
index 8fe70760e548e89f79346cd24b716b33791001e8..53f623a4af6532d68f6c9507348ed5d3f0ac2d8c 100644 (file)
@@ -1,19 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: channel.h
- *
  */
 
 #ifndef _CHANNEL_H_
index 2fee6e759ad84aecdc2f3ccaac17bfa9a01a5317..b4a0037b40c16ca185b3c2b2f4dec9f2290702d0 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: desc.h
  *
  * Purpose:The header file of descriptor
index 3ae40d846a0927635caca95cf0be6c9e0a55480c..2f9e9219e8c82947a1ff83926efece8cd09ea8eb 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: device.h
  *
  * Purpose: MAC Data structure
index 0298ea923f972b3326b40cf5d877870691bbb914..73f904b51b965d8226eadc83ba4021187285072d 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: device_cfg.h
  *
  * Purpose: Driver configuration header
index 1123b4f1e1d66987981687445129347c119fad14..0dc902022a918f76ad8c17dd3f693f92d7963f0d 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: device_main.c
  *
  * Purpose: driver entry for initial, open, close, tx and rx.
@@ -547,7 +538,7 @@ static void device_init_rd0_ring(struct vnt_private *priv)
        for (i = 0; i < priv->opts.rx_descs0;
             i ++, curr += sizeof(struct vnt_rx_desc)) {
                desc = &priv->aRD0Ring[i];
-               desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_ATOMIC);
+               desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL);
 
                if (!device_alloc_rx_buf(priv, desc))
                        dev_err(&priv->pcid->dev, "can not alloc rx bufs\n");
@@ -571,7 +562,7 @@ static void device_init_rd1_ring(struct vnt_private *priv)
        for (i = 0; i < priv->opts.rx_descs1;
             i ++, curr += sizeof(struct vnt_rx_desc)) {
                desc = &priv->aRD1Ring[i];
-               desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_ATOMIC);
+               desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL);
 
                if (!device_alloc_rx_buf(priv, desc))
                        dev_err(&priv->pcid->dev, "can not alloc rx bufs\n");
@@ -629,7 +620,7 @@ static void device_init_td0_ring(struct vnt_private *priv)
        for (i = 0; i < priv->opts.tx_descs[0];
             i++, curr += sizeof(struct vnt_tx_desc)) {
                desc = &priv->apTD0Rings[i];
-               desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_ATOMIC);
+               desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL);
 
                desc->td_info->buf = priv->tx0_bufs + i * PKT_BUF_SZ;
                desc->td_info->buf_dma = priv->tx_bufs_dma0 + i * PKT_BUF_SZ;
@@ -654,7 +645,7 @@ static void device_init_td1_ring(struct vnt_private *priv)
        for (i = 0; i < priv->opts.tx_descs[1];
             i++, curr += sizeof(struct vnt_tx_desc)) {
                desc = &priv->apTD1Rings[i];
-               desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_ATOMIC);
+               desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL);
 
                desc->td_info->buf = priv->tx1_bufs + i * PKT_BUF_SZ;
                desc->td_info->buf_dma = priv->tx_bufs_dma1 + i * PKT_BUF_SZ;
index 9b3fa779258a672b0196b600d73832596d5538bb..088d2d9dbc21fe1f2dd294ebd8995806254cf6ab 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: dpc.c
  *
  * Purpose: handle dpc rx functions
index 6e75fa9c5618c2fc164455de43d686e702ba2204..93af4220605fbbbd09e6de93cc3bfc50b4b93198 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: dpc.h
  *
  * Purpose:
index d891993b20cfb4e4f59685a666d1a7543ce7ab90..4d6b48fd119d215803b6256a29c4e35f8e895ca9 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: key.c
  *
  * Purpose: Implement functions for 802.11i Key management
index a5024611af60ded3c9b48ec1cdfe3d2dee3a99ec..0942d8703f9891a85e46745dfbeb276a0d006ec8 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: key.h
  *
  * Purpose: Implement functions for 802.11i Key management
index f7550b215f72d11d40c7129dda653945eb788cdf..4750863c1bb743012db7ed2e2b3d16f6e20b7494 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: mac.c
  *
  * Purpose:  MAC routines
index db401e32ae23757c94ae802b7567fa3cfaaa167a..b8ab0943477355227cb7df8373e75d9319079d44 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: mac.h
  *
  * Purpose: MAC routines
index 716d2a80f8400c0c11f615484e384f7920f6b5b2..d6c581b31569d7b7785a8f065cd6a0fdb852b863 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: power.c
  *
  * Purpose: Handles 802.11 power management  functions
index f360c5966523d4994d916a03737b2e991d945b46..2ec40045fddb1ed96f51b32113d2799d6533d082 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: power.h
  *
  * Purpose: Handles 802.11 power management  functions
index edf7db9d53b32c2a6b54a40dbb66e19c5c2a25be..03b0d56dbe9e4c2b0ab7b645d192abafaf6a537f 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: rf.c
  *
  * Purpose: rf function code
index ba222301d49d0f0e01ed440b99fa8c11fdc57114..bfce5a89657d36314fd6498f372bb037306993a2 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: rf.h
  *
  * Purpose:
index 3efe19a1b13f55cd4d1d895a32797951681432e1..9aa4d5262aaa17bdf5319b4d3990ab34c83aa354 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: rxtx.c
  *
  * Purpose: handle WMAC/802.3/802.11 rx & tx functions
index 095258923ebdce810497919b1647d1b56fd8ac97..08db848613f05b896d502aa32aaa8515b697c676 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: rxtx.h
  *
  * Purpose:
index 635f271595f680ebe4755d48ad5858c4dfe879f0..df57d120ed30eb508686ed4970224914b72366e9 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: srom.c
  *
  * Purpose:Implement functions to access eeprom
index 6e03ab6dfa9d33800a5987c47b56140a3329cfa0..577f20dc4308acc4a2d3b25d3d58b9f75bd998f5 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: srom.h
  *
  * Purpose: Implement functions to access eeprom
index d6a0563ad55c1381b5a30b719742590642440b97..6795b5d74cfcc10d1d66679b18580f1c834d8525 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: tmacro.h
  *
  * Purpose: define basic common types and macros
index 9806b5989014fa147705a7417a77a3f554c401c9..61b3e568ff9aad96e8000e8354573077adc853fe 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * File: upc.h
  *
  * Purpose: Macros to access device
index 882fe54ce41d876d700943f11dc305f6c9848630..b29ba237fa2953f968864dc6376f3d5519160bec 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: baseband.c
  *
  * Purpose: Implement functions to access baseband
index fe1c25c64cca14d9098986d8ef384bafc7af279f..a907e302601272668f195fa1d318c0309ebec261 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: baseband.h
  *
  * Purpose: Implement functions to access baseband
index 4fd9cd64c6e8da2140eab7a555769e5fb8f433ee..501f482b41c49087ec6753cb67d945a47d3ce1ba 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: card.c
  * Purpose: Provide functions to setup NIC operation mode
  * Functions:
index 7f08cda27e2c4f4bb0db792b61936f05ea82cd72..0a91d9ba468817debab55438e7a5bd01c2269f46 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: card.h
  *
  * Purpose: Provide functions to setup NIC operation mode
index a4299f405d7f5dddc18a1a8287a76f9655ada80a..5d57d34577f5f89779e201817bb7ab0dc078743d 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: channel.c
  *
  * Purpose: Channel number mapping
index 62f18a959098e77870d4928df264dc563d17d45e..6d0d2825d9925b2cb6f902a0b6f1f7d6c6da21e3 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: channel.h
  *
  * Purpose: Country Regulation Rules header file
index 59e3071021bde9de639a40af4e213b01fce37315..ac45ebb71195230e58588f5d6a0d880bace96809 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: desc.h
  *
  * Purpose:The header file of descriptor
index 74715c85485600c27b34b303e11b6c389698d9ba..a2feeb916836ccbc8b7240235b924a3e491d4c94 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: device.h
  *
  * Purpose: MAC Data structure
index 655f0002f8808a6d4527dd23f35987d8c014bda2..c3b5b14310483e7ddb2f3a9ae6d050584475313c 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: dpc.c
  *
  * Purpose: handle dpc rx functions
index 5d0454f3af0ea28e0943a9929c65f216d8de9da4..ddd0cb710512d30302d425f98c4e9b3ae1ab90ce 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: dpc.h
  *
  * Purpose:
index 093a6048bd223f0fb9898b17f3f51be3bfd88421..38521c338917b628541e23af8ea4913ca1712eaf 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: baseband.c
  *
  * Purpose: Implement functions to access baseband
index f753019c94c9ef36110cc2f5ddc382599a3db31e..f30ae90cbb1f4081bc69904948ce2e90c1f0328c 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: firmware.h
  *
  * Purpose: Version and Release Information
index c6ffbe0e2728c29250bee442afab8cddacf1bc8f..504424b19fcf9981ceb1a1ff28348ba8e2624c22 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: int.c
  *
  * Purpose: Handle USB interrupt endpoint
index b5f1b4b02ce4b4735b6f9da3ed5395cc0f8a0ec5..1e6ff925701a14e20eecf774941f64ee938b2b9a 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: int.h
  *
  * Purpose:
index cc18cb141bff18e8f80437361506d857eb0b8acc..91dede54cc1f5c2ea533d1895541ffa5512c0f3b 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: key.c
  *
  * Purpose: Implement functions for 802.11i Key management
index cfc6c21315366898079a08c3d0eb49e7a14f9f50..1306ff441b871008a5ffeba49bc4d02f63f004ca 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: key.h
  *
  * Purpose: Implement functions for 802.11i Key management
index 417fdad1f9aeaf84b38f7d771cad3fc78b61a7c7..0b543854ea972bd6302692484f3b5efb85f60ea8 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: mac.c
  *
  * Purpose:  MAC routines
index 29f37a0ff156484cba7928d9e0690194ac48238d..94e700fcd0b6dde966ec61de1f16356b7988c415 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: mac.h
  *
  * Purpose: MAC routines
index cc6d8778fe5ba89220dd60e5b878a7bf5dc7c5f6..ccafcc2c87ac980da5f70e52cfa89ad41a0cdf45 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: main_usb.c
  *
  * Purpose: driver entry for initial, open, close, tx and rx.
@@ -437,11 +427,8 @@ static bool vnt_alloc_bufs(struct vnt_private *priv)
 
        for (ii = 0; ii < priv->num_rcb; ii++) {
                priv->rcb[ii] = kzalloc(sizeof(*priv->rcb[ii]), GFP_KERNEL);
-               if (!priv->rcb[ii]) {
-                       dev_err(&priv->usb->dev,
-                               "failed to allocate rcb no %d\n", ii);
+               if (!priv->rcb[ii])
                        goto free_rx_tx;
-               }
 
                rcb = priv->rcb[ii];
 
index c466e0614bc4c223fef81f8dcc9b869682b9008c..7a086c72d5a89fbf5b5e465b420ca0e3644b24dd 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: power.c
  *
  * Purpose: Handles 802.11 power management functions
index 859e75fc77accf2b1d4014cd3eb4440c66e554cc..d5a3198206dad07eb5112024cb4be725b3d914a1 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: power.h
  *
  * Purpose: Handles 802.11 power management  functions
index 3a9d19a0b84284926ddab622fd8ae4ba2d85e15b..18f75dcc65d2129957cb958f7dd29d554425aae6 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: rf.c
  *
  * Purpose: rf function code
index c907a18047d2829e4b7d2832f2c2dca779013156..f77866a9c177ad9efc1468c179d0a3a6c778fd9e 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: rf.h
  *
  * Purpose:
index a44abcce6fb4504add5b871d7580304781dd988a..26ca3fa293010f58386eb81de1d4e1509aa952fb 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: rxtx.c
  *
  * Purpose: handle WMAC/802.3/802.11 rx & tx functions
index 1ba8647bea864916b6ccd548e1536418c07a1d10..44698f41a234cc09e32e0b5e8d1927545609bbf3 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: rxtx.h
  *
  * Purpose:
index 23eaef45855629e052a84725109627be0f6bf0da..273176386a51af01382330fa1463bc37e6c86d32 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: usbpipe.c
  *
  * Purpose: Handle USB control endpoint
index 9fc5ac0ef6c19408805042e26050188e0b11c24f..5d7708fcf5578ab0b089a6a01a133d042fd9eca0 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: usbpipe.h
  *
  * Purpose:
index b2fc17f1381b2543484491f3cfefea75f93fd486..3eb2f11a5de13676247c8daf4d2ac7407ecfe555 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: wcmd.c
  *
  * Purpose: Handles the management command interface functions
index 727ec14380c4d52928fbfbcf76342778556e3f09..4a96f4de980daab48d682906d90456ef966f764f 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
  * File: wcmd.h
  *
  * Purpose: Handles the management command interface functions
index 8cf886d32afb218f574a16a42f278cdd5db8b7ff..e98fc8e93011d5d3b2954f3e2aea1b7382be9e33 100644 (file)
@@ -201,7 +201,7 @@ static inline u16 get_cap_info(u8 *data)
 
        st = get_sub_type(data);
 
-       if ((st == BEACON) || (st == PROBE_RSP))
+       if (st == BEACON || st == PROBE_RSP)
                index += TIME_STAMP_LEN + BEACON_INTERVAL_LEN;
 
        cap_info  = data[index];
index d69248a8c7b5978b5665c78bcda0d04026a45df4..358354b3a2b49a31308a87ea33ef06cab07fce42 100644 (file)
@@ -202,7 +202,7 @@ struct host_if_msg {
 };
 
 struct join_bss_param {
-       BSSTYPE_T bss_type;
+       enum bss_types bss_type;
        u8 dtim_period;
        u16 beacon_period;
        u16 cap_info;
@@ -394,7 +394,7 @@ static void handle_set_operation_mode(struct wilc_vif *vif,
        ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
                                   wilc_get_vif_idx(vif));
 
-       if ((hif_op_mode->mode) == IDLE_MODE)
+       if (hif_op_mode->mode == IDLE_MODE)
                complete(&hif_driver_comp);
 
        if (ret)
@@ -760,8 +760,8 @@ static s32 handle_scan(struct wilc_vif *vif, struct scan_attr *scan_info)
        hif_drv->usr_scan_req.scan_result = scan_info->result;
        hif_drv->usr_scan_req.arg = scan_info->arg;
 
-       if ((hif_drv->hif_state >= HOST_IF_SCANNING) &&
-           (hif_drv->hif_state < HOST_IF_CONNECTED)) {
+       if (hif_drv->hif_state >= HOST_IF_SCANNING &&
+           hif_drv->hif_state < HOST_IF_CONNECTED) {
                netdev_err(vif->ndev, "Already scan\n");
                result = -EBUSY;
                goto ERRORHANDLER;
@@ -1025,7 +1025,7 @@ static s32 Handle_Connect(struct wilc_vif *vif,
        pu8CurrByte += MAX_SSID_LEN;
        *(pu8CurrByte++) = INFRASTRUCTURE;
 
-       if ((pstrHostIFconnectAttr->ch >= 1) && (pstrHostIFconnectAttr->ch <= 14)) {
+       if (pstrHostIFconnectAttr->ch >= 1 && pstrHostIFconnectAttr->ch <= 14) {
                *(pu8CurrByte++) = pstrHostIFconnectAttr->ch;
        } else {
                netdev_err(vif->ndev, "Channel out of range\n");
@@ -1258,8 +1258,8 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif,
 
        if (hif_drv->usr_scan_req.scan_result) {
                wilc_parse_network_info(pstrRcvdNetworkInfo->buffer, &pstrNetworkInfo);
-               if ((!pstrNetworkInfo) ||
-                   (!hif_drv->usr_scan_req.scan_result)) {
+               if (!pstrNetworkInfo ||
+                   !hif_drv->usr_scan_req.scan_result) {
                        netdev_err(vif->ndev, "driver is null\n");
                        result = -EINVAL;
                        goto done;
@@ -1340,8 +1340,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif,
                return -ENODEV;
        }
 
-       if ((hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) ||
-           (hif_drv->hif_state == HOST_IF_CONNECTED) ||
+       if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
+           hif_drv->hif_state == HOST_IF_CONNECTED ||
            hif_drv->usr_scan_req.scan_result) {
                if (!pstrRcvdGnrlAsyncInfo->buffer ||
                    !hif_drv->usr_conn_req.conn_result) {
@@ -1400,8 +1400,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif,
                                }
                        }
 
-                       if ((u8MacStatus == MAC_CONNECTED) &&
-                           (strConnectInfo.status != SUCCESSFUL_STATUSCODE))   {
+                       if (u8MacStatus == MAC_CONNECTED &&
+                           strConnectInfo.status != SUCCESSFUL_STATUSCODE)     {
                                netdev_err(vif->ndev, "Received MAC status is MAC_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE\n");
                                eth_zero_addr(wilc_connected_ssid);
                        } else if (u8MacStatus == MAC_DISCONNECTED)    {
@@ -1412,8 +1412,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif,
                        if (hif_drv->usr_conn_req.bssid) {
                                memcpy(strConnectInfo.bssid, hif_drv->usr_conn_req.bssid, 6);
 
-                               if ((u8MacStatus == MAC_CONNECTED) &&
-                                   (strConnectInfo.status == SUCCESSFUL_STATUSCODE))   {
+                               if (u8MacStatus == MAC_CONNECTED &&
+                                   strConnectInfo.status == SUCCESSFUL_STATUSCODE)     {
                                        memcpy(hif_drv->assoc_bssid,
                                               hif_drv->usr_conn_req.bssid, ETH_ALEN);
                                }
@@ -1434,8 +1434,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif,
                                                          NULL,
                                                          hif_drv->usr_conn_req.arg);
 
-                       if ((u8MacStatus == MAC_CONNECTED) &&
-                           (strConnectInfo.status == SUCCESSFUL_STATUSCODE))   {
+                       if (u8MacStatus == MAC_CONNECTED &&
+                           strConnectInfo.status == SUCCESSFUL_STATUSCODE)     {
                                wilc_set_power_mgmt(vif, 0, 0);
 
                                hif_drv->hif_state = HOST_IF_CONNECTED;
@@ -1864,8 +1864,8 @@ void wilc_resolve_disconnect_aberration(struct wilc_vif *vif)
 {
        if (!vif->hif_drv)
                return;
-       if ((vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) ||
-           (vif->hif_drv->hif_state == HOST_IF_CONNECTING))
+       if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
+           vif->hif_drv->hif_state == HOST_IF_CONNECTING)
                wilc_disconnect(vif, 1);
 }
 
@@ -2414,7 +2414,7 @@ static void Handle_SetMulticastFilter(struct wilc_vif *vif,
 
        wid.id = (u16)WID_SETUP_MULTICAST_FILTER;
        wid.type = WID_BIN;
-       wid.size = sizeof(struct set_multicast) + ((strHostIfSetMulti->cnt) * ETH_ALEN);
+       wid.size = sizeof(struct set_multicast) + (strHostIfSetMulti->cnt * ETH_ALEN);
        wid.val = kmalloc(wid.size, GFP_KERNEL);
        if (!wid.val)
                goto ERRORHANDLER;
@@ -3730,8 +3730,8 @@ int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param)
        memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param));
        if (add_sta_info->rates_len > 0) {
                add_sta_info->rates = kmemdup(sta_param->rates,
-                                     add_sta_info->rates_len,
-                                     GFP_KERNEL);
+                                             add_sta_info->rates_len,
+                                             GFP_KERNEL);
                if (!add_sta_info->rates)
                        return -ENOMEM;
        }
index 119f3459b5bbf3f49c41179053d87fa36f1780d4..d9725efe05371142d15a37daa75f6150efe61a63 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include "wilc_wfi_cfgoperations.h"
 #include "wilc_wlan_if.h"
 #include "wilc_wlan.h"
@@ -694,7 +695,7 @@ static int wlan_initialize_threads(struct net_device *dev)
        wilc = vif->wilc;
 
        wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev,
-                                    "K_TXQ_TASK");
+                                      "K_TXQ_TASK");
        if (IS_ERR(wilc->txq_thread)) {
                netdev_err(dev, "couldn't create TXQ thread\n");
                wilc->close = 0;
@@ -910,13 +911,13 @@ static void wilc_set_multicast_list(struct net_device *dev)
        if (dev->flags & IFF_PROMISC)
                return;
 
-       if ((dev->flags & IFF_ALLMULTI) ||
-           (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) {
+       if (dev->flags & IFF_ALLMULTI ||
+           dev->mc.count > WILC_MULTICAST_TABLE_SIZE) {
                wilc_setup_multicast_filter(vif, false, 0);
                return;
        }
 
-       if ((dev->mc.count) == 0) {
+       if (dev->mc.count == 0) {
                wilc_setup_multicast_filter(vif, true, 0);
                return;
        }
@@ -1029,7 +1030,7 @@ static int wilc_mac_close(struct net_device *ndev)
        if (!hif_drv)
                return 0;
 
-       if ((wl->open_ifcs) > 0)
+       if (wl->open_ifcs > 0)
                wl->open_ifcs--;
        else
                return 0;
index ce54864569c7dbd38c00a659b6c9b65abb7e1099..0deb61a21b27f1e814e653fe2f4afa25140de54b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * NewportMedia WiFi chipset driver test tools - wilc-debug
  * Copyright (c) 2012 NewportMedia Inc.
index 0189e3edbbbe631e730ad9a6ee2dc5c25ac79946..bb65b374c1cebd2ad2d8e162f10417990666f8f0 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) Atmel Corporation.  All rights reserved.
  *
@@ -374,7 +375,7 @@ static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data)
 
        data = cpu_to_le32(data);
 
-       if ((addr >= 0xf0) && (addr <= 0xff)) {
+       if (addr >= 0xf0 && addr <= 0xff) {
                struct sdio_cmd52 cmd;
 
                cmd.read_write = 1;
@@ -514,7 +515,7 @@ static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data)
        struct sdio_func *func = dev_to_sdio_func(wilc->dev);
        int ret;
 
-       if ((addr >= 0xf0) && (addr <= 0xff)) {
+       if (addr >= 0xf0 && addr <= 0xff) {
                struct sdio_cmd52 cmd;
 
                cmd.read_write = 0;
index 5ef84410e0f20e6b1e8ceceb724d208d922a5966..8f71a60227219badcecd6faa227c2d0e956880e7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) Atmel Corporation.  All rights reserved.
  *
@@ -389,11 +390,11 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz,
 #define NUM_DATA_BYTES (4)
 #define NUM_CRC_BYTES (2)
 #define NUM_DUMMY_BYTES (3)
-       if ((cmd == CMD_RESET) ||
-           (cmd == CMD_TERMINATE) ||
-           (cmd == CMD_REPEAT)) {
+       if (cmd == CMD_RESET ||
+           cmd == CMD_TERMINATE ||
+           cmd == CMD_REPEAT) {
                len2 = len + (NUM_SKIP_BYTES + NUM_RSP_BYTES + NUM_DUMMY_BYTES);
-       } else if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) {
+       } else if (cmd == CMD_INTERNAL_READ || cmd == CMD_SINGLE_READ) {
                if (!g_spi.crc_off) {
                        len2 = len + (NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES
                                      + NUM_CRC_BYTES + NUM_DUMMY_BYTES);
@@ -424,9 +425,9 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz,
        /**
         * Command/Control response
         **/
-       if ((cmd == CMD_RESET) ||
-           (cmd == CMD_TERMINATE) ||
-           (cmd == CMD_REPEAT)) {
+       if (cmd == CMD_RESET ||
+           cmd == CMD_TERMINATE ||
+           cmd == CMD_REPEAT) {
                rix++;         /* skip 1 byte */
        }
 
@@ -452,8 +453,8 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz,
                return N_FAIL;
        }
 
-       if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ) ||
-           (cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) {
+       if (cmd == CMD_INTERNAL_READ || cmd == CMD_SINGLE_READ ||
+           cmd == CMD_DMA_READ || cmd == CMD_DMA_EXT_READ) {
                int retry;
                /* u16 crc1, crc2; */
                u8 crc[2];
@@ -479,7 +480,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz,
                        return N_RESET;
                }
 
-               if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) {
+               if (cmd == CMD_INTERNAL_READ || cmd == CMD_SINGLE_READ) {
                        /**
                         * Read bytes
                         **/
index 028da1dc1b818380bd36c71b4cf403cce5523b45..621810d704501d51ca1546d399bfcda3854981cb 100644 (file)
@@ -379,7 +379,7 @@ static void CfgScanResult(enum scan_event scan_event,
        struct cfg80211_bss *bss = NULL;
 
        priv = user_void;
-       if (priv->bCfgScanning) {
+       if (priv->cfg_scanning) {
                if (scan_event == SCAN_EVENT_NETWORK_FOUND) {
                        wiphy = priv->dev->ieee80211_ptr->wiphy;
 
@@ -399,8 +399,8 @@ static void CfgScanResult(enum scan_event scan_event,
                                        return;
 
                                if (network_info->new_network) {
-                                       if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) {
-                                               priv->u32RcvdChCount++;
+                                       if (priv->rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) {
+                                               priv->rcvd_ch_cnt++;
 
                                                add_network_to_shadow(network_info, priv, join_params);
 
@@ -422,7 +422,7 @@ static void CfgScanResult(enum scan_event scan_event,
                                } else {
                                        u32 i;
 
-                                       for (i = 0; i < priv->u32RcvdChCount; i++) {
+                                       for (i = 0; i < priv->rcvd_ch_cnt; i++) {
                                                if (memcmp(last_scanned_shadow[i].bssid, network_info->bssid, 6) == 0) {
                                                        last_scanned_shadow[i].rssi = network_info->rssi;
                                                        last_scanned_shadow[i].time_scan = jiffies;
@@ -436,21 +436,21 @@ static void CfgScanResult(enum scan_event scan_event,
 
                        mutex_lock(&priv->scan_req_lock);
 
-                       if (priv->pstrScanReq) {
+                       if (priv->scan_req) {
                                struct cfg80211_scan_info info = {
                                        .aborted = false,
                                };
 
-                               cfg80211_scan_done(priv->pstrScanReq, &info);
-                               priv->u32RcvdChCount = 0;
-                               priv->bCfgScanning = false;
-                               priv->pstrScanReq = NULL;
+                               cfg80211_scan_done(priv->scan_req, &info);
+                               priv->rcvd_ch_cnt = 0;
+                               priv->cfg_scanning = false;
+                               priv->scan_req = NULL;
                        }
                        mutex_unlock(&priv->scan_req_lock);
                } else if (scan_event == SCAN_EVENT_ABORTED) {
                        mutex_lock(&priv->scan_req_lock);
 
-                       if (priv->pstrScanReq) {
+                       if (priv->scan_req) {
                                struct cfg80211_scan_info info = {
                                        .aborted = false,
                                };
@@ -458,9 +458,9 @@ static void CfgScanResult(enum scan_event scan_event,
                                update_scan_time();
                                refresh_scan(priv, false);
 
-                               cfg80211_scan_done(priv->pstrScanReq, &info);
-                               priv->bCfgScanning = false;
-                               priv->pstrScanReq = NULL;
+                               cfg80211_scan_done(priv->scan_req, &info);
+                               priv->cfg_scanning = false;
+                               priv->scan_req = NULL;
                        }
                        mutex_unlock(&priv->scan_req_lock);
                }
@@ -469,92 +469,92 @@ static void CfgScanResult(enum scan_event scan_event,
 
 int wilc_connecting;
 
-static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
-                            struct connect_info *pstrConnectInfo,
-                            u8 u8MacStatus,
-                            struct disconnect_info *pstrDisconnectNotifInfo,
-                            void *pUserVoid)
+static void cfg_connect_result(enum conn_event conn_disconn_evt,
+                              struct connect_info *conn_info,
+                              u8 mac_status,
+                              struct disconnect_info *disconn_info,
+                              void *priv_data)
 {
        struct wilc_priv *priv;
        struct net_device *dev;
-       struct host_if_drv *pstrWFIDrv;
-       u8 NullBssid[ETH_ALEN] = {0};
+       struct host_if_drv *wfi_drv;
+       u8 null_bssid[ETH_ALEN] = {0};
        struct wilc *wl;
        struct wilc_vif *vif;
 
        wilc_connecting = 0;
 
-       priv = pUserVoid;
+       priv = priv_data;
        dev = priv->dev;
        vif = netdev_priv(dev);
        wl = vif->wilc;
-       pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
+       wfi_drv = (struct host_if_drv *)priv->hif_drv;
 
-       if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) {
-               u16 u16ConnectStatus;
+       if (conn_disconn_evt == CONN_DISCONN_EVENT_CONN_RESP) {
+               u16 connect_status;
 
-               u16ConnectStatus = pstrConnectInfo->status;
+               connect_status = conn_info->status;
 
-               if ((u8MacStatus == MAC_DISCONNECTED) &&
-                   (pstrConnectInfo->status == SUCCESSFUL_STATUSCODE)) {
-                       u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
-                       wilc_wlan_set_bssid(priv->dev, NullBssid,
+               if (mac_status == MAC_DISCONNECTED &&
+                   conn_info->status == SUCCESSFUL_STATUSCODE) {
+                       connect_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                       wilc_wlan_set_bssid(priv->dev, null_bssid,
                                            STATION_MODE);
                        eth_zero_addr(wilc_connected_ssid);
 
-                       if (!pstrWFIDrv->p2p_connect)
+                       if (!wfi_drv->p2p_connect)
                                wlan_channel = INVALID_CHANNEL;
 
                        netdev_err(dev, "Unspecified failure\n");
                }
 
-               if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
-                       bool bNeedScanRefresh = false;
+               if (connect_status == WLAN_STATUS_SUCCESS) {
+                       bool scan_refresh = false;
                        u32 i;
 
-                       memcpy(priv->au8AssociatedBss, pstrConnectInfo->bssid, ETH_ALEN);
+                       memcpy(priv->associated_bss, conn_info->bssid, ETH_ALEN);
 
                        for (i = 0; i < last_scanned_cnt; i++) {
                                if (memcmp(last_scanned_shadow[i].bssid,
-                                          pstrConnectInfo->bssid,
+                                          conn_info->bssid,
                                           ETH_ALEN) == 0) {
                                        unsigned long now = jiffies;
 
                                        if (time_after(now,
                                                       last_scanned_shadow[i].time_scan_cached +
                                                       (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ))))
-                                               bNeedScanRefresh = true;
+                                               scan_refresh = true;
 
                                        break;
                                }
                        }
 
-                       if (bNeedScanRefresh)
+                       if (scan_refresh)
                                refresh_scan(priv, true);
                }
 
-               cfg80211_connect_result(dev, pstrConnectInfo->bssid,
-                                       pstrConnectInfo->req_ies, pstrConnectInfo->req_ies_len,
-                                       pstrConnectInfo->resp_ies, pstrConnectInfo->resp_ies_len,
-                                       u16ConnectStatus, GFP_KERNEL);
-       } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF)    {
+               cfg80211_connect_result(dev, conn_info->bssid,
+                                       conn_info->req_ies, conn_info->req_ies_len,
+                                       conn_info->resp_ies, conn_info->resp_ies_len,
+                                       connect_status, GFP_KERNEL);
+       } else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF)    {
                wilc_optaining_ip = false;
                p2p_local_random = 0x01;
                p2p_recv_random = 0x00;
                wilc_ie = false;
-               eth_zero_addr(priv->au8AssociatedBss);
-               wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
+               eth_zero_addr(priv->associated_bss);
+               wilc_wlan_set_bssid(priv->dev, null_bssid, STATION_MODE);
                eth_zero_addr(wilc_connected_ssid);
 
-               if (!pstrWFIDrv->p2p_connect)
+               if (!wfi_drv->p2p_connect)
                        wlan_channel = INVALID_CHANNEL;
-               if ((pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev))
-                       pstrDisconnectNotifInfo->reason = 3;
-               else if ((!pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev))
-                       pstrDisconnectNotifInfo->reason = 1;
+               if (wfi_drv->IFC_UP && dev == wl->vif[1]->ndev)
+                       disconn_info->reason = 3;
+               else if (!wfi_drv->IFC_UP && dev == wl->vif[1]->ndev)
+                       disconn_info->reason = 1;
 
-               cfg80211_disconnected(dev, pstrDisconnectNotifInfo->reason, pstrDisconnectNotifInfo->ie,
-                                     pstrDisconnectNotifInfo->ie_len, false,
+               cfg80211_disconnected(dev, disconn_info->reason, disconn_info->ie,
+                                     disconn_info->ie_len, false,
                                      GFP_KERNEL);
        }
 }
@@ -585,7 +585,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
        struct wilc_priv *priv;
        u32 i;
-       s32 s32Error = 0;
+       s32 ret = 0;
        u8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS];
        struct hidden_network strHiddenNetwork;
        struct wilc_vif *vif;
@@ -593,13 +593,13 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
        priv = wiphy_priv(wiphy);
        vif = netdev_priv(priv->dev);
 
-       priv->pstrScanReq = request;
+       priv->scan_req = request;
 
-       priv->u32RcvdChCount = 0;
+       priv->rcvd_ch_cnt = 0;
 
        reset_shadow_found();
 
-       priv->bCfgScanning = true;
+       priv->cfg_scanning = true;
        if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) {
                for (i = 0; i < request->n_channels; i++)
                        au8ScanChanList[i] = (u8)ieee80211_frequency_to_channel(request->channels[i]->center_freq);
@@ -622,56 +622,56 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
                                        strHiddenNetwork.n_ssids -= 1;
                                }
                        }
-                       s32Error = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
-                                            au8ScanChanList,
-                                            request->n_channels,
-                                            (const u8 *)request->ie,
-                                            request->ie_len, CfgScanResult,
-                                            (void *)priv, &strHiddenNetwork);
+                       ret = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
+                                       au8ScanChanList,
+                                       request->n_channels,
+                                       (const u8 *)request->ie,
+                                       request->ie_len, CfgScanResult,
+                                       (void *)priv, &strHiddenNetwork);
                } else {
-                       s32Error = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
-                                            au8ScanChanList,
-                                            request->n_channels,
-                                            (const u8 *)request->ie,
-                                            request->ie_len, CfgScanResult,
-                                            (void *)priv, NULL);
+                       ret = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
+                                       au8ScanChanList,
+                                       request->n_channels,
+                                       (const u8 *)request->ie,
+                                       request->ie_len, CfgScanResult,
+                                       (void *)priv, NULL);
                }
        } else {
                netdev_err(priv->dev, "Requested scanned channels over\n");
        }
 
-       if (s32Error != 0)
-               s32Error = -EBUSY;
+       if (ret != 0)
+               ret = -EBUSY;
 
-       return s32Error;
+       return ret;
 }
 
 static int connect(struct wiphy *wiphy, struct net_device *dev,
                   struct cfg80211_connect_params *sme)
 {
-       s32 s32Error = 0;
+       s32 ret = 0;
        u32 i;
        u32 sel_bssi_idx = UINT_MAX;
        u8 u8security = NO_ENCRYPT;
-       enum AUTHTYPE tenuAuth_type = ANY;
+       enum AUTHTYPE auth_type = ANY;
 
        struct wilc_priv *priv;
-       struct host_if_drv *pstrWFIDrv;
+       struct host_if_drv *wfi_drv;
        struct network_info *pstrNetworkInfo = NULL;
        struct wilc_vif *vif;
 
        wilc_connecting = 1;
        priv = wiphy_priv(wiphy);
        vif = netdev_priv(priv->dev);
-       pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
+       wfi_drv = (struct host_if_drv *)priv->hif_drv;
 
        if (!(strncmp(sme->ssid, "DIRECT-", 7)))
-               pstrWFIDrv->p2p_connect = 1;
+               wfi_drv->p2p_connect = 1;
        else
-               pstrWFIDrv->p2p_connect = 0;
+               wfi_drv->p2p_connect = 0;
 
        for (i = 0; i < last_scanned_cnt; i++) {
-               if ((sme->ssid_len == last_scanned_shadow[i].ssid_len) &&
+               if (sme->ssid_len == last_scanned_shadow[i].ssid_len &&
                    memcmp(last_scanned_shadow[i].ssid,
                           sme->ssid,
                           sme->ssid_len) == 0) {
@@ -694,9 +694,9 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
        if (sel_bssi_idx < last_scanned_cnt) {
                pstrNetworkInfo = &last_scanned_shadow[sel_bssi_idx];
        } else {
-               s32Error = -ENOENT;
+               ret = -ENOENT;
                wilc_connecting = 0;
-               return s32Error;
+               return ret;
        }
 
        memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
@@ -744,10 +744,10 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
                        else
                                u8security = ENCRYPT_ENABLED | WPA | AES;
                } else {
-                       s32Error = -ENOTSUPP;
+                       ret = -ENOTSUPP;
                        netdev_err(dev, "Not supported cipher\n");
                        wilc_connecting = 0;
-                       return s32Error;
+                       return ret;
                }
        }
 
@@ -763,11 +763,11 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
 
        switch (sme->auth_type) {
        case NL80211_AUTHTYPE_OPEN_SYSTEM:
-               tenuAuth_type = OPEN_SYSTEM;
+               auth_type = OPEN_SYSTEM;
                break;
 
        case NL80211_AUTHTYPE_SHARED_KEY:
-               tenuAuth_type = SHARED_KEY;
+               auth_type = SHARED_KEY;
                break;
 
        default:
@@ -777,7 +777,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
        if (sme->crypto.n_akm_suites) {
                switch (sme->crypto.akm_suites[0]) {
                case WLAN_AKM_SUITE_8021X:
-                       tenuAuth_type = IEEE8021;
+                       auth_type = IEEE8021;
                        break;
 
                default:
@@ -787,35 +787,35 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
 
        curr_channel = pstrNetworkInfo->ch;
 
-       if (!pstrWFIDrv->p2p_connect)
+       if (!wfi_drv->p2p_connect)
                wlan_channel = pstrNetworkInfo->ch;
 
        wilc_wlan_set_bssid(dev, pstrNetworkInfo->bssid, STATION_MODE);
 
-       s32Error = wilc_set_join_req(vif, pstrNetworkInfo->bssid, sme->ssid,
-                                    sme->ssid_len, sme->ie, sme->ie_len,
-                                    CfgConnectResult, (void *)priv,
-                                    u8security, tenuAuth_type,
-                                    pstrNetworkInfo->ch,
-                                    pstrNetworkInfo->join_params);
-       if (s32Error != 0) {
+       ret = wilc_set_join_req(vif, pstrNetworkInfo->bssid, sme->ssid,
+                               sme->ssid_len, sme->ie, sme->ie_len,
+                               cfg_connect_result, (void *)priv,
+                               u8security, auth_type,
+                               pstrNetworkInfo->ch,
+                               pstrNetworkInfo->join_params);
+       if (ret != 0) {
                netdev_err(dev, "wilc_set_join_req(): Error\n");
-               s32Error = -ENOENT;
+               ret = -ENOENT;
                wilc_connecting = 0;
-               return s32Error;
+               return ret;
        }
 
-       return s32Error;
+       return ret;
 }
 
 static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
 {
-       s32 s32Error = 0;
+       s32 ret = 0;
        struct wilc_priv *priv;
-       struct host_if_drv *pstrWFIDrv;
+       struct host_if_drv *wfi_drv;
        struct wilc_vif *vif;
        struct wilc *wilc;
-       u8 NullBssid[ETH_ALEN] = {0};
+       u8 null_bssid[ETH_ALEN] = {0};
 
        wilc_connecting = 0;
        priv = wiphy_priv(wiphy);
@@ -831,23 +831,23 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_co
                return 0;
        }
 
-       pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
-       if (!pstrWFIDrv->p2p_connect)
+       wfi_drv = (struct host_if_drv *)priv->hif_drv;
+       if (!wfi_drv->p2p_connect)
                wlan_channel = INVALID_CHANNEL;
-       wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
+       wilc_wlan_set_bssid(priv->dev, null_bssid, STATION_MODE);
 
        p2p_local_random = 0x01;
        p2p_recv_random = 0x00;
        wilc_ie = false;
-       pstrWFIDrv->p2p_timeout = 0;
+       wfi_drv->p2p_timeout = 0;
 
-       s32Error = wilc_disconnect(vif, reason_code);
-       if (s32Error != 0) {
+       ret = wilc_disconnect(vif, reason_code);
+       if (ret != 0) {
                netdev_err(priv->dev, "Error in disconnecting\n");
-               s32Error = -EINVAL;
+               ret = -EINVAL;
        }
 
-       return s32Error;
+       return ret;
 }
 
 static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
@@ -855,14 +855,14 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                   const u8 *mac_addr, struct key_params *params)
 
 {
-       s32 s32Error = 0, KeyLen = params->key_len;
+       s32 ret = 0, keylen = params->key_len;
        struct wilc_priv *priv;
-       const u8 *pu8RxMic = NULL;
-       const u8 *pu8TxMic = NULL;
+       const u8 *rx_mic = NULL;
+       const u8 *tx_mic = NULL;
        u8 u8mode = NO_ENCRYPT;
        u8 u8gmode = NO_ENCRYPT;
        u8 u8pmode = NO_ENCRYPT;
-       enum AUTHTYPE tenuAuth_type = ANY;
+       enum AUTHTYPE auth_type = ANY;
        struct wilc *wl;
        struct wilc_vif *vif;
 
@@ -877,7 +877,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                        priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
                        memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
 
-                       tenuAuth_type = OPEN_SYSTEM;
+                       auth_type = OPEN_SYSTEM;
 
                        if (params->cipher == WLAN_CIPHER_SUITE_WEP40)
                                u8mode = ENCRYPT_ENABLED | WEP;
@@ -886,7 +886,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 
                        wilc_add_wep_key_bss_ap(vif, params->key,
                                                params->key_len, key_index,
-                                               u8mode, tenuAuth_type);
+                                               u8mode, auth_type);
                        break;
                }
                if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
@@ -922,9 +922,9 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                                priv->wilc_groupkey = u8gmode;
 
                                if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
-                                       pu8TxMic = params->key + 24;
-                                       pu8RxMic = params->key + 16;
-                                       KeyLen = params->key_len - 16;
+                                       tx_mic = params->key + 24;
+                                       rx_mic = params->key + 16;
+                                       keylen = params->key_len - 16;
                                }
                                kfree(priv->wilc_gtk[key_index]->key);
 
@@ -932,7 +932,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                                memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
                                kfree(priv->wilc_gtk[key_index]->seq);
 
-                               if ((params->seq_len) > 0) {
+                               if (params->seq_len > 0) {
                                        priv->wilc_gtk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
                                        memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
                                }
@@ -941,10 +941,10 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                                priv->wilc_gtk[key_index]->key_len = params->key_len;
                                priv->wilc_gtk[key_index]->seq_len = params->seq_len;
 
-                               wilc_add_rx_gtk(vif, params->key, KeyLen,
+                               wilc_add_rx_gtk(vif, params->key, keylen,
                                                key_index, params->seq_len,
-                                               params->seq, pu8RxMic,
-                                               pu8TxMic, AP_MODE, u8gmode);
+                                               params->seq, rx_mic,
+                                               tx_mic, AP_MODE, u8gmode);
 
                        } else {
                                if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
@@ -953,9 +953,9 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                                        u8pmode = priv->wilc_groupkey | AES;
 
                                if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
-                                       pu8TxMic = params->key + 24;
-                                       pu8RxMic = params->key + 16;
-                                       KeyLen = params->key_len - 16;
+                                       tx_mic = params->key + 24;
+                                       rx_mic = params->key + 16;
+                                       keylen = params->key_len - 16;
                                }
 
                                kfree(priv->wilc_ptk[key_index]->key);
@@ -964,20 +964,20 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 
                                kfree(priv->wilc_ptk[key_index]->seq);
 
-                               if ((params->seq_len) > 0)
+                               if (params->seq_len > 0)
                                        priv->wilc_ptk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
 
                                memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
 
-                               if ((params->seq_len) > 0)
+                               if (params->seq_len > 0)
                                        memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
 
                                priv->wilc_ptk[key_index]->cipher = params->cipher;
                                priv->wilc_ptk[key_index]->key_len = params->key_len;
                                priv->wilc_ptk[key_index]->seq_len = params->seq_len;
 
-                               wilc_add_ptk(vif, params->key, KeyLen,
-                                            mac_addr, pu8RxMic, pu8TxMic,
+                               wilc_add_ptk(vif, params->key, keylen,
+                                            mac_addr, rx_mic, tx_mic,
                                             AP_MODE, u8pmode, key_index);
                        }
                        break;
@@ -987,9 +987,9 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                        u8mode = 0;
                        if (!pairwise) {
                                if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
-                                       pu8RxMic = params->key + 24;
-                                       pu8TxMic = params->key + 16;
-                                       KeyLen = params->key_len - 16;
+                                       rx_mic = params->key + 24;
+                                       tx_mic = params->key + 16;
+                                       keylen = params->key_len - 16;
                                }
 
                                if (!g_gtk_keys_saved && netdev == wl->vif[0]->ndev) {
@@ -1013,16 +1013,16 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                                        g_gtk_keys_saved = true;
                                }
 
-                               wilc_add_rx_gtk(vif, params->key, KeyLen,
+                               wilc_add_rx_gtk(vif, params->key, keylen,
                                                key_index, params->seq_len,
-                                               params->seq, pu8RxMic,
-                                               pu8TxMic, STATION_MODE,
+                                               params->seq, rx_mic,
+                                               tx_mic, STATION_MODE,
                                                u8mode);
                        } else {
                                if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
-                                       pu8RxMic = params->key + 24;
-                                       pu8TxMic = params->key + 16;
-                                       KeyLen = params->key_len - 16;
+                                       rx_mic = params->key + 24;
+                                       tx_mic = params->key + 16;
+                                       keylen = params->key_len - 16;
                                }
 
                                if (!g_ptk_keys_saved && netdev == wl->vif[0]->ndev) {
@@ -1046,8 +1046,8 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                                        g_ptk_keys_saved = true;
                                }
 
-                               wilc_add_ptk(vif, params->key, KeyLen,
-                                            mac_addr, pu8RxMic, pu8TxMic,
+                               wilc_add_ptk(vif, params->key, keylen,
+                                            mac_addr, rx_mic, tx_mic,
                                             STATION_MODE, u8mode, key_index);
                        }
                }
@@ -1055,10 +1055,10 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 
        default:
                netdev_err(netdev, "Not supported cipher\n");
-               s32Error = -ENOTSUPP;
+               ret = -ENOTSUPP;
        }
 
-       return s32Error;
+       return ret;
 }
 
 static int del_key(struct wiphy *wiphy, struct net_device *netdev,
@@ -1082,7 +1082,7 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
                kfree(g_key_wep_params.key);
                g_key_wep_params.key = NULL;
 
-               if ((priv->wilc_gtk[key_index]) != NULL) {
+               if (priv->wilc_gtk[key_index] != NULL) {
                        kfree(priv->wilc_gtk[key_index]->key);
                        priv->wilc_gtk[key_index]->key = NULL;
                        kfree(priv->wilc_gtk[key_index]->seq);
@@ -1092,7 +1092,7 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
                        priv->wilc_gtk[key_index] = NULL;
                }
 
-               if ((priv->wilc_ptk[key_index]) != NULL) {
+               if (priv->wilc_ptk[key_index] != NULL) {
                        kfree(priv->wilc_ptk[key_index]->key);
                        priv->wilc_ptk[key_index]->key = NULL;
                        kfree(priv->wilc_ptk[key_index]->seq);
@@ -1182,7 +1182,7 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev,
 
        if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
                for (i = 0; i < NUM_STA_ASSOCIATED; i++) {
-                       if (!(memcmp(mac, priv->assoc_stainfo.au8Sta_AssociatedBss[i], ETH_ALEN))) {
+                       if (!(memcmp(mac, priv->assoc_stainfo.sta_associated_bss[i], ETH_ALEN))) {
                                associatedsta = i;
                                break;
                        }
@@ -1200,9 +1200,9 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev,
        }
 
        if (vif->iftype == STATION_MODE) {
-               struct rf_info strStatistics;
+               struct rf_info stats;
 
-               wilc_get_statistics(vif, &strStatistics);
+               wilc_get_statistics(vif, &stats);
 
                sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
                                                BIT(NL80211_STA_INFO_RX_PACKETS) |
@@ -1210,16 +1210,16 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev,
                                                BIT(NL80211_STA_INFO_TX_FAILED) |
                                                BIT(NL80211_STA_INFO_TX_BITRATE);
 
-               sinfo->signal = strStatistics.rssi;
-               sinfo->rx_packets = strStatistics.rx_cnt;
-               sinfo->tx_packets = strStatistics.tx_cnt + strStatistics.tx_fail_cnt;
-               sinfo->tx_failed = strStatistics.tx_fail_cnt;
-               sinfo->txrate.legacy = strStatistics.link_speed * 10;
+               sinfo->signal = stats.rssi;
+               sinfo->rx_packets = stats.rx_cnt;
+               sinfo->tx_packets = stats.tx_cnt + stats.tx_fail_cnt;
+               sinfo->tx_failed = stats.tx_fail_cnt;
+               sinfo->txrate.legacy = stats.link_speed * 10;
 
-               if ((strStatistics.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH) &&
-                   (strStatistics.link_speed != DEFAULT_LINK_SPEED))
+               if (stats.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
+                   stats.link_speed != DEFAULT_LINK_SPEED)
                        wilc_enable_tcp_ack_filter(true);
-               else if (strStatistics.link_speed != DEFAULT_LINK_SPEED)
+               else if (stats.link_speed != DEFAULT_LINK_SPEED)
                        wilc_enable_tcp_ack_filter(false);
        }
        return 0;
@@ -1233,46 +1233,46 @@ static int change_bss(struct wiphy *wiphy, struct net_device *dev,
 
 static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
 {
-       s32 s32Error = 0;
-       struct cfg_param_attr pstrCfgParamVal;
+       s32 ret = 0;
+       struct cfg_param_attr cfg_param_val;
        struct wilc_priv *priv;
        struct wilc_vif *vif;
 
        priv = wiphy_priv(wiphy);
        vif = netdev_priv(priv->dev);
 
-       pstrCfgParamVal.flag = 0;
+       cfg_param_val.flag = 0;
 
        if (changed & WIPHY_PARAM_RETRY_SHORT) {
-               pstrCfgParamVal.flag  |= RETRY_SHORT;
-               pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short;
+               cfg_param_val.flag  |= RETRY_SHORT;
+               cfg_param_val.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short;
        }
        if (changed & WIPHY_PARAM_RETRY_LONG) {
-               pstrCfgParamVal.flag |= RETRY_LONG;
-               pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long;
+               cfg_param_val.flag |= RETRY_LONG;
+               cfg_param_val.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long;
        }
        if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
-               pstrCfgParamVal.flag |= FRAG_THRESHOLD;
-               pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold;
+               cfg_param_val.flag |= FRAG_THRESHOLD;
+               cfg_param_val.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold;
        }
 
        if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
-               pstrCfgParamVal.flag |= RTS_THRESHOLD;
-               pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold;
+               cfg_param_val.flag |= RTS_THRESHOLD;
+               cfg_param_val.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold;
        }
 
-       s32Error = wilc_hif_set_cfg(vif, &pstrCfgParamVal);
-       if (s32Error)
+       ret = wilc_hif_set_cfg(vif, &cfg_param_val);
+       if (ret)
                netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n");
 
-       return s32Error;
+       return ret;
 }
 
 static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
                     struct cfg80211_pmksa *pmksa)
 {
        u32 i;
-       s32 s32Error = 0;
+       s32 ret = 0;
        u8 flag = 0;
        struct wilc_vif *vif;
        struct wilc_priv *priv = wiphy_priv(wiphy);
@@ -1295,20 +1295,20 @@ static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
                        priv->pmkid_list.numpmkid++;
        } else {
                netdev_err(netdev, "Invalid PMKID index\n");
-               s32Error = -EINVAL;
+               ret = -EINVAL;
        }
 
-       if (!s32Error)
-               s32Error = wilc_set_pmkid_info(vif, &priv->pmkid_list);
+       if (!ret)
+               ret = wilc_set_pmkid_info(vif, &priv->pmkid_list);
 
-       return s32Error;
+       return ret;
 }
 
 static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
                     struct cfg80211_pmksa *pmksa)
 {
        u32 i;
-       s32 s32Error = 0;
+       s32 ret = 0;
 
        struct wilc_priv *priv = wiphy_priv(wiphy);
 
@@ -1331,10 +1331,10 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
                }
                priv->pmkid_list.numpmkid--;
        } else {
-               s32Error = -EINVAL;
+               ret = -EINVAL;
        }
 
-       return s32Error;
+       return ret;
 }
 
 static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
@@ -1346,7 +1346,7 @@ static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
        return 0;
 }
 
-static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len)
+static void wilc_wfi_cfg_parse_rx_action(u8 *buf, u32 len)
 {
        u32 index = 0;
        u32 i = 0, j = 0;
@@ -1382,7 +1382,7 @@ static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len)
        }
 }
 
-static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftype)
+static void wilc_wfi_cfg_parse_tx_action(u8 *buf, u32 len, bool oper_ch, u8 iftype)
 {
        u32 index = 0;
        u32 i = 0, j = 0;
@@ -1403,7 +1403,7 @@ static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftyp
                        op_channel_attr_index = index;
                index += buf[index + 1] + 3;
        }
-       if (wlan_channel != INVALID_CHANNEL && bOperChan) {
+       if (wlan_channel != INVALID_CHANNEL && oper_ch) {
                if (channel_list_attr_index) {
                        for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
                                if (buf[i] == 0x51) {
@@ -1425,12 +1425,12 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
 {
        struct wilc_priv *priv;
        u32 header, pkt_offset;
-       struct host_if_drv *pstrWFIDrv;
+       struct host_if_drv *wfi_drv;
        u32 i = 0;
        s32 s32Freq;
 
        priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
-       pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
+       wfi_drv = (struct host_if_drv *)priv->hif_drv;
 
        memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
 
@@ -1438,20 +1438,20 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
 
        if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
                if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) {
-                       cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
+                       cfg80211_mgmt_tx_status(priv->wdev, priv->tx_cookie, buff, size, true, GFP_KERNEL);
                        return;
                } else {
                        if (pkt_offset & IS_MGMT_STATUS_SUCCES)
-                               cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
+                               cfg80211_mgmt_tx_status(priv->wdev, priv->tx_cookie, buff, size, true, GFP_KERNEL);
                        else
-                               cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL);
+                               cfg80211_mgmt_tx_status(priv->wdev, priv->tx_cookie, buff, size, false, GFP_KERNEL);
                        return;
                }
        } else {
                s32Freq = ieee80211_channel_to_frequency(curr_channel, NL80211_BAND_2GHZ);
 
                if (ieee80211_is_action(buff[FRAME_TYPE_ID])) {
-                       if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) {
+                       if (priv->cfg_scanning && time_after_eq(jiffies, (unsigned long)wfi_drv->p2p_timeout)) {
                                netdev_dbg(dev, "Receiving action wrong ch\n");
                                return;
                        }
@@ -1481,7 +1481,7 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
                                                             buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
                                                                for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
                                                                        if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buff[i + 2], 4))) {
-                                                                               WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6));
+                                                                               wilc_wfi_cfg_parse_rx_action(&buff[i + 6], size - (i + 6));
                                                                                break;
                                                                        }
                                                                }
@@ -1508,7 +1508,7 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
        }
 }
 
-static void WILC_WFI_mgmt_tx_complete(void *priv, int status)
+static void wilc_wfi_mgmt_tx_complete(void *priv, int status)
 {
        struct p2p_mgmt_data *pv_data = priv;
 
@@ -1516,33 +1516,33 @@ static void WILC_WFI_mgmt_tx_complete(void *priv, int status)
        kfree(pv_data);
 }
 
-static void WILC_WFI_RemainOnChannelReady(void *pUserVoid)
+static void wilc_wfi_remain_on_channel_ready(void *priv_data)
 {
        struct wilc_priv *priv;
 
-       priv = pUserVoid;
+       priv = priv_data;
 
-       priv->bInP2PlistenState = true;
+       priv->p2p_listen_state = true;
 
        cfg80211_ready_on_channel(priv->wdev,
-                                 priv->strRemainOnChanParams.u64ListenCookie,
-                                 priv->strRemainOnChanParams.pstrListenChan,
-                                 priv->strRemainOnChanParams.u32ListenDuration,
+                                 priv->remain_on_ch_params.listen_cookie,
+                                 priv->remain_on_ch_params.listen_ch,
+                                 priv->remain_on_ch_params.listen_duration,
                                  GFP_KERNEL);
 }
 
-static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID)
+static void wilc_wfi_remain_on_channel_expired(void *data, u32 session_id)
 {
        struct wilc_priv *priv;
 
-       priv = pUserVoid;
+       priv = data;
 
-       if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
-               priv->bInP2PlistenState = false;
+       if (session_id == priv->remain_on_ch_params.listen_session_id) {
+               priv->p2p_listen_state = false;
 
                cfg80211_remain_on_channel_expired(priv->wdev,
-                                                  priv->strRemainOnChanParams.u64ListenCookie,
-                                                  priv->strRemainOnChanParams.pstrListenChan,
+                                                  priv->remain_on_ch_params.listen_cookie,
+                                                  priv->remain_on_ch_params.listen_ch,
                                                   GFP_KERNEL);
        }
 }
@@ -1552,7 +1552,7 @@ static int remain_on_channel(struct wiphy *wiphy,
                             struct ieee80211_channel *chan,
                             unsigned int duration, u64 *cookie)
 {
-       s32 s32Error = 0;
+       s32 ret = 0;
        struct wilc_priv *priv;
        struct wilc_vif *vif;
 
@@ -1561,21 +1561,21 @@ static int remain_on_channel(struct wiphy *wiphy,
 
        if (wdev->iftype == NL80211_IFTYPE_AP) {
                netdev_dbg(vif->ndev, "Required while in AP mode\n");
-               return s32Error;
+               return ret;
        }
 
        curr_channel = chan->hw_value;
 
-       priv->strRemainOnChanParams.pstrListenChan = chan;
-       priv->strRemainOnChanParams.u64ListenCookie = *cookie;
-       priv->strRemainOnChanParams.u32ListenDuration = duration;
-       priv->strRemainOnChanParams.u32ListenSessionID++;
+       priv->remain_on_ch_params.listen_ch = chan;
+       priv->remain_on_ch_params.listen_cookie = *cookie;
+       priv->remain_on_ch_params.listen_duration = duration;
+       priv->remain_on_ch_params.listen_session_id++;
 
        return wilc_remain_on_channel(vif,
-                               priv->strRemainOnChanParams.u32ListenSessionID,
+                               priv->remain_on_ch_params.listen_session_id,
                                duration, chan->hw_value,
-                               WILC_WFI_RemainOnChannelExpired,
-                               WILC_WFI_RemainOnChannelReady, (void *)priv);
+                               wilc_wfi_remain_on_channel_expired,
+                               wilc_wfi_remain_on_channel_ready, (void *)priv);
 }
 
 static int cancel_remain_on_channel(struct wiphy *wiphy,
@@ -1589,7 +1589,7 @@ static int cancel_remain_on_channel(struct wiphy *wiphy,
        vif = netdev_priv(priv->dev);
 
        return wilc_listen_state_expired(vif,
-                       priv->strRemainOnChanParams.u32ListenSessionID);
+                       priv->remain_on_ch_params.listen_session_id);
 }
 
 static int mgmt_tx(struct wiphy *wiphy,
@@ -1604,17 +1604,17 @@ static int mgmt_tx(struct wiphy *wiphy,
        const struct ieee80211_mgmt *mgmt;
        struct p2p_mgmt_data *mgmt_tx;
        struct wilc_priv *priv;
-       struct host_if_drv *pstrWFIDrv;
+       struct host_if_drv *wfi_drv;
        u32 i;
        struct wilc_vif *vif;
        u32 buf_len = len + sizeof(p2p_vendor_spec) + sizeof(p2p_local_random);
 
        vif = netdev_priv(wdev->netdev);
        priv = wiphy_priv(wiphy);
-       pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
+       wfi_drv = (struct host_if_drv *)priv->hif_drv;
 
        *cookie = (unsigned long)buf;
-       priv->u64tx_cookie = *cookie;
+       priv->tx_cookie = *cookie;
        mgmt = (const struct ieee80211_mgmt *)buf;
 
        if (ieee80211_is_mgmt(mgmt->frame_control)) {
@@ -1665,9 +1665,9 @@ static int mgmt_tx(struct wiphy *wiphy,
                                                                for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
                                                                        if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buf[i + 2], 4))) {
                                                                                if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
-                                                                                       WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, vif->iftype);
+                                                                                       wilc_wfi_cfg_parse_tx_action(&mgmt_tx->buff[i + 6], len - (i + 6), true, vif->iftype);
                                                                                else
-                                                                                       WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), false, vif->iftype);
+                                                                                       wilc_wfi_cfg_parse_tx_action(&mgmt_tx->buff[i + 6], len - (i + 6), false, vif->iftype);
                                                                                break;
                                                                        }
                                                                }
@@ -1695,12 +1695,12 @@ static int mgmt_tx(struct wiphy *wiphy,
                                }
                        }
 
-                       pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));
+                       wfi_drv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));
                }
 
                wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,
                                           mgmt_tx->buff, mgmt_tx->size,
-                                          WILC_WFI_mgmt_tx_complete);
+                                          wilc_wfi_mgmt_tx_complete);
        }
        return 0;
 }
@@ -1710,16 +1710,16 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
                               u64 cookie)
 {
        struct wilc_priv *priv;
-       struct host_if_drv *pstrWFIDrv;
+       struct host_if_drv *wfi_drv;
 
        priv = wiphy_priv(wiphy);
-       pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
-       pstrWFIDrv->p2p_timeout = jiffies;
+       wfi_drv = (struct host_if_drv *)priv->hif_drv;
+       wfi_drv->p2p_timeout = jiffies;
 
-       if (!priv->bInP2PlistenState) {
+       if (!priv->p2p_listen_state) {
                cfg80211_remain_on_channel_expired(priv->wdev,
-                                                  priv->strRemainOnChanParams.u64ListenCookie,
-                                                  priv->strRemainOnChanParams.pstrListenChan,
+                                                  priv->remain_on_ch_params.listen_cookie,
+                                                  priv->remain_on_ch_params.listen_ch,
                                                   GFP_KERNEL);
        }
 
@@ -1788,7 +1788,7 @@ static int dump_station(struct wiphy *wiphy, struct net_device *dev,
 
        wilc_get_rssi(vif, &sinfo->signal);
 
-       memcpy(mac, priv->au8AssociatedBss, ETH_ALEN);
+       memcpy(mac, priv->associated_bss, ETH_ALEN);
        return 0;
 }
 
@@ -1837,7 +1837,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
                vif->iftype = STATION_MODE;
                wilc_set_operation_mode(vif, STATION_MODE);
 
-               memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
+               memset(priv->assoc_stainfo.sta_associated_bss, 0, MAX_NUM_STA * ETH_ALEN);
 
                wilc_enable_ps = true;
                wilc_set_power_mgmt(vif, 1, 0);
@@ -1893,9 +1893,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
 static int start_ap(struct wiphy *wiphy, struct net_device *dev,
                    struct cfg80211_ap_settings *settings)
 {
-       struct cfg80211_beacon_data *beacon = &(settings->beacon);
+       struct cfg80211_beacon_data *beacon = &settings->beacon;
        struct wilc_priv *priv;
-       s32 s32Error = 0;
+       s32 ret = 0;
        struct wilc *wl;
        struct wilc_vif *vif;
 
@@ -1903,9 +1903,9 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
        vif = netdev_priv(dev);
        wl = vif->wilc;
 
-       s32Error = set_channel(wiphy, &settings->chandef);
+       ret = set_channel(wiphy, &settings->chandef);
 
-       if (s32Error != 0)
+       if (ret != 0)
                netdev_err(dev, "Error in setting channel\n");
 
        wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE);
@@ -1933,10 +1933,10 @@ static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
 
 static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
 {
-       s32 s32Error = 0;
+       s32 ret = 0;
        struct wilc_priv *priv;
        struct wilc_vif *vif;
-       u8 NullBssid[ETH_ALEN] = {0};
+       u8 null_bssid[ETH_ALEN] = {0};
 
        if (!wiphy)
                return -EFAULT;
@@ -1944,22 +1944,22 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
        priv = wiphy_priv(wiphy);
        vif = netdev_priv(priv->dev);
 
-       wilc_wlan_set_bssid(dev, NullBssid, AP_MODE);
+       wilc_wlan_set_bssid(dev, null_bssid, AP_MODE);
 
-       s32Error = wilc_del_beacon(vif);
+       ret = wilc_del_beacon(vif);
 
-       if (s32Error)
+       if (ret)
                netdev_err(dev, "Host delete beacon fail\n");
 
-       return s32Error;
+       return ret;
 }
 
 static int add_station(struct wiphy *wiphy, struct net_device *dev,
                       const u8 *mac, struct station_parameters *params)
 {
-       s32 s32Error = 0;
+       s32 ret = 0;
        struct wilc_priv *priv;
-       struct add_sta_param strStaParams = { {0} };
+       struct add_sta_param sta_params = { {0} };
        struct wilc_vif *vif;
 
        if (!wiphy)
@@ -1969,35 +1969,35 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev,
        vif = netdev_priv(dev);
 
        if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
-               memcpy(strStaParams.bssid, mac, ETH_ALEN);
-               memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
-               strStaParams.aid = params->aid;
-               strStaParams.rates_len = params->supported_rates_len;
-               strStaParams.rates = params->supported_rates;
+               memcpy(sta_params.bssid, mac, ETH_ALEN);
+               memcpy(priv->assoc_stainfo.sta_associated_bss[params->aid], mac, ETH_ALEN);
+               sta_params.aid = params->aid;
+               sta_params.rates_len = params->supported_rates_len;
+               sta_params.rates = params->supported_rates;
 
                if (!params->ht_capa) {
-                       strStaParams.ht_supported = false;
+                       sta_params.ht_supported = false;
                } else {
-                       strStaParams.ht_supported = true;
-                       strStaParams.ht_capa = *params->ht_capa;
+                       sta_params.ht_supported = true;
+                       sta_params.ht_capa = *params->ht_capa;
                }
 
-               strStaParams.flags_mask = params->sta_flags_mask;
-               strStaParams.flags_set = params->sta_flags_set;
+               sta_params.flags_mask = params->sta_flags_mask;
+               sta_params.flags_set = params->sta_flags_set;
 
-               s32Error = wilc_add_station(vif, &strStaParams);
-               if (s32Error)
+               ret = wilc_add_station(vif, &sta_params);
+               if (ret)
                        netdev_err(dev, "Host add station fail\n");
        }
 
-       return s32Error;
+       return ret;
 }
 
 static int del_station(struct wiphy *wiphy, struct net_device *dev,
                       struct station_del_parameters *params)
 {
        const u8 *mac = params->mac;
-       s32 s32Error = 0;
+       s32 ret = 0;
        struct wilc_priv *priv;
        struct wilc_vif *vif;
 
@@ -2009,23 +2009,23 @@ static int del_station(struct wiphy *wiphy, struct net_device *dev,
 
        if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
                if (!mac)
-                       s32Error = wilc_del_allstation(vif,
-                                    priv->assoc_stainfo.au8Sta_AssociatedBss);
+                       ret = wilc_del_allstation(vif,
+                                    priv->assoc_stainfo.sta_associated_bss);
 
-               s32Error = wilc_del_station(vif, mac);
+               ret = wilc_del_station(vif, mac);
 
-               if (s32Error)
+               if (ret)
                        netdev_err(dev, "Host delete station fail\n");
        }
-       return s32Error;
+       return ret;
 }
 
 static int change_station(struct wiphy *wiphy, struct net_device *dev,
                          const u8 *mac, struct station_parameters *params)
 {
-       s32 s32Error = 0;
+       s32 ret = 0;
        struct wilc_priv *priv;
-       struct add_sta_param strStaParams = { {0} };
+       struct add_sta_param sta_params = { {0} };
        struct wilc_vif *vif;
 
        if (!wiphy)
@@ -2035,26 +2035,26 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev,
        vif = netdev_priv(dev);
 
        if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
-               memcpy(strStaParams.bssid, mac, ETH_ALEN);
-               strStaParams.aid = params->aid;
-               strStaParams.rates_len = params->supported_rates_len;
-               strStaParams.rates = params->supported_rates;
+               memcpy(sta_params.bssid, mac, ETH_ALEN);
+               sta_params.aid = params->aid;
+               sta_params.rates_len = params->supported_rates_len;
+               sta_params.rates = params->supported_rates;
 
                if (!params->ht_capa) {
-                       strStaParams.ht_supported = false;
+                       sta_params.ht_supported = false;
                } else {
-                       strStaParams.ht_supported = true;
-                       strStaParams.ht_capa = *params->ht_capa;
+                       sta_params.ht_supported = true;
+                       sta_params.ht_capa = *params->ht_capa;
                }
 
-               strStaParams.flags_mask = params->sta_flags_mask;
-               strStaParams.flags_set = params->sta_flags_set;
+               sta_params.flags_mask = params->sta_flags_mask;
+               sta_params.flags_set = params->sta_flags_set;
 
-               s32Error = wilc_edit_station(vif, &strStaParams);
-               if (s32Error)
+               ret = wilc_edit_station(vif, &sta_params);
+               if (ret)
                        netdev_err(dev, "Host edit station fail\n");
        }
-       return s32Error;
+       return ret;
 }
 
 static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
@@ -2198,7 +2198,7 @@ static const struct cfg80211_ops wilc_cfg80211_ops = {
 
 };
 
-static struct wireless_dev *WILC_WFI_CfgAlloc(void)
+static struct wireless_dev *wilc_wfi_cfg_alloc(void)
 {
        struct wireless_dev *wdev;
 
@@ -2230,9 +2230,9 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de
 {
        struct wilc_priv *priv;
        struct wireless_dev *wdev;
-       s32 s32Error = 0;
+       s32 ret = 0;
 
-       wdev = WILC_WFI_CfgAlloc();
+       wdev = wilc_wfi_cfg_alloc();
        if (!wdev) {
                netdev_err(net, "wiphy new allocate failed\n");
                return NULL;
@@ -2262,8 +2262,8 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de
 
        set_wiphy_dev(wdev->wiphy, dev);
 
-       s32Error = wiphy_register(wdev->wiphy);
-       if (s32Error)
+       ret = wiphy_register(wdev->wiphy);
+       if (ret)
                netdev_err(net, "Cannot register wiphy device\n");
 
        priv->dev = net;
@@ -2272,7 +2272,7 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de
 
 int wilc_init_host_int(struct net_device *net)
 {
-       int s32Error = 0;
+       int ret = 0;
 
        struct wilc_priv *priv;
 
@@ -2283,43 +2283,43 @@ int wilc_init_host_int(struct net_device *net)
        }
        op_ifcs++;
 
-       priv->gbAutoRateAdjusted = false;
+       priv->auto_rate_adjusted = false;
 
-       priv->bInP2PlistenState = false;
+       priv->p2p_listen_state = false;
 
        mutex_init(&priv->scan_req_lock);
-       s32Error = wilc_init(net, &priv->hif_drv);
-       if (s32Error)
+       ret = wilc_init(net, &priv->hif_drv);
+       if (ret)
                netdev_err(net, "Error while initializing hostinterface\n");
 
-       return s32Error;
+       return ret;
 }
 
 int wilc_deinit_host_int(struct net_device *net)
 {
-       int s32Error = 0;
+       int ret = 0;
        struct wilc_vif *vif;
        struct wilc_priv *priv;
 
        priv = wdev_priv(net->ieee80211_ptr);
        vif = netdev_priv(priv->dev);
 
-       priv->gbAutoRateAdjusted = false;
+       priv->auto_rate_adjusted = false;
 
-       priv->bInP2PlistenState = false;
+       priv->p2p_listen_state = false;
 
        op_ifcs--;
 
-       s32Error = wilc_deinit(vif);
+       ret = wilc_deinit(vif);
 
        clear_shadow_scan();
        if (op_ifcs == 0)
                del_timer_sync(&wilc_during_ip_timer);
 
-       if (s32Error)
+       if (ret)
                netdev_err(net, "Error while deinitializing host interface\n");
 
-       return s32Error;
+       return ret;
 }
 
 void wilc_free_wiphy(struct net_device *net)
index e6f4d84971c3a3032bb2e570476c2ebc41696d1e..3337fb26c8e295ddda200af4905a36a2a2960230 100644 (file)
@@ -86,29 +86,28 @@ struct wilc_wfi_wep_key {
 };
 
 struct sta_info {
-       u8 au8Sta_AssociatedBss[MAX_NUM_STA][ETH_ALEN];
+       u8 sta_associated_bss[MAX_NUM_STA][ETH_ALEN];
 };
 
 /*Parameters needed for host interface for  remaining on channel*/
-struct wilc_wfi_p2pListenParams {
-       struct ieee80211_channel *pstrListenChan;
-       enum nl80211_channel_type tenuChannelType;
-       u32 u32ListenDuration;
-       u64 u64ListenCookie;
-       u32 u32ListenSessionID;
+struct wilc_wfi_p2p_listen_params {
+       struct ieee80211_channel *listen_ch;
+       u32 listen_duration;
+       u64 listen_cookie;
+       u32 listen_session_id;
 };
 
 struct wilc_priv {
        struct wireless_dev *wdev;
-       struct cfg80211_scan_request *pstrScanReq;
+       struct cfg80211_scan_request *scan_req;
 
-       struct wilc_wfi_p2pListenParams strRemainOnChanParams;
-       u64 u64tx_cookie;
+       struct wilc_wfi_p2p_listen_params remain_on_ch_params;
+       u64 tx_cookie;
 
-       bool bCfgScanning;
-       u32 u32RcvdChCount;
+       bool cfg_scanning;
+       u32 rcvd_ch_cnt;
 
-       u8 au8AssociatedBss[ETH_ALEN];
+       u8 associated_bss[ETH_ALEN];
        struct sta_info assoc_stainfo;
        struct net_device_stats stats;
        u8 monitor_flag;
@@ -135,9 +134,9 @@ struct wilc_priv {
        /* mutexes */
        struct mutex scan_req_lock;
        /*  */
-       bool gbAutoRateAdjusted;
+       bool auto_rate_adjusted;
 
-       bool bInP2PlistenState;
+       bool p2p_listen_state;
 
 };
 
index f49dfa82f1b8a5b2562e7e6271e8158ee8630443..acaeafc2c3507ec7063983012faf72bcf10011cc 100644 (file)
@@ -1,19 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/completion.h>
 #include "wilc_wlan_if.h"
 #include "wilc_wlan.h"
 #include "wilc_wfi_netdevice.h"
 #include "wilc_wlan_cfg.h"
 
-static CHIP_PS_STATE_T chip_ps_state = CHIP_WAKEDUP;
+static enum chip_ps_states chip_ps_state = CHIP_WAKEDUP;
 
-static inline void acquire_bus(struct wilc *wilc, BUS_ACQUIRE_T acquire)
+static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire)
 {
        mutex_lock(&wilc->hif_cs);
        if (acquire == ACQUIRE_AND_WAKEUP)
                chip_wakeup(wilc);
 }
 
-static inline void release_bus(struct wilc *wilc, BUS_RELEASE_T release)
+static inline void release_bus(struct wilc *wilc, enum bus_release release)
 {
        if (release == RELEASE_ALLOW_SLEEP)
                chip_allow_sleep(wilc);
@@ -692,7 +693,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
                i = 0;
                do {
                        tqe = wilc_wlan_txq_remove_from_head(dev);
-                       if (tqe && (vmm_table[i] != 0)) {
+                       if (tqe && vmm_table[i] != 0) {
                                u32 header, buffer_offset;
 
                                vmm_table[i] = cpu_to_le32(vmm_table[i]);
index 19e4f85fdd279ad659caa767834ac783600d68b6..aeb5417f3587a24fdfff810ce752b6e095112bfe 100644 (file)
@@ -235,7 +235,7 @@ static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str, u32 siz
        buf[2] = (u8)size;
        buf[3] = (u8)(size >> 8);
 
-       if ((str) && (size != 0))
+       if (str && size != 0)
                memcpy(&buf[4], str, size);
 
        return (size + 4);
@@ -256,7 +256,7 @@ static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size)
        buf[2] = (u8)size;
        buf[3] = (u8)(size >> 8);
 
-       if ((b) && (size != 0)) {
+       if ((b) && size != 0) {
                memcpy(&buf[4], b, size);
                for (i = 0; i < size; i++)
                        checksum += buf[i + 4];
@@ -370,7 +370,7 @@ static int wilc_wlan_parse_info_frame(u8 *info, int size)
 
        len = info[2];
 
-       if ((len == 1) && (wid == WID_STATUS)) {
+       if (len == 1 && wid == WID_STATUS) {
                pd->mac_status = info[3];
                type = WILC_CFG_RSP_STATUS;
        }
index c1693cfc076de7f451b4053a9797278e765e3b74..e186509ad334ab5267f3a1d32804eaa43b0a6dbf 100644 (file)
@@ -75,7 +75,7 @@ typedef void (*wilc_tx_complete_func_t)(void *, int);
 #define MAX_SSID_LEN            33
 #define MAX_RATES_SUPPORTED     12
 
-typedef enum {
+enum {
        SUPP_RATES_IE           = 1,
        EXT_SUPP_RATES_IE       = 50,
        HT_CAPABILITY_IE        = 45,
@@ -83,15 +83,15 @@ typedef enum {
        WPA_IE                  = 221,
        WMM_IE                  = 221,
        P2P_IE                  = 221,
-} BEACON_IE;
+};
 
-typedef enum {
+enum bss_types {
        INFRASTRUCTURE          = 0,
        INDEPENDENT,
        AP,
-} BSSTYPE_T;
+};
 
-typedef enum {
+enum {
        RATE_AUTO               = 0,
        RATE_1MB                = 1,
        RATE_2MB                = 2,
@@ -105,55 +105,55 @@ typedef enum {
        RATE_26MB               = 36,
        RATE_48MB               = 48,
        RATE_54MB               = 54
-} TX_RATE_T;
+};
 
-typedef enum {
+enum {
        B_ONLY_MODE             = 0,    /* 1, 2 M, otherwise 5, 11 M */
        G_ONLY_MODE,                    /* 6,12,24 otherwise 9,18,36,48,54 */
        G_MIXED_11B_1_MODE,             /* 1,2,5.5,11 otherwise all on */
        G_MIXED_11B_2_MODE,             /* 1,2,5,11,6,12,24 otherwise all on */
-} G_OPERATING_MODE_T;
+};
 
-typedef enum {
+enum {
        G_SHORT_PREAMBLE        = 0,    /* Short Preamble */
        G_LONG_PREAMBLE         = 1,    /* Long Preamble */
        G_AUTO_PREAMBLE         = 2,    /* Auto Preamble Selection */
-} G_PREAMBLE_T;
+};
 
 #define MAC_CONNECTED          1
 #define MAC_DISCONNECTED       0
 
 #define SCAN_DONE              TRUE
-typedef enum {
+enum {
        PASSIVE_SCAN            = 0,
        ACTIVE_SCAN             = 1,
-} SCANTYPE_T;
+};
 
-typedef enum {
+enum {
        NO_POWERSAVE            = 0,
        MIN_FAST_PS             = 1,
        MAX_FAST_PS             = 2,
        MIN_PSPOLL_PS           = 3,
        MAX_PSPOLL_PS           = 4
-} USER_PS_MODE_T;
+};
 
-typedef enum {
+enum chip_ps_states {
        CHIP_WAKEDUP            = 0,
        CHIP_SLEEPING_AUTO      = 1,
        CHIP_SLEEPING_MANUAL    = 2
-} CHIP_PS_STATE_T;
+};
 
-typedef enum {
+enum bus_acquire {
        ACQUIRE_ONLY            = 0,
        ACQUIRE_AND_WAKEUP      = 1,
-} BUS_ACQUIRE_T;
+};
 
-typedef enum {
+enum bus_release {
        RELEASE_ONLY            = 0,
        RELEASE_ALLOW_SLEEP     = 1,
-} BUS_RELEASE_T;
+};
 
-typedef enum {
+enum {
        NO_SECURITY             = 0,
        WEP_40                  = 0x3,
        WEP_104                 = 0x7,
@@ -163,7 +163,7 @@ typedef enum {
        WPA2_AES                = 0x31,
        WPA2_TKIP               = 0x51,
        WPA2_AES_TKIP           = 0x71, /* Aes or Tkip */
-} SECURITY_T;
+};
 
 enum AUTHTYPE {
        OPEN_SYSTEM             = 1,
@@ -178,88 +178,88 @@ enum SITESURVEY {
        SITE_SURVEY_OFF         = 2
 };
 
-typedef enum {
+enum {
        NORMAL_ACK              = 0,
        NO_ACK,
-} ACK_POLICY_T;
+};
 
-typedef enum {
+enum {
        DONT_RESET              = 0,
        DO_RESET                = 1,
        NO_REQUEST              = 2,
-} RESET_REQ_T;
+};
 
-typedef enum {
+enum {
        REKEY_DISABLE           = 1,
        REKEY_TIME_BASE,
        REKEY_PKT_BASE,
        REKEY_TIME_PKT_BASE
-} RSNA_REKEY_POLICY_T;
+};
 
-typedef enum {
+enum {
        FILTER_NO               = 0x00,
        FILTER_AP_ONLY          = 0x01,
        FILTER_STA_ONLY         = 0x02
-} SCAN_CLASS_FITLER_T;
+};
 
-typedef enum {
+enum {
        PRI_HIGH_RSSI           = 0x00,
        PRI_LOW_RSSI            = 0x04,
        PRI_DETECT              = 0x08
-} SCAN_PRI_T;
+};
 
-typedef enum {
+enum {
        CH_FILTER_OFF           = 0x00,
        CH_FILTER_ON            = 0x10
-} CH_FILTER_T;
+};
 
-typedef enum {
+enum {
        AUTO_PROT               = 0,    /* Auto */
        NO_PROT,                        /* Do not use any protection */
        ERP_PROT,                       /* Protect all ERP frame exchanges */
        HT_PROT,                        /* Protect all HT frame exchanges  */
        GF_PROT,                        /* Protect all GF frame exchanges  */
-} N_PROTECTION_MODE_T;
+};
 
-typedef enum {
+enum {
        G_SELF_CTS_PROT,
        G_RTS_CTS_PROT,
-} G_PROTECTION_MODE_T;
+};
 
-typedef enum {
+enum {
        HT_MIXED_MODE           = 1,
        HT_ONLY_20MHZ_MODE,
        HT_ONLY_20_40MHZ_MODE,
-} N_OPERATING_MODE_T;
+};
 
-typedef enum {
+enum {
        NO_DETECT               = 0,
        DETECT_ONLY             = 1,
        DETECT_PROTECT          = 2,
        DETECT_PROTECT_REPORT   = 3,
-} N_OBSS_DETECTION_T;
+};
 
-typedef enum {
+enum {
        RTS_CTS_NONHT_PROT      = 0,    /* RTS-CTS at non-HT rate */
        FIRST_FRAME_NONHT_PROT,         /* First frame at non-HT rate */
        LSIG_TXOP_PROT,                 /* LSIG TXOP Protection */
        FIRST_FRAME_MIXED_PROT,         /* First frame at Mixed format */
-} N_PROTECTION_TYPE_T;
+};
 
-typedef enum {
+enum {
        STATIC_MODE             = 1,
        DYNAMIC_MODE            = 2,
        MIMO_MODE               = 3,    /* power save disable */
-} N_SMPS_MODE_T;
+};
 
-typedef enum {
+enum {
        DISABLE_SELF_CTS,
        ENABLE_SELF_CTS,
        DISABLE_TX_ABORT,
        ENABLE_TX_ABORT,
        HW_TRIGGER_ABORT,
        SW_TRIGGER_ABORT,
-} TX_ABORT_OPTION_T;
+};
 
 enum wid_type {
        WID_CHAR                = 0,
@@ -281,7 +281,7 @@ struct wid {
        s8 *val;
 };
 
-typedef enum {
+enum {
        WID_NIL                         = 0xffff,
 
        /*
@@ -889,7 +889,7 @@ typedef enum {
        /* Miscellaneous WIDs */
        WID_ALL                         = 0x7FFE,
        WID_MAX                         = 0xFFFF
-} WID_T;
+};
 
 struct wilc;
 int wilc_wlan_init(struct net_device *dev);
index f5a3a1ce21ce8f27eec3b28c4ee2aa8c874e9a04..85c3af00abd2eb410481e9a3e35051cab16b04d7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* hfa384x.h
  *
  * Defines the constants and data structures for the hfa384x
index 197f5a914e8fadbc63821a2879ad999a093fb0de..555711bc12f068ebd36861ebf837532f5d95bfae 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* src/prism2/driver/hfa384x_usb.c
  *
  * Functions that talk to the USB variantof the Intersil hfa384x MAC
@@ -2457,7 +2458,8 @@ int hfa384x_drvr_start(struct hfa384x *hw)
         * ok
         */
        result =
-           usb_get_std_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status);
+           usb_get_std_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in,
+                              &status);
        if (result < 0) {
                netdev_err(hw->wlandev->netdev, "Cannot get bulk in endpoint status.\n");
                goto done;
@@ -2466,7 +2468,8 @@ int hfa384x_drvr_start(struct hfa384x *hw)
                netdev_err(hw->wlandev->netdev, "Failed to reset bulk in endpoint.\n");
 
        result =
-           usb_get_std_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status);
+           usb_get_std_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out,
+                              &status);
        if (result < 0) {
                netdev_err(hw->wlandev->netdev, "Cannot get bulk out endpoint status.\n");
                goto done;
index c1b6d426bcad7d5e9252d8a29308dfe253d53f42..855b424f64236df209d1648fb36fc16b41d58346 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* src/p80211/p80211conv.c
  *
  * Ether/802.11 conversions and packet buffer routines
index 66332b1fb6d568d3ebf4ef2b9a1568949dfafded..28459dcea4b1a065b06697c850e25b477514285f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* p80211conv.h
  *
  * Ether/802.11 conversions and packet buffer routines
index 2c44c613a5864e64d242bc3e2c076812cc1fba5f..133d70c08ecf757ae21a178a3bdff2de1ab540f7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* p80211hdr.h
  *
  * Macros, types, and functions for handling 802.11 MAC headers
index ab6067e650502bab60eaa030bd0923ce50c61504..d8cde1d8870b926eb89312f50bba3927a19f4c0f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* p80211ioctl.h
  *
  * Declares constants and types for the p80211 ioctls
index ea3d9ce222b95192ef87c3d5bad0e724bd017b4f..4ac2f08a520ae893bc3ab0edaf7bb8528173163a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* This file is GENERATED AUTOMATICALLY.  DO NOT EDIT OR MODIFY.
  * --------------------------------------------------------------------
  *
index 850d897fc163bf620bfaab280b229d7dc9c99f40..15b7c08e210d88f5605188afe768fb519feaecbe 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* This file is GENERATED AUTOMATICALLY.  DO NOT EDIT OR MODIFY.
 * --------------------------------------------------------------------
 *
index 653950fd9843472e644f00ce3c43fe08298d8bf5..3c12929858cbd48bd707aaf9f593d30d05859e71 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* p80211mgmt.h
  *
  * Macros, types, and functions to handle 802.11 mgmt frames
index 40c5cf5997c7027dac88f3084c58cd01e5ec0b3f..ae119ecd74b03a400c18e7e68f012f5b6b18589b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* p80211msg.h
  *
  * Macros, constants, types, and funcs for req and ind messages
index 0f503652740fa3b350aff5639c789e26acdb6f34..ec9cc00ee241e995372206bc0473e4203efde11e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* src/p80211/p80211knetdev.c
  *
  * Linux Kernel net device interface
@@ -640,7 +641,8 @@ static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr)
        dot11req.msgcode = DIDmsg_dot11req_mibset;
        dot11req.msglen = sizeof(dot11req);
        memcpy(dot11req.devname,
-              ((struct wlandevice *)dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1);
+              ((struct wlandevice *)dev->ml_priv)->name,
+              WLAN_DEVNAMELEN_MAX - 1);
 
        /* Set up the mibattribute argument */
        mibattr->did = DIDmsg_dot11req_mibset_mibattribute;
index 8e0d08298c8bc13b9b9e1b99560e601f469affcd..cebbe746a52fdeb8ccb28bbc7b1cf9e38189d6b1 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* p80211netdev.h
  *
  * WLAN net device structure and functions
index afe847722cf7d6e676b710b6ea433c24ade8165b..c36d01469afc6d11187a9ab2adba771f81af4ed5 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* src/p80211/p80211req.c
  *
  * Request/Indication/MacMgmt interface handling functions
index 6c72f59993e0b0c8d7e9f72253a5f12bf3f7d58b..20be2c3af4c12bb4e6464818f39822579cdfedee 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* p80211req.h
  *
  * Request handling functions
index 263ef2ddb19775276c807791b282a19c434ea2f9..94420562c4188c864aa4b5f49c951bd79816f600 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /*
  * p80211types.h
  *
index 6492ffe59085f3e4eceac881e9a636a9687ce479..8bd92bba0ac15c40723fe72ee1f869a1c1736159 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* src/p80211/p80211wep.c
  *
  * WEP encode/decode for P80211.
index 344bec8cc31b3ea2bf3044474b7d81e2445d3624..5860d0d65841d48c9c1e454946899396131fcbf1 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* from src/prism2/download/prism2dl.c
  *
  * utility for downloading prism2 images moved into kernelspace
index 72070593394a331f010f3a846ed878ae7ead0608..78934e435fcfb7d01072d7caad1df3f343711773 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* src/prism2/driver/prism2mgmt.c
  *
  * Management request handler functions.
index c062418f12029d35a7677d61e4e68a1ed6ea75a3..564c3f4a3e03a916679d5adb91f5c3171692f482 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* prism2mgmt.h
  *
  * Declares the mgmt command handler functions
index e41207d973091a6ca76402833d1bd46addf497c5..edad299ff5ad00b0814c6fe8e1688a3a41c4896d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* src/prism2/driver/prism2mib.c
  *
  * Management request for mibset/mibget
index 99316b9a4e49b5c4870440237a67de3fedf9c4dd..fed0b8ceca6f729e5c9bb757eb46bd1c64709067 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
 /* src/prism2/driver/prism2sta.c
  *
  * Implements the station functionality for prism2
index a3af1cbbf8ee65d22e889b92011d5b163e9b50c2..e19a8291cb2aafb2b1afe04543e65a4a4b29d4bd 100644 (file)
@@ -18,19 +18,6 @@ static const struct pci_device_id xgifb_pci_table[] = {
 
 MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
 
-/* To be included in fb.h */
-#define XGISR                    (xgifb_info->dev_info.P3c4)
-#define XGICR                    (xgifb_info->dev_info.P3d4)
-#define XGIDACA                          (xgifb_info->dev_info.P3c8)
-#define XGIDACD                          (xgifb_info->dev_info.P3c9)
-#define XGIPART1                 (xgifb_info->dev_info.Part1Port)
-#define XGIPART2                 (xgifb_info->dev_info.Part2Port)
-#define XGIPART3                 (xgifb_info->dev_info.Part3Port)
-#define XGIPART4                 (xgifb_info->dev_info.Part4Port)
-#define XGIPART5                 (xgifb_info->dev_info.Part5Port)
-#define XGIDAC2A                  XGIPART5
-#define XGIDAC2D                  (XGIPART5 + 1)
-
 #define IND_XGI_SCRATCH_REG_CR30  0x30  /* CRs */
 #define IND_XGI_SCRATCH_REG_CR31  0x31
 #define IND_XGI_SCRATCH_REG_CR32  0x32
index b813f1d460ce3d3793890e322ec5d1d3cb4a27cd..10107de0119a29d73d13a83071418e31150d6059 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * XG20, XG21, XG40, XG42 frame buffer device
  * for Linux kernels  2.5.x, 2.6.x
@@ -31,18 +32,19 @@ static unsigned int refresh_rate;
 #ifdef DEBUG
 static void dumpVGAReg(struct xgifb_video_info *xgifb_info)
 {
+       struct vb_device_info *vb = &xgifb_info->dev_info;
        u8 i, reg;
 
-       xgifb_reg_set(XGISR, 0x05, 0x86);
+       xgifb_reg_set(vb->P3c4, 0x05, 0x86);
 
        for (i = 0; i < 0x4f; i++) {
-               reg = xgifb_reg_get(XGISR, i);
+               reg = xgifb_reg_get(vb->P3c4, i);
                pr_debug("o 3c4 %x\n", i);
                pr_debug("i 3c5 => %x\n", reg);
        }
 
        for (i = 0; i < 0xF0; i++) {
-               reg = xgifb_reg_get(XGICR, i);
+               reg = xgifb_reg_get(vb->P3d4, i);
                pr_debug("o 3d4 %x\n", i);
                pr_debug("i 3d5 => %x\n", reg);
        }
@@ -644,9 +646,10 @@ static void XGIfb_bpp_to_var(struct xgifb_video_info *xgifb_info,
 
 static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info)
 {
+       struct vb_device_info *vb = &xgifb_info->dev_info;
        u8 cr30 = 0, cr31 = 0;
 
-       cr31 = xgifb_reg_get(XGICR, 0x31);
+       cr31 = xgifb_reg_get(vb->P3d4, 0x31);
        cr31 &= ~0x60;
 
        switch (xgifb_info->display2) {
@@ -683,14 +686,15 @@ static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info)
                cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
        }
 
-       xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
-       xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
-       xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33,
+       xgifb_reg_set(vb->P3d4, IND_XGI_SCRATCH_REG_CR30, cr30);
+       xgifb_reg_set(vb->P3d4, IND_XGI_SCRATCH_REG_CR31, cr31);
+       xgifb_reg_set(vb->P3d4, IND_XGI_SCRATCH_REG_CR33,
                      (xgifb_info->rate_idx & 0x0F));
 }
 
 static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
 {
+       struct vb_device_info *vb = &xgifb_info->dev_info;
        u8 reg;
        unsigned char doit = 1;
 
@@ -713,7 +717,7 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
 
        /* We can't switch off CRT1 if bridge is in slave mode */
        if (xgifb_info->hasVB != HASVB_NONE) {
-               reg = xgifb_reg_get(XGIPART1, 0x00);
+               reg = xgifb_reg_get(vb->Part1Port, 0x00);
 
                if ((reg & 0x50) == 0x10)
                        doit = 0;
@@ -722,18 +726,18 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
                XGIfb_crt1off = 0;
        }
 
-       reg = xgifb_reg_get(XGICR, 0x17);
+       reg = xgifb_reg_get(vb->P3d4, 0x17);
        if ((XGIfb_crt1off) && (doit))
                reg &= ~0x80;
        else
                reg |= 0x80;
-       xgifb_reg_set(XGICR, 0x17, reg);
+       xgifb_reg_set(vb->P3d4, 0x17, reg);
 
-       xgifb_reg_and(XGISR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+       xgifb_reg_and(vb->P3c4, IND_SIS_RAMDAC_CONTROL, ~0x04);
 
        if (xgifb_info->display2 == XGIFB_DISP_TV &&
            xgifb_info->hasVB == HASVB_301) {
-               reg = xgifb_reg_get(XGIPART4, 0x01);
+               reg = xgifb_reg_get(vb->Part4Port, 0x01);
 
                if (reg < 0xB0) { /* Set filter for XGI301 */
                        int filter_tb;
@@ -760,60 +764,58 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
                                filter = -1;
                                break;
                        }
-                       xgifb_reg_or(XGIPART1,
-                                    SIS_CRT2_WENABLE_315,
-                                    0x01);
+                       xgifb_reg_or(vb->Part1Port, SIS_CRT2_WENABLE_315, 0x01);
 
                        if (xgifb_info->TV_type == TVMODE_NTSC) {
-                               xgifb_reg_and(XGIPART2, 0x3a, 0x1f);
+                               xgifb_reg_and(vb->Part2Port, 0x3a, 0x1f);
 
                                if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
-                                       xgifb_reg_and(XGIPART2, 0x30, 0xdf);
+                                       xgifb_reg_and(vb->Part2Port, 0x30, 0xdf);
 
                                } else if (xgifb_info->TV_plug
                                                == TVPLUG_COMPOSITE) {
-                                       xgifb_reg_or(XGIPART2, 0x30, 0x20);
+                                       xgifb_reg_or(vb->Part2Port, 0x30, 0x20);
 
                                        switch (xgifb_info->video_width) {
                                        case 640:
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x35,
                                                              0xEB);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x36,
                                                              0x04);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x37,
                                                              0x25);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x38,
                                                              0x18);
                                                break;
                                        case 720:
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x35,
                                                              0xEE);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x36,
                                                              0x0C);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x37,
                                                              0x22);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x38,
                                                              0x08);
                                                break;
                                        case 800:
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x35,
                                                              0xEB);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x36,
                                                              0x15);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x37,
                                                              0x25);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x38,
                                                              0xF6);
                                                break;
@@ -821,55 +823,55 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
                                }
 
                        } else if (xgifb_info->TV_type == TVMODE_PAL) {
-                               xgifb_reg_and(XGIPART2, 0x3A, 0x1F);
+                               xgifb_reg_and(vb->Part2Port, 0x3A, 0x1F);
 
                                if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
-                                       xgifb_reg_and(XGIPART2, 0x30, 0xDF);
+                                       xgifb_reg_and(vb->Part2Port, 0x30, 0xDF);
 
                                } else if (xgifb_info->TV_plug
                                                == TVPLUG_COMPOSITE) {
-                                       xgifb_reg_or(XGIPART2, 0x30, 0x20);
+                                       xgifb_reg_or(vb->Part2Port, 0x30, 0x20);
 
                                        switch (xgifb_info->video_width) {
                                        case 640:
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x35,
                                                              0xF1);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x36,
                                                              0xF7);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x37,
                                                              0x1F);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x38,
                                                              0x32);
                                                break;
                                        case 720:
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x35,
                                                              0xF3);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x36,
                                                              0x00);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x37,
                                                              0x1D);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x38,
                                                              0x20);
                                                break;
                                        case 800:
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x35,
                                                              0xFC);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x36,
                                                              0xFB);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x37,
                                                              0x14);
-                                               xgifb_reg_set(XGIPART2,
+                                               xgifb_reg_set(vb->Part2Port,
                                                              0x38,
                                                              0x2A);
                                                break;
@@ -882,10 +884,10 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
 
                                pr_debug("FilterTable[%d]-%d: %*ph\n",
                                         filter_tb, filter, 4, f);
-                               xgifb_reg_set(XGIPART2, 0x35, f[0]);
-                               xgifb_reg_set(XGIPART2, 0x36, f[1]);
-                               xgifb_reg_set(XGIPART2, 0x37, f[2]);
-                               xgifb_reg_set(XGIPART2, 0x38, f[3]);
+                               xgifb_reg_set(vb->Part2Port, 0x35, f[0]);
+                               xgifb_reg_set(vb->Part2Port, 0x36, f[1]);
+                               xgifb_reg_set(vb->Part2Port, 0x37, f[2]);
+                               xgifb_reg_set(vb->Part2Port, 0x38, f[3]);
                        }
                }
        }
@@ -895,6 +897,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
                            struct fb_info *info)
 {
        struct xgifb_video_info *xgifb_info = info->par;
+       struct vb_device_info *vb = &xgifb_info->dev_info;
        struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
        unsigned int htotal = var->left_margin + var->xres + var->right_margin
                        + var->hsync_len;
@@ -981,11 +984,10 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
                info->fix.line_length = (info->var.xres_virtual
                                * info->var.bits_per_pixel) >> 6;
 
-               xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
+               xgifb_reg_set(vb->P3c4, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-               xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff));
-               xgifb_reg_set(XGISR,
-                             0x0E,
+               xgifb_reg_set(vb->P3d4, 0x13, (info->fix.line_length & 0x00ff));
+               xgifb_reg_set(vb->P3c4, 0x0E,
                              (info->fix.line_length & 0xff00) >> 8);
 
                XGIfb_post_setmode(xgifb_info);
@@ -1013,16 +1015,16 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
                        xgifb_info->XGI310_AccelDepth = 0x00000000;
                        xgifb_info->video_cmap_len = 256;
 #if defined(__BIG_ENDIAN)
-                       cr_data = xgifb_reg_get(XGICR, 0x4D);
-                       xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
+                       cr_data = xgifb_reg_get(vb->P3d4, 0x4D);
+                       xgifb_reg_set(vb->P3d4, 0x4D, (cr_data & 0xE0));
 #endif
                        break;
                case 16:
                        xgifb_info->DstColor = 0x8000;
                        xgifb_info->XGI310_AccelDepth = 0x00010000;
 #if defined(__BIG_ENDIAN)
-                       cr_data = xgifb_reg_get(XGICR, 0x4D);
-                       xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
+                       cr_data = xgifb_reg_get(vb->P3d4, 0x4D);
+                       xgifb_reg_set(vb->P3d4, 0x4D, ((cr_data & 0xE0) | 0x0B));
 #endif
                        xgifb_info->video_cmap_len = 16;
                        break;
@@ -1031,8 +1033,8 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
                        xgifb_info->XGI310_AccelDepth = 0x00020000;
                        xgifb_info->video_cmap_len = 16;
 #if defined(__BIG_ENDIAN)
-                       cr_data = xgifb_reg_get(XGICR, 0x4D);
-                       xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
+                       cr_data = xgifb_reg_get(vb->P3d4, 0x4D);
+                       xgifb_reg_set(vb->P3d4, 0x4D, ((cr_data & 0xE0) | 0x15));
 #endif
                        break;
                default:
@@ -1051,6 +1053,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
        struct xgifb_video_info *xgifb_info = info->par;
+       struct vb_device_info *vb = &xgifb_info->dev_info;
        unsigned int base;
 
        base = var->yoffset * info->var.xres_virtual + var->xoffset;
@@ -1068,22 +1071,20 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
                break;
        }
 
-       xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
+       xgifb_reg_set(vb->P3c4, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-       xgifb_reg_set(XGICR, 0x0D, base & 0xFF);
-       xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF);
-       xgifb_reg_set(XGISR, 0x0D, (base >> 16) & 0xFF);
-       xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
-       xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
+       xgifb_reg_set(vb->P3d4, 0x0D, base & 0xFF);
+       xgifb_reg_set(vb->P3d4, 0x0C, (base >> 8) & 0xFF);
+       xgifb_reg_set(vb->P3c4, 0x0D, (base >> 16) & 0xFF);
+       xgifb_reg_set(vb->P3c4, 0x37, (base >> 24) & 0x03);
+       xgifb_reg_and_or(vb->P3c4, 0x37, 0xDF, (base >> 21) & 0x04);
 
        if (xgifb_info->display2 != XGIFB_DISP_NONE) {
-               xgifb_reg_or(XGIPART1, SIS_CRT2_WENABLE_315, 0x01);
-               xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
-               xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
-               xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
-               xgifb_reg_and_or(XGIPART1,
-                                0x02,
-                                0x7F,
+               xgifb_reg_or(vb->Part1Port, SIS_CRT2_WENABLE_315, 0x01);
+               xgifb_reg_set(vb->Part1Port, 0x06, (base & 0xFF));
+               xgifb_reg_set(vb->Part1Port, 0x05, ((base >> 8) & 0xFF));
+               xgifb_reg_set(vb->Part1Port, 0x04, ((base >> 16) & 0xFF));
+               xgifb_reg_and_or(vb->Part1Port, 0x02, 0x7F,
                                 ((base >> 24) & 0x01) << 7);
        }
        return 0;
@@ -1110,21 +1111,22 @@ static int XGIfb_setcolreg(unsigned int regno, unsigned int red,
                           unsigned int transp, struct fb_info *info)
 {
        struct xgifb_video_info *xgifb_info = info->par;
+       struct vb_device_info *vb = &xgifb_info->dev_info;
 
        if (regno >= XGIfb_get_cmap_len(&info->var))
                return 1;
 
        switch (info->var.bits_per_pixel) {
        case 8:
-               outb(regno, XGIDACA);
-               outb((red >> 10), XGIDACD);
-               outb((green >> 10), XGIDACD);
-               outb((blue >> 10), XGIDACD);
+               outb(regno, vb->P3c8);
+               outb((red >> 10), vb->P3c9);
+               outb((green >> 10), vb->P3c9);
+               outb((blue >> 10), vb->P3c9);
                if (xgifb_info->display2 != XGIFB_DISP_NONE) {
-                       outb(regno, XGIDAC2A);
-                       outb((red >> 8), XGIDAC2D);
-                       outb((green >> 8), XGIDAC2D);
-                       outb((blue >> 8), XGIDAC2D);
+                       outb(regno, vb->Part5Port);
+                       outb((red >> 8), (vb->Part5Port + 1));
+                       outb((green >> 8), (vb->Part5Port + 1));
+                       outb((blue >> 8), (vb->Part5Port + 1));
                }
                break;
        case 16:
@@ -1344,18 +1346,19 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var,
 static int XGIfb_blank(int blank, struct fb_info *info)
 {
        struct xgifb_video_info *xgifb_info = info->par;
+       struct vb_device_info *vb = &xgifb_info->dev_info;
        u8 reg;
 
-       reg = xgifb_reg_get(XGICR, 0x17);
+       reg = xgifb_reg_get(vb->P3d4, 0x17);
 
        if (blank > 0)
                reg &= 0x7f;
        else
                reg |= 0x80;
 
-       xgifb_reg_set(XGICR, 0x17, reg);
-       xgifb_reg_set(XGISR, 0x00, 0x01); /* Synchronous Reset */
-       xgifb_reg_set(XGISR, 0x00, 0x03); /* End Reset */
+       xgifb_reg_set(vb->P3d4, 0x17, reg);
+       xgifb_reg_set(vb->P3c4, 0x00, 0x01); /* Synchronous Reset */
+       xgifb_reg_set(vb->P3c4, 0x00, 0x03); /* End Reset */
        return 0;
 }
 
@@ -1379,14 +1382,15 @@ static struct fb_ops XGIfb_ops = {
 
 static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info)
 {
+       struct vb_device_info *vb = &xgifb_info->dev_info;
        u8 ChannelNum, tmp;
        u8 reg = 0;
 
        /* xorg driver sets 32MB * 1 channel */
        if (xgifb_info->chip == XG27)
-               xgifb_reg_set(XGISR, IND_SIS_DRAM_SIZE, 0x51);
+               xgifb_reg_set(vb->P3c4, IND_SIS_DRAM_SIZE, 0x51);
 
-       reg = xgifb_reg_get(XGISR, IND_SIS_DRAM_SIZE);
+       reg = xgifb_reg_get(vb->P3c4, IND_SIS_DRAM_SIZE);
        if (!reg)
                return -1;
 
@@ -1457,12 +1461,13 @@ static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info)
 
 static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
 {
+       struct vb_device_info *vb = &xgifb_info->dev_info;
        u8 cr32, temp = 0;
 
        xgifb_info->TV_plug = 0;
        xgifb_info->TV_type = 0;
 
-       cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32);
+       cr32 = xgifb_reg_get(vb->P3d4, IND_XGI_SCRATCH_REG_CR32);
 
        if ((cr32 & SIS_CRT1) && !XGIfb_crt1off) {
                XGIfb_crt1off = 0;
@@ -1499,7 +1504,7 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
        }
 
        if (xgifb_info->TV_type == 0) {
-               temp = xgifb_reg_get(XGICR, 0x38);
+               temp = xgifb_reg_get(vb->P3d4, 0x38);
                if (temp & 0x10)
                        xgifb_info->TV_type = TVMODE_PAL;
                else
@@ -1519,7 +1524,7 @@ static bool XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
 {
        u8 vb_chipid;
 
-       vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
+       vb_chipid = xgifb_reg_get(xgifb_info->dev_info.Part4Port, 0x00);
        switch (vb_chipid) {
        case 0x01:
                xgifb_info->hasVB = HASVB_301;
@@ -1539,7 +1544,8 @@ static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info)
        u8 reg;
 
        if (!XGIfb_has_VB(xgifb_info)) {
-               reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
+               reg = xgifb_reg_get(xgifb_info->dev_info.P3d4,
+                                   IND_XGI_SCRATCH_REG_CR37);
                switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
                case SIS_EXTERNAL_CHIP_LVDS:
                        xgifb_info->hasVB = HASVB_LVDS;
@@ -1617,6 +1623,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        int ret;
        struct fb_info *fb_info;
        struct xgifb_video_info *xgifb_info;
+       struct vb_device_info *vb;
        struct xgi_hw_device_info *hw_info;
        unsigned long video_size_max;
 
@@ -1625,6 +1632,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENOMEM;
 
        xgifb_info = fb_info->par;
+       vb = &xgifb_info->dev_info;
        hw_info = &xgifb_info->hw_info;
        xgifb_info->fb_info = fb_info;
        xgifb_info->chip_id = pdev->device;
@@ -1658,10 +1666,11 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                xgifb_info->display2_force = true;
        }
 
-       XGIRegInit(&xgifb_info->dev_info, xgifb_info->vga_base);
+       XGIRegInit(vb, xgifb_info->vga_base);
 
-       xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
-       reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD);
+       xgifb_reg_set(vb->P3c4,
+                     IND_SIS_PASSWORD, SIS_PASSWORD);
+       reg1 = xgifb_reg_get(vb->P3c4, IND_SIS_PASSWORD);
 
        if (reg1 != 0xa1) { /* I/O error */
                dev_err(&pdev->dev, "I/O error\n");
@@ -1671,8 +1680,10 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        switch (xgifb_info->chip_id) {
        case PCI_DEVICE_ID_XGI_20:
-               xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
-               CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
+               xgifb_reg_or(vb->P3d4,
+                            Index_CR_GPIO_Reg3, GPIOG_EN);
+               CR48 = xgifb_reg_get(vb->P3d4,
+                                    Index_CR_GPIO_Reg1);
                if (CR48 & GPIOG_READ)
                        xgifb_info->chip = XG21;
                else
@@ -1703,11 +1714,12 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
-       xgifb_reg_or(XGISR,
+       xgifb_reg_or(vb->P3c4,
                     IND_SIS_PCI_ADDRESS_SET,
                     (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
        /* Enable 2D accelerator engine */
-       xgifb_reg_or(XGISR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
+       xgifb_reg_or(vb->P3c4,
+                    IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
 
        hw_info->ulVideoMemorySize = xgifb_info->video_size;
 
@@ -1760,7 +1772,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
            (xgifb_info->chip == XG27)) {
                xgifb_info->hasVB = HASVB_NONE;
        } else if (xgifb_info->chip == XG21) {
-               CR38 = xgifb_reg_get(XGICR, 0x38);
+               CR38 = xgifb_reg_get(vb->P3d4, 0x38);
                if ((CR38 & 0xE0) == 0xC0)
                        xgifb_info->display2 = XGIFB_DISP_LCD;
                else if ((CR38 & 0xE0) == 0x60)
@@ -1777,7 +1789,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        switch (xgifb_info->hasVB) {
        case HASVB_301:
-               reg = xgifb_reg_get(XGIPART4, 0x01);
+               reg = xgifb_reg_get(vb->Part4Port, 0x01);
                if (reg >= 0xE0) {
                        hw_info->ujVBChipID = VB_CHIP_302LV;
                        dev_info(&pdev->dev,
@@ -1794,7 +1806,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
                break;
        case HASVB_302:
-               reg = xgifb_reg_get(XGIPART4, 0x01);
+               reg = xgifb_reg_get(vb->Part4Port, 0x01);
                if (reg >= 0xE0) {
                        hw_info->ujVBChipID = VB_CHIP_302LV;
                        dev_info(&pdev->dev,
@@ -1806,7 +1818,8 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                 "XGI302LV bridge detected (revision 0x%02x)\n",
                                 reg);
                } else if (reg >= 0xB0) {
-                       reg1 = xgifb_reg_get(XGIPART4, 0x23);
+                       reg1 = xgifb_reg_get(vb->Part4Port,
+                                            0x23);
 
                        hw_info->ujVBChipID = VB_CHIP_302B;
 
@@ -1844,7 +1857,8 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if (xgifb_info->display2 == XGIFB_DISP_LCD) {
                if (!enable_dstn) {
-                       reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
+                       reg = xgifb_reg_get(vb->P3d4,
+                                           IND_XGI_LCD_PANEL);
                        reg &= 0x0f;
                        hw_info->ulCRT2LCDType = XGI310paneltype[reg];
                }
@@ -1940,11 +1954,11 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        XGIfb_bpp_to_var(xgifb_info, &fb_info->var);
 
        fb_info->var.pixclock = (u32)(1000000000 / XGIfb_mode_rate_to_dclock
-                                     (&xgifb_info->dev_info, hw_info,
+                                     (vb, hw_info,
                                       XGIbios_mode[xgifb_info->mode_idx].mode_no));
 
-       if (XGIfb_mode_rate_to_ddata(&xgifb_info->dev_info,
-                                    hw_info, XGIbios_mode[xgifb_info->mode_idx].mode_no,
+       if (XGIfb_mode_rate_to_ddata(vb, hw_info,
+                                    XGIbios_mode[xgifb_info->mode_idx].mode_no,
                                     &fb_info->var.left_margin,
                                     &fb_info->var.right_margin,
                                     &fb_info->var.upper_margin,
index e9d930f150cb6dedfe6c94af8f7102abc15df72e..1fa0dc66406e68e0a52b3370a502b81f1da8e782 100644 (file)
@@ -74,7 +74,8 @@ static void XGI_SetSeqRegs(struct vb_device_info *pVBInfo)
                /* Get SR1,2,3,4 from file */
                /* SR1 is with screen off 0x20 */
                SRdata = XGI330_StandTable.SR[i];
-               xgifb_reg_set(pVBInfo->P3c4, i + 1, SRdata); /* Set SR 1 2 3 4 */
+               /* Set SR 1 2 3 4 */
+               xgifb_reg_set(pVBInfo->P3c4, i + 1, SRdata);
        }
 }
 
@@ -628,12 +629,14 @@ static void xgifb_set_lcd(int chip_id,
        xgifb_reg_and(pVBInfo->P3c4, 0x35, ~0x80); /* Vsync polarity */
 
        temp = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-       if (temp & 0x4000)
+       if (temp & 0x4000) {
                /* Hsync polarity */
                xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20);
-       if (temp & 0x8000)
+       }
+       if (temp & 0x8000) {
                /* Vsync polarity */
                xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80);
+       }
 }
 
 /*
@@ -1225,9 +1228,10 @@ static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table,
        return table[i].DATAPTR;
 }
 
-static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeIdIndex,
-                                            unsigned short RefreshRateTableIndex,
-                                            struct vb_device_info *pVBInfo)
+static struct SiS_TVData const *XGI_GetTVPtr(
+       unsigned short ModeIdIndex,
+       unsigned short RefreshRateTableIndex,
+       struct vb_device_info *pVBInfo)
 {
        unsigned short i, tempdx, tempal, modeflag;
 
@@ -1480,14 +1484,16 @@ static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
        if (tempcx >= tempax)
                tempcx -= tempax;
 
-       xgifb_reg_set(pVBInfo->Part1Port, 0x1b, (unsigned short)(tempbx & 0xff));
-       xgifb_reg_set(pVBInfo->Part1Port, 0x1c, (unsigned short)(tempcx & 0xff));
+       xgifb_reg_set(pVBInfo->Part1Port, 0x1b,
+                     (unsigned short)(tempbx & 0xff));
+       xgifb_reg_set(pVBInfo->Part1Port, 0x1c,
+                     (unsigned short)(tempcx & 0xff));
 
        tempbx = (tempbx >> 8) & 0x07;
        tempcx = (tempcx >> 8) & 0x07;
 
-       xgifb_reg_set(pVBInfo->Part1Port, 0x1d, (unsigned short)((tempcx << 3) |
-                     tempbx));
+       xgifb_reg_set(pVBInfo->Part1Port, 0x1d,
+                     (unsigned short)((tempcx << 3) | tempbx));
 
        tempax = pVBInfo->VT;
        tempbx = LCDPtr1->LCDVRS;
@@ -1501,8 +1507,10 @@ static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
        if (tempcx >= tempax)
                tempcx -= tempax;
 
-       xgifb_reg_set(pVBInfo->Part1Port, 0x18, (unsigned short)(tempbx & 0xff));
-       xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, ~0x0f, (unsigned short)(tempcx & 0x0f));
+       xgifb_reg_set(pVBInfo->Part1Port, 0x18,
+                     (unsigned short)(tempbx & 0xff));
+       xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, ~0x0f,
+                        (unsigned short)(tempcx & 0x0f));
 
        tempax = ((tempbx >> 8) & 0x07) << 3;
 
@@ -1592,16 +1600,20 @@ static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
 
        tempax = ((tempbx >> 8) & 0xff) << 3;
        tempax |= (unsigned short)((temp3 >> 8) & 0x07);
-       xgifb_reg_set(pVBInfo->Part1Port, 0x20, (unsigned short)(tempax & 0xff));
-       xgifb_reg_set(pVBInfo->Part1Port, 0x21, (unsigned short)(tempbx & 0xff));
+       xgifb_reg_set(pVBInfo->Part1Port, 0x20,
+                     (unsigned short)(tempax & 0xff));
+       xgifb_reg_set(pVBInfo->Part1Port, 0x21,
+                     (unsigned short)(tempbx & 0xff));
 
        temp3 >>= 16;
 
        if (modeflag & HalfDCLK)
                temp3 >>= 1;
 
-       xgifb_reg_set(pVBInfo->Part1Port, 0x22, (unsigned short)((temp3 >> 8) & 0xff));
-       xgifb_reg_set(pVBInfo->Part1Port, 0x23, (unsigned short)(temp3 & 0xff));
+       xgifb_reg_set(pVBInfo->Part1Port, 0x22,
+                     (unsigned short)((temp3 >> 8) & 0xff));
+       xgifb_reg_set(pVBInfo->Part1Port, 0x23,
+                     (unsigned short)(temp3 & 0xff));
 }
 
 /*
@@ -1760,9 +1772,10 @@ static void XGI_UpdateModeInfo(struct vb_device_info *pVBInfo)
 
                        temp &= 0x05;
 
-                       if (!(tempcl & ActiveLCD))
+                       if (!(tempcl & ActiveLCD)) {
                                if (temp == 0x01)
                                        tempcl |= ActiveCRT2;
+                       }
 
                        if (temp == 0x04)
                                tempcl |= ActiveLCD;
@@ -1856,7 +1869,8 @@ finish:
        pVBInfo->VBType = tempbx;
 }
 
-static void XGI_GetVBInfo(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+static void XGI_GetVBInfo(unsigned short ModeIdIndex,
+                         struct vb_device_info *pVBInfo)
 {
        unsigned short tempax, push, tempbx, temp, modeflag;
 
@@ -1981,7 +1995,8 @@ static void XGI_GetVBInfo(unsigned short ModeIdIndex, struct vb_device_info *pVB
        pVBInfo->VBInfo = tempbx;
 }
 
-static void XGI_GetTVInfo(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+static void XGI_GetTVInfo(unsigned short ModeIdIndex,
+                         struct vb_device_info *pVBInfo)
 {
        unsigned short tempbx = 0, resinfo = 0, modeflag, index1;
 
@@ -1998,10 +2013,11 @@ static void XGI_GetTVInfo(unsigned short ModeIdIndex, struct vb_device_info *pVB
                        if (tempbx & TVSetPALM)
                                /* set to NTSC if PAL-M */
                                tempbx &= ~TVSetPAL;
-               } else
+               } else {
                        tempbx &= (SetCHTVOverScan |
                                   TVSetNTSCJ |
                                   TVSetPAL);
+               }
 
                if (pVBInfo->VBInfo & SetCRT2ToSCART)
                        tempbx |= TVSetPAL;
@@ -2026,9 +2042,10 @@ static void XGI_GetTVInfo(unsigned short ModeIdIndex, struct vb_device_info *pVB
                    (!(pVBInfo->VBInfo & SetNotSimuMode)))
                        tempbx |= TVSimuMode;
 
-               if (!(tempbx & TVSetPAL) && (modeflag > 13) && (resinfo == 8))
+               if (!(tempbx & TVSetPAL) && (modeflag > 13) && (resinfo == 8)) {
                        /* NTSC 1024x768, */
                        tempbx |= NTSC1024x768;
+               }
 
                tempbx |= RPLLDIV2XO;
 
@@ -2327,9 +2344,10 @@ void XGI_DisplayOff(struct xgifb_video_info *xgifb_info,
                        mdelay(xgifb_info->lvds_data.PSC_S3);
                }
 
-               if (pVBInfo->IF_DEF_LVDS == 0)
+               if (pVBInfo->IF_DEF_LVDS == 0) {
                        /* DVO/DVI signal off */
                        XGI_XG27BLSignalVDD(0x20, 0x00, pVBInfo);
+               }
        }
 
        xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x20);
@@ -2688,7 +2706,7 @@ static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex)
 
 static unsigned short XGI_GetOffset(unsigned short ModeNo,
                                    unsigned short ModeIdIndex,
-               unsigned short RefreshRateTableIndex)
+                                   unsigned short RefreshRateTableIndex)
 {
        unsigned short temp, colordepth, modeinfo, index, infoflag,
                        ColorDepth[] = { 0x01, 0x02, 0x04 };
@@ -3633,7 +3651,8 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
        }
 }
 
-static void XGI_SetLCDRegs(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
+                          struct vb_device_info *pVBInfo)
 {
        unsigned short pushbx, tempax, tempbx, tempcx, temp, tempah,
                        tempbh, tempch;
@@ -4527,8 +4546,10 @@ static unsigned short XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo)
  * 1 : 301B/302B/301LV/302LV
  * Description :
  */
-static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl,
-                              unsigned char *tempch, struct vb_device_info *pVBInfo)
+static void XGI_GetTVPtrIndex2(unsigned short *tempbx,
+                              unsigned char *tempcl,
+                              unsigned char *tempch,
+                              struct vb_device_info *pVBInfo)
 {
        *tempbx = 0;
        *tempcl = 0;
@@ -4632,13 +4653,14 @@ static void XGI_SetLCDCap_A(unsigned short tempcx,
 static void XGI_SetLCDCap_B(unsigned short tempcx,
                            struct vb_device_info *pVBInfo)
 {
-       if (tempcx & EnableLCD24bpp) /* 24bits */
+       if (tempcx & EnableLCD24bpp) /* 24bits */
                xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
                                 (unsigned short)(((tempcx & 0x00ff) >> 6) | 0x0c));
-       else
+       } else {
                xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
                                 (unsigned short)(((tempcx & 0x00ff) >> 6) | 0x18));
                                  /* Enable Dither */
+       }
 }
 
 static void XGI_LongWait(struct vb_device_info *pVBInfo)
@@ -5461,8 +5483,9 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
                        switch (HwDeviceExtension->ujVBChipID) {
                        case VB_CHIP_301: /* fall through */
                        case VB_CHIP_302:
+                               /* add for CRT2 */
                                XGI_SetCRT2Group301(ModeNo, HwDeviceExtension,
-                                                   pVBInfo); /* add for CRT2 */
+                                                   pVBInfo);
                                break;
 
                        default:
index 0da63e1da32fa43bc497e2ece890180dbe277890..42ecf7fe67663058837c82d9231c692e0580bcd0 100644 (file)
@@ -2493,7 +2493,7 @@ static const struct XGI301C_Tap4TimingStruct xgifb_ntsc_525_tap4_timing[] = {
                 0x02, 0x0C, 0x0E, 0x04, 0x01, 0x0B, 0x0E, 0x06, /* ; EA-EF */
                 0x01, 0x0B, 0x0E, 0x06, 0x00, 0x0A, 0x0F, 0x07, /* ; F0-F7 */
                 0x00, 0x0A, 0x0F, 0x07, 0x00, 0x09, 0x0F, 0x08  /* ; F8-FF */
-                }
+               }
        }
 };
 
@@ -2507,7 +2507,7 @@ static const struct XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[] = {
                 0x7D, 0x0F, 0x16, 0x7E, 0x7D, 0x0E, 0x17, 0x7E, /* ; EA-EF */
                 0x7D, 0x0C, 0x18, 0x7F, 0x7D, 0x0A, 0x18, 0x01, /* ; F0-F7 */
                 0x7D, 0x08, 0x19, 0x02, 0x7D, 0x06, 0x19, 0x04 /* F8-FF */
-                }
+               }
        }
 };
 #endif
diff --git a/drivers/visorbus/Kconfig b/drivers/visorbus/Kconfig
new file mode 100644 (file)
index 0000000..1f5812b
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Unisys visorbus configuration
+#
+
+config UNISYS_VISORBUS
+       tristate "Unisys visorbus driver"
+       depends on X86_64 && ACPI
+       ---help---
+       The visorbus driver is a virtualized bus for the Unisys s-Par firmware.
+       Virtualized devices allow Linux guests on a system to share disks and
+       network cards that do not have SR-IOV support, and to be accessed using
+       the partition desktop application. The visorbus driver is required to
+       discover devices on an s-Par guest, and must be present for any other
+       s-Par guest driver to function correctly.
diff --git a/drivers/visorbus/Makefile b/drivers/visorbus/Makefile
new file mode 100644 (file)
index 0000000..e8df59d
--- /dev/null
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Unisys visorbus
+#
+
+obj-$(CONFIG_UNISYS_VISORBUS)  += visorbus.o
+
+visorbus-y := visorbus_main.o
+visorbus-y += visorchannel.o
+visorbus-y += visorchipset.o
diff --git a/drivers/visorbus/controlvmchannel.h b/drivers/visorbus/controlvmchannel.h
new file mode 100644 (file)
index 0000000..8c57562
--- /dev/null
@@ -0,0 +1,650 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ */
+
+#ifndef __CONTROLVMCHANNEL_H__
+#define __CONTROLVMCHANNEL_H__
+
+#include <linux/uuid.h>
+#include <linux/visorbus.h>
+
+/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */
+#define VISOR_CONTROLVM_CHANNEL_GUID \
+       GUID_INIT(0x2b3c2d10, 0x7ef5, 0x4ad8, \
+                 0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d)
+
+#define CONTROLVM_MESSAGE_MAX 64
+
+/*
+ * Must increment this whenever you insert or delete fields within this channel
+ * struct.  Also increment whenever you change the meaning of fields within this
+ * channel struct so as to break pre-existing software. Note that you can
+ * usually add fields to the END of the channel struct withOUT needing to
+ * increment this.
+ */
+#define VISOR_CONTROLVM_CHANNEL_VERSIONID 1
+
+/* Defines for various channel queues */
+#define CONTROLVM_QUEUE_REQUEST                0
+#define CONTROLVM_QUEUE_RESPONSE       1
+#define CONTROLVM_QUEUE_EVENT          2
+#define CONTROLVM_QUEUE_ACK            3
+
+/* Max num of messages stored during IOVM creation to be reused after crash */
+#define CONTROLVM_CRASHMSG_MAX 2
+
+/*
+ * struct visor_segment_state
+ * @enabled:   May enter other states.
+ * @active:    Assigned to active partition.
+ * @alive:     Configure message sent to service/server.
+ * @revoked:   Similar to partition state ShuttingDown.
+ * @allocated: Memory (device/port number) has been selected by Command.
+ * @known:     Has been introduced to the service/guest partition.
+ * @ready:     Service/Guest partition has responded to introduction.
+ * @operating: Resource is configured and operating.
+ * @reserved:  Natural alignment.
+ *
+ * Note: Don't use high bit unless we need to switch to ushort which is
+ * non-compliant.
+ */
+struct visor_segment_state  {
+       u16 enabled:1;
+       u16 active:1;
+       u16 alive:1;
+       u16 revoked:1;
+       u16 allocated:1;
+       u16 known:1;
+       u16 ready:1;
+       u16 operating:1;
+       u16 reserved:8;
+} __packed;
+
+static const struct visor_segment_state segment_state_running = {
+       1, 1, 1, 0, 1, 1, 1, 1
+};
+
+static const struct visor_segment_state segment_state_paused = {
+       1, 1, 1, 0, 1, 1, 1, 0
+};
+
+static const struct visor_segment_state segment_state_standby = {
+       1, 1, 0, 0, 1, 1, 1, 0
+};
+
+/*
+ * enum controlvm_id
+ * @CONTROLVM_INVALID:
+ * @CONTROLVM_BUS_CREATE:              CP --> SP, GP.
+ * @CONTROLVM_BUS_DESTROY:             CP --> SP, GP.
+ * @CONTROLVM_BUS_CONFIGURE:           CP --> SP.
+ * @CONTROLVM_BUS_CHANGESTATE:         CP --> SP, GP.
+ * @CONTROLVM_BUS_CHANGESTATE_EVENT:   SP, GP --> CP.
+ * @CONTROLVM_DEVICE_CREATE:           CP --> SP, GP.
+ * @CONTROLVM_DEVICE_DESTROY:          CP --> SP, GP.
+ * @CONTROLVM_DEVICE_CONFIGURE:                CP --> SP.
+ * @CONTROLVM_DEVICE_CHANGESTATE:      CP --> SP, GP.
+ * @CONTROLVM_DEVICE_CHANGESTATE_EVENT:        SP, GP --> CP.
+ * @CONTROLVM_DEVICE_RECONFIGURE:      CP --> Boot.
+ * @CONTROLVM_CHIPSET_INIT:            CP --> SP, GP.
+ * @CONTROLVM_CHIPSET_STOP:            CP --> SP, GP.
+ * @CONTROLVM_CHIPSET_READY:           CP --> SP.
+ * @CONTROLVM_CHIPSET_SELFTEST:                CP --> SP.
+ *
+ * Ids for commands that may appear in either queue of a ControlVm channel.
+ *
+ * Commands that are initiated by the command partition (CP), by an IO or
+ * console service partition (SP), or by a guest partition (GP) are:
+ * - issued on the RequestQueue queue (q #0) in the ControlVm channel
+ * - responded to on the ResponseQueue queue (q #1) in the ControlVm channel
+ *
+ * Events that are initiated by an IO or console service partition (SP) or
+ * by a guest partition (GP) are:
+ * - issued on the EventQueue queue (q #2) in the ControlVm channel
+ * - responded to on the EventAckQueue queue (q #3) in the ControlVm channel
+ */
+enum controlvm_id {
+       CONTROLVM_INVALID = 0,
+       /*
+        * SWITCH commands required Parameter: SwitchNumber.
+        * BUS commands required Parameter: BusNumber
+        */
+       CONTROLVM_BUS_CREATE = 0x101,
+       CONTROLVM_BUS_DESTROY = 0x102,
+       CONTROLVM_BUS_CONFIGURE = 0x104,
+       CONTROLVM_BUS_CHANGESTATE = 0x105,
+       CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106,
+       /* DEVICE commands required Parameter: BusNumber, DeviceNumber */
+       CONTROLVM_DEVICE_CREATE = 0x201,
+       CONTROLVM_DEVICE_DESTROY = 0x202,
+       CONTROLVM_DEVICE_CONFIGURE = 0x203,
+       CONTROLVM_DEVICE_CHANGESTATE = 0x204,
+       CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205,
+       CONTROLVM_DEVICE_RECONFIGURE = 0x206,
+       /* CHIPSET commands */
+       CONTROLVM_CHIPSET_INIT = 0x301,
+       CONTROLVM_CHIPSET_STOP = 0x302,
+       CONTROLVM_CHIPSET_READY = 0x304,
+       CONTROLVM_CHIPSET_SELFTEST = 0x305,
+};
+
+/*
+ * struct irq_info
+ * @reserved1:      Natural alignment purposes
+ * @recv_irq_handle: Specifies interrupt handle. It is used to retrieve the
+ *                  corresponding interrupt pin from Monitor; and the interrupt
+ *                  pin is used to connect to the corresponding interrupt.
+ *                  Used by IOPart-GP only.
+ * @recv_irq_vector: Specifies interrupt vector. It, interrupt pin, and shared
+ *                  are used to connect to the corresponding interrupt.
+ *                  Used by IOPart-GP only.
+ * @recv_irq_shared: Specifies if the recvInterrupt is shared.  It, interrupt
+ *                  pin and vector are used to connect to 0 = not shared;
+ *                  1 = shared the corresponding interrupt.
+ *                  Used by IOPart-GP only.
+ * @reserved:       Natural alignment purposes
+ */
+struct irq_info {
+       u64 reserved1;
+       u64 recv_irq_handle;
+       u32 recv_irq_vector;
+       u8 recv_irq_shared;
+       u8 reserved[3];
+} __packed;
+
+/*
+ * struct efi_visor_indication
+ * @boot_to_fw_ui: Stop in UEFI UI
+ * @clear_nvram:   Clear NVRAM
+ * @clear_cmos:           Clear CMOS
+ * @boot_to_tool:  Run install tool
+ * @reserved:     Natural alignment
+ */
+struct efi_visor_indication  {
+       u64 boot_to_fw_ui:1;
+       u64 clear_nvram:1;
+       u64 clear_cmos:1;
+       u64 boot_to_tool:1;
+       /* Remaining bits are available */
+       u64 reserved:60;
+} __packed;
+
+enum visor_chipset_feature {
+       VISOR_CHIPSET_FEATURE_REPLY = 0x00000001,
+       VISOR_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002,
+};
+
+/*
+ * struct controlvm_message_header
+ * @id:                       See CONTROLVM_ID.
+ * @message_size:      Includes size of this struct + size of message.
+ * @segment_index:     Index of segment containing Vm message/information.
+ * @completion_status: Error status code or result of  message completion.
+ * @struct flags:
+ *     @failed:             =1 in a response to signify failure.
+ *     @response_expected:  =1 in all messages that expect a response.
+ *     @server:             =1 in all bus & device-related messages where the
+ *                          message receiver is to act as the bus or device
+ *                          server.
+ *     @test_message:       =1 for testing use only (Control and Command
+ *                          ignore this).
+ *     @partial_completion: =1 if there are forthcoming responses/acks
+ *                           associated with this message.
+ *      @preserve:          =1 this is to let us know to preserve channel
+ *                          contents.
+ *     @writer_in_diag:     =1 the DiagWriter is active in the Diagnostic
+ *                          Partition.
+ *     @reserve:            Natural alignment.
+ * @reserved:         Natural alignment.
+ * @message_handle:    Identifies the particular message instance.
+ * @payload_vm_offset: Offset of payload area from start of this instance.
+ * @payload_max_bytes: Maximum bytes allocated in payload area of ControlVm
+ *                    segment.
+ * @payload_bytes:     Actual number of bytes of payload area to copy between
+ *                    IO/Command. If non-zero, there is a payload to copy.
+ *
+ * This is the common structure that is at the beginning of every
+ * ControlVm message (both commands and responses) in any ControlVm
+ * queue.  Commands are easily distinguished from responses by
+ * looking at the flags.response field.
+ */
+struct controlvm_message_header  {
+       u32 id;
+       /*
+        * For requests, indicates the message type. For responses, indicates
+        * the type of message we are responding to.
+        */
+       u32 message_size;
+       u32 segment_index;
+       u32 completion_status;
+       struct  {
+               u32 failed:1;
+               u32 response_expected:1;
+               u32 server:1;
+               u32 test_message:1;
+               u32 partial_completion:1;
+               u32 preserve:1;
+               u32 writer_in_diag:1;
+               u32 reserve:25;
+       } __packed flags;
+       u32 reserved;
+       u64 message_handle;
+       u64 payload_vm_offset;
+       u32 payload_max_bytes;
+       u32 payload_bytes;
+} __packed;
+
+/*
+ * struct controlvm_packet_device_create - For CONTROLVM_DEVICE_CREATE
+ * @bus_no:        Bus # (0..n-1) from the msg receiver's end.
+ * @dev_no:        Bus-relative (0..n-1) device number.
+ * @channel_addr:   Guest physical address of the channel, which can be
+ *                 dereferenced by the receiver of this ControlVm command.
+ * @channel_bytes:  Specifies size of the channel in bytes.
+ * @data_type_uuid: Specifies format of data in channel.
+ * @dev_inst_uuid:  Instance guid for the device.
+ * @irq_info intr:  Specifies interrupt information.
+ */
+struct controlvm_packet_device_create  {
+       u32 bus_no;
+       u32 dev_no;
+       u64 channel_addr;
+       u64 channel_bytes;
+       guid_t data_type_guid;
+       guid_t dev_inst_guid;
+       struct irq_info intr;
+} __packed;
+
+/*
+ * struct controlvm_packet_device_configure - For CONTROLVM_DEVICE_CONFIGURE
+ * @bus_no: Bus number (0..n-1) from the msg receiver's perspective.
+ * @dev_no: Bus-relative (0..n-1) device number.
+ */
+struct controlvm_packet_device_configure  {
+       u32 bus_no;
+       u32 dev_no;
+} __packed;
+
+/* Total 128 bytes */
+struct controlvm_message_device_create {
+       struct controlvm_message_header header;
+       struct controlvm_packet_device_create packet;
+} __packed;
+
+/* Total 56 bytes */
+struct controlvm_message_device_configure  {
+       struct controlvm_message_header header;
+       struct controlvm_packet_device_configure packet;
+} __packed;
+
+/*
+ * struct controlvm_message_packet - This is the format for a message in any
+ *                                   ControlVm queue.
+ * @struct create_bus:         For CONTROLVM_BUS_CREATE.
+ *     @bus_no:             Bus # (0..n-1) from the msg receiver's perspective.
+ *     @dev_count:          Indicates the max number of devices on this bus.
+ *     @channel_addr:       Guest physical address of the channel, which can be
+ *                          dereferenced by the receiver of this ControlVM
+ *                          command.
+ *     @channel_bytes:      Size of the channel.
+ *     @bus_data_type_uuid: Indicates format of data in bus channel.
+ *     @bus_inst_uuid:      Instance uuid for the bus.
+ *
+ * @struct destroy_bus:                For CONTROLVM_BUS_DESTROY.
+ *     @bus_no: Bus # (0..n-1) from the msg receiver's perspective.
+ *     @reserved: Natural alignment purposes.
+ *
+ * @struct configure_bus:      For CONTROLVM_BUS_CONFIGURE.
+ *     @bus_no:              Bus # (0..n-1) from the receiver's perspective.
+ *     @reserved1:           For alignment purposes.
+ *     @guest_handle:        This is used to convert guest physical address to
+ *                           physical address.
+ *     @recv_bus_irq_handle: Specifies interrupt info. It is used by SP to
+ *                           register to receive interrupts from the CP. This
+ *                           interrupt is used for bus level notifications.
+ *                           The corresponding sendBusInterruptHandle is kept
+ *                           in CP.
+ *
+ * @struct create_device:      For CONTROLVM_DEVICE_CREATE.
+ *
+ * @struct destroy_device:     For CONTROLVM_DEVICE_DESTROY.
+ *     @bus_no: Bus # (0..n-1) from the msg receiver's perspective.
+ *     @dev_no: Bus-relative (0..n-1) device number.
+ *
+ * @struct configure_device:   For CONTROLVM_DEVICE_CONFIGURE.
+ *
+ * @struct reconfigure_device: For CONTROLVM_DEVICE_RECONFIGURE.
+ *     @bus_no: Bus # (0..n-1) from the msg receiver's perspective.
+ *     @dev_no: Bus-relative (0..n-1) device number.
+ *
+ * @struct bus_change_state:   For CONTROLVM_BUS_CHANGESTATE.
+ *     @bus_no:
+ *     @struct state:
+ *     @reserved: Natural alignment purposes.
+ *
+ * @struct device_change_state:        For CONTROLVM_DEVICE_CHANGESTATE.
+ *     @bus_no:
+ *     @dev_no:
+ *     @struct state:
+ *     @struct flags:
+ *             @phys_device: =1 if message is for a physical device.
+ *             @reserved:    Natural alignment.
+ *             @reserved1:   Natural alignment.
+ *     @reserved:    Natural alignment purposes.
+ *
+ * @struct device_change_state_event:  For CONTROLVM_DEVICE_CHANGESTATE_EVENT.
+ *     @bus_no:
+ *     @dev_no:
+ *     @struct state:
+ *     @reserved:     Natural alignment purposes.
+ *
+ * @struct init_chipset:       For CONTROLVM_CHIPSET_INIT.
+ *     @bus_count:       Indicates the max number of busses.
+ *     @switch_count:    Indicates the max number of switches.
+ *     @enum features:
+ *     @platform_number:
+ *
+ * @struct chipset_selftest:   For CONTROLVM_CHIPSET_SELFTEST.
+ *      @options: Reserved.
+ *      @test:   Bit 0 set to run embedded selftest.
+ *
+ * @addr:   A physical address of something, that can be dereferenced by the
+ *         receiver of this ControlVm command.
+ *
+ * @handle: A handle of something (depends on command id).
+ */
+struct controlvm_message_packet  {
+       union  {
+               struct  {
+                       u32 bus_no;
+                       u32 dev_count;
+                       u64 channel_addr;
+                       u64 channel_bytes;
+                       guid_t bus_data_type_guid;
+                       guid_t bus_inst_guid;
+               } __packed create_bus;
+               struct  {
+                       u32 bus_no;
+                       u32 reserved;
+               } __packed destroy_bus;
+               struct  {
+                       u32 bus_no;
+                       u32 reserved1;
+                       u64 guest_handle;
+                       u64 recv_bus_irq_handle;
+               } __packed configure_bus;
+               struct controlvm_packet_device_create create_device;
+               struct  {
+                       u32 bus_no;
+                       u32 dev_no;
+               } __packed destroy_device;
+               struct controlvm_packet_device_configure configure_device;
+               struct  {
+                       u32 bus_no;
+                       u32 dev_no;
+               } __packed reconfigure_device;
+               struct  {
+                       u32 bus_no;
+                       struct visor_segment_state state;
+                       u8 reserved[2];
+               } __packed bus_change_state;
+               struct  {
+                       u32 bus_no;
+                       u32 dev_no;
+                       struct visor_segment_state state;
+                       struct  {
+                               u32 phys_device:1;
+                               u32 reserved:31;
+                               u32 reserved1;
+                       } __packed flags;
+                       u8 reserved[2];
+               } __packed device_change_state;
+               struct  {
+                       u32 bus_no;
+                       u32 dev_no;
+                       struct visor_segment_state state;
+                       u8 reserved[6];
+               } __packed device_change_state_event;
+               struct  {
+                       u32 bus_count;
+                       u32 switch_count;
+                       enum visor_chipset_feature features;
+                       u32 platform_number;
+               } __packed init_chipset;
+               struct  {
+                       u32 options;
+                       u32 test;
+               } __packed chipset_selftest;
+               u64 addr;
+               u64 handle;
+       };
+} __packed;
+
+/* All messages in any ControlVm queue have this layout. */
+struct controlvm_message {
+       struct controlvm_message_header hdr;
+       struct controlvm_message_packet cmd;
+} __packed;
+
+/*
+ * struct visor_controlvm_channel
+ * @struct header:
+ * @gp_controlvm:                      Guest phys addr of this channel.
+ * @gp_partition_tables:               Guest phys addr of partition tables.
+ * @gp_diag_guest:                     Guest phys addr of diagnostic channel.
+ * @gp_boot_romdisk:                   Guest phys addr of (read* only) Boot
+ *                                     ROM disk.
+ * @gp_boot_ramdisk:                   Guest phys addr of writable Boot RAM
+ *                                     disk.
+ * @gp_acpi_table:                     Guest phys addr of acpi table.
+ * @gp_control_channel:                        Guest phys addr of control channel.
+ * @gp_diag_romdisk:                   Guest phys addr of diagnostic ROM disk.
+ * @gp_nvram:                          Guest phys addr of NVRAM channel.
+ * @request_payload_offset:            Offset to request payload area.
+ * @event_payload_offset:              Offset to event payload area.
+ * @request_payload_bytes:             Bytes available in request payload area.
+ * @event_payload_bytes:               Bytes available in event payload area.
+ * @control_channel_bytes:
+ * @nvram_channel_bytes:               Bytes in PartitionNvram segment.
+ * @message_bytes:                     sizeof(CONTROLVM_MESSAGE).
+ * @message_count:                     CONTROLVM_MESSAGE_MAX.
+ * @gp_smbios_table:                   Guest phys addr of SMBIOS tables.
+ * @gp_physical_smbios_table:          Guest phys addr of SMBIOS table.
+ * @gp_reserved:                       VISOR_MAX_GUESTS_PER_SERVICE.
+ * @virtual_guest_firmware_image_base: Guest physical address of EFI firmware
+ *                                     image base.
+ * @virtual_guest_firmware_entry_point:        Guest physical address of EFI firmware
+ *                                     entry point.
+ * @virtual_guest_firmware_image_size: Guest EFI firmware image size.
+ * @virtual_guest_firmware_boot_base:  GPA = 1MB where EFI firmware image is
+ *                                     copied to.
+ * @virtual_guest_image_base:
+ * @virtual_guest_image_size:
+ * @prototype_control_channel_offset:
+ * @virtual_guest_partition_handle:
+ * @restore_action:                    Restore Action field to restore the
+ *                                     guest partition.
+ * @dump_action:                       For Windows guests it shows if the
+ *                                     visordisk is in dump mode.
+ * @nvram_fail_count:
+ * @saved_crash_message_count:         = CONTROLVM_CRASHMSG_MAX.
+ * @saved_crash_message_offset:                Offset to request payload area needed
+ *                                     for crash dump.
+ * @installation_error:                        Type of error encountered during
+ *                                     installation.
+ * @installation_text_id:              Id of string to display.
+ * @installation_remaining_steps:      Number of remaining installation steps
+ *                                     (for progress bars).
+ * @tool_action:                       VISOR_TOOL_ACTIONS Installation Action
+ *                                     field.
+ * @reserved: Alignment.
+ * @struct efi_visor_ind:
+ * @sp_reserved:
+ * @reserved2:                         Force signals to begin on 128-byte
+ *                                     cache line.
+ * @struct request_queue:              Guest partition uses this queue to send
+ *                                     requests to Control.
+ * @struct response_queue:             Control uses this queue to respond to
+ *                                     service or guest partition request.
+ * @struct event_queue:                        Control uses this queue to send events
+ *                                     to guest partition.
+ * @struct event_ack_queue:            Service or guest partition uses this
+ *                                     queue to ack Control events.
+ * @struct request_msg:                        Request fixed-size message pool -
+ *                                     does not include payload.
+ * @struct response_msg:               Response fixed-size message pool -
+ *                                     does not include payload.
+ * @struct event_msg:                  Event fixed-size message pool -
+ *                                     does not include payload.
+ * @struct event_ack_msg:              Ack fixed-size message pool -
+ *                                     does not include payload.
+ * @struct saved_crash_msg:            Message stored during IOVM creation to
+ *                                     be reused after crash.
+ */
+struct visor_controlvm_channel {
+       struct channel_header header;
+       u64 gp_controlvm;
+       u64 gp_partition_tables;
+       u64 gp_diag_guest;
+       u64 gp_boot_romdisk;
+       u64 gp_boot_ramdisk;
+       u64 gp_acpi_table;
+       u64 gp_control_channel;
+       u64 gp_diag_romdisk;
+       u64 gp_nvram;
+       u64 request_payload_offset;
+       u64 event_payload_offset;
+       u32 request_payload_bytes;
+       u32 event_payload_bytes;
+       u32 control_channel_bytes;
+       u32 nvram_channel_bytes;
+       u32 message_bytes;
+       u32 message_count;
+       u64 gp_smbios_table;
+       u64 gp_physical_smbios_table;
+       char gp_reserved[2688];
+       u64 virtual_guest_firmware_image_base;
+       u64 virtual_guest_firmware_entry_point;
+       u64 virtual_guest_firmware_image_size;
+       u64 virtual_guest_firmware_boot_base;
+       u64 virtual_guest_image_base;
+       u64 virtual_guest_image_size;
+       u64 prototype_control_channel_offset;
+       u64 virtual_guest_partition_handle;
+       u16 restore_action;
+       u16 dump_action;
+       u16 nvram_fail_count;
+       u16 saved_crash_message_count;
+       u32 saved_crash_message_offset;
+       u32 installation_error;
+       u32 installation_text_id;
+       u16 installation_remaining_steps;
+       u8 tool_action;
+       u8 reserved;
+       struct efi_visor_indication efi_visor_ind;
+       u32 sp_reserved;
+       u8 reserved2[28];
+       struct signal_queue_header request_queue;
+       struct signal_queue_header response_queue;
+       struct signal_queue_header event_queue;
+       struct signal_queue_header event_ack_queue;
+       struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX];
+       struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX];
+       struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX];
+       struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX];
+       struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX];
+} __packed;
+
+/*
+ * struct visor_controlvm_parameters_header
+ *
+ * The following header will be located at the beginning of PayloadVmOffset for
+ * various ControlVm commands. The receiver of a ControlVm command with a
+ * PayloadVmOffset will dereference this address and then use connection_offset,
+ * initiator_offset, and target_offset to get the location of UTF-8 formatted
+ * strings that can be parsed to obtain command-specific information. The value
+ * of total_length should equal PayloadBytes. The format of the strings at
+ * PayloadVmOffset will take different forms depending on the message.
+ */
+struct visor_controlvm_parameters_header {
+       u32 total_length;
+       u32 header_length;
+       u32 connection_offset;
+       u32 connection_length;
+       u32 initiator_offset;
+       u32 initiator_length;
+       u32 target_offset;
+       u32 target_length;
+       u32 client_offset;
+       u32 client_length;
+       u32 name_offset;
+       u32 name_length;
+       guid_t id;
+       u32 revision;
+       /* Natural alignment */
+       u32 reserved;
+} __packed;
+
+/* General Errors------------------------------------------------------[0-99] */
+#define CONTROLVM_RESP_SUCCESS                    0
+#define CONTROLVM_RESP_ALREADY_DONE               1
+#define CONTROLVM_RESP_IOREMAP_FAILED             2
+#define CONTROLVM_RESP_KMALLOC_FAILED             3
+#define CONTROLVM_RESP_ID_UNKNOWN                 4
+#define CONTROLVM_RESP_ID_INVALID_FOR_CLIENT      5
+/* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */
+#define CONTROLVM_RESP_CLIENT_SWITCHCOUNT_NONZERO  100
+#define CONTROLVM_RESP_EXPECTED_CHIPSET_INIT      101
+/* Maximum Limit----------------------------------------------------[200-299] */
+/* BUS_CREATE */
+#define CONTROLVM_RESP_ERROR_MAX_BUSES            201
+/* DEVICE_CREATE */
+#define CONTROLVM_RESP_ERROR_MAX_DEVICES          202
+/* Payload and Parameter Related------------------------------------[400-499] */
+/* SWITCH_ATTACHEXTPORT, DEVICE_CONFIGURE */
+#define CONTROLVM_RESP_PAYLOAD_INVALID            400
+/* Multiple */
+#define CONTROLVM_RESP_INITIATOR_PARAMETER_INVALID 401
+/* DEVICE_CONFIGURE */
+#define CONTROLVM_RESP_TARGET_PARAMETER_INVALID           402
+/* DEVICE_CONFIGURE */
+#define CONTROLVM_RESP_CLIENT_PARAMETER_INVALID           403
+/* Specified[Packet Structure] Value--------------------------------[500-599] */
+/* SWITCH_ATTACHINTPORT */
+/* BUS_CONFIGURE, DEVICE_CREATE, DEVICE_CONFIG, DEVICE_DESTROY */
+#define CONTROLVM_RESP_BUS_INVALID                500
+/* SWITCH_ATTACHINTPORT*/
+/* DEVICE_CREATE, DEVICE_CONFIGURE, DEVICE_DESTROY */
+#define CONTROLVM_RESP_DEVICE_INVALID             501
+/* DEVICE_CREATE, DEVICE_CONFIGURE */
+#define CONTROLVM_RESP_CHANNEL_INVALID            502
+/* Partition Driver Callback Interface------------------------------[600-699] */
+/* BUS_CREATE, BUS_DESTROY, DEVICE_CREATE, DEVICE_DESTROY */
+#define CONTROLVM_RESP_VIRTPCI_DRIVER_FAILURE     604
+/* Unable to invoke VIRTPCI callback. VIRTPCI Callback returned error. */
+/* BUS_CREATE, BUS_DESTROY, DEVICE_CREATE, DEVICE_DESTROY */
+#define CONTROLVM_RESP_VIRTPCI_DRIVER_CALLBACK_ERROR   605
+/* Generic device callback returned error. */
+/* SWITCH_ATTACHEXTPORT, SWITCH_DETACHEXTPORT, DEVICE_CONFIGURE */
+#define CONTROLVM_RESP_GENERIC_DRIVER_CALLBACK_ERROR   606
+/* Bus Related------------------------------------------------------[700-799] */
+/* BUS_DESTROY */
+#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED       700
+/* Channel Related--------------------------------------------------[800-899] */
+/* GET_CHANNELINFO, DEVICE_DESTROY */
+#define CONTROLVM_RESP_CHANNEL_TYPE_UNKNOWN           800
+/* DEVICE_CREATE */
+#define CONTROLVM_RESP_CHANNEL_SIZE_TOO_SMALL         801
+/* Chipset Shutdown Related---------------------------------------[1000-1099] */
+#define CONTROLVM_RESP_CHIPSET_SHUTDOWN_FAILED        1000
+#define CONTROLVM_RESP_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001
+/* Chipset Stop Related-------------------------------------------[1100-1199] */
+#define CONTROLVM_RESP_CHIPSET_STOP_FAILED_BUS        1100
+#define CONTROLVM_RESP_CHIPSET_STOP_FAILED_SWITCH      1101
+/* Device Related-------------------------------------------------[1400-1499] */
+#define CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT            1400
+
+/* __CONTROLVMCHANNEL_H__ */
+#endif
diff --git a/drivers/visorbus/vbuschannel.h b/drivers/visorbus/vbuschannel.h
new file mode 100644 (file)
index 0000000..b1dce26
--- /dev/null
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ */
+
+#ifndef __VBUSCHANNEL_H__
+#define __VBUSCHANNEL_H__
+
+/*
+ * The vbus channel is the channel area provided via the BUS_CREATE controlvm
+ * message for each virtual bus.  This channel area is provided to both server
+ * and client ends of the bus.  The channel header area is initialized by
+ * the server, and the remaining information is filled in by the client.
+ * We currently use this for the client to provide various information about
+ * the client devices and client drivers for the server end to see.
+ */
+
+#include <linux/uuid.h>
+#include <linux/visorbus.h>
+
+/* {193b331b-c58f-11da-95a9-00e08161165f} */
+#define VISOR_VBUS_CHANNEL_GUID                                                \
+       GUID_INIT(0x193b331b, 0xc58f, 0x11da,                           \
+                 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
+
+/*
+ * Must increment this whenever you insert or delete fields within this channel
+ * struct.  Also increment whenever you change the meaning of fields within this
+ * channel struct so as to break pre-existing software.  Note that you can
+ * usually add fields to the END of the channel struct withOUT needing to
+ * increment this.
+ */
+#define VISOR_VBUS_CHANNEL_VERSIONID 1
+
+/*
+ * struct visor_vbus_deviceinfo
+ * @devtype:  Short string identifying the device type.
+ * @drvname:  Driver .sys file name.
+ * @infostrs: Kernel vversion.
+ * @reserved: Pad size to 256 bytes.
+ *
+ * An array of this struct is present in the channel area for each vbus. It is
+ * filled in by the client side to provide info about the device and driver from
+ * the client's perspective.
+ */
+struct visor_vbus_deviceinfo {
+       u8 devtype[16];
+       u8 drvname[16];
+       u8 infostrs[96];
+       u8 reserved[128];
+} __packed;
+
+/*
+ * struct visor_vbus_headerinfo
+ * @struct_bytes:            Size of this struct in bytes.
+ * @device_info_struct_bytes: Size of VISOR_VBUS_DEVICEINFO.
+ * @dev_info_count:          Num of items in DevInfo member. This is the
+ *                           allocated size.
+ * @chp_info_offset:         Byte offset from beginning of this struct to the
+ *                           ChpInfo struct.
+ * @bus_info_offset:         Byte offset from beginning of this struct to the
+ *                           BusInfo struct.
+ * @dev_info_offset:         Byte offset from beginning of this struct to the
+ *                           DevInfo array.
+ * @reserved:                Natural alignment.
+ */
+struct visor_vbus_headerinfo {
+       u32 struct_bytes;
+       u32 device_info_struct_bytes;
+       u32 dev_info_count;
+       u32 chp_info_offset;
+       u32 bus_info_offset;
+       u32 dev_info_offset;
+       u8 reserved[104];
+} __packed;
+
+/*
+ * struct visor_vbus_channel
+ * @channel_header: Initialized by server.
+ * @hdr_info:      Initialized by server.
+ * @chp_info:      Describes client chipset device and driver.
+ * @bus_info:      Describes client bus device and driver.
+ * @dev_info:      Describes client device and driver for each device on the
+ *                 bus.
+ */
+struct visor_vbus_channel {
+       struct channel_header channel_header;
+       struct visor_vbus_headerinfo hdr_info;
+       struct visor_vbus_deviceinfo chp_info;
+       struct visor_vbus_deviceinfo bus_info;
+       struct visor_vbus_deviceinfo dev_info[0];
+} __packed;
+
+#endif
diff --git a/drivers/visorbus/visorbus_main.c b/drivers/visorbus/visorbus_main.c
new file mode 100644 (file)
index 0000000..0b2434c
--- /dev/null
@@ -0,0 +1,1234 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright ï¿½ 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ */
+
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/visorbus.h>
+#include <linux/uuid.h>
+
+#include "visorbus_private.h"
+
+static const guid_t visor_vbus_channel_guid = VISOR_VBUS_CHANNEL_GUID;
+
+/* Display string that is guaranteed to be no longer the 99 characters */
+#define LINESIZE 99
+#define POLLJIFFIES_NORMALCHANNEL 10
+
+/* stores whether bus_registration was successful */
+static bool initialized;
+static struct dentry *visorbus_debugfs_dir;
+
+/*
+ * DEVICE type attributes
+ *
+ * The modalias file will contain the guid of the device.
+ */
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct visor_device *vdev;
+       const guid_t *guid;
+
+       vdev = to_visor_device(dev);
+       guid = visorchannel_get_guid(vdev->visorchannel);
+       return sprintf(buf, "visorbus:%pUl\n", guid);
+}
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *visorbus_dev_attrs[] = {
+       &dev_attr_modalias.attr,
+       NULL,
+};
+
+ATTRIBUTE_GROUPS(visorbus_dev);
+
+/* filled in with info about parent chipset driver when we register with it */
+static struct visor_vbus_deviceinfo chipset_driverinfo;
+/* filled in with info about this driver, wrt it servicing client busses */
+static struct visor_vbus_deviceinfo clientbus_driverinfo;
+
+/* list of visor_device structs, linked via .list_all */
+static LIST_HEAD(list_all_bus_instances);
+/* list of visor_device structs, linked via .list_all */
+static LIST_HEAD(list_all_device_instances);
+
+/*
+ * Generic function useful for validating any type of channel when it is
+ * received by the client that will be accessing the channel.
+ * Note that <logCtx> is only needed for callers in the EFI environment, and
+ * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
+ */
+int visor_check_channel(struct channel_header *ch, struct device *dev,
+                       const guid_t *expected_guid, char *chname,
+                       u64 expected_min_bytes, u32 expected_version,
+                       u64 expected_signature)
+{
+       if (!guid_is_null(expected_guid)) {
+               /* caller wants us to verify type GUID */
+               if (!guid_equal(&ch->chtype, expected_guid)) {
+                       dev_err(dev, "Channel mismatch on channel=%s(%pUL) field=type expected=%pUL actual=%pUL\n",
+                               chname, expected_guid, expected_guid,
+                               &ch->chtype);
+                       return 0;
+               }
+       }
+       /* verify channel size */
+       if (expected_min_bytes > 0) {
+               if (ch->size < expected_min_bytes) {
+                       dev_err(dev, "Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n",
+                               chname, expected_guid,
+                               (unsigned long long)expected_min_bytes,
+                               ch->size);
+                       return 0;
+               }
+       }
+       /* verify channel version */
+       if (expected_version > 0) {
+               if (ch->version_id != expected_version) {
+                       dev_err(dev, "Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8x\n",
+                               chname, expected_guid,
+                               (unsigned long)expected_version,
+                               ch->version_id);
+                       return 0;
+               }
+       }
+       /* verify channel signature */
+       if (expected_signature > 0) {
+               if (ch->signature != expected_signature) {
+                       dev_err(dev, "Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8Lx actual=0x%-8.8Lx\n",
+                               chname, expected_guid,  expected_signature,
+                               ch->signature);
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env)
+{
+       struct visor_device *dev;
+       const guid_t *guid;
+
+       dev = to_visor_device(xdev);
+       guid = visorchannel_get_guid(dev->visorchannel);
+       return add_uevent_var(env, "MODALIAS=visorbus:%pUl", guid);
+}
+
+/*
+ * visorbus_match() - called automatically upon adding a visor_device
+ *                    (device_add), or adding a visor_driver
+ *                    (visorbus_register_visor_driver)
+ * @xdev: struct device for the device being matched
+ * @xdrv: struct device_driver for driver to match device against
+ *
+ * Return: 1 iff the provided driver can control the specified device
+ */
+static int visorbus_match(struct device *xdev, struct device_driver *xdrv)
+{
+       const guid_t *channel_type;
+       int i;
+       struct visor_device *dev;
+       struct visor_driver *drv;
+       struct visorchannel *chan;
+
+       dev = to_visor_device(xdev);
+       channel_type = visorchannel_get_guid(dev->visorchannel);
+       drv = to_visor_driver(xdrv);
+       chan = dev->visorchannel;
+       if (!drv->channel_types)
+               return 0;
+       for (i = 0; !guid_is_null(&drv->channel_types[i].guid); i++)
+               if (guid_equal(&drv->channel_types[i].guid, channel_type) &&
+                   visor_check_channel(visorchannel_get_header(chan),
+                                       xdev,
+                                       &drv->channel_types[i].guid,
+                                       (char *)drv->channel_types[i].name,
+                                       drv->channel_types[i].min_bytes,
+                                       drv->channel_types[i].version,
+                                       VISOR_CHANNEL_SIGNATURE))
+                       return i + 1;
+       return 0;
+}
+
+/*
+ * This describes the TYPE of bus.
+ * (Don't confuse this with an INSTANCE of the bus.)
+ */
+static struct bus_type visorbus_type = {
+       .name = "visorbus",
+       .match = visorbus_match,
+       .uevent = visorbus_uevent,
+       .dev_groups = visorbus_dev_groups,
+};
+
+struct visor_busdev {
+       u32 bus_no;
+       u32 dev_no;
+};
+
+static int match_visorbus_dev_by_id(struct device *dev, void *data)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+       struct visor_busdev *id = data;
+
+       if (vdev->chipset_bus_no == id->bus_no &&
+           vdev->chipset_dev_no == id->dev_no)
+               return 1;
+       return 0;
+}
+
+struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
+                                              struct visor_device *from)
+{
+       struct device *dev;
+       struct device *dev_start = NULL;
+       struct visor_busdev id = {
+               .bus_no = bus_no,
+               .dev_no = dev_no
+       };
+
+       if (from)
+               dev_start = &from->device;
+       dev = bus_find_device(&visorbus_type, dev_start, (void *)&id,
+                             match_visorbus_dev_by_id);
+       if (!dev)
+               return NULL;
+       return to_visor_device(dev);
+}
+
+/*
+ * visorbus_release_busdevice() - called when device_unregister() is called for
+ *                                the bus device instance, after all other tasks
+ *                                involved with destroying the dev are complete
+ * @xdev: struct device for the bus being released
+ */
+static void visorbus_release_busdevice(struct device *xdev)
+{
+       struct visor_device *dev = dev_get_drvdata(xdev);
+
+       debugfs_remove(dev->debugfs_bus_info);
+       debugfs_remove_recursive(dev->debugfs_dir);
+       visorchannel_destroy(dev->visorchannel);
+       kfree(dev);
+}
+
+/*
+ * visorbus_release_device() - called when device_unregister() is called for
+ *                             each child device instance
+ * @xdev: struct device for the visor device being released
+ */
+static void visorbus_release_device(struct device *xdev)
+{
+       struct visor_device *dev = to_visor_device(xdev);
+
+       visorchannel_destroy(dev->visorchannel);
+       kfree(dev);
+}
+
+/*
+ * BUS specific channel attributes to appear under
+ * /sys/bus/visorbus<x>/dev<y>/channel
+ */
+
+static ssize_t physaddr_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+
+       return sprintf(buf, "0x%llx\n",
+                      visorchannel_get_physaddr(vdev->visorchannel));
+}
+static DEVICE_ATTR_RO(physaddr);
+
+static ssize_t nbytes_show(struct device *dev, struct device_attribute *attr,
+                          char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+
+       return sprintf(buf, "0x%lx\n",
+                      visorchannel_get_nbytes(vdev->visorchannel));
+}
+static DEVICE_ATTR_RO(nbytes);
+
+static ssize_t clientpartition_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+
+       return sprintf(buf, "0x%llx\n",
+                      visorchannel_get_clientpartition(vdev->visorchannel));
+}
+static DEVICE_ATTR_RO(clientpartition);
+
+static ssize_t typeguid_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+       char typeid[LINESIZE];
+
+       return sprintf(buf, "%s\n",
+                      visorchannel_id(vdev->visorchannel, typeid));
+}
+static DEVICE_ATTR_RO(typeguid);
+
+static ssize_t zoneguid_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+       char zoneid[LINESIZE];
+
+       return sprintf(buf, "%s\n",
+                      visorchannel_zoneid(vdev->visorchannel, zoneid));
+}
+static DEVICE_ATTR_RO(zoneguid);
+
+static ssize_t typename_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       int i = 0;
+       struct bus_type *xbus = dev->bus;
+       struct device_driver *xdrv = dev->driver;
+       struct visor_driver *drv = NULL;
+
+       if (!xdrv)
+               return 0;
+       i = xbus->match(dev, xdrv);
+       if (!i)
+               return 0;
+       drv = to_visor_driver(xdrv);
+       return sprintf(buf, "%s\n", drv->channel_types[i - 1].name);
+}
+static DEVICE_ATTR_RO(typename);
+
+static struct attribute *channel_attrs[] = {
+       &dev_attr_physaddr.attr,
+       &dev_attr_nbytes.attr,
+       &dev_attr_clientpartition.attr,
+       &dev_attr_typeguid.attr,
+       &dev_attr_zoneguid.attr,
+       &dev_attr_typename.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(channel);
+
+/*
+ *  BUS instance attributes
+ *
+ *  define & implement display of bus attributes under
+ *  /sys/bus/visorbus/devices/visorbus<n>.
+ */
+static ssize_t partition_handle_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+       u64 handle = visorchannel_get_clientpartition(vdev->visorchannel);
+
+       return sprintf(buf, "0x%llx\n", handle);
+}
+static DEVICE_ATTR_RO(partition_handle);
+
+static ssize_t partition_guid_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+
+       return sprintf(buf, "{%pUb}\n", &vdev->partition_guid);
+}
+static DEVICE_ATTR_RO(partition_guid);
+
+static ssize_t partition_name_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+
+       return sprintf(buf, "%s\n", vdev->name);
+}
+static DEVICE_ATTR_RO(partition_name);
+
+static ssize_t channel_addr_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+       u64 addr = visorchannel_get_physaddr(vdev->visorchannel);
+
+       return sprintf(buf, "0x%llx\n", addr);
+}
+static DEVICE_ATTR_RO(channel_addr);
+
+static ssize_t channel_bytes_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+       u64 nbytes = visorchannel_get_nbytes(vdev->visorchannel);
+
+       return sprintf(buf, "0x%llx\n", nbytes);
+}
+static DEVICE_ATTR_RO(channel_bytes);
+
+static ssize_t channel_id_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct visor_device *vdev = to_visor_device(dev);
+       int len = 0;
+
+       visorchannel_id(vdev->visorchannel, buf);
+       len = strlen(buf);
+       buf[len++] = '\n';
+       return len;
+}
+static DEVICE_ATTR_RO(channel_id);
+
+static struct attribute *visorbus_attrs[] = {
+       &dev_attr_partition_handle.attr,
+       &dev_attr_partition_guid.attr,
+       &dev_attr_partition_name.attr,
+       &dev_attr_channel_addr.attr,
+       &dev_attr_channel_bytes.attr,
+       &dev_attr_channel_id.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(visorbus);
+
+/*
+ *  BUS debugfs entries
+ *
+ *  define & implement display of debugfs attributes under
+ *  /sys/kernel/debug/visorbus/visorbus<n>.
+ */
+
+/*
+ * vbuschannel_print_devinfo() - format a struct visor_vbus_deviceinfo
+ *                               and write it to a seq_file
+ * @devinfo: the struct visor_vbus_deviceinfo to format
+ * @seq: seq_file to write to
+ * @devix: the device index to be included in the output data, or -1 if no
+ *         device index is to be included
+ *
+ * Reads @devInfo, and writes it in human-readable notation to @seq.
+ */
+static void vbuschannel_print_devinfo(struct visor_vbus_deviceinfo *devinfo,
+                                     struct seq_file *seq, int devix)
+{
+       /* uninitialized vbus device entry */
+       if (!isprint(devinfo->devtype[0]))
+               return;
+       if (devix >= 0)
+               seq_printf(seq, "[%d]", devix);
+       else
+               /* vbus device entry is for bus or chipset */
+               seq_puts(seq, "   ");
+       /*
+        * Note: because the s-Par back-end is free to scribble in this area,
+        * we never assume '\0'-termination.
+        */
+       seq_printf(seq, "%-*.*s ", (int)sizeof(devinfo->devtype),
+                  (int)sizeof(devinfo->devtype), devinfo->devtype);
+       seq_printf(seq, "%-*.*s ", (int)sizeof(devinfo->drvname),
+                  (int)sizeof(devinfo->drvname), devinfo->drvname);
+       seq_printf(seq, "%.*s\n", (int)sizeof(devinfo->infostrs),
+                  devinfo->infostrs);
+}
+
+static int bus_info_debugfs_show(struct seq_file *seq, void *v)
+{
+       int i = 0;
+       unsigned long off;
+       struct visor_vbus_deviceinfo dev_info;
+       struct visor_device *vdev = seq->private;
+       struct visorchannel *channel = vdev->visorchannel;
+
+       if (!channel)
+               return 0;
+
+       seq_printf(seq,
+                  "Client device/driver info for %s partition (vbus #%u):\n",
+                  ((vdev->name) ? (char *)(vdev->name) : ""),
+                  vdev->chipset_bus_no);
+       if (visorchannel_read(channel,
+                             offsetof(struct visor_vbus_channel, chp_info),
+                             &dev_info, sizeof(dev_info)) >= 0)
+               vbuschannel_print_devinfo(&dev_info, seq, -1);
+       if (visorchannel_read(channel,
+                             offsetof(struct visor_vbus_channel, bus_info),
+                             &dev_info, sizeof(dev_info)) >= 0)
+               vbuschannel_print_devinfo(&dev_info, seq, -1);
+
+       off = offsetof(struct visor_vbus_channel, dev_info);
+       while (off + sizeof(dev_info) <= visorchannel_get_nbytes(channel)) {
+               if (visorchannel_read(channel, off, &dev_info,
+                                     sizeof(dev_info)) >= 0)
+                       vbuschannel_print_devinfo(&dev_info, seq, i);
+               off += sizeof(dev_info);
+               i++;
+       }
+       return 0;
+}
+
+static int bus_info_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, bus_info_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations bus_info_debugfs_fops = {
+       .owner = THIS_MODULE,
+       .open = bus_info_debugfs_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static void dev_periodic_work(struct timer_list *t)
+{
+       struct visor_device *dev = from_timer(dev, t, timer);
+       struct visor_driver *drv = to_visor_driver(dev->device.driver);
+
+       drv->channel_interrupt(dev);
+       mod_timer(&dev->timer, jiffies + POLLJIFFIES_NORMALCHANNEL);
+}
+
+static int dev_start_periodic_work(struct visor_device *dev)
+{
+       if (dev->being_removed || dev->timer_active)
+               return -EINVAL;
+
+       /* now up by at least 2 */
+       get_device(&dev->device);
+       dev->timer.expires = jiffies + POLLJIFFIES_NORMALCHANNEL;
+       add_timer(&dev->timer);
+       dev->timer_active = true;
+       return 0;
+}
+
+static void dev_stop_periodic_work(struct visor_device *dev)
+{
+       if (!dev->timer_active)
+               return;
+
+       del_timer_sync(&dev->timer);
+       dev->timer_active = false;
+       put_device(&dev->device);
+}
+
+/*
+ * visordriver_remove_device() - handle visor device going away
+ * @xdev: struct device for the visor device being removed
+ *
+ * This is called when device_unregister() is called for each child device
+ * instance, to notify the appropriate visorbus function driver that the device
+ * is going away, and to decrease the reference count of the device.
+ *
+ * Return: 0 iff successful
+ */
+static int visordriver_remove_device(struct device *xdev)
+{
+       struct visor_device *dev = to_visor_device(xdev);
+       struct visor_driver *drv = to_visor_driver(xdev->driver);
+
+       mutex_lock(&dev->visordriver_callback_lock);
+       dev->being_removed = true;
+       drv->remove(dev);
+       mutex_unlock(&dev->visordriver_callback_lock);
+       dev_stop_periodic_work(dev);
+       put_device(&dev->device);
+       return 0;
+}
+
+/*
+ * visorbus_unregister_visor_driver() - unregisters the provided driver
+ * @drv: the driver to unregister
+ *
+ * A visor function driver calls this function to unregister the driver,
+ * i.e., within its module_exit function.
+ */
+void visorbus_unregister_visor_driver(struct visor_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver);
+
+/*
+ * visorbus_read_channel() - reads from the designated channel into
+ *                           the provided buffer
+ * @dev:    the device whose channel is read from
+ * @offset: the offset into the channel at which reading starts
+ * @dest:   the destination buffer that is written into from the channel
+ * @nbytes: the number of bytes to read from the channel
+ *
+ * If receiving a message, use the visorchannel_signalremove() function instead.
+ *
+ * Return: integer indicating success (zero) or failure (non-zero)
+ */
+int visorbus_read_channel(struct visor_device *dev, unsigned long offset,
+                         void *dest, unsigned long nbytes)
+{
+       return visorchannel_read(dev->visorchannel, offset, dest, nbytes);
+}
+EXPORT_SYMBOL_GPL(visorbus_read_channel);
+
+/*
+ * visorbus_write_channel() - writes the provided buffer into the designated
+ *                            channel
+ * @dev:    the device whose channel is written to
+ * @offset: the offset into the channel at which writing starts
+ * @src:    the source buffer that is written into the channel
+ * @nbytes: the number of bytes to write into the channel
+ *
+ * If sending a message, use the visorchannel_signalinsert() function instead.
+ *
+ * Return: integer indicating success (zero) or failure (non-zero)
+ */
+int visorbus_write_channel(struct visor_device *dev, unsigned long offset,
+                          void *src, unsigned long nbytes)
+{
+       return visorchannel_write(dev->visorchannel, offset, src, nbytes);
+}
+EXPORT_SYMBOL_GPL(visorbus_write_channel);
+
+/*
+ * visorbus_enable_channel_interrupts() - enables interrupts on the
+ *                                        designated device
+ * @dev: the device on which to enable interrupts
+ *
+ * Currently we don't yet have a real interrupt, so for now we just call the
+ * interrupt function periodically via a timer.
+ */
+int visorbus_enable_channel_interrupts(struct visor_device *dev)
+{
+       struct visor_driver *drv = to_visor_driver(dev->device.driver);
+
+       if (!drv->channel_interrupt) {
+               dev_err(&dev->device, "%s no interrupt function!\n", __func__);
+               return -ENOENT;
+       }
+
+       return dev_start_periodic_work(dev);
+}
+EXPORT_SYMBOL_GPL(visorbus_enable_channel_interrupts);
+
+/*
+ * visorbus_disable_channel_interrupts() - disables interrupts on the
+ *                                         designated device
+ * @dev: the device on which to disable interrupts
+ */
+void visorbus_disable_channel_interrupts(struct visor_device *dev)
+{
+       dev_stop_periodic_work(dev);
+}
+EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts);
+
+/*
+ * create_visor_device() - create visor device as a result of receiving the
+ *                         controlvm device_create message for a new device
+ * @dev: a freshly-zeroed struct visor_device, containing only filled-in values
+ *       for chipset_bus_no and chipset_dev_no, that will be initialized
+ *
+ * This is how everything starts from the device end.
+ * This function is called when a channel first appears via a ControlVM
+ * message.  In response, this function allocates a visor_device to correspond
+ * to the new channel, and attempts to connect it the appropriate * driver. If
+ * the appropriate driver is found, the visor_driver.probe() function for that
+ * driver will be called, and will be passed the new * visor_device that we
+ * just created.
+ *
+ * It's ok if the appropriate driver is not yet loaded, because in that case
+ * the new device struct will just stick around in the bus' list of devices.
+ * When the appropriate driver calls visorbus_register_visor_driver(), the
+ * visor_driver.probe() for the new driver will be called with the new device.
+ *
+ * Return: 0 if successful, otherwise the negative value returned by
+ *         device_add() indicating the reason for failure
+ */
+int create_visor_device(struct visor_device *dev)
+{
+       int err;
+       u32 chipset_bus_no = dev->chipset_bus_no;
+       u32 chipset_dev_no = dev->chipset_dev_no;
+
+       mutex_init(&dev->visordriver_callback_lock);
+       dev->device.bus = &visorbus_type;
+       dev->device.groups = channel_groups;
+       device_initialize(&dev->device);
+       dev->device.release = visorbus_release_device;
+       /* keep a reference just for us (now 2) */
+       get_device(&dev->device);
+       timer_setup(&dev->timer, dev_periodic_work, 0);
+       /*
+        * bus_id must be a unique name with respect to this bus TYPE (NOT bus
+        * instance).  That's why we need to include the bus number within the
+        * name.
+        */
+       err = dev_set_name(&dev->device, "vbus%u:dev%u",
+                          chipset_bus_no, chipset_dev_no);
+       if (err)
+               goto err_put;
+       /*
+        * device_add does this:
+        *    bus_add_device(dev)
+        *    ->device_attach(dev)
+        *      ->for each driver drv registered on the bus that dev is on
+        *          if (dev.drv)  **  device already has a driver **
+        *            ** not sure we could ever get here... **
+        *          else
+        *            if (bus.match(dev,drv)) [visorbus_match]
+        *              dev.drv = drv
+        *              if (!drv.probe(dev))  [visordriver_probe_device]
+        *                dev.drv = NULL
+        *
+        * Note that device_add does NOT fail if no driver failed to claim the
+        * device.  The device will be linked onto bus_type.klist_devices
+        * regardless (use bus_for_each_dev).
+        */
+       err = device_add(&dev->device);
+       if (err < 0)
+               goto err_put;
+       list_add_tail(&dev->list_all, &list_all_device_instances);
+       dev->state.created = 1;
+       visorbus_response(dev, err, CONTROLVM_DEVICE_CREATE);
+       /* success: reference kept via unmatched get_device() */
+       return 0;
+
+err_put:
+       put_device(&dev->device);
+       dev_err(&dev->device, "Creating visor device failed. %d\n", err);
+       return err;
+}
+
+void remove_visor_device(struct visor_device *dev)
+{
+       list_del(&dev->list_all);
+       put_device(&dev->device);
+       if (dev->pending_msg_hdr)
+               visorbus_response(dev, 0, CONTROLVM_DEVICE_DESTROY);
+       device_unregister(&dev->device);
+}
+
+static int get_vbus_header_info(struct visorchannel *chan,
+                               struct device *dev,
+                               struct visor_vbus_headerinfo *hdr_info)
+{
+       int err;
+
+       if (!visor_check_channel(visorchannel_get_header(chan),
+                                dev,
+                                &visor_vbus_channel_guid,
+                                "vbus",
+                                sizeof(struct visor_vbus_channel),
+                                VISOR_VBUS_CHANNEL_VERSIONID,
+                                VISOR_CHANNEL_SIGNATURE))
+               return -EINVAL;
+
+       err = visorchannel_read(chan, sizeof(struct channel_header), hdr_info,
+                               sizeof(*hdr_info));
+       if (err < 0)
+               return err;
+       if (hdr_info->struct_bytes < sizeof(struct visor_vbus_headerinfo))
+               return -EINVAL;
+       if (hdr_info->device_info_struct_bytes <
+           sizeof(struct visor_vbus_deviceinfo))
+               return -EINVAL;
+       return 0;
+}
+
+/*
+ * write_vbus_chp_info() - write the contents of <info> to the struct
+ *                         visor_vbus_channel.chp_info
+ * @chan:     indentifies the s-Par channel that will be updated
+ * @hdr_info: used to find appropriate channel offset to write data
+ * @info:     contains the information to write
+ *
+ * Writes chipset info into the channel memory to be used for diagnostic
+ * purposes.
+ *
+ * Returns no value since this is debug information and not needed for
+ * device functionality.
+ */
+static void write_vbus_chp_info(struct visorchannel *chan,
+                               struct visor_vbus_headerinfo *hdr_info,
+                               struct visor_vbus_deviceinfo *info)
+{
+       int off;
+
+       if (hdr_info->chp_info_offset == 0)
+               return;
+
+       off = sizeof(struct channel_header) + hdr_info->chp_info_offset;
+       visorchannel_write(chan, off, info, sizeof(*info));
+}
+
+/*
+ * write_vbus_bus_info() - write the contents of <info> to the struct
+ *                         visor_vbus_channel.bus_info
+ * @chan:     indentifies the s-Par channel that will be updated
+ * @hdr_info: used to find appropriate channel offset to write data
+ * @info:     contains the information to write
+ *
+ * Writes bus info into the channel memory to be used for diagnostic
+ * purposes.
+ *
+ * Returns no value since this is debug information and not needed for
+ * device functionality.
+ */
+static void write_vbus_bus_info(struct visorchannel *chan,
+                               struct visor_vbus_headerinfo *hdr_info,
+                               struct visor_vbus_deviceinfo *info)
+{
+       int off;
+
+       if (hdr_info->bus_info_offset == 0)
+               return;
+
+       off = sizeof(struct channel_header) + hdr_info->bus_info_offset;
+       visorchannel_write(chan, off, info, sizeof(*info));
+}
+
+/*
+ * write_vbus_dev_info() - write the contents of <info> to the struct
+ *                         visor_vbus_channel.dev_info[<devix>]
+ * @chan:     indentifies the s-Par channel that will be updated
+ * @hdr_info: used to find appropriate channel offset to write data
+ * @info:     contains the information to write
+ * @devix:    the relative device number (0..n-1) of the device on the bus
+ *
+ * Writes device info into the channel memory to be used for diagnostic
+ * purposes.
+ *
+ * Returns no value since this is debug information and not needed for
+ * device functionality.
+ */
+static void write_vbus_dev_info(struct visorchannel *chan,
+                               struct visor_vbus_headerinfo *hdr_info,
+                               struct visor_vbus_deviceinfo *info,
+                               unsigned int devix)
+{
+       int off;
+
+       if (hdr_info->dev_info_offset == 0)
+               return;
+       off = (sizeof(struct channel_header) + hdr_info->dev_info_offset) +
+             (hdr_info->device_info_struct_bytes * devix);
+       visorchannel_write(chan, off, info, sizeof(*info));
+}
+
+static void bus_device_info_init(
+               struct visor_vbus_deviceinfo *bus_device_info_ptr,
+               const char *dev_type, const char *drv_name)
+{
+       memset(bus_device_info_ptr, 0, sizeof(struct visor_vbus_deviceinfo));
+       snprintf(bus_device_info_ptr->devtype,
+                sizeof(bus_device_info_ptr->devtype),
+                "%s", (dev_type) ? dev_type : "unknownType");
+       snprintf(bus_device_info_ptr->drvname,
+                sizeof(bus_device_info_ptr->drvname),
+                "%s", (drv_name) ? drv_name : "unknownDriver");
+       snprintf(bus_device_info_ptr->infostrs,
+                sizeof(bus_device_info_ptr->infostrs), "kernel ver. %s",
+                utsname()->release);
+}
+
+/*
+ * publish_vbus_dev_info() - for a child device just created on a client bus,
+ *                          fill in information about the driver that is
+ *                          controlling this device into the appropriate slot
+ *                          within the vbus channel of the bus instance
+ * @visordev: struct visor_device for the desired device
+ */
+static void publish_vbus_dev_info(struct visor_device *visordev)
+{
+       int i;
+       struct visor_device *bdev;
+       struct visor_driver *visordrv;
+       u32 bus_no = visordev->chipset_bus_no;
+       u32 dev_no = visordev->chipset_dev_no;
+       struct visor_vbus_deviceinfo dev_info;
+       const char *chan_type_name = NULL;
+       struct visor_vbus_headerinfo *hdr_info;
+
+       if (!visordev->device.driver)
+               return;
+       bdev = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+       if (!bdev)
+               return;
+       hdr_info = (struct visor_vbus_headerinfo *)bdev->vbus_hdr_info;
+       if (!hdr_info)
+               return;
+       visordrv = to_visor_driver(visordev->device.driver);
+
+       /*
+        * Within the list of device types (by GUID) that the driver
+        * says it supports, find out which one of those types matches
+        * the type of this device, so that we can include the device
+        * type name
+        */
+       for (i = 0; visordrv->channel_types[i].name; i++) {
+               if (guid_equal(&visordrv->channel_types[i].guid,
+                              &visordev->channel_type_guid)) {
+                       chan_type_name = visordrv->channel_types[i].name;
+                       break;
+               }
+       }
+       bus_device_info_init(&dev_info, chan_type_name, visordrv->name);
+       write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no);
+       write_vbus_chp_info(bdev->visorchannel, hdr_info, &chipset_driverinfo);
+       write_vbus_bus_info(bdev->visorchannel, hdr_info,
+                           &clientbus_driverinfo);
+}
+
+/*
+ * visordriver_probe_device() - handle new visor device coming online
+ * @xdev: struct device for the visor device being probed
+ *
+ * This is called automatically upon adding a visor_device (device_add), or
+ * adding a visor_driver (visorbus_register_visor_driver), but only after
+ * visorbus_match() has returned 1 to indicate a successful match between
+ * driver and device.
+ *
+ * If successful, a reference to the device will be held onto via get_device().
+ *
+ * Return: 0 if successful, meaning the function driver's probe() function
+ *         was successful with this device, otherwise a negative errno
+ *         value indicating failure reason
+ */
+static int visordriver_probe_device(struct device *xdev)
+{
+       int err;
+       struct visor_driver *drv = to_visor_driver(xdev->driver);
+       struct visor_device *dev = to_visor_device(xdev);
+
+       mutex_lock(&dev->visordriver_callback_lock);
+       dev->being_removed = false;
+       err = drv->probe(dev);
+       if (err) {
+               mutex_unlock(&dev->visordriver_callback_lock);
+               return err;
+       }
+       /* success: reference kept via unmatched get_device() */
+       get_device(&dev->device);
+       publish_vbus_dev_info(dev);
+       mutex_unlock(&dev->visordriver_callback_lock);
+       return 0;
+}
+
+/*
+ * visorbus_register_visor_driver() - registers the provided visor driver for
+ *                                   handling one or more visor device
+ *                                    types (channel_types)
+ * @drv: the driver to register
+ *
+ * A visor function driver calls this function to register the driver. The
+ * caller MUST fill in the following fields within the #drv structure:
+ *     name, version, owner, channel_types, probe, remove
+ *
+ * Here's how the whole Linux bus / driver / device model works.
+ *
+ * At system start-up, the visorbus kernel module is loaded, which registers
+ * visorbus_type as a bus type, using bus_register().
+ *
+ * All kernel modules that support particular device types on a
+ * visorbus bus are loaded.  Each of these kernel modules calls
+ * visorbus_register_visor_driver() in their init functions, passing a
+ * visor_driver struct.  visorbus_register_visor_driver() in turn calls
+ * register_driver(&visor_driver.driver).  This .driver member is
+ * initialized with generic methods (like probe), whose sole responsibility
+ * is to act as a broker for the real methods, which are within the
+ * visor_driver struct.  (This is the way the subclass behavior is
+ * implemented, since visor_driver is essentially a subclass of the
+ * generic driver.)  Whenever a driver_register() happens, core bus code in
+ * the kernel does (see device_attach() in drivers/base/dd.c):
+ *
+ *     for each dev associated with the bus (the bus that driver is on) that
+ *     does not yet have a driver
+ *         if bus.match(dev,newdriver) == yes_matched  ** .match specified
+ *                                                ** during bus_register().
+ *             newdriver.probe(dev)  ** for visor drivers, this will call
+ *                   ** the generic driver.probe implemented in visorbus.c,
+ *                   ** which in turn calls the probe specified within the
+ *                   ** struct visor_driver (which was specified by the
+ *                   ** actual device driver as part of
+ *                   ** visorbus_register_visor_driver()).
+ *
+ * The above dance also happens when a new device appears.
+ * So the question is, how are devices created within the system?
+ * Basically, just call device_add(dev).  See pci_bus_add_devices().
+ * pci_scan_device() shows an example of how to build a device struct.  It
+ * returns the newly-created struct to pci_scan_single_device(), who adds it
+ * to the list of devices at PCIBUS.devices.  That list of devices is what
+ * is traversed by pci_bus_add_devices().
+ *
+ * Return: integer indicating success (zero) or failure (non-zero)
+ */
+int visorbus_register_visor_driver(struct visor_driver *drv)
+{
+       /* can't register on a nonexistent bus */
+       if (!initialized)
+               return -ENODEV;
+       if (!drv->probe)
+               return -EINVAL;
+       if (!drv->remove)
+               return -EINVAL;
+       if (!drv->pause)
+               return -EINVAL;
+       if (!drv->resume)
+               return -EINVAL;
+
+       drv->driver.name = drv->name;
+       drv->driver.bus = &visorbus_type;
+       drv->driver.probe = visordriver_probe_device;
+       drv->driver.remove = visordriver_remove_device;
+       drv->driver.owner = drv->owner;
+       /*
+        * driver_register does this:
+        *   bus_add_driver(drv)
+        *   ->if (drv.bus)  ** (bus_type) **
+        *       driver_attach(drv)
+        *         for each dev with bus type of drv.bus
+        *           if (!dev.drv)  ** no driver assigned yet **
+        *             if (bus.match(dev,drv))  [visorbus_match]
+        *               dev.drv = drv
+        *               if (!drv.probe(dev))   [visordriver_probe_device]
+        *                 dev.drv = NULL
+        */
+       return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(visorbus_register_visor_driver);
+
+/*
+ * visorbus_create_instance() - create a device instance for the visorbus itself
+ * @dev: struct visor_device indicating the bus instance
+ *
+ * Return: 0 for success, otherwise negative errno value indicating reason for
+ *         failure
+ */
+int visorbus_create_instance(struct visor_device *dev)
+{
+       int id = dev->chipset_bus_no;
+       int err;
+       struct visor_vbus_headerinfo *hdr_info;
+
+       hdr_info = kzalloc(sizeof(*hdr_info), GFP_KERNEL);
+       if (!hdr_info)
+               return -ENOMEM;
+       dev_set_name(&dev->device, "visorbus%d", id);
+       dev->device.bus = &visorbus_type;
+       dev->device.groups = visorbus_groups;
+       dev->device.release = visorbus_release_busdevice;
+       dev->debugfs_dir = debugfs_create_dir(dev_name(&dev->device),
+                                             visorbus_debugfs_dir);
+       dev->debugfs_bus_info = debugfs_create_file("client_bus_info", 0440,
+                                                   dev->debugfs_dir, dev,
+                                                   &bus_info_debugfs_fops);
+       dev_set_drvdata(&dev->device, dev);
+       err = get_vbus_header_info(dev->visorchannel, &dev->device, hdr_info);
+       if (err < 0)
+               goto err_debugfs_dir;
+       err = device_register(&dev->device);
+       if (err < 0)
+               goto err_debugfs_dir;
+       list_add_tail(&dev->list_all, &list_all_bus_instances);
+       dev->state.created = 1;
+       dev->vbus_hdr_info = (void *)hdr_info;
+       write_vbus_chp_info(dev->visorchannel, hdr_info, &chipset_driverinfo);
+       write_vbus_bus_info(dev->visorchannel, hdr_info, &clientbus_driverinfo);
+       visorbus_response(dev, err, CONTROLVM_BUS_CREATE);
+       return 0;
+
+err_debugfs_dir:
+       debugfs_remove_recursive(dev->debugfs_dir);
+       kfree(hdr_info);
+       dev_err(&dev->device, "%s failed: %d\n", __func__, err);
+       return err;
+}
+
+/*
+ * visorbus_remove_instance() - remove a device instance for the visorbus itself
+ * @dev: struct visor_device indentifying the bus to remove
+ */
+void visorbus_remove_instance(struct visor_device *dev)
+{
+       /*
+        * Note that this will result in the release method for
+        * dev->dev being called, which will call
+        * visorbus_release_busdevice().  This has something to do with
+        * the put_device() done in device_unregister(), but I have never
+        * successfully been able to trace thru the code to see where/how
+        * release() gets called.  But I know it does.
+        */
+       kfree(dev->vbus_hdr_info);
+       list_del(&dev->list_all);
+       if (dev->pending_msg_hdr)
+               visorbus_response(dev, 0, CONTROLVM_BUS_DESTROY);
+       device_unregister(&dev->device);
+}
+
+/*
+ * remove_all_visor_devices() - remove all child visorbus device instances
+ */
+static void remove_all_visor_devices(void)
+{
+       struct list_head *listentry, *listtmp;
+
+       list_for_each_safe(listentry, listtmp, &list_all_device_instances) {
+               struct visor_device *dev;
+
+               dev = list_entry(listentry, struct visor_device, list_all);
+               remove_visor_device(dev);
+       }
+}
+
+/*
+ * pause_state_change_complete() - the callback function to be called by a
+ *                                 visorbus function driver when a
+ *                                 pending "pause device" operation has
+ *                                 completed
+ * @dev: struct visor_device identifying the paused device
+ * @status: 0 iff the pause state change completed successfully, otherwise
+ *          a negative errno value indicating the reason for failure
+ */
+static void pause_state_change_complete(struct visor_device *dev, int status)
+{
+       if (!dev->pausing)
+               return;
+
+       dev->pausing = false;
+       visorbus_device_changestate_response(dev, status,
+                                            segment_state_standby);
+}
+
+/*
+ * resume_state_change_complete() - the callback function to be called by a
+ *                                  visorbus function driver when a
+ *                                  pending "resume device" operation has
+ *                                  completed
+ * @dev: struct visor_device identifying the resumed device
+ * @status: 0 iff the resume state change completed successfully, otherwise
+ *          a negative errno value indicating the reason for failure
+ */
+static void resume_state_change_complete(struct visor_device *dev, int status)
+{
+       if (!dev->resuming)
+               return;
+
+       dev->resuming = false;
+       /*
+        * Notify the chipset driver that the resume is complete,
+        * which will presumably want to send some sort of response to
+        * the initiator.
+        */
+       visorbus_device_changestate_response(dev, status,
+                                            segment_state_running);
+}
+
+/*
+ * visorchipset_initiate_device_pause_resume() - start a pause or resume
+ *                                               operation for a visor device
+ * @dev: struct visor_device identifying the device being paused or resumed
+ * @is_pause: true to indicate pause operation, false to indicate resume
+ *
+ * Tell the subordinate function driver for a specific device to pause
+ * or resume that device.  Success/failure result is returned asynchronously
+ * via a callback function; see pause_state_change_complete() and
+ * resume_state_change_complete().
+ */
+static int visorchipset_initiate_device_pause_resume(struct visor_device *dev,
+                                                    bool is_pause)
+{
+       int err;
+       struct visor_driver *drv;
+
+       /* If no driver associated with the device nothing to pause/resume */
+       if (!dev->device.driver)
+               return 0;
+       if (dev->pausing || dev->resuming)
+               return -EBUSY;
+
+       drv = to_visor_driver(dev->device.driver);
+       if (is_pause) {
+               dev->pausing = true;
+               err = drv->pause(dev, pause_state_change_complete);
+       } else {
+               /*
+                * The vbus_dev_info structure in the channel was been cleared,
+                * make sure it is valid.
+                */
+               publish_vbus_dev_info(dev);
+               dev->resuming = true;
+               err = drv->resume(dev, resume_state_change_complete);
+       }
+       return err;
+}
+
+/*
+ * visorchipset_device_pause() - start a pause operation for a visor device
+ * @dev_info: struct visor_device identifying the device being paused
+ *
+ * Tell the subordinate function driver for a specific device to pause
+ * that device.  Success/failure result is returned asynchronously
+ * via a callback function; see pause_state_change_complete().
+ */
+int visorchipset_device_pause(struct visor_device *dev_info)
+{
+       int err;
+
+       err = visorchipset_initiate_device_pause_resume(dev_info, true);
+       if (err < 0) {
+               dev_info->pausing = false;
+               return err;
+       }
+       return 0;
+}
+
+/*
+ * visorchipset_device_resume() - start a resume operation for a visor device
+ * @dev_info: struct visor_device identifying the device being resumed
+ *
+ * Tell the subordinate function driver for a specific device to resume
+ * that device.  Success/failure result is returned asynchronously
+ * via a callback function; see resume_state_change_complete().
+ */
+int visorchipset_device_resume(struct visor_device *dev_info)
+{
+       int err;
+
+       err = visorchipset_initiate_device_pause_resume(dev_info, false);
+       if (err < 0) {
+               dev_info->resuming = false;
+               return err;
+       }
+       return 0;
+}
+
+int visorbus_init(void)
+{
+       int err;
+
+       visorbus_debugfs_dir = debugfs_create_dir("visorbus", NULL);
+       bus_device_info_init(&clientbus_driverinfo, "clientbus", "visorbus");
+       err = bus_register(&visorbus_type);
+       if (err < 0)
+               return err;
+       initialized = true;
+       bus_device_info_init(&chipset_driverinfo, "chipset", "visorchipset");
+       return 0;
+}
+
+void visorbus_exit(void)
+{
+       struct list_head *listentry, *listtmp;
+
+       remove_all_visor_devices();
+       list_for_each_safe(listentry, listtmp, &list_all_bus_instances) {
+               struct visor_device *dev;
+
+               dev = list_entry(listentry, struct visor_device, list_all);
+               visorbus_remove_instance(dev);
+       }
+       bus_unregister(&visorbus_type);
+       initialized = false;
+       debugfs_remove_recursive(visorbus_debugfs_dir);
+}
diff --git a/drivers/visorbus/visorbus_private.h b/drivers/visorbus/visorbus_private.h
new file mode 100644 (file)
index 0000000..366380b
--- /dev/null
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ */
+
+#ifndef __VISORBUS_PRIVATE_H__
+#define __VISORBUS_PRIVATE_H__
+
+#include <linux/uuid.h>
+#include <linux/utsname.h>
+#include <linux/visorbus.h>
+
+#include "controlvmchannel.h"
+#include "vbuschannel.h"
+
+struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
+                                              struct visor_device *from);
+int visorbus_create_instance(struct visor_device *dev);
+void visorbus_remove_instance(struct visor_device *bus_info);
+int create_visor_device(struct visor_device *dev_info);
+void remove_visor_device(struct visor_device *dev_info);
+int visorchipset_device_pause(struct visor_device *dev_info);
+int visorchipset_device_resume(struct visor_device *dev_info);
+void visorbus_response(struct visor_device *p, int response, int controlvm_id);
+void visorbus_device_changestate_response(struct visor_device *p, int response,
+                                         struct visor_segment_state state);
+int visorbus_init(void);
+void visorbus_exit(void);
+
+/* visorchannel access functions */
+struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
+                                        const guid_t *guid, bool needs_lock);
+void visorchannel_destroy(struct visorchannel *channel);
+int visorchannel_read(struct visorchannel *channel, ulong offset,
+                     void *dest, ulong nbytes);
+int visorchannel_write(struct visorchannel *channel, ulong offset,
+                      void *dest, ulong nbytes);
+u64 visorchannel_get_physaddr(struct visorchannel *channel);
+ulong visorchannel_get_nbytes(struct visorchannel *channel);
+char *visorchannel_id(struct visorchannel *channel, char *s);
+char *visorchannel_zoneid(struct visorchannel *channel, char *s);
+u64 visorchannel_get_clientpartition(struct visorchannel *channel);
+int visorchannel_set_clientpartition(struct visorchannel *channel,
+                                    u64 partition_handle);
+char *visorchannel_guid_id(const guid_t *guid, char *s);
+void *visorchannel_get_header(struct visorchannel *channel);
+#endif
diff --git a/drivers/visorbus/visorchannel.c b/drivers/visorbus/visorchannel.c
new file mode 100644 (file)
index 0000000..bd890e0
--- /dev/null
@@ -0,0 +1,434 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ */
+
+/*
+ *  This provides s-Par channel communication primitives, which are
+ *  independent of the mechanism used to access the channel data.
+ */
+
+#include <linux/uuid.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/visorbus.h>
+
+#include "visorbus_private.h"
+#include "controlvmchannel.h"
+
+#define VISOR_DRV_NAME "visorchannel"
+
+#define VISOR_CONSOLEVIDEO_CHANNEL_GUID \
+       GUID_INIT(0x3cd6e705, 0xd6a2, 0x4aa5, \
+                 0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
+
+static const guid_t visor_video_guid = VISOR_CONSOLEVIDEO_CHANNEL_GUID;
+
+struct visorchannel {
+       u64 physaddr;
+       ulong nbytes;
+       void *mapped;
+       bool requested;
+       struct channel_header chan_hdr;
+       guid_t guid;
+       /*
+        * channel creator knows if more than one thread will be inserting or
+        * removing
+        */
+       bool needs_lock;
+       /* protect head writes in chan_hdr */
+       spinlock_t insert_lock;
+       /* protect tail writes in chan_hdr */
+       spinlock_t remove_lock;
+       guid_t type;
+       guid_t inst;
+};
+
+void visorchannel_destroy(struct visorchannel *channel)
+{
+       if (!channel)
+               return;
+
+       if (channel->mapped) {
+               memunmap(channel->mapped);
+               if (channel->requested)
+                       release_mem_region(channel->physaddr, channel->nbytes);
+       }
+       kfree(channel);
+}
+
+u64 visorchannel_get_physaddr(struct visorchannel *channel)
+{
+       return channel->physaddr;
+}
+
+ulong visorchannel_get_nbytes(struct visorchannel *channel)
+{
+       return channel->nbytes;
+}
+
+char *visorchannel_guid_id(const guid_t *guid, char *s)
+{
+       sprintf(s, "%pUL", guid);
+       return s;
+}
+
+char *visorchannel_id(struct visorchannel *channel, char *s)
+{
+       return visorchannel_guid_id(&channel->guid, s);
+}
+
+char *visorchannel_zoneid(struct visorchannel *channel, char *s)
+{
+       return visorchannel_guid_id(&channel->chan_hdr.zone_guid, s);
+}
+
+u64 visorchannel_get_clientpartition(struct visorchannel *channel)
+{
+       return channel->chan_hdr.partition_handle;
+}
+
+int visorchannel_set_clientpartition(struct visorchannel *channel,
+                                    u64 partition_handle)
+{
+       channel->chan_hdr.partition_handle = partition_handle;
+       return 0;
+}
+
+/**
+ * visorchannel_get_guid() - queries the GUID of the designated channel
+ * @channel: the channel to query
+ *
+ * Return: the GUID of the provided channel
+ */
+const guid_t *visorchannel_get_guid(struct visorchannel *channel)
+{
+       return &channel->guid;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_guid);
+
+int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest,
+                     ulong nbytes)
+{
+       if (offset + nbytes > channel->nbytes)
+               return -EIO;
+
+       memcpy(dest, channel->mapped + offset, nbytes);
+       return 0;
+}
+
+int visorchannel_write(struct visorchannel *channel, ulong offset, void *dest,
+                      ulong nbytes)
+{
+       size_t chdr_size = sizeof(struct channel_header);
+       size_t copy_size;
+
+       if (offset + nbytes > channel->nbytes)
+               return -EIO;
+
+       if (offset < chdr_size) {
+               copy_size = min(chdr_size - offset, nbytes);
+               memcpy(((char *)(&channel->chan_hdr)) + offset,
+                      dest, copy_size);
+       }
+       memcpy(channel->mapped + offset, dest, nbytes);
+       return 0;
+}
+
+void *visorchannel_get_header(struct visorchannel *channel)
+{
+       return &channel->chan_hdr;
+}
+
+/*
+ * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
+ * channel header
+ */
+static int sig_queue_offset(struct channel_header *chan_hdr, int q)
+{
+       return ((chan_hdr)->ch_space_offset +
+              ((q) * sizeof(struct signal_queue_header)));
+}
+
+/*
+ * Return offset of a specific queue entry (data) from the beginning of a
+ * channel header
+ */
+static int sig_data_offset(struct channel_header *chan_hdr, int q,
+                          struct signal_queue_header *sig_hdr, int slot)
+{
+       return (sig_queue_offset(chan_hdr, q) + sig_hdr->sig_base_offset +
+              (slot * sig_hdr->signal_size));
+}
+
+/*
+ * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back into
+ * host memory
+ */
+#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \
+       visorchannel_write(channel, \
+                          sig_queue_offset(&channel->chan_hdr, queue) + \
+                          offsetof(struct signal_queue_header, FIELD), \
+                          &((sig_hdr)->FIELD), \
+                          sizeof((sig_hdr)->FIELD))
+
+static int sig_read_header(struct visorchannel *channel, u32 queue,
+                          struct signal_queue_header *sig_hdr)
+{
+       if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
+               return -EINVAL;
+
+       /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
+       return visorchannel_read(channel,
+                                sig_queue_offset(&channel->chan_hdr, queue),
+                                sig_hdr, sizeof(struct signal_queue_header));
+}
+
+static int sig_read_data(struct visorchannel *channel, u32 queue,
+                        struct signal_queue_header *sig_hdr, u32 slot,
+                        void *data)
+{
+       int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
+                                                sig_hdr, slot);
+
+       return visorchannel_read(channel, signal_data_offset,
+                                data, sig_hdr->signal_size);
+}
+
+static int sig_write_data(struct visorchannel *channel, u32 queue,
+                         struct signal_queue_header *sig_hdr, u32 slot,
+                         void *data)
+{
+       int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
+                                                sig_hdr, slot);
+
+       return visorchannel_write(channel, signal_data_offset,
+                                 data, sig_hdr->signal_size);
+}
+
+static int signalremove_inner(struct visorchannel *channel, u32 queue,
+                             void *msg)
+{
+       struct signal_queue_header sig_hdr;
+       int error;
+
+       error = sig_read_header(channel, queue, &sig_hdr);
+       if (error)
+               return error;
+       /* No signals to remove; have caller try again. */
+       if (sig_hdr.head == sig_hdr.tail)
+               return -EAGAIN;
+       sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
+       error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg);
+       if (error)
+               return error;
+       sig_hdr.num_received++;
+       /*
+        * For each data field in SIGNAL_QUEUE_HEADER that was modified, update
+        * host memory. Required for channel sync.
+        */
+       mb();
+       error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail);
+       if (error)
+               return error;
+       error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received);
+       if (error)
+               return error;
+       return 0;
+}
+
+/**
+ * visorchannel_signalremove() - removes a message from the designated
+ *                               channel/queue
+ * @channel: the channel the message will be removed from
+ * @queue:   the queue the message will be removed from
+ * @msg:     the message to remove
+ *
+ * Return: integer error code indicating the status of the removal
+ */
+int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
+                             void *msg)
+{
+       int rc;
+       unsigned long flags;
+
+       if (channel->needs_lock) {
+               spin_lock_irqsave(&channel->remove_lock, flags);
+               rc = signalremove_inner(channel, queue, msg);
+               spin_unlock_irqrestore(&channel->remove_lock, flags);
+       } else {
+               rc = signalremove_inner(channel, queue, msg);
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalremove);
+
+static bool queue_empty(struct visorchannel *channel, u32 queue)
+{
+       struct signal_queue_header sig_hdr;
+
+       if (sig_read_header(channel, queue, &sig_hdr))
+               return true;
+       return (sig_hdr.head == sig_hdr.tail);
+}
+
+/**
+ * visorchannel_signalempty() - checks if the designated channel/queue contains
+ *                             any messages
+ * @channel: the channel to query
+ * @queue:   the queue in the channel to query
+ *
+ * Return: boolean indicating whether any messages in the designated
+ *         channel/queue are present
+ */
+bool visorchannel_signalempty(struct visorchannel *channel, u32 queue)
+{
+       bool rc;
+       unsigned long flags;
+
+       if (!channel->needs_lock)
+               return queue_empty(channel, queue);
+       spin_lock_irqsave(&channel->remove_lock, flags);
+       rc = queue_empty(channel, queue);
+       spin_unlock_irqrestore(&channel->remove_lock, flags);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalempty);
+
+static int signalinsert_inner(struct visorchannel *channel, u32 queue,
+                             void *msg)
+{
+       struct signal_queue_header sig_hdr;
+       int err;
+
+       err = sig_read_header(channel, queue, &sig_hdr);
+       if (err)
+               return err;
+       sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots;
+       if (sig_hdr.head == sig_hdr.tail) {
+               sig_hdr.num_overflows++;
+               err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows);
+               if (err)
+                       return err;
+               return -EIO;
+       }
+       err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg);
+       if (err)
+               return err;
+       sig_hdr.num_sent++;
+       /*
+        * For each data field in SIGNAL_QUEUE_HEADER that was modified, update
+        * host memory. Required for channel sync.
+        */
+       mb();
+       err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head);
+       if (err)
+               return err;
+       err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent);
+       if (err)
+               return err;
+       return 0;
+}
+
+/*
+ * visorchannel_create() - creates the struct visorchannel abstraction for a
+ *                         data area in memory, but does NOT modify this data
+ *                         area
+ * @physaddr:      physical address of start of channel
+ * @gfp:           gfp_t to use when allocating memory for the data struct
+ * @guid:          GUID that identifies channel type;
+ * @needs_lock:    must specify true if you have multiple threads of execution
+ *                 that will be calling visorchannel methods of this
+ *                 visorchannel at the same time
+ *
+ * Return: pointer to visorchannel that was created if successful,
+ *         otherwise NULL
+ */
+struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
+                                        const guid_t *guid, bool needs_lock)
+{
+       struct visorchannel *channel;
+       int err;
+       size_t size = sizeof(struct channel_header);
+
+       if (physaddr == 0)
+               return NULL;
+
+       channel = kzalloc(sizeof(*channel), gfp);
+       if (!channel)
+               return NULL;
+       channel->needs_lock = needs_lock;
+       spin_lock_init(&channel->insert_lock);
+       spin_lock_init(&channel->remove_lock);
+       /*
+        * Video driver constains the efi framebuffer so it will get a conflict
+        * resource when requesting its full mem region. Since we are only
+        * using the efi framebuffer for video we can ignore this. Remember that
+        * we haven't requested it so we don't try to release later on.
+        */
+       channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME);
+       if (!channel->requested && !guid_equal(guid, &visor_video_guid))
+               /* we only care about errors if this is not the video channel */
+               goto err_destroy_channel;
+       channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
+       if (!channel->mapped) {
+               release_mem_region(physaddr, size);
+               goto err_destroy_channel;
+       }
+       channel->physaddr = physaddr;
+       channel->nbytes = size;
+       err = visorchannel_read(channel, 0, &channel->chan_hdr, size);
+       if (err)
+               goto err_destroy_channel;
+       size = (ulong)channel->chan_hdr.size;
+       memunmap(channel->mapped);
+       if (channel->requested)
+               release_mem_region(channel->physaddr, channel->nbytes);
+       channel->mapped = NULL;
+       channel->requested = request_mem_region(channel->physaddr, size,
+                                               VISOR_DRV_NAME);
+       if (!channel->requested && !guid_equal(guid, &visor_video_guid))
+               /* we only care about errors if this is not the video channel */
+               goto err_destroy_channel;
+       channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB);
+       if (!channel->mapped) {
+               release_mem_region(channel->physaddr, size);
+               goto err_destroy_channel;
+       }
+       channel->nbytes = size;
+       guid_copy(&channel->guid, guid);
+       return channel;
+
+err_destroy_channel:
+       visorchannel_destroy(channel);
+       return NULL;
+}
+
+/**
+ * visorchannel_signalinsert() - inserts a message into the designated
+ *                               channel/queue
+ * @channel: the channel the message will be added to
+ * @queue:   the queue the message will be added to
+ * @msg:     the message to insert
+ *
+ * Return: integer error code indicating the status of the insertion
+ */
+int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
+                             void *msg)
+{
+       int rc;
+       unsigned long flags;
+
+       if (channel->needs_lock) {
+               spin_lock_irqsave(&channel->insert_lock, flags);
+               rc = signalinsert_inner(channel, queue, msg);
+               spin_unlock_irqrestore(&channel->insert_lock, flags);
+       } else {
+               rc = signalinsert_inner(channel, queue, msg);
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
diff --git a/drivers/visorbus/visorchipset.c b/drivers/visorbus/visorchipset.c
new file mode 100644 (file)
index 0000000..ca752b8
--- /dev/null
@@ -0,0 +1,1686 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ */
+
+#include <linux/acpi.h>
+#include <linux/crash_dump.h>
+#include <linux/visorbus.h>
+
+#include "visorbus_private.h"
+
+/* {72120008-4AAB-11DC-8530-444553544200} */
+#define VISOR_SIOVM_GUID GUID_INIT(0x72120008, 0x4AAB, 0x11DC, 0x85, 0x30, \
+                                  0x44, 0x45, 0x53, 0x54, 0x42, 0x00)
+
+static const guid_t visor_vhba_channel_guid = VISOR_VHBA_CHANNEL_GUID;
+static const guid_t visor_siovm_guid = VISOR_SIOVM_GUID;
+static const guid_t visor_controlvm_channel_guid = VISOR_CONTROLVM_CHANNEL_GUID;
+
+#define POLLJIFFIES_CONTROLVM_FAST 1
+#define POLLJIFFIES_CONTROLVM_SLOW 100
+
+#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
+
+#define UNISYS_VISOR_LEAF_ID 0x40000000
+
+/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
+#define UNISYS_VISOR_ID_EBX 0x73696e55
+#define UNISYS_VISOR_ID_ECX 0x70537379
+#define UNISYS_VISOR_ID_EDX 0x34367261
+
+/*
+ * When the controlvm channel is idle for at least MIN_IDLE_SECONDS, we switch
+ * to slow polling mode. As soon as we get a controlvm message, we switch back
+ * to fast polling mode.
+ */
+#define MIN_IDLE_SECONDS 10
+
+struct parser_context {
+       unsigned long allocbytes;
+       unsigned long param_bytes;
+       u8 *curr;
+       unsigned long bytes_remaining;
+       bool byte_stream;
+       struct visor_controlvm_parameters_header data;
+};
+
+/* VMCALL_CONTROLVM_ADDR: Used by all guests, not just IO. */
+#define VMCALL_CONTROLVM_ADDR 0x0501
+
+enum vmcall_result {
+       VMCALL_RESULT_SUCCESS = 0,
+       VMCALL_RESULT_INVALID_PARAM = 1,
+       VMCALL_RESULT_DATA_UNAVAILABLE = 2,
+       VMCALL_RESULT_FAILURE_UNAVAILABLE = 3,
+       VMCALL_RESULT_DEVICE_ERROR = 4,
+       VMCALL_RESULT_DEVICE_NOT_READY = 5
+};
+
+/*
+ * struct vmcall_io_controlvm_addr_params - Structure for IO VMCALLS. Has
+ *                                         parameters to VMCALL_CONTROLVM_ADDR
+ *                                         interface.
+ * @address:      The Guest-relative physical address of the ControlVm channel.
+ *                This VMCall fills this in with the appropriate address.
+ *                Contents provided by this VMCALL (OUT).
+ * @channel_bytes: The size of the ControlVm channel in bytes This VMCall fills
+ *                this in with the appropriate address. Contents provided by
+ *                this VMCALL (OUT).
+ * @unused:       Unused Bytes in the 64-Bit Aligned Struct.
+ */
+struct vmcall_io_controlvm_addr_params {
+       u64 address;
+       u32 channel_bytes;
+       u8 unused[4];
+} __packed;
+
+struct visorchipset_device {
+       struct acpi_device *acpi_device;
+       unsigned long poll_jiffies;
+       /* when we got our last controlvm message */
+       unsigned long most_recent_message_jiffies;
+       struct delayed_work periodic_controlvm_work;
+       struct visorchannel *controlvm_channel;
+       unsigned long controlvm_payload_bytes_buffered;
+       /*
+        * The following variables are used to handle the scenario where we are
+        * unable to offload the payload from a controlvm message due to memory
+        * requirements. In this scenario, we simply stash the controlvm
+        * message, then attempt to process it again the next time
+        * controlvm_periodic_work() runs.
+        */
+       struct controlvm_message controlvm_pending_msg;
+       bool controlvm_pending_msg_valid;
+       struct vmcall_io_controlvm_addr_params controlvm_params;
+};
+
+static struct visorchipset_device *chipset_dev;
+
+struct parahotplug_request {
+       struct list_head list;
+       int id;
+       unsigned long expiration;
+       struct controlvm_message msg;
+};
+
+/* prototypes for attributes */
+static ssize_t toolaction_show(struct device *dev,
+                              struct device_attribute *attr,
+                              char *buf)
+{
+       u8 tool_action = 0;
+       int err;
+
+       err = visorchannel_read(chipset_dev->controlvm_channel,
+                               offsetof(struct visor_controlvm_channel,
+                                        tool_action),
+                               &tool_action, sizeof(u8));
+       if (err)
+               return err;
+       return sprintf(buf, "%u\n", tool_action);
+}
+
+static ssize_t toolaction_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       u8 tool_action;
+       int err;
+
+       if (kstrtou8(buf, 10, &tool_action))
+               return -EINVAL;
+       err = visorchannel_write(chipset_dev->controlvm_channel,
+                                offsetof(struct visor_controlvm_channel,
+                                         tool_action),
+                                &tool_action, sizeof(u8));
+       if (err)
+               return err;
+       return count;
+}
+static DEVICE_ATTR_RW(toolaction);
+
+static ssize_t boottotool_show(struct device *dev,
+                              struct device_attribute *attr,
+                              char *buf)
+{
+       struct efi_visor_indication efi_visor_indication;
+       int err;
+
+       err = visorchannel_read(chipset_dev->controlvm_channel,
+                               offsetof(struct visor_controlvm_channel,
+                                        efi_visor_ind),
+                               &efi_visor_indication,
+                               sizeof(struct efi_visor_indication));
+       if (err)
+               return err;
+       return sprintf(buf, "%u\n", efi_visor_indication.boot_to_tool);
+}
+
+static ssize_t boottotool_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       int val, err;
+       struct efi_visor_indication efi_visor_indication;
+
+       if (kstrtoint(buf, 10, &val))
+               return -EINVAL;
+       efi_visor_indication.boot_to_tool = val;
+       err = visorchannel_write(chipset_dev->controlvm_channel,
+                                offsetof(struct visor_controlvm_channel,
+                                         efi_visor_ind),
+                                &(efi_visor_indication),
+                                sizeof(struct efi_visor_indication));
+       if (err)
+               return err;
+       return count;
+}
+static DEVICE_ATTR_RW(boottotool);
+
+static ssize_t error_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       u32 error = 0;
+       int err;
+
+       err = visorchannel_read(chipset_dev->controlvm_channel,
+                               offsetof(struct visor_controlvm_channel,
+                                        installation_error),
+                               &error, sizeof(u32));
+       if (err)
+               return err;
+       return sprintf(buf, "%u\n", error);
+}
+
+static ssize_t error_store(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       u32 error;
+       int err;
+
+       if (kstrtou32(buf, 10, &error))
+               return -EINVAL;
+       err = visorchannel_write(chipset_dev->controlvm_channel,
+                                offsetof(struct visor_controlvm_channel,
+                                         installation_error),
+                                &error, sizeof(u32));
+       if (err)
+               return err;
+       return count;
+}
+static DEVICE_ATTR_RW(error);
+
+static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
+                          char *buf)
+{
+       u32 text_id = 0;
+       int err;
+
+       err = visorchannel_read(chipset_dev->controlvm_channel,
+                               offsetof(struct visor_controlvm_channel,
+                                        installation_text_id),
+                               &text_id, sizeof(u32));
+       if (err)
+               return err;
+       return sprintf(buf, "%u\n", text_id);
+}
+
+static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       u32 text_id;
+       int err;
+
+       if (kstrtou32(buf, 10, &text_id))
+               return -EINVAL;
+       err = visorchannel_write(chipset_dev->controlvm_channel,
+                                offsetof(struct visor_controlvm_channel,
+                                         installation_text_id),
+                                &text_id, sizeof(u32));
+       if (err)
+               return err;
+       return count;
+}
+static DEVICE_ATTR_RW(textid);
+
+static ssize_t remaining_steps_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       u16 remaining_steps = 0;
+       int err;
+
+       err = visorchannel_read(chipset_dev->controlvm_channel,
+                               offsetof(struct visor_controlvm_channel,
+                                        installation_remaining_steps),
+                               &remaining_steps, sizeof(u16));
+       if (err)
+               return err;
+       return sprintf(buf, "%hu\n", remaining_steps);
+}
+
+static ssize_t remaining_steps_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       u16 remaining_steps;
+       int err;
+
+       if (kstrtou16(buf, 10, &remaining_steps))
+               return -EINVAL;
+       err = visorchannel_write(chipset_dev->controlvm_channel,
+                                offsetof(struct visor_controlvm_channel,
+                                         installation_remaining_steps),
+                                &remaining_steps, sizeof(u16));
+       if (err)
+               return err;
+       return count;
+}
+static DEVICE_ATTR_RW(remaining_steps);
+
+static void controlvm_init_response(struct controlvm_message *msg,
+                                   struct controlvm_message_header *msg_hdr,
+                                   int response)
+{
+       memset(msg, 0, sizeof(struct controlvm_message));
+       memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
+       msg->hdr.payload_bytes = 0;
+       msg->hdr.payload_vm_offset = 0;
+       msg->hdr.payload_max_bytes = 0;
+       if (response < 0) {
+               msg->hdr.flags.failed = 1;
+               msg->hdr.completion_status = (u32)(-response);
+       }
+}
+
+static int controlvm_respond_chipset_init(
+                               struct controlvm_message_header *msg_hdr,
+                               int response,
+                               enum visor_chipset_feature features)
+{
+       struct controlvm_message outmsg;
+
+       controlvm_init_response(&outmsg, msg_hdr, response);
+       outmsg.cmd.init_chipset.features = features;
+       return visorchannel_signalinsert(chipset_dev->controlvm_channel,
+                                        CONTROLVM_QUEUE_REQUEST, &outmsg);
+}
+
+static int chipset_init(struct controlvm_message *inmsg)
+{
+       static int chipset_inited;
+       enum visor_chipset_feature features = 0;
+       int rc = CONTROLVM_RESP_SUCCESS;
+       int res = 0;
+
+       if (chipset_inited) {
+               rc = -CONTROLVM_RESP_ALREADY_DONE;
+               res = -EIO;
+               goto out_respond;
+       }
+       chipset_inited = 1;
+       /*
+        * Set features to indicate we support parahotplug (if Command also
+        * supports it). Set the "reply" bit so Command knows this is a
+        * features-aware driver.
+        */
+       features = inmsg->cmd.init_chipset.features &
+                  VISOR_CHIPSET_FEATURE_PARA_HOTPLUG;
+       features |= VISOR_CHIPSET_FEATURE_REPLY;
+
+out_respond:
+       if (inmsg->hdr.flags.response_expected)
+               res = controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
+
+       return res;
+}
+
+static int controlvm_respond(struct controlvm_message_header *msg_hdr,
+                            int response, struct visor_segment_state *state)
+{
+       struct controlvm_message outmsg;
+
+       controlvm_init_response(&outmsg, msg_hdr, response);
+       if (outmsg.hdr.flags.test_message == 1)
+               return -EINVAL;
+       if (state) {
+               outmsg.cmd.device_change_state.state = *state;
+               outmsg.cmd.device_change_state.flags.phys_device = 1;
+       }
+       return visorchannel_signalinsert(chipset_dev->controlvm_channel,
+                                        CONTROLVM_QUEUE_REQUEST, &outmsg);
+}
+
+enum crash_obj_type {
+       CRASH_DEV,
+       CRASH_BUS,
+};
+
+static int save_crash_message(struct controlvm_message *msg,
+                             enum crash_obj_type cr_type)
+{
+       u32 local_crash_msg_offset;
+       u16 local_crash_msg_count;
+       int err;
+
+       err = visorchannel_read(chipset_dev->controlvm_channel,
+                               offsetof(struct visor_controlvm_channel,
+                                        saved_crash_message_count),
+                               &local_crash_msg_count, sizeof(u16));
+       if (err) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed to read message count\n");
+               return err;
+       }
+       if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "invalid number of messages\n");
+               return -EIO;
+       }
+       err = visorchannel_read(chipset_dev->controlvm_channel,
+                               offsetof(struct visor_controlvm_channel,
+                                        saved_crash_message_offset),
+                               &local_crash_msg_offset, sizeof(u32));
+       if (err) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed to read offset\n");
+               return err;
+       }
+       switch (cr_type) {
+       case CRASH_DEV:
+               local_crash_msg_offset += sizeof(struct controlvm_message);
+               err = visorchannel_write(chipset_dev->controlvm_channel,
+                                        local_crash_msg_offset, msg,
+                                        sizeof(struct controlvm_message));
+               if (err) {
+                       dev_err(&chipset_dev->acpi_device->dev,
+                               "failed to write dev msg\n");
+                       return err;
+               }
+               break;
+       case CRASH_BUS:
+               err = visorchannel_write(chipset_dev->controlvm_channel,
+                                        local_crash_msg_offset, msg,
+                                        sizeof(struct controlvm_message));
+               if (err) {
+                       dev_err(&chipset_dev->acpi_device->dev,
+                               "failed to write bus msg\n");
+                       return err;
+               }
+               break;
+       default:
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "Invalid crash_obj_type\n");
+               break;
+       }
+       return 0;
+}
+
+static int controlvm_responder(enum controlvm_id cmd_id,
+                              struct controlvm_message_header *pending_msg_hdr,
+                              int response)
+{
+       if (pending_msg_hdr->id != (u32)cmd_id)
+               return -EINVAL;
+
+       return controlvm_respond(pending_msg_hdr, response, NULL);
+}
+
+static int device_changestate_responder(enum controlvm_id cmd_id,
+                                       struct visor_device *p, int response,
+                                       struct visor_segment_state state)
+{
+       struct controlvm_message outmsg;
+
+       if (p->pending_msg_hdr->id != cmd_id)
+               return -EINVAL;
+
+       controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
+       outmsg.cmd.device_change_state.bus_no = p->chipset_bus_no;
+       outmsg.cmd.device_change_state.dev_no = p->chipset_dev_no;
+       outmsg.cmd.device_change_state.state = state;
+       return visorchannel_signalinsert(chipset_dev->controlvm_channel,
+                                        CONTROLVM_QUEUE_REQUEST, &outmsg);
+}
+
+static int visorbus_create(struct controlvm_message *inmsg)
+{
+       struct controlvm_message_packet *cmd = &inmsg->cmd;
+       struct controlvm_message_header *pmsg_hdr;
+       u32 bus_no = cmd->create_bus.bus_no;
+       struct visor_device *bus_info;
+       struct visorchannel *visorchannel;
+       int err;
+
+       bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+       if (bus_info && bus_info->state.created == 1) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed %s: already exists\n", __func__);
+               err = -EEXIST;
+               goto err_respond;
+       }
+       bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
+       if (!bus_info) {
+               err = -ENOMEM;
+               goto err_respond;
+       }
+       INIT_LIST_HEAD(&bus_info->list_all);
+       bus_info->chipset_bus_no = bus_no;
+       bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
+       if (guid_equal(&cmd->create_bus.bus_inst_guid, &visor_siovm_guid)) {
+               err = save_crash_message(inmsg, CRASH_BUS);
+               if (err)
+                       goto err_free_bus_info;
+       }
+       if (inmsg->hdr.flags.response_expected == 1) {
+               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
+               if (!pmsg_hdr) {
+                       err = -ENOMEM;
+                       goto err_free_bus_info;
+               }
+               memcpy(pmsg_hdr, &inmsg->hdr,
+                      sizeof(struct controlvm_message_header));
+               bus_info->pending_msg_hdr = pmsg_hdr;
+       }
+       visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
+                                          GFP_KERNEL,
+                                          &cmd->create_bus.bus_data_type_guid,
+                                          false);
+       if (!visorchannel) {
+               err = -ENOMEM;
+               goto err_free_pending_msg;
+       }
+       bus_info->visorchannel = visorchannel;
+       /* Response will be handled by visorbus_create_instance on success */
+       err = visorbus_create_instance(bus_info);
+       if (err)
+               goto err_destroy_channel;
+       return 0;
+
+err_destroy_channel:
+       visorchannel_destroy(visorchannel);
+
+err_free_pending_msg:
+       kfree(bus_info->pending_msg_hdr);
+
+err_free_bus_info:
+       kfree(bus_info);
+
+err_respond:
+       if (inmsg->hdr.flags.response_expected == 1)
+               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
+       return err;
+}
+
+static int visorbus_destroy(struct controlvm_message *inmsg)
+{
+       struct controlvm_message_header *pmsg_hdr;
+       u32 bus_no = inmsg->cmd.destroy_bus.bus_no;
+       struct visor_device *bus_info;
+       int err;
+
+       bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+       if (!bus_info) {
+               err = -ENODEV;
+               goto err_respond;
+       }
+       if (bus_info->state.created == 0) {
+               err = -ENOENT;
+               goto err_respond;
+       }
+       if (bus_info->pending_msg_hdr) {
+               /* only non-NULL if dev is still waiting on a response */
+               err = -EEXIST;
+               goto err_respond;
+       }
+       if (inmsg->hdr.flags.response_expected == 1) {
+               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
+               if (!pmsg_hdr) {
+                       err = -ENOMEM;
+                       goto err_respond;
+               }
+               memcpy(pmsg_hdr, &inmsg->hdr,
+                      sizeof(struct controlvm_message_header));
+               bus_info->pending_msg_hdr = pmsg_hdr;
+       }
+       /* Response will be handled by visorbus_remove_instance */
+       visorbus_remove_instance(bus_info);
+       return 0;
+
+err_respond:
+       if (inmsg->hdr.flags.response_expected == 1)
+               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
+       return err;
+}
+
+static const guid_t *parser_id_get(struct parser_context *ctx)
+{
+       return &ctx->data.id;
+}
+
+static void *parser_string_get(u8 *pscan, int nscan)
+{
+       int value_length;
+       void *value;
+
+       if (nscan == 0)
+               return NULL;
+
+       value_length = strnlen(pscan, nscan);
+       value = kzalloc(value_length + 1, GFP_KERNEL);
+       if (!value)
+               return NULL;
+       if (value_length > 0)
+               memcpy(value, pscan, value_length);
+       return value;
+}
+
+static void *parser_name_get(struct parser_context *ctx)
+{
+       struct visor_controlvm_parameters_header *phdr;
+
+       phdr = &ctx->data;
+       if ((unsigned long)phdr->name_offset +
+           (unsigned long)phdr->name_length > ctx->param_bytes)
+               return NULL;
+       ctx->curr = (char *)&phdr + phdr->name_offset;
+       ctx->bytes_remaining = phdr->name_length;
+       return parser_string_get(ctx->curr, phdr->name_length);
+}
+
+static int visorbus_configure(struct controlvm_message *inmsg,
+                             struct parser_context *parser_ctx)
+{
+       struct controlvm_message_packet *cmd = &inmsg->cmd;
+       u32 bus_no;
+       struct visor_device *bus_info;
+       int err = 0;
+
+       bus_no = cmd->configure_bus.bus_no;
+       bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+       if (!bus_info) {
+               err = -EINVAL;
+               goto err_respond;
+       }
+       if (bus_info->state.created == 0) {
+               err = -EINVAL;
+               goto err_respond;
+       }
+       if (bus_info->pending_msg_hdr) {
+               err = -EIO;
+               goto err_respond;
+       }
+       err = visorchannel_set_clientpartition(bus_info->visorchannel,
+                                              cmd->configure_bus.guest_handle);
+       if (err)
+               goto err_respond;
+       if (parser_ctx) {
+               const guid_t *partition_guid = parser_id_get(parser_ctx);
+
+               guid_copy(&bus_info->partition_guid, partition_guid);
+               bus_info->name = parser_name_get(parser_ctx);
+       }
+       if (inmsg->hdr.flags.response_expected == 1)
+               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
+       return 0;
+
+err_respond:
+       dev_err(&chipset_dev->acpi_device->dev,
+               "%s exited with err: %d\n", __func__, err);
+       if (inmsg->hdr.flags.response_expected == 1)
+               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
+       return err;
+}
+
+static int visorbus_device_create(struct controlvm_message *inmsg)
+{
+       struct controlvm_message_packet *cmd = &inmsg->cmd;
+       struct controlvm_message_header *pmsg_hdr;
+       u32 bus_no = cmd->create_device.bus_no;
+       u32 dev_no = cmd->create_device.dev_no;
+       struct visor_device *dev_info;
+       struct visor_device *bus_info;
+       struct visorchannel *visorchannel;
+       int err;
+
+       bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+       if (!bus_info) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed to get bus by id: %d\n", bus_no);
+               err = -ENODEV;
+               goto err_respond;
+       }
+       if (bus_info->state.created == 0) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "bus not created, id: %d\n", bus_no);
+               err = -EINVAL;
+               goto err_respond;
+       }
+       dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
+       if (dev_info && dev_info->state.created == 1) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed to get bus by id: %d/%d\n", bus_no, dev_no);
+               err = -EEXIST;
+               goto err_respond;
+       }
+
+       dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
+       if (!dev_info) {
+               err = -ENOMEM;
+               goto err_respond;
+       }
+       dev_info->chipset_bus_no = bus_no;
+       dev_info->chipset_dev_no = dev_no;
+       guid_copy(&dev_info->inst, &cmd->create_device.dev_inst_guid);
+       dev_info->device.parent = &bus_info->device;
+       visorchannel = visorchannel_create(cmd->create_device.channel_addr,
+                                          GFP_KERNEL,
+                                          &cmd->create_device.data_type_guid,
+                                          true);
+       if (!visorchannel) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed to create visorchannel: %d/%d\n",
+                       bus_no, dev_no);
+               err = -ENOMEM;
+               goto err_free_dev_info;
+       }
+       dev_info->visorchannel = visorchannel;
+       guid_copy(&dev_info->channel_type_guid,
+                 &cmd->create_device.data_type_guid);
+       if (guid_equal(&cmd->create_device.data_type_guid,
+                      &visor_vhba_channel_guid)) {
+               err = save_crash_message(inmsg, CRASH_DEV);
+               if (err)
+                       goto err_destroy_visorchannel;
+       }
+       if (inmsg->hdr.flags.response_expected == 1) {
+               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
+               if (!pmsg_hdr) {
+                       err = -ENOMEM;
+                       goto err_destroy_visorchannel;
+               }
+               memcpy(pmsg_hdr, &inmsg->hdr,
+                      sizeof(struct controlvm_message_header));
+               dev_info->pending_msg_hdr = pmsg_hdr;
+       }
+       /* create_visor_device will send response */
+       err = create_visor_device(dev_info);
+       if (err)
+               goto err_destroy_visorchannel;
+
+       return 0;
+
+err_destroy_visorchannel:
+       visorchannel_destroy(visorchannel);
+
+err_free_dev_info:
+       kfree(dev_info);
+
+err_respond:
+       if (inmsg->hdr.flags.response_expected == 1)
+               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
+       return err;
+}
+
+static int visorbus_device_changestate(struct controlvm_message *inmsg)
+{
+       struct controlvm_message_packet *cmd = &inmsg->cmd;
+       struct controlvm_message_header *pmsg_hdr;
+       u32 bus_no = cmd->device_change_state.bus_no;
+       u32 dev_no = cmd->device_change_state.dev_no;
+       struct visor_segment_state state = cmd->device_change_state.state;
+       struct visor_device *dev_info;
+       int err = 0;
+
+       dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
+       if (!dev_info) {
+               err = -ENODEV;
+               goto err_respond;
+       }
+       if (dev_info->state.created == 0) {
+               err = -EINVAL;
+               goto err_respond;
+       }
+       if (dev_info->pending_msg_hdr) {
+               /* only non-NULL if dev is still waiting on a response */
+               err = -EIO;
+               goto err_respond;
+       }
+
+       if (inmsg->hdr.flags.response_expected == 1) {
+               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
+               if (!pmsg_hdr) {
+                       err = -ENOMEM;
+                       goto err_respond;
+               }
+               memcpy(pmsg_hdr, &inmsg->hdr,
+                      sizeof(struct controlvm_message_header));
+               dev_info->pending_msg_hdr = pmsg_hdr;
+       }
+       if (state.alive == segment_state_running.alive &&
+           state.operating == segment_state_running.operating)
+               /* Response will be sent from visorchipset_device_resume */
+               err = visorchipset_device_resume(dev_info);
+       /* ServerNotReady / ServerLost / SegmentStateStandby */
+       else if (state.alive == segment_state_standby.alive &&
+                state.operating == segment_state_standby.operating)
+               /*
+                * technically this is standby case where server is lost.
+                * Response will be sent from visorchipset_device_pause.
+                */
+               err = visorchipset_device_pause(dev_info);
+       if (err)
+               goto err_respond;
+       return 0;
+
+err_respond:
+       dev_err(&chipset_dev->acpi_device->dev, "failed: %d\n", err);
+       if (inmsg->hdr.flags.response_expected == 1)
+               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
+       return err;
+}
+
+static int visorbus_device_destroy(struct controlvm_message *inmsg)
+{
+       struct controlvm_message_packet *cmd = &inmsg->cmd;
+       struct controlvm_message_header *pmsg_hdr;
+       u32 bus_no = cmd->destroy_device.bus_no;
+       u32 dev_no = cmd->destroy_device.dev_no;
+       struct visor_device *dev_info;
+       int err;
+
+       dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
+       if (!dev_info) {
+               err = -ENODEV;
+               goto err_respond;
+       }
+       if (dev_info->state.created == 0) {
+               err = -EINVAL;
+               goto err_respond;
+       }
+       if (dev_info->pending_msg_hdr) {
+               /* only non-NULL if dev is still waiting on a response */
+               err = -EIO;
+               goto err_respond;
+       }
+       if (inmsg->hdr.flags.response_expected == 1) {
+               pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
+               if (!pmsg_hdr) {
+                       err = -ENOMEM;
+                       goto err_respond;
+               }
+
+               memcpy(pmsg_hdr, &inmsg->hdr,
+                      sizeof(struct controlvm_message_header));
+               dev_info->pending_msg_hdr = pmsg_hdr;
+       }
+       kfree(dev_info->name);
+       remove_visor_device(dev_info);
+       return 0;
+
+err_respond:
+       if (inmsg->hdr.flags.response_expected == 1)
+               controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
+       return err;
+}
+
+/*
+ * The general parahotplug flow works as follows. The visorchipset receives
+ * a DEVICE_CHANGESTATE message from Command specifying a physical device
+ * to enable or disable. The CONTROLVM message handler calls
+ * parahotplug_process_message, which then adds the message to a global list
+ * and kicks off a udev event which causes a user level script to enable or
+ * disable the specified device. The udev script then writes to
+ * /sys/devices/platform/visorchipset/parahotplug, which causes the
+ * parahotplug store functions to get called, at which point the
+ * appropriate CONTROLVM message is retrieved from the list and responded to.
+ */
+
+#define PARAHOTPLUG_TIMEOUT_MS 2000
+
+/*
+ * parahotplug_next_id() - generate unique int to match an outstanding
+ *                         CONTROLVM message with a udev script /sys
+ *                         response
+ *
+ * Return: a unique integer value
+ */
+static int parahotplug_next_id(void)
+{
+       static atomic_t id = ATOMIC_INIT(0);
+
+       return atomic_inc_return(&id);
+}
+
+/*
+ * parahotplug_next_expiration() - returns the time (in jiffies) when a
+ *                                 CONTROLVM message on the list should expire
+ *                                 -- PARAHOTPLUG_TIMEOUT_MS in the future
+ *
+ * Return: expected expiration time (in jiffies)
+ */
+static unsigned long parahotplug_next_expiration(void)
+{
+       return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
+}
+
+/*
+ * parahotplug_request_create() - create a parahotplug_request, which is
+ *                                basically a wrapper for a CONTROLVM_MESSAGE
+ *                                that we can stick on a list
+ * @msg: the message to insert in the request
+ *
+ * Return: the request containing the provided message
+ */
+static struct parahotplug_request *parahotplug_request_create(
+                                               struct controlvm_message *msg)
+{
+       struct parahotplug_request *req;
+
+       req = kmalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return NULL;
+       req->id = parahotplug_next_id();
+       req->expiration = parahotplug_next_expiration();
+       req->msg = *msg;
+       return req;
+}
+
+/*
+ * parahotplug_request_destroy() - free a parahotplug_request
+ * @req: the request to deallocate
+ */
+static void parahotplug_request_destroy(struct parahotplug_request *req)
+{
+       kfree(req);
+}
+
+static LIST_HEAD(parahotplug_request_list);
+/* lock for above */
+static DEFINE_SPINLOCK(parahotplug_request_list_lock);
+
+/*
+ * parahotplug_request_complete() - mark request as complete
+ * @id:     the id of the request
+ * @active: indicates whether the request is assigned to active partition
+ *
+ * Called from the /sys handler, which means the user script has
+ * finished the enable/disable. Find the matching identifier, and
+ * respond to the CONTROLVM message with success.
+ *
+ * Return: 0 on success or -EINVAL on failure
+ */
+static int parahotplug_request_complete(int id, u16 active)
+{
+       struct list_head *pos;
+       struct list_head *tmp;
+       struct parahotplug_request *req;
+
+       spin_lock(&parahotplug_request_list_lock);
+       /* Look for a request matching "id". */
+       list_for_each_safe(pos, tmp, &parahotplug_request_list) {
+               req = list_entry(pos, struct parahotplug_request, list);
+               if (req->id == id) {
+                       /*
+                        * Found a match. Remove it from the list and
+                        * respond.
+                        */
+                       list_del(pos);
+                       spin_unlock(&parahotplug_request_list_lock);
+                       req->msg.cmd.device_change_state.state.active = active;
+                       if (req->msg.hdr.flags.response_expected)
+                               controlvm_respond(
+                                      &req->msg.hdr, CONTROLVM_RESP_SUCCESS,
+                                      &req->msg.cmd.device_change_state.state);
+                       parahotplug_request_destroy(req);
+                       return 0;
+               }
+       }
+       spin_unlock(&parahotplug_request_list_lock);
+       return -EINVAL;
+}
+
+/*
+ * devicedisabled_store() - disables the hotplug device
+ * @dev:   sysfs interface variable not utilized in this function
+ * @attr:  sysfs interface variable not utilized in this function
+ * @buf:   buffer containing the device id
+ * @count: the size of the buffer
+ *
+ * The parahotplug/devicedisabled interface gets called by our support script
+ * when an SR-IOV device has been shut down. The ID is passed to the script
+ * and then passed back when the device has been removed.
+ *
+ * Return: the size of the buffer for success or negative for error
+ */
+static ssize_t devicedisabled_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       unsigned int id;
+       int err;
+
+       if (kstrtouint(buf, 10, &id))
+               return -EINVAL;
+       err = parahotplug_request_complete(id, 0);
+       if (err < 0)
+               return err;
+       return count;
+}
+static DEVICE_ATTR_WO(devicedisabled);
+
+/*
+ * deviceenabled_store() - enables the hotplug device
+ * @dev:   sysfs interface variable not utilized in this function
+ * @attr:  sysfs interface variable not utilized in this function
+ * @buf:   buffer containing the device id
+ * @count: the size of the buffer
+ *
+ * The parahotplug/deviceenabled interface gets called by our support script
+ * when an SR-IOV device has been recovered. The ID is passed to the script
+ * and then passed back when the device has been brought back up.
+ *
+ * Return: the size of the buffer for success or negative for error
+ */
+static ssize_t deviceenabled_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       unsigned int id;
+
+       if (kstrtouint(buf, 10, &id))
+               return -EINVAL;
+       parahotplug_request_complete(id, 1);
+       return count;
+}
+static DEVICE_ATTR_WO(deviceenabled);
+
+static struct attribute *visorchipset_install_attrs[] = {
+       &dev_attr_toolaction.attr,
+       &dev_attr_boottotool.attr,
+       &dev_attr_error.attr,
+       &dev_attr_textid.attr,
+       &dev_attr_remaining_steps.attr,
+       NULL
+};
+
+static const struct attribute_group visorchipset_install_group = {
+       .name = "install",
+       .attrs = visorchipset_install_attrs
+};
+
+static struct attribute *visorchipset_parahotplug_attrs[] = {
+       &dev_attr_devicedisabled.attr,
+       &dev_attr_deviceenabled.attr,
+       NULL
+};
+
+static const struct attribute_group visorchipset_parahotplug_group = {
+       .name = "parahotplug",
+       .attrs = visorchipset_parahotplug_attrs
+};
+
+static const struct attribute_group *visorchipset_dev_groups[] = {
+       &visorchipset_install_group,
+       &visorchipset_parahotplug_group,
+       NULL
+};
+
+/*
+ * parahotplug_request_kickoff() - initiate parahotplug request
+ * @req: the request to initiate
+ *
+ * Cause uevent to run the user level script to do the disable/enable specified
+ * in the parahotplug_request.
+ */
+static int parahotplug_request_kickoff(struct parahotplug_request *req)
+{
+       struct controlvm_message_packet *cmd = &req->msg.cmd;
+       char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
+            env_func[40];
+       char *envp[] = { env_cmd, env_id, env_state, env_bus, env_dev,
+                        env_func, NULL
+       };
+
+       sprintf(env_cmd, "VISOR_PARAHOTPLUG=1");
+       sprintf(env_id, "VISOR_PARAHOTPLUG_ID=%d", req->id);
+       sprintf(env_state, "VISOR_PARAHOTPLUG_STATE=%d",
+               cmd->device_change_state.state.active);
+       sprintf(env_bus, "VISOR_PARAHOTPLUG_BUS=%d",
+               cmd->device_change_state.bus_no);
+       sprintf(env_dev, "VISOR_PARAHOTPLUG_DEVICE=%d",
+               cmd->device_change_state.dev_no >> 3);
+       sprintf(env_func, "VISOR_PARAHOTPLUG_FUNCTION=%d",
+               cmd->device_change_state.dev_no & 0x7);
+       return kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj,
+                                 KOBJ_CHANGE, envp);
+}
+
+/*
+ * parahotplug_process_message() - enables or disables a PCI device by kicking
+ *                                 off a udev script
+ * @inmsg: the message indicating whether to enable or disable
+ */
+static int parahotplug_process_message(struct controlvm_message *inmsg)
+{
+       struct parahotplug_request *req;
+       int err;
+
+       req = parahotplug_request_create(inmsg);
+       if (!req)
+               return -ENOMEM;
+       /*
+        * For enable messages, just respond with success right away, we don't
+        * need to wait to see if the enable was successful.
+        */
+       if (inmsg->cmd.device_change_state.state.active) {
+               err = parahotplug_request_kickoff(req);
+               if (err)
+                       goto err_respond;
+               controlvm_respond(&inmsg->hdr, CONTROLVM_RESP_SUCCESS,
+                                 &inmsg->cmd.device_change_state.state);
+               parahotplug_request_destroy(req);
+               return 0;
+       }
+       /*
+        * For disable messages, add the request to the request list before
+        * kicking off the udev script. It won't get responded to until the
+        * script has indicated it's done.
+        */
+       spin_lock(&parahotplug_request_list_lock);
+       list_add_tail(&req->list, &parahotplug_request_list);
+       spin_unlock(&parahotplug_request_list_lock);
+       err = parahotplug_request_kickoff(req);
+       if (err)
+               goto err_respond;
+       return 0;
+
+err_respond:
+       controlvm_respond(&inmsg->hdr, err,
+                         &inmsg->cmd.device_change_state.state);
+       return err;
+}
+
+/*
+ * chipset_ready_uevent() - sends chipset_ready action
+ *
+ * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
+ *
+ * Return: 0 on success, negative on failure
+ */
+static int chipset_ready_uevent(struct controlvm_message_header *msg_hdr)
+{
+       int res;
+
+       res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj, KOBJ_ONLINE);
+       if (msg_hdr->flags.response_expected)
+               controlvm_respond(msg_hdr, res, NULL);
+       return res;
+}
+
+/*
+ * chipset_selftest_uevent() - sends chipset_selftest action
+ *
+ * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
+ *
+ * Return: 0 on success, negative on failure
+ */
+static int chipset_selftest_uevent(struct controlvm_message_header *msg_hdr)
+{
+       char env_selftest[20];
+       char *envp[] = { env_selftest, NULL };
+       int res;
+
+       sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
+       res = kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj,
+                                KOBJ_CHANGE, envp);
+       if (msg_hdr->flags.response_expected)
+               controlvm_respond(msg_hdr, res, NULL);
+       return res;
+}
+
+/*
+ * chipset_notready_uevent() - sends chipset_notready action
+ *
+ * Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
+ *
+ * Return: 0 on success, negative on failure
+ */
+static int chipset_notready_uevent(struct controlvm_message_header *msg_hdr)
+{
+       int res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj,
+                                KOBJ_OFFLINE);
+
+       if (msg_hdr->flags.response_expected)
+               controlvm_respond(msg_hdr, res, NULL);
+       return res;
+}
+
+static int unisys_vmcall(unsigned long tuple, unsigned long param)
+{
+       int result = 0;
+       unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
+       unsigned long reg_ebx;
+       unsigned long reg_ecx;
+
+       reg_ebx = param & 0xFFFFFFFF;
+       reg_ecx = param >> 32;
+       cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx);
+       if (!(cpuid_ecx & 0x80000000))
+               return -EPERM;
+       __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
+                            "a"(tuple), "b"(reg_ebx), "c"(reg_ecx));
+       if (result)
+               goto error;
+       return 0;
+
+/* Need to convert from VMCALL error codes to Linux */
+error:
+       switch (result) {
+       case VMCALL_RESULT_INVALID_PARAM:
+               return -EINVAL;
+       case VMCALL_RESULT_DATA_UNAVAILABLE:
+               return -ENODEV;
+       default:
+               return -EFAULT;
+       }
+}
+
+static int controlvm_channel_create(struct visorchipset_device *dev)
+{
+       struct visorchannel *chan;
+       u64 addr;
+       int err;
+
+       err = unisys_vmcall(VMCALL_CONTROLVM_ADDR,
+                           virt_to_phys(&dev->controlvm_params));
+       if (err)
+               return err;
+       addr = dev->controlvm_params.address;
+       chan = visorchannel_create(addr, GFP_KERNEL,
+                                  &visor_controlvm_channel_guid, true);
+       if (!chan)
+               return -ENOMEM;
+       dev->controlvm_channel = chan;
+       return 0;
+}
+
+static void setup_crash_devices_work_queue(struct work_struct *work)
+{
+       struct controlvm_message local_crash_bus_msg;
+       struct controlvm_message local_crash_dev_msg;
+       struct controlvm_message msg;
+       u32 local_crash_msg_offset;
+       u16 local_crash_msg_count;
+
+       /* send init chipset msg */
+       msg.hdr.id = CONTROLVM_CHIPSET_INIT;
+       msg.cmd.init_chipset.bus_count = 23;
+       msg.cmd.init_chipset.switch_count = 0;
+       chipset_init(&msg);
+       /* get saved message count */
+       if (visorchannel_read(chipset_dev->controlvm_channel,
+                             offsetof(struct visor_controlvm_channel,
+                                      saved_crash_message_count),
+                             &local_crash_msg_count, sizeof(u16)) < 0) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed to read channel\n");
+               return;
+       }
+       if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
+               dev_err(&chipset_dev->acpi_device->dev, "invalid count\n");
+               return;
+       }
+       /* get saved crash message offset */
+       if (visorchannel_read(chipset_dev->controlvm_channel,
+                             offsetof(struct visor_controlvm_channel,
+                                      saved_crash_message_offset),
+                             &local_crash_msg_offset, sizeof(u32)) < 0) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed to read channel\n");
+               return;
+       }
+       /* read create device message for storage bus offset */
+       if (visorchannel_read(chipset_dev->controlvm_channel,
+                             local_crash_msg_offset,
+                             &local_crash_bus_msg,
+                             sizeof(struct controlvm_message)) < 0) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed to read channel\n");
+               return;
+       }
+       /* read create device message for storage device */
+       if (visorchannel_read(chipset_dev->controlvm_channel,
+                             local_crash_msg_offset +
+                             sizeof(struct controlvm_message),
+                             &local_crash_dev_msg,
+                             sizeof(struct controlvm_message)) < 0) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "failed to read channel\n");
+               return;
+       }
+       /* reuse IOVM create bus message */
+       if (!local_crash_bus_msg.cmd.create_bus.channel_addr) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "no valid create_bus message\n");
+               return;
+       }
+       visorbus_create(&local_crash_bus_msg);
+       /* reuse create device message for storage device */
+       if (!local_crash_dev_msg.cmd.create_device.channel_addr) {
+               dev_err(&chipset_dev->acpi_device->dev,
+                       "no valid create_device message\n");
+               return;
+       }
+       visorbus_device_create(&local_crash_dev_msg);
+}
+
+void visorbus_response(struct visor_device *bus_info, int response,
+                      int controlvm_id)
+{
+       if (!bus_info->pending_msg_hdr)
+               return;
+
+       controlvm_responder(controlvm_id, bus_info->pending_msg_hdr, response);
+       kfree(bus_info->pending_msg_hdr);
+       bus_info->pending_msg_hdr = NULL;
+}
+
+void visorbus_device_changestate_response(struct visor_device *dev_info,
+                                         int response,
+                                         struct visor_segment_state state)
+{
+       if (!dev_info->pending_msg_hdr)
+               return;
+
+       device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, dev_info,
+                                    response, state);
+       kfree(dev_info->pending_msg_hdr);
+       dev_info->pending_msg_hdr = NULL;
+}
+
+static void parser_done(struct parser_context *ctx)
+{
+       chipset_dev->controlvm_payload_bytes_buffered -= ctx->param_bytes;
+       kfree(ctx);
+}
+
+static struct parser_context *parser_init_stream(u64 addr, u32 bytes,
+                                                bool *retry)
+{
+       unsigned long allocbytes;
+       struct parser_context *ctx;
+       void *mapping;
+
+       *retry = false;
+       /* alloc an extra byte to ensure payload is \0 terminated */
+       allocbytes = (unsigned long)bytes + 1 + (sizeof(struct parser_context) -
+                    sizeof(struct visor_controlvm_parameters_header));
+       if ((chipset_dev->controlvm_payload_bytes_buffered + bytes) >
+            MAX_CONTROLVM_PAYLOAD_BYTES) {
+               *retry = true;
+               return NULL;
+       }
+       ctx = kzalloc(allocbytes, GFP_KERNEL);
+       if (!ctx) {
+               *retry = true;
+               return NULL;
+       }
+       ctx->allocbytes = allocbytes;
+       ctx->param_bytes = bytes;
+       mapping = memremap(addr, bytes, MEMREMAP_WB);
+       if (!mapping)
+               goto err_finish_ctx;
+       memcpy(&ctx->data, mapping, bytes);
+       memunmap(mapping);
+       ctx->byte_stream = true;
+       chipset_dev->controlvm_payload_bytes_buffered += ctx->param_bytes;
+       return ctx;
+
+err_finish_ctx:
+       kfree(ctx);
+       return NULL;
+}
+
+/*
+ * handle_command() - process a controlvm message
+ * @inmsg:        the message to process
+ * @channel_addr: address of the controlvm channel
+ *
+ * Return:
+ *     0       - Successfully processed the message
+ *     -EAGAIN - ControlVM message was not processed and should be retried
+ *               reading the next controlvm message; a scenario where this can
+ *               occur is when we need to throttle the allocation of memory in
+ *               which to copy out controlvm payload data.
+ *     < 0     - error: ControlVM message was processed but an error occurred.
+ */
+static int handle_command(struct controlvm_message inmsg, u64 channel_addr)
+{
+       struct controlvm_message_packet *cmd = &inmsg.cmd;
+       u64 parm_addr;
+       u32 parm_bytes;
+       struct parser_context *parser_ctx = NULL;
+       struct controlvm_message ackmsg;
+       int err = 0;
+
+       /* create parsing context if necessary */
+       parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
+       parm_bytes = inmsg.hdr.payload_bytes;
+       /*
+        * Parameter and channel addresses within test messages actually lie
+        * within our OS-controlled memory. We need to know that, because it
+        * makes a difference in how we compute the virtual address.
+        */
+       if (parm_bytes) {
+               bool retry;
+
+               parser_ctx = parser_init_stream(parm_addr, parm_bytes, &retry);
+               if (!parser_ctx && retry)
+                       return -EAGAIN;
+       }
+       controlvm_init_response(&ackmsg, &inmsg.hdr, CONTROLVM_RESP_SUCCESS);
+       err = visorchannel_signalinsert(chipset_dev->controlvm_channel,
+                                       CONTROLVM_QUEUE_ACK, &ackmsg);
+       if (err)
+               return err;
+       switch (inmsg.hdr.id) {
+       case CONTROLVM_CHIPSET_INIT:
+               err = chipset_init(&inmsg);
+               break;
+       case CONTROLVM_BUS_CREATE:
+               err = visorbus_create(&inmsg);
+               break;
+       case CONTROLVM_BUS_DESTROY:
+               err = visorbus_destroy(&inmsg);
+               break;
+       case CONTROLVM_BUS_CONFIGURE:
+               err = visorbus_configure(&inmsg, parser_ctx);
+               break;
+       case CONTROLVM_DEVICE_CREATE:
+               err = visorbus_device_create(&inmsg);
+               break;
+       case CONTROLVM_DEVICE_CHANGESTATE:
+               if (cmd->device_change_state.flags.phys_device) {
+                       err = parahotplug_process_message(&inmsg);
+               } else {
+                       /*
+                        * save the hdr and cmd structures for later use when
+                        * sending back the response to Command
+                        */
+                       err = visorbus_device_changestate(&inmsg);
+                       break;
+               }
+               break;
+       case CONTROLVM_DEVICE_DESTROY:
+               err = visorbus_device_destroy(&inmsg);
+               break;
+       case CONTROLVM_DEVICE_CONFIGURE:
+               /* no op just send a respond that we passed */
+               if (inmsg.hdr.flags.response_expected)
+                       controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS,
+                                         NULL);
+               break;
+       case CONTROLVM_CHIPSET_READY:
+               err = chipset_ready_uevent(&inmsg.hdr);
+               break;
+       case CONTROLVM_CHIPSET_SELFTEST:
+               err = chipset_selftest_uevent(&inmsg.hdr);
+               break;
+       case CONTROLVM_CHIPSET_STOP:
+               err = chipset_notready_uevent(&inmsg.hdr);
+               break;
+       default:
+               err = -ENOMSG;
+               if (inmsg.hdr.flags.response_expected)
+                       controlvm_respond(&inmsg.hdr,
+                                         -CONTROLVM_RESP_ID_UNKNOWN, NULL);
+               break;
+       }
+       if (parser_ctx) {
+               parser_done(parser_ctx);
+               parser_ctx = NULL;
+       }
+       return err;
+}
+
+/*
+ * read_controlvm_event() - retreives the next message from the
+ *                          CONTROLVM_QUEUE_EVENT queue in the controlvm
+ *                          channel
+ * @msg: pointer to the retrieved message
+ *
+ * Return: 0 if valid message was retrieved or -error
+ */
+static int read_controlvm_event(struct controlvm_message *msg)
+{
+       int err = visorchannel_signalremove(chipset_dev->controlvm_channel,
+                                           CONTROLVM_QUEUE_EVENT, msg);
+
+       if (err)
+               return err;
+       /* got a message */
+       if (msg->hdr.flags.test_message == 1)
+               return -EINVAL;
+       return 0;
+}
+
+/*
+ * parahotplug_process_list() - remove any request from the list that's been on
+ *                              there too long and respond with an error
+ */
+static void parahotplug_process_list(void)
+{
+       struct list_head *pos;
+       struct list_head *tmp;
+
+       spin_lock(&parahotplug_request_list_lock);
+       list_for_each_safe(pos, tmp, &parahotplug_request_list) {
+               struct parahotplug_request *req =
+                   list_entry(pos, struct parahotplug_request, list);
+
+               if (!time_after_eq(jiffies, req->expiration))
+                       continue;
+               list_del(pos);
+               if (req->msg.hdr.flags.response_expected)
+                       controlvm_respond(
+                               &req->msg.hdr,
+                               CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT,
+                               &req->msg.cmd.device_change_state.state);
+               parahotplug_request_destroy(req);
+       }
+       spin_unlock(&parahotplug_request_list_lock);
+}
+
+static void controlvm_periodic_work(struct work_struct *work)
+{
+       struct controlvm_message inmsg;
+       int count = 0;
+       int err;
+
+       /* Drain the RESPONSE queue make it empty */
+       do {
+               err = visorchannel_signalremove(chipset_dev->controlvm_channel,
+                                               CONTROLVM_QUEUE_RESPONSE,
+                                               &inmsg);
+       } while ((!err) && (++count < CONTROLVM_MESSAGE_MAX));
+       if (err != -EAGAIN)
+               goto schedule_out;
+       if (chipset_dev->controlvm_pending_msg_valid) {
+               /*
+                * we throttled processing of a prior msg, so try to process
+                * it again rather than reading a new one
+                */
+               inmsg = chipset_dev->controlvm_pending_msg;
+               chipset_dev->controlvm_pending_msg_valid = false;
+               err = 0;
+       } else {
+               err = read_controlvm_event(&inmsg);
+       }
+       while (!err) {
+               chipset_dev->most_recent_message_jiffies = jiffies;
+               err = handle_command(inmsg,
+                                    visorchannel_get_physaddr
+                                    (chipset_dev->controlvm_channel));
+               if (err == -EAGAIN) {
+                       chipset_dev->controlvm_pending_msg = inmsg;
+                       chipset_dev->controlvm_pending_msg_valid = true;
+                       break;
+               }
+
+               err = read_controlvm_event(&inmsg);
+       }
+       /* parahotplug_worker */
+       parahotplug_process_list();
+
+/*
+ * The controlvm messages are sent in a bulk. If we start receiving messages, we
+ * want the polling to be fast. If we do not receive any message for
+ * MIN_IDLE_SECONDS, we can slow down the polling.
+ */
+schedule_out:
+       if (time_after(jiffies, chipset_dev->most_recent_message_jiffies +
+                               (HZ * MIN_IDLE_SECONDS))) {
+               /*
+                * it's been longer than MIN_IDLE_SECONDS since we processed
+                * our last controlvm message; slow down the polling
+                */
+               if (chipset_dev->poll_jiffies != POLLJIFFIES_CONTROLVM_SLOW)
+                       chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_SLOW;
+       } else {
+               if (chipset_dev->poll_jiffies != POLLJIFFIES_CONTROLVM_FAST)
+                       chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST;
+       }
+       schedule_delayed_work(&chipset_dev->periodic_controlvm_work,
+                             chipset_dev->poll_jiffies);
+}
+
+static int visorchipset_init(struct acpi_device *acpi_device)
+{
+       int err = -ENODEV;
+       struct visorchannel *controlvm_channel;
+
+       chipset_dev = kzalloc(sizeof(*chipset_dev), GFP_KERNEL);
+       if (!chipset_dev)
+               goto error;
+       err = controlvm_channel_create(chipset_dev);
+       if (err)
+               goto error_free_chipset_dev;
+       acpi_device->driver_data = chipset_dev;
+       chipset_dev->acpi_device = acpi_device;
+       chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST;
+       err = sysfs_create_groups(&chipset_dev->acpi_device->dev.kobj,
+                                 visorchipset_dev_groups);
+       if (err < 0)
+               goto error_destroy_channel;
+       controlvm_channel = chipset_dev->controlvm_channel;
+       if (!visor_check_channel(visorchannel_get_header(controlvm_channel),
+                                &chipset_dev->acpi_device->dev,
+                                &visor_controlvm_channel_guid,
+                                "controlvm",
+                                sizeof(struct visor_controlvm_channel),
+                                VISOR_CONTROLVM_CHANNEL_VERSIONID,
+                                VISOR_CHANNEL_SIGNATURE))
+               goto error_delete_groups;
+       /* if booting in a crash kernel */
+       if (is_kdump_kernel())
+               INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work,
+                                 setup_crash_devices_work_queue);
+       else
+               INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work,
+                                 controlvm_periodic_work);
+       chipset_dev->most_recent_message_jiffies = jiffies;
+       chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST;
+       schedule_delayed_work(&chipset_dev->periodic_controlvm_work,
+                             chipset_dev->poll_jiffies);
+       err = visorbus_init();
+       if (err < 0)
+               goto error_cancel_work;
+       return 0;
+
+error_cancel_work:
+       cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work);
+
+error_delete_groups:
+       sysfs_remove_groups(&chipset_dev->acpi_device->dev.kobj,
+                           visorchipset_dev_groups);
+
+error_destroy_channel:
+       visorchannel_destroy(chipset_dev->controlvm_channel);
+
+error_free_chipset_dev:
+       kfree(chipset_dev);
+
+error:
+       dev_err(&acpi_device->dev, "failed with error %d\n", err);
+       return err;
+}
+
+static int visorchipset_exit(struct acpi_device *acpi_device)
+{
+       visorbus_exit();
+       cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work);
+       sysfs_remove_groups(&chipset_dev->acpi_device->dev.kobj,
+                           visorchipset_dev_groups);
+       visorchannel_destroy(chipset_dev->controlvm_channel);
+       kfree(chipset_dev);
+       return 0;
+}
+
+static const struct acpi_device_id unisys_device_ids[] = {
+       {"PNP0A07", 0},
+       {"", 0},
+};
+
+static struct acpi_driver unisys_acpi_driver = {
+       .name = "unisys_acpi",
+       .class = "unisys_acpi_class",
+       .owner = THIS_MODULE,
+       .ids = unisys_device_ids,
+       .ops = {
+               .add = visorchipset_init,
+               .remove = visorchipset_exit,
+       },
+};
+
+MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
+
+static __init int visorutil_spar_detect(void)
+{
+       unsigned int eax, ebx, ecx, edx;
+
+       if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
+               /* check the ID */
+               cpuid(UNISYS_VISOR_LEAF_ID, &eax, &ebx, &ecx, &edx);
+               return  (ebx == UNISYS_VISOR_ID_EBX) &&
+                       (ecx == UNISYS_VISOR_ID_ECX) &&
+                       (edx == UNISYS_VISOR_ID_EDX);
+       }
+       return 0;
+}
+
+static int __init init_unisys(void)
+{
+       int result;
+
+       if (!visorutil_spar_detect())
+               return -ENODEV;
+       result = acpi_bus_register_driver(&unisys_acpi_driver);
+       if (result)
+               return -ENODEV;
+       pr_info("Unisys Visorchipset Driver Loaded.\n");
+       return 0;
+};
+
+static void __exit exit_unisys(void)
+{
+       acpi_bus_unregister_driver(&unisys_acpi_driver);
+}
+
+module_init(init_unisys);
+module_exit(exit_unisys);
+
+MODULE_AUTHOR("Unisys");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("s-Par visorbus driver for virtual device buses");
index 0ed56752f20800cfaac5757783d7cacfb42998c4..9774588da60ef8f27109064f4340b6fa53dac626 100644 (file)
@@ -294,7 +294,6 @@ config NFS_COMMON
 source "net/sunrpc/Kconfig"
 source "fs/ceph/Kconfig"
 source "fs/cifs/Kconfig"
-source "fs/ncpfs/Kconfig"
 source "fs/coda/Kconfig"
 source "fs/afs/Kconfig"
 source "fs/9p/Kconfig"
index ef772f1eaff80ade97232f502bb4c8915e87cdac..add789ea270ad703e9502efad6e3f4070bbae47b 100644 (file)
@@ -92,7 +92,6 @@ obj-$(CONFIG_LOCKD)           += lockd/
 obj-$(CONFIG_NLS)              += nls/
 obj-$(CONFIG_SYSV_FS)          += sysv/
 obj-$(CONFIG_CIFS)             += cifs/
-obj-$(CONFIG_NCP_FS)           += ncpfs/
 obj-$(CONFIG_HPFS_FS)          += hpfs/
 obj-$(CONFIG_NTFS_FS)          += ntfs/
 obj-$(CONFIG_UFS_FS)           += ufs/
diff --git a/fs/ncpfs/Kconfig b/fs/ncpfs/Kconfig
deleted file mode 100644 (file)
index c931cf2..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-#
-# NCP Filesystem configuration
-#
-config NCP_FS
-       tristate "NCP file system support (to mount NetWare volumes)"
-       depends on IPX!=n || INET
-       help
-         NCP (NetWare Core Protocol) is a protocol that runs over IPX and is
-         used by Novell NetWare clients to talk to file servers.  It is to
-         IPX what NFS is to TCP/IP, if that helps.  Saying Y here allows you
-         to mount NetWare file server volumes and to access them just like
-         any other Unix directory.  For details, please read the file
-         <file:Documentation/filesystems/ncpfs.txt> in the kernel source and
-         the IPX-HOWTO from <http://www.tldp.org/docs.html#howto>.
-
-         You do not have to say Y here if you want your Linux box to act as a
-         file *server* for Novell NetWare clients.
-
-         General information about how to connect Linux, Windows machines and
-         Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
-
-         To compile this as a module, choose M here: the module will be called
-         ncpfs.  Say N unless you are connected to a Novell network.
-
-config NCPFS_PACKET_SIGNING
-       bool "Packet signatures"
-       depends on NCP_FS
-       help
-         NCP allows packets to be signed for stronger security. If you want
-         security, say Y.  Normal users can leave it off.  To be able to use
-         packet signing you must use ncpfs > 2.0.12.
-
-config NCPFS_IOCTL_LOCKING
-       bool "Proprietary file locking"
-       depends on NCP_FS
-       help
-         Allows locking of records on remote volumes.  Say N unless you have
-         special applications which are able to utilize this locking scheme.
-
-config NCPFS_STRONG
-       bool "Clear remove/delete inhibit when needed"
-       depends on NCP_FS
-       help
-         Allows manipulation of files flagged as Delete or Rename Inhibit.
-         To use this feature you must mount volumes with the ncpmount
-         parameter "-s" (ncpfs-2.0.12 and newer).  Say Y unless you are not
-         mounting volumes with -f 444.
-
-config NCPFS_NFS_NS
-       bool "Use NFS namespace if available"
-       depends on NCP_FS
-       help
-         Allows you to utilize NFS namespace on NetWare servers.  It brings
-         you case sensitive filenames.  Say Y.  You can disable it at
-         mount-time with the `-N nfs' parameter of ncpmount.
-
-config NCPFS_OS2_NS
-       bool "Use LONG (OS/2) namespace if available"
-       depends on NCP_FS
-       help
-         Allows you to utilize OS2/LONG namespace on NetWare servers.
-         Filenames in this namespace are limited to 255 characters, they are
-         case insensitive, and case in names is preserved.  Say Y.  You can
-         disable it at mount time with the -N os2 parameter of ncpmount.
-
-config NCPFS_SMALLDOS
-       bool "Lowercase DOS filenames"
-       depends on NCP_FS
-       ---help---
-         If you say Y here, every filename on a NetWare server volume using
-         the OS2/LONG namespace and created under DOS or on a volume using
-         DOS namespace will be converted to lowercase characters.
-         Saying N here will give you these filenames in uppercase.
-
-         This is only a cosmetic option since the OS2/LONG namespace is case
-         insensitive. The only major reason for this option is backward
-         compatibility when moving from DOS to OS2/LONG namespace support.
-         Long filenames (created by Win95) will not be affected.
-
-         This option does not solve the problem that filenames appear
-         differently under Linux and under Windows, since Windows does an
-         additional conversions on the client side. You can achieve similar
-         effects by saying Y to "Allow using of Native Language Support"
-         below.
-
-config NCPFS_NLS
-       bool "Use Native Language Support"
-       depends on NCP_FS
-       select NLS
-       help
-         Allows you to use codepages and I/O charsets for file name
-         translation between the server file system and input/output. This
-         may be useful, if you want to access the server with other operating
-         systems, e.g. Windows 95. See also NLS for more Information.
-
-         To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer.
-
-config NCPFS_EXTRAS
-       bool "Enable symbolic links and execute flags"
-       depends on NCP_FS
-       help
-         This enables the use of symbolic links and an execute permission
-         bit on NCPFS. The file server need not have long name space or NFS
-         name space loaded for these to work.
-
-         To use the new attributes, it is recommended to use the flags
-         '-f 600 -d 755' on the ncpmount command line.
-
diff --git a/fs/ncpfs/Makefile b/fs/ncpfs/Makefile
deleted file mode 100644 (file)
index 66fe5f8..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the linux ncp filesystem routines.
-#
-
-obj-$(CONFIG_NCP_FS) += ncpfs.o
-
-ncpfs-y      := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \
-               ncpsign_kernel.o getopt.o
-
-ncpfs-$(CONFIG_NCPFS_EXTRAS)   += symlink.o
-ncpfs-$(CONFIG_NCPFS_NFS_NS)   += symlink.o
-
-# If you want debugging output, please uncomment the following line
-# ccflags-y := -DDEBUG_NCP=1
-
-CFLAGS_ncplib_kernel.o := -finline-functions
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
deleted file mode 100644 (file)
index 0c57c5c..0000000
+++ /dev/null
@@ -1,1232 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  dir.c
- *
- *  Copyright (C) 1995, 1996 by Volker Lendecke
- *  Modified for big endian by J.F. Chadima and David S. Miller
- *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- *  Modified 1998, 1999 Wolfram Pienkoss for NLS
- *  Modified 1999 Wolfram Pienkoss for directory caching
- *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
- *
- */
-
-
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/stat.h>
-#include <linux/kernel.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/namei.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-
-#include "ncp_fs.h"
-
-static void ncp_read_volume_list(struct file *, struct dir_context *,
-                               struct ncp_cache_control *);
-static void ncp_do_readdir(struct file *, struct dir_context *,
-                               struct ncp_cache_control *);
-
-static int ncp_readdir(struct file *, struct dir_context *);
-
-static int ncp_create(struct inode *, struct dentry *, umode_t, bool);
-static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int);
-static int ncp_unlink(struct inode *, struct dentry *);
-static int ncp_mkdir(struct inode *, struct dentry *, umode_t);
-static int ncp_rmdir(struct inode *, struct dentry *);
-static int ncp_rename(struct inode *, struct dentry *,
-                     struct inode *, struct dentry *, unsigned int);
-static int ncp_mknod(struct inode * dir, struct dentry *dentry,
-                    umode_t mode, dev_t rdev);
-#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-extern int ncp_symlink(struct inode *, struct dentry *, const char *);
-#else
-#define ncp_symlink NULL
-#endif
-                     
-const struct file_operations ncp_dir_operations =
-{
-       .llseek         = generic_file_llseek,
-       .read           = generic_read_dir,
-       .iterate        = ncp_readdir,
-       .unlocked_ioctl = ncp_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = ncp_compat_ioctl,
-#endif
-};
-
-const struct inode_operations ncp_dir_inode_operations =
-{
-       .create         = ncp_create,
-       .lookup         = ncp_lookup,
-       .unlink         = ncp_unlink,
-       .symlink        = ncp_symlink,
-       .mkdir          = ncp_mkdir,
-       .rmdir          = ncp_rmdir,
-       .mknod          = ncp_mknod,
-       .rename         = ncp_rename,
-       .setattr        = ncp_notify_change,
-};
-
-/*
- * Dentry operations routines
- */
-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 *,
-               unsigned int, const char *, const struct qstr *);
-static int ncp_delete_dentry(const struct dentry *);
-static void ncp_d_prune(struct dentry *dentry);
-
-const struct dentry_operations ncp_dentry_operations =
-{
-       .d_revalidate   = ncp_lookup_validate,
-       .d_hash         = ncp_hash_dentry,
-       .d_compare      = ncp_compare_dentry,
-       .d_delete       = ncp_delete_dentry,
-       .d_prune        = ncp_d_prune,
-};
-
-#define ncp_namespace(i)       (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
-
-static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
-{
-#ifdef CONFIG_NCPFS_SMALLDOS
-       int ns = ncp_namespace(i);
-
-       if ((ns == NW_NS_DOS)
-#ifdef CONFIG_NCPFS_OS2_NS
-               || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
-#endif /* CONFIG_NCPFS_OS2_NS */
-          )
-               return 0;
-#endif /* CONFIG_NCPFS_SMALLDOS */
-       return 1;
-}
-
-#define ncp_preserve_case(i)   (ncp_namespace(i) != NW_NS_DOS)
-
-static inline int ncp_case_sensitive(const struct inode *i)
-{
-#ifdef CONFIG_NCPFS_NFS_NS
-       return ncp_namespace(i) == NW_NS_NFS;
-#else
-       return 0;
-#endif /* CONFIG_NCPFS_NFS_NS */
-}
-
-/*
- * Note: leave the hash unchanged if the directory
- * is case-sensitive.
- */
-static int 
-ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
-{
-       struct inode *inode = d_inode_rcu(dentry);
-
-       if (!inode)
-               return 0;
-
-       if (!ncp_case_sensitive(inode)) {
-               struct nls_table *t;
-               unsigned long hash;
-               int i;
-
-               t = NCP_IO_TABLE(dentry->d_sb);
-               hash = init_name_hash(dentry);
-               for (i=0; i<this->len ; i++)
-                       hash = partial_name_hash(ncp_tolower(t, this->name[i]),
-                                                                       hash);
-               this->hash = end_name_hash(hash);
-       }
-       return 0;
-}
-
-static int
-ncp_compare_dentry(const struct dentry *dentry,
-               unsigned int len, const char *str, const struct qstr *name)
-{
-       struct inode *pinode;
-
-       if (len != name->len)
-               return 1;
-
-       pinode = d_inode_rcu(dentry->d_parent);
-       if (!pinode)
-               return 1;
-
-       if (ncp_case_sensitive(pinode))
-               return strncmp(str, name->name, len);
-
-       return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
-}
-
-/*
- * This is the callback from dput() when d_count is going to 0.
- * We use this to unhash dentries with bad inodes.
- * Closing files can be safely postponed until iput() - it's done there anyway.
- */
-static int
-ncp_delete_dentry(const struct dentry * dentry)
-{
-       struct inode *inode = d_inode(dentry);
-
-       if (inode) {
-               if (is_bad_inode(inode))
-                       return 1;
-       } else
-       {
-       /* N.B. Unhash negative dentries? */
-       }
-       return 0;
-}
-
-static inline int
-ncp_single_volume(struct ncp_server *server)
-{
-       return (server->m.mounted_vol[0] != '\0');
-}
-
-static inline int ncp_is_server_root(struct inode *inode)
-{
-       return !ncp_single_volume(NCP_SERVER(inode)) &&
-               is_root_inode(inode);
-}
-
-
-/*
- * This is the callback when the dcache has a lookup hit.
- */
-
-
-#ifdef CONFIG_NCPFS_STRONG
-/* try to delete a readonly file (NW R bit set) */
-
-static int
-ncp_force_unlink(struct inode *dir, struct dentry* dentry)
-{
-        int res=0x9c,res2;
-       struct nw_modify_dos_info info;
-       __le32 old_nwattr;
-       struct inode *inode;
-
-       memset(&info, 0, sizeof(info));
-       
-        /* remove the Read-Only flag on the NW server */
-       inode = d_inode(dentry);
-
-       old_nwattr = NCP_FINFO(inode)->nwattr;
-       info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
-       res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
-       if (res2)
-               goto leave_me;
-
-        /* now try again the delete operation */
-        res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
-
-        if (res)  /* delete failed, set R bit again */
-        {
-               info.attributes = old_nwattr;
-               res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
-               if (res2)
-                        goto leave_me;
-        }
-leave_me:
-        return(res);
-}
-#endif /* CONFIG_NCPFS_STRONG */
-
-#ifdef CONFIG_NCPFS_STRONG
-static int
-ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
-                 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
-{
-       struct nw_modify_dos_info info;
-        int res=0x90,res2;
-       struct inode *old_inode = d_inode(old_dentry);
-       __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
-       __le32 new_nwattr = 0; /* shut compiler warning */
-       int old_nwattr_changed = 0;
-       int new_nwattr_changed = 0;
-
-       memset(&info, 0, sizeof(info));
-       
-        /* remove the Read-Only flag on the NW server */
-
-       info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
-       res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
-       if (!res2)
-               old_nwattr_changed = 1;
-       if (new_dentry && d_really_is_positive(new_dentry)) {
-               new_nwattr = NCP_FINFO(d_inode(new_dentry))->nwattr;
-               info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
-               res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
-               if (!res2)
-                       new_nwattr_changed = 1;
-       }
-        /* now try again the rename operation */
-       /* but only if something really happened */
-       if (new_nwattr_changed || old_nwattr_changed) {
-               res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
-                                                   old_dir, _old_name,
-                                                   new_dir, _new_name);
-       } 
-       if (res)
-               goto leave_me;
-       /* file was successfully renamed, so:
-          do not set attributes on old file - it no longer exists
-          copy attributes from old file to new */
-       new_nwattr_changed = old_nwattr_changed;
-       new_nwattr = old_nwattr;
-       old_nwattr_changed = 0;
-       
-leave_me:;
-       if (old_nwattr_changed) {
-               info.attributes = old_nwattr;
-               res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
-               /* ignore errors */
-       }
-       if (new_nwattr_changed) {
-               info.attributes = new_nwattr;
-               res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
-               /* ignore errors */
-       }
-        return(res);
-}
-#endif /* CONFIG_NCPFS_STRONG */
-
-
-static int
-ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
-{
-       struct ncp_server *server;
-       struct dentry *parent;
-       struct inode *dir;
-       struct ncp_entry_info finfo;
-       int res, val = 0, len;
-       __u8 __name[NCP_MAXPATHLEN + 1];
-
-       if (dentry == dentry->d_sb->s_root)
-               return 1;
-
-       if (flags & LOOKUP_RCU)
-               return -ECHILD;
-
-       parent = dget_parent(dentry);
-       dir = d_inode(parent);
-
-       if (d_really_is_negative(dentry))
-               goto finished;
-
-       server = NCP_SERVER(dir);
-
-       /*
-        * Inspired by smbfs:
-        * The default validation is based on dentry age:
-        * We set the max age at mount time.  (But each
-        * successful server lookup renews the timestamp.)
-        */
-       val = NCP_TEST_AGE(server, dentry);
-       if (val)
-               goto finished;
-
-       ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n",
-               dentry, NCP_GET_AGE(dentry));
-
-       len = sizeof(__name);
-       if (ncp_is_server_root(dir)) {
-               res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
-                                dentry->d_name.len, 1);
-               if (!res) {
-                       res = ncp_lookup_volume(server, __name, &(finfo.i));
-                       if (!res)
-                               ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
-               }
-       } else {
-               res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
-                                dentry->d_name.len, !ncp_preserve_case(dir));
-               if (!res)
-                       res = ncp_obtain_info(server, dir, __name, &(finfo.i));
-       }
-       finfo.volume = finfo.i.volNumber;
-       ncp_dbg(2, "looked for %pd/%s, res=%d\n",
-               dentry->d_parent, __name, res);
-       /*
-        * If we didn't find it, or if it has a different dirEntNum to
-        * what we remember, it's not valid any more.
-        */
-       if (!res) {
-               struct inode *inode = d_inode(dentry);
-
-               inode_lock(inode);
-               if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
-                       ncp_new_dentry(dentry);
-                       val=1;
-               } else
-                       ncp_dbg(2, "found, but dirEntNum changed\n");
-
-               ncp_update_inode2(inode, &finfo);
-               inode_unlock(inode);
-       }
-
-finished:
-       ncp_dbg(2, "result=%d\n", val);
-       dput(parent);
-       return val;
-}
-
-static time_t ncp_obtain_mtime(struct dentry *dentry)
-{
-       struct inode *inode = d_inode(dentry);
-       struct ncp_server *server = NCP_SERVER(inode);
-       struct nw_info_struct i;
-
-       if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
-               return 0;
-
-       if (ncp_obtain_info(server, inode, NULL, &i))
-               return 0;
-
-       return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
-}
-
-static inline void
-ncp_invalidate_dircache_entries(struct dentry *parent)
-{
-       struct ncp_server *server = NCP_SERVER(d_inode(parent));
-       struct dentry *dentry;
-
-       spin_lock(&parent->d_lock);
-       list_for_each_entry(dentry, &parent->d_subdirs, d_child) {
-               dentry->d_fsdata = NULL;
-               ncp_age_dentry(server, dentry);
-       }
-       spin_unlock(&parent->d_lock);
-}
-
-static int ncp_readdir(struct file *file, struct dir_context *ctx)
-{
-       struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = d_inode(dentry);
-       struct page *page = NULL;
-       struct ncp_server *server = NCP_SERVER(inode);
-       union  ncp_dir_cache *cache = NULL;
-       struct ncp_cache_control ctl;
-       int result, mtime_valid = 0;
-       time_t mtime = 0;
-
-       ctl.page  = NULL;
-       ctl.cache = NULL;
-
-       ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos);
-
-       result = -EIO;
-       /* Do not generate '.' and '..' when server is dead. */
-       if (!ncp_conn_valid(server))
-               goto out;
-
-       result = 0;
-       if (!dir_emit_dots(file, ctx))
-               goto out;
-
-       page = grab_cache_page(&inode->i_data, 0);
-       if (!page)
-               goto read_really;
-
-       ctl.cache = cache = kmap(page);
-       ctl.head  = cache->head;
-
-       if (!PageUptodate(page) || !ctl.head.eof)
-               goto init_cache;
-
-       if (ctx->pos == 2) {
-               if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
-                       goto init_cache;
-
-               mtime = ncp_obtain_mtime(dentry);
-               mtime_valid = 1;
-               if ((!mtime) || (mtime != ctl.head.mtime))
-                       goto init_cache;
-       }
-
-       if (ctx->pos > ctl.head.end)
-               goto finished;
-
-       ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2);
-       ctl.ofs  = ctl.fpos / NCP_DIRCACHE_SIZE;
-       ctl.idx  = ctl.fpos % NCP_DIRCACHE_SIZE;
-
-       for (;;) {
-               if (ctl.ofs != 0) {
-                       ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
-                       if (!ctl.page)
-                               goto invalid_cache;
-                       ctl.cache = kmap(ctl.page);
-                       if (!PageUptodate(ctl.page))
-                               goto invalid_cache;
-               }
-               while (ctl.idx < NCP_DIRCACHE_SIZE) {
-                       struct dentry *dent;
-                       bool over;
-
-                       spin_lock(&dentry->d_lock);
-                       if (!(NCP_FINFO(inode)->flags & NCPI_DIR_CACHE)) { 
-                               spin_unlock(&dentry->d_lock);
-                               goto invalid_cache;
-                       }
-                       dent = ctl.cache->dentry[ctl.idx];
-                       if (unlikely(!lockref_get_not_dead(&dent->d_lockref))) {
-                               spin_unlock(&dentry->d_lock);
-                               goto invalid_cache;
-                       }
-                       spin_unlock(&dentry->d_lock);
-                       if (d_really_is_negative(dent)) {
-                               dput(dent);
-                               goto invalid_cache;
-                       }
-                       over = !dir_emit(ctx, dent->d_name.name,
-                                       dent->d_name.len,
-                                       d_inode(dent)->i_ino, DT_UNKNOWN);
-                       dput(dent);
-                       if (over)
-                               goto finished;
-                       ctx->pos += 1;
-                       ctl.idx += 1;
-                       if (ctx->pos > ctl.head.end)
-                               goto finished;
-               }
-               if (ctl.page) {
-                       kunmap(ctl.page);
-                       SetPageUptodate(ctl.page);
-                       unlock_page(ctl.page);
-                       put_page(ctl.page);
-                       ctl.page = NULL;
-               }
-               ctl.idx  = 0;
-               ctl.ofs += 1;
-       }
-invalid_cache:
-       if (ctl.page) {
-               kunmap(ctl.page);
-               unlock_page(ctl.page);
-               put_page(ctl.page);
-               ctl.page = NULL;
-       }
-       ctl.cache = cache;
-init_cache:
-       ncp_invalidate_dircache_entries(dentry);
-       if (!mtime_valid) {
-               mtime = ncp_obtain_mtime(dentry);
-               mtime_valid = 1;
-       }
-       ctl.head.mtime = mtime;
-       ctl.head.time = jiffies;
-       ctl.head.eof = 0;
-       ctl.fpos = 2;
-       ctl.ofs = 0;
-       ctl.idx = NCP_DIRCACHE_START;
-       ctl.filled = 0;
-       ctl.valid  = 1;
-read_really:
-       spin_lock(&dentry->d_lock);
-       NCP_FINFO(inode)->flags |= NCPI_DIR_CACHE;
-       spin_unlock(&dentry->d_lock);
-       if (ncp_is_server_root(inode)) {
-               ncp_read_volume_list(file, ctx, &ctl);
-       } else {
-               ncp_do_readdir(file, ctx, &ctl);
-       }
-       ctl.head.end = ctl.fpos - 1;
-       ctl.head.eof = ctl.valid;
-finished:
-       if (ctl.page) {
-               kunmap(ctl.page);
-               SetPageUptodate(ctl.page);
-               unlock_page(ctl.page);
-               put_page(ctl.page);
-       }
-       if (page) {
-               cache->head = ctl.head;
-               kunmap(page);
-               SetPageUptodate(page);
-               unlock_page(page);
-               put_page(page);
-       }
-out:
-       return result;
-}
-
-static void ncp_d_prune(struct dentry *dentry)
-{
-       if (!dentry->d_fsdata)  /* not referenced from page cache */
-               return;
-       NCP_FINFO(d_inode(dentry->d_parent))->flags &= ~NCPI_DIR_CACHE;
-}
-
-static int
-ncp_fill_cache(struct file *file, struct dir_context *ctx,
-               struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
-               int inval_childs)
-{
-       struct dentry *newdent, *dentry = file->f_path.dentry;
-       struct inode *dir = d_inode(dentry);
-       struct ncp_cache_control ctl = *ctrl;
-       struct qstr qname;
-       int valid = 0;
-       int hashed = 0;
-       ino_t ino = 0;
-       __u8 __name[NCP_MAXPATHLEN + 1];
-
-       qname.len = sizeof(__name);
-       if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
-                       entry->i.entryName, entry->i.nameLen,
-                       !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
-               return 1; /* I'm not sure */
-
-       qname.name = __name;
-
-       newdent = d_hash_and_lookup(dentry, &qname);
-       if (IS_ERR(newdent))
-               goto end_advance;
-       if (!newdent) {
-               newdent = d_alloc(dentry, &qname);
-               if (!newdent)
-                       goto end_advance;
-       } else {
-               hashed = 1;
-
-               /* If case sensitivity changed for this volume, all entries below this one
-                  should be thrown away.  This entry itself is not affected, as its case
-                  sensitivity is controlled by its own parent. */
-               if (inval_childs)
-                       shrink_dcache_parent(newdent);
-
-               /*
-                * NetWare's OS2 namespace is case preserving yet case
-                * insensitive.  So we update dentry's name as received from
-                * server. Parent dir's i_mutex is locked because we're in
-                * readdir.
-                */
-               dentry_update_name_case(newdent, &qname);
-       }
-
-       if (d_really_is_negative(newdent)) {
-               struct inode *inode;
-
-               entry->opened = 0;
-               entry->ino = iunique(dir->i_sb, 2);
-               inode = ncp_iget(dir->i_sb, entry);
-               if (inode) {
-                       d_instantiate(newdent, inode);
-                       if (!hashed)
-                               d_rehash(newdent);
-               } else {
-                       spin_lock(&dentry->d_lock);
-                       NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE;
-                       spin_unlock(&dentry->d_lock);
-               }
-       } else {
-               struct inode *inode = d_inode(newdent);
-
-               inode_lock_nested(inode, I_MUTEX_CHILD);
-               ncp_update_inode2(inode, entry);
-               inode_unlock(inode);
-       }
-
-       if (ctl.idx >= NCP_DIRCACHE_SIZE) {
-               if (ctl.page) {
-                       kunmap(ctl.page);
-                       SetPageUptodate(ctl.page);
-                       unlock_page(ctl.page);
-                       put_page(ctl.page);
-               }
-               ctl.cache = NULL;
-               ctl.idx  -= NCP_DIRCACHE_SIZE;
-               ctl.ofs  += 1;
-               ctl.page  = grab_cache_page(&dir->i_data, ctl.ofs);
-               if (ctl.page)
-                       ctl.cache = kmap(ctl.page);
-       }
-       if (ctl.cache) {
-               if (d_really_is_positive(newdent)) {
-                       newdent->d_fsdata = newdent;
-                       ctl.cache->dentry[ctl.idx] = newdent;
-                       ino = d_inode(newdent)->i_ino;
-                       ncp_new_dentry(newdent);
-               }
-               valid = 1;
-       }
-       dput(newdent);
-end_advance:
-       if (!valid)
-               ctl.valid = 0;
-       if (!ctl.filled && (ctl.fpos == ctx->pos)) {
-               if (!ino)
-                       ino = iunique(dir->i_sb, 2);
-               ctl.filled = !dir_emit(ctx, qname.name, qname.len,
-                                    ino, DT_UNKNOWN);
-               if (!ctl.filled)
-                       ctx->pos += 1;
-       }
-       ctl.fpos += 1;
-       ctl.idx  += 1;
-       *ctrl = ctl;
-       return (ctl.valid || !ctl.filled);
-}
-
-static void
-ncp_read_volume_list(struct file *file, struct dir_context *ctx,
-                       struct ncp_cache_control *ctl)
-{
-       struct inode *inode = file_inode(file);
-       struct ncp_server *server = NCP_SERVER(inode);
-       struct ncp_volume_info info;
-       struct ncp_entry_info entry;
-       int i;
-
-       ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->pos);
-
-       for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
-               int inval_dentry;
-
-               if (ncp_get_volume_info_with_number(server, i, &info) != 0)
-                       return;
-               if (!strlen(info.volume_name))
-                       continue;
-
-               ncp_dbg(1, "found vol: %s\n", info.volume_name);
-
-               if (ncp_lookup_volume(server, info.volume_name,
-                                       &entry.i)) {
-                       ncp_dbg(1, "could not lookup vol %s\n",
-                               info.volume_name);
-                       continue;
-               }
-               inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
-               entry.volume = entry.i.volNumber;
-               if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry))
-                       return;
-       }
-}
-
-static void
-ncp_do_readdir(struct file *file, struct dir_context *ctx,
-                                               struct ncp_cache_control *ctl)
-{
-       struct inode *dir = file_inode(file);
-       struct ncp_server *server = NCP_SERVER(dir);
-       struct nw_search_sequence seq;
-       struct ncp_entry_info entry;
-       int err;
-       void* buf;
-       int more;
-       size_t bufsize;
-
-       ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos);
-       ncp_vdbg("init %pD, volnum=%d, dirent=%u\n",
-                file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
-
-       err = ncp_initialize_search(server, dir, &seq);
-       if (err) {
-               ncp_dbg(1, "init failed, err=%d\n", err);
-               return;
-       }
-       /* We MUST NOT use server->buffer_size handshaked with server if we are
-          using UDP, as for UDP server uses max. buffer size determined by
-          MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 
-          So we use 128KB, just to be sure, as there is no way how to know
-          this value in advance. */
-       bufsize = 131072;
-       buf = vmalloc(bufsize);
-       if (!buf)
-               return;
-       do {
-               int cnt;
-               char* rpl;
-               size_t rpls;
-
-               err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
-               if (err)                /* Error */
-                       break;
-               if (!cnt)               /* prevent endless loop */
-                       break;
-               while (cnt--) {
-                       size_t onerpl;
-                       
-                       if (rpls < offsetof(struct nw_info_struct, entryName))
-                               break;  /* short packet */
-                       ncp_extract_file_info(rpl, &entry.i);
-                       onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
-                       if (rpls < onerpl)
-                               break;  /* short packet */
-                       (void)ncp_obtain_nfs_info(server, &entry.i);
-                       rpl += onerpl;
-                       rpls -= onerpl;
-                       entry.volume = entry.i.volNumber;
-                       if (!ncp_fill_cache(file, ctx, ctl, &entry, 0))
-                               break;
-               }
-       } while (more);
-       vfree(buf);
-       return;
-}
-
-int ncp_conn_logged_in(struct super_block *sb)
-{
-       struct ncp_server* server = NCP_SBP(sb);
-       int result;
-
-       if (ncp_single_volume(server)) {
-               int len;
-               struct dentry* dent;
-               __u32 volNumber;
-               __le32 dirEntNum;
-               __le32 DosDirNum;
-               __u8 __name[NCP_MAXPATHLEN + 1];
-
-               len = sizeof(__name);
-               result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
-                                   strlen(server->m.mounted_vol), 1);
-               if (result)
-                       goto out;
-               result = -ENOENT;
-               if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
-                       ncp_vdbg("%s not found\n", server->m.mounted_vol);
-                       goto out;
-               }
-               dent = sb->s_root;
-               if (dent) {
-                       struct inode* ino = d_inode(dent);
-                       if (ino) {
-                               ncp_update_known_namespace(server, volNumber, NULL);
-                               NCP_FINFO(ino)->volNumber = volNumber;
-                               NCP_FINFO(ino)->dirEntNum = dirEntNum;
-                               NCP_FINFO(ino)->DosDirNum = DosDirNum;
-                               result = 0;
-                       } else {
-                               ncp_dbg(1, "d_inode(sb->s_root) == NULL!\n");
-                       }
-               } else {
-                       ncp_dbg(1, "sb->s_root == NULL!\n");
-               }
-       } else
-               result = 0;
-
-out:
-       return result;
-}
-
-static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
-{
-       struct ncp_server *server = NCP_SERVER(dir);
-       struct inode *inode = NULL;
-       struct ncp_entry_info finfo;
-       int error, res, len;
-       __u8 __name[NCP_MAXPATHLEN + 1];
-
-       error = -EIO;
-       if (!ncp_conn_valid(server))
-               goto finished;
-
-       ncp_vdbg("server lookup for %pd2\n", dentry);
-
-       len = sizeof(__name);
-       if (ncp_is_server_root(dir)) {
-               res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
-                                dentry->d_name.len, 1);
-               if (!res)
-                       res = ncp_lookup_volume(server, __name, &(finfo.i));
-               if (!res)
-                       ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
-       } else {
-               res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
-                                dentry->d_name.len, !ncp_preserve_case(dir));
-               if (!res)
-                       res = ncp_obtain_info(server, dir, __name, &(finfo.i));
-       }
-       ncp_vdbg("looked for %pd2, res=%d\n", dentry, res);
-       /*
-        * If we didn't find an entry, make a negative dentry.
-        */
-       if (res)
-               goto add_entry;
-
-       /*
-        * Create an inode for the entry.
-        */
-       finfo.opened = 0;
-       finfo.ino = iunique(dir->i_sb, 2);
-       finfo.volume = finfo.i.volNumber;
-       error = -EACCES;
-       inode = ncp_iget(dir->i_sb, &finfo);
-
-       if (inode) {
-               ncp_new_dentry(dentry);
-add_entry:
-               d_add(dentry, inode);
-               error = 0;
-       }
-
-finished:
-       ncp_vdbg("result=%d\n", error);
-       return ERR_PTR(error);
-}
-
-/*
- * This code is common to create, mkdir, and mknod.
- */
-static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
-                       struct ncp_entry_info *finfo)
-{
-       struct inode *inode;
-       int error = -EINVAL;
-
-       finfo->ino = iunique(dir->i_sb, 2);
-       inode = ncp_iget(dir->i_sb, finfo);
-       if (!inode)
-               goto out_close;
-       d_instantiate(dentry,inode);
-       error = 0;
-out:
-       return error;
-
-out_close:
-       ncp_vdbg("%pd2 failed, closing file\n", dentry);
-       ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
-       goto out;
-}
-
-int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
-                  dev_t rdev, __le32 attributes)
-{
-       struct ncp_server *server = NCP_SERVER(dir);
-       struct ncp_entry_info finfo;
-       int error, result, len;
-       int opmode;
-       __u8 __name[NCP_MAXPATHLEN + 1];
-       
-       ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode);
-
-       ncp_age_dentry(server, dentry);
-       len = sizeof(__name);
-       error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
-                          dentry->d_name.len, !ncp_preserve_case(dir));
-       if (error)
-               goto out;
-
-       error = -EACCES;
-       
-       if (S_ISREG(mode) && 
-           (server->m.flags & NCP_MOUNT_EXTRAS) && 
-           (mode & S_IXUGO))
-               attributes |= aSYSTEM | aSHARED;
-       
-       result = ncp_open_create_file_or_subdir(server, dir, __name,
-                               OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
-                               attributes, AR_READ | AR_WRITE, &finfo);
-       opmode = O_RDWR;
-       if (result) {
-               result = ncp_open_create_file_or_subdir(server, dir, __name,
-                               OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
-                               attributes, AR_WRITE, &finfo);
-               if (result) {
-                       if (result == 0x87)
-                               error = -ENAMETOOLONG;
-                       else if (result < 0)
-                               error = result;
-                       ncp_dbg(1, "%pd2 failed\n", dentry);
-                       goto out;
-               }
-               opmode = O_WRONLY;
-       }
-       finfo.access = opmode;
-       if (ncp_is_nfs_extras(server, finfo.volume)) {
-               finfo.i.nfs.mode = mode;
-               finfo.i.nfs.rdev = new_encode_dev(rdev);
-               if (ncp_modify_nfs_info(server, finfo.volume,
-                                       finfo.i.dirEntNum,
-                                       mode, new_encode_dev(rdev)) != 0)
-                       goto out;
-       }
-
-       error = ncp_instantiate(dir, dentry, &finfo);
-out:
-       return error;
-}
-
-static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               bool excl)
-{
-       return ncp_create_new(dir, dentry, mode, 0, 0);
-}
-
-static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
-{
-       struct ncp_entry_info finfo;
-       struct ncp_server *server = NCP_SERVER(dir);
-       int error, len;
-       __u8 __name[NCP_MAXPATHLEN + 1];
-
-       ncp_dbg(1, "making %pd2\n", dentry);
-
-       ncp_age_dentry(server, dentry);
-       len = sizeof(__name);
-       error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
-                          dentry->d_name.len, !ncp_preserve_case(dir));
-       if (error)
-               goto out;
-
-       error = ncp_open_create_file_or_subdir(server, dir, __name,
-                                          OC_MODE_CREATE, aDIR,
-                                          cpu_to_le16(0xffff),
-                                          &finfo);
-       if (error == 0) {
-               if (ncp_is_nfs_extras(server, finfo.volume)) {
-                       mode |= S_IFDIR;
-                       finfo.i.nfs.mode = mode;
-                       if (ncp_modify_nfs_info(server,
-                                               finfo.volume,
-                                               finfo.i.dirEntNum,
-                                               mode, 0) != 0)
-                               goto out;
-               }
-               error = ncp_instantiate(dir, dentry, &finfo);
-       } else if (error > 0) {
-               error = -EACCES;
-       }
-out:
-       return error;
-}
-
-static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
-{
-       struct ncp_server *server = NCP_SERVER(dir);
-       int error, result, len;
-       __u8 __name[NCP_MAXPATHLEN + 1];
-
-       ncp_dbg(1, "removing %pd2\n", dentry);
-
-       len = sizeof(__name);
-       error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
-                          dentry->d_name.len, !ncp_preserve_case(dir));
-       if (error)
-               goto out;
-
-       result = ncp_del_file_or_subdir(server, dir, __name);
-       switch (result) {
-               case 0x00:
-                       error = 0;
-                       break;
-               case 0x85:      /* unauthorized to delete file */
-               case 0x8A:      /* unauthorized to delete file */
-                       error = -EACCES;
-                       break;
-               case 0x8F:
-               case 0x90:      /* read only */
-                       error = -EPERM;
-                       break;
-               case 0x9F:      /* in use by another client */
-                       error = -EBUSY;
-                       break;
-               case 0xA0:      /* directory not empty */
-                       error = -ENOTEMPTY;
-                       break;
-               case 0xFF:      /* someone deleted file */
-                       error = -ENOENT;
-                       break;
-               default:
-                       error = result < 0 ? result : -EACCES;
-                       break;
-               }
-out:
-       return error;
-}
-
-static int ncp_unlink(struct inode *dir, struct dentry *dentry)
-{
-       struct inode *inode = d_inode(dentry);
-       struct ncp_server *server;
-       int error;
-
-       server = NCP_SERVER(dir);
-       ncp_dbg(1, "unlinking %pd2\n", dentry);
-       
-       /*
-        * Check whether to close the file ...
-        */
-       if (inode) {
-               ncp_vdbg("closing file\n");
-               ncp_make_closed(inode);
-       }
-
-       error = ncp_del_file_or_subdir2(server, dentry);
-#ifdef CONFIG_NCPFS_STRONG
-       /* 9C is Invalid path.. It should be 8F, 90 - read only, but
-          it is not :-( */
-       if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
-               error = ncp_force_unlink(dir, dentry);
-       }
-#endif
-       switch (error) {
-               case 0x00:
-                       ncp_dbg(1, "removed %pd2\n", dentry);
-                       break;
-               case 0x85:
-               case 0x8A:
-                       error = -EACCES;
-                       break;
-               case 0x8D:      /* some files in use */
-               case 0x8E:      /* all files in use */
-                       error = -EBUSY;
-                       break;
-               case 0x8F:      /* some read only */
-               case 0x90:      /* all read only */
-               case 0x9C:      /* !!! returned when in-use or read-only by NW4 */
-                       error = -EPERM;
-                       break;
-               case 0xFF:
-                       error = -ENOENT;
-                       break;
-               default:
-                       error = error < 0 ? error : -EACCES;
-                       break;
-       }
-       return error;
-}
-
-static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
-                     struct inode *new_dir, struct dentry *new_dentry,
-                     unsigned int flags)
-{
-       struct ncp_server *server = NCP_SERVER(old_dir);
-       int error;
-       int old_len, new_len;
-       __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
-
-       if (flags)
-               return -EINVAL;
-
-       ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry);
-
-       ncp_age_dentry(server, old_dentry);
-       ncp_age_dentry(server, new_dentry);
-
-       old_len = sizeof(__old_name);
-       error = ncp_io2vol(server, __old_name, &old_len,
-                          old_dentry->d_name.name, old_dentry->d_name.len,
-                          !ncp_preserve_case(old_dir));
-       if (error)
-               goto out;
-
-       new_len = sizeof(__new_name);
-       error = ncp_io2vol(server, __new_name, &new_len,
-                          new_dentry->d_name.name, new_dentry->d_name.len,
-                          !ncp_preserve_case(new_dir));
-       if (error)
-               goto out;
-
-       error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
-                                                     new_dir, __new_name);
-#ifdef CONFIG_NCPFS_STRONG
-       if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
-                       server->m.flags & NCP_MOUNT_STRONG) {   /* RO */
-               error = ncp_force_rename(old_dir, old_dentry, __old_name,
-                                        new_dir, new_dentry, __new_name);
-       }
-#endif
-       switch (error) {
-               case 0x00:
-                       ncp_dbg(1, "renamed %pd -> %pd\n",
-                               old_dentry, new_dentry);
-                       ncp_d_prune(old_dentry);
-                       ncp_d_prune(new_dentry);
-                       break;
-               case 0x9E:
-                       error = -ENAMETOOLONG;
-                       break;
-               case 0xFF:
-                       error = -ENOENT;
-                       break;
-               default:
-                       error = error < 0 ? error : -EACCES;
-                       break;
-       }
-out:
-       return error;
-}
-
-static int ncp_mknod(struct inode * dir, struct dentry *dentry,
-                    umode_t mode, dev_t rdev)
-{
-       if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
-               ncp_dbg(1, "mode = 0%ho\n", mode);
-               return ncp_create_new(dir, dentry, mode, rdev, 0);
-       }
-       return -EPERM; /* Strange, but true */
-}
-
-/* The following routines are taken directly from msdos-fs */
-
-/* Linear day numbers of the respective 1sts in non-leap years. */
-
-static int day_n[] =
-{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
-/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
-
-static int utc2local(int time)
-{
-       return time - sys_tz.tz_minuteswest * 60;
-}
-
-static int local2utc(int time)
-{
-       return time + sys_tz.tz_minuteswest * 60;
-}
-
-/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
-int
-ncp_date_dos2unix(__le16 t, __le16 d)
-{
-       unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
-       int month, year, secs;
-
-       /* first subtract and mask after that... Otherwise, if
-          date == 0, bad things happen */
-       month = ((date >> 5) - 1) & 15;
-       year = date >> 9;
-       secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
-               86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 
-               year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
-       /* days since 1.1.70 plus 80's leap day */
-       return local2utc(secs);
-}
-
-
-/* Convert linear UNIX date to a MS-DOS time/date pair. */
-void
-ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
-{
-       int day, year, nl_day, month;
-
-       unix_date = utc2local(unix_date);
-       *time = cpu_to_le16(
-               (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
-               (((unix_date / 3600) % 24) << 11));
-       day = unix_date / 86400 - 3652;
-       year = day / 365;
-       if ((year + 3) / 4 + 365 * year > day)
-               year--;
-       day -= (year + 3) / 4 + 365 * year;
-       if (day == 59 && !(year & 3)) {
-               nl_day = day;
-               month = 2;
-       } else {
-               nl_day = (year & 3) || day <= 59 ? day : day - 1;
-               for (month = 1; month < 12; month++)
-                       if (day_n[month] > nl_day)
-                               break;
-       }
-       *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
-}
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
deleted file mode 100644 (file)
index 8f8cc03..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  file.c
- *
- *  Copyright (C) 1995, 1996 by Volker Lendecke
- *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/uaccess.h>
-
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-
-#include "ncp_fs.h"
-
-static int ncp_fsync(struct file *file, loff_t start, loff_t end, int datasync)
-{
-       return file_write_and_wait_range(file, start, end);
-}
-
-/*
- * Open a file with the specified read/write mode.
- */
-int ncp_make_open(struct inode *inode, int right)
-{
-       int error;
-       int access;
-
-       error = -EINVAL;
-       if (!inode) {
-               pr_err("%s: got NULL inode\n", __func__);
-               goto out;
-       }
-
-       ncp_dbg(1, "opened=%d, volume # %u, dir entry # %u\n",
-               atomic_read(&NCP_FINFO(inode)->opened), 
-               NCP_FINFO(inode)->volNumber, 
-               NCP_FINFO(inode)->dirEntNum);
-       error = -EACCES;
-       mutex_lock(&NCP_FINFO(inode)->open_mutex);
-       if (!atomic_read(&NCP_FINFO(inode)->opened)) {
-               struct ncp_entry_info finfo;
-               int result;
-
-               /* tries max. rights */
-               finfo.access = O_RDWR;
-               result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
-                                       inode, NULL, OC_MODE_OPEN,
-                                       0, AR_READ | AR_WRITE, &finfo);
-               if (!result)
-                       goto update;
-               /* RDWR did not succeeded, try readonly or writeonly as requested */
-               switch (right) {
-                       case O_RDONLY:
-                               finfo.access = O_RDONLY;
-                               result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
-                                       inode, NULL, OC_MODE_OPEN,
-                                       0, AR_READ, &finfo);
-                               break;
-                       case O_WRONLY:
-                               finfo.access = O_WRONLY;
-                               result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
-                                       inode, NULL, OC_MODE_OPEN,
-                                       0, AR_WRITE, &finfo);
-                               break;
-               }
-               if (result) {
-                       ncp_vdbg("failed, result=%d\n", result);
-                       goto out_unlock;
-               }
-               /*
-                * Update the inode information.
-                */
-       update:
-               ncp_update_inode(inode, &finfo);
-               atomic_set(&NCP_FINFO(inode)->opened, 1);
-       }
-
-       access = NCP_FINFO(inode)->access;
-       ncp_vdbg("file open, access=%x\n", access);
-       if (access == right || access == O_RDWR) {
-               atomic_inc(&NCP_FINFO(inode)->opened);
-               error = 0;
-       }
-
-out_unlock:
-       mutex_unlock(&NCP_FINFO(inode)->open_mutex);
-out:
-       return error;
-}
-
-static ssize_t
-ncp_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
-{
-       struct file *file = iocb->ki_filp;
-       struct inode *inode = file_inode(file);
-       size_t already_read = 0;
-       off_t pos = iocb->ki_pos;
-       size_t bufsize;
-       int error;
-       void *freepage;
-       size_t freelen;
-
-       ncp_dbg(1, "enter %pD2\n", file);
-
-       if (!iov_iter_count(to))
-               return 0;
-       if (pos > inode->i_sb->s_maxbytes)
-               return 0;
-       iov_iter_truncate(to, inode->i_sb->s_maxbytes - pos);
-
-       error = ncp_make_open(inode, O_RDONLY);
-       if (error) {
-               ncp_dbg(1, "open failed, error=%d\n", error);
-               return error;
-       }
-
-       bufsize = NCP_SERVER(inode)->buffer_size;
-
-       error = -EIO;
-       freelen = ncp_read_bounce_size(bufsize);
-       freepage = vmalloc(freelen);
-       if (!freepage)
-               goto outrel;
-       error = 0;
-       /* First read in as much as possible for each bufsize. */
-       while (iov_iter_count(to)) {
-               int read_this_time;
-               size_t to_read = min_t(size_t,
-                                    bufsize - (pos % bufsize),
-                                    iov_iter_count(to));
-
-               error = ncp_read_bounce(NCP_SERVER(inode),
-                               NCP_FINFO(inode)->file_handle,
-                               pos, to_read, to, &read_this_time, 
-                               freepage, freelen);
-               if (error) {
-                       error = -EIO;   /* NW errno -> Linux errno */
-                       break;
-               }
-               pos += read_this_time;
-               already_read += read_this_time;
-
-               if (read_this_time != to_read)
-                       break;
-       }
-       vfree(freepage);
-
-       iocb->ki_pos = pos;
-
-       file_accessed(file);
-
-       ncp_dbg(1, "exit %pD2\n", file);
-outrel:
-       ncp_inode_close(inode);         
-       return already_read ? already_read : error;
-}
-
-static ssize_t
-ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
-{
-       struct file *file = iocb->ki_filp;
-       struct inode *inode = file_inode(file);
-       size_t already_written = 0;
-       size_t bufsize;
-       int errno;
-       void *bouncebuffer;
-       off_t pos;
-
-       ncp_dbg(1, "enter %pD2\n", file);
-       errno = generic_write_checks(iocb, from);
-       if (errno <= 0)
-               return errno;
-
-       errno = ncp_make_open(inode, O_WRONLY);
-       if (errno) {
-               ncp_dbg(1, "open failed, error=%d\n", errno);
-               return errno;
-       }
-       bufsize = NCP_SERVER(inode)->buffer_size;
-
-       errno = file_update_time(file);
-       if (errno)
-               goto outrel;
-
-       bouncebuffer = vmalloc(bufsize);
-       if (!bouncebuffer) {
-               errno = -EIO;   /* -ENOMEM */
-               goto outrel;
-       }
-       pos = iocb->ki_pos;
-       while (iov_iter_count(from)) {
-               int written_this_time;
-               size_t to_write = min_t(size_t,
-                                     bufsize - (pos % bufsize),
-                                     iov_iter_count(from));
-
-               if (!copy_from_iter_full(bouncebuffer, to_write, from)) {
-                       errno = -EFAULT;
-                       break;
-               }
-               if (ncp_write_kernel(NCP_SERVER(inode), 
-                   NCP_FINFO(inode)->file_handle,
-                   pos, to_write, bouncebuffer, &written_this_time) != 0) {
-                       errno = -EIO;
-                       break;
-               }
-               pos += written_this_time;
-               already_written += written_this_time;
-
-               if (written_this_time != to_write)
-                       break;
-       }
-       vfree(bouncebuffer);
-
-       iocb->ki_pos = pos;
-
-       if (pos > i_size_read(inode)) {
-               inode_lock(inode);
-               if (pos > i_size_read(inode))
-                       i_size_write(inode, pos);
-               inode_unlock(inode);
-       }
-       ncp_dbg(1, "exit %pD2\n", file);
-outrel:
-       ncp_inode_close(inode);         
-       return already_written ? already_written : errno;
-}
-
-static int ncp_release(struct inode *inode, struct file *file) {
-       if (ncp_make_closed(inode)) {
-               ncp_dbg(1, "failed to close\n");
-       }
-       return 0;
-}
-
-const struct file_operations ncp_file_operations =
-{
-       .llseek         = generic_file_llseek,
-       .read_iter      = ncp_file_read_iter,
-       .write_iter     = ncp_file_write_iter,
-       .unlocked_ioctl = ncp_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = ncp_compat_ioctl,
-#endif
-       .mmap           = ncp_mmap,
-       .release        = ncp_release,
-       .fsync          = ncp_fsync,
-};
-
-const struct inode_operations ncp_file_inode_operations =
-{
-       .setattr        = ncp_notify_change,
-};
diff --git a/fs/ncpfs/getopt.c b/fs/ncpfs/getopt.c
deleted file mode 100644 (file)
index 5c941be..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * getopt.c
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include <asm/errno.h>
-
-#include "getopt.h"
-
-/**
- *     ncp_getopt - option parser
- *     @caller: name of the caller, for error messages
- *     @options: the options string
- *     @opts: an array of &struct option entries controlling parser operations
- *     @optopt: output; will contain the current option
- *     @optarg: output; will contain the value (if one exists)
- *     @value: output; may be NULL; will be overwritten with the integer value
- *             of the current argument.
- *
- *     Helper to parse options on the format used by mount ("a=b,c=d,e,f").
- *     Returns opts->val if a matching entry in the 'opts' array is found,
- *     0 when no more tokens are found, -1 if an error is encountered.
- */
-int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts,
-              char **optopt, char **optarg, unsigned long *value)
-{
-       char *token;
-       char *val;
-
-       do {
-               if ((token = strsep(options, ",")) == NULL)
-                       return 0;
-       } while (*token == '\0');
-       if (optopt)
-               *optopt = token;
-
-       if ((val = strchr (token, '=')) != NULL) {
-               *val++ = 0;
-       }
-       *optarg = val;
-       for (; opts->name; opts++) {
-               if (!strcmp(opts->name, token)) {
-                       if (!val) {
-                               if (opts->has_arg & OPT_NOPARAM) {
-                                       return opts->val;
-                               }
-                               pr_info("%s: the %s option requires an argument\n",
-                                       caller, token);
-                               return -EINVAL;
-                       }
-                       if (opts->has_arg & OPT_INT) {
-                               int rc = kstrtoul(val, 0, value);
-
-                               if (rc) {
-                                       pr_info("%s: invalid numeric value in %s=%s\n",
-                                               caller, token, val);
-                                       return rc;
-                               }
-                               return opts->val;
-                       }
-                       if (opts->has_arg & OPT_STRING) {
-                               return opts->val;
-                       }
-                       pr_info("%s: unexpected argument %s to the %s option\n",
-                               caller, val, token);
-                       return -EINVAL;
-               }
-       }
-       pr_info("%s: Unrecognized mount option %s\n", caller, token);
-       return -EOPNOTSUPP;
-}
diff --git a/fs/ncpfs/getopt.h b/fs/ncpfs/getopt.h
deleted file mode 100644 (file)
index 30f0da3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _LINUX_GETOPT_H
-#define _LINUX_GETOPT_H
-
-#define OPT_NOPARAM    1
-#define OPT_INT                2
-#define OPT_STRING     4
-struct ncp_option {
-       const char *name;
-       unsigned int has_arg;
-       int val;
-};
-
-extern int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts,
-                     char **optopt, char **optarg, unsigned long *value);
-
-#endif /* _LINUX_GETOPT_H */
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
deleted file mode 100644 (file)
index 41de88c..0000000
+++ /dev/null
@@ -1,1066 +0,0 @@
-/*
- *  inode.c
- *
- *  Copyright (C) 1995, 1996 by Volker Lendecke
- *  Modified for big endian by J.F. Chadima and David S. Miller
- *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- *  Modified 1998 Wolfram Pienkoss for NLS
- *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/file.h>
-#include <linux/fcntl.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/vfs.h>
-#include <linux/mount.h>
-#include <linux/seq_file.h>
-#include <linux/sched/signal.h>
-#include <linux/namei.h>
-
-#include <net/sock.h>
-
-#include "ncp_fs.h"
-#include "getopt.h"
-
-#define NCP_DEFAULT_FILE_MODE 0600
-#define NCP_DEFAULT_DIR_MODE 0700
-#define NCP_DEFAULT_TIME_OUT 10
-#define NCP_DEFAULT_RETRY_COUNT 20
-
-static void ncp_evict_inode(struct inode *);
-static void ncp_put_super(struct super_block *);
-static int  ncp_statfs(struct dentry *, struct kstatfs *);
-static int  ncp_show_options(struct seq_file *, struct dentry *);
-
-static struct kmem_cache * ncp_inode_cachep;
-
-static struct inode *ncp_alloc_inode(struct super_block *sb)
-{
-       struct ncp_inode_info *ei;
-       ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
-       if (!ei)
-               return NULL;
-       return &ei->vfs_inode;
-}
-
-static void ncp_i_callback(struct rcu_head *head)
-{
-       struct inode *inode = container_of(head, struct inode, i_rcu);
-       kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
-}
-
-static void ncp_destroy_inode(struct inode *inode)
-{
-       call_rcu(&inode->i_rcu, ncp_i_callback);
-}
-
-static void init_once(void *foo)
-{
-       struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
-
-       mutex_init(&ei->open_mutex);
-       inode_init_once(&ei->vfs_inode);
-}
-
-static int init_inodecache(void)
-{
-       ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
-                                            sizeof(struct ncp_inode_info),
-                                            0, (SLAB_RECLAIM_ACCOUNT|
-                                               SLAB_MEM_SPREAD|SLAB_ACCOUNT),
-                                            init_once);
-       if (ncp_inode_cachep == NULL)
-               return -ENOMEM;
-       return 0;
-}
-
-static void destroy_inodecache(void)
-{
-       /*
-        * Make sure all delayed rcu free inodes are flushed before we
-        * destroy cache.
-        */
-       rcu_barrier();
-       kmem_cache_destroy(ncp_inode_cachep);
-}
-
-static int ncp_remount(struct super_block *sb, int *flags, char* data)
-{
-       sync_filesystem(sb);
-       *flags |= SB_NODIRATIME;
-       return 0;
-}
-
-static const struct super_operations ncp_sops =
-{
-       .alloc_inode    = ncp_alloc_inode,
-       .destroy_inode  = ncp_destroy_inode,
-       .drop_inode     = generic_delete_inode,
-       .evict_inode    = ncp_evict_inode,
-       .put_super      = ncp_put_super,
-       .statfs         = ncp_statfs,
-       .remount_fs     = ncp_remount,
-       .show_options   = ncp_show_options,
-};
-
-/*
- * Fill in the ncpfs-specific information in the inode.
- */
-static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
-{
-       NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
-       NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
-       NCP_FINFO(inode)->volNumber = nwinfo->volume;
-}
-
-void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
-{
-       ncp_update_dirent(inode, nwinfo);
-       NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
-       NCP_FINFO(inode)->access = nwinfo->access;
-       memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
-                       sizeof(nwinfo->file_handle));
-       ncp_dbg(1, "updated %s, volnum=%d, dirent=%u\n",
-               nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
-               NCP_FINFO(inode)->dirEntNum);
-}
-
-static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
-{
-       /* NFS namespace mode overrides others if it's set. */
-       ncp_dbg(1, "(%s) nfs.mode=0%o\n", nwi->entryName, nwi->nfs.mode);
-       if (nwi->nfs.mode) {
-               /* XXX Security? */
-               inode->i_mode = nwi->nfs.mode;
-       }
-
-       inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
-
-       inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
-       inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
-       inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
-       inode->i_atime.tv_nsec = 0;
-       inode->i_mtime.tv_nsec = 0;
-       inode->i_ctime.tv_nsec = 0;
-}
-
-static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
-{
-       struct nw_info_struct *nwi = &nwinfo->i;
-       struct ncp_server *server = NCP_SERVER(inode);
-
-       if (nwi->attributes & aDIR) {
-               inode->i_mode = server->m.dir_mode;
-               /* for directories dataStreamSize seems to be some
-                  Object ID ??? */
-               i_size_write(inode, NCP_BLOCK_SIZE);
-       } else {
-               u32 size;
-
-               inode->i_mode = server->m.file_mode;
-               size = le32_to_cpu(nwi->dataStreamSize);
-               i_size_write(inode, size);
-#ifdef CONFIG_NCPFS_EXTRAS
-               if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
-                && (nwi->attributes & aSHARED)) {
-                       switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
-                               case aHIDDEN:
-                                       if (server->m.flags & NCP_MOUNT_SYMLINKS) {
-                                               if (/* (size >= NCP_MIN_SYMLINK_SIZE)
-                                                && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
-                                                       inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
-                                                       NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
-                                                       break;
-                                               }
-                                       }
-                                       /* FALLTHROUGH */
-                               case 0:
-                                       if (server->m.flags & NCP_MOUNT_EXTRAS)
-                                               inode->i_mode |= S_IRUGO;
-                                       break;
-                               case aSYSTEM:
-                                       if (server->m.flags & NCP_MOUNT_EXTRAS)
-                                               inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
-                                       break;
-                               /* case aSYSTEM|aHIDDEN: */
-                               default:
-                                       /* reserved combination */
-                                       break;
-                       }
-               }
-#endif
-       }
-       if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
-}
-
-void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
-{
-       NCP_FINFO(inode)->flags = 0;
-       if (!atomic_read(&NCP_FINFO(inode)->opened)) {
-               NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
-               ncp_update_attrs(inode, nwinfo);
-       }
-
-       ncp_update_dates(inode, &nwinfo->i);
-       ncp_update_dirent(inode, nwinfo);
-}
-
-/*
- * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
- */
-static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
-{
-       struct ncp_server *server = NCP_SERVER(inode);
-
-       NCP_FINFO(inode)->flags = 0;
-       
-       ncp_update_attrs(inode, nwinfo);
-
-       ncp_dbg(2, "inode->i_mode = %u\n", inode->i_mode);
-
-       set_nlink(inode, 1);
-       inode->i_uid = server->m.uid;
-       inode->i_gid = server->m.gid;
-
-       ncp_update_dates(inode, &nwinfo->i);
-       ncp_update_inode(inode, nwinfo);
-}
-
-#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-static const struct inode_operations ncp_symlink_inode_operations = {
-       .get_link       = page_get_link,
-       .setattr        = ncp_notify_change,
-};
-#endif
-
-/*
- * Get a new inode.
- */
-struct inode * 
-ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
-{
-       struct inode *inode;
-
-       if (info == NULL) {
-               pr_err("%s: info is NULL\n", __func__);
-               return NULL;
-       }
-
-       inode = new_inode(sb);
-       if (inode) {
-               atomic_set(&NCP_FINFO(inode)->opened, info->opened);
-
-               inode->i_ino = info->ino;
-               ncp_set_attr(inode, info);
-               if (S_ISREG(inode->i_mode)) {
-                       inode->i_op = &ncp_file_inode_operations;
-                       inode->i_fop = &ncp_file_operations;
-               } else if (S_ISDIR(inode->i_mode)) {
-                       inode->i_op = &ncp_dir_inode_operations;
-                       inode->i_fop = &ncp_dir_operations;
-#ifdef CONFIG_NCPFS_NFS_NS
-               } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
-                       init_special_inode(inode, inode->i_mode,
-                               new_decode_dev(info->i.nfs.rdev));
-#endif
-#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-               } else if (S_ISLNK(inode->i_mode)) {
-                       inode->i_op = &ncp_symlink_inode_operations;
-                       inode_nohighmem(inode);
-                       inode->i_data.a_ops = &ncp_symlink_aops;
-#endif
-               } else {
-                       make_bad_inode(inode);
-               }
-               insert_inode_hash(inode);
-       } else
-               pr_err("%s: iget failed!\n", __func__);
-       return inode;
-}
-
-static void
-ncp_evict_inode(struct inode *inode)
-{
-       truncate_inode_pages_final(&inode->i_data);
-       clear_inode(inode);
-
-       if (S_ISDIR(inode->i_mode)) {
-               ncp_dbg(2, "put directory %ld\n", inode->i_ino);
-       }
-
-       if (ncp_make_closed(inode) != 0) {
-               /* We can't do anything but complain. */
-               pr_err("%s: could not close\n", __func__);
-       }
-}
-
-static void ncp_stop_tasks(struct ncp_server *server) {
-       struct sock* sk = server->ncp_sock->sk;
-
-       lock_sock(sk);
-       sk->sk_error_report = server->error_report;
-       sk->sk_data_ready   = server->data_ready;
-       sk->sk_write_space  = server->write_space;
-       release_sock(sk);
-       del_timer_sync(&server->timeout_tm);
-
-       flush_work(&server->rcv.tq);
-       if (sk->sk_socket->type == SOCK_STREAM)
-               flush_work(&server->tx.tq);
-       else
-               flush_work(&server->timeout_tq);
-}
-
-static int  ncp_show_options(struct seq_file *seq, struct dentry *root)
-{
-       struct ncp_server *server = NCP_SBP(root->d_sb);
-       unsigned int tmp;
-
-       if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID))
-               seq_printf(seq, ",uid=%u",
-                          from_kuid_munged(&init_user_ns, server->m.uid));
-       if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID))
-               seq_printf(seq, ",gid=%u",
-                          from_kgid_munged(&init_user_ns, server->m.gid));
-       if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID))
-               seq_printf(seq, ",owner=%u",
-                          from_kuid_munged(&init_user_ns, server->m.mounted_uid));
-       tmp = server->m.file_mode & S_IALLUGO;
-       if (tmp != NCP_DEFAULT_FILE_MODE)
-               seq_printf(seq, ",mode=0%o", tmp);
-       tmp = server->m.dir_mode & S_IALLUGO;
-       if (tmp != NCP_DEFAULT_DIR_MODE)
-               seq_printf(seq, ",dirmode=0%o", tmp);
-       if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
-               tmp = server->m.time_out * 100 / HZ;
-               seq_printf(seq, ",timeout=%u", tmp);
-       }
-       if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
-               seq_printf(seq, ",retry=%u", server->m.retry_count);
-       if (server->m.flags != 0)
-               seq_printf(seq, ",flags=%lu", server->m.flags);
-       if (server->m.wdog_pid != NULL)
-               seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
-
-       return 0;
-}
-
-static const struct ncp_option ncp_opts[] = {
-       { "uid",        OPT_INT,        'u' },
-       { "gid",        OPT_INT,        'g' },
-       { "owner",      OPT_INT,        'o' },
-       { "mode",       OPT_INT,        'm' },
-       { "dirmode",    OPT_INT,        'd' },
-       { "timeout",    OPT_INT,        't' },
-       { "retry",      OPT_INT,        'r' },
-       { "flags",      OPT_INT,        'f' },
-       { "wdogpid",    OPT_INT,        'w' },
-       { "ncpfd",      OPT_INT,        'n' },
-       { "infofd",     OPT_INT,        'i' },  /* v5 */
-       { "version",    OPT_INT,        'v' },
-       { NULL,         0,              0 } };
-
-static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
-       int optval;
-       char *optarg;
-       unsigned long optint;
-       int version = 0;
-       int ret;
-
-       data->flags = 0;
-       data->int_flags = 0;
-       data->mounted_uid = GLOBAL_ROOT_UID;
-       data->wdog_pid = NULL;
-       data->ncp_fd = ~0;
-       data->time_out = NCP_DEFAULT_TIME_OUT;
-       data->retry_count = NCP_DEFAULT_RETRY_COUNT;
-       data->uid = GLOBAL_ROOT_UID;
-       data->gid = GLOBAL_ROOT_GID;
-       data->file_mode = NCP_DEFAULT_FILE_MODE;
-       data->dir_mode = NCP_DEFAULT_DIR_MODE;
-       data->info_fd = -1;
-       data->mounted_vol[0] = 0;
-       
-       while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
-               ret = optval;
-               if (ret < 0)
-                       goto err;
-               switch (optval) {
-                       case 'u':
-                               data->uid = make_kuid(current_user_ns(), optint);
-                               if (!uid_valid(data->uid)) {
-                                       ret = -EINVAL;
-                                       goto err;
-                               }
-                               break;
-                       case 'g':
-                               data->gid = make_kgid(current_user_ns(), optint);
-                               if (!gid_valid(data->gid)) {
-                                       ret = -EINVAL;
-                                       goto err;
-                               }
-                               break;
-                       case 'o':
-                               data->mounted_uid = make_kuid(current_user_ns(), optint);
-                               if (!uid_valid(data->mounted_uid)) {
-                                       ret = -EINVAL;
-                                       goto err;
-                               }
-                               break;
-                       case 'm':
-                               data->file_mode = optint;
-                               break;
-                       case 'd':
-                               data->dir_mode = optint;
-                               break;
-                       case 't':
-                               data->time_out = optint;
-                               break;
-                       case 'r':
-                               data->retry_count = optint;
-                               break;
-                       case 'f':
-                               data->flags = optint;
-                               break;
-                       case 'w':
-                               data->wdog_pid = find_get_pid(optint);
-                               break;
-                       case 'n':
-                               data->ncp_fd = optint;
-                               break;
-                       case 'i':
-                               data->info_fd = optint;
-                               break;
-                       case 'v':
-                               ret = -ECHRNG;
-                               if (optint < NCP_MOUNT_VERSION_V4)
-                                       goto err;
-                               if (optint > NCP_MOUNT_VERSION_V5)
-                                       goto err;
-                               version = optint;
-                               break;
-                       
-               }
-       }
-       return 0;
-err:
-       put_pid(data->wdog_pid);
-       data->wdog_pid = NULL;
-       return ret;
-}
-
-static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
-{
-       struct ncp_mount_data_kernel data;
-       struct ncp_server *server;
-       struct inode *root_inode;
-       struct socket *sock;
-       int error;
-       int default_bufsize;
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
-       int options;
-#endif
-       struct ncp_entry_info finfo;
-
-       memset(&data, 0, sizeof(data));
-       server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
-       if (!server)
-               return -ENOMEM;
-       sb->s_fs_info = server;
-
-       error = -EFAULT;
-       if (raw_data == NULL)
-               goto out;
-       switch (*(int*)raw_data) {
-               case NCP_MOUNT_VERSION:
-                       {
-                               struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
-
-                               data.flags = md->flags;
-                               data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
-                               data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
-                               data.wdog_pid = find_get_pid(md->wdog_pid);
-                               data.ncp_fd = md->ncp_fd;
-                               data.time_out = md->time_out;
-                               data.retry_count = md->retry_count;
-                               data.uid = make_kuid(current_user_ns(), md->uid);
-                               data.gid = make_kgid(current_user_ns(), md->gid);
-                               data.file_mode = md->file_mode;
-                               data.dir_mode = md->dir_mode;
-                               data.info_fd = -1;
-                               memcpy(data.mounted_vol, md->mounted_vol,
-                                       NCP_VOLNAME_LEN+1);
-                       }
-                       break;
-               case NCP_MOUNT_VERSION_V4:
-                       {
-                               struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
-
-                               data.flags = md->flags;
-                               data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
-                               data.wdog_pid = find_get_pid(md->wdog_pid);
-                               data.ncp_fd = md->ncp_fd;
-                               data.time_out = md->time_out;
-                               data.retry_count = md->retry_count;
-                               data.uid = make_kuid(current_user_ns(), md->uid);
-                               data.gid = make_kgid(current_user_ns(), md->gid);
-                               data.file_mode = md->file_mode;
-                               data.dir_mode = md->dir_mode;
-                               data.info_fd = -1;
-                       }
-                       break;
-               default:
-                       error = -ECHRNG;
-                       if (memcmp(raw_data, "vers", 4) == 0) {
-                               error = ncp_parse_options(&data, raw_data);
-                       }
-                       if (error)
-                               goto out;
-                       break;
-       }
-       error = -EINVAL;
-       if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) ||
-           !gid_valid(data.gid))
-               goto out;
-       sock = sockfd_lookup(data.ncp_fd, &error);
-       if (!sock)
-               goto out;
-
-       if (sock->type == SOCK_STREAM)
-               default_bufsize = 0xF000;
-       else
-               default_bufsize = 1024;
-
-       sb->s_flags |= SB_NODIRATIME;   /* probably even noatime */
-       sb->s_maxbytes = 0xFFFFFFFFU;
-       sb->s_blocksize = 1024; /* Eh...  Is this correct? */
-       sb->s_blocksize_bits = 10;
-       sb->s_magic = NCP_SUPER_MAGIC;
-       sb->s_op = &ncp_sops;
-       sb->s_d_op = &ncp_dentry_operations;
-
-       server = NCP_SBP(sb);
-       memset(server, 0, sizeof(*server));
-
-       error = super_setup_bdi(sb);
-       if (error)
-               goto out_fput;
-
-       server->ncp_sock = sock;
-       
-       if (data.info_fd != -1) {
-               struct socket *info_sock = sockfd_lookup(data.info_fd, &error);
-               if (!info_sock)
-                       goto out_fput;
-               server->info_sock = info_sock;
-               error = -EBADFD;
-               if (info_sock->type != SOCK_STREAM)
-                       goto out_fput2;
-       }
-
-/*     server->lock = 0;       */
-       mutex_init(&server->mutex);
-       server->packet = NULL;
-/*     server->buffer_size = 0;        */
-/*     server->conn_status = 0;        */
-/*     server->root_dentry = NULL;     */
-/*     server->root_setuped = 0;       */
-       mutex_init(&server->root_setup_lock);
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
-/*     server->sign_wanted = 0;        */
-/*     server->sign_active = 0;        */
-#endif
-       init_rwsem(&server->auth_rwsem);
-       server->auth.auth_type = NCP_AUTH_NONE;
-/*     server->auth.object_name_len = 0;       */
-/*     server->auth.object_name = NULL;        */
-/*     server->auth.object_type = 0;           */
-/*     server->priv.len = 0;                   */
-/*     server->priv.data = NULL;               */
-
-       server->m = data;
-       /* Although anything producing this is buggy, it happens
-          now because of PATH_MAX changes.. */
-       if (server->m.time_out < 1) {
-               server->m.time_out = 10;
-               pr_info("You need to recompile your ncpfs utils..\n");
-       }
-       server->m.time_out = server->m.time_out * HZ / 100;
-       server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
-       server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
-
-#ifdef CONFIG_NCPFS_NLS
-       /* load the default NLS charsets */
-       server->nls_vol = load_nls_default();
-       server->nls_io = load_nls_default();
-#endif /* CONFIG_NCPFS_NLS */
-
-       atomic_set(&server->dentry_ttl, 0);     /* no caching */
-
-       INIT_LIST_HEAD(&server->tx.requests);
-       mutex_init(&server->rcv.creq_mutex);
-       server->tx.creq         = NULL;
-       server->rcv.creq        = NULL;
-
-       timer_setup(&server->timeout_tm, ncpdgram_timeout_call, 0);
-#undef NCP_PACKET_SIZE
-#define NCP_PACKET_SIZE 131072
-       error = -ENOMEM;
-       server->packet_size = NCP_PACKET_SIZE;
-       server->packet = vmalloc(NCP_PACKET_SIZE);
-       if (server->packet == NULL)
-               goto out_nls;
-       server->txbuf = vmalloc(NCP_PACKET_SIZE);
-       if (server->txbuf == NULL)
-               goto out_packet;
-       server->rxbuf = vmalloc(NCP_PACKET_SIZE);
-       if (server->rxbuf == NULL)
-               goto out_txbuf;
-
-       lock_sock(sock->sk);
-       server->data_ready      = sock->sk->sk_data_ready;
-       server->write_space     = sock->sk->sk_write_space;
-       server->error_report    = sock->sk->sk_error_report;
-       sock->sk->sk_user_data  = server;
-       sock->sk->sk_data_ready   = ncp_tcp_data_ready;
-       sock->sk->sk_error_report = ncp_tcp_error_report;
-       if (sock->type == SOCK_STREAM) {
-               server->rcv.ptr = (unsigned char*)&server->rcv.buf;
-               server->rcv.len = 10;
-               server->rcv.state = 0;
-               INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
-               INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
-               sock->sk->sk_write_space = ncp_tcp_write_space;
-       } else {
-               INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
-               INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
-       }
-       release_sock(sock->sk);
-
-       ncp_lock_server(server);
-       error = ncp_connect(server);
-       ncp_unlock_server(server);
-       if (error < 0)
-               goto out_rxbuf;
-       ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb));
-
-       error = -EMSGSIZE;      /* -EREMOTESIDEINCOMPATIBLE */
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
-       if (ncp_negotiate_size_and_options(server, default_bufsize,
-               NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
-       {
-               if (options != NCP_DEFAULT_OPTIONS)
-               {
-                       if (ncp_negotiate_size_and_options(server, 
-                               default_bufsize,
-                               options & 2, 
-                               &(server->buffer_size), &options) != 0)
-                               
-                       {
-                               goto out_disconnect;
-                       }
-               }
-               ncp_lock_server(server);
-               if (options & 2)
-                       server->sign_wanted = 1;
-               ncp_unlock_server(server);
-       }
-       else 
-#endif /* CONFIG_NCPFS_PACKET_SIGNING */
-       if (ncp_negotiate_buffersize(server, default_bufsize,
-                                    &(server->buffer_size)) != 0)
-               goto out_disconnect;
-       ncp_dbg(1, "bufsize = %d\n", server->buffer_size);
-
-       memset(&finfo, 0, sizeof(finfo));
-       finfo.i.attributes      = aDIR;
-       finfo.i.dataStreamSize  = 0;    /* ignored */
-       finfo.i.dirEntNum       = 0;
-       finfo.i.DosDirNum       = 0;
-#ifdef CONFIG_NCPFS_SMALLDOS
-       finfo.i.NSCreator       = NW_NS_DOS;
-#endif
-       finfo.volume            = NCP_NUMBER_OF_VOLUMES;
-       /* set dates of mountpoint to Jan 1, 1986; 00:00 */
-       finfo.i.creationTime    = finfo.i.modifyTime
-                               = cpu_to_le16(0x0000);
-       finfo.i.creationDate    = finfo.i.modifyDate
-                               = finfo.i.lastAccessDate
-                               = cpu_to_le16(0x0C21);
-       finfo.i.nameLen         = 0;
-       finfo.i.entryName[0]    = '\0';
-
-       finfo.opened            = 0;
-       finfo.ino               = 2;    /* tradition */
-
-       server->name_space[finfo.volume] = NW_NS_DOS;
-
-       error = -ENOMEM;
-        root_inode = ncp_iget(sb, &finfo);
-        if (!root_inode)
-               goto out_disconnect;
-       ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
-       sb->s_root = d_make_root(root_inode);
-        if (!sb->s_root)
-               goto out_disconnect;
-       return 0;
-
-out_disconnect:
-       ncp_lock_server(server);
-       ncp_disconnect(server);
-       ncp_unlock_server(server);
-out_rxbuf:
-       ncp_stop_tasks(server);
-       vfree(server->rxbuf);
-out_txbuf:
-       vfree(server->txbuf);
-out_packet:
-       vfree(server->packet);
-out_nls:
-#ifdef CONFIG_NCPFS_NLS
-       unload_nls(server->nls_io);
-       unload_nls(server->nls_vol);
-#endif
-       mutex_destroy(&server->rcv.creq_mutex);
-       mutex_destroy(&server->root_setup_lock);
-       mutex_destroy(&server->mutex);
-out_fput2:
-       if (server->info_sock)
-               sockfd_put(server->info_sock);
-out_fput:
-       sockfd_put(sock);
-out:
-       put_pid(data.wdog_pid);
-       sb->s_fs_info = NULL;
-       kfree(server);
-       return error;
-}
-
-static void delayed_free(struct rcu_head *p)
-{
-       struct ncp_server *server = container_of(p, struct ncp_server, rcu);
-#ifdef CONFIG_NCPFS_NLS
-       /* unload the NLS charsets */
-       unload_nls(server->nls_vol);
-       unload_nls(server->nls_io);
-#endif /* CONFIG_NCPFS_NLS */
-       kfree(server);
-}
-
-static void ncp_put_super(struct super_block *sb)
-{
-       struct ncp_server *server = NCP_SBP(sb);
-
-       ncp_lock_server(server);
-       ncp_disconnect(server);
-       ncp_unlock_server(server);
-
-       ncp_stop_tasks(server);
-
-       mutex_destroy(&server->rcv.creq_mutex);
-       mutex_destroy(&server->root_setup_lock);
-       mutex_destroy(&server->mutex);
-
-       if (server->info_sock)
-               sockfd_put(server->info_sock);
-       sockfd_put(server->ncp_sock);
-       kill_pid(server->m.wdog_pid, SIGTERM, 1);
-       put_pid(server->m.wdog_pid);
-
-       kfree(server->priv.data);
-       kfree(server->auth.object_name);
-       vfree(server->rxbuf);
-       vfree(server->txbuf);
-       vfree(server->packet);
-       call_rcu(&server->rcu, delayed_free);
-}
-
-static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
-       struct dentry* d;
-       struct inode* i;
-       struct ncp_inode_info* ni;
-       struct ncp_server* s;
-       struct ncp_volume_info vi;
-       struct super_block *sb = dentry->d_sb;
-       int err;
-       __u8 dh;
-       
-       d = sb->s_root;
-       if (!d) {
-               goto dflt;
-       }
-       i = d_inode(d);
-       if (!i) {
-               goto dflt;
-       }
-       ni = NCP_FINFO(i);
-       if (!ni) {
-               goto dflt;
-       }
-       s = NCP_SBP(sb);
-       if (!s) {
-               goto dflt;
-       }
-       if (!s->m.mounted_vol[0]) {
-               goto dflt;
-       }
-
-       err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
-       if (err) {
-               goto dflt;
-       }
-       err = ncp_get_directory_info(s, dh, &vi);
-       ncp_dirhandle_free(s, dh);
-       if (err) {
-               goto dflt;
-       }
-       buf->f_type = NCP_SUPER_MAGIC;
-       buf->f_bsize = vi.sectors_per_block * 512;
-       buf->f_blocks = vi.total_blocks;
-       buf->f_bfree = vi.free_blocks;
-       buf->f_bavail = vi.free_blocks;
-       buf->f_files = vi.total_dir_entries;
-       buf->f_ffree = vi.available_dir_entries;
-       buf->f_namelen = 12;
-       return 0;
-
-       /* We cannot say how much disk space is left on a mounted
-          NetWare Server, because free space is distributed over
-          volumes, and the current user might have disk quotas. So
-          free space is not that simple to determine. Our decision
-          here is to err conservatively. */
-
-dflt:;
-       buf->f_type = NCP_SUPER_MAGIC;
-       buf->f_bsize = NCP_BLOCK_SIZE;
-       buf->f_blocks = 0;
-       buf->f_bfree = 0;
-       buf->f_bavail = 0;
-       buf->f_namelen = 12;
-       return 0;
-}
-
-int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
-{
-       struct inode *inode = d_inode(dentry);
-       int result = 0;
-       __le32 info_mask;
-       struct nw_modify_dos_info info;
-       struct ncp_server *server;
-
-       result = -EIO;
-
-       server = NCP_SERVER(inode);
-       if (!server)    /* How this could happen? */
-               goto out;
-
-       result = -EPERM;
-       if (IS_DEADDIR(d_inode(dentry)))
-               goto out;
-
-       /* ageing the dentry to force validation */
-       ncp_age_dentry(server, dentry);
-
-       result = setattr_prepare(dentry, attr);
-       if (result < 0)
-               goto out;
-
-       result = -EPERM;
-       if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid))
-               goto out;
-
-       if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid))
-               goto out;
-
-       if (((attr->ia_valid & ATTR_MODE) &&
-            (attr->ia_mode &
-             ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
-               goto out;
-
-       info_mask = 0;
-       memset(&info, 0, sizeof(info));
-
-#if 1 
-        if ((attr->ia_valid & ATTR_MODE) != 0)
-        {
-               umode_t newmode = attr->ia_mode;
-
-               info_mask |= DM_ATTRIBUTES;
-
-                if (S_ISDIR(inode->i_mode)) {
-                       newmode &= server->m.dir_mode;
-               } else {
-#ifdef CONFIG_NCPFS_EXTRAS                     
-                       if (server->m.flags & NCP_MOUNT_EXTRAS) {
-                               /* any non-default execute bit set */
-                               if (newmode & ~server->m.file_mode & S_IXUGO)
-                                       info.attributes |= aSHARED | aSYSTEM;
-                               /* read for group/world and not in default file_mode */
-                               else if (newmode & ~server->m.file_mode & S_IRUGO)
-                                       info.attributes |= aSHARED;
-                       } else
-#endif
-                               newmode &= server->m.file_mode;                 
-                }
-                if (newmode & S_IWUGO)
-                       info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
-                else
-                       info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
-
-#ifdef CONFIG_NCPFS_NFS_NS
-               if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
-                       result = ncp_modify_nfs_info(server,
-                                                    NCP_FINFO(inode)->volNumber,
-                                                    NCP_FINFO(inode)->dirEntNum,
-                                                    attr->ia_mode, 0);
-                       if (result != 0)
-                               goto out;
-                       info.attributes &= ~(aSHARED | aSYSTEM);
-                       {
-                               /* mark partial success */
-                               struct iattr tmpattr;
-                               
-                               tmpattr.ia_valid = ATTR_MODE;
-                               tmpattr.ia_mode = attr->ia_mode;
-
-                               setattr_copy(inode, &tmpattr);
-                               mark_inode_dirty(inode);
-                       }
-               }
-#endif
-        }
-#endif
-
-       /* Do SIZE before attributes, otherwise mtime together with size does not work...
-        */
-       if ((attr->ia_valid & ATTR_SIZE) != 0) {
-               int written;
-
-               ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size);
-
-               if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
-                       result = -EACCES;
-                       goto out;
-               }
-               ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
-                         attr->ia_size, 0, "", &written);
-
-               /* According to ndir, the changes only take effect after
-                  closing the file */
-               ncp_inode_close(inode);
-               result = ncp_make_closed(inode);
-               if (result)
-                       goto out;
-
-               if (attr->ia_size != i_size_read(inode)) {
-                       truncate_setsize(inode, attr->ia_size);
-                       mark_inode_dirty(inode);
-               }
-       }
-       if ((attr->ia_valid & ATTR_CTIME) != 0) {
-               info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
-               ncp_date_unix2dos(attr->ia_ctime.tv_sec,
-                            &info.creationTime, &info.creationDate);
-       }
-       if ((attr->ia_valid & ATTR_MTIME) != 0) {
-               info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
-               ncp_date_unix2dos(attr->ia_mtime.tv_sec,
-                                 &info.modifyTime, &info.modifyDate);
-       }
-       if ((attr->ia_valid & ATTR_ATIME) != 0) {
-               __le16 dummy;
-               info_mask |= (DM_LAST_ACCESS_DATE);
-               ncp_date_unix2dos(attr->ia_atime.tv_sec,
-                                 &dummy, &info.lastAccessDate);
-       }
-       if (info_mask != 0) {
-               result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
-                                     inode, info_mask, &info);
-               if (result != 0) {
-                       if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
-                               /* NetWare seems not to allow this. I
-                                  do not know why. So, just tell the
-                                  user everything went fine. This is
-                                  a terrible hack, but I do not know
-                                  how to do this correctly. */
-                               result = 0;
-                       } else
-                               goto out;
-               }
-#ifdef CONFIG_NCPFS_STRONG             
-               if ((!result) && (info_mask & DM_ATTRIBUTES))
-                       NCP_FINFO(inode)->nwattr = info.attributes;
-#endif
-       }
-       if (result)
-               goto out;
-
-       setattr_copy(inode, attr);
-       mark_inode_dirty(inode);
-
-out:
-       if (result > 0)
-               result = -EACCES;
-       return result;
-}
-
-static struct dentry *ncp_mount(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data)
-{
-       return mount_nodev(fs_type, flags, data, ncp_fill_super);
-}
-
-static struct file_system_type ncp_fs_type = {
-       .owner          = THIS_MODULE,
-       .name           = "ncpfs",
-       .mount          = ncp_mount,
-       .kill_sb        = kill_anon_super,
-       .fs_flags       = FS_BINARY_MOUNTDATA,
-};
-MODULE_ALIAS_FS("ncpfs");
-
-static int __init init_ncp_fs(void)
-{
-       int err;
-       ncp_dbg(1, "called\n");
-
-       err = init_inodecache();
-       if (err)
-               goto out1;
-       err = register_filesystem(&ncp_fs_type);
-       if (err)
-               goto out;
-       return 0;
-out:
-       destroy_inodecache();
-out1:
-       return err;
-}
-
-static void __exit exit_ncp_fs(void)
-{
-       ncp_dbg(1, "called\n");
-       unregister_filesystem(&ncp_fs_type);
-       destroy_inodecache();
-}
-
-module_init(init_ncp_fs)
-module_exit(exit_ncp_fs)
-MODULE_LICENSE("GPL");
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
deleted file mode 100644 (file)
index d378b98..0000000
+++ /dev/null
@@ -1,923 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  ioctl.c
- *
- *  Copyright (C) 1995, 1996 by Volker Lendecke
- *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- *  Modified 1998, 1999 Wolfram Pienkoss for NLS
- *
- */
-
-#include <linux/capability.h>
-#include <linux/compat.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ioctl.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/mount.h>
-#include <linux/slab.h>
-#include <linux/highuid.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/cred.h>
-
-#include <linux/uaccess.h>
-
-#include "ncp_fs.h"
-
-/* maximum limit for ncp_objectname_ioctl */
-#define NCP_OBJECT_NAME_MAX_LEN        4096
-/* maximum limit for ncp_privatedata_ioctl */
-#define NCP_PRIVATE_DATA_MAX_LEN 8192
-/* maximum negotiable packet size */
-#define NCP_PACKET_SIZE_INTERNAL 65536
-
-static int
-ncp_get_fs_info(struct ncp_server * server, struct inode *inode,
-               struct ncp_fs_info __user *arg)
-{
-       struct ncp_fs_info info;
-
-       if (copy_from_user(&info, arg, sizeof(info)))
-               return -EFAULT;
-
-       if (info.version != NCP_GET_FS_INFO_VERSION) {
-               ncp_dbg(1, "info.version invalid: %d\n", info.version);
-               return -EINVAL;
-       }
-       /* TODO: info.addr = server->m.serv_addr; */
-       SET_UID(info.mounted_uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid));
-       info.connection         = server->connection;
-       info.buffer_size        = server->buffer_size;
-       info.volume_number      = NCP_FINFO(inode)->volNumber;
-       info.directory_id       = NCP_FINFO(inode)->DosDirNum;
-
-       if (copy_to_user(arg, &info, sizeof(info)))
-               return -EFAULT;
-       return 0;
-}
-
-static int
-ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode,
-                  struct ncp_fs_info_v2 __user * arg)
-{
-       struct ncp_fs_info_v2 info2;
-
-       if (copy_from_user(&info2, arg, sizeof(info2)))
-               return -EFAULT;
-
-       if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
-               ncp_dbg(1, "info.version invalid: %d\n", info2.version);
-               return -EINVAL;
-       }
-       info2.mounted_uid   = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
-       info2.connection    = server->connection;
-       info2.buffer_size   = server->buffer_size;
-       info2.volume_number = NCP_FINFO(inode)->volNumber;
-       info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
-       info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
-
-       if (copy_to_user(arg, &info2, sizeof(info2)))
-               return -EFAULT;
-       return 0;
-}
-
-#ifdef CONFIG_COMPAT
-struct compat_ncp_objectname_ioctl
-{
-       s32             auth_type;
-       u32             object_name_len;
-       compat_caddr_t  object_name;    /* a userspace data, in most cases user name */
-};
-
-struct compat_ncp_fs_info_v2 {
-       s32 version;
-       u32 mounted_uid;
-       u32 connection;
-       u32 buffer_size;
-
-       u32 volume_number;
-       u32 directory_id;
-
-       u32 dummy1;
-       u32 dummy2;
-       u32 dummy3;
-};
-
-struct compat_ncp_ioctl_request {
-       u32 function;
-       u32 size;
-       compat_caddr_t data;
-};
-
-struct compat_ncp_privatedata_ioctl
-{
-       u32             len;
-       compat_caddr_t  data;           /* ~1000 for NDS */
-};
-
-#define NCP_IOC_GET_FS_INFO_V2_32      _IOWR('n', 4, struct compat_ncp_fs_info_v2)
-#define NCP_IOC_NCPREQUEST_32          _IOR('n', 1, struct compat_ncp_ioctl_request)
-#define NCP_IOC_GETOBJECTNAME_32       _IOWR('n', 9, struct compat_ncp_objectname_ioctl)
-#define NCP_IOC_SETOBJECTNAME_32       _IOR('n', 9, struct compat_ncp_objectname_ioctl)
-#define NCP_IOC_GETPRIVATEDATA_32      _IOWR('n', 10, struct compat_ncp_privatedata_ioctl)
-#define NCP_IOC_SETPRIVATEDATA_32      _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
-
-static int
-ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode,
-                  struct compat_ncp_fs_info_v2 __user * arg)
-{
-       struct compat_ncp_fs_info_v2 info2;
-
-       if (copy_from_user(&info2, arg, sizeof(info2)))
-               return -EFAULT;
-
-       if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
-               ncp_dbg(1, "info.version invalid: %d\n", info2.version);
-               return -EINVAL;
-       }
-       info2.mounted_uid   = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
-       info2.connection    = server->connection;
-       info2.buffer_size   = server->buffer_size;
-       info2.volume_number = NCP_FINFO(inode)->volNumber;
-       info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
-       info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
-
-       if (copy_to_user(arg, &info2, sizeof(info2)))
-               return -EFAULT;
-       return 0;
-}
-#endif
-
-#define NCP_IOC_GETMOUNTUID16          _IOW('n', 2, u16)
-#define NCP_IOC_GETMOUNTUID32          _IOW('n', 2, u32)
-#define NCP_IOC_GETMOUNTUID64          _IOW('n', 2, u64)
-
-#ifdef CONFIG_NCPFS_NLS
-/* Here we are select the iocharset and the codepage for NLS.
- * Thanks Petr Vandrovec for idea and many hints.
- */
-static int
-ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
-{
-       struct ncp_nls_ioctl user;
-       struct nls_table *codepage;
-       struct nls_table *iocharset;
-       struct nls_table *oldset_io;
-       struct nls_table *oldset_cp;
-       int utf8;
-       int err;
-
-       if (copy_from_user(&user, arg, sizeof(user)))
-               return -EFAULT;
-
-       codepage = NULL;
-       user.codepage[NCP_IOCSNAME_LEN] = 0;
-       if (!user.codepage[0] || !strcmp(user.codepage, "default"))
-               codepage = load_nls_default();
-       else {
-               codepage = load_nls(user.codepage);
-               if (!codepage) {
-                       return -EBADRQC;
-               }
-       }
-
-       iocharset = NULL;
-       user.iocharset[NCP_IOCSNAME_LEN] = 0;
-       if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
-               iocharset = load_nls_default();
-               utf8 = 0;
-       } else if (!strcmp(user.iocharset, "utf8")) {
-               iocharset = load_nls_default();
-               utf8 = 1;
-       } else {
-               iocharset = load_nls(user.iocharset);
-               if (!iocharset) {
-                       unload_nls(codepage);
-                       return -EBADRQC;
-               }
-               utf8 = 0;
-       }
-
-       mutex_lock(&server->root_setup_lock);
-       if (server->root_setuped) {
-               oldset_cp = codepage;
-               oldset_io = iocharset;
-               err = -EBUSY;
-       } else {
-               if (utf8)
-                       NCP_SET_FLAG(server, NCP_FLAG_UTF8);
-               else
-                       NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
-               oldset_cp = server->nls_vol;
-               server->nls_vol = codepage;
-               oldset_io = server->nls_io;
-               server->nls_io = iocharset;
-               err = 0;
-       }
-       mutex_unlock(&server->root_setup_lock);
-       unload_nls(oldset_cp);
-       unload_nls(oldset_io);
-
-       return err;
-}
-
-static int
-ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
-{
-       struct ncp_nls_ioctl user;
-       int len;
-
-       memset(&user, 0, sizeof(user));
-       mutex_lock(&server->root_setup_lock);
-       if (server->nls_vol && server->nls_vol->charset) {
-               len = strlen(server->nls_vol->charset);
-               if (len > NCP_IOCSNAME_LEN)
-                       len = NCP_IOCSNAME_LEN;
-               strncpy(user.codepage, server->nls_vol->charset, len);
-               user.codepage[len] = 0;
-       }
-
-       if (NCP_IS_FLAG(server, NCP_FLAG_UTF8))
-               strcpy(user.iocharset, "utf8");
-       else if (server->nls_io && server->nls_io->charset) {
-               len = strlen(server->nls_io->charset);
-               if (len > NCP_IOCSNAME_LEN)
-                       len = NCP_IOCSNAME_LEN;
-               strncpy(user.iocharset, server->nls_io->charset, len);
-               user.iocharset[len] = 0;
-       }
-       mutex_unlock(&server->root_setup_lock);
-
-       if (copy_to_user(arg, &user, sizeof(user)))
-               return -EFAULT;
-       return 0;
-}
-#endif /* CONFIG_NCPFS_NLS */
-
-static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg)
-{
-       struct ncp_server *server = NCP_SERVER(inode);
-       int result;
-       struct ncp_ioctl_request request;
-       char* bouncebuffer;
-       void __user *argp = (void __user *)arg;
-
-       switch (cmd) {
-#ifdef CONFIG_COMPAT
-       case NCP_IOC_NCPREQUEST_32:
-#endif
-       case NCP_IOC_NCPREQUEST:
-#ifdef CONFIG_COMPAT
-               if (cmd == NCP_IOC_NCPREQUEST_32) {
-                       struct compat_ncp_ioctl_request request32;
-                       if (copy_from_user(&request32, argp, sizeof(request32)))
-                               return -EFAULT;
-                       request.function = request32.function;
-                       request.size = request32.size;
-                       request.data = compat_ptr(request32.data);
-               } else
-#endif
-               if (copy_from_user(&request, argp, sizeof(request)))
-                       return -EFAULT;
-
-               if ((request.function > 255)
-                   || (request.size >
-                 NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
-                       return -EINVAL;
-               }
-               bouncebuffer = vmalloc(NCP_PACKET_SIZE_INTERNAL);
-               if (!bouncebuffer)
-                       return -ENOMEM;
-               if (copy_from_user(bouncebuffer, request.data, request.size)) {
-                       vfree(bouncebuffer);
-                       return -EFAULT;
-               }
-               ncp_lock_server(server);
-
-               /* FIXME: We hack around in the server's structures
-                  here to be able to use ncp_request */
-
-               server->has_subfunction = 0;
-               server->current_size = request.size;
-               memcpy(server->packet, bouncebuffer, request.size);
-
-               result = ncp_request2(server, request.function,
-                       bouncebuffer, NCP_PACKET_SIZE_INTERNAL);
-               if (result < 0)
-                       result = -EIO;
-               else
-                       result = server->reply_size;
-               ncp_unlock_server(server);
-               ncp_dbg(1, "copy %d bytes\n", result);
-               if (result >= 0)
-                       if (copy_to_user(request.data, bouncebuffer, result))
-                               result = -EFAULT;
-               vfree(bouncebuffer);
-               return result;
-
-       case NCP_IOC_CONN_LOGGED_IN:
-
-               if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
-                       return -EINVAL;
-               mutex_lock(&server->root_setup_lock);
-               if (server->root_setuped)
-                       result = -EBUSY;
-               else {
-                       result = ncp_conn_logged_in(inode->i_sb);
-                       if (result == 0)
-                               server->root_setuped = 1;
-               }
-               mutex_unlock(&server->root_setup_lock);
-               return result;
-
-       case NCP_IOC_GET_FS_INFO:
-               return ncp_get_fs_info(server, inode, argp);
-
-       case NCP_IOC_GET_FS_INFO_V2:
-               return ncp_get_fs_info_v2(server, inode, argp);
-
-#ifdef CONFIG_COMPAT
-       case NCP_IOC_GET_FS_INFO_V2_32:
-               return ncp_get_compat_fs_info_v2(server, inode, argp);
-#endif
-       /* we have too many combinations of CONFIG_COMPAT,
-        * CONFIG_64BIT and CONFIG_UID16, so just handle
-        * any of the possible ioctls */
-       case NCP_IOC_GETMOUNTUID16:
-               {
-                       u16 uid;
-
-                       SET_UID(uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid));
-                       if (put_user(uid, (u16 __user *)argp))
-                               return -EFAULT;
-                       return 0;
-               }
-       case NCP_IOC_GETMOUNTUID32:
-       {
-               uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
-               if (put_user(uid, (u32 __user *)argp))
-                       return -EFAULT;
-               return 0;
-       }
-       case NCP_IOC_GETMOUNTUID64:
-       {
-               uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
-               if (put_user(uid, (u64 __user *)argp))
-                       return -EFAULT;
-               return 0;
-       }
-       case NCP_IOC_GETROOT:
-               {
-                       struct ncp_setroot_ioctl sr;
-
-                       result = -EACCES;
-                       mutex_lock(&server->root_setup_lock);
-                       if (server->m.mounted_vol[0]) {
-                               struct dentry* dentry = inode->i_sb->s_root;
-
-                               if (dentry) {
-                                       struct inode* s_inode = d_inode(dentry);
-
-                                       if (s_inode) {
-                                               sr.volNumber = NCP_FINFO(s_inode)->volNumber;
-                                               sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum;
-                                               sr.namespace = server->name_space[sr.volNumber];
-                                               result = 0;
-                                       } else
-                                               ncp_dbg(1, "d_inode(s_root)==NULL\n");
-                               } else
-                                       ncp_dbg(1, "s_root==NULL\n");
-                       } else {
-                               sr.volNumber = -1;
-                               sr.namespace = 0;
-                               sr.dirEntNum = 0;
-                               result = 0;
-                       }
-                       mutex_unlock(&server->root_setup_lock);
-                       if (!result && copy_to_user(argp, &sr, sizeof(sr)))
-                               result = -EFAULT;
-                       return result;
-               }
-
-       case NCP_IOC_SETROOT:
-               {
-                       struct ncp_setroot_ioctl sr;
-                       __u32 vnum;
-                       __le32 de;
-                       __le32 dosde;
-                       struct dentry* dentry;
-
-                       if (copy_from_user(&sr, argp, sizeof(sr)))
-                               return -EFAULT;
-                       mutex_lock(&server->root_setup_lock);
-                       if (server->root_setuped)
-                               result = -EBUSY;
-                       else {
-                               if (sr.volNumber < 0) {
-                                       server->m.mounted_vol[0] = 0;
-                                       vnum = NCP_NUMBER_OF_VOLUMES;
-                                       de = 0;
-                                       dosde = 0;
-                                       result = 0;
-                               } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
-                                       result = -EINVAL;
-                               } else if (ncp_mount_subdir(server, sr.volNumber,
-                                                       sr.namespace, sr.dirEntNum,
-                                                       &vnum, &de, &dosde)) {
-                                       result = -ENOENT;
-                               } else
-                                       result = 0;
-
-                               if (result == 0) {
-                                       dentry = inode->i_sb->s_root;
-                                       if (dentry) {
-                                               struct inode* s_inode = d_inode(dentry);
-
-                                               if (s_inode) {
-                                                       NCP_FINFO(s_inode)->volNumber = vnum;
-                                                       NCP_FINFO(s_inode)->dirEntNum = de;
-                                                       NCP_FINFO(s_inode)->DosDirNum = dosde;
-                                                       server->root_setuped = 1;
-                                               } else {
-                                                       ncp_dbg(1, "d_inode(s_root)==NULL\n");
-                                                       result = -EIO;
-                                               }
-                                       } else {
-                                               ncp_dbg(1, "s_root==NULL\n");
-                                               result = -EIO;
-                                       }
-                               }
-                       }
-                       mutex_unlock(&server->root_setup_lock);
-
-                       return result;
-               }
-
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
-       case NCP_IOC_SIGN_INIT:
-               {
-                       struct ncp_sign_init sign;
-
-                       if (argp)
-                               if (copy_from_user(&sign, argp, sizeof(sign)))
-                                       return -EFAULT;
-                       ncp_lock_server(server);
-                       mutex_lock(&server->rcv.creq_mutex);
-                       if (argp) {
-                               if (server->sign_wanted) {
-                                       memcpy(server->sign_root,sign.sign_root,8);
-                                       memcpy(server->sign_last,sign.sign_last,16);
-                                       server->sign_active = 1;
-                               }
-                               /* ignore when signatures not wanted */
-                       } else {
-                               server->sign_active = 0;
-                       }
-                       mutex_unlock(&server->rcv.creq_mutex);
-                       ncp_unlock_server(server);
-                       return 0;
-               }
-
-        case NCP_IOC_SIGN_WANTED:
-               {
-                       int state;
-
-                       ncp_lock_server(server);
-                       state = server->sign_wanted;
-                       ncp_unlock_server(server);
-                       if (put_user(state, (int __user *)argp))
-                               return -EFAULT;
-                       return 0;
-               }
-
-       case NCP_IOC_SET_SIGN_WANTED:
-               {
-                       int newstate;
-
-                       /* get only low 8 bits... */
-                       if (get_user(newstate, (unsigned char __user *)argp))
-                               return -EFAULT;
-                       result = 0;
-                       ncp_lock_server(server);
-                       if (server->sign_active) {
-                               /* cannot turn signatures OFF when active */
-                               if (!newstate)
-                                       result = -EINVAL;
-                       } else {
-                               server->sign_wanted = newstate != 0;
-                       }
-                       ncp_unlock_server(server);
-                       return result;
-               }
-
-#endif /* CONFIG_NCPFS_PACKET_SIGNING */
-
-#ifdef CONFIG_NCPFS_IOCTL_LOCKING
-       case NCP_IOC_LOCKUNLOCK:
-               {
-                       struct ncp_lock_ioctl    rqdata;
-
-                       if (copy_from_user(&rqdata, argp, sizeof(rqdata)))
-                               return -EFAULT;
-                       if (rqdata.origin != 0)
-                               return -EINVAL;
-                       /* check for cmd */
-                       switch (rqdata.cmd) {
-                               case NCP_LOCK_EX:
-                               case NCP_LOCK_SH:
-                                               if (rqdata.timeout < 0)
-                                                       return -EINVAL;
-                                               if (rqdata.timeout == 0)
-                                                       rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT;
-                                               else if (rqdata.timeout > NCP_LOCK_MAX_TIMEOUT)
-                                                       rqdata.timeout = NCP_LOCK_MAX_TIMEOUT;
-                                               break;
-                               case NCP_LOCK_LOG:
-                                               rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT;      /* has no effect */
-                               case NCP_LOCK_CLEAR:
-                                               break;
-                               default:
-                                               return -EINVAL;
-                       }
-                       /* locking needs both read and write access */
-                       if ((result = ncp_make_open(inode, O_RDWR)) != 0)
-                       {
-                               return result;
-                       }
-                       result = -EISDIR;
-                       if (!S_ISREG(inode->i_mode))
-                               goto outrel;
-                       if (rqdata.cmd == NCP_LOCK_CLEAR)
-                       {
-                               result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
-                                                       NCP_FINFO(inode)->file_handle,
-                                                       rqdata.offset,
-                                                       rqdata.length);
-                               if (result > 0) result = 0;     /* no such lock */
-                       }
-                       else
-                       {
-                               int lockcmd;
-
-                               switch (rqdata.cmd)
-                               {
-                                       case NCP_LOCK_EX:  lockcmd=1; break;
-                                       case NCP_LOCK_SH:  lockcmd=3; break;
-                                       default:           lockcmd=0; break;
-                               }
-                               result = ncp_LogPhysicalRecord(NCP_SERVER(inode),
-                                                       NCP_FINFO(inode)->file_handle,
-                                                       lockcmd,
-                                                       rqdata.offset,
-                                                       rqdata.length,
-                                                       rqdata.timeout);
-                               if (result > 0) result = -EAGAIN;
-                       }
-outrel:
-                       ncp_inode_close(inode);
-                       return result;
-               }
-#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
-
-#ifdef CONFIG_COMPAT
-       case NCP_IOC_GETOBJECTNAME_32:
-               {
-                       struct compat_ncp_objectname_ioctl user;
-                       size_t outl;
-
-                       if (copy_from_user(&user, argp, sizeof(user)))
-                               return -EFAULT;
-                       down_read(&server->auth_rwsem);
-                       user.auth_type = server->auth.auth_type;
-                       outl = user.object_name_len;
-                       user.object_name_len = server->auth.object_name_len;
-                       if (outl > user.object_name_len)
-                               outl = user.object_name_len;
-                       result = 0;
-                       if (outl) {
-                               if (copy_to_user(compat_ptr(user.object_name),
-                                                server->auth.object_name,
-                                                outl))
-                                       result = -EFAULT;
-                       }
-                       up_read(&server->auth_rwsem);
-                       if (!result && copy_to_user(argp, &user, sizeof(user)))
-                               result = -EFAULT;
-                       return result;
-               }
-#endif
-
-       case NCP_IOC_GETOBJECTNAME:
-               {
-                       struct ncp_objectname_ioctl user;
-                       size_t outl;
-
-                       if (copy_from_user(&user, argp, sizeof(user)))
-                               return -EFAULT;
-                       down_read(&server->auth_rwsem);
-                       user.auth_type = server->auth.auth_type;
-                       outl = user.object_name_len;
-                       user.object_name_len = server->auth.object_name_len;
-                       if (outl > user.object_name_len)
-                               outl = user.object_name_len;
-                       result = 0;
-                       if (outl) {
-                               if (copy_to_user(user.object_name,
-                                                server->auth.object_name,
-                                                outl))
-                                       result = -EFAULT;
-                       }
-                       up_read(&server->auth_rwsem);
-                       if (!result && copy_to_user(argp, &user, sizeof(user)))
-                               result = -EFAULT;
-                       return result;
-               }
-
-#ifdef CONFIG_COMPAT
-       case NCP_IOC_SETOBJECTNAME_32:
-#endif
-       case NCP_IOC_SETOBJECTNAME:
-               {
-                       struct ncp_objectname_ioctl user;
-                       void* newname;
-                       void* oldname;
-                       size_t oldnamelen;
-                       void* oldprivate;
-                       size_t oldprivatelen;
-
-#ifdef CONFIG_COMPAT
-                       if (cmd == NCP_IOC_SETOBJECTNAME_32) {
-                               struct compat_ncp_objectname_ioctl user32;
-                               if (copy_from_user(&user32, argp, sizeof(user32)))
-                                       return -EFAULT;
-                               user.auth_type = user32.auth_type;
-                               user.object_name_len = user32.object_name_len;
-                               user.object_name = compat_ptr(user32.object_name);
-                       } else
-#endif
-                       if (copy_from_user(&user, argp, sizeof(user)))
-                               return -EFAULT;
-
-                       if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
-                               return -ENOMEM;
-                       if (user.object_name_len) {
-                               newname = memdup_user(user.object_name,
-                                                     user.object_name_len);
-                               if (IS_ERR(newname))
-                                       return PTR_ERR(newname);
-                       } else {
-                               newname = NULL;
-                       }
-                       down_write(&server->auth_rwsem);
-                       oldname = server->auth.object_name;
-                       oldnamelen = server->auth.object_name_len;
-                       oldprivate = server->priv.data;
-                       oldprivatelen = server->priv.len;
-                       server->auth.auth_type = user.auth_type;
-                       server->auth.object_name_len = user.object_name_len;
-                       server->auth.object_name = newname;
-                       server->priv.len = 0;
-                       server->priv.data = NULL;
-                       up_write(&server->auth_rwsem);
-                       kfree(oldprivate);
-                       kfree(oldname);
-                       return 0;
-               }
-
-#ifdef CONFIG_COMPAT
-       case NCP_IOC_GETPRIVATEDATA_32:
-#endif
-       case NCP_IOC_GETPRIVATEDATA:
-               {
-                       struct ncp_privatedata_ioctl user;
-                       size_t outl;
-
-#ifdef CONFIG_COMPAT
-                       if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
-                               struct compat_ncp_privatedata_ioctl user32;
-                               if (copy_from_user(&user32, argp, sizeof(user32)))
-                                       return -EFAULT;
-                               user.len = user32.len;
-                               user.data = compat_ptr(user32.data);
-                       } else
-#endif
-                       if (copy_from_user(&user, argp, sizeof(user)))
-                               return -EFAULT;
-
-                       down_read(&server->auth_rwsem);
-                       outl = user.len;
-                       user.len = server->priv.len;
-                       if (outl > user.len) outl = user.len;
-                       result = 0;
-                       if (outl) {
-                               if (copy_to_user(user.data,
-                                                server->priv.data,
-                                                outl))
-                                       result = -EFAULT;
-                       }
-                       up_read(&server->auth_rwsem);
-                       if (result)
-                               return result;
-#ifdef CONFIG_COMPAT
-                       if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
-                               struct compat_ncp_privatedata_ioctl user32;
-                               user32.len = user.len;
-                               user32.data = (unsigned long) user.data;
-                               if (copy_to_user(argp, &user32, sizeof(user32)))
-                                       return -EFAULT;
-                       } else
-#endif
-                       if (copy_to_user(argp, &user, sizeof(user)))
-                               return -EFAULT;
-
-                       return 0;
-               }
-
-#ifdef CONFIG_COMPAT
-       case NCP_IOC_SETPRIVATEDATA_32:
-#endif
-       case NCP_IOC_SETPRIVATEDATA:
-               {
-                       struct ncp_privatedata_ioctl user;
-                       void* new;
-                       void* old;
-                       size_t oldlen;
-
-#ifdef CONFIG_COMPAT
-                       if (cmd == NCP_IOC_SETPRIVATEDATA_32) {
-                               struct compat_ncp_privatedata_ioctl user32;
-                               if (copy_from_user(&user32, argp, sizeof(user32)))
-                                       return -EFAULT;
-                               user.len = user32.len;
-                               user.data = compat_ptr(user32.data);
-                       } else
-#endif
-                       if (copy_from_user(&user, argp, sizeof(user)))
-                               return -EFAULT;
-
-                       if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
-                               return -ENOMEM;
-                       if (user.len) {
-                               new = memdup_user(user.data, user.len);
-                               if (IS_ERR(new))
-                                       return PTR_ERR(new);
-                       } else {
-                               new = NULL;
-                       }
-                       down_write(&server->auth_rwsem);
-                       old = server->priv.data;
-                       oldlen = server->priv.len;
-                       server->priv.len = user.len;
-                       server->priv.data = new;
-                       up_write(&server->auth_rwsem);
-                       kfree(old);
-                       return 0;
-               }
-
-#ifdef CONFIG_NCPFS_NLS
-       case NCP_IOC_SETCHARSETS:
-               return ncp_set_charsets(server, argp);
-
-       case NCP_IOC_GETCHARSETS:
-               return ncp_get_charsets(server, argp);
-
-#endif /* CONFIG_NCPFS_NLS */
-
-       case NCP_IOC_SETDENTRYTTL:
-               {
-                       u_int32_t user;
-
-                       if (copy_from_user(&user, argp, sizeof(user)))
-                               return -EFAULT;
-                       /* 20 secs at most... */
-                       if (user > 20000)
-                               return -EINVAL;
-                       user = (user * HZ) / 1000;
-                       atomic_set(&server->dentry_ttl, user);
-                       return 0;
-               }
-
-       case NCP_IOC_GETDENTRYTTL:
-               {
-                       u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ;
-                       if (copy_to_user(argp, &user, sizeof(user)))
-                               return -EFAULT;
-                       return 0;
-               }
-
-       }
-       return -EINVAL;
-}
-
-long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       struct inode *inode = file_inode(filp);
-       struct ncp_server *server = NCP_SERVER(inode);
-       kuid_t uid = current_uid();
-       int need_drop_write = 0;
-       long ret;
-
-       switch (cmd) {
-       case NCP_IOC_SETCHARSETS:
-       case NCP_IOC_CONN_LOGGED_IN:
-       case NCP_IOC_SETROOT:
-               if (!capable(CAP_SYS_ADMIN)) {
-                       ret = -EPERM;
-                       goto out;
-               }
-               break;
-       }
-       if (!uid_eq(server->m.mounted_uid, uid)) {
-               switch (cmd) {
-               /*
-                * Only mount owner can issue these ioctls.  Information
-                * necessary to authenticate to other NDS servers are
-                * stored here.
-                */
-               case NCP_IOC_GETOBJECTNAME:
-               case NCP_IOC_SETOBJECTNAME:
-               case NCP_IOC_GETPRIVATEDATA:
-               case NCP_IOC_SETPRIVATEDATA:
-#ifdef CONFIG_COMPAT
-               case NCP_IOC_GETOBJECTNAME_32:
-               case NCP_IOC_SETOBJECTNAME_32:
-               case NCP_IOC_GETPRIVATEDATA_32:
-               case NCP_IOC_SETPRIVATEDATA_32:
-#endif
-                       ret = -EACCES;
-                       goto out;
-               /*
-                * These require write access on the inode if user id
-                * does not match.  Note that they do not write to the
-                * file...  But old code did mnt_want_write, so I keep
-                * it as is.  Of course not for mountpoint owner, as
-                * that breaks read-only mounts altogether as ncpmount
-                * needs working NCP_IOC_NCPREQUEST and
-                * NCP_IOC_GET_FS_INFO.  Some of these codes (setdentryttl,
-                * signinit, setsignwanted) should be probably restricted
-                * to owner only, or even more to CAP_SYS_ADMIN).
-                */
-               case NCP_IOC_GET_FS_INFO:
-               case NCP_IOC_GET_FS_INFO_V2:
-               case NCP_IOC_NCPREQUEST:
-               case NCP_IOC_SETDENTRYTTL:
-               case NCP_IOC_SIGN_INIT:
-               case NCP_IOC_LOCKUNLOCK:
-               case NCP_IOC_SET_SIGN_WANTED:
-#ifdef CONFIG_COMPAT
-               case NCP_IOC_GET_FS_INFO_V2_32:
-               case NCP_IOC_NCPREQUEST_32:
-#endif
-                       ret = mnt_want_write_file(filp);
-                       if (ret)
-                               goto out;
-                       need_drop_write = 1;
-                       ret = inode_permission(inode, MAY_WRITE);
-                       if (ret)
-                               goto outDropWrite;
-                       break;
-               /*
-                * Read access required.
-                */
-               case NCP_IOC_GETMOUNTUID16:
-               case NCP_IOC_GETMOUNTUID32:
-               case NCP_IOC_GETMOUNTUID64:
-               case NCP_IOC_GETROOT:
-               case NCP_IOC_SIGN_WANTED:
-                       ret = inode_permission(inode, MAY_READ);
-                       if (ret)
-                               goto out;
-                       break;
-               /*
-                * Anybody can read these.
-                */
-               case NCP_IOC_GETCHARSETS:
-               case NCP_IOC_GETDENTRYTTL:
-               default:
-               /* Three codes below are protected by CAP_SYS_ADMIN above. */
-               case NCP_IOC_SETCHARSETS:
-               case NCP_IOC_CONN_LOGGED_IN:
-               case NCP_IOC_SETROOT:
-                       break;
-               }
-       }
-       ret = __ncp_ioctl(inode, cmd, arg);
-outDropWrite:
-       if (need_drop_write)
-               mnt_drop_write_file(filp);
-out:
-       return ret;
-}
-
-#ifdef CONFIG_COMPAT
-long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       long ret;
-
-       arg = (unsigned long) compat_ptr(arg);
-       ret = ncp_ioctl(file, cmd, arg);
-       return ret;
-}
-#endif
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
deleted file mode 100644 (file)
index a5c5cf2..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  mmap.c
- *
- *  Copyright (C) 1995, 1996 by Volker Lendecke
- *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- *
- */
-
-#include <linux/stat.h>
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <linux/gfp.h>
-#include <linux/mm.h>
-#include <linux/shm.h>
-#include <linux/errno.h>
-#include <linux/mman.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/memcontrol.h>
-
-#include <linux/uaccess.h>
-
-#include "ncp_fs.h"
-
-/*
- * Fill in the supplied page for mmap
- * XXX: how are we excluding truncate/invalidate here? Maybe need to lock
- * page?
- */
-static int ncp_file_mmap_fault(struct vm_fault *vmf)
-{
-       struct inode *inode = file_inode(vmf->vma->vm_file);
-       char *pg_addr;
-       unsigned int already_read;
-       unsigned int count;
-       int bufsize;
-       int pos; /* XXX: loff_t ? */
-
-       /*
-        * ncpfs has nothing against high pages as long
-        * as recvmsg and memset works on it
-        */
-       vmf->page = alloc_page(GFP_HIGHUSER);
-       if (!vmf->page)
-               return VM_FAULT_OOM;
-       pg_addr = kmap(vmf->page);
-       pos = vmf->pgoff << PAGE_SHIFT;
-
-       count = PAGE_SIZE;
-       /* what we can read in one go */
-       bufsize = NCP_SERVER(inode)->buffer_size;
-
-       already_read = 0;
-       if (ncp_make_open(inode, O_RDONLY) >= 0) {
-               while (already_read < count) {
-                       int read_this_time;
-                       int to_read;
-
-                       to_read = bufsize - (pos % bufsize);
-
-                       to_read = min_t(unsigned int, to_read, count - already_read);
-
-                       if (ncp_read_kernel(NCP_SERVER(inode),
-                                    NCP_FINFO(inode)->file_handle,
-                                    pos, to_read,
-                                    pg_addr + already_read,
-                                    &read_this_time) != 0) {
-                               read_this_time = 0;
-                       }
-                       pos += read_this_time;
-                       already_read += read_this_time;
-
-                       if (read_this_time < to_read) {
-                               break;
-                       }
-               }
-               ncp_inode_close(inode);
-
-       }
-
-       if (already_read < PAGE_SIZE)
-               memset(pg_addr + already_read, 0, PAGE_SIZE - already_read);
-       flush_dcache_page(vmf->page);
-       kunmap(vmf->page);
-
-       /*
-        * If I understand ncp_read_kernel() properly, the above always
-        * fetches from the network, here the analogue of disk.
-        * -- nyc
-        */
-       count_vm_event(PGMAJFAULT);
-       count_memcg_event_mm(vmf->vma->vm_mm, PGMAJFAULT);
-       return VM_FAULT_MAJOR;
-}
-
-static const struct vm_operations_struct ncp_file_mmap =
-{
-       .fault = ncp_file_mmap_fault,
-};
-
-
-/* This is used for a general mmap of a ncp file */
-int ncp_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct inode *inode = file_inode(file);
-       
-       ncp_dbg(1, "called\n");
-
-       if (!ncp_conn_valid(NCP_SERVER(inode)))
-               return -EIO;
-
-       /* only PAGE_COW or read-only supported now */
-       if (vma->vm_flags & VM_SHARED)
-               return -EINVAL;
-       /* we do not support files bigger than 4GB... We eventually 
-          supports just 4GB... */
-       if (vma_pages(vma) + vma->vm_pgoff
-          > (1U << (32 - PAGE_SHIFT)))
-               return -EFBIG;
-
-       vma->vm_ops = &ncp_file_mmap;
-       file_accessed(file);
-       return 0;
-}
diff --git a/fs/ncpfs/ncp_fs.h b/fs/ncpfs/ncp_fs.h
deleted file mode 100644 (file)
index bdd262b..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <linux/ncp_fs.h>
-#include "ncp_fs_i.h"
-#include "ncp_fs_sb.h"
-
-#undef NCPFS_PARANOIA
-#ifdef NCPFS_PARANOIA
-#define ncp_vdbg(fmt, ...)                                     \
-       pr_debug(fmt, ##__VA_ARGS__)
-#else
-#define ncp_vdbg(fmt, ...)                                     \
-do {                                                           \
-       if (0)                                                  \
-               pr_debug(fmt, ##__VA_ARGS__);                   \
-} while (0)
-#endif
-
-#ifndef DEBUG_NCP
-#define DEBUG_NCP 0
-#endif
-
-#if DEBUG_NCP > 0 && !defined(DEBUG)
-#define DEBUG
-#endif
-
-#define ncp_dbg(level, fmt, ...)                               \
-do {                                                           \
-       if (level <= DEBUG_NCP)                                 \
-               pr_debug(fmt, ##__VA_ARGS__);                   \
-} while (0)
-
-#define NCP_MAX_RPC_TIMEOUT (6*HZ)
-
-
-struct ncp_entry_info {
-       struct nw_info_struct   i;
-       ino_t                   ino;
-       int                     opened;
-       int                     access;
-       unsigned int            volume;
-       __u8                    file_handle[6];
-};
-
-static inline struct ncp_server *NCP_SBP(const struct super_block *sb)
-{
-       return sb->s_fs_info;
-}
-
-#define NCP_SERVER(inode)      NCP_SBP((inode)->i_sb)
-static inline struct ncp_inode_info *NCP_FINFO(const struct inode *inode)
-{
-       return container_of(inode, struct ncp_inode_info, vfs_inode);
-}
-
-/* linux/fs/ncpfs/inode.c */
-int ncp_notify_change(struct dentry *, struct iattr *);
-struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *);
-void ncp_update_inode(struct inode *, struct ncp_entry_info *);
-void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
-
-/* linux/fs/ncpfs/dir.c */
-extern const struct inode_operations ncp_dir_inode_operations;
-extern const struct file_operations ncp_dir_operations;
-extern const struct dentry_operations ncp_dentry_operations;
-int ncp_conn_logged_in(struct super_block *);
-int ncp_date_dos2unix(__le16 time, __le16 date);
-void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date);
-
-/* linux/fs/ncpfs/ioctl.c */
-long ncp_ioctl(struct file *, unsigned int, unsigned long);
-long ncp_compat_ioctl(struct file *, unsigned int, unsigned long);
-
-/* linux/fs/ncpfs/sock.c */
-int ncp_request2(struct ncp_server *server, int function,
-       void* reply, int max_reply_size);
-static inline int ncp_request(struct ncp_server *server, int function) {
-       return ncp_request2(server, function, server->packet, server->packet_size);
-}
-int ncp_connect(struct ncp_server *server);
-int ncp_disconnect(struct ncp_server *server);
-void ncp_lock_server(struct ncp_server *server);
-void ncp_unlock_server(struct ncp_server *server);
-
-/* linux/fs/ncpfs/symlink.c */
-#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-extern const struct address_space_operations ncp_symlink_aops;
-int ncp_symlink(struct inode*, struct dentry*, const char*);
-#endif
-
-/* linux/fs/ncpfs/file.c */
-extern const struct inode_operations ncp_file_inode_operations;
-extern const struct file_operations ncp_file_operations;
-int ncp_make_open(struct inode *, int);
-
-/* linux/fs/ncpfs/mmap.c */
-int ncp_mmap(struct file *, struct vm_area_struct *);
-
-/* linux/fs/ncpfs/ncplib_kernel.c */
-int ncp_make_closed(struct inode *);
-
-#include "ncplib_kernel.h"
diff --git a/fs/ncpfs/ncp_fs_i.h b/fs/ncpfs/ncp_fs_i.h
deleted file mode 100644 (file)
index 3432baf..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *  ncp_fs_i.h
- *
- *  Copyright (C) 1995 Volker Lendecke
- *
- */
-
-#ifndef _LINUX_NCP_FS_I
-#define _LINUX_NCP_FS_I
-
-/*
- * This is the ncpfs part of the inode structure. This must contain
- * all the information we need to work with an inode after creation.
- */
-struct ncp_inode_info {
-       __le32  dirEntNum;
-       __le32  DosDirNum;
-       __u8    volNumber;
-       __le32  nwattr;
-       struct mutex open_mutex;
-       atomic_t        opened;
-       int     access;
-       int     flags;
-#define NCPI_KLUDGE_SYMLINK    0x0001
-#define NCPI_DIR_CACHE         0x0002
-       __u8    file_handle[6];
-       struct inode vfs_inode;
-};
-
-#endif /* _LINUX_NCP_FS_I */
diff --git a/fs/ncpfs/ncp_fs_sb.h b/fs/ncpfs/ncp_fs_sb.h
deleted file mode 100644 (file)
index f06cde4..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *  ncp_fs_sb.h
- *
- *  Copyright (C) 1995, 1996 by Volker Lendecke
- *
- */
-
-#ifndef _NCP_FS_SB
-#define _NCP_FS_SB
-
-#include <linux/types.h>
-#include <linux/ncp_mount.h>
-#include <linux/net.h>
-#include <linux/mutex.h>
-#include <linux/backing-dev.h>
-#include <linux/workqueue.h>
-
-#define NCP_DEFAULT_OPTIONS 0          /* 2 for packet signatures */
-
-struct sock;
-
-struct ncp_mount_data_kernel {
-       unsigned long    flags;         /* NCP_MOUNT_* flags */
-       unsigned int     int_flags;     /* internal flags */
-#define NCP_IMOUNT_LOGGEDIN_POSSIBLE   0x0001
-       kuid_t           mounted_uid;   /* Who may umount() this filesystem? */
-       struct pid      *wdog_pid;      /* Who cares for our watchdog packets? */
-       unsigned int     ncp_fd;        /* The socket to the ncp port */
-       unsigned int     time_out;      /* How long should I wait after
-                                          sending a NCP request? */
-       unsigned int     retry_count;   /* And how often should I retry? */
-       unsigned char    mounted_vol[NCP_VOLNAME_LEN + 1];
-       kuid_t           uid;
-       kgid_t           gid;
-       umode_t          file_mode;
-       umode_t          dir_mode;
-       int              info_fd;
-};
-
-struct ncp_server {
-       struct rcu_head rcu;
-       struct ncp_mount_data_kernel m; /* Nearly all of the mount data is of
-                                          interest for us later, so we store
-                                          it completely. */
-
-       __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2];
-
-       struct socket *ncp_sock;/* ncp socket */
-       struct socket *info_sock;
-
-       u8 sequence;
-       u8 task;
-       u16 connection;         /* Remote connection number */
-
-       u8 completion;          /* Status message from server */
-       u8 conn_status;         /* Bit 4 = 1 ==> Server going down, no
-                                  requests allowed anymore.
-                                  Bit 0 = 1 ==> Server is down. */
-
-       int buffer_size;        /* Negotiated bufsize */
-
-       int reply_size;         /* Size of last reply */
-
-       int packet_size;
-       unsigned char *packet;  /* Here we prepare requests and
-                                  receive replies */
-       unsigned char *txbuf;   /* Storage for current request */
-       unsigned char *rxbuf;   /* Storage for reply to current request */
-
-       int lock;               /* To prevent mismatch in protocols. */
-       struct mutex mutex;
-
-       int current_size;       /* for packet preparation */
-       int has_subfunction;
-       int ncp_reply_size;
-
-       int root_setuped;
-       struct mutex root_setup_lock;
-
-       /* info for packet signing */
-       int sign_wanted;        /* 1=Server needs signed packets */
-       int sign_active;        /* 0=don't do signing, 1=do */
-       char sign_root[8];      /* generated from password and encr. key */
-       char sign_last[16];     
-
-       /* Authentication info: NDS or BINDERY, username */
-       struct {
-               int     auth_type;
-               size_t  object_name_len;
-               void*   object_name;
-               int     object_type;
-       } auth;
-       /* Password info */
-       struct {
-               size_t  len;
-               void*   data;
-       } priv;
-       struct rw_semaphore auth_rwsem;
-
-       /* nls info: codepage for volume and charset for I/O */
-       struct nls_table *nls_vol;
-       struct nls_table *nls_io;
-
-       /* maximum age in jiffies */
-       atomic_t dentry_ttl;
-
-       /* miscellaneous */
-       unsigned int flags;
-
-       spinlock_t requests_lock;       /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */
-
-       void (*data_ready)(struct sock* sk);
-       void (*error_report)(struct sock* sk);
-       void (*write_space)(struct sock* sk);   /* STREAM mode only */
-       struct {
-               struct work_struct tq;          /* STREAM/DGRAM: data/error ready */
-               struct ncp_request_reply* creq; /* STREAM/DGRAM: awaiting reply from this request */
-               struct mutex creq_mutex;        /* DGRAM only: lock accesses to rcv.creq */
-
-               unsigned int state;             /* STREAM only: receiver state */
-               struct {
-                       __u32 magic __packed;
-                       __u32 len __packed;
-                       __u16 type __packed;
-                       __u16 p1 __packed;
-                       __u16 p2 __packed;
-                       __u16 p3 __packed;
-                       __u16 type2 __packed;
-               } buf;                          /* STREAM only: temporary buffer */
-               unsigned char* ptr;             /* STREAM only: pointer to data */
-               size_t len;                     /* STREAM only: length of data to receive */
-       } rcv;
-       struct {
-               struct list_head requests;      /* STREAM only: queued requests */
-               struct work_struct tq;          /* STREAM only: transmitter ready */
-               struct ncp_request_reply* creq; /* STREAM only: currently transmitted entry */
-       } tx;
-       struct timer_list timeout_tm;           /* DGRAM only: timeout timer */
-       struct work_struct timeout_tq;          /* DGRAM only: associated queue, we run timers from process context */
-       int timeout_last;                       /* DGRAM only: current timeout length */
-       int timeout_retries;                    /* DGRAM only: retries left */
-       struct {
-               size_t len;
-               __u8 data[128];
-       } unexpected_packet;
-};
-
-extern void ncp_tcp_rcv_proc(struct work_struct *work);
-extern void ncp_tcp_tx_proc(struct work_struct *work);
-extern void ncpdgram_rcv_proc(struct work_struct *work);
-extern void ncpdgram_timeout_proc(struct work_struct *work);
-extern void ncpdgram_timeout_call(struct timer_list *t);
-extern void ncp_tcp_data_ready(struct sock* sk);
-extern void ncp_tcp_write_space(struct sock* sk);
-extern void ncp_tcp_error_report(struct sock* sk);
-
-#define NCP_FLAG_UTF8  1
-
-#define NCP_CLR_FLAG(server, flag)     ((server)->flags &= ~(flag))
-#define NCP_SET_FLAG(server, flag)     ((server)->flags |= (flag))
-#define NCP_IS_FLAG(server, flag)      ((server)->flags & (flag))
-
-static inline int ncp_conn_valid(struct ncp_server *server)
-{
-       return ((server->conn_status & 0x11) == 0);
-}
-
-static inline void ncp_invalidate_conn(struct ncp_server *server)
-{
-       server->conn_status |= 0x01;
-}
-
-#endif
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
deleted file mode 100644 (file)
index 804adfe..0000000
+++ /dev/null
@@ -1,1322 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  ncplib_kernel.c
- *
- *  Copyright (C) 1995, 1996 by Volker Lendecke
- *  Modified for big endian by J.F. Chadima and David S. Miller
- *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- *  Modified 1999 Wolfram Pienkoss for NLS
- *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "ncp_fs.h"
-
-static inline void assert_server_locked(struct ncp_server *server)
-{
-       if (server->lock == 0) {
-               ncp_dbg(1, "server not locked!\n");
-       }
-}
-
-static void ncp_add_byte(struct ncp_server *server, __u8 x)
-{
-       assert_server_locked(server);
-       *(__u8 *) (&(server->packet[server->current_size])) = x;
-       server->current_size += 1;
-       return;
-}
-
-static void ncp_add_word(struct ncp_server *server, __le16 x)
-{
-       assert_server_locked(server);
-       put_unaligned(x, (__le16 *) (&(server->packet[server->current_size])));
-       server->current_size += 2;
-       return;
-}
-
-static void ncp_add_be16(struct ncp_server *server, __u16 x)
-{
-       assert_server_locked(server);
-       put_unaligned(cpu_to_be16(x), (__be16 *) (&(server->packet[server->current_size])));
-       server->current_size += 2;
-}
-
-static void ncp_add_dword(struct ncp_server *server, __le32 x)
-{
-       assert_server_locked(server);
-       put_unaligned(x, (__le32 *) (&(server->packet[server->current_size])));
-       server->current_size += 4;
-       return;
-}
-
-static void ncp_add_be32(struct ncp_server *server, __u32 x)
-{
-       assert_server_locked(server);
-       put_unaligned(cpu_to_be32(x), (__be32 *)(&(server->packet[server->current_size])));
-       server->current_size += 4;
-}
-
-static inline void ncp_add_dword_lh(struct ncp_server *server, __u32 x) {
-       ncp_add_dword(server, cpu_to_le32(x));
-}
-
-static void ncp_add_mem(struct ncp_server *server, const void *source, int size)
-{
-       assert_server_locked(server);
-       memcpy(&(server->packet[server->current_size]), source, size);
-       server->current_size += size;
-       return;
-}
-
-static void ncp_add_pstring(struct ncp_server *server, const char *s)
-{
-       int len = strlen(s);
-       assert_server_locked(server);
-       if (len > 255) {
-               ncp_dbg(1, "string too long: %s\n", s);
-               len = 255;
-       }
-       ncp_add_byte(server, len);
-       ncp_add_mem(server, s, len);
-       return;
-}
-
-static inline void ncp_init_request(struct ncp_server *server)
-{
-       ncp_lock_server(server);
-
-       server->current_size = sizeof(struct ncp_request_header);
-       server->has_subfunction = 0;
-}
-
-static inline void ncp_init_request_s(struct ncp_server *server, int subfunction)
-{
-       ncp_lock_server(server);
-       
-       server->current_size = sizeof(struct ncp_request_header) + 2;
-       ncp_add_byte(server, subfunction);
-
-       server->has_subfunction = 1;
-}
-
-static inline char *
-ncp_reply_data(struct ncp_server *server, int offset)
-{
-       return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
-}
-
-static inline u8 BVAL(const void *data)
-{
-       return *(const u8 *)data;
-}
-
-static u8 ncp_reply_byte(struct ncp_server *server, int offset)
-{
-       return *(const u8 *)ncp_reply_data(server, offset);
-}
-
-static inline u16 WVAL_LH(const void *data)
-{
-       return get_unaligned_le16(data);
-}
-
-static u16
-ncp_reply_le16(struct ncp_server *server, int offset)
-{
-       return get_unaligned_le16(ncp_reply_data(server, offset));
-}
-
-static u16
-ncp_reply_be16(struct ncp_server *server, int offset)
-{
-       return get_unaligned_be16(ncp_reply_data(server, offset));
-}
-
-static inline u32 DVAL_LH(const void *data)
-{
-       return get_unaligned_le32(data);
-}
-
-static __le32
-ncp_reply_dword(struct ncp_server *server, int offset)
-{
-       return get_unaligned((__le32 *)ncp_reply_data(server, offset));
-}
-
-static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) {
-       return le32_to_cpu(ncp_reply_dword(server, offset));
-}
-
-int
-ncp_negotiate_buffersize(struct ncp_server *server, int size, int *target)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_be16(server, size);
-
-       if ((result = ncp_request(server, 33)) != 0) {
-               ncp_unlock_server(server);
-               return result;
-       }
-       *target = min_t(unsigned int, ncp_reply_be16(server, 0), size);
-
-       ncp_unlock_server(server);
-       return 0;
-}
-
-
-/* options: 
- *     bit 0   ipx checksum
- *     bit 1   packet signing
- */
-int
-ncp_negotiate_size_and_options(struct ncp_server *server, 
-       int size, int options, int *ret_size, int *ret_options) {
-       int result;
-
-       /* there is minimum */
-       if (size < NCP_BLOCK_SIZE) size = NCP_BLOCK_SIZE;
-
-       ncp_init_request(server);
-       ncp_add_be16(server, size);
-       ncp_add_byte(server, options);
-       
-       if ((result = ncp_request(server, 0x61)) != 0)
-       {
-               ncp_unlock_server(server);
-               return result;
-       }
-
-       /* NCP over UDP returns 0 (!!!) */
-       result = ncp_reply_be16(server, 0);
-       if (result >= NCP_BLOCK_SIZE)
-               size = min(result, size);
-       *ret_size = size;
-       *ret_options = ncp_reply_byte(server, 4);
-
-       ncp_unlock_server(server);
-       return 0;
-}
-
-int ncp_get_volume_info_with_number(struct ncp_server* server,
-                            int n, struct ncp_volume_info* target) {
-       int result;
-       int len;
-
-       ncp_init_request_s(server, 44);
-       ncp_add_byte(server, n);
-
-       if ((result = ncp_request(server, 22)) != 0) {
-               goto out;
-       }
-       target->total_blocks = ncp_reply_dword_lh(server, 0);
-       target->free_blocks = ncp_reply_dword_lh(server, 4);
-       target->purgeable_blocks = ncp_reply_dword_lh(server, 8);
-       target->not_yet_purgeable_blocks = ncp_reply_dword_lh(server, 12);
-       target->total_dir_entries = ncp_reply_dword_lh(server, 16);
-       target->available_dir_entries = ncp_reply_dword_lh(server, 20);
-       target->sectors_per_block = ncp_reply_byte(server, 28);
-
-       memset(&(target->volume_name), 0, sizeof(target->volume_name));
-
-       result = -EIO;
-       len = ncp_reply_byte(server, 29);
-       if (len > NCP_VOLNAME_LEN) {
-               ncp_dbg(1, "volume name too long: %d\n", len);
-               goto out;
-       }
-       memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
-       result = 0;
-out:
-       ncp_unlock_server(server);
-       return result;
-}
-
-int ncp_get_directory_info(struct ncp_server* server, __u8 n, 
-                          struct ncp_volume_info* target) {
-       int result;
-       int len;
-
-       ncp_init_request_s(server, 45);
-       ncp_add_byte(server, n);
-
-       if ((result = ncp_request(server, 22)) != 0) {
-               goto out;
-       }
-       target->total_blocks = ncp_reply_dword_lh(server, 0);
-       target->free_blocks = ncp_reply_dword_lh(server, 4);
-       target->purgeable_blocks = 0;
-       target->not_yet_purgeable_blocks = 0;
-       target->total_dir_entries = ncp_reply_dword_lh(server, 8);
-       target->available_dir_entries = ncp_reply_dword_lh(server, 12);
-       target->sectors_per_block = ncp_reply_byte(server, 20);
-
-       memset(&(target->volume_name), 0, sizeof(target->volume_name));
-
-       result = -EIO;
-       len = ncp_reply_byte(server, 21);
-       if (len > NCP_VOLNAME_LEN) {
-               ncp_dbg(1, "volume name too long: %d\n", len);
-               goto out;
-       }
-       memcpy(&(target->volume_name), ncp_reply_data(server, 22), len);
-       result = 0;
-out:
-       ncp_unlock_server(server);
-       return result;
-}
-
-int
-ncp_close_file(struct ncp_server *server, const char *file_id)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 0);
-       ncp_add_mem(server, file_id, 6);
-
-       result = ncp_request(server, 66);
-       ncp_unlock_server(server);
-       return result;
-}
-
-int
-ncp_make_closed(struct inode *inode)
-{
-       int err;
-
-       err = 0;
-       mutex_lock(&NCP_FINFO(inode)->open_mutex);
-       if (atomic_read(&NCP_FINFO(inode)->opened) == 1) {
-               atomic_set(&NCP_FINFO(inode)->opened, 0);
-               err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle);
-
-               if (!err)
-                       ncp_vdbg("volnum=%d, dirent=%u, error=%d\n",
-                                NCP_FINFO(inode)->volNumber,
-                                NCP_FINFO(inode)->dirEntNum, err);
-       }
-       mutex_unlock(&NCP_FINFO(inode)->open_mutex);
-       return err;
-}
-
-static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
-                               __le32 dir_base, int have_dir_base, 
-                               const char *path)
-{
-       ncp_add_byte(server, vol_num);
-       ncp_add_dword(server, dir_base);
-       if (have_dir_base != 0) {
-               ncp_add_byte(server, 1);        /* dir_base */
-       } else {
-               ncp_add_byte(server, 0xff);     /* no handle */
-       }
-       if (path != NULL) {
-               ncp_add_byte(server, 1);        /* 1 component */
-               ncp_add_pstring(server, path);
-       } else {
-               ncp_add_byte(server, 0);
-       }
-}
-
-int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __le32 dirent,
-                       __u8* dirhandle) {
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 12);               /* subfunction */
-       ncp_add_byte(server, NW_NS_DOS);
-       ncp_add_byte(server, 0);
-       ncp_add_word(server, 0);
-       ncp_add_handle_path(server, volnum, dirent, 1, NULL);
-       if ((result = ncp_request(server, 87)) == 0) {
-               *dirhandle = ncp_reply_byte(server, 0);
-       }
-       ncp_unlock_server(server);
-       return result;
-}
-
-int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) {
-       int result;
-       
-       ncp_init_request_s(server, 20);
-       ncp_add_byte(server, dirhandle);
-       result = ncp_request(server, 22);
-       ncp_unlock_server(server);
-       return result;
-}
-
-void ncp_extract_file_info(const void *structure, struct nw_info_struct *target)
-{
-       const __u8 *name_len;
-       const int info_struct_size = offsetof(struct nw_info_struct, nameLen);
-
-       memcpy(target, structure, info_struct_size);
-       name_len = structure + info_struct_size;
-       target->nameLen = *name_len;
-       memcpy(target->entryName, name_len + 1, *name_len);
-       target->entryName[*name_len] = '\0';
-       target->volNumber = le32_to_cpu(target->volNumber);
-       return;
-}
-
-#ifdef CONFIG_NCPFS_NFS_NS
-static inline void ncp_extract_nfs_info(const unsigned char *structure,
-                                struct nw_nfs_info *target)
-{
-       target->mode = DVAL_LH(structure);
-       target->rdev = DVAL_LH(structure + 8);
-}
-#endif
-
-int ncp_obtain_nfs_info(struct ncp_server *server,
-                       struct nw_info_struct *target)
-
-{
-       int result = 0;
-#ifdef CONFIG_NCPFS_NFS_NS
-       __u32 volnum = target->volNumber;
-
-       if (ncp_is_nfs_extras(server, volnum)) {
-               ncp_init_request(server);
-               ncp_add_byte(server, 19);       /* subfunction */
-               ncp_add_byte(server, server->name_space[volnum]);
-               ncp_add_byte(server, NW_NS_NFS);
-               ncp_add_byte(server, 0);
-               ncp_add_byte(server, volnum);
-               ncp_add_dword(server, target->dirEntNum);
-               /* We must retrieve both nlinks and rdev, otherwise some server versions
-                  report zeroes instead of valid data */
-               ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV);
-
-               if ((result = ncp_request(server, 87)) == 0) {
-                       ncp_extract_nfs_info(ncp_reply_data(server, 0), &target->nfs);
-                       ncp_dbg(1, "(%s) mode=0%o, rdev=0x%x\n",
-                               target->entryName, target->nfs.mode,
-                               target->nfs.rdev);
-               } else {
-                       target->nfs.mode = 0;
-                       target->nfs.rdev = 0;
-               }
-               ncp_unlock_server(server);
-
-       } else
-#endif
-       {
-               target->nfs.mode = 0;
-               target->nfs.rdev = 0;
-       }
-       return result;
-}
-
-/*
- * Returns information for a (one-component) name relative to
- * the specified directory.
- */
-int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path,
-                       struct nw_info_struct *target)
-{
-       __u8  volnum = NCP_FINFO(dir)->volNumber;
-       __le32 dirent = NCP_FINFO(dir)->dirEntNum;
-       int result;
-
-       if (target == NULL) {
-               pr_err("%s: invalid call\n", __func__);
-               return -EINVAL;
-       }
-       ncp_init_request(server);
-       ncp_add_byte(server, 6);        /* subfunction */
-       ncp_add_byte(server, server->name_space[volnum]);
-       ncp_add_byte(server, server->name_space[volnum]); /* N.B. twice ?? */
-       ncp_add_word(server, cpu_to_le16(0x8006));      /* get all */
-       ncp_add_dword(server, RIM_ALL);
-       ncp_add_handle_path(server, volnum, dirent, 1, path);
-
-       if ((result = ncp_request(server, 87)) != 0)
-               goto out;
-       ncp_extract_file_info(ncp_reply_data(server, 0), target);
-       ncp_unlock_server(server);
-       
-       result = ncp_obtain_nfs_info(server, target);
-       return result;
-
-out:
-       ncp_unlock_server(server);
-       return result;
-}
-
-#ifdef CONFIG_NCPFS_NFS_NS
-static int
-ncp_obtain_DOS_dir_base(struct ncp_server *server,
-               __u8 ns, __u8 volnum, __le32 dirent,
-               const char *path, /* At most 1 component */
-               __le32 *DOS_dir_base)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 6); /* subfunction */
-       ncp_add_byte(server, ns);
-       ncp_add_byte(server, ns);
-       ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
-       ncp_add_dword(server, RIM_DIRECTORY);
-       ncp_add_handle_path(server, volnum, dirent, 1, path);
-
-       if ((result = ncp_request(server, 87)) == 0)
-       {
-               if (DOS_dir_base) *DOS_dir_base=ncp_reply_dword(server, 0x34);
-       }
-       ncp_unlock_server(server);
-       return result;
-}
-#endif /* CONFIG_NCPFS_NFS_NS */
-
-static inline int
-ncp_get_known_namespace(struct ncp_server *server, __u8 volume)
-{
-#if defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS)
-       int result;
-       __u8 *namespace;
-       __u16 no_namespaces;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 24);       /* Subfunction: Get Name Spaces Loaded */
-       ncp_add_word(server, 0);
-       ncp_add_byte(server, volume);
-
-       if ((result = ncp_request(server, 87)) != 0) {
-               ncp_unlock_server(server);
-               return NW_NS_DOS; /* not result ?? */
-       }
-
-       result = NW_NS_DOS;
-       no_namespaces = ncp_reply_le16(server, 0);
-       namespace = ncp_reply_data(server, 2);
-
-       while (no_namespaces > 0) {
-               ncp_dbg(1, "found %d on %d\n", *namespace, volume);
-
-#ifdef CONFIG_NCPFS_NFS_NS
-               if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS)) 
-               {
-                       result = NW_NS_NFS;
-                       break;
-               }
-#endif /* CONFIG_NCPFS_NFS_NS */
-#ifdef CONFIG_NCPFS_OS2_NS
-               if ((*namespace == NW_NS_OS2) && !(server->m.flags&NCP_MOUNT_NO_OS2))
-               {
-                       result = NW_NS_OS2;
-               }
-#endif /* CONFIG_NCPFS_OS2_NS */
-               namespace += 1;
-               no_namespaces -= 1;
-       }
-       ncp_unlock_server(server);
-       return result;
-#else  /* neither OS2 nor NFS - only DOS */
-       return NW_NS_DOS;
-#endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
-}
-
-int
-ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns)
-{
-       int ns = ncp_get_known_namespace(server, volume);
-
-       if (ret_ns)
-               *ret_ns = ns;
-
-       ncp_dbg(1, "namespace[%d] = %d\n", volume, server->name_space[volume]);
-
-       if (server->name_space[volume] == ns)
-               return 0;
-       server->name_space[volume] = ns;
-       return 1;
-}
-
-static int
-ncp_ObtainSpecificDirBase(struct ncp_server *server,
-               __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
-               const char *path, /* At most 1 component */
-               __le32 *dirEntNum, __le32 *DosDirNum)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 6); /* subfunction */
-       ncp_add_byte(server, nsSrc);
-       ncp_add_byte(server, nsDst);
-       ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
-       ncp_add_dword(server, RIM_ALL);
-       ncp_add_handle_path(server, vol_num, dir_base, 1, path);
-
-       if ((result = ncp_request(server, 87)) != 0)
-       {
-               ncp_unlock_server(server);
-               return result;
-       }
-
-       if (dirEntNum)
-               *dirEntNum = ncp_reply_dword(server, 0x30);
-       if (DosDirNum)
-               *DosDirNum = ncp_reply_dword(server, 0x34);
-       ncp_unlock_server(server);
-       return 0;
-}
-
-int
-ncp_mount_subdir(struct ncp_server *server,
-                __u8 volNumber, __u8 srcNS, __le32 dirEntNum,
-                __u32* volume, __le32* newDirEnt, __le32* newDosEnt)
-{
-       int dstNS;
-       int result;
-
-       ncp_update_known_namespace(server, volNumber, &dstNS);
-       if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, 
-                                     dirEntNum, NULL, newDirEnt, newDosEnt)) != 0)
-       {
-               return result;
-       }
-       *volume = volNumber;
-       server->m.mounted_vol[1] = 0;
-       server->m.mounted_vol[0] = 'X';
-       return 0;
-}
-
-int 
-ncp_get_volume_root(struct ncp_server *server,
-                   const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent)
-{
-       int result;
-
-       ncp_dbg(1, "looking up vol %s\n", volname);
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 22);       /* Subfunction: Generate dir handle */
-       ncp_add_byte(server, 0);        /* DOS namespace */
-       ncp_add_byte(server, 0);        /* reserved */
-       ncp_add_byte(server, 0);        /* reserved */
-       ncp_add_byte(server, 0);        /* reserved */
-
-       ncp_add_byte(server, 0);        /* faked volume number */
-       ncp_add_dword(server, 0);       /* faked dir_base */
-       ncp_add_byte(server, 0xff);     /* Don't have a dir_base */
-       ncp_add_byte(server, 1);        /* 1 path component */
-       ncp_add_pstring(server, volname);
-
-       if ((result = ncp_request(server, 87)) != 0) {
-               ncp_unlock_server(server);
-               return result;
-       }
-       *dirent = *dosdirent = ncp_reply_dword(server, 4);
-       *volume = ncp_reply_byte(server, 8);
-       ncp_unlock_server(server);
-       return 0;
-}
-
-int
-ncp_lookup_volume(struct ncp_server *server,
-                 const char *volname, struct nw_info_struct *target)
-{
-       int result;
-
-       memset(target, 0, sizeof(*target));
-       result = ncp_get_volume_root(server, volname,
-                       &target->volNumber, &target->dirEntNum, &target->DosDirNum);
-       if (result) {
-               return result;
-       }
-       ncp_update_known_namespace(server, target->volNumber, NULL);
-       target->nameLen = strlen(volname);
-       memcpy(target->entryName, volname, target->nameLen+1);
-       target->attributes = aDIR;
-       /* set dates to Jan 1, 1986  00:00 */
-       target->creationTime = target->modifyTime = cpu_to_le16(0x0000);
-       target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21);
-       target->nfs.mode = 0;
-       return 0;
-}
-
-int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server,
-                                           struct inode *dir,
-                                           const char *path,
-                                           __le32 info_mask,
-                                           const struct nw_modify_dos_info *info)
-{
-       __u8  volnum = NCP_FINFO(dir)->volNumber;
-       __le32 dirent = NCP_FINFO(dir)->dirEntNum;
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 7);        /* subfunction */
-       ncp_add_byte(server, server->name_space[volnum]);
-       ncp_add_byte(server, 0);        /* reserved */
-       ncp_add_word(server, cpu_to_le16(0x8006));      /* search attribs: all */
-
-       ncp_add_dword(server, info_mask);
-       ncp_add_mem(server, info, sizeof(*info));
-       ncp_add_handle_path(server, volnum, dirent, 1, path);
-
-       result = ncp_request(server, 87);
-       ncp_unlock_server(server);
-       return result;
-}
-
-int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
-                                      struct inode *dir,
-                                      __le32 info_mask,
-                                      const struct nw_modify_dos_info *info)
-{
-       return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL,
-               info_mask, info);
-}
-
-#ifdef CONFIG_NCPFS_NFS_NS
-int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
-                              __u32 mode, __u32 rdev)
-
-{
-       int result = 0;
-
-       ncp_init_request(server);
-       if (server->name_space[volnum] == NW_NS_NFS) {
-               ncp_add_byte(server, 25);       /* subfunction */
-               ncp_add_byte(server, server->name_space[volnum]);
-               ncp_add_byte(server, NW_NS_NFS);
-               ncp_add_byte(server, volnum);
-               ncp_add_dword(server, dirent);
-               /* we must always operate on both nlinks and rdev, otherwise
-                  rdev is not set */
-               ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV);
-               ncp_add_dword_lh(server, mode);
-               ncp_add_dword_lh(server, 1);    /* nlinks */
-               ncp_add_dword_lh(server, rdev);
-               result = ncp_request(server, 87);
-       }
-       ncp_unlock_server(server);
-       return result;
-}
-#endif
-
-
-static int
-ncp_DeleteNSEntry(struct ncp_server *server,
-                 __u8 have_dir_base, __u8 volnum, __le32 dirent,
-                 const char* name, __u8 ns, __le16 attr)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 8);        /* subfunction */
-       ncp_add_byte(server, ns);
-       ncp_add_byte(server, 0);        /* reserved */
-       ncp_add_word(server, attr);     /* search attribs: all */
-       ncp_add_handle_path(server, volnum, dirent, have_dir_base, name);
-
-       result = ncp_request(server, 87);
-       ncp_unlock_server(server);
-       return result;
-}
-
-int
-ncp_del_file_or_subdir2(struct ncp_server *server,
-                       struct dentry *dentry)
-{
-       struct inode *inode = d_inode(dentry);
-       __u8  volnum;
-       __le32 dirent;
-
-       if (!inode) {
-               return 0xFF;    /* Any error */
-       }
-       volnum = NCP_FINFO(inode)->volNumber;
-       dirent = NCP_FINFO(inode)->DosDirNum;
-       return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
-}
-
-int
-ncp_del_file_or_subdir(struct ncp_server *server,
-                      struct inode *dir, const char *name)
-{
-       __u8  volnum = NCP_FINFO(dir)->volNumber;
-       __le32 dirent = NCP_FINFO(dir)->dirEntNum;
-       int name_space;
-
-       name_space = server->name_space[volnum];
-#ifdef CONFIG_NCPFS_NFS_NS
-       if (name_space == NW_NS_NFS)
-       {
-               int result;
-               result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent);
-               if (result) return result;
-               name = NULL;
-               name_space = NW_NS_DOS;
-       }
-#endif /* CONFIG_NCPFS_NFS_NS */
-       return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006));
-}
-
-static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
-{
-       __le16 *dest = (__le16 *) ret;
-       dest[1] = cpu_to_le16(v0);
-       dest[2] = cpu_to_le16(v1);
-       dest[0] = cpu_to_le16(v0 + 1);
-       return;
-}
-
-/* If both dir and name are NULL, then in target there's already a
-   looked-up entry that wants to be opened. */
-int ncp_open_create_file_or_subdir(struct ncp_server *server,
-                                  struct inode *dir, const char *name,
-                                  int open_create_mode,
-                                  __le32 create_attributes,
-                                  __le16 desired_acc_rights,
-                                  struct ncp_entry_info *target)
-{
-       __le16 search_attribs = cpu_to_le16(0x0006);
-       __u8  volnum;
-       __le32 dirent;
-       int result;
-
-       volnum = NCP_FINFO(dir)->volNumber;
-       dirent = NCP_FINFO(dir)->dirEntNum;
-
-       if ((create_attributes & aDIR) != 0) {
-               search_attribs |= cpu_to_le16(0x8000);
-       }
-       ncp_init_request(server);
-       ncp_add_byte(server, 1);        /* subfunction */
-       ncp_add_byte(server, server->name_space[volnum]);
-       ncp_add_byte(server, open_create_mode);
-       ncp_add_word(server, search_attribs);
-       ncp_add_dword(server, RIM_ALL);
-       ncp_add_dword(server, create_attributes);
-       /* The desired acc rights seem to be the inherited rights mask
-          for directories */
-       ncp_add_word(server, desired_acc_rights);
-       ncp_add_handle_path(server, volnum, dirent, 1, name);
-
-       if ((result = ncp_request(server, 87)) != 0)
-               goto out;
-       if (!(create_attributes & aDIR))
-               target->opened = 1;
-
-       /* in target there's a new finfo to fill */
-       ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
-       target->volume = target->i.volNumber;
-       ConvertToNWfromDWORD(ncp_reply_le16(server, 0),
-                            ncp_reply_le16(server, 2),
-                            target->file_handle);
-       
-       ncp_unlock_server(server);
-
-       (void)ncp_obtain_nfs_info(server, &(target->i));
-       return 0;
-
-out:
-       ncp_unlock_server(server);
-       return result;
-}
-
-int
-ncp_initialize_search(struct ncp_server *server, struct inode *dir,
-                       struct nw_search_sequence *target)
-{
-       __u8  volnum = NCP_FINFO(dir)->volNumber;
-       __le32 dirent = NCP_FINFO(dir)->dirEntNum;
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 2);        /* subfunction */
-       ncp_add_byte(server, server->name_space[volnum]);
-       ncp_add_byte(server, 0);        /* reserved */
-       ncp_add_handle_path(server, volnum, dirent, 1, NULL);
-
-       result = ncp_request(server, 87);
-       if (result)
-               goto out;
-       memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
-
-out:
-       ncp_unlock_server(server);
-       return result;
-}
-
-int ncp_search_for_fileset(struct ncp_server *server,
-                          struct nw_search_sequence *seq,
-                          int* more,
-                          int* cnt,
-                          char* buffer,
-                          size_t bufsize,
-                          char** rbuf,
-                          size_t* rsize)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 20);
-       ncp_add_byte(server, server->name_space[seq->volNumber]);
-       ncp_add_byte(server, 0);                /* datastream */
-       ncp_add_word(server, cpu_to_le16(0x8006));
-       ncp_add_dword(server, RIM_ALL);
-       ncp_add_word(server, cpu_to_le16(32767));       /* max returned items */
-       ncp_add_mem(server, seq, 9);
-#ifdef CONFIG_NCPFS_NFS_NS
-       if (server->name_space[seq->volNumber] == NW_NS_NFS) {
-               ncp_add_byte(server, 0);        /* 0 byte pattern */
-       } else 
-#endif
-       {
-               ncp_add_byte(server, 2);        /* 2 byte pattern */
-               ncp_add_byte(server, 0xff);     /* following is a wildcard */
-               ncp_add_byte(server, '*');
-       }
-       result = ncp_request2(server, 87, buffer, bufsize);
-       if (result) {
-               ncp_unlock_server(server);
-               return result;
-       }
-       if (server->ncp_reply_size < 12) {
-               ncp_unlock_server(server);
-               return 0xFF;
-       }
-       *rsize = server->ncp_reply_size - 12;
-       ncp_unlock_server(server);
-       buffer = buffer + sizeof(struct ncp_reply_header);
-       *rbuf = buffer + 12;
-       *cnt = WVAL_LH(buffer + 10);
-       *more = BVAL(buffer + 9);
-       memcpy(seq, buffer, 9);
-       return 0;
-}
-
-static int
-ncp_RenameNSEntry(struct ncp_server *server,
-                 struct inode *old_dir, const char *old_name, __le16 old_type,
-                 struct inode *new_dir, const char *new_name)
-{
-       int result = -EINVAL;
-
-       if ((old_dir == NULL) || (old_name == NULL) ||
-           (new_dir == NULL) || (new_name == NULL))
-               goto out;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 4);        /* subfunction */
-       ncp_add_byte(server, server->name_space[NCP_FINFO(old_dir)->volNumber]);
-       ncp_add_byte(server, 1);        /* rename flag */
-       ncp_add_word(server, old_type); /* search attributes */
-
-       /* source Handle Path */
-       ncp_add_byte(server, NCP_FINFO(old_dir)->volNumber);
-       ncp_add_dword(server, NCP_FINFO(old_dir)->dirEntNum);
-       ncp_add_byte(server, 1);
-       ncp_add_byte(server, 1);        /* 1 source component */
-
-       /* dest Handle Path */
-       ncp_add_byte(server, NCP_FINFO(new_dir)->volNumber);
-       ncp_add_dword(server, NCP_FINFO(new_dir)->dirEntNum);
-       ncp_add_byte(server, 1);
-       ncp_add_byte(server, 1);        /* 1 destination component */
-
-       /* source path string */
-       ncp_add_pstring(server, old_name);
-       /* dest path string */
-       ncp_add_pstring(server, new_name);
-
-       result = ncp_request(server, 87);
-       ncp_unlock_server(server);
-out:
-       return result;
-}
-
-int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
-                               struct inode *old_dir, const char *old_name,
-                               struct inode *new_dir, const char *new_name)
-{
-        int result;
-        __le16 old_type = cpu_to_le16(0x06);
-
-/* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */
-       result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
-                                          new_dir, new_name);
-        if (result == 0xFF)    /* File Not Found, try directory */
-       {
-               old_type = cpu_to_le16(0x16);
-               result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
-                                                  new_dir, new_name);
-       }
-       if (result != 0x92) return result;      /* All except NO_FILES_RENAMED */
-       result = ncp_del_file_or_subdir(server, new_dir, new_name);
-       if (result != 0) return -EACCES;
-       result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
-                                          new_dir, new_name);
-       return result;
-}
-       
-
-/* We have to transfer to/from user space */
-int
-ncp_read_kernel(struct ncp_server *server, const char *file_id,
-            __u32 offset, __u16 to_read, char *target, int *bytes_read)
-{
-       const char *source;
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 0);
-       ncp_add_mem(server, file_id, 6);
-       ncp_add_be32(server, offset);
-       ncp_add_be16(server, to_read);
-
-       if ((result = ncp_request(server, 72)) != 0) {
-               goto out;
-       }
-       *bytes_read = ncp_reply_be16(server, 0);
-       source = ncp_reply_data(server, 2 + (offset & 1));
-
-       memcpy(target, source, *bytes_read);
-out:
-       ncp_unlock_server(server);
-       return result;
-}
-
-/* There is a problem... egrep and some other silly tools do:
-       x = mmap(NULL, MAP_PRIVATE, PROT_READ|PROT_WRITE, <ncpfs fd>, 32768);
-       read(<ncpfs fd>, x, 32768);
-   Now copying read result by copy_to_user causes pagefault. This pagefault
-   could not be handled because of server was locked due to read. So we have
-   to use temporary buffer. So ncp_unlock_server must be done before
-   copy_to_user (and for write, copy_from_user must be done before 
-   ncp_init_request... same applies for send raw packet ioctl). Because of
-   file is normally read in bigger chunks, caller provides kmalloced 
-   (vmalloced) chunk of memory with size >= to_read...
- */
-int
-ncp_read_bounce(struct ncp_server *server, const char *file_id,
-        __u32 offset, __u16 to_read, struct iov_iter *to,
-        int *bytes_read, void *bounce, __u32 bufsize)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 0);
-       ncp_add_mem(server, file_id, 6);
-       ncp_add_be32(server, offset);
-       ncp_add_be16(server, to_read);
-       result = ncp_request2(server, 72, bounce, bufsize);
-       ncp_unlock_server(server);
-       if (!result) {
-               int len = get_unaligned_be16((char *)bounce +
-                         sizeof(struct ncp_reply_header));
-               result = -EIO;
-               if (len <= to_read) {
-                       char* source;
-
-                       source = (char*)bounce + 
-                                sizeof(struct ncp_reply_header) + 2 + 
-                                (offset & 1);
-                       *bytes_read = len;
-                       result = 0;
-                       if (copy_to_iter(source, len, to) != len)
-                               result = -EFAULT;
-               }
-       }
-       return result;
-}
-
-int
-ncp_write_kernel(struct ncp_server *server, const char *file_id,
-                __u32 offset, __u16 to_write,
-                const char *source, int *bytes_written)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 0);
-       ncp_add_mem(server, file_id, 6);
-       ncp_add_be32(server, offset);
-       ncp_add_be16(server, to_write);
-       ncp_add_mem(server, source, to_write);
-       
-       if ((result = ncp_request(server, 73)) == 0)
-               *bytes_written = to_write;
-       ncp_unlock_server(server);
-       return result;
-}
-
-#ifdef CONFIG_NCPFS_IOCTL_LOCKING
-int
-ncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id,
-         __u8 locktype, __u32 offset, __u32 length, __u16 timeout)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, locktype);
-       ncp_add_mem(server, file_id, 6);
-       ncp_add_be32(server, offset);
-       ncp_add_be32(server, length);
-       ncp_add_be16(server, timeout);
-
-       if ((result = ncp_request(server, 0x1A)) != 0)
-       {
-               ncp_unlock_server(server);
-               return result;
-       }
-       ncp_unlock_server(server);
-       return 0;
-}
-
-int
-ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id,
-         __u32 offset, __u32 length)
-{
-       int result;
-
-       ncp_init_request(server);
-       ncp_add_byte(server, 0);        /* who knows... lanalyzer says that */
-       ncp_add_mem(server, file_id, 6);
-       ncp_add_be32(server, offset);
-       ncp_add_be32(server, length);
-
-       if ((result = ncp_request(server, 0x1E)) != 0)
-       {
-               ncp_unlock_server(server);
-               return result;
-       }
-       ncp_unlock_server(server);
-       return 0;
-}
-#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
-
-#ifdef CONFIG_NCPFS_NLS
-/* This are the NLS conversion routines with inspirations and code parts
- * from the vfat file system and hints from Petr Vandrovec.
- */
-
-int
-ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen,
-               const unsigned char *iname, unsigned int ilen, int cc)
-{
-       struct nls_table *in = server->nls_io;
-       struct nls_table *out = server->nls_vol;
-       unsigned char *vname_start;
-       unsigned char *vname_end;
-       const unsigned char *iname_end;
-
-       iname_end = iname + ilen;
-       vname_start = vname;
-       vname_end = vname + *vlen - 1;
-
-       while (iname < iname_end) {
-               int chl;
-               wchar_t ec;
-
-               if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
-                       int k;
-                       unicode_t u;
-
-                       k = utf8_to_utf32(iname, iname_end - iname, &u);
-                       if (k < 0 || u > MAX_WCHAR_T)
-                               return -EINVAL;
-                       iname += k;
-                       ec = u;
-               } else {
-                       if (*iname == NCP_ESC) {
-                               int k;
-
-                               if (iname_end - iname < 5)
-                                       goto nospec;
-
-                               ec = 0;
-                               for (k = 1; k < 5; k++) {
-                                       unsigned char nc;
-
-                                       nc = iname[k] - '0';
-                                       if (nc >= 10) {
-                                               nc -= 'A' - '0' - 10;
-                                               if ((nc < 10) || (nc > 15)) {
-                                                       goto nospec;
-                                               }
-                                       }
-                                       ec = (ec << 4) | nc;
-                               }
-                               iname += 5;
-                       } else {
-nospec:;                       
-                               if ( (chl = in->char2uni(iname, iname_end - iname, &ec)) < 0)
-                                       return chl;
-                               iname += chl;
-                       }
-               }
-
-               /* unitoupper should be here! */
-
-               chl = out->uni2char(ec, vname, vname_end - vname);
-               if (chl < 0)
-                       return chl;
-
-               /* this is wrong... */
-               if (cc) {
-                       int chi;
-
-                       for (chi = 0; chi < chl; chi++){
-                               vname[chi] = ncp_toupper(out, vname[chi]);
-                       }
-               }
-               vname += chl;
-       }
-
-       *vname = 0;
-       *vlen = vname - vname_start;
-       return 0;
-}
-
-int
-ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen,
-               const unsigned char *vname, unsigned int vlen, int cc)
-{
-       struct nls_table *in = server->nls_vol;
-       struct nls_table *out = server->nls_io;
-       const unsigned char *vname_end;
-       unsigned char *iname_start;
-       unsigned char *iname_end;
-       unsigned char *vname_cc;
-       int err;
-
-       vname_cc = NULL;
-
-       if (cc) {
-               int i;
-
-               /* this is wrong! */
-               vname_cc = kmalloc(vlen, GFP_KERNEL);
-               if (!vname_cc)
-                       return -ENOMEM;
-               for (i = 0; i < vlen; i++)
-                       vname_cc[i] = ncp_tolower(in, vname[i]);
-               vname = vname_cc;
-       }
-
-       iname_start = iname;
-       iname_end = iname + *ilen - 1;
-       vname_end = vname + vlen;
-
-       while (vname < vname_end) {
-               wchar_t ec;
-               int chl;
-
-               if ( (chl = in->char2uni(vname, vname_end - vname, &ec)) < 0) {
-                       err = chl;
-                       goto quit;
-               }
-               vname += chl;
-
-               /* unitolower should be here! */
-
-               if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
-                       int k;
-
-                       k = utf32_to_utf8(ec, iname, iname_end - iname);
-                       if (k < 0) {
-                               err = -ENAMETOOLONG;
-                               goto quit;
-                       }
-                       iname += k;
-               } else {
-                       if ( (chl = out->uni2char(ec, iname, iname_end - iname)) >= 0) {
-                               iname += chl;
-                       } else {
-                               int k;
-
-                               if (iname_end - iname < 5) {
-                                       err = -ENAMETOOLONG;
-                                       goto quit;
-                               }
-                               *iname = NCP_ESC;
-                               for (k = 4; k > 0; k--) {
-                                       unsigned char v;
-                                       
-                                       v = (ec & 0xF) + '0';
-                                       if (v > '9') {
-                                               v += 'A' - '9' - 1;
-                                       }
-                                       iname[k] = v;
-                                       ec >>= 4;
-                               }
-                               iname += 5;
-                       }
-               }
-       }
-
-       *iname = 0;
-       *ilen = iname - iname_start;
-       err = 0;
-quit:;
-       if (cc)
-               kfree(vname_cc);
-       return err;
-}
-
-#else
-
-int
-ncp__io2vol(unsigned char *vname, unsigned int *vlen,
-               const unsigned char *iname, unsigned int ilen, int cc)
-{
-       int i;
-
-       if (*vlen <= ilen)
-               return -ENAMETOOLONG;
-
-       if (cc)
-               for (i = 0; i < ilen; i++) {
-                       *vname = toupper(*iname);
-                       vname++;
-                       iname++;
-               }
-       else {
-               memmove(vname, iname, ilen);
-               vname += ilen;
-       }
-
-       *vlen = ilen;
-       *vname = 0;
-       return 0;
-}
-
-int
-ncp__vol2io(unsigned char *iname, unsigned int *ilen,
-               const unsigned char *vname, unsigned int vlen, int cc)
-{
-       int i;
-
-       if (*ilen <= vlen)
-               return -ENAMETOOLONG;
-
-       if (cc)
-               for (i = 0; i < vlen; i++) {
-                       *iname = tolower(*vname);
-                       iname++;
-                       vname++;
-               }
-       else {
-               memmove(iname, vname, vlen);
-               iname += vlen;
-       }
-
-       *ilen = vlen;
-       *iname = 0;
-       return 0;
-}
-
-#endif
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
deleted file mode 100644 (file)
index aaae8aa..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *  ncplib_kernel.h
- *
- *  Copyright (C) 1995, 1996 by Volker Lendecke
- *  Modified for big endian by J.F. Chadima and David S. Miller
- *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- *  Modified 1998, 1999 Wolfram Pienkoss for NLS
- *  Modified 1999 Wolfram Pienkoss for directory caching
- *
- */
-
-#ifndef _NCPLIB_H
-#define _NCPLIB_H
-
-
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/pagemap.h>
-
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <asm/unaligned.h>
-#include <asm/string.h>
-
-#ifdef CONFIG_NCPFS_NLS
-#include <linux/nls.h>
-#else
-#include <linux/ctype.h>
-#endif /* CONFIG_NCPFS_NLS */
-
-#define NCP_MIN_SYMLINK_SIZE   8
-#define NCP_MAX_SYMLINK_SIZE   512
-
-#define NCP_BLOCK_SHIFT                9
-#define NCP_BLOCK_SIZE         (1 << (NCP_BLOCK_SHIFT))
-
-int ncp_negotiate_buffersize(struct ncp_server *, int, int *);
-int ncp_negotiate_size_and_options(struct ncp_server *server, int size,
-                         int options, int *ret_size, int *ret_options);
-
-int ncp_get_volume_info_with_number(struct ncp_server* server, int n,
-                                   struct ncp_volume_info *target);
-
-int ncp_get_directory_info(struct ncp_server* server, __u8 dirhandle,
-                          struct ncp_volume_info* target);
-
-int ncp_close_file(struct ncp_server *, const char *);
-static inline int ncp_read_bounce_size(__u32 size) {
-       return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8;
-};
-int ncp_read_bounce(struct ncp_server *, const char *, __u32, __u16, 
-               struct iov_iter *, int *, void *bounce, __u32 bouncelen);
-int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, 
-               char *, int *);
-int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16,
-               const char *, int *);
-
-static inline void ncp_inode_close(struct inode *inode) {
-       atomic_dec(&NCP_FINFO(inode)->opened);
-}
-
-void ncp_extract_file_info(const void* src, struct nw_info_struct* target);
-int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *,
-               struct nw_info_struct *target);
-int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
-int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns);
-int ncp_get_volume_root(struct ncp_server *server, const char *volname,
-                       __u32 *volume, __le32 *dirent, __le32 *dosdirent);
-int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *);
-int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *,
-        __le32, const struct nw_modify_dos_info *info);
-int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *,
-        const char* path, __le32, const struct nw_modify_dos_info *info);
-int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent,
-                       __u32 mode, __u32 rdev);
-
-int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
-int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *);
-int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *,
-                               int, __le32, __le16, struct ncp_entry_info *);
-
-int ncp_initialize_search(struct ncp_server *, struct inode *,
-                     struct nw_search_sequence *target);
-int ncp_search_for_fileset(struct ncp_server *server,
-                          struct nw_search_sequence *seq,
-                          int* more, int* cnt,
-                          char* buffer, size_t bufsize,
-                          char** rbuf, size_t* rsize);
-
-int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
-                             struct inode *, const char *, struct inode *, const char *);
-
-
-int
-ncp_LogPhysicalRecord(struct ncp_server *server,
-                     const char *file_id, __u8 locktype,
-                     __u32 offset, __u32 length, __u16 timeout);
-
-#ifdef CONFIG_NCPFS_IOCTL_LOCKING
-int
-ncp_ClearPhysicalRecord(struct ncp_server *server,
-                       const char *file_id,
-                       __u32 offset, __u32 length);
-#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
-
-int
-ncp_mount_subdir(struct ncp_server *, __u8, __u8, __le32,
-                __u32* volume, __le32* dirent, __le32* dosdirent);
-int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __le32 dirent, __u8 *dirhandle);
-int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle);
-
-int ncp_create_new(struct inode *dir, struct dentry *dentry,
-                          umode_t mode, dev_t rdev, __le32 attributes);
-
-static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int volnum) {
-#ifdef CONFIG_NCPFS_NFS_NS
-       return (server->m.flags & NCP_MOUNT_NFS_EXTRAS) &&
-              (server->name_space[volnum] == NW_NS_NFS);
-#else
-       return 0;
-#endif
-}
-
-#ifdef CONFIG_NCPFS_NLS
-
-int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *,
-                               const unsigned char *, unsigned int, int);
-int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *,
-                               const unsigned char *, unsigned int, int);
-
-#define NCP_ESC                        ':'
-#define NCP_IO_TABLE(sb)       (NCP_SBP(sb)->nls_io)
-#define ncp_tolower(t, c)      nls_tolower(t, c)
-#define ncp_toupper(t, c)      nls_toupper(t, c)
-#define ncp_strnicmp(t, s1, s2, len) \
-       nls_strnicmp(t, s1, s2, len)
-#define ncp_io2vol(S,m,i,n,k,U)        ncp__io2vol(S,m,i,n,k,U)
-#define ncp_vol2io(S,m,i,n,k,U)        ncp__vol2io(S,m,i,n,k,U)
-
-#else
-
-int ncp__io2vol(unsigned char *, unsigned int *,
-                               const unsigned char *, unsigned int, int);
-int ncp__vol2io(unsigned char *, unsigned int *,
-                               const unsigned char *, unsigned int, int);
-
-#define NCP_IO_TABLE(sb)       NULL
-#define ncp_tolower(t, c)      tolower(c)
-#define ncp_toupper(t, c)      toupper(c)
-#define ncp_io2vol(S,m,i,n,k,U)        ncp__io2vol(m,i,n,k,U)
-#define ncp_vol2io(S,m,i,n,k,U)        ncp__vol2io(m,i,n,k,U)
-
-
-static inline int ncp_strnicmp(const struct nls_table *t,
-               const unsigned char *s1, const unsigned char *s2, int len)
-{
-       while (len--) {
-               if (tolower(*s1++) != tolower(*s2++))
-                       return 1;
-       }
-
-       return 0;
-}
-
-#endif /* CONFIG_NCPFS_NLS */
-
-#define NCP_GET_AGE(dentry)    (jiffies - (dentry)->d_time)
-#define NCP_MAX_AGE(server)    atomic_read(&(server)->dentry_ttl)
-#define NCP_TEST_AGE(server,dentry)    (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server))
-
-static inline void
-ncp_age_dentry(struct ncp_server* server, struct dentry* dentry)
-{
-       dentry->d_time = jiffies - NCP_MAX_AGE(server);
-}
-
-static inline void
-ncp_new_dentry(struct dentry* dentry)
-{
-       dentry->d_time = jiffies;
-}
-
-struct ncp_cache_head {
-       time_t          mtime;
-       unsigned long   time;   /* cache age */
-       unsigned long   end;    /* last valid fpos in cache */
-       int             eof;
-};
-
-#define NCP_DIRCACHE_SIZE      ((int)(PAGE_SIZE/sizeof(struct dentry *)))
-union ncp_dir_cache {
-       struct ncp_cache_head   head;
-       struct dentry           *dentry[NCP_DIRCACHE_SIZE];
-};
-
-#define NCP_FIRSTCACHE_SIZE    ((int)((NCP_DIRCACHE_SIZE * \
-       sizeof(struct dentry *) - sizeof(struct ncp_cache_head)) / \
-       sizeof(struct dentry *)))
-
-#define NCP_DIRCACHE_START     (NCP_DIRCACHE_SIZE - NCP_FIRSTCACHE_SIZE)
-
-struct ncp_cache_control {
-       struct  ncp_cache_head          head;
-       struct  page                    *page;
-       union   ncp_dir_cache           *cache;
-       unsigned long                   fpos, ofs;
-       int                             filled, valid, idx;
-};
-
-#endif /* _NCPLIB_H */
diff --git a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c
deleted file mode 100644 (file)
index 8085b1a..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  ncpsign_kernel.c
- *
- *  Arne de Bruijn (arne@knoware.nl), 1997
- *
- */
-
-
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
-
-#include <linux/string.h>
-#include <linux/ncp.h>
-#include <linux/bitops.h>
-#include "ncp_fs.h"
-#include "ncpsign_kernel.h"
-
-/* i386: 32-bit, little endian, handles mis-alignment */
-#ifdef __i386__
-#define GET_LE32(p) (*(const int *)(p))
-#define PUT_LE32(p,v) { *(int *)(p)=v; }
-#else
-/* from include/ncplib.h */
-#define BVAL(buf,pos) (((const __u8 *)(buf))[pos])
-#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
-#define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val))
-
-static inline __u16
-WVAL_LH(const __u8 * buf, int pos)
-{
-       return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8;
-}
-static inline __u32
-DVAL_LH(const __u8 * buf, int pos)
-{
-       return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16;
-}
-static inline void
-WSET_LH(__u8 * buf, int pos, __u16 val)
-{
-       BSET(buf, pos, val & 0xff);
-       BSET(buf, pos + 1, val >> 8);
-}
-static inline void
-DSET_LH(__u8 * buf, int pos, __u32 val)
-{
-       WSET_LH(buf, pos, val & 0xffff);
-       WSET_LH(buf, pos + 2, val >> 16);
-}
-
-#define GET_LE32(p) DVAL_LH(p,0)
-#define PUT_LE32(p,v) DSET_LH(p,0,v)
-#endif
-
-static void nwsign(char *r_data1, char *r_data2, char *outdata) {
- int i;
- unsigned int w0,w1,w2,w3;
- static int rbit[4]={0, 2, 1, 3};
-#ifdef __i386__
- unsigned int *data2=(unsigned int *)r_data2;
-#else
- unsigned int data2[16];
- for (i=0;i<16;i++)
-  data2[i]=GET_LE32(r_data2+(i<<2));
-#endif 
- w0=GET_LE32(r_data1);
- w1=GET_LE32(r_data1+4);
- w2=GET_LE32(r_data1+8);
- w3=GET_LE32(r_data1+12);
- for (i=0;i<16;i+=4) {
-  w0=rol32(w0 + ((w1 & w2) | ((~w1) & w3)) + data2[i+0],3);
-  w3=rol32(w3 + ((w0 & w1) | ((~w0) & w2)) + data2[i+1],7);
-  w2=rol32(w2 + ((w3 & w0) | ((~w3) & w1)) + data2[i+2],11);
-  w1=rol32(w1 + ((w2 & w3) | ((~w2) & w0)) + data2[i+3],19);
- }
- for (i=0;i<4;i++) {
-  w0=rol32(w0 + (((w2 | w3) & w1) | (w2 & w3)) + 0x5a827999 + data2[i+0],3);
-  w3=rol32(w3 + (((w1 | w2) & w0) | (w1 & w2)) + 0x5a827999 + data2[i+4],5);
-  w2=rol32(w2 + (((w0 | w1) & w3) | (w0 & w1)) + 0x5a827999 + data2[i+8],9);
-  w1=rol32(w1 + (((w3 | w0) & w2) | (w3 & w0)) + 0x5a827999 + data2[i+12],13);
- }
- for (i=0;i<4;i++) {
-  w0=rol32(w0 + ((w1 ^ w2) ^ w3) + 0x6ed9eba1 + data2[rbit[i]+0],3);
-  w3=rol32(w3 + ((w0 ^ w1) ^ w2) + 0x6ed9eba1 + data2[rbit[i]+8],9);
-  w2=rol32(w2 + ((w3 ^ w0) ^ w1) + 0x6ed9eba1 + data2[rbit[i]+4],11);
-  w1=rol32(w1 + ((w2 ^ w3) ^ w0) + 0x6ed9eba1 + data2[rbit[i]+12],15);
- }
- PUT_LE32(outdata,(w0+GET_LE32(r_data1)) & 0xffffffff);
- PUT_LE32(outdata+4,(w1+GET_LE32(r_data1+4)) & 0xffffffff);
- PUT_LE32(outdata+8,(w2+GET_LE32(r_data1+8)) & 0xffffffff);
- PUT_LE32(outdata+12,(w3+GET_LE32(r_data1+12)) & 0xffffffff);
-}
-
-/* Make a signature for the current packet and add it at the end of the */
-/* packet. */
-void __sign_packet(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, void *sign_buff) {
-       unsigned char data[64];
-
-       memcpy(data, server->sign_root, 8);
-       *(__u32*)(data + 8) = totalsize;
-       if (size < 52) {
-               memcpy(data + 12, packet, size);
-               memset(data + 12 + size, 0, 52 - size);
-       } else {
-               memcpy(data + 12, packet, 52);
-       }
-       nwsign(server->sign_last, data, server->sign_last);
-       memcpy(sign_buff, server->sign_last, 8);
-}
-
-int sign_verify_reply(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, const void *sign_buff) {
-       unsigned char data[64];
-       unsigned char hash[16];
-
-       memcpy(data, server->sign_root, 8);
-       *(__u32*)(data + 8) = totalsize;
-       if (size < 52) {
-               memcpy(data + 12, packet, size);
-               memset(data + 12 + size, 0, 52 - size);
-       } else {
-               memcpy(data + 12, packet, 52);
-       }
-       nwsign(server->sign_last, data, hash);
-       return memcmp(sign_buff, hash, 8);
-}
-
-#endif /* CONFIG_NCPFS_PACKET_SIGNING */
-
diff --git a/fs/ncpfs/ncpsign_kernel.h b/fs/ncpfs/ncpsign_kernel.h
deleted file mode 100644 (file)
index 57ff0a0..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *  ncpsign_kernel.h
- *
- *  Arne de Bruijn (arne@knoware.nl), 1997
- *
- */
-#ifndef _NCPSIGN_KERNEL_H
-#define _NCPSIGN_KERNEL_H
-
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
-void __sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff);
-int sign_verify_reply(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, const void *sign_buff);
-#endif
-
-static inline size_t sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff) {
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
-       if (server->sign_active) {
-               __sign_packet(server, data, size, totalsize, sign_buff);
-               return 8;
-       }
-#endif
-       return 0;
-}
-
-#endif
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
deleted file mode 100644 (file)
index 4c13174..0000000
+++ /dev/null
@@ -1,855 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  linux/fs/ncpfs/sock.c
- *
- *  Copyright (C) 1992, 1993  Rick Sladkey
- *
- *  Modified 1995, 1996 by Volker Lendecke to be usable for ncp
- *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/socket.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/sched/signal.h>
-#include <linux/uaccess.h>
-#include <linux/in.h>
-#include <linux/net.h>
-#include <linux/mm.h>
-#include <linux/netdevice.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <net/scm.h>
-#include <net/sock.h>
-#include <linux/ipx.h>
-#include <linux/poll.h>
-#include <linux/file.h>
-
-#include "ncp_fs.h"
-
-#include "ncpsign_kernel.h"
-
-static int _recv(struct socket *sock, void *buf, int size, unsigned flags)
-{
-       struct msghdr msg = {NULL, };
-       struct kvec iov = {buf, size};
-       iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, size);
-       return sock_recvmsg(sock, &msg, flags);
-}
-
-static int _send(struct socket *sock, const void *buff, int len)
-{
-       struct msghdr msg = { .msg_flags = 0 };
-       struct kvec vec = {.iov_base = (void *)buff, .iov_len = len};
-       iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &vec, 1, len);
-       return sock_sendmsg(sock, &msg);
-}
-
-struct ncp_request_reply {
-       struct list_head req;
-       wait_queue_head_t wq;
-       atomic_t refs;
-       unsigned char* reply_buf;
-       size_t datalen;
-       int result;
-       enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status;
-       struct iov_iter from;
-       struct kvec tx_iov[3];
-       u_int16_t tx_type;
-       u_int32_t sign[6];
-};
-
-static inline struct ncp_request_reply* ncp_alloc_req(void)
-{
-       struct ncp_request_reply *req;
-
-       req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL);
-       if (!req)
-               return NULL;
-
-       init_waitqueue_head(&req->wq);
-       atomic_set(&req->refs, (1));
-       req->status = RQ_IDLE;
-
-       return req;
-}
-
-static void ncp_req_get(struct ncp_request_reply *req)
-{
-       atomic_inc(&req->refs);
-}
-
-static void ncp_req_put(struct ncp_request_reply *req)
-{
-       if (atomic_dec_and_test(&req->refs))
-               kfree(req);
-}
-
-void ncp_tcp_data_ready(struct sock *sk)
-{
-       struct ncp_server *server = sk->sk_user_data;
-
-       server->data_ready(sk);
-       schedule_work(&server->rcv.tq);
-}
-
-void ncp_tcp_error_report(struct sock *sk)
-{
-       struct ncp_server *server = sk->sk_user_data;
-       
-       server->error_report(sk);
-       schedule_work(&server->rcv.tq);
-}
-
-void ncp_tcp_write_space(struct sock *sk)
-{
-       struct ncp_server *server = sk->sk_user_data;
-       
-       /* We do not need any locking: we first set tx.creq, and then we do sendmsg,
-          not vice versa... */
-       server->write_space(sk);
-       if (server->tx.creq)
-               schedule_work(&server->tx.tq);
-}
-
-void ncpdgram_timeout_call(struct timer_list *t)
-{
-       struct ncp_server *server = from_timer(server, t, timeout_tm);
-
-       schedule_work(&server->timeout_tq);
-}
-
-static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result)
-{
-       req->result = result;
-       if (req->status != RQ_ABANDONED)
-               memcpy(req->reply_buf, server->rxbuf, req->datalen);
-       req->status = RQ_DONE;
-       wake_up_all(&req->wq);
-       ncp_req_put(req);
-}
-
-static void __abort_ncp_connection(struct ncp_server *server)
-{
-       struct ncp_request_reply *req;
-
-       ncp_invalidate_conn(server);
-       del_timer(&server->timeout_tm);
-       while (!list_empty(&server->tx.requests)) {
-               req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
-               
-               list_del_init(&req->req);
-               ncp_finish_request(server, req, -EIO);
-       }
-       req = server->rcv.creq;
-       if (req) {
-               server->rcv.creq = NULL;
-               ncp_finish_request(server, req, -EIO);
-               server->rcv.ptr = NULL;
-               server->rcv.state = 0;
-       }
-       req = server->tx.creq;
-       if (req) {
-               server->tx.creq = NULL;
-               ncp_finish_request(server, req, -EIO);
-       }
-}
-
-static inline int get_conn_number(struct ncp_reply_header *rp)
-{
-       return rp->conn_low | (rp->conn_high << 8);
-}
-
-static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
-{
-       /* If req is done, we got signal, but we also received answer... */
-       switch (req->status) {
-               case RQ_IDLE:
-               case RQ_DONE:
-                       break;
-               case RQ_QUEUED:
-                       list_del_init(&req->req);
-                       ncp_finish_request(server, req, err);
-                       break;
-               case RQ_INPROGRESS:
-                       req->status = RQ_ABANDONED;
-                       break;
-               case RQ_ABANDONED:
-                       break;
-       }
-}
-
-static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
-{
-       mutex_lock(&server->rcv.creq_mutex);
-       __ncp_abort_request(server, req, err);
-       mutex_unlock(&server->rcv.creq_mutex);
-}
-
-static inline void __ncptcp_abort(struct ncp_server *server)
-{
-       __abort_ncp_connection(server);
-}
-
-static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req)
-{
-       struct msghdr msg = { .msg_iter = req->from, .msg_flags = MSG_DONTWAIT };
-       return sock_sendmsg(sock, &msg);
-}
-
-static void __ncptcp_try_send(struct ncp_server *server)
-{
-       struct ncp_request_reply *rq;
-       struct msghdr msg = { .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT };
-       int result;
-
-       rq = server->tx.creq;
-       if (!rq)
-               return;
-
-       msg.msg_iter = rq->from;
-       result = sock_sendmsg(server->ncp_sock, &msg);
-
-       if (result == -EAGAIN)
-               return;
-
-       if (result < 0) {
-               pr_err("tcp: Send failed: %d\n", result);
-               __ncp_abort_request(server, rq, result);
-               return;
-       }
-       if (!msg_data_left(&msg)) {
-               server->rcv.creq = rq;
-               server->tx.creq = NULL;
-               return;
-       }
-       rq->from = msg.msg_iter;
-}
-
-static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h)
-{
-       req->status = RQ_INPROGRESS;
-       h->conn_low = server->connection;
-       h->conn_high = server->connection >> 8;
-       h->sequence = ++server->sequence;
-}
-       
-static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req)
-{
-       size_t signlen, len = req->tx_iov[1].iov_len;
-       struct ncp_request_header *h = req->tx_iov[1].iov_base;
-       
-       ncp_init_header(server, req, h);
-       signlen = sign_packet(server,
-                       req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, 
-                       len - sizeof(struct ncp_request_header) + 1,
-                       cpu_to_le32(len), req->sign);
-       if (signlen) {
-               /* NCP over UDP appends signature */
-               req->tx_iov[2].iov_base = req->sign;
-               req->tx_iov[2].iov_len = signlen;
-       }
-       iov_iter_kvec(&req->from, WRITE | ITER_KVEC,
-                       req->tx_iov + 1, signlen ? 2 : 1, len + signlen);
-       server->rcv.creq = req;
-       server->timeout_last = server->m.time_out;
-       server->timeout_retries = server->m.retry_count;
-       ncpdgram_send(server->ncp_sock, req);
-       mod_timer(&server->timeout_tm, jiffies + server->m.time_out);
-}
-
-#define NCP_TCP_XMIT_MAGIC     (0x446D6454)
-#define NCP_TCP_XMIT_VERSION   (1)
-#define NCP_TCP_RCVD_MAGIC     (0x744E6350)
-
-static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
-{
-       size_t signlen, len = req->tx_iov[1].iov_len;
-       struct ncp_request_header *h = req->tx_iov[1].iov_base;
-
-       ncp_init_header(server, req, h);
-       signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
-                       len - sizeof(struct ncp_request_header) + 1,
-                       cpu_to_be32(len + 24), req->sign + 4) + 16;
-
-       req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC);
-       req->sign[1] = htonl(len + signlen);
-       req->sign[2] = htonl(NCP_TCP_XMIT_VERSION);
-       req->sign[3] = htonl(req->datalen + 8);
-       /* NCP over TCP prepends signature */
-       req->tx_iov[0].iov_base = req->sign;
-       req->tx_iov[0].iov_len = signlen;
-       iov_iter_kvec(&req->from, WRITE | ITER_KVEC,
-                       req->tx_iov, 2, len + signlen);
-
-       server->tx.creq = req;
-       __ncptcp_try_send(server);
-}
-
-static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
-{
-       /* we copy the data so that we do not depend on the caller
-          staying alive */
-       memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len);
-       req->tx_iov[1].iov_base = server->txbuf;
-
-       if (server->ncp_sock->type == SOCK_STREAM)
-               ncptcp_start_request(server, req);
-       else
-               ncpdgram_start_request(server, req);
-}
-
-static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req)
-{
-       mutex_lock(&server->rcv.creq_mutex);
-       if (!ncp_conn_valid(server)) {
-               mutex_unlock(&server->rcv.creq_mutex);
-               pr_err("tcp: Server died\n");
-               return -EIO;
-       }
-       ncp_req_get(req);
-       if (server->tx.creq || server->rcv.creq) {
-               req->status = RQ_QUEUED;
-               list_add_tail(&req->req, &server->tx.requests);
-               mutex_unlock(&server->rcv.creq_mutex);
-               return 0;
-       }
-       __ncp_start_request(server, req);
-       mutex_unlock(&server->rcv.creq_mutex);
-       return 0;
-}
-
-static void __ncp_next_request(struct ncp_server *server)
-{
-       struct ncp_request_reply *req;
-
-       server->rcv.creq = NULL;
-       if (list_empty(&server->tx.requests)) {
-               return;
-       }
-       req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
-       list_del_init(&req->req);
-       __ncp_start_request(server, req);
-}
-
-static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len)
-{
-       if (server->info_sock) {
-               struct msghdr msg = { .msg_flags = MSG_NOSIGNAL };
-               __be32 hdr[2] = {cpu_to_be32(len + 8), cpu_to_be32(id)};
-               struct kvec iov[2] = {
-                       {.iov_base = hdr, .iov_len = 8},
-                       {.iov_base = (void *)data, .iov_len = len},
-               };
-
-               iov_iter_kvec(&msg.msg_iter, ITER_KVEC | WRITE,
-                               iov, 2, len + 8);
-
-               sock_sendmsg(server->info_sock, &msg);
-       }
-}
-
-void ncpdgram_rcv_proc(struct work_struct *work)
-{
-       struct ncp_server *server =
-               container_of(work, struct ncp_server, rcv.tq);
-       struct socket* sock;
-       
-       sock = server->ncp_sock;
-       
-       while (1) {
-               struct ncp_reply_header reply;
-               int result;
-
-               result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT);
-               if (result < 0) {
-                       break;
-               }
-               if (result >= sizeof(reply)) {
-                       struct ncp_request_reply *req;
-       
-                       if (reply.type == NCP_WATCHDOG) {
-                               unsigned char buf[10];
-
-                               if (server->connection != get_conn_number(&reply)) {
-                                       goto drop;
-                               }
-                               result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
-                               if (result < 0) {
-                                       ncp_dbg(1, "recv failed with %d\n", result);
-                                       continue;
-                               }
-                               if (result < 10) {
-                                       ncp_dbg(1, "too short (%u) watchdog packet\n", result);
-                                       continue;
-                               }
-                               if (buf[9] != '?') {
-                                       ncp_dbg(1, "bad signature (%02X) in watchdog packet\n", buf[9]);
-                                       continue;
-                               }
-                               buf[9] = 'Y';
-                               _send(sock, buf, sizeof(buf));
-                               continue;
-                       }
-                       if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
-                               result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
-                               if (result < 0) {
-                                       continue;
-                               }
-                               info_server(server, 0, server->unexpected_packet.data, result);
-                               continue;
-                       }
-                       mutex_lock(&server->rcv.creq_mutex);
-                       req = server->rcv.creq;
-                       if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && 
-                                       server->connection == get_conn_number(&reply)))) {
-                               if (reply.type == NCP_POSITIVE_ACK) {
-                                       server->timeout_retries = server->m.retry_count;
-                                       server->timeout_last = NCP_MAX_RPC_TIMEOUT;
-                                       mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
-                               } else if (reply.type == NCP_REPLY) {
-                                       result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT);
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
-                                       if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
-                                               if (result < 8 + 8) {
-                                                       result = -EIO;
-                                               } else {
-                                                       unsigned int hdrl;
-                                                       
-                                                       result -= 8;
-                                                       hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
-                                                       if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) {
-                                                               pr_info("Signature violation\n");
-                                                               result = -EIO;
-                                                       }
-                                               }
-                                       }
-#endif
-                                       del_timer(&server->timeout_tm);
-                                       server->rcv.creq = NULL;
-                                       ncp_finish_request(server, req, result);
-                                       __ncp_next_request(server);
-                                       mutex_unlock(&server->rcv.creq_mutex);
-                                       continue;
-                               }
-                       }
-                       mutex_unlock(&server->rcv.creq_mutex);
-               }
-drop:;         
-               _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT);
-       }
-}
-
-static void __ncpdgram_timeout_proc(struct ncp_server *server)
-{
-       /* If timer is pending, we are processing another request... */
-       if (!timer_pending(&server->timeout_tm)) {
-               struct ncp_request_reply* req;
-               
-               req = server->rcv.creq;
-               if (req) {
-                       int timeout;
-                       
-                       if (server->m.flags & NCP_MOUNT_SOFT) {
-                               if (server->timeout_retries-- == 0) {
-                                       __ncp_abort_request(server, req, -ETIMEDOUT);
-                                       return;
-                               }
-                       }
-                       /* Ignore errors */
-                       ncpdgram_send(server->ncp_sock, req);
-                       timeout = server->timeout_last << 1;
-                       if (timeout > NCP_MAX_RPC_TIMEOUT) {
-                               timeout = NCP_MAX_RPC_TIMEOUT;
-                       }
-                       server->timeout_last = timeout;
-                       mod_timer(&server->timeout_tm, jiffies + timeout);
-               }
-       }
-}
-
-void ncpdgram_timeout_proc(struct work_struct *work)
-{
-       struct ncp_server *server =
-               container_of(work, struct ncp_server, timeout_tq);
-       mutex_lock(&server->rcv.creq_mutex);
-       __ncpdgram_timeout_proc(server);
-       mutex_unlock(&server->rcv.creq_mutex);
-}
-
-static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len)
-{
-       int result;
-       
-       if (buffer) {
-               result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT);
-       } else {
-               static unsigned char dummy[1024];
-                       
-               if (len > sizeof(dummy)) {
-                       len = sizeof(dummy);
-               }
-               result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT);
-       }
-       if (result < 0) {
-               return result;
-       }
-       if (result > len) {
-               pr_err("tcp: bug in recvmsg (%u > %zu)\n", result, len);
-               return -EIO;                    
-       }
-       return result;
-}      
-
-static int __ncptcp_rcv_proc(struct ncp_server *server)
-{
-       /* We have to check the result, so store the complete header */
-       while (1) {
-               int result;
-               struct ncp_request_reply *req;
-               int datalen;
-               int type;
-
-               while (server->rcv.len) {
-                       result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len);
-                       if (result == -EAGAIN) {
-                               return 0;
-                       }
-                       if (result <= 0) {
-                               req = server->rcv.creq;
-                               if (req) {
-                                       __ncp_abort_request(server, req, -EIO);
-                               } else {
-                                       __ncptcp_abort(server);
-                               }
-                               if (result < 0) {
-                                       pr_err("tcp: error in recvmsg: %d\n", result);
-                               } else {
-                                       ncp_dbg(1, "tcp: EOF\n");
-                               }
-                               return -EIO;
-                       }
-                       if (server->rcv.ptr) {
-                               server->rcv.ptr += result;
-                       }
-                       server->rcv.len -= result;
-               }
-               switch (server->rcv.state) {
-                       case 0:
-                               if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
-                                       pr_err("tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
-                                       __ncptcp_abort(server);
-                                       return -EIO;
-                               }
-                               datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
-                               if (datalen < 10) {
-                                       pr_err("tcp: Unexpected reply len %d\n", datalen);
-                                       __ncptcp_abort(server);
-                                       return -EIO;
-                               }
-#ifdef CONFIG_NCPFS_PACKET_SIGNING                             
-                               if (server->sign_active) {
-                                       if (datalen < 18) {
-                                               pr_err("tcp: Unexpected reply len %d\n", datalen);
-                                               __ncptcp_abort(server);
-                                               return -EIO;
-                                       }
-                                       server->rcv.buf.len = datalen - 8;
-                                       server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1;
-                                       server->rcv.len = 8;
-                                       server->rcv.state = 4;
-                                       break;
-                               }
-#endif                         
-                               type = ntohs(server->rcv.buf.type);
-#ifdef CONFIG_NCPFS_PACKET_SIGNING                             
-cont:;                         
-#endif
-                               if (type != NCP_REPLY) {
-                                       if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
-                                               *(__u16*)(server->unexpected_packet.data) = htons(type);
-                                               server->unexpected_packet.len = datalen - 8;
-
-                                               server->rcv.state = 5;
-                                               server->rcv.ptr = server->unexpected_packet.data + 2;
-                                               server->rcv.len = datalen - 10;
-                                               break;
-                                       }                                       
-                                       ncp_dbg(1, "tcp: Unexpected NCP type %02X\n", type);
-skipdata2:;
-                                       server->rcv.state = 2;
-skipdata:;
-                                       server->rcv.ptr = NULL;
-                                       server->rcv.len = datalen - 10;
-                                       break;
-                               }
-                               req = server->rcv.creq;
-                               if (!req) {
-                                       ncp_dbg(1, "Reply without appropriate request\n");
-                                       goto skipdata2;
-                               }
-                               if (datalen > req->datalen + 8) {
-                                       pr_err("tcp: Unexpected reply len %d (expected at most %zd)\n", datalen, req->datalen + 8);
-                                       server->rcv.state = 3;
-                                       goto skipdata;
-                               }
-                               req->datalen = datalen - 8;
-                               ((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY;
-                               server->rcv.ptr = server->rxbuf + 2;
-                               server->rcv.len = datalen - 10;
-                               server->rcv.state = 1;
-                               break;
-#ifdef CONFIG_NCPFS_PACKET_SIGNING                             
-                       case 4:
-                               datalen = server->rcv.buf.len;
-                               type = ntohs(server->rcv.buf.type2);
-                               goto cont;
-#endif
-                       case 1:
-                               req = server->rcv.creq;
-                               if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
-                                       if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) {
-                                               pr_err("tcp: Bad sequence number\n");
-                                               __ncp_abort_request(server, req, -EIO);
-                                               return -EIO;
-                                       }
-                                       if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) {
-                                               pr_err("tcp: Connection number mismatch\n");
-                                               __ncp_abort_request(server, req, -EIO);
-                                               return -EIO;
-                                       }
-                               }
-#ifdef CONFIG_NCPFS_PACKET_SIGNING                             
-                               if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
-                                       if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
-                                               pr_err("tcp: Signature violation\n");
-                                               __ncp_abort_request(server, req, -EIO);
-                                               return -EIO;
-                                       }
-                               }
-#endif                         
-                               ncp_finish_request(server, req, req->datalen);
-                       nextreq:;
-                               __ncp_next_request(server);
-                       case 2:
-                       next:;
-                               server->rcv.ptr = (unsigned char*)&server->rcv.buf;
-                               server->rcv.len = 10;
-                               server->rcv.state = 0;
-                               break;
-                       case 3:
-                               ncp_finish_request(server, server->rcv.creq, -EIO);
-                               goto nextreq;
-                       case 5:
-                               info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
-                               goto next;
-               }
-       }
-}
-
-void ncp_tcp_rcv_proc(struct work_struct *work)
-{
-       struct ncp_server *server =
-               container_of(work, struct ncp_server, rcv.tq);
-
-       mutex_lock(&server->rcv.creq_mutex);
-       __ncptcp_rcv_proc(server);
-       mutex_unlock(&server->rcv.creq_mutex);
-}
-
-void ncp_tcp_tx_proc(struct work_struct *work)
-{
-       struct ncp_server *server =
-               container_of(work, struct ncp_server, tx.tq);
-       
-       mutex_lock(&server->rcv.creq_mutex);
-       __ncptcp_try_send(server);
-       mutex_unlock(&server->rcv.creq_mutex);
-}
-
-static int do_ncp_rpc_call(struct ncp_server *server, int size,
-               unsigned char* reply_buf, int max_reply_size)
-{
-       int result;
-       struct ncp_request_reply *req;
-
-       req = ncp_alloc_req();
-       if (!req)
-               return -ENOMEM;
-
-       req->reply_buf = reply_buf;
-       req->datalen = max_reply_size;
-       req->tx_iov[1].iov_base = server->packet;
-       req->tx_iov[1].iov_len = size;
-       req->tx_type = *(u_int16_t*)server->packet;
-
-       result = ncp_add_request(server, req);
-       if (result < 0)
-               goto out;
-
-       if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) {
-               ncp_abort_request(server, req, -EINTR);
-               result = -EINTR;
-               goto out;
-       }
-
-       result = req->result;
-
-out:
-       ncp_req_put(req);
-
-       return result;
-}
-
-/*
- * We need the server to be locked here, so check!
- */
-
-static int ncp_do_request(struct ncp_server *server, int size,
-               void* reply, int max_reply_size)
-{
-       int result;
-
-       if (server->lock == 0) {
-               pr_err("Server not locked!\n");
-               return -EIO;
-       }
-       if (!ncp_conn_valid(server)) {
-               return -EIO;
-       }
-       {
-               sigset_t old_set;
-               unsigned long mask, flags;
-
-               spin_lock_irqsave(&current->sighand->siglock, flags);
-               old_set = current->blocked;
-               if (current->flags & PF_EXITING)
-                       mask = 0;
-               else
-                       mask = sigmask(SIGKILL);
-               if (server->m.flags & NCP_MOUNT_INTR) {
-                       /* FIXME: This doesn't seem right at all.  So, like,
-                          we can't handle SIGINT and get whatever to stop?
-                          What if we've blocked it ourselves?  What about
-                          alarms?  Why, in fact, are we mucking with the
-                          sigmask at all? -- r~ */
-                       if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL)
-                               mask |= sigmask(SIGINT);
-                       if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL)
-                               mask |= sigmask(SIGQUIT);
-               }
-               siginitsetinv(&current->blocked, mask);
-               recalc_sigpending();
-               spin_unlock_irqrestore(&current->sighand->siglock, flags);
-               
-               result = do_ncp_rpc_call(server, size, reply, max_reply_size);
-
-               spin_lock_irqsave(&current->sighand->siglock, flags);
-               current->blocked = old_set;
-               recalc_sigpending();
-               spin_unlock_irqrestore(&current->sighand->siglock, flags);
-       }
-
-       ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result);
-
-       return result;
-}
-
-/* ncp_do_request assures that at least a complete reply header is
- * received. It assumes that server->current_size contains the ncp
- * request size
- */
-int ncp_request2(struct ncp_server *server, int function, 
-               void* rpl, int size)
-{
-       struct ncp_request_header *h;
-       struct ncp_reply_header* reply = rpl;
-       int result;
-
-       h = (struct ncp_request_header *) (server->packet);
-       if (server->has_subfunction != 0) {
-               *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2);
-       }
-       h->type = NCP_REQUEST;
-       /*
-        * The server shouldn't know or care what task is making a
-        * request, so we always use the same task number.
-        */
-       h->task = 2; /* (current->pid) & 0xff; */
-       h->function = function;
-
-       result = ncp_do_request(server, server->current_size, reply, size);
-       if (result < 0) {
-               ncp_dbg(1, "ncp_request_error: %d\n", result);
-               goto out;
-       }
-       server->completion = reply->completion_code;
-       server->conn_status = reply->connection_state;
-       server->reply_size = result;
-       server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
-
-       result = reply->completion_code;
-
-       if (result != 0)
-               ncp_vdbg("completion code=%x\n", result);
-out:
-       return result;
-}
-
-int ncp_connect(struct ncp_server *server)
-{
-       struct ncp_request_header *h;
-       int result;
-
-       server->connection = 0xFFFF;
-       server->sequence = 255;
-
-       h = (struct ncp_request_header *) (server->packet);
-       h->type = NCP_ALLOC_SLOT_REQUEST;
-       h->task         = 2; /* see above */
-       h->function     = 0;
-
-       result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
-       if (result < 0)
-               goto out;
-       server->connection = h->conn_low + (h->conn_high * 256);
-       result = 0;
-out:
-       return result;
-}
-
-int ncp_disconnect(struct ncp_server *server)
-{
-       struct ncp_request_header *h;
-
-       h = (struct ncp_request_header *) (server->packet);
-       h->type = NCP_DEALLOC_SLOT_REQUEST;
-       h->task         = 2; /* see above */
-       h->function     = 0;
-
-       return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
-}
-
-void ncp_lock_server(struct ncp_server *server)
-{
-       mutex_lock(&server->mutex);
-       if (server->lock)
-               pr_warn("%s: was locked!\n", __func__);
-       server->lock = 1;
-}
-
-void ncp_unlock_server(struct ncp_server *server)
-{
-       if (!server->lock) {
-               pr_warn("%s: was not locked!\n", __func__);
-               return;
-       }
-       server->lock = 0;
-       mutex_unlock(&server->mutex);
-}
diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
deleted file mode 100644 (file)
index b6e16da..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  linux/fs/ncpfs/symlink.c
- *
- *  Code for allowing symbolic links on NCPFS (i.e. NetWare)
- *  Symbolic links are not supported on native NetWare, so we use an
- *  infrequently-used flag (Sh) and store a two-word magic header in
- *  the file to make sure we don't accidentally use a non-link file
- *  as a link.
- *
- *  When using the NFS namespace, we set the mode to indicate a symlink and
- *  don't bother with the magic numbers.
- *
- *  from linux/fs/ext2/symlink.c
- *
- *  Copyright (C) 1998-99, Frank A. Vorstenbosch
- *
- *  ncpfs symlink handling code
- *  NLS support (c) 1999 Petr Vandrovec
- *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
- *
- */
-
-
-#include <linux/uaccess.h>
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/time.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/stat.h>
-#include "ncp_fs.h"
-
-/* these magic numbers must appear in the symlink file -- this makes it a bit
-   more resilient against the magic attributes being set on random files. */
-
-#define NCP_SYMLINK_MAGIC0     cpu_to_le32(0x6c6d7973)     /* "symlnk->" */
-#define NCP_SYMLINK_MAGIC1     cpu_to_le32(0x3e2d6b6e)
-
-/* ----- read a symbolic link ------------------------------------------ */
-
-static int ncp_symlink_readpage(struct file *file, struct page *page)
-{
-       struct inode *inode = page->mapping->host;
-       int error, length, len;
-       char *link, *rawlink;
-       char *buf = kmap(page);
-
-       error = -ENOMEM;
-       rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
-       if (!rawlink)
-               goto fail;
-
-       if (ncp_make_open(inode,O_RDONLY))
-               goto failEIO;
-
-       error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
-                         0,NCP_MAX_SYMLINK_SIZE,rawlink,&length);
-
-       ncp_inode_close(inode);
-       /* Close file handle if no other users... */
-       ncp_make_closed(inode);
-       if (error)
-               goto failEIO;
-
-       if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) {
-               if (length<NCP_MIN_SYMLINK_SIZE || 
-                   ((__le32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
-                   ((__le32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
-                       goto failEIO;
-               link = rawlink + 8;
-               length -= 8;
-       } else {
-               link = rawlink;
-       }
-
-       len = NCP_MAX_SYMLINK_SIZE;
-       error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link, length, 0);
-       kfree(rawlink);
-       if (error)
-               goto fail;
-       SetPageUptodate(page);
-       kunmap(page);
-       unlock_page(page);
-       return 0;
-
-failEIO:
-       error = -EIO;
-       kfree(rawlink);
-fail:
-       SetPageError(page);
-       kunmap(page);
-       unlock_page(page);
-       return error;
-}
-
-/*
- * symlinks can't do much...
- */
-const struct address_space_operations ncp_symlink_aops = {
-       .readpage       = ncp_symlink_readpage,
-};
-       
-/* ----- create a new symbolic link -------------------------------------- */
-int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
-       struct inode *inode;
-       char *rawlink;
-       int length, err, i, outlen;
-       int kludge;
-       umode_t mode;
-       __le32 attr;
-       unsigned int hdr;
-
-       ncp_dbg(1, "dir=%p, dentry=%p, symname=%s\n", dir, dentry, symname);
-
-       if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber))
-               kludge = 0;
-       else
-#ifdef CONFIG_NCPFS_EXTRAS
-       if (NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS)
-               kludge = 1;
-       else
-#endif
-       /* EPERM is returned by VFS if symlink procedure does not exist */
-               return -EPERM;
-  
-       rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
-       if (!rawlink)
-               return -ENOMEM;
-
-       if (kludge) {
-               mode = 0;
-               attr = aSHARED | aHIDDEN;
-               ((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
-               ((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
-               hdr = 8;
-       } else {
-               mode = S_IFLNK | S_IRWXUGO;
-               attr = 0;
-               hdr = 0;
-       }                       
-
-       length = strlen(symname);
-       /* map to/from server charset, do not touch upper/lower case as
-          symlink can point out of ncp filesystem */
-       outlen = NCP_MAX_SYMLINK_SIZE - hdr;
-       err = ncp_io2vol(NCP_SERVER(dir), rawlink + hdr, &outlen, symname, length, 0);
-       if (err)
-               goto failfree;
-
-       outlen += hdr;
-
-       err = -EIO;
-       if (ncp_create_new(dir,dentry,mode,0,attr)) {
-               goto failfree;
-       }
-
-       inode=d_inode(dentry);
-
-       if (ncp_make_open(inode, O_WRONLY))
-               goto failfree;
-
-       if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 
-                            0, outlen, rawlink, &i) || i!=outlen) {
-               goto fail;
-       }
-
-       ncp_inode_close(inode);
-       ncp_make_closed(inode);
-       kfree(rawlink);
-       return 0;
-fail:;
-       ncp_inode_close(inode);
-       ncp_make_closed(inode);
-failfree:;
-       kfree(rawlink);
-       return err;
-}
-
-/* ----- EOF ----- */
index f12a61be1ede9de046acd24d5407b34d156f1051..11579fd4126ef4251a69be5b47450660db449734 100644 (file)
@@ -578,8 +578,8 @@ const struct iio_chan_spec
  * iio_device_register() - register a device with the IIO subsystem
  * @indio_dev:         Device structure filled by the device driver
  **/
-#define iio_device_register(iio_dev) \
-       __iio_device_register((iio_dev), THIS_MODULE)
+#define iio_device_register(indio_dev) \
+       __iio_device_register((indio_dev), THIS_MODULE)
 int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod);
 void iio_device_unregister(struct iio_dev *indio_dev);
 /**
index 1601a2a63a7291f4267fd280d461702d4521f357..5e1cfa75f6525e903bba2ac9e30f590572c04842 100644 (file)
@@ -28,4 +28,11 @@ struct iio_map {
        void *consumer_data;
 };
 
+#define IIO_MAP(_provider_channel, _consumer_dev_name, _consumer_channel) \
+{                                                                        \
+       .adc_channel_label = _provider_channel,                           \
+       .consumer_dev_name = _consumer_dev_name,                          \
+       .consumer_channel  = _consumer_channel,                           \
+}
+
 #endif
index 7d5e445183793c98b1d1decd4488f4f9de56b834..b19b7204ef8408d74889e339a18c753291e7bd82 100644 (file)
@@ -43,12 +43,13 @@ struct iio_trigger_ops {
 /**
  * struct iio_trigger - industrial I/O trigger device
  * @ops:               [DRIVER] operations structure
+ * @owner:             [INTERN] owner of this driver module
  * @id:                        [INTERN] unique id number
  * @name:              [DRIVER] unique name
  * @dev:               [DRIVER] associated device (if relevant)
  * @list:              [INTERN] used in maintenance of global trigger list
  * @alloc_list:                [DRIVER] used for driver specific trigger list
- * @use_count:         use count for the trigger
+ * @use_count:         [INTERN] use count for the trigger.
  * @subirq_chip:       [INTERN] associate 'virtual' irq chip.
  * @subirq_base:       [INTERN] base number for irqs provided by trigger.
  * @subirqs:           [INTERN] information about the 'child' irqs.
diff --git a/include/linux/visorbus.h b/include/linux/visorbus.h
new file mode 100644 (file)
index 0000000..0d8bd67
--- /dev/null
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ */
+
+/*
+ *  This header file is to be included by other kernel mode components that
+ *  implement a particular kind of visor_device.  Each of these other kernel
+ *  mode components is called a visor device driver.  Refer to visortemplate
+ *  for a minimal sample visor device driver.
+ *
+ *  There should be nothing in this file that is private to the visorbus
+ *  bus implementation itself.
+ */
+
+#ifndef __VISORBUS_H__
+#define __VISORBUS_H__
+
+#include <linux/device.h>
+
+#define VISOR_CHANNEL_SIGNATURE ('L' << 24 | 'N' << 16 | 'C' << 8 | 'E')
+
+/*
+ * enum channel_serverstate
+ * @CHANNELSRV_UNINITIALIZED: Channel is in an undefined state.
+ * @CHANNELSRV_READY:        Channel has been initialized by server.
+ */
+enum channel_serverstate {
+       CHANNELSRV_UNINITIALIZED = 0,
+       CHANNELSRV_READY = 1
+};
+
+/*
+ * enum channel_clientstate
+ * @CHANNELCLI_DETACHED:
+ * @CHANNELCLI_DISABLED:  Client can see channel but is NOT allowed to use it
+ *                       unless given TBD* explicit request
+ *                       (should actually be < DETACHED).
+ * @CHANNELCLI_ATTACHING: Legacy EFI client request for EFI server to attach.
+ * @CHANNELCLI_ATTACHED:  Idle, but client may want to use channel any time.
+ * @CHANNELCLI_BUSY:     Client either wants to use or is using channel.
+ * @CHANNELCLI_OWNED:    "No worries" state - client can access channel
+ *                       anytime.
+ */
+enum channel_clientstate {
+       CHANNELCLI_DETACHED = 0,
+       CHANNELCLI_DISABLED = 1,
+       CHANNELCLI_ATTACHING = 2,
+       CHANNELCLI_ATTACHED = 3,
+       CHANNELCLI_BUSY = 4,
+       CHANNELCLI_OWNED = 5
+};
+
+/*
+ * Values for VISOR_CHANNEL_PROTOCOL.Features: This define exists so that
+ * a guest can look at the FeatureFlags in the io channel, and configure the
+ * driver to use interrupts or not based on this setting. All feature bits for
+ * all channels should be defined here. The io channel feature bits are defined
+ * below.
+ */
+#define VISOR_DRIVER_ENABLES_INTS (0x1ULL << 1)
+#define VISOR_CHANNEL_IS_POLLING (0x1ULL << 3)
+#define VISOR_IOVM_OK_DRIVER_DISABLING_INTS (0x1ULL << 4)
+#define VISOR_DRIVER_DISABLES_INTS (0x1ULL << 5)
+#define VISOR_DRIVER_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
+
+/*
+ * struct channel_header - Common Channel Header
+ * @signature:        Signature.
+ * @legacy_state:      DEPRECATED - being replaced by.
+ * @header_size:       sizeof(struct channel_header).
+ * @size:             Total size of this channel in bytes.
+ * @features:         Flags to modify behavior.
+ * @chtype:           Channel type: data, bus, control, etc..
+ * @partition_handle:  ID of guest partition.
+ * @handle:           Device number of this channel in client.
+ * @ch_space_offset:   Offset in bytes to channel specific area.
+ * @version_id:               Struct channel_header Version ID.
+ * @partition_index:   Index of guest partition.
+ * @zone_uuid:        Guid of Channel's zone.
+ * @cli_str_offset:    Offset from channel header to null-terminated
+ *                    ClientString (0 if ClientString not present).
+ * @cli_state_boot:    CHANNEL_CLIENTSTATE of pre-boot EFI client of this
+ *                    channel.
+ * @cmd_state_cli:     CHANNEL_COMMANDSTATE (overloaded in Windows drivers, see
+ *                    ServerStateUp, ServerStateDown, etc).
+ * @cli_state_os:      CHANNEL_CLIENTSTATE of Guest OS client of this channel.
+ * @ch_characteristic: CHANNEL_CHARACTERISTIC_<xxx>.
+ * @cmd_state_srv:     CHANNEL_COMMANDSTATE (overloaded in Windows drivers, see
+ *                    ServerStateUp, ServerStateDown, etc).
+ * @srv_state:        CHANNEL_SERVERSTATE.
+ * @cli_error_boot:    Bits to indicate err states for boot clients, so err
+ *                    messages can be throttled.
+ * @cli_error_os:      Bits to indicate err states for OS clients, so err
+ *                    messages can be throttled.
+ * @filler:           Pad out to 128 byte cacheline.
+ * @recover_channel:   Please add all new single-byte values below here.
+ */
+struct channel_header {
+       u64 signature;
+       u32 legacy_state;
+       /* SrvState, CliStateBoot, and CliStateOS below */
+       u32 header_size;
+       u64 size;
+       u64 features;
+       guid_t chtype;
+       u64 partition_handle;
+       u64 handle;
+       u64 ch_space_offset;
+       u32 version_id;
+       u32 partition_index;
+       guid_t zone_guid;
+       u32 cli_str_offset;
+       u32 cli_state_boot;
+       u32 cmd_state_cli;
+       u32 cli_state_os;
+       u32 ch_characteristic;
+       u32 cmd_state_srv;
+       u32 srv_state;
+       u8 cli_error_boot;
+       u8 cli_error_os;
+       u8 filler[1];
+       u8 recover_channel;
+} __packed;
+
+#define VISOR_CHANNEL_ENABLE_INTS (0x1ULL << 0)
+
+/*
+ * struct signal_queue_header - Subheader for the Signal Type variation of the
+ *                              Common Channel.
+ * @version:         SIGNAL_QUEUE_HEADER Version ID.
+ * @chtype:          Queue type: storage, network.
+ * @size:            Total size of this queue in bytes.
+ * @sig_base_offset:  Offset to signal queue area.
+ * @features:        Flags to modify behavior.
+ * @num_sent:        Total # of signals placed in this queue.
+ * @num_overflows:    Total # of inserts failed due to full queue.
+ * @signal_size:      Total size of a signal for this queue.
+ * @max_slots:        Max # of slots in queue, 1 slot is always empty.
+ * @max_signals:      Max # of signals in queue (MaxSignalSlots-1).
+ * @head:            Queue head signal #.
+ * @num_received:     Total # of signals removed from this queue.
+ * @tail:            Queue tail signal.
+ * @reserved1:       Reserved field.
+ * @reserved2:       Reserved field.
+ * @client_queue:
+ * @num_irq_received: Total # of Interrupts received. This is incremented by the
+ *                   ISR in the guest windows driver.
+ * @num_empty:       Number of times that visor_signal_remove is called and
+ *                   returned Empty Status.
+ * @errorflags:              Error bits set during SignalReinit to denote trouble with
+ *                   client's fields.
+ * @filler:          Pad out to 64 byte cacheline.
+ */
+struct signal_queue_header {
+       /* 1st cache line */
+       u32 version;
+       u32 chtype;
+       u64 size;
+       u64 sig_base_offset;
+       u64 features;
+       u64 num_sent;
+       u64 num_overflows;
+       u32 signal_size;
+       u32 max_slots;
+       u32 max_signals;
+       u32 head;
+       /* 2nd cache line */
+       u64 num_received;
+       u32 tail;
+       u32 reserved1;
+       u64 reserved2;
+       u64 client_queue;
+       u64 num_irq_received;
+       u64 num_empty;
+       u32 errorflags;
+       u8 filler[12];
+} __packed;
+
+/* VISORCHANNEL Guids */
+/* {414815ed-c58c-11da-95a9-00e08161165f} */
+#define VISOR_VHBA_CHANNEL_GUID \
+       GUID_INIT(0x414815ed, 0xc58c, 0x11da, \
+                 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
+#define VISOR_VHBA_CHANNEL_GUID_STR \
+       "414815ed-c58c-11da-95a9-00e08161165f"
+struct visorchipset_state {
+       u32 created:1;
+       u32 attached:1;
+       u32 configured:1;
+       u32 running:1;
+       /* Remaining bits in this 32-bit word are reserved. */
+};
+
+/**
+ * struct visor_device - A device type for things "plugged" into the visorbus
+ *                       bus
+ * @visorchannel:              Points to the channel that the device is
+ *                             associated with.
+ * @channel_type_guid:         Identifies the channel type to the bus driver.
+ * @device:                    Device struct meant for use by the bus driver
+ *                             only.
+ * @list_all:                  Used by the bus driver to enumerate devices.
+ * @timer:                     Timer fired periodically to do interrupt-type
+ *                             activity.
+ * @being_removed:             Indicates that the device is being removed from
+ *                             the bus. Private bus driver use only.
+ * @visordriver_callback_lock: Used by the bus driver to lock when adding and
+ *                             removing devices.
+ * @pausing:                   Indicates that a change towards a paused state.
+ *                             is in progress. Only modified by the bus driver.
+ * @resuming:                  Indicates that a change towards a running state
+ *                             is in progress. Only modified by the bus driver.
+ * @chipset_bus_no:            Private field used by the bus driver.
+ * @chipset_dev_no:            Private field used the bus driver.
+ * @state:                     Used to indicate the current state of the
+ *                             device.
+ * @inst:                      Unique GUID for this instance of the device.
+ * @name:                      Name of the device.
+ * @pending_msg_hdr:           For private use by bus driver to respond to
+ *                             hypervisor requests.
+ * @vbus_hdr_info:             A pointer to header info. Private use by bus
+ *                             driver.
+ * @partition_guid:            Indicates client partion id. This should be the
+ *                             same across all visor_devices in the current
+ *                             guest. Private use by bus driver only.
+ */
+struct visor_device {
+       struct visorchannel *visorchannel;
+       guid_t channel_type_guid;
+       /* These fields are for private use by the bus driver only. */
+       struct device device;
+       struct list_head list_all;
+       struct timer_list timer;
+       bool timer_active;
+       bool being_removed;
+       struct mutex visordriver_callback_lock; /* synchronize probe/remove */
+       bool pausing;
+       bool resuming;
+       u32 chipset_bus_no;
+       u32 chipset_dev_no;
+       struct visorchipset_state state;
+       guid_t inst;
+       u8 *name;
+       struct controlvm_message_header *pending_msg_hdr;
+       void *vbus_hdr_info;
+       guid_t partition_guid;
+       struct dentry *debugfs_dir;
+       struct dentry *debugfs_bus_info;
+};
+
+#define to_visor_device(x) container_of(x, struct visor_device, device)
+
+typedef void (*visorbus_state_complete_func) (struct visor_device *dev,
+                                             int status);
+
+/*
+ * This struct describes a specific visor channel, by providing its GUID, name,
+ * and sizes.
+ */
+struct visor_channeltype_descriptor {
+       const guid_t guid;
+       const char *name;
+       u64 min_bytes;
+       u32 version;
+};
+
+/**
+ * struct visor_driver - Information provided by each visor driver when it
+ *                       registers with the visorbus driver
+ * @name:              Name of the visor driver.
+ * @owner:             The module owner.
+ * @channel_types:     Types of channels handled by this driver, ending with
+ *                     a zero GUID. Our specialized BUS.match() method knows
+ *                     about this list, and uses it to determine whether this
+ *                     driver will in fact handle a new device that it has
+ *                     detected.
+ * @probe:             Called when a new device comes online, by our probe()
+ *                     function specified by driver.probe() (triggered
+ *                     ultimately by some call to driver_register(),
+ *                     bus_add_driver(), or driver_attach()).
+ * @remove:            Called when a new device is removed, by our remove()
+ *                     function specified by driver.remove() (triggered
+ *                     ultimately by some call to device_release_driver()).
+ * @channel_interrupt: Called periodically, whenever there is a possiblity
+ *                     that "something interesting" may have happened to the
+ *                     channel.
+ * @pause:             Called to initiate a change of the device's state.  If
+ *                     the return valu`e is < 0, there was an error and the
+ *                     state transition will NOT occur.  If the return value
+ *                     is >= 0, then the state transition was INITIATED
+ *                     successfully, and complete_func() will be called (or
+ *                     was just called) with the final status when either the
+ *                     state transition fails or completes successfully.
+ * @resume:            Behaves similar to pause.
+ * @driver:            Private reference to the device driver. For use by bus
+ *                     driver only.
+ */
+struct visor_driver {
+       const char *name;
+       struct module *owner;
+       struct visor_channeltype_descriptor *channel_types;
+       int (*probe)(struct visor_device *dev);
+       void (*remove)(struct visor_device *dev);
+       void (*channel_interrupt)(struct visor_device *dev);
+       int (*pause)(struct visor_device *dev,
+                    visorbus_state_complete_func complete_func);
+       int (*resume)(struct visor_device *dev,
+                     visorbus_state_complete_func complete_func);
+
+       /* These fields are for private use by the bus driver only. */
+       struct device_driver driver;
+};
+
+#define to_visor_driver(x) (container_of(x, struct visor_driver, driver))
+
+int visor_check_channel(struct channel_header *ch, struct device *dev,
+                       const guid_t *expected_uuid, char *chname,
+                       u64 expected_min_bytes, u32 expected_version,
+                       u64 expected_signature);
+
+int visorbus_register_visor_driver(struct visor_driver *drv);
+void visorbus_unregister_visor_driver(struct visor_driver *drv);
+int visorbus_read_channel(struct visor_device *dev,
+                         unsigned long offset, void *dest,
+                         unsigned long nbytes);
+int visorbus_write_channel(struct visor_device *dev,
+                          unsigned long offset, void *src,
+                          unsigned long nbytes);
+int visorbus_enable_channel_interrupts(struct visor_device *dev);
+void visorbus_disable_channel_interrupts(struct visor_device *dev);
+
+int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
+                             void *msg);
+int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
+                             void *msg);
+bool visorchannel_signalempty(struct visorchannel *channel, u32 queue);
+const guid_t *visorchannel_get_guid(struct visorchannel *channel);
+
+#define BUS_ROOT_DEVICE UINT_MAX
+struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
+                                              struct visor_device *from);
+#endif
index 8dd2e66e838323f07eb291b8f4ea88fc19a9352b..017044c2623373455274a1d642cecc7e3c4811aa 100644 (file)
@@ -3807,6 +3807,7 @@ int apply_workqueue_attrs(struct workqueue_struct *wq,
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(apply_workqueue_attrs);
 
 /**
  * wq_update_unbound_numa - update NUMA affinity of a wq for CPU hot[un]plug
index 37ec8e67af57550691fceab1c76ca6d87716f081..0428f12c25c2fc0cda29bf32065265094534f5f8 100644 (file)
@@ -213,7 +213,6 @@ source "net/dsa/Kconfig"
 source "net/8021q/Kconfig"
 source "net/decnet/Kconfig"
 source "net/llc/Kconfig"
-source "net/ipx/Kconfig"
 source "drivers/net/appletalk/Kconfig"
 source "net/x25/Kconfig"
 source "net/lapb/Kconfig"
index 14fede520840e25aa2db28c5d1aeb02a8fc1f2d9..a6147c61b17402ac49a493ee0f32872b0a02e293 100644 (file)
@@ -24,7 +24,6 @@ obj-$(CONFIG_PACKET)          += packet/
 obj-$(CONFIG_NET_KEY)          += key/
 obj-$(CONFIG_BRIDGE)           += bridge/
 obj-$(CONFIG_NET_DSA)          += dsa/
-obj-$(CONFIG_IPX)              += ipx/
 obj-$(CONFIG_ATALK)            += appletalk/
 obj-$(CONFIG_X25)              += x25/
 obj-$(CONFIG_LAPB)             += lapb/
diff --git a/net/ipx/Kconfig b/net/ipx/Kconfig
deleted file mode 100644 (file)
index e9ad006..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# IPX configuration
-#
-config IPX
-       tristate "The IPX protocol"
-       select LLC
-       ---help---
-         This is support for the Novell networking protocol, IPX, commonly
-         used for local networks of Windows machines.  You need it if you
-         want to access Novell NetWare file or print servers using the Linux
-         Novell client ncpfs (available from
-         <ftp://platan.vc.cvut.cz/pub/linux/ncpfs/>) or from
-         within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>).  In order
-         to do the former, you'll also have to say Y to "NCP file system
-         support", below.
-
-         IPX is similar in scope to IP, while SPX, which runs on top of IPX,
-         is similar to TCP.
-
-         To turn your Linux box into a fully featured NetWare file server and
-         IPX router, say Y here and fetch either lwared from
-         <ftp://ibiblio.org/pub/Linux/system/network/daemons/> or
-         mars_nwe from <ftp://www.compu-art.de/mars_nwe/>. For more
-         information, read the IPX-HOWTO available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         The IPX driver would enlarge your kernel by about 16 KB. To compile
-         this driver as a module, choose M here: the module will be called ipx.
-         Unless you want to integrate your Linux box with a local Novell
-         network, say N.
-
-config IPX_INTERN
-       bool "IPX: Full internal IPX network"
-       depends on IPX
-       ---help---
-         Every IPX network has an address that identifies it. Sometimes it is
-         useful to give an IPX "network" address to your Linux box as well
-         (for example if your box is acting as a file server for different
-         IPX networks: it will then be accessible from everywhere using the
-         same address). The way this is done is to create a virtual internal
-         "network" inside your box and to assign an IPX address to this
-         network. Say Y here if you want to do this; read the IPX-HOWTO at
-         <http://www.tldp.org/docs.html#howto> for details.
-
-         The full internal IPX network enables you to allocate sockets on
-         different virtual nodes of the internal network. This is done by
-         evaluating the field sipx_node of the socket address given to the
-         bind call. So applications should always initialize the node field
-         to 0 when binding a socket on the primary network. In this case the
-         socket is assigned the default node that has been given to the
-         kernel when the internal network was created. By enabling the full
-         internal IPX network the cross-forwarding of packets targeted at
-         'special' sockets to sockets listening on the primary network is
-         disabled. This might break existing applications, especially RIP/SAP
-         daemons. A RIP/SAP daemon that works well with the full internal net
-         can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/>.
-
-         If you don't know what you are doing, say N.
-
diff --git a/net/ipx/Makefile b/net/ipx/Makefile
deleted file mode 100644 (file)
index 440fafa..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the Linux IPX layer.
-#
-
-obj-$(CONFIG_IPX) += ipx.o
-
-ipx-y                  := af_ipx.o ipx_route.o ipx_proc.o pe2.o
-ipx-$(CONFIG_SYSCTL)   += sysctl_net_ipx.o
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
deleted file mode 100644 (file)
index d21a9d1..0000000
+++ /dev/null
@@ -1,2084 +0,0 @@
-/*
- *     Implements an IPX socket layer.
- *
- *     This code is derived from work by
- *             Ross Biro       :       Writing the original IP stack
- *             Fred Van Kempen :       Tidying up the TCP/IP
- *
- *     Many thanks go to Keith Baker, Institute For Industrial Information
- *     Technology Ltd, Swansea University for allowing me to work on this
- *     in my own time even though it was in some ways related to commercial
- *     work I am currently employed to do there.
- *
- *     All the material in this file is subject to the Gnu license version 2.
- *     Neither Alan Cox nor the Swansea University Computer Society admit
- *     liability nor provide warranty for any of this software. This material
- *     is provided as is and at no charge.
- *
- *     Portions Copyright (c) 2000-2003 Conectiva, Inc. <acme@conectiva.com.br>
- *     Neither Arnaldo Carvalho de Melo nor Conectiva, Inc. admit liability nor
- *     provide warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     Portions Copyright (c) 1995 Caldera, Inc. <greg@caldera.com>
- *     Neither Greg Page nor Caldera, Inc. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     See net/ipx/ChangeLog.
- */
-
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/init.h>
-#include <linux/ipx.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/uio.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/termios.h>
-
-#include <net/ipx.h>
-#include <net/p8022.h>
-#include <net/psnap.h>
-#include <net/sock.h>
-#include <net/datalink.h>
-#include <net/tcp_states.h>
-#include <net/net_namespace.h>
-
-#include <linux/uaccess.h>
-
-/* Configuration Variables */
-static unsigned char ipxcfg_max_hops = 16;
-static char ipxcfg_auto_select_primary;
-static char ipxcfg_auto_create_interfaces;
-int sysctl_ipx_pprop_broadcasting = 1;
-
-/* Global Variables */
-static struct datalink_proto *p8022_datalink;
-static struct datalink_proto *pEII_datalink;
-static struct datalink_proto *p8023_datalink;
-static struct datalink_proto *pSNAP_datalink;
-
-static const struct proto_ops ipx_dgram_ops;
-
-LIST_HEAD(ipx_interfaces);
-DEFINE_SPINLOCK(ipx_interfaces_lock);
-
-struct ipx_interface *ipx_primary_net;
-struct ipx_interface *ipx_internal_net;
-
-struct ipx_interface *ipx_interfaces_head(void)
-{
-       struct ipx_interface *rc = NULL;
-
-       if (!list_empty(&ipx_interfaces))
-               rc = list_entry(ipx_interfaces.next,
-                               struct ipx_interface, node);
-       return rc;
-}
-
-static void ipxcfg_set_auto_select(char val)
-{
-       ipxcfg_auto_select_primary = val;
-       if (val && !ipx_primary_net)
-               ipx_primary_net = ipx_interfaces_head();
-}
-
-static int ipxcfg_get_config_data(struct ipx_config_data __user *arg)
-{
-       struct ipx_config_data vals;
-
-       vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
-       vals.ipxcfg_auto_select_primary    = ipxcfg_auto_select_primary;
-
-       return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0;
-}
-
-/*
- * Note: Sockets may not be removed _during_ an interrupt or inet_bh
- * handler using this technique. They can be added although we do not
- * use this facility.
- */
-
-static void ipx_remove_socket(struct sock *sk)
-{
-       /* Determine interface with which socket is associated */
-       struct ipx_interface *intrfc = ipx_sk(sk)->intrfc;
-
-       if (!intrfc)
-               goto out;
-
-       ipxitf_hold(intrfc);
-       spin_lock_bh(&intrfc->if_sklist_lock);
-       sk_del_node_init(sk);
-       spin_unlock_bh(&intrfc->if_sklist_lock);
-       ipxitf_put(intrfc);
-out:
-       return;
-}
-
-static void ipx_destroy_socket(struct sock *sk)
-{
-       ipx_remove_socket(sk);
-       skb_queue_purge(&sk->sk_receive_queue);
-       sk_refcnt_debug_dec(sk);
-}
-
-/*
- * The following code is used to support IPX Interfaces (IPXITF).  An
- * IPX interface is defined by a physical device and a frame type.
- */
-
-/* ipxitf_clear_primary_net has to be called with ipx_interfaces_lock held */
-
-static void ipxitf_clear_primary_net(void)
-{
-       ipx_primary_net = NULL;
-       if (ipxcfg_auto_select_primary)
-               ipx_primary_net = ipx_interfaces_head();
-}
-
-static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
-                                                     __be16 datalink)
-{
-       struct ipx_interface *i;
-
-       list_for_each_entry(i, &ipx_interfaces, node)
-               if (i->if_dev == dev && i->if_dlink_type == datalink)
-                       goto out;
-       i = NULL;
-out:
-       return i;
-}
-
-static struct ipx_interface *ipxitf_find_using_phys(struct net_device *dev,
-                                                   __be16 datalink)
-{
-       struct ipx_interface *i;
-
-       spin_lock_bh(&ipx_interfaces_lock);
-       i = __ipxitf_find_using_phys(dev, datalink);
-       if (i)
-               ipxitf_hold(i);
-       spin_unlock_bh(&ipx_interfaces_lock);
-       return i;
-}
-
-struct ipx_interface *ipxitf_find_using_net(__be32 net)
-{
-       struct ipx_interface *i;
-
-       spin_lock_bh(&ipx_interfaces_lock);
-       if (net) {
-               list_for_each_entry(i, &ipx_interfaces, node)
-                       if (i->if_netnum == net)
-                               goto hold;
-               i = NULL;
-               goto unlock;
-       }
-
-       i = ipx_primary_net;
-       if (i)
-hold:
-               ipxitf_hold(i);
-unlock:
-       spin_unlock_bh(&ipx_interfaces_lock);
-       return i;
-}
-
-/* Sockets are bound to a particular IPX interface. */
-static void ipxitf_insert_socket(struct ipx_interface *intrfc, struct sock *sk)
-{
-       ipxitf_hold(intrfc);
-       spin_lock_bh(&intrfc->if_sklist_lock);
-       ipx_sk(sk)->intrfc = intrfc;
-       sk_add_node(sk, &intrfc->if_sklist);
-       spin_unlock_bh(&intrfc->if_sklist_lock);
-       ipxitf_put(intrfc);
-}
-
-/* caller must hold intrfc->if_sklist_lock */
-static struct sock *__ipxitf_find_socket(struct ipx_interface *intrfc,
-                                        __be16 port)
-{
-       struct sock *s;
-
-       sk_for_each(s, &intrfc->if_sklist)
-               if (ipx_sk(s)->port == port)
-                       goto found;
-       s = NULL;
-found:
-       return s;
-}
-
-/* caller must hold a reference to intrfc */
-static struct sock *ipxitf_find_socket(struct ipx_interface *intrfc,
-                                       __be16 port)
-{
-       struct sock *s;
-
-       spin_lock_bh(&intrfc->if_sklist_lock);
-       s = __ipxitf_find_socket(intrfc, port);
-       if (s)
-               sock_hold(s);
-       spin_unlock_bh(&intrfc->if_sklist_lock);
-
-       return s;
-}
-
-#ifdef CONFIG_IPX_INTERN
-static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc,
-                                               unsigned char *ipx_node,
-                                               __be16 port)
-{
-       struct sock *s;
-
-       ipxitf_hold(intrfc);
-       spin_lock_bh(&intrfc->if_sklist_lock);
-
-       sk_for_each(s, &intrfc->if_sklist) {
-               struct ipx_sock *ipxs = ipx_sk(s);
-
-               if (ipxs->port == port &&
-                   !memcmp(ipx_node, ipxs->node, IPX_NODE_LEN))
-                       goto found;
-       }
-       s = NULL;
-found:
-       spin_unlock_bh(&intrfc->if_sklist_lock);
-       ipxitf_put(intrfc);
-       return s;
-}
-#endif
-
-static void __ipxitf_down(struct ipx_interface *intrfc)
-{
-       struct sock *s;
-       struct hlist_node *t;
-
-       /* Delete all routes associated with this interface */
-       ipxrtr_del_routes(intrfc);
-
-       spin_lock_bh(&intrfc->if_sklist_lock);
-       /* error sockets */
-       sk_for_each_safe(s, t, &intrfc->if_sklist) {
-               struct ipx_sock *ipxs = ipx_sk(s);
-
-               s->sk_err = ENOLINK;
-               s->sk_error_report(s);
-               ipxs->intrfc = NULL;
-               ipxs->port   = 0;
-               sock_set_flag(s, SOCK_ZAPPED); /* Indicates it is no longer bound */
-               sk_del_node_init(s);
-       }
-       INIT_HLIST_HEAD(&intrfc->if_sklist);
-       spin_unlock_bh(&intrfc->if_sklist_lock);
-
-       /* remove this interface from list */
-       list_del(&intrfc->node);
-
-       /* remove this interface from *special* networks */
-       if (intrfc == ipx_primary_net)
-               ipxitf_clear_primary_net();
-       if (intrfc == ipx_internal_net)
-               ipx_internal_net = NULL;
-
-       if (intrfc->if_dev)
-               dev_put(intrfc->if_dev);
-       kfree(intrfc);
-}
-
-void ipxitf_down(struct ipx_interface *intrfc)
-{
-       spin_lock_bh(&ipx_interfaces_lock);
-       __ipxitf_down(intrfc);
-       spin_unlock_bh(&ipx_interfaces_lock);
-}
-
-static void __ipxitf_put(struct ipx_interface *intrfc)
-{
-       if (refcount_dec_and_test(&intrfc->refcnt))
-               __ipxitf_down(intrfc);
-}
-
-static int ipxitf_device_event(struct notifier_block *notifier,
-                               unsigned long event, void *ptr)
-{
-       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-       struct ipx_interface *i, *tmp;
-
-       if (!net_eq(dev_net(dev), &init_net))
-               return NOTIFY_DONE;
-
-       if (event != NETDEV_DOWN && event != NETDEV_UP)
-               goto out;
-
-       spin_lock_bh(&ipx_interfaces_lock);
-       list_for_each_entry_safe(i, tmp, &ipx_interfaces, node)
-               if (i->if_dev == dev) {
-                       if (event == NETDEV_UP)
-                               ipxitf_hold(i);
-                       else
-                               __ipxitf_put(i);
-               }
-       spin_unlock_bh(&ipx_interfaces_lock);
-out:
-       return NOTIFY_DONE;
-}
-
-
-static __exit void ipxitf_cleanup(void)
-{
-       struct ipx_interface *i, *tmp;
-
-       spin_lock_bh(&ipx_interfaces_lock);
-       list_for_each_entry_safe(i, tmp, &ipx_interfaces, node)
-               __ipxitf_put(i);
-       spin_unlock_bh(&ipx_interfaces_lock);
-}
-
-static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
-{
-       if (sock_queue_rcv_skb(sock, skb) < 0)
-               kfree_skb(skb);
-}
-
-/*
- * On input skb->sk is NULL. Nobody is charged for the memory.
- */
-
-/* caller must hold a reference to intrfc */
-
-#ifdef CONFIG_IPX_INTERN
-static int ipxitf_demux_socket(struct ipx_interface *intrfc,
-                              struct sk_buff *skb, int copy)
-{
-       struct ipxhdr *ipx = ipx_hdr(skb);
-       int is_broadcast = !memcmp(ipx->ipx_dest.node, ipx_broadcast_node,
-                                  IPX_NODE_LEN);
-       struct sock *s;
-       int rc;
-
-       spin_lock_bh(&intrfc->if_sklist_lock);
-
-       sk_for_each(s, &intrfc->if_sklist) {
-               struct ipx_sock *ipxs = ipx_sk(s);
-
-               if (ipxs->port == ipx->ipx_dest.sock &&
-                   (is_broadcast || !memcmp(ipx->ipx_dest.node,
-                                            ipxs->node, IPX_NODE_LEN))) {
-                       /* We found a socket to which to send */
-                       struct sk_buff *skb1;
-
-                       if (copy) {
-                               skb1 = skb_clone(skb, GFP_ATOMIC);
-                               rc = -ENOMEM;
-                               if (!skb1)
-                                       goto out;
-                       } else {
-                               skb1 = skb;
-                               copy = 1; /* skb may only be used once */
-                       }
-                       ipxitf_def_skb_handler(s, skb1);
-
-                       /* On an external interface, one socket can listen */
-                       if (intrfc != ipx_internal_net)
-                               break;
-               }
-       }
-
-       /* skb was solely for us, and we did not make a copy, so free it. */
-       if (!copy)
-               kfree_skb(skb);
-
-       rc = 0;
-out:
-       spin_unlock_bh(&intrfc->if_sklist_lock);
-       return rc;
-}
-#else
-static struct sock *ncp_connection_hack(struct ipx_interface *intrfc,
-                                       struct ipxhdr *ipx)
-{
-       /* The packet's target is a NCP connection handler. We want to hand it
-        * to the correct socket directly within the kernel, so that the
-        * mars_nwe packet distribution process does not have to do it. Here we
-        * only care about NCP and BURST packets.
-        *
-        * You might call this a hack, but believe me, you do not want a
-        * complete NCP layer in the kernel, and this is VERY fast as well. */
-       struct sock *sk = NULL;
-       int connection = 0;
-       u8 *ncphdr = (u8 *)(ipx + 1);
-
-       if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */
-               connection = (((int) *(ncphdr + 5)) << 8) | (int) *(ncphdr + 3);
-       else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77) /* BURST packet */
-               connection = (((int) *(ncphdr + 9)) << 8) | (int) *(ncphdr + 8);
-
-       if (connection) {
-               /* Now we have to look for a special NCP connection handling
-                * socket. Only these sockets have ipx_ncp_conn != 0, set by
-                * SIOCIPXNCPCONN. */
-               spin_lock_bh(&intrfc->if_sklist_lock);
-               sk_for_each(sk, &intrfc->if_sklist)
-                       if (ipx_sk(sk)->ipx_ncp_conn == connection) {
-                               sock_hold(sk);
-                               goto found;
-                       }
-               sk = NULL;
-       found:
-               spin_unlock_bh(&intrfc->if_sklist_lock);
-       }
-       return sk;
-}
-
-static int ipxitf_demux_socket(struct ipx_interface *intrfc,
-                              struct sk_buff *skb, int copy)
-{
-       struct ipxhdr *ipx = ipx_hdr(skb);
-       struct sock *sock1 = NULL, *sock2 = NULL;
-       struct sk_buff *skb1 = NULL, *skb2 = NULL;
-       int rc;
-
-       if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451)
-               sock1 = ncp_connection_hack(intrfc, ipx);
-       if (!sock1)
-               /* No special socket found, forward the packet the normal way */
-               sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
-
-       /*
-        * We need to check if there is a primary net and if
-        * this is addressed to one of the *SPECIAL* sockets because
-        * these need to be propagated to the primary net.
-        * The *SPECIAL* socket list contains: 0x452(SAP), 0x453(RIP) and
-        * 0x456(Diagnostic).
-        */
-
-       if (ipx_primary_net && intrfc != ipx_primary_net) {
-               const int dsock = ntohs(ipx->ipx_dest.sock);
-
-               if (dsock == 0x452 || dsock == 0x453 || dsock == 0x456)
-                       /* The appropriate thing to do here is to dup the
-                        * packet and route to the primary net interface via
-                        * ipxitf_send; however, we'll cheat and just demux it
-                        * here. */
-                       sock2 = ipxitf_find_socket(ipx_primary_net,
-                                                       ipx->ipx_dest.sock);
-       }
-
-       /*
-        * If there is nothing to do return. The kfree will cancel any charging.
-        */
-       rc = 0;
-       if (!sock1 && !sock2) {
-               if (!copy)
-                       kfree_skb(skb);
-               goto out;
-       }
-
-       /*
-        * This next segment of code is a little awkward, but it sets it up
-        * so that the appropriate number of copies of the SKB are made and
-        * that skb1 and skb2 point to it (them) so that it (they) can be
-        * demuxed to sock1 and/or sock2.  If we are unable to make enough
-        * copies, we do as much as is possible.
-        */
-
-       if (copy)
-               skb1 = skb_clone(skb, GFP_ATOMIC);
-       else
-               skb1 = skb;
-
-       rc = -ENOMEM;
-       if (!skb1)
-               goto out_put;
-
-       /* Do we need 2 SKBs? */
-       if (sock1 && sock2)
-               skb2 = skb_clone(skb1, GFP_ATOMIC);
-       else
-               skb2 = skb1;
-
-       if (sock1)
-               ipxitf_def_skb_handler(sock1, skb1);
-
-       if (!skb2)
-               goto out_put;
-
-       if (sock2)
-               ipxitf_def_skb_handler(sock2, skb2);
-
-       rc = 0;
-out_put:
-       if (sock1)
-               sock_put(sock1);
-       if (sock2)
-               sock_put(sock2);
-out:
-       return rc;
-}
-#endif /* CONFIG_IPX_INTERN */
-
-static struct sk_buff *ipxitf_adjust_skbuff(struct ipx_interface *intrfc,
-                                           struct sk_buff *skb)
-{
-       struct sk_buff *skb2;
-       int in_offset = (unsigned char *)ipx_hdr(skb) - skb->head;
-       int out_offset = intrfc->if_ipx_offset;
-       int len;
-
-       /* Hopefully, most cases */
-       if (in_offset >= out_offset)
-               return skb;
-
-       /* Need new SKB */
-       len  = skb->len + out_offset;
-       skb2 = alloc_skb(len, GFP_ATOMIC);
-       if (skb2) {
-               skb_reserve(skb2, out_offset);
-               skb_reset_network_header(skb2);
-               skb_reset_transport_header(skb2);
-               skb_put(skb2, skb->len);
-               memcpy(ipx_hdr(skb2), ipx_hdr(skb), skb->len);
-               memcpy(skb2->cb, skb->cb, sizeof(skb->cb));
-       }
-       kfree_skb(skb);
-       return skb2;
-}
-
-/* caller must hold a reference to intrfc and the skb has to be unshared */
-int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node)
-{
-       struct ipxhdr *ipx = ipx_hdr(skb);
-       struct net_device *dev = intrfc->if_dev;
-       struct datalink_proto *dl = intrfc->if_dlink;
-       char dest_node[IPX_NODE_LEN];
-       int send_to_wire = 1;
-       int addr_len;
-
-       ipx->ipx_tctrl = IPX_SKB_CB(skb)->ipx_tctrl;
-       ipx->ipx_dest.net = IPX_SKB_CB(skb)->ipx_dest_net;
-       ipx->ipx_source.net = IPX_SKB_CB(skb)->ipx_source_net;
-
-       /* see if we need to include the netnum in the route list */
-       if (IPX_SKB_CB(skb)->last_hop.index >= 0) {
-               __be32 *last_hop = (__be32 *)(((u8 *) skb->data) +
-                               sizeof(struct ipxhdr) +
-                               IPX_SKB_CB(skb)->last_hop.index *
-                               sizeof(__be32));
-               *last_hop = IPX_SKB_CB(skb)->last_hop.netnum;
-               IPX_SKB_CB(skb)->last_hop.index = -1;
-       }
-
-       /*
-        * We need to know how many skbuffs it will take to send out this
-        * packet to avoid unnecessary copies.
-        */
-
-       if (!dl || !dev || dev->flags & IFF_LOOPBACK)
-               send_to_wire = 0;       /* No non looped */
-
-       /*
-        * See if this should be demuxed to sockets on this interface
-        *
-        * We want to ensure the original was eaten or that we only use
-        * up clones.
-        */
-
-       if (ipx->ipx_dest.net == intrfc->if_netnum) {
-               /*
-                * To our own node, loop and free the original.
-                * The internal net will receive on all node address.
-                */
-               if (intrfc == ipx_internal_net ||
-                   !memcmp(intrfc->if_node, node, IPX_NODE_LEN)) {
-                       /* Don't charge sender */
-                       skb_orphan(skb);
-
-                       /* Will charge receiver */
-                       return ipxitf_demux_socket(intrfc, skb, 0);
-               }
-
-               /* Broadcast, loop and possibly keep to send on. */
-               if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN)) {
-                       if (!send_to_wire)
-                               skb_orphan(skb);
-                       ipxitf_demux_socket(intrfc, skb, send_to_wire);
-                       if (!send_to_wire)
-                               goto out;
-               }
-       }
-
-       /*
-        * If the originating net is not equal to our net; this is routed
-        * We are still charging the sender. Which is right - the driver
-        * free will handle this fairly.
-        */
-       if (ipx->ipx_source.net != intrfc->if_netnum) {
-               /*
-                * Unshare the buffer before modifying the count in
-                * case it's a flood or tcpdump
-                */
-               skb = skb_unshare(skb, GFP_ATOMIC);
-               if (!skb)
-                       goto out;
-               if (++ipx->ipx_tctrl > ipxcfg_max_hops)
-                       send_to_wire = 0;
-       }
-
-       if (!send_to_wire) {
-               kfree_skb(skb);
-               goto out;
-       }
-
-       /* Determine the appropriate hardware address */
-       addr_len = dev->addr_len;
-       if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN))
-               memcpy(dest_node, dev->broadcast, addr_len);
-       else
-               memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len);
-
-       /* Make any compensation for differing physical/data link size */
-       skb = ipxitf_adjust_skbuff(intrfc, skb);
-       if (!skb)
-               goto out;
-
-       /* set up data link and physical headers */
-       skb->dev        = dev;
-       skb->protocol   = htons(ETH_P_IPX);
-
-       /* Send it out */
-       dl->request(dl, skb, dest_node);
-out:
-       return 0;
-}
-
-static int ipxitf_add_local_route(struct ipx_interface *intrfc)
-{
-       return ipxrtr_add_route(intrfc->if_netnum, intrfc, NULL);
-}
-
-static void ipxitf_discover_netnum(struct ipx_interface *intrfc,
-                                  struct sk_buff *skb);
-static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb);
-
-static int ipxitf_rcv(struct ipx_interface *intrfc, struct sk_buff *skb)
-{
-       struct ipxhdr *ipx = ipx_hdr(skb);
-       int rc = 0;
-
-       ipxitf_hold(intrfc);
-
-       /* See if we should update our network number */
-       if (!intrfc->if_netnum) /* net number of intrfc not known yet */
-               ipxitf_discover_netnum(intrfc, skb);
-
-       IPX_SKB_CB(skb)->last_hop.index = -1;
-       if (ipx->ipx_type == IPX_TYPE_PPROP) {
-               rc = ipxitf_pprop(intrfc, skb);
-               if (rc)
-                       goto out_free_skb;
-       }
-
-       /* local processing follows */
-       if (!IPX_SKB_CB(skb)->ipx_dest_net)
-               IPX_SKB_CB(skb)->ipx_dest_net = intrfc->if_netnum;
-       if (!IPX_SKB_CB(skb)->ipx_source_net)
-               IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum;
-
-       /* it doesn't make sense to route a pprop packet, there's no meaning
-        * in the ipx_dest_net for such packets */
-       if (ipx->ipx_type != IPX_TYPE_PPROP &&
-           intrfc->if_netnum != IPX_SKB_CB(skb)->ipx_dest_net) {
-               /* We only route point-to-point packets. */
-               if (skb->pkt_type == PACKET_HOST) {
-                       skb = skb_unshare(skb, GFP_ATOMIC);
-                       if (skb)
-                               rc = ipxrtr_route_skb(skb);
-                       goto out_intrfc;
-               }
-
-               goto out_free_skb;
-       }
-
-       /* see if we should keep it */
-       if (!memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) ||
-           !memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN)) {
-               rc = ipxitf_demux_socket(intrfc, skb, 0);
-               goto out_intrfc;
-       }
-
-       /* we couldn't pawn it off so unload it */
-out_free_skb:
-       kfree_skb(skb);
-out_intrfc:
-       ipxitf_put(intrfc);
-       return rc;
-}
-
-static void ipxitf_discover_netnum(struct ipx_interface *intrfc,
-                                  struct sk_buff *skb)
-{
-       const struct ipx_cb *cb = IPX_SKB_CB(skb);
-
-       /* see if this is an intra packet: source_net == dest_net */
-       if (cb->ipx_source_net == cb->ipx_dest_net && cb->ipx_source_net) {
-               struct ipx_interface *i =
-                               ipxitf_find_using_net(cb->ipx_source_net);
-               /* NB: NetWare servers lie about their hop count so we
-                * dropped the test based on it. This is the best way
-                * to determine this is a 0 hop count packet. */
-               if (!i) {
-                       intrfc->if_netnum = cb->ipx_source_net;
-                       ipxitf_add_local_route(intrfc);
-               } else {
-                       printk(KERN_WARNING "IPX: Network number collision "
-                               "%lx\n        %s %s and %s %s\n",
-                               (unsigned long) ntohl(cb->ipx_source_net),
-                               ipx_device_name(i),
-                               ipx_frame_name(i->if_dlink_type),
-                               ipx_device_name(intrfc),
-                               ipx_frame_name(intrfc->if_dlink_type));
-                       ipxitf_put(i);
-               }
-       }
-}
-
-/**
- * ipxitf_pprop - Process packet propagation IPX packet type 0x14, used for
- *               NetBIOS broadcasts
- * @intrfc: IPX interface receiving this packet
- * @skb: Received packet
- *
- * Checks if packet is valid: if its more than %IPX_MAX_PPROP_HOPS hops or if it
- * is smaller than a IPX header + the room for %IPX_MAX_PPROP_HOPS hops we drop
- * it, not even processing it locally, if it has exact %IPX_MAX_PPROP_HOPS we
- * don't broadcast it, but process it locally. See chapter 5 of Novell's "IPX
- * RIP and SAP Router Specification", Part Number 107-000029-001.
- *
- * If it is valid, check if we have pprop broadcasting enabled by the user,
- * if not, just return zero for local processing.
- *
- * If it is enabled check the packet and don't broadcast it if we have already
- * seen this packet.
- *
- * Broadcast: send it to the interfaces that aren't on the packet visited nets
- * array, just after the IPX header.
- *
- * Returns -EINVAL for invalid packets, so that the calling function drops
- * the packet without local processing. 0 if packet is to be locally processed.
- */
-static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
-{
-       struct ipxhdr *ipx = ipx_hdr(skb);
-       int i, rc = -EINVAL;
-       struct ipx_interface *ifcs;
-       char *c;
-       __be32 *l;
-
-       /* Illegal packet - too many hops or too short */
-       /* We decide to throw it away: no broadcasting, no local processing.
-        * NetBIOS unaware implementations route them as normal packets -
-        * tctrl <= 15, any data payload... */
-       if (IPX_SKB_CB(skb)->ipx_tctrl > IPX_MAX_PPROP_HOPS ||
-           ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr) +
-                                       IPX_MAX_PPROP_HOPS * sizeof(u32))
-               goto out;
-       /* are we broadcasting this damn thing? */
-       rc = 0;
-       if (!sysctl_ipx_pprop_broadcasting)
-               goto out;
-       /* We do broadcast packet on the IPX_MAX_PPROP_HOPS hop, but we
-        * process it locally. All previous hops broadcasted it, and process it
-        * locally. */
-       if (IPX_SKB_CB(skb)->ipx_tctrl == IPX_MAX_PPROP_HOPS)
-               goto out;
-
-       c = ((u8 *) ipx) + sizeof(struct ipxhdr);
-       l = (__be32 *) c;
-
-       /* Don't broadcast packet if already seen this net */
-       for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++)
-               if (*l++ == intrfc->if_netnum)
-                       goto out;
-
-       /* < IPX_MAX_PPROP_HOPS hops && input interface not in list. Save the
-        * position where we will insert recvd netnum into list, later on,
-        * in ipxitf_send */
-       IPX_SKB_CB(skb)->last_hop.index = i;
-       IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum;
-       /* xmit on all other interfaces... */
-       spin_lock_bh(&ipx_interfaces_lock);
-       list_for_each_entry(ifcs, &ipx_interfaces, node) {
-               /* Except unconfigured interfaces */
-               if (!ifcs->if_netnum)
-                       continue;
-
-               /* That aren't in the list */
-               if (ifcs == intrfc)
-                       continue;
-               l = (__be32 *) c;
-               /* don't consider the last entry in the packet list,
-                * it is our netnum, and it is not there yet */
-               for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++)
-                       if (ifcs->if_netnum == *l++)
-                               break;
-               if (i == IPX_SKB_CB(skb)->ipx_tctrl) {
-                       struct sk_buff *s = skb_copy(skb, GFP_ATOMIC);
-
-                       if (s) {
-                               IPX_SKB_CB(s)->ipx_dest_net = ifcs->if_netnum;
-                               ipxrtr_route_skb(s);
-                       }
-               }
-       }
-       spin_unlock_bh(&ipx_interfaces_lock);
-out:
-       return rc;
-}
-
-static void ipxitf_insert(struct ipx_interface *intrfc)
-{
-       spin_lock_bh(&ipx_interfaces_lock);
-       list_add_tail(&intrfc->node, &ipx_interfaces);
-       spin_unlock_bh(&ipx_interfaces_lock);
-
-       if (ipxcfg_auto_select_primary && !ipx_primary_net)
-               ipx_primary_net = intrfc;
-}
-
-static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __be32 netnum,
-                                         __be16 dlink_type,
-                                         struct datalink_proto *dlink,
-                                         unsigned char internal,
-                                         int ipx_offset)
-{
-       struct ipx_interface *intrfc = kmalloc(sizeof(*intrfc), GFP_ATOMIC);
-
-       if (intrfc) {
-               intrfc->if_dev          = dev;
-               intrfc->if_netnum       = netnum;
-               intrfc->if_dlink_type   = dlink_type;
-               intrfc->if_dlink        = dlink;
-               intrfc->if_internal     = internal;
-               intrfc->if_ipx_offset   = ipx_offset;
-               intrfc->if_sknum        = IPX_MIN_EPHEMERAL_SOCKET;
-               INIT_HLIST_HEAD(&intrfc->if_sklist);
-               refcount_set(&intrfc->refcnt, 1);
-               spin_lock_init(&intrfc->if_sklist_lock);
-       }
-
-       return intrfc;
-}
-
-static int ipxitf_create_internal(struct ipx_interface_definition *idef)
-{
-       struct ipx_interface *intrfc;
-       int rc = -EEXIST;
-
-       /* Only one primary network allowed */
-       if (ipx_primary_net)
-               goto out;
-
-       /* Must have a valid network number */
-       rc = -EADDRNOTAVAIL;
-       if (!idef->ipx_network)
-               goto out;
-       intrfc = ipxitf_find_using_net(idef->ipx_network);
-       rc = -EADDRINUSE;
-       if (intrfc) {
-               ipxitf_put(intrfc);
-               goto out;
-       }
-       intrfc = ipxitf_alloc(NULL, idef->ipx_network, 0, NULL, 1, 0);
-       rc = -EAGAIN;
-       if (!intrfc)
-               goto out;
-       memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN);
-       ipx_internal_net = ipx_primary_net = intrfc;
-       ipxitf_hold(intrfc);
-       ipxitf_insert(intrfc);
-
-       rc = ipxitf_add_local_route(intrfc);
-       ipxitf_put(intrfc);
-out:
-       return rc;
-}
-
-static __be16 ipx_map_frame_type(unsigned char type)
-{
-       __be16 rc = 0;
-
-       switch (type) {
-       case IPX_FRAME_ETHERII: rc = htons(ETH_P_IPX);          break;
-       case IPX_FRAME_8022:    rc = htons(ETH_P_802_2);        break;
-       case IPX_FRAME_SNAP:    rc = htons(ETH_P_SNAP);         break;
-       case IPX_FRAME_8023:    rc = htons(ETH_P_802_3);        break;
-       }
-
-       return rc;
-}
-
-static int ipxitf_create(struct ipx_interface_definition *idef)
-{
-       struct net_device *dev;
-       __be16 dlink_type = 0;
-       struct datalink_proto *datalink = NULL;
-       struct ipx_interface *intrfc;
-       int rc;
-
-       if (idef->ipx_special == IPX_INTERNAL) {
-               rc = ipxitf_create_internal(idef);
-               goto out;
-       }
-
-       rc = -EEXIST;
-       if (idef->ipx_special == IPX_PRIMARY && ipx_primary_net)
-               goto out;
-
-       intrfc = ipxitf_find_using_net(idef->ipx_network);
-       rc = -EADDRINUSE;
-       if (idef->ipx_network && intrfc) {
-               ipxitf_put(intrfc);
-               goto out;
-       }
-
-       if (intrfc)
-               ipxitf_put(intrfc);
-
-       dev = dev_get_by_name(&init_net, idef->ipx_device);
-       rc = -ENODEV;
-       if (!dev)
-               goto out;
-
-       switch (idef->ipx_dlink_type) {
-       case IPX_FRAME_8022:
-               dlink_type      = htons(ETH_P_802_2);
-               datalink        = p8022_datalink;
-               break;
-       case IPX_FRAME_ETHERII:
-               if (dev->type != ARPHRD_IEEE802) {
-                       dlink_type      = htons(ETH_P_IPX);
-                       datalink        = pEII_datalink;
-                       break;
-               }
-               /* fall through */
-       case IPX_FRAME_SNAP:
-               dlink_type      = htons(ETH_P_SNAP);
-               datalink        = pSNAP_datalink;
-               break;
-       case IPX_FRAME_8023:
-               dlink_type      = htons(ETH_P_802_3);
-               datalink        = p8023_datalink;
-               break;
-       case IPX_FRAME_NONE:
-       default:
-               rc = -EPROTONOSUPPORT;
-               goto out_dev;
-       }
-
-       rc = -ENETDOWN;
-       if (!(dev->flags & IFF_UP))
-               goto out_dev;
-
-       /* Check addresses are suitable */
-       rc = -EINVAL;
-       if (dev->addr_len > IPX_NODE_LEN)
-               goto out_dev;
-
-       intrfc = ipxitf_find_using_phys(dev, dlink_type);
-       if (!intrfc) {
-               /* Ok now create */
-               intrfc = ipxitf_alloc(dev, idef->ipx_network, dlink_type,
-                                     datalink, 0, dev->hard_header_len +
-                                       datalink->header_length);
-               rc = -EAGAIN;
-               if (!intrfc)
-                       goto out_dev;
-               /* Setup primary if necessary */
-               if (idef->ipx_special == IPX_PRIMARY)
-                       ipx_primary_net = intrfc;
-               if (!memcmp(idef->ipx_node, "\000\000\000\000\000\000",
-                           IPX_NODE_LEN)) {
-                       memset(intrfc->if_node, 0, IPX_NODE_LEN);
-                       memcpy(intrfc->if_node + IPX_NODE_LEN - dev->addr_len,
-                               dev->dev_addr, dev->addr_len);
-               } else
-                       memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN);
-               ipxitf_hold(intrfc);
-               ipxitf_insert(intrfc);
-       }
-
-
-       /* If the network number is known, add a route */
-       rc = 0;
-       if (!intrfc->if_netnum)
-               goto out_intrfc;
-
-       rc = ipxitf_add_local_route(intrfc);
-out_intrfc:
-       ipxitf_put(intrfc);
-       goto out;
-out_dev:
-       dev_put(dev);
-out:
-       return rc;
-}
-
-static int ipxitf_delete(struct ipx_interface_definition *idef)
-{
-       struct net_device *dev = NULL;
-       __be16 dlink_type = 0;
-       struct ipx_interface *intrfc;
-       int rc = 0;
-
-       spin_lock_bh(&ipx_interfaces_lock);
-       if (idef->ipx_special == IPX_INTERNAL) {
-               if (ipx_internal_net) {
-                       __ipxitf_put(ipx_internal_net);
-                       goto out;
-               }
-               rc = -ENOENT;
-               goto out;
-       }
-
-       dlink_type = ipx_map_frame_type(idef->ipx_dlink_type);
-       rc = -EPROTONOSUPPORT;
-       if (!dlink_type)
-               goto out;
-
-       dev = __dev_get_by_name(&init_net, idef->ipx_device);
-       rc = -ENODEV;
-       if (!dev)
-               goto out;
-
-       intrfc = __ipxitf_find_using_phys(dev, dlink_type);
-       rc = -EINVAL;
-       if (!intrfc)
-               goto out;
-       __ipxitf_put(intrfc);
-
-       rc = 0;
-out:
-       spin_unlock_bh(&ipx_interfaces_lock);
-       return rc;
-}
-
-static struct ipx_interface *ipxitf_auto_create(struct net_device *dev,
-                                               __be16 dlink_type)
-{
-       struct ipx_interface *intrfc = NULL;
-       struct datalink_proto *datalink;
-
-       if (!dev)
-               goto out;
-
-       /* Check addresses are suitable */
-       if (dev->addr_len > IPX_NODE_LEN)
-               goto out;
-
-       switch (ntohs(dlink_type)) {
-       case ETH_P_IPX:         datalink = pEII_datalink;       break;
-       case ETH_P_802_2:       datalink = p8022_datalink;      break;
-       case ETH_P_SNAP:        datalink = pSNAP_datalink;      break;
-       case ETH_P_802_3:       datalink = p8023_datalink;      break;
-       default:                goto out;
-       }
-
-       intrfc = ipxitf_alloc(dev, 0, dlink_type, datalink, 0,
-                               dev->hard_header_len + datalink->header_length);
-
-       if (intrfc) {
-               memset(intrfc->if_node, 0, IPX_NODE_LEN);
-               memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
-                       dev->dev_addr, dev->addr_len);
-               spin_lock_init(&intrfc->if_sklist_lock);
-               refcount_set(&intrfc->refcnt, 1);
-               ipxitf_insert(intrfc);
-               dev_hold(dev);
-       }
-
-out:
-       return intrfc;
-}
-
-static int ipxitf_ioctl(unsigned int cmd, void __user *arg)
-{
-       int rc = -EINVAL;
-       struct ifreq ifr;
-       int val;
-
-       switch (cmd) {
-       case SIOCSIFADDR: {
-               struct sockaddr_ipx *sipx;
-               struct ipx_interface_definition f;
-
-               rc = -EFAULT;
-               if (copy_from_user(&ifr, arg, sizeof(ifr)))
-                       break;
-               sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
-               rc = -EINVAL;
-               if (sipx->sipx_family != AF_IPX)
-                       break;
-               f.ipx_network = sipx->sipx_network;
-               memcpy(f.ipx_device, ifr.ifr_name,
-                       sizeof(f.ipx_device));
-               memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN);
-               f.ipx_dlink_type = sipx->sipx_type;
-               f.ipx_special = sipx->sipx_special;
-
-               if (sipx->sipx_action == IPX_DLTITF)
-                       rc = ipxitf_delete(&f);
-               else
-                       rc = ipxitf_create(&f);
-               break;
-       }
-       case SIOCGIFADDR: {
-               struct sockaddr_ipx *sipx;
-               struct ipx_interface *ipxif;
-               struct net_device *dev;
-
-               rc = -EFAULT;
-               if (copy_from_user(&ifr, arg, sizeof(ifr)))
-                       break;
-               sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
-               dev  = __dev_get_by_name(&init_net, ifr.ifr_name);
-               rc   = -ENODEV;
-               if (!dev)
-                       break;
-               ipxif = ipxitf_find_using_phys(dev,
-                                          ipx_map_frame_type(sipx->sipx_type));
-               rc = -EADDRNOTAVAIL;
-               if (!ipxif)
-                       break;
-
-               sipx->sipx_family       = AF_IPX;
-               sipx->sipx_network      = ipxif->if_netnum;
-               memcpy(sipx->sipx_node, ipxif->if_node,
-                       sizeof(sipx->sipx_node));
-               rc = 0;
-               if (copy_to_user(arg, &ifr, sizeof(ifr)))
-                       rc = -EFAULT;
-               ipxitf_put(ipxif);
-               break;
-       }
-       case SIOCAIPXITFCRT:
-               rc = -EFAULT;
-               if (get_user(val, (unsigned char __user *) arg))
-                       break;
-               rc = 0;
-               ipxcfg_auto_create_interfaces = val;
-               break;
-       case SIOCAIPXPRISLT:
-               rc = -EFAULT;
-               if (get_user(val, (unsigned char __user *) arg))
-                       break;
-               rc = 0;
-               ipxcfg_set_auto_select(val);
-               break;
-       }
-
-       return rc;
-}
-
-/*
- *     Checksum routine for IPX
- */
-
-/* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
-/* This functions should *not* mess with packet contents */
-
-__be16 ipx_cksum(struct ipxhdr *packet, int length)
-{
-       /*
-        *      NOTE: sum is a net byte order quantity, which optimizes the
-        *      loop. This only works on big and little endian machines. (I
-        *      don't know of a machine that isn't.)
-        */
-       /* handle the first 3 words separately; checksum should be skipped
-        * and ipx_tctrl masked out */
-       __u16 *p = (__u16 *)packet;
-       __u32 sum = p[1] + (p[2] & (__force u16)htons(0x00ff));
-       __u32 i = (length >> 1) - 3; /* Number of remaining complete words */
-
-       /* Loop through them */
-       p += 3;
-       while (i--)
-               sum += *p++;
-
-       /* Add on the last part word if it exists */
-       if (packet->ipx_pktsize & htons(1))
-               sum += (__force u16)htons(0xff00) & *p;
-
-       /* Do final fixup */
-       sum = (sum & 0xffff) + (sum >> 16);
-
-       /* It's a pity there's no concept of carry in C */
-       if (sum >= 0x10000)
-               sum++;
-
-       /*
-        * Leave 0 alone; we don't want 0xffff here.  Note that we can't get
-        * here with 0x10000, so this check is the same as ((__u16)sum)
-        */
-       if (sum)
-               sum = ~sum;
-
-       return (__force __be16)sum;
-}
-
-const char *ipx_frame_name(__be16 frame)
-{
-       char* rc = "None";
-
-       switch (ntohs(frame)) {
-       case ETH_P_IPX:         rc = "EtherII"; break;
-       case ETH_P_802_2:       rc = "802.2";   break;
-       case ETH_P_SNAP:        rc = "SNAP";    break;
-       case ETH_P_802_3:       rc = "802.3";   break;
-       }
-
-       return rc;
-}
-
-const char *ipx_device_name(struct ipx_interface *intrfc)
-{
-       return intrfc->if_internal ? "Internal" :
-               intrfc->if_dev ? intrfc->if_dev->name : "Unknown";
-}
-
-/* Handling for system calls applied via the various interfaces to an IPX
- * socket object. */
-
-static int ipx_setsockopt(struct socket *sock, int level, int optname,
-                         char __user *optval, unsigned int optlen)
-{
-       struct sock *sk = sock->sk;
-       int opt;
-       int rc = -EINVAL;
-
-       lock_sock(sk);
-       if (optlen != sizeof(int))
-               goto out;
-
-       rc = -EFAULT;
-       if (get_user(opt, (unsigned int __user *)optval))
-               goto out;
-
-       rc = -ENOPROTOOPT;
-       if (!(level == SOL_IPX && optname == IPX_TYPE))
-               goto out;
-
-       ipx_sk(sk)->type = opt;
-       rc = 0;
-out:
-       release_sock(sk);
-       return rc;
-}
-
-static int ipx_getsockopt(struct socket *sock, int level, int optname,
-       char __user *optval, int __user *optlen)
-{
-       struct sock *sk = sock->sk;
-       int val = 0;
-       int len;
-       int rc = -ENOPROTOOPT;
-
-       lock_sock(sk);
-       if (!(level == SOL_IPX && optname == IPX_TYPE))
-               goto out;
-
-       val = ipx_sk(sk)->type;
-
-       rc = -EFAULT;
-       if (get_user(len, optlen))
-               goto out;
-
-       len = min_t(unsigned int, len, sizeof(int));
-       rc = -EINVAL;
-       if(len < 0)
-               goto out;
-
-       rc = -EFAULT;
-       if (put_user(len, optlen) || copy_to_user(optval, &val, len))
-               goto out;
-
-       rc = 0;
-out:
-       release_sock(sk);
-       return rc;
-}
-
-static struct proto ipx_proto = {
-       .name     = "IPX",
-       .owner    = THIS_MODULE,
-       .obj_size = sizeof(struct ipx_sock),
-};
-
-static int ipx_create(struct net *net, struct socket *sock, int protocol,
-                     int kern)
-{
-       int rc = -ESOCKTNOSUPPORT;
-       struct sock *sk;
-
-       if (!net_eq(net, &init_net))
-               return -EAFNOSUPPORT;
-
-       /*
-        * SPX support is not anymore in the kernel sources. If you want to
-        * ressurrect it, completing it and making it understand shared skbs,
-        * be fully multithreaded, etc, grab the sources in an early 2.5 kernel
-        * tree.
-        */
-       if (sock->type != SOCK_DGRAM)
-               goto out;
-
-       rc = -ENOMEM;
-       sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto, kern);
-       if (!sk)
-               goto out;
-
-       sk_refcnt_debug_inc(sk);
-       sock_init_data(sock, sk);
-       sk->sk_no_check_tx = 1;         /* Checksum off by default */
-       sock->ops = &ipx_dgram_ops;
-       rc = 0;
-out:
-       return rc;
-}
-
-static int ipx_release(struct socket *sock)
-{
-       struct sock *sk = sock->sk;
-
-       if (!sk)
-               goto out;
-
-       lock_sock(sk);
-       sk->sk_shutdown = SHUTDOWN_MASK;
-       if (!sock_flag(sk, SOCK_DEAD))
-               sk->sk_state_change(sk);
-
-       sock_set_flag(sk, SOCK_DEAD);
-       sock->sk = NULL;
-       sk_refcnt_debug_release(sk);
-       ipx_destroy_socket(sk);
-       release_sock(sk);
-       sock_put(sk);
-out:
-       return 0;
-}
-
-/* caller must hold a reference to intrfc */
-
-static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc)
-{
-       unsigned short socketNum = intrfc->if_sknum;
-
-       spin_lock_bh(&intrfc->if_sklist_lock);
-
-       if (socketNum < IPX_MIN_EPHEMERAL_SOCKET)
-               socketNum = IPX_MIN_EPHEMERAL_SOCKET;
-
-       while (__ipxitf_find_socket(intrfc, htons(socketNum)))
-               if (socketNum > IPX_MAX_EPHEMERAL_SOCKET)
-                       socketNum = IPX_MIN_EPHEMERAL_SOCKET;
-               else
-                       socketNum++;
-
-       spin_unlock_bh(&intrfc->if_sklist_lock);
-       intrfc->if_sknum = socketNum;
-
-       return htons(socketNum);
-}
-
-static int __ipx_bind(struct socket *sock,
-                       struct sockaddr *uaddr, int addr_len)
-{
-       struct sock *sk = sock->sk;
-       struct ipx_sock *ipxs = ipx_sk(sk);
-       struct ipx_interface *intrfc;
-       struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr;
-       int rc = -EINVAL;
-
-       if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_ipx))
-               goto out;
-
-       intrfc = ipxitf_find_using_net(addr->sipx_network);
-       rc = -EADDRNOTAVAIL;
-       if (!intrfc)
-               goto out;
-
-       if (!addr->sipx_port) {
-               addr->sipx_port = ipx_first_free_socketnum(intrfc);
-               rc = -EINVAL;
-               if (!addr->sipx_port)
-                       goto out_put;
-       }
-
-       /* protect IPX system stuff like routing/sap */
-       rc = -EACCES;
-       if (ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET &&
-           !capable(CAP_NET_ADMIN))
-               goto out_put;
-
-       ipxs->port = addr->sipx_port;
-
-#ifdef CONFIG_IPX_INTERN
-       if (intrfc == ipx_internal_net) {
-               /* The source address is to be set explicitly if the
-                * socket is to be bound on the internal network. If a
-                * node number 0 was specified, the default is used.
-                */
-
-               rc = -EINVAL;
-               if (!memcmp(addr->sipx_node, ipx_broadcast_node, IPX_NODE_LEN))
-                       goto out_put;
-               if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN))
-                       memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN);
-               else
-                       memcpy(ipxs->node, addr->sipx_node, IPX_NODE_LEN);
-
-               rc = -EADDRINUSE;
-               if (ipxitf_find_internal_socket(intrfc, ipxs->node,
-                                               ipxs->port)) {
-                       SOCK_DEBUG(sk,
-                               "IPX: bind failed because port %X in use.\n",
-                               ntohs(addr->sipx_port));
-                       goto out_put;
-               }
-       } else {
-               /* Source addresses are easy. It must be our
-                * network:node pair for an interface routed to IPX
-                * with the ipx routing ioctl()
-                */
-
-               memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN);
-
-               rc = -EADDRINUSE;
-               if (ipxitf_find_socket(intrfc, addr->sipx_port)) {
-                       SOCK_DEBUG(sk,
-                               "IPX: bind failed because port %X in use.\n",
-                               ntohs(addr->sipx_port));
-                       goto out_put;
-               }
-       }
-
-#else  /* !def CONFIG_IPX_INTERN */
-
-       /* Source addresses are easy. It must be our network:node pair for
-          an interface routed to IPX with the ipx routing ioctl() */
-
-       rc = -EADDRINUSE;
-       if (ipxitf_find_socket(intrfc, addr->sipx_port)) {
-               SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n",
-                               ntohs((int)addr->sipx_port));
-               goto out_put;
-       }
-
-#endif /* CONFIG_IPX_INTERN */
-
-       ipxitf_insert_socket(intrfc, sk);
-       sock_reset_flag(sk, SOCK_ZAPPED);
-
-       rc = 0;
-out_put:
-       ipxitf_put(intrfc);
-out:
-       return rc;
-}
-
-static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
-{
-       struct sock *sk = sock->sk;
-       int rc;
-
-       lock_sock(sk);
-       rc = __ipx_bind(sock, uaddr, addr_len);
-       release_sock(sk);
-
-       return rc;
-}
-
-static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
-       int addr_len, int flags)
-{
-       struct sock *sk = sock->sk;
-       struct ipx_sock *ipxs = ipx_sk(sk);
-       struct sockaddr_ipx *addr;
-       int rc = -EINVAL;
-       struct ipx_route *rt;
-
-       sk->sk_state    = TCP_CLOSE;
-       sock->state     = SS_UNCONNECTED;
-
-       lock_sock(sk);
-       if (addr_len != sizeof(*addr))
-               goto out;
-       addr = (struct sockaddr_ipx *)uaddr;
-
-       /* put the autobinding in */
-       if (!ipxs->port) {
-               struct sockaddr_ipx uaddr;
-
-               uaddr.sipx_port         = 0;
-               uaddr.sipx_network      = 0;
-
-#ifdef CONFIG_IPX_INTERN
-               rc = -ENETDOWN;
-               if (!ipxs->intrfc)
-                       goto out; /* Someone zonked the iface */
-               memcpy(uaddr.sipx_node, ipxs->intrfc->if_node,
-                       IPX_NODE_LEN);
-#endif /* CONFIG_IPX_INTERN */
-
-               rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
-                             sizeof(struct sockaddr_ipx));
-               if (rc)
-                       goto out;
-       }
-
-       /* We can either connect to primary network or somewhere
-        * we can route to */
-       rt = ipxrtr_lookup(addr->sipx_network);
-       rc = -ENETUNREACH;
-       if (!rt && !(!addr->sipx_network && ipx_primary_net))
-               goto out;
-
-       ipxs->dest_addr.net  = addr->sipx_network;
-       ipxs->dest_addr.sock = addr->sipx_port;
-       memcpy(ipxs->dest_addr.node, addr->sipx_node, IPX_NODE_LEN);
-       ipxs->type = addr->sipx_type;
-
-       if (sock->type == SOCK_DGRAM) {
-               sock->state     = SS_CONNECTED;
-               sk->sk_state    = TCP_ESTABLISHED;
-       }
-
-       if (rt)
-               ipxrtr_put(rt);
-       rc = 0;
-out:
-       release_sock(sk);
-       return rc;
-}
-
-
-static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
-                       int *uaddr_len, int peer)
-{
-       struct ipx_address *addr;
-       struct sockaddr_ipx sipx;
-       struct sock *sk = sock->sk;
-       struct ipx_sock *ipxs = ipx_sk(sk);
-       int rc;
-
-       *uaddr_len = sizeof(struct sockaddr_ipx);
-
-       lock_sock(sk);
-       if (peer) {
-               rc = -ENOTCONN;
-               if (sk->sk_state != TCP_ESTABLISHED)
-                       goto out;
-
-               addr = &ipxs->dest_addr;
-               sipx.sipx_network       = addr->net;
-               sipx.sipx_port          = addr->sock;
-               memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN);
-       } else {
-               if (ipxs->intrfc) {
-                       sipx.sipx_network = ipxs->intrfc->if_netnum;
-#ifdef CONFIG_IPX_INTERN
-                       memcpy(sipx.sipx_node, ipxs->node, IPX_NODE_LEN);
-#else
-                       memcpy(sipx.sipx_node, ipxs->intrfc->if_node,
-                               IPX_NODE_LEN);
-#endif /* CONFIG_IPX_INTERN */
-
-               } else {
-                       sipx.sipx_network = 0;
-                       memset(sipx.sipx_node, '\0', IPX_NODE_LEN);
-               }
-
-               sipx.sipx_port = ipxs->port;
-       }
-
-       sipx.sipx_family = AF_IPX;
-       sipx.sipx_type   = ipxs->type;
-       sipx.sipx_zero   = 0;
-       memcpy(uaddr, &sipx, sizeof(sipx));
-
-       rc = 0;
-out:
-       release_sock(sk);
-       return rc;
-}
-
-static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
-{
-       /* NULL here for pt means the packet was looped back */
-       struct ipx_interface *intrfc;
-       struct ipxhdr *ipx;
-       u16 ipx_pktsize;
-       int rc = 0;
-
-       if (!net_eq(dev_net(dev), &init_net))
-               goto drop;
-
-       /* Not ours */
-       if (skb->pkt_type == PACKET_OTHERHOST)
-               goto drop;
-
-       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
-               goto out;
-
-       if (!pskb_may_pull(skb, sizeof(struct ipxhdr)))
-               goto drop;
-
-       ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize);
-
-       /* Too small or invalid header? */
-       if (ipx_pktsize < sizeof(struct ipxhdr) ||
-           !pskb_may_pull(skb, ipx_pktsize))
-               goto drop;
-
-       ipx = ipx_hdr(skb);
-       if (ipx->ipx_checksum != IPX_NO_CHECKSUM &&
-          ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))
-               goto drop;
-
-       IPX_SKB_CB(skb)->ipx_tctrl      = ipx->ipx_tctrl;
-       IPX_SKB_CB(skb)->ipx_dest_net   = ipx->ipx_dest.net;
-       IPX_SKB_CB(skb)->ipx_source_net = ipx->ipx_source.net;
-
-       /* Determine what local ipx endpoint this is */
-       intrfc = ipxitf_find_using_phys(dev, pt->type);
-       if (!intrfc) {
-               if (ipxcfg_auto_create_interfaces &&
-                  IPX_SKB_CB(skb)->ipx_dest_net) {
-                       intrfc = ipxitf_auto_create(dev, pt->type);
-                       if (intrfc)
-                               ipxitf_hold(intrfc);
-               }
-
-               if (!intrfc)    /* Not one of ours */
-                               /* or invalid packet for auto creation */
-                       goto drop;
-       }
-
-       rc = ipxitf_rcv(intrfc, skb);
-       ipxitf_put(intrfc);
-       goto out;
-drop:
-       kfree_skb(skb);
-out:
-       return rc;
-}
-
-static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
-{
-       struct sock *sk = sock->sk;
-       struct ipx_sock *ipxs = ipx_sk(sk);
-       DECLARE_SOCKADDR(struct sockaddr_ipx *, usipx, msg->msg_name);
-       struct sockaddr_ipx local_sipx;
-       int rc = -EINVAL;
-       int flags = msg->msg_flags;
-
-       lock_sock(sk);
-       /* Socket gets bound below anyway */
-/*     if (sk->sk_zapped)
-               return -EIO; */ /* Socket not bound */
-       if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
-               goto out;
-
-       /* Max possible packet size limited by 16 bit pktsize in header */
-       if (len >= 65535 - sizeof(struct ipxhdr))
-               goto out;
-
-       if (usipx) {
-               if (!ipxs->port) {
-                       struct sockaddr_ipx uaddr;
-
-                       uaddr.sipx_port         = 0;
-                       uaddr.sipx_network      = 0;
-#ifdef CONFIG_IPX_INTERN
-                       rc = -ENETDOWN;
-                       if (!ipxs->intrfc)
-                               goto out; /* Someone zonked the iface */
-                       memcpy(uaddr.sipx_node, ipxs->intrfc->if_node,
-                               IPX_NODE_LEN);
-#endif
-                       rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
-                                       sizeof(struct sockaddr_ipx));
-                       if (rc)
-                               goto out;
-               }
-
-               rc = -EINVAL;
-               if (msg->msg_namelen < sizeof(*usipx) ||
-                   usipx->sipx_family != AF_IPX)
-                       goto out;
-       } else {
-               rc = -ENOTCONN;
-               if (sk->sk_state != TCP_ESTABLISHED)
-                       goto out;
-
-               usipx = &local_sipx;
-               usipx->sipx_family      = AF_IPX;
-               usipx->sipx_type        = ipxs->type;
-               usipx->sipx_port        = ipxs->dest_addr.sock;
-               usipx->sipx_network     = ipxs->dest_addr.net;
-               memcpy(usipx->sipx_node, ipxs->dest_addr.node, IPX_NODE_LEN);
-       }
-
-       rc = ipxrtr_route_packet(sk, usipx, msg, len, flags & MSG_DONTWAIT);
-       if (rc >= 0)
-               rc = len;
-out:
-       release_sock(sk);
-       return rc;
-}
-
-
-static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
-                      int flags)
-{
-       struct sock *sk = sock->sk;
-       struct ipx_sock *ipxs = ipx_sk(sk);
-       DECLARE_SOCKADDR(struct sockaddr_ipx *, sipx, msg->msg_name);
-       struct ipxhdr *ipx = NULL;
-       struct sk_buff *skb;
-       int copied, rc;
-       bool locked = true;
-
-       lock_sock(sk);
-       /* put the autobinding in */
-       if (!ipxs->port) {
-               struct sockaddr_ipx uaddr;
-
-               uaddr.sipx_port         = 0;
-               uaddr.sipx_network      = 0;
-
-#ifdef CONFIG_IPX_INTERN
-               rc = -ENETDOWN;
-               if (!ipxs->intrfc)
-                       goto out; /* Someone zonked the iface */
-               memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN);
-#endif /* CONFIG_IPX_INTERN */
-
-               rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
-                             sizeof(struct sockaddr_ipx));
-               if (rc)
-                       goto out;
-       }
-
-       rc = -ENOTCONN;
-       if (sock_flag(sk, SOCK_ZAPPED))
-               goto out;
-
-       release_sock(sk);
-       locked = false;
-       skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
-                               flags & MSG_DONTWAIT, &rc);
-       if (!skb) {
-               if (rc == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN))
-                       rc = 0;
-               goto out;
-       }
-
-       ipx     = ipx_hdr(skb);
-       copied  = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);
-       if (copied > size) {
-               copied = size;
-               msg->msg_flags |= MSG_TRUNC;
-       }
-
-       rc = skb_copy_datagram_msg(skb, sizeof(struct ipxhdr), msg, copied);
-       if (rc)
-               goto out_free;
-       if (skb->tstamp)
-               sk->sk_stamp = skb->tstamp;
-
-       if (sipx) {
-               sipx->sipx_family       = AF_IPX;
-               sipx->sipx_port         = ipx->ipx_source.sock;
-               memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN);
-               sipx->sipx_network      = IPX_SKB_CB(skb)->ipx_source_net;
-               sipx->sipx_type         = ipx->ipx_type;
-               sipx->sipx_zero         = 0;
-               msg->msg_namelen        = sizeof(*sipx);
-       }
-       rc = copied;
-
-out_free:
-       skb_free_datagram(sk, skb);
-out:
-       if (locked)
-               release_sock(sk);
-       return rc;
-}
-
-
-static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-       int rc = 0;
-       long amount = 0;
-       struct sock *sk = sock->sk;
-       void __user *argp = (void __user *)arg;
-
-       lock_sock(sk);
-       switch (cmd) {
-       case TIOCOUTQ:
-               amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
-               if (amount < 0)
-                       amount = 0;
-               rc = put_user(amount, (int __user *)argp);
-               break;
-       case TIOCINQ: {
-               struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
-               /* These two are safe on a single CPU system as only
-                * user tasks fiddle here */
-               if (skb)
-                       amount = skb->len - sizeof(struct ipxhdr);
-               rc = put_user(amount, (int __user *)argp);
-               break;
-       }
-       case SIOCADDRT:
-       case SIOCDELRT:
-               rc = -EPERM;
-               if (capable(CAP_NET_ADMIN))
-                       rc = ipxrtr_ioctl(cmd, argp);
-               break;
-       case SIOCSIFADDR:
-       case SIOCAIPXITFCRT:
-       case SIOCAIPXPRISLT:
-               rc = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
-                       break;
-               /* fall through */
-       case SIOCGIFADDR:
-               rc = ipxitf_ioctl(cmd, argp);
-               break;
-       case SIOCIPXCFGDATA:
-               rc = ipxcfg_get_config_data(argp);
-               break;
-       case SIOCIPXNCPCONN:
-               /*
-                * This socket wants to take care of the NCP connection
-                * handed to us in arg.
-                */
-               rc = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
-                       break;
-               rc = get_user(ipx_sk(sk)->ipx_ncp_conn,
-                             (const unsigned short __user *)argp);
-               break;
-       case SIOCGSTAMP:
-               rc = sock_get_timestamp(sk, argp);
-               break;
-       case SIOCGIFDSTADDR:
-       case SIOCSIFDSTADDR:
-       case SIOCGIFBRDADDR:
-       case SIOCSIFBRDADDR:
-       case SIOCGIFNETMASK:
-       case SIOCSIFNETMASK:
-               rc = -EINVAL;
-               break;
-       default:
-               rc = -ENOIOCTLCMD;
-               break;
-       }
-       release_sock(sk);
-
-       return rc;
-}
-
-
-#ifdef CONFIG_COMPAT
-static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-       /*
-        * These 4 commands use same structure on 32bit and 64bit.  Rest of IPX
-        * commands is handled by generic ioctl code.  As these commands are
-        * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic
-        * code.
-        */
-       switch (cmd) {
-       case SIOCAIPXITFCRT:
-       case SIOCAIPXPRISLT:
-       case SIOCIPXCFGDATA:
-       case SIOCIPXNCPCONN:
-               return ipx_ioctl(sock, cmd, arg);
-       default:
-               return -ENOIOCTLCMD;
-       }
-}
-#endif
-
-static int ipx_shutdown(struct socket *sock, int mode)
-{
-       struct sock *sk = sock->sk;
-
-       if (mode < SHUT_RD || mode > SHUT_RDWR)
-               return -EINVAL;
-       /* This maps:
-        * SHUT_RD   (0) -> RCV_SHUTDOWN  (1)
-        * SHUT_WR   (1) -> SEND_SHUTDOWN (2)
-        * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
-        */
-       ++mode;
-
-       lock_sock(sk);
-       sk->sk_shutdown |= mode;
-       release_sock(sk);
-       sk->sk_state_change(sk);
-
-       return 0;
-}
-
-/*
- * Socket family declarations
- */
-
-static const struct net_proto_family ipx_family_ops = {
-       .family         = PF_IPX,
-       .create         = ipx_create,
-       .owner          = THIS_MODULE,
-};
-
-static const struct proto_ops ipx_dgram_ops = {
-       .family         = PF_IPX,
-       .owner          = THIS_MODULE,
-       .release        = ipx_release,
-       .bind           = ipx_bind,
-       .connect        = ipx_connect,
-       .socketpair     = sock_no_socketpair,
-       .accept         = sock_no_accept,
-       .getname        = ipx_getname,
-       .poll           = datagram_poll,
-       .ioctl          = ipx_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = ipx_compat_ioctl,
-#endif
-       .listen         = sock_no_listen,
-       .shutdown       = ipx_shutdown,
-       .setsockopt     = ipx_setsockopt,
-       .getsockopt     = ipx_getsockopt,
-       .sendmsg        = ipx_sendmsg,
-       .recvmsg        = ipx_recvmsg,
-       .mmap           = sock_no_mmap,
-       .sendpage       = sock_no_sendpage,
-};
-
-static struct packet_type ipx_8023_packet_type __read_mostly = {
-       .type           = cpu_to_be16(ETH_P_802_3),
-       .func           = ipx_rcv,
-};
-
-static struct packet_type ipx_dix_packet_type __read_mostly = {
-       .type           = cpu_to_be16(ETH_P_IPX),
-       .func           = ipx_rcv,
-};
-
-static struct notifier_block ipx_dev_notifier = {
-       .notifier_call  = ipxitf_device_event,
-};
-
-static const unsigned char ipx_8022_type = 0xE0;
-static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
-static const char ipx_EII_err_msg[] __initconst =
-       KERN_CRIT "IPX: Unable to register with Ethernet II\n";
-static const char ipx_8023_err_msg[] __initconst =
-       KERN_CRIT "IPX: Unable to register with 802.3\n";
-static const char ipx_llc_err_msg[] __initconst =
-       KERN_CRIT "IPX: Unable to register with 802.2\n";
-static const char ipx_snap_err_msg[] __initconst =
-       KERN_CRIT "IPX: Unable to register with SNAP\n";
-
-static int __init ipx_init(void)
-{
-       int rc = proto_register(&ipx_proto, 1);
-
-       if (rc != 0)
-               goto out;
-
-       sock_register(&ipx_family_ops);
-
-       pEII_datalink = make_EII_client();
-       if (pEII_datalink)
-               dev_add_pack(&ipx_dix_packet_type);
-       else
-               printk(ipx_EII_err_msg);
-
-       p8023_datalink = make_8023_client();
-       if (p8023_datalink)
-               dev_add_pack(&ipx_8023_packet_type);
-       else
-               printk(ipx_8023_err_msg);
-
-       p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv);
-       if (!p8022_datalink)
-               printk(ipx_llc_err_msg);
-
-       pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv);
-       if (!pSNAP_datalink)
-               printk(ipx_snap_err_msg);
-
-       register_netdevice_notifier(&ipx_dev_notifier);
-       ipx_register_sysctl();
-       ipx_proc_init();
-out:
-       return rc;
-}
-
-static void __exit ipx_proto_finito(void)
-{
-       ipx_proc_exit();
-       ipx_unregister_sysctl();
-
-       unregister_netdevice_notifier(&ipx_dev_notifier);
-
-       ipxitf_cleanup();
-
-       if (pSNAP_datalink) {
-               unregister_snap_client(pSNAP_datalink);
-               pSNAP_datalink = NULL;
-       }
-
-       if (p8022_datalink) {
-               unregister_8022_client(p8022_datalink);
-               p8022_datalink = NULL;
-       }
-
-       dev_remove_pack(&ipx_8023_packet_type);
-       if (p8023_datalink) {
-               destroy_8023_client(p8023_datalink);
-               p8023_datalink = NULL;
-       }
-
-       dev_remove_pack(&ipx_dix_packet_type);
-       if (pEII_datalink) {
-               destroy_EII_client(pEII_datalink);
-               pEII_datalink = NULL;
-       }
-
-       proto_unregister(&ipx_proto);
-       sock_unregister(ipx_family_ops.family);
-}
-
-module_init(ipx_init);
-module_exit(ipx_proto_finito);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_NETPROTO(PF_IPX);
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
deleted file mode 100644 (file)
index b9232e4..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *     IPX proc routines
- *
- *     Copyright(C) Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2002
- */
-
-#include <linux/init.h>
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/seq_file.h>
-#include <linux/export.h>
-#include <net/net_namespace.h>
-#include <net/tcp_states.h>
-#include <net/ipx.h>
-
-static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos)
-{
-       spin_lock_bh(&ipx_interfaces_lock);
-       return seq_list_start_head(&ipx_interfaces, *pos);
-}
-
-static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       return seq_list_next(v, &ipx_interfaces, pos);
-}
-
-static void ipx_seq_interface_stop(struct seq_file *seq, void *v)
-{
-       spin_unlock_bh(&ipx_interfaces_lock);
-}
-
-static int ipx_seq_interface_show(struct seq_file *seq, void *v)
-{
-       struct ipx_interface *i;
-
-       if (v == &ipx_interfaces) {
-               seq_puts(seq, "Network    Node_Address   Primary  Device     "
-                             "Frame_Type");
-#ifdef IPX_REFCNT_DEBUG
-               seq_puts(seq, "  refcnt");
-#endif
-               seq_puts(seq, "\n");
-               goto out;
-       }
-
-       i = list_entry(v, struct ipx_interface, node);
-       seq_printf(seq, "%08X   ", ntohl(i->if_netnum));
-       seq_printf(seq, "%02X%02X%02X%02X%02X%02X   ",
-                       i->if_node[0], i->if_node[1], i->if_node[2],
-                       i->if_node[3], i->if_node[4], i->if_node[5]);
-       seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No");
-       seq_printf(seq, "%-11s", ipx_device_name(i));
-       seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type));
-#ifdef IPX_REFCNT_DEBUG
-       seq_printf(seq, "%6d", refcount_read(&i->refcnt));
-#endif
-       seq_puts(seq, "\n");
-out:
-       return 0;
-}
-
-static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos)
-{
-       read_lock_bh(&ipx_routes_lock);
-       return seq_list_start_head(&ipx_routes, *pos);
-}
-
-static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       return seq_list_next(v, &ipx_routes, pos);
-}
-
-static void ipx_seq_route_stop(struct seq_file *seq, void *v)
-{
-       read_unlock_bh(&ipx_routes_lock);
-}
-
-static int ipx_seq_route_show(struct seq_file *seq, void *v)
-{
-       struct ipx_route *rt;
-
-       if (v == &ipx_routes) {
-               seq_puts(seq, "Network    Router_Net   Router_Node\n");
-               goto out;
-       }
-
-       rt = list_entry(v, struct ipx_route, node);
-
-       seq_printf(seq, "%08X   ", ntohl(rt->ir_net));
-       if (rt->ir_routed)
-               seq_printf(seq, "%08X     %02X%02X%02X%02X%02X%02X\n",
-                          ntohl(rt->ir_intrfc->if_netnum),
-                          rt->ir_router_node[0], rt->ir_router_node[1],
-                          rt->ir_router_node[2], rt->ir_router_node[3],
-                          rt->ir_router_node[4], rt->ir_router_node[5]);
-       else
-               seq_puts(seq, "Directly     Connected\n");
-out:
-       return 0;
-}
-
-static __inline__ struct sock *ipx_get_socket_idx(loff_t pos)
-{
-       struct sock *s = NULL;
-       struct ipx_interface *i;
-
-       list_for_each_entry(i, &ipx_interfaces, node) {
-               spin_lock_bh(&i->if_sklist_lock);
-               sk_for_each(s, &i->if_sklist) {
-                       if (!pos)
-                               break;
-                       --pos;
-               }
-               spin_unlock_bh(&i->if_sklist_lock);
-               if (!pos) {
-                       if (s)
-                               goto found;
-                       break;
-               }
-       }
-       s = NULL;
-found:
-       return s;
-}
-
-static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos)
-{
-       loff_t l = *pos;
-
-       spin_lock_bh(&ipx_interfaces_lock);
-       return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN;
-}
-
-static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       struct sock* sk, *next;
-       struct ipx_interface *i;
-       struct ipx_sock *ipxs;
-
-       ++*pos;
-       if (v == SEQ_START_TOKEN) {
-               sk = NULL;
-               i = ipx_interfaces_head();
-               if (!i)
-                       goto out;
-               sk = sk_head(&i->if_sklist);
-               if (sk)
-                       spin_lock_bh(&i->if_sklist_lock);
-               goto out;
-       }
-       sk = v;
-       next = sk_next(sk);
-       if (next) {
-               sk = next;
-               goto out;
-       }
-       ipxs = ipx_sk(sk);
-       i = ipxs->intrfc;
-       spin_unlock_bh(&i->if_sklist_lock);
-       sk = NULL;
-       for (;;) {
-               if (i->node.next == &ipx_interfaces)
-                       break;
-               i = list_entry(i->node.next, struct ipx_interface, node);
-               spin_lock_bh(&i->if_sklist_lock);
-               if (!hlist_empty(&i->if_sklist)) {
-                       sk = sk_head(&i->if_sklist);
-                       break;
-               }
-               spin_unlock_bh(&i->if_sklist_lock);
-       }
-out:
-       return sk;
-}
-
-static int ipx_seq_socket_show(struct seq_file *seq, void *v)
-{
-       struct sock *s;
-       struct ipx_sock *ipxs;
-
-       if (v == SEQ_START_TOKEN) {
-#ifdef CONFIG_IPX_INTERN
-               seq_puts(seq, "Local_Address               "
-                             "Remote_Address              Tx_Queue  "
-                             "Rx_Queue  State  Uid\n");
-#else
-               seq_puts(seq, "Local_Address  Remote_Address              "
-                             "Tx_Queue  Rx_Queue  State  Uid\n");
-#endif
-               goto out;
-       }
-
-       s = v;
-       ipxs = ipx_sk(s);
-#ifdef CONFIG_IPX_INTERN
-       seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X  ",
-                  ntohl(ipxs->intrfc->if_netnum),
-                  ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3],
-                  ipxs->node[4], ipxs->node[5], ntohs(ipxs->port));
-#else
-       seq_printf(seq, "%08X:%04X  ", ntohl(ipxs->intrfc->if_netnum),
-                  ntohs(ipxs->port));
-#endif /* CONFIG_IPX_INTERN */
-       if (s->sk_state != TCP_ESTABLISHED)
-               seq_printf(seq, "%-28s", "Not_Connected");
-       else {
-               seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X  ",
-                          ntohl(ipxs->dest_addr.net),
-                          ipxs->dest_addr.node[0], ipxs->dest_addr.node[1],
-                          ipxs->dest_addr.node[2], ipxs->dest_addr.node[3],
-                          ipxs->dest_addr.node[4], ipxs->dest_addr.node[5],
-                          ntohs(ipxs->dest_addr.sock));
-       }
-
-       seq_printf(seq, "%08X  %08X  %02X     %03u\n",
-                  sk_wmem_alloc_get(s),
-                  sk_rmem_alloc_get(s),
-                  s->sk_state,
-                  from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)));
-out:
-       return 0;
-}
-
-static const struct seq_operations ipx_seq_interface_ops = {
-       .start  = ipx_seq_interface_start,
-       .next   = ipx_seq_interface_next,
-       .stop   = ipx_seq_interface_stop,
-       .show   = ipx_seq_interface_show,
-};
-
-static const struct seq_operations ipx_seq_route_ops = {
-       .start  = ipx_seq_route_start,
-       .next   = ipx_seq_route_next,
-       .stop   = ipx_seq_route_stop,
-       .show   = ipx_seq_route_show,
-};
-
-static const struct seq_operations ipx_seq_socket_ops = {
-       .start  = ipx_seq_socket_start,
-       .next   = ipx_seq_socket_next,
-       .stop   = ipx_seq_interface_stop,
-       .show   = ipx_seq_socket_show,
-};
-
-static int ipx_seq_route_open(struct inode *inode, struct file *file)
-{
-       return seq_open(file, &ipx_seq_route_ops);
-}
-
-static int ipx_seq_interface_open(struct inode *inode, struct file *file)
-{
-       return seq_open(file, &ipx_seq_interface_ops);
-}
-
-static int ipx_seq_socket_open(struct inode *inode, struct file *file)
-{
-       return seq_open(file, &ipx_seq_socket_ops);
-}
-
-static const struct file_operations ipx_seq_interface_fops = {
-       .open           = ipx_seq_interface_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
-};
-
-static const struct file_operations ipx_seq_route_fops = {
-       .open           = ipx_seq_route_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
-};
-
-static const struct file_operations ipx_seq_socket_fops = {
-       .open           = ipx_seq_socket_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
-};
-
-static struct proc_dir_entry *ipx_proc_dir;
-
-int __init ipx_proc_init(void)
-{
-       struct proc_dir_entry *p;
-       int rc = -ENOMEM;
-
-       ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net);
-
-       if (!ipx_proc_dir)
-               goto out;
-       p = proc_create("interface", S_IRUGO,
-                       ipx_proc_dir, &ipx_seq_interface_fops);
-       if (!p)
-               goto out_interface;
-
-       p = proc_create("route", S_IRUGO, ipx_proc_dir, &ipx_seq_route_fops);
-       if (!p)
-               goto out_route;
-
-       p = proc_create("socket", S_IRUGO, ipx_proc_dir, &ipx_seq_socket_fops);
-       if (!p)
-               goto out_socket;
-
-       rc = 0;
-out:
-       return rc;
-out_socket:
-       remove_proc_entry("route", ipx_proc_dir);
-out_route:
-       remove_proc_entry("interface", ipx_proc_dir);
-out_interface:
-       remove_proc_entry("ipx", init_net.proc_net);
-       goto out;
-}
-
-void __exit ipx_proc_exit(void)
-{
-       remove_proc_entry("interface", ipx_proc_dir);
-       remove_proc_entry("route", ipx_proc_dir);
-       remove_proc_entry("socket", ipx_proc_dir);
-       remove_proc_entry("ipx", init_net.proc_net);
-}
-
-#else /* CONFIG_PROC_FS */
-
-int __init ipx_proc_init(void)
-{
-       return 0;
-}
-
-void __exit ipx_proc_exit(void)
-{
-}
-
-#endif /* CONFIG_PROC_FS */
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
deleted file mode 100644 (file)
index 3cf93aa..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *     Implements the IPX routing routines.
- *     Code moved from af_ipx.c.
- *
- *     Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2003
- *
- *     See net/ipx/ChangeLog.
- */
-
-#include <linux/list.h>
-#include <linux/route.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-
-#include <net/ipx.h>
-#include <net/sock.h>
-
-LIST_HEAD(ipx_routes);
-DEFINE_RWLOCK(ipx_routes_lock);
-
-extern struct ipx_interface *ipx_internal_net;
-
-extern struct ipx_interface *ipxitf_find_using_net(__be32 net);
-extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
-                              struct sk_buff *skb, int copy);
-extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
-                              struct sk_buff *skb, int copy);
-
-struct ipx_route *ipxrtr_lookup(__be32 net)
-{
-       struct ipx_route *r;
-
-       read_lock_bh(&ipx_routes_lock);
-       list_for_each_entry(r, &ipx_routes, node)
-               if (r->ir_net == net) {
-                       ipxrtr_hold(r);
-                       goto unlock;
-               }
-       r = NULL;
-unlock:
-       read_unlock_bh(&ipx_routes_lock);
-       return r;
-}
-
-/*
- * Caller must hold a reference to intrfc
- */
-int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
-                    unsigned char *node)
-{
-       struct ipx_route *rt;
-       int rc;
-
-       /* Get a route structure; either existing or create */
-       rt = ipxrtr_lookup(network);
-       if (!rt) {
-               rt = kmalloc(sizeof(*rt), GFP_ATOMIC);
-               rc = -EAGAIN;
-               if (!rt)
-                       goto out;
-
-               refcount_set(&rt->refcnt, 1);
-               ipxrtr_hold(rt);
-               write_lock_bh(&ipx_routes_lock);
-               list_add(&rt->node, &ipx_routes);
-               write_unlock_bh(&ipx_routes_lock);
-       } else {
-               rc = -EEXIST;
-               if (intrfc == ipx_internal_net)
-                       goto out_put;
-       }
-
-       rt->ir_net      = network;
-       rt->ir_intrfc   = intrfc;
-       if (!node) {
-               memset(rt->ir_router_node, '\0', IPX_NODE_LEN);
-               rt->ir_routed = 0;
-       } else {
-               memcpy(rt->ir_router_node, node, IPX_NODE_LEN);
-               rt->ir_routed = 1;
-       }
-
-       rc = 0;
-out_put:
-       ipxrtr_put(rt);
-out:
-       return rc;
-}
-
-void ipxrtr_del_routes(struct ipx_interface *intrfc)
-{
-       struct ipx_route *r, *tmp;
-
-       write_lock_bh(&ipx_routes_lock);
-       list_for_each_entry_safe(r, tmp, &ipx_routes, node)
-               if (r->ir_intrfc == intrfc) {
-                       list_del(&r->node);
-                       ipxrtr_put(r);
-               }
-       write_unlock_bh(&ipx_routes_lock);
-}
-
-static int ipxrtr_create(struct ipx_route_definition *rd)
-{
-       struct ipx_interface *intrfc;
-       int rc = -ENETUNREACH;
-
-       /* Find the appropriate interface */
-       intrfc = ipxitf_find_using_net(rd->ipx_router_network);
-       if (!intrfc)
-               goto out;
-       rc = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node);
-       ipxitf_put(intrfc);
-out:
-       return rc;
-}
-
-static int ipxrtr_delete(__be32 net)
-{
-       struct ipx_route *r, *tmp;
-       int rc;
-
-       write_lock_bh(&ipx_routes_lock);
-       list_for_each_entry_safe(r, tmp, &ipx_routes, node)
-               if (r->ir_net == net) {
-                       /* Directly connected; can't lose route */
-                       rc = -EPERM;
-                       if (!r->ir_routed)
-                               goto out;
-                       list_del(&r->node);
-                       ipxrtr_put(r);
-                       rc = 0;
-                       goto out;
-               }
-       rc = -ENOENT;
-out:
-       write_unlock_bh(&ipx_routes_lock);
-       return rc;
-}
-
-/*
- * The skb has to be unshared, we'll end up calling ipxitf_send, that'll
- * modify the packet
- */
-int ipxrtr_route_skb(struct sk_buff *skb)
-{
-       struct ipxhdr *ipx = ipx_hdr(skb);
-       struct ipx_route *r = ipxrtr_lookup(IPX_SKB_CB(skb)->ipx_dest_net);
-
-       if (!r) {       /* no known route */
-               kfree_skb(skb);
-               return 0;
-       }
-
-       ipxitf_hold(r->ir_intrfc);
-       ipxitf_send(r->ir_intrfc, skb, r->ir_routed ?
-                       r->ir_router_node : ipx->ipx_dest.node);
-       ipxitf_put(r->ir_intrfc);
-       ipxrtr_put(r);
-
-       return 0;
-}
-
-/*
- * Route an outgoing frame from a socket.
- */
-int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
-                       struct msghdr *msg, size_t len, int noblock)
-{
-       struct sk_buff *skb;
-       struct ipx_sock *ipxs = ipx_sk(sk);
-       struct ipx_interface *intrfc;
-       struct ipxhdr *ipx;
-       size_t size;
-       int ipx_offset;
-       struct ipx_route *rt = NULL;
-       int rc;
-
-       /* Find the appropriate interface on which to send packet */
-       if (!usipx->sipx_network && ipx_primary_net) {
-               usipx->sipx_network = ipx_primary_net->if_netnum;
-               intrfc = ipx_primary_net;
-       } else {
-               rt = ipxrtr_lookup(usipx->sipx_network);
-               rc = -ENETUNREACH;
-               if (!rt)
-                       goto out;
-               intrfc = rt->ir_intrfc;
-       }
-
-       ipxitf_hold(intrfc);
-       ipx_offset = intrfc->if_ipx_offset;
-       size = sizeof(struct ipxhdr) + len + ipx_offset;
-
-       skb = sock_alloc_send_skb(sk, size, noblock, &rc);
-       if (!skb)
-               goto out_put;
-
-       skb_reserve(skb, ipx_offset);
-       skb->sk = sk;
-
-       /* Fill in IPX header */
-       skb_reset_network_header(skb);
-       skb_reset_transport_header(skb);
-       skb_put(skb, sizeof(struct ipxhdr));
-       ipx = ipx_hdr(skb);
-       ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr));
-       IPX_SKB_CB(skb)->ipx_tctrl = 0;
-       ipx->ipx_type    = usipx->sipx_type;
-
-       IPX_SKB_CB(skb)->last_hop.index = -1;
-#ifdef CONFIG_IPX_INTERN
-       IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum;
-       memcpy(ipx->ipx_source.node, ipxs->node, IPX_NODE_LEN);
-#else
-       rc = ntohs(ipxs->port);
-       if (rc == 0x453 || rc == 0x452) {
-               /* RIP/SAP special handling for mars_nwe */
-               IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum;
-               memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN);
-       } else {
-               IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum;
-               memcpy(ipx->ipx_source.node, ipxs->intrfc->if_node,
-                       IPX_NODE_LEN);
-       }
-#endif /* CONFIG_IPX_INTERN */
-       ipx->ipx_source.sock            = ipxs->port;
-       IPX_SKB_CB(skb)->ipx_dest_net   = usipx->sipx_network;
-       memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN);
-       ipx->ipx_dest.sock              = usipx->sipx_port;
-
-       rc = memcpy_from_msg(skb_put(skb, len), msg, len);
-       if (rc) {
-               kfree_skb(skb);
-               goto out_put;
-       }
-
-       /* Apply checksum. Not allowed on 802.3 links. */
-       if (sk->sk_no_check_tx ||
-           intrfc->if_dlink_type == htons(IPX_FRAME_8023))
-               ipx->ipx_checksum = htons(0xFFFF);
-       else
-               ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
-
-       rc = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
-                        rt->ir_router_node : ipx->ipx_dest.node);
-out_put:
-       ipxitf_put(intrfc);
-       if (rt)
-               ipxrtr_put(rt);
-out:
-       return rc;
-}
-
-/*
- * We use a normal struct rtentry for route handling
- */
-int ipxrtr_ioctl(unsigned int cmd, void __user *arg)
-{
-       struct rtentry rt;      /* Use these to behave like 'other' stacks */
-       struct sockaddr_ipx *sg, *st;
-       int rc = -EFAULT;
-
-       if (copy_from_user(&rt, arg, sizeof(rt)))
-               goto out;
-
-       sg = (struct sockaddr_ipx *)&rt.rt_gateway;
-       st = (struct sockaddr_ipx *)&rt.rt_dst;
-
-       rc = -EINVAL;
-       if (!(rt.rt_flags & RTF_GATEWAY) || /* Direct routes are fixed */
-           sg->sipx_family != AF_IPX ||
-           st->sipx_family != AF_IPX)
-               goto out;
-
-       switch (cmd) {
-       case SIOCDELRT:
-               rc = ipxrtr_delete(st->sipx_network);
-               break;
-       case SIOCADDRT: {
-               struct ipx_route_definition f;
-               f.ipx_network           = st->sipx_network;
-               f.ipx_router_network    = sg->sipx_network;
-               memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN);
-               rc = ipxrtr_create(&f);
-               break;
-       }
-       }
-
-out:
-       return rc;
-}
diff --git a/net/ipx/pe2.c b/net/ipx/pe2.c
deleted file mode 100644 (file)
index ba7d421..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/in.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-
-#include <net/datalink.h>
-
-static int pEII_request(struct datalink_proto *dl,
-                       struct sk_buff *skb, unsigned char *dest_node)
-{
-       struct net_device *dev = skb->dev;
-
-       skb->protocol = htons(ETH_P_IPX);
-       dev_hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
-       return dev_queue_xmit(skb);
-}
-
-struct datalink_proto *make_EII_client(void)
-{
-       struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
-
-       if (proto) {
-               proto->header_length = 0;
-               proto->request = pEII_request;
-       }
-
-       return proto;
-}
-
-void destroy_EII_client(struct datalink_proto *dl)
-{
-       kfree(dl);
-}
diff --git a/net/ipx/sysctl_net_ipx.c b/net/ipx/sysctl_net_ipx.c
deleted file mode 100644 (file)
index c3eef45..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* -*- linux-c -*-
- * sysctl_net_ipx.c: sysctl interface to net IPX subsystem.
- *
- * Begun April 1, 1996, Mike Shaver.
- * Added /proc/sys/net/ipx directory entry (empty =) ). [MS]
- * Added /proc/sys/net/ipx/ipx_pprop_broadcasting - acme March 4, 2001
- */
-
-#include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <net/net_namespace.h>
-#include <net/ipx.h>
-
-#ifndef CONFIG_SYSCTL
-#error This file should not be compiled without CONFIG_SYSCTL defined
-#endif
-
-static struct ctl_table ipx_table[] = {
-       {
-               .procname       = "ipx_pprop_broadcasting",
-               .data           = &sysctl_ipx_pprop_broadcasting,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec,
-       },
-       { },
-};
-
-static struct ctl_table_header *ipx_table_header;
-
-void ipx_register_sysctl(void)
-{
-       ipx_table_header = register_net_sysctl(&init_net, "net/ipx", ipx_table);
-}
-
-void ipx_unregister_sysctl(void)
-{
-       unregister_net_sysctl_table(ipx_table_header);
-}