aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-adc.txt13
-rw-r--r--Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt60
-rw-r--r--Documentation/devicetree/bindings/iio/iio-bindings.txt97
-rw-r--r--Documentation/devicetree/bindings/staging/dwc2.txt15
-rw-r--r--Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt2
-rw-r--r--MAINTAINERS12
-rw-r--r--drivers/hwmon/Kconfig9
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/iio_hwmon.c (renamed from drivers/staging/iio/iio_hwmon.c)8
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c24
-rw-r--r--drivers/iio/accel/kxsd9.c6
-rw-r--r--drivers/iio/accel/st_accel_buffer.c2
-rw-r--r--drivers/iio/adc/Kconfig20
-rw-r--r--drivers/iio/adc/Makefile2
-rw-r--r--drivers/iio/adc/ad7266.c12
-rw-r--r--drivers/iio/adc/ad7298.c10
-rw-r--r--drivers/iio/adc/ad7476.c10
-rw-r--r--drivers/iio/adc/ad7887.c8
-rw-r--r--drivers/iio/adc/ad7923.c383
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c2
-rw-r--r--drivers/iio/adc/at91_adc.c98
-rw-r--r--drivers/iio/adc/exynos_adc.c452
-rw-r--r--drivers/iio/adc/lp8788_adc.c4
-rw-r--r--drivers/iio/adc/max1363.c9
-rw-r--r--drivers/iio/adc/ti-adc081c.c4
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c2
-rw-r--r--drivers/iio/adc/viperboard_adc.c2
-rw-r--r--drivers/iio/amplifiers/ad8366.c2
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c4
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_spi.c11
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_trigger.c2
-rw-r--r--drivers/iio/dac/ad5064.c4
-rw-r--r--drivers/iio/dac/ad5360.c10
-rw-r--r--drivers/iio/dac/ad5380.c8
-rw-r--r--drivers/iio/dac/ad5421.c10
-rw-r--r--drivers/iio/dac/ad5446.c4
-rw-r--r--drivers/iio/dac/ad5449.c4
-rw-r--r--drivers/iio/dac/ad5504.c4
-rw-r--r--drivers/iio/dac/ad5624r_spi.c4
-rw-r--r--drivers/iio/dac/ad5686.c6
-rw-r--r--drivers/iio/dac/ad5755.c10
-rw-r--r--drivers/iio/dac/ad5764.c10
-rw-r--r--drivers/iio/dac/ad5791.c6
-rw-r--r--drivers/iio/dac/max517.c4
-rw-r--r--drivers/iio/dac/mcp4725.c4
-rw-r--r--drivers/iio/frequency/ad9523.c8
-rw-r--r--drivers/iio/gyro/adis16080.c22
-rw-r--r--drivers/iio/gyro/adis16136.c13
-rw-r--r--drivers/iio/gyro/adxrs450.c22
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c24
-rw-r--r--drivers/iio/gyro/itg3200_buffer.c4
-rw-r--r--drivers/iio/gyro/itg3200_core.c13
-rw-r--r--drivers/iio/gyro/st_gyro_buffer.c2
-rw-r--r--drivers/iio/iio_core.h1
-rw-r--r--drivers/iio/imu/adis16400_core.c49
-rw-r--r--drivers/iio/imu/adis16480.c32
-rw-r--r--drivers/iio/imu/adis_trigger.c4
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c10
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c5
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c4
-rw-r--r--drivers/iio/industrialio-core.c35
-rw-r--r--drivers/iio/industrialio-event.c29
-rw-r--r--drivers/iio/inkern.c171
-rw-r--r--drivers/iio/light/adjd_s311.c4
-rw-r--r--drivers/iio/light/hid-sensor-als.c8
-rw-r--r--drivers/iio/light/lm3533-als.c6
-rw-r--r--drivers/iio/light/tsl2563.c10
-rw-r--r--drivers/iio/light/vcnl4000.c6
-rw-r--r--drivers/iio/magnetometer/Kconfig11
-rw-r--r--drivers/iio/magnetometer/Makefile1
-rw-r--r--drivers/iio/magnetometer/ak8975.c (renamed from drivers/staging/iio/magnetometer/ak8975.c)73
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c24
-rw-r--r--drivers/staging/Kconfig10
-rw-r--r--drivers/staging/Makefile6
-rw-r--r--drivers/staging/android/Kconfig29
-rw-r--r--drivers/staging/android/Makefile2
-rw-r--r--drivers/staging/android/ashmem.c66
-rw-r--r--drivers/staging/android/ashmem.h7
-rw-r--r--drivers/staging/android/binder.c138
-rw-r--r--drivers/staging/android/binder.h8
-rw-r--r--drivers/staging/android/logger.c196
-rw-r--r--drivers/staging/android/logger.h40
-rw-r--r--drivers/staging/android/lowmemorykiller.c9
-rw-r--r--drivers/staging/android/sw_sync.c264
-rw-r--r--drivers/staging/android/sw_sync.h58
-rw-r--r--drivers/staging/android/sync.c1017
-rw-r--r--drivers/staging/android/sync.h426
-rw-r--r--drivers/staging/android/trace/sync.h82
-rw-r--r--drivers/staging/bcm/Bcmchar.c2
-rw-r--r--drivers/staging/bcm/InterfaceDld.c32
-rw-r--r--drivers/staging/bcm/PHSModule.c1906
-rw-r--r--drivers/staging/bcm/nvm.c14
-rw-r--r--drivers/staging/ccg/Kconfig25
-rw-r--r--drivers/staging/ccg/Makefile2
-rw-r--r--drivers/staging/ccg/TODO6
-rw-r--r--drivers/staging/ccg/ccg.c1292
-rw-r--r--drivers/staging/ccg/composite.c1688
-rw-r--r--drivers/staging/ccg/composite.h395
-rw-r--r--drivers/staging/ccg/config.c158
-rw-r--r--drivers/staging/ccg/epautoconf.c393
-rw-r--r--drivers/staging/ccg/f_acm.c814
-rw-r--r--drivers/staging/ccg/f_fs.c2456
-rw-r--r--drivers/staging/ccg/f_mass_storage.c3135
-rw-r--r--drivers/staging/ccg/f_rndis.c918
-rw-r--r--drivers/staging/ccg/gadget_chips.h150
-rw-r--r--drivers/staging/ccg/ndis.h47
-rw-r--r--drivers/staging/ccg/rndis.c1175
-rw-r--r--drivers/staging/ccg/rndis.h222
-rw-r--r--drivers/staging/ccg/storage_common.c893
-rw-r--r--drivers/staging/ccg/sysfs-class-ccg_usb158
-rw-r--r--drivers/staging/ccg/u_ether.c986
-rw-r--r--drivers/staging/ccg/u_ether.h154
-rw-r--r--drivers/staging/ccg/u_serial.c1339
-rw-r--r--drivers/staging/ccg/u_serial.h65
-rw-r--r--drivers/staging/ccg/usbstring.c71
-rw-r--r--drivers/staging/comedi/Kconfig60
-rw-r--r--drivers/staging/comedi/comedi_buf.c18
-rw-r--r--drivers/staging/comedi/comedi_fops.c545
-rw-r--r--drivers/staging/comedi/comedi_internal.h5
-rw-r--r--drivers/staging/comedi/comedi_pci.c34
-rw-r--r--drivers/staging/comedi/comedidev.h31
-rw-r--r--drivers/staging/comedi/drivers.c182
-rw-r--r--drivers/staging/comedi/drivers/8255.c23
-rw-r--r--drivers/staging/comedi/drivers/8255.h1
-rw-r--r--drivers/staging/comedi/drivers/8255_pci.c210
-rw-r--r--drivers/staging/comedi/drivers/Makefile9
-rw-r--r--drivers/staging/comedi/drivers/acl7225b.c141
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c34
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.h5
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_035.c20
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1032.c15
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1500.c23
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1516.c66
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1564.c20
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_16xx.c69
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1710.c64
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2032.c18
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2200.c18
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3120.c52
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3200.c55
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3501.c15
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3xxx.c300
-rw-r--r--drivers/staging/comedi/drivers/addi_watchdog.c6
-rw-r--r--drivers/staging/comedi/drivers/addi_watchdog.h1
-rw-r--r--drivers/staging/comedi/drivers/adl_pci6208.c63
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7x3x.c95
-rw-r--r--drivers/staging/comedi/drivers/adl_pci8164.c346
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c64
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c19
-rw-r--r--drivers/staging/comedi/drivers/adq12b.c48
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c142
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c20
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1724.c409
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c178
-rw-r--r--drivers/staging/comedi/drivers/aio_aio12_8.c22
-rw-r--r--drivers/staging/comedi/drivers/aio_iiro_16.c26
-rw-r--r--drivers/staging/comedi/drivers/am9513.h79
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c1980
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.h95
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200_common.c1271
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200_pci.c486
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.c91
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc263.c303
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c21
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c26
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci263.c127
-rw-r--r--drivers/staging/comedi/drivers/c6xdigio.c39
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c98
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c970
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidda.c96
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c16
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdda.c19
-rw-r--r--drivers/staging/comedi/drivers/comedi_fc.c6
-rw-r--r--drivers/staging/comedi/drivers/comedi_parport.c29
-rw-r--r--drivers/staging/comedi/drivers/comedi_test.c2
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c21
-rw-r--r--drivers/staging/comedi/drivers/daqboard2000.c40
-rw-r--r--drivers/staging/comedi/drivers/das08.c3
-rw-r--r--drivers/staging/comedi/drivers/das08.h1
-rw-r--r--drivers/staging/comedi/drivers/das08_cs.c1
-rw-r--r--drivers/staging/comedi/drivers/das08_isa.c14
-rw-r--r--drivers/staging/comedi/drivers/das08_pci.c13
-rw-r--r--drivers/staging/comedi/drivers/das16.c67
-rw-r--r--drivers/staging/comedi/drivers/das16m1.c46
-rw-r--r--drivers/staging/comedi/drivers/das1800.c92
-rw-r--r--drivers/staging/comedi/drivers/das6402.c27
-rw-r--r--drivers/staging/comedi/drivers/das800.c999
-rw-r--r--drivers/staging/comedi/drivers/dmm32at.c28
-rw-r--r--drivers/staging/comedi/drivers/dt2801.c36
-rw-r--r--drivers/staging/comedi/drivers/dt2811.c29
-rw-r--r--drivers/staging/comedi/drivers/dt2814.c22
-rw-r--r--drivers/staging/comedi/drivers/dt2815.c29
-rw-r--r--drivers/staging/comedi/drivers/dt2817.c22
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c59
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c103
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c30
-rw-r--r--drivers/staging/comedi/drivers/dyna_pci10xx.c15
-rw-r--r--drivers/staging/comedi/drivers/fl512.c31
-rw-r--r--drivers/staging/comedi/drivers/gsc_hpdi.c30
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c23
-rw-r--r--drivers/staging/comedi/drivers/ii_pci20kc.c4
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c18
-rw-r--r--drivers/staging/comedi/drivers/ke_counter.c21
-rw-r--r--drivers/staging/comedi/drivers/me4000.c213
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c84
-rw-r--r--drivers/staging/comedi/drivers/mite.c76
-rw-r--r--drivers/staging/comedi/drivers/mpc624.c39
-rw-r--r--drivers/staging/comedi/drivers/multiq3.c45
-rw-r--r--drivers/staging/comedi/drivers/ni_6527.c82
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c394
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c144
-rw-r--r--drivers/staging/comedi/drivers/ni_670x.c64
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c47
-rw-r--r--drivers/staging/comedi/drivers/ni_at_ao.c24
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio.c29
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio16d.c30
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_dio24.c5
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c2448
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.h30
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_cs.c6
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_pci.c142
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c355
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c68
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c2056
-rw-r--r--drivers/staging/comedi/drivers/ni_stc.h4
-rw-r--r--drivers/staging/comedi/drivers/pcl711.c30
-rw-r--r--drivers/staging/comedi/drivers/pcl724.c37
-rw-r--r--drivers/staging/comedi/drivers/pcl725.c21
-rw-r--r--drivers/staging/comedi/drivers/pcl726.c36
-rw-r--r--drivers/staging/comedi/drivers/pcl730.c26
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c65
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c180
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c481
-rw-r--r--drivers/staging/comedi/drivers/pcm3724.c31
-rw-r--r--drivers/staging/comedi/drivers/pcm3730.c22
-rw-r--r--drivers/staging/comedi/drivers/pcmad.c26
-rw-r--r--drivers/staging/comedi/drivers/pcmda12.c26
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c26
-rw-r--r--drivers/staging/comedi/drivers/pcmuio.c26
-rw-r--r--drivers/staging/comedi/drivers/plx9052.h106
-rw-r--r--drivers/staging/comedi/drivers/poc.c34
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c716
-rw-r--r--drivers/staging/comedi/drivers/rtd520.h381
-rw-r--r--drivers/staging/comedi/drivers/rti800.c575
-rw-r--r--drivers/staging/comedi/drivers/rti802.c21
-rw-r--r--drivers/staging/comedi/drivers/s526.c22
-rw-r--r--drivers/staging/comedi/drivers/s626.c1209
-rw-r--r--drivers/staging/comedi/drivers/s626.h101
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c895
-rw-r--r--drivers/staging/comedi/drivers/skel.c136
-rw-r--r--drivers/staging/comedi/drivers/ssv_dnp.c2
-rw-r--r--drivers/staging/comedi/drivers/unioxx5.c64
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c408
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c2
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c12
-rw-r--r--drivers/staging/comedi/kcomedilib/kcomedilib_main.c12
-rw-r--r--drivers/staging/comedi/range.c22
-rw-r--r--drivers/staging/cptm1217/clearpad_tm1217.c16
-rw-r--r--drivers/staging/csr/bh.c2
-rw-r--r--drivers/staging/csr/csr_log.h6
-rw-r--r--drivers/staging/csr/csr_sdio.h24
-rw-r--r--drivers/staging/csr/csr_time.c8
-rw-r--r--drivers/staging/csr/csr_wifi_fsm.h6
-rw-r--r--drivers/staging/csr/csr_wifi_hip_card_sdio.c8
-rw-r--r--drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c10
-rw-r--r--drivers/staging/csr/csr_wifi_hip_chiphelper.h4
-rw-r--r--drivers/staging/csr/csr_wifi_hip_unifi.h20
-rw-r--r--drivers/staging/csr/drv.c4
-rw-r--r--drivers/staging/csr/netdev.c2
-rw-r--r--drivers/staging/csr/sdio_mmc.c3
-rw-r--r--drivers/staging/csr/sme_native.c2
-rw-r--r--drivers/staging/csr/sme_wext.c3
-rw-r--r--drivers/staging/csr/unifi_pdu_processing.c20
-rw-r--r--drivers/staging/csr/unifi_sme.c2
-rw-r--r--drivers/staging/cxt1e1/pmcc4_drv.c1
-rw-r--r--drivers/staging/dgrp/dgrp_common.h2
-rw-r--r--drivers/staging/dgrp/dgrp_dpa_ops.c3
-rw-r--r--drivers/staging/dgrp/dgrp_driver.c6
-rw-r--r--drivers/staging/dgrp/dgrp_mon_ops.c2
-rw-r--r--drivers/staging/dgrp/dgrp_net_ops.c4
-rw-r--r--drivers/staging/dgrp/dgrp_ports_ops.c2
-rw-r--r--drivers/staging/dgrp/dgrp_specproc.c6
-rw-r--r--drivers/staging/dgrp/dgrp_sysfs.c30
-rw-r--r--drivers/staging/dwc2/Kconfig54
-rw-r--r--drivers/staging/dwc2/Makefile25
-rw-r--r--drivers/staging/dwc2/core.c2759
-rw-r--r--drivers/staging/dwc2/core.h662
-rw-r--r--drivers/staging/dwc2/core_intr.c505
-rw-r--r--drivers/staging/dwc2/hcd.c2981
-rw-r--r--drivers/staging/dwc2/hcd.h765
-rw-r--r--drivers/staging/dwc2/hcd_ddma.c1196
-rw-r--r--drivers/staging/dwc2/hcd_intr.c2130
-rw-r--r--drivers/staging/dwc2/hcd_queue.c677
-rw-r--r--drivers/staging/dwc2/hw.h811
-rw-r--r--drivers/staging/dwc2/pci.c180
-rw-r--r--drivers/staging/dwc2/platform.c145
-rw-r--r--drivers/staging/et131x/et131x.c5
-rw-r--r--drivers/staging/fwserial/fwserial.c6
-rw-r--r--drivers/staging/gdm72xx/gdm_qos.c47
-rw-r--r--drivers/staging/gdm72xx/gdm_sdio.c1
-rw-r--r--drivers/staging/gdm72xx/netlink_k.c1
-rw-r--r--drivers/staging/gdm72xx/sdio_boot.c1
-rw-r--r--drivers/staging/iio/Documentation/trigger.txt3
-rw-r--r--drivers/staging/iio/Kconfig8
-rw-r--r--drivers/staging/iio/Makefile2
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c8
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c2
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c8
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c4
-rw-r--r--drivers/staging/iio/accel/adis16220_core.c26
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c9
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c11
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c6
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c5
-rw-r--r--drivers/staging/iio/adc/Kconfig7
-rw-r--r--drivers/staging/iio/adc/Makefile1
-rw-r--r--drivers/staging/iio/adc/ad7280a.c12
-rw-r--r--drivers/staging/iio/adc/ad7291.c10
-rw-r--r--drivers/staging/iio/adc/ad7606_core.c4
-rw-r--r--drivers/staging/iio/adc/ad799x.h7
-rw-r--r--drivers/staging/iio/adc/ad799x_core.c417
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c16
-rw-r--r--drivers/staging/iio/adc/adt7410.c1102
-rw-r--r--drivers/staging/iio/adc/lpc32xx_adc.c2
-rw-r--r--drivers/staging/iio/adc/mxs-lradc.c12
-rw-r--r--drivers/staging/iio/adc/spear_adc.c4
-rw-r--r--drivers/staging/iio/addac/adt7316.c26
-rw-r--r--drivers/staging/iio/cdc/ad7150.c8
-rw-r--r--drivers/staging/iio/cdc/ad7152.c32
-rw-r--r--drivers/staging/iio/cdc/ad7746.c48
-rw-r--r--drivers/staging/iio/gyro/adis16060_core.c11
-rw-r--r--drivers/staging/iio/gyro/adis16130_core.c4
-rw-r--r--drivers/staging/iio/gyro/adis16260_core.c4
-rw-r--r--drivers/staging/iio/iio_simple_dummy.c44
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c10
-rw-r--r--drivers/staging/iio/light/isl29018.c8
-rw-r--r--drivers/staging/iio/light/isl29028.c10
-rw-r--r--drivers/staging/iio/light/tsl2x7x_core.c40
-rw-r--r--drivers/staging/iio/magnetometer/Kconfig11
-rw-r--r--drivers/staging/iio/magnetometer/Makefile1
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c4
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c60
-rw-r--r--drivers/staging/iio/meter/ade7758_trigger.c6
-rw-r--r--drivers/staging/iio/resolver/ad2s1200.c4
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c4
-rw-r--r--drivers/staging/iio/resolver/ad2s90.c2
-rw-r--r--drivers/staging/iio/trigger/iio-trig-bfin-timer.c8
-rw-r--r--drivers/staging/iio/trigger/iio-trig-gpio.c6
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c12
-rw-r--r--drivers/staging/iio/trigger/iio-trig-sysfs.c4
-rw-r--r--drivers/staging/imx-drm/Kconfig7
-rw-r--r--drivers/staging/imx-drm/Makefile1
-rw-r--r--drivers/staging/imx-drm/TODO3
-rw-r--r--drivers/staging/imx-drm/imx-drm-core.c15
-rw-r--r--drivers/staging/imx-drm/imx-drm.h14
-rw-r--r--drivers/staging/imx-drm/imx-tve.c755
-rw-r--r--drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h6
-rw-r--r--drivers/staging/imx-drm/ipu-v3/ipu-common.c3
-rw-r--r--drivers/staging/imx-drm/ipu-v3/ipu-dc.c64
-rw-r--r--drivers/staging/imx-drm/ipu-v3/ipu-di.c100
-rw-r--r--drivers/staging/imx-drm/ipu-v3/ipu-dp.c1
-rw-r--r--drivers/staging/imx-drm/ipuv3-crtc.c11
-rw-r--r--drivers/staging/imx-drm/parallel-display.c12
-rw-r--r--drivers/staging/line6/pod.c3
-rw-r--r--drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt2
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_isif.c6
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.c8
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.h2
-rw-r--r--drivers/staging/net/Kconfig38
-rw-r--r--drivers/staging/net/Makefile5
-rw-r--r--drivers/staging/net/TODO5
-rw-r--r--drivers/staging/net/pc300-falc-lh.h1238
-rw-r--r--drivers/staging/net/pc300.h436
-rw-r--r--drivers/staging/net/pc300_drv.c3670
-rw-r--r--drivers/staging/net/pc300_tty.c1079
-rw-r--r--drivers/staging/netlogic/Kconfig7
-rw-r--r--drivers/staging/netlogic/Makefile1
-rw-r--r--drivers/staging/netlogic/TODO12
-rw-r--r--drivers/staging/netlogic/platform_net.c223
-rw-r--r--drivers/staging/netlogic/platform_net.h46
-rw-r--r--drivers/staging/netlogic/xlr_net.c1114
-rw-r--r--drivers/staging/netlogic/xlr_net.h1099
-rw-r--r--drivers/staging/nvec/Kconfig10
-rw-r--r--drivers/staging/nvec/nvec.c8
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c4
-rw-r--r--drivers/staging/omap-thermal/Makefile5
-rw-r--r--drivers/staging/omap-thermal/TODO28
-rw-r--r--drivers/staging/omap-thermal/omap-bandgap.c1174
-rw-r--r--drivers/staging/omap-thermal/omap-bandgap.h432
-rw-r--r--drivers/staging/omap-thermal/omap-thermal-common.c338
-rw-r--r--drivers/staging/omap-thermal/omap5-thermal.c297
-rw-r--r--drivers/staging/ozwpan/ozcdev.c1
-rw-r--r--drivers/staging/rtl8192u/r8192U_dm.h77
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c8
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.h108
-rw-r--r--drivers/staging/rts5139/rts51x_scsi.c2
-rw-r--r--drivers/staging/rts5139/rts51x_scsi.h1
-rw-r--r--drivers/staging/rts5139/trace.h24
-rw-r--r--drivers/staging/sb105x/sb_mp_register.h4
-rw-r--r--drivers/staging/sb105x/sb_pci_mp.c4
-rw-r--r--drivers/staging/sb105x/sb_pci_mp.h2
-rw-r--r--drivers/staging/sep/sep_crypto.c4
-rw-r--r--drivers/staging/sep/sep_driver_config.h2
-rw-r--r--drivers/staging/sep/sep_main.c9
-rw-r--r--drivers/staging/sep/sep_trace_events.h11
-rw-r--r--drivers/staging/silicom/bp_mod.c10
-rw-r--r--drivers/staging/silicom/bypasslib/bypass.c94
-rw-r--r--drivers/staging/slicoss/slicoss.c133
-rw-r--r--drivers/staging/sm7xxfb/sm7xxfb.c10
-rw-r--r--drivers/staging/speakup/kobjects.c8
-rw-r--r--drivers/staging/speakup/main.c2
-rw-r--r--drivers/staging/speakup/selection.c2
-rw-r--r--drivers/staging/speakup/speakup.h6
-rw-r--r--drivers/staging/speakup/varhandlers.c60
-rw-r--r--drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c2
-rw-r--r--drivers/staging/ti-soc-thermal/Kconfig (renamed from drivers/staging/omap-thermal/Kconfig)22
-rw-r--r--drivers/staging/ti-soc-thermal/Makefile5
-rw-r--r--drivers/staging/ti-soc-thermal/TODO12
-rw-r--r--drivers/staging/ti-soc-thermal/omap4-thermal-data.c (renamed from drivers/staging/omap-thermal/omap4-thermal.c)86
-rw-r--r--drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h175
-rw-r--r--drivers/staging/ti-soc-thermal/omap5-thermal-data.c359
-rw-r--r--drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h200
-rw-r--r--drivers/staging/ti-soc-thermal/ti-bandgap.c1546
-rw-r--r--drivers/staging/ti-soc-thermal/ti-bandgap.h403
-rw-r--r--drivers/staging/ti-soc-thermal/ti-thermal-common.c367
-rw-r--r--drivers/staging/ti-soc-thermal/ti-thermal.h (renamed from drivers/staging/omap-thermal/omap-thermal.h)61
-rw-r--r--drivers/staging/ti-soc-thermal/ti_soc_thermal.txt (renamed from drivers/staging/omap-thermal/omap_bandgap.txt)36
-rw-r--r--drivers/staging/tidspbridge/rmgr/proc.c12
-rw-r--r--drivers/staging/tidspbridge/rmgr/strm.c6
-rw-r--r--drivers/staging/usbip/stub_dev.c38
-rw-r--r--drivers/staging/usbip/stub_main.c34
-rw-r--r--drivers/staging/usbip/stub_rx.c100
-rw-r--r--drivers/staging/usbip/usbip_common.c2
-rw-r--r--drivers/staging/usbip/userspace/README4
-rw-r--r--drivers/staging/usbip/userspace/doc/usbip.84
-rw-r--r--drivers/staging/usbip/userspace/libsrc/names.c521
-rw-r--r--drivers/staging/usbip/userspace/libsrc/names.h24
-rw-r--r--drivers/staging/usbip/userspace/libsrc/usbip_common.c28
-rw-r--r--drivers/staging/usbip/userspace/libsrc/usbip_common.h11
-rw-r--r--drivers/staging/usbip/userspace/libsrc/vhci_driver.c40
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_attach.c12
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_detach.c2
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_list.c12
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_network.c6
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_network.h4
-rw-r--r--drivers/staging/usbip/userspace/src/usbipd.c15
-rw-r--r--drivers/staging/usbip/vhci.h1
-rw-r--r--drivers/staging/usbip/vhci_hcd.c5
-rw-r--r--drivers/staging/usbip/vhci_rx.c56
-rw-r--r--drivers/staging/vme/devices/vme_user.c4
-rw-r--r--drivers/staging/vt6655/80211hdr.h71
-rw-r--r--drivers/staging/vt6655/80211mgr.c1166
-rw-r--r--drivers/staging/vt6655/80211mgr.h698
-rw-r--r--drivers/staging/vt6655/IEEE11h.c115
-rw-r--r--drivers/staging/vt6655/IEEE11h.h6
-rw-r--r--drivers/staging/vt6655/aes_ccmp.c563
-rw-r--r--drivers/staging/vt6655/baseband.c4855
-rw-r--r--drivers/staging/vt6655/baseband.h56
-rw-r--r--drivers/staging/vt6655/bssdb.c2665
-rw-r--r--drivers/staging/vt6655/bssdb.h411
-rw-r--r--drivers/staging/vt6655/card.c2842
-rw-r--r--drivers/staging/vt6655/card.h137
-rw-r--r--drivers/staging/vt6655/channel.c767
-rw-r--r--drivers/staging/vt6655/channel.h16
-rw-r--r--drivers/staging/vt6655/country.h238
-rw-r--r--drivers/staging/vt6655/datarate.c469
-rw-r--r--drivers/staging/vt6655/datarate.h49
-rw-r--r--drivers/staging/vt6655/desc.h504
-rw-r--r--drivers/staging/vt6655/device.h999
-rw-r--r--drivers/staging/vt6655/device_cfg.h31
-rw-r--r--drivers/staging/vt6655/device_main.c4931
-rw-r--r--drivers/staging/vt6655/dpc.c2425
-rw-r--r--drivers/staging/vt6655/dpc.h11
-rw-r--r--drivers/staging/vt6655/hostap.c690
-rw-r--r--drivers/staging/vt6655/hostap.h4
-rw-r--r--drivers/staging/vt6655/iocmd.h246
-rw-r--r--drivers/staging/vt6655/ioctl.c16
-rw-r--r--drivers/staging/vt6655/ioctl.h16
-rw-r--r--drivers/staging/vt6655/iowpa.h54
-rw-r--r--drivers/staging/vt6655/iwctl.c2213
-rw-r--r--drivers/staging/vt6655/iwctl.h208
-rw-r--r--drivers/staging/vt6655/key.c1150
-rw-r--r--drivers/staging/vt6655/key.h171
-rw-r--r--drivers/staging/vt6655/mac.c1657
-rw-r--r--drivers/staging/vt6655/mac.h773
-rw-r--r--drivers/staging/vt6655/mib.c698
-rw-r--r--drivers/staging/vt6655/mib.h507
-rw-r--r--drivers/staging/vt6655/michael.c164
-rw-r--r--drivers/staging/vt6655/michael.h8
-rw-r--r--drivers/staging/vt6655/power.c484
-rw-r--r--drivers/staging/vt6655/power.h33
-rw-r--r--drivers/staging/vt6655/rc4.c78
-rw-r--r--drivers/staging/vt6655/rc4.h6
-rw-r--r--drivers/staging/vt6655/rf.c1480
-rw-r--r--drivers/staging/vt6655/rf.h26
-rw-r--r--drivers/staging/vt6655/rxtx.c5545
-rw-r--r--drivers/staging/vt6655/rxtx.h56
-rw-r--r--drivers/staging/vt6655/srom.c269
-rw-r--r--drivers/staging/vt6655/srom.h60
-rw-r--r--drivers/staging/vt6655/tcrc.c163
-rw-r--r--drivers/staging/vt6655/tcrc.h3
-rw-r--r--drivers/staging/vt6655/tether.c50
-rw-r--r--drivers/staging/vt6655/tether.h42
-rw-r--r--drivers/staging/vt6655/tkip.c331
-rw-r--r--drivers/staging/vt6655/tkip.h15
-rw-r--r--drivers/staging/vt6655/tmacro.h2
-rw-r--r--drivers/staging/vt6655/ttype.h14
-rw-r--r--drivers/staging/vt6655/upc.h187
-rw-r--r--drivers/staging/vt6655/vntwifi.c925
-rw-r--r--drivers/staging/vt6655/vntwifi.h278
-rw-r--r--drivers/staging/vt6655/wcmd.c1747
-rw-r--r--drivers/staging/vt6655/wcmd.h118
-rw-r--r--drivers/staging/vt6655/wctl.c244
-rw-r--r--drivers/staging/vt6655/wctl.h76
-rw-r--r--drivers/staging/vt6655/wmgr.c8006
-rw-r--r--drivers/staging/vt6655/wmgr.h552
-rw-r--r--drivers/staging/vt6655/wpa.c340
-rw-r--r--drivers/staging/vt6655/wpa.h23
-rw-r--r--drivers/staging/vt6655/wpa2.c504
-rw-r--r--drivers/staging/vt6655/wpa2.h29
-rw-r--r--drivers/staging/vt6655/wpactl.c903
-rw-r--r--drivers/staging/vt6655/wpactl.h8
-rw-r--r--drivers/staging/vt6655/wroute.c257
-rw-r--r--drivers/staging/vt6655/wroute.h5
-rw-r--r--drivers/staging/vt6656/80211hdr.h130
-rw-r--r--drivers/staging/vt6656/80211mgr.c224
-rw-r--r--drivers/staging/vt6656/80211mgr.h335
-rw-r--r--drivers/staging/vt6656/TODO2
-rw-r--r--drivers/staging/vt6656/aes_ccmp.c131
-rw-r--r--drivers/staging/vt6656/aes_ccmp.h13
-rw-r--r--drivers/staging/vt6656/baseband.c183
-rw-r--r--drivers/staging/vt6656/baseband.h23
-rw-r--r--drivers/staging/vt6656/bssdb.c70
-rw-r--r--drivers/staging/vt6656/bssdb.h124
-rw-r--r--drivers/staging/vt6656/card.c127
-rw-r--r--drivers/staging/vt6656/card.h18
-rw-r--r--drivers/staging/vt6656/channel.c53
-rw-r--r--drivers/staging/vt6656/channel.h14
-rw-r--r--drivers/staging/vt6656/control.c10
-rw-r--r--drivers/staging/vt6656/control.h10
-rw-r--r--drivers/staging/vt6656/country.h1
-rw-r--r--drivers/staging/vt6656/datarate.c85
-rw-r--r--drivers/staging/vt6656/datarate.h27
-rw-r--r--drivers/staging/vt6656/desc.h230
-rw-r--r--drivers/staging/vt6656/device.h56
-rw-r--r--drivers/staging/vt6656/device_cfg.h2
-rw-r--r--drivers/staging/vt6656/dpc.c262
-rw-r--r--drivers/staging/vt6656/dpc.h9
-rw-r--r--drivers/staging/vt6656/firmware.c17
-rw-r--r--drivers/staging/vt6656/firmware.h9
-rw-r--r--drivers/staging/vt6656/hostap.c29
-rw-r--r--drivers/staging/vt6656/hostap.h9
-rw-r--r--drivers/staging/vt6656/int.c27
-rw-r--r--drivers/staging/vt6656/int.h46
-rw-r--r--drivers/staging/vt6656/iocmd.h18
-rw-r--r--drivers/staging/vt6656/iowpa.h13
-rw-r--r--drivers/staging/vt6656/iwctl.c27
-rw-r--r--drivers/staging/vt6656/iwctl.h8
-rw-r--r--drivers/staging/vt6656/key.c111
-rw-r--r--drivers/staging/vt6656/key.h43
-rw-r--r--drivers/staging/vt6656/mac.c132
-rw-r--r--drivers/staging/vt6656/mac.h19
-rw-r--r--drivers/staging/vt6656/main_usb.c63
-rw-r--r--drivers/staging/vt6656/mib.c131
-rw-r--r--drivers/staging/vt6656/mib.h294
-rw-r--r--drivers/staging/vt6656/michael.c49
-rw-r--r--drivers/staging/vt6656/michael.h12
-rw-r--r--drivers/staging/vt6656/power.c13
-rw-r--r--drivers/staging/vt6656/power.h12
-rw-r--r--drivers/staging/vt6656/rc4.c22
-rw-r--r--drivers/staging/vt6656/rc4.h10
-rw-r--r--drivers/staging/vt6656/rf.c49
-rw-r--r--drivers/staging/vt6656/rf.h10
-rw-r--r--drivers/staging/vt6656/rndis.h90
-rw-r--r--drivers/staging/vt6656/rxtx.c610
-rw-r--r--drivers/staging/vt6656/rxtx.h691
-rw-r--r--drivers/staging/vt6656/srom.h71
-rw-r--r--drivers/staging/vt6656/tcrc.c28
-rw-r--r--drivers/staging/vt6656/tcrc.h20
-rw-r--r--drivers/staging/vt6656/tether.c53
-rw-r--r--drivers/staging/vt6656/tether.h61
-rw-r--r--drivers/staging/vt6656/tkip.c37
-rw-r--r--drivers/staging/vt6656/tkip.h22
-rw-r--r--drivers/staging/vt6656/tmacro.h14
-rw-r--r--drivers/staging/vt6656/ttype.h55
-rw-r--r--drivers/staging/vt6656/usbpipe.c29
-rw-r--r--drivers/staging/vt6656/usbpipe.h9
-rw-r--r--drivers/staging/vt6656/wcmd.c63
-rw-r--r--drivers/staging/vt6656/wcmd.h18
-rw-r--r--drivers/staging/vt6656/wctl.c56
-rw-r--r--drivers/staging/vt6656/wctl.h49
-rw-r--r--drivers/staging/vt6656/wmgr.c228
-rw-r--r--drivers/staging/vt6656/wmgr.h35
-rw-r--r--drivers/staging/vt6656/wpa.c32
-rw-r--r--drivers/staging/vt6656/wpa.h16
-rw-r--r--drivers/staging/vt6656/wpa2.c165
-rw-r--r--drivers/staging/vt6656/wpa2.h17
-rw-r--r--drivers/staging/vt6656/wpactl.c33
-rw-r--r--drivers/staging/vt6656/wpactl.h10
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c51
-rw-r--r--drivers/staging/wlan-ng/prism2usb.c12
-rw-r--r--drivers/staging/xgifb/vb_def.h4
-rw-r--r--drivers/staging/xgifb/vb_init.c64
-rw-r--r--drivers/staging/xgifb/vb_setmode.c4
-rw-r--r--drivers/staging/xgifb/vb_struct.h16
-rw-r--r--drivers/staging/xgifb/vb_table.h98
-rw-r--r--drivers/staging/zcache/Kconfig16
-rw-r--r--drivers/staging/zcache/Makefile2
-rw-r--r--drivers/staging/zcache/TODO9
-rw-r--r--drivers/staging/zcache/debug.c107
-rw-r--r--drivers/staging/zcache/debug.h305
-rw-r--r--drivers/staging/zcache/ramster/debug.c66
-rw-r--r--drivers/staging/zcache/ramster/debug.h145
-rw-r--r--drivers/staging/zcache/ramster/ramster.c141
-rw-r--r--drivers/staging/zcache/zbud.c7
-rw-r--r--drivers/staging/zcache/zcache-main.c526
-rw-r--r--drivers/staging/zram/zram_drv.c5
-rw-r--r--drivers/staging/zsmalloc/Kconfig2
-rw-r--r--drivers/staging/zsmalloc/zsmalloc-main.c7
-rw-r--r--include/linux/iio/adc/ad_sigma_delta.h6
-rw-r--r--include/linux/iio/common/st_sensors.h5
-rw-r--r--include/linux/iio/iio.h79
-rw-r--r--include/linux/iio/imu/adis.h34
-rw-r--r--include/linux/iio/trigger.h26
627 files changed, 65068 insertions, 76244 deletions
diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
index c63097d6afe..16769d9cedd 100644
--- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
@@ -14,9 +14,19 @@ Required properties:
- atmel,adc-status-register: Offset of the Interrupt Status Register
- atmel,adc-trigger-register: Offset of the Trigger Register
- atmel,adc-vref: Reference voltage in millivolts for the conversions
+ - atmel,adc-res: List of resolution in bits supported by the ADC. List size
+ must be two at least.
+ - atmel,adc-res-names: Contains one identifier string for each resolution
+ in atmel,adc-res property. "lowres" and "highres"
+ identifiers are required.
Optional properties:
- atmel,adc-use-external: Boolean to enable of external triggers
+ - atmel,adc-use-res: String corresponding to an identifier from
+ atmel,adc-res-names property. If not specified, the highest
+ resolution will be used.
+ - atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion
+ - atmel,adc-sample-hold-time: Sample and Hold Time in microseconds
Optional trigger Nodes:
- Required properties:
@@ -40,6 +50,9 @@ adc0: adc@fffb0000 {
atmel,adc-trigger-register = <0x08>;
atmel,adc-use-external;
atmel,adc-vref = <3300>;
+ atmel,adc-res = <8 10>;
+ atmel,adc-res-names = "lowres", "highres";
+ atmel,adc-use-res = "lowres";
trigger@0 {
trigger-name = "external-rising";
diff --git a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
new file mode 100644
index 00000000000..47ada1dff21
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
@@ -0,0 +1,60 @@
+Samsung Exynos Analog to Digital Converter bindings
+
+The devicetree bindings are for the new ADC driver written for
+Exynos4 and upward SoCs from Samsung.
+
+New driver handles the following
+1. Supports ADC IF found on EXYNOS4412/EXYNOS5250
+ and future SoCs from Samsung
+2. Add ADC driver under iio/adc framework
+3. Also adds the Documentation for device tree bindings
+
+Required properties:
+- compatible: Must be "samsung,exynos-adc-v1"
+ for exynos4412/5250 controllers.
+ Must be "samsung,exynos-adc-v2" for
+ future controllers.
+- reg: Contains ADC register address range (base address and
+ length) and the address of the phy enable register.
+- interrupts: Contains the interrupt information for the timer. The
+ format is being dependent on which interrupt controller
+ the Samsung device uses.
+- #io-channel-cells = <1>; As ADC has multiple outputs
+- clocks From common clock binding: handle to adc clock.
+- clock-names From common clock binding: Shall be "adc".
+- vdd-supply VDD input supply.
+
+Note: child nodes can be added for auto probing from device tree.
+
+Example: adding device info in dtsi file
+
+adc: adc@12D10000 {
+ compatible = "samsung,exynos-adc-v1";
+ reg = <0x12D10000 0x100>, <0x10040718 0x4>;
+ interrupts = <0 106 0>;
+ #io-channel-cells = <1>;
+ io-channel-ranges;
+
+ clocks = <&clock 303>;
+ clock-names = "adc";
+
+ vdd-supply = <&buck5_reg>;
+};
+
+
+Example: Adding child nodes in dts file
+
+adc@12D10000 {
+
+ /* NTC thermistor is a hwmon device */
+ ncp15wb473@0 {
+ compatible = "ntc,ncp15wb473";
+ pullup-uV = <1800000>;
+ pullup-ohm = <47000>;
+ pulldown-ohm = <0>;
+ io-channels = <&adc 4>;
+ };
+};
+
+Note: Does not apply to ADC driver under arch/arm/plat-samsung/
+Note: The child node can be added under the adc node or separately.
diff --git a/Documentation/devicetree/bindings/iio/iio-bindings.txt b/Documentation/devicetree/bindings/iio/iio-bindings.txt
new file mode 100644
index 00000000000..0b447d9ad19
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/iio-bindings.txt
@@ -0,0 +1,97 @@
+This binding is derived from clock bindings, and based on suggestions
+from Lars-Peter Clausen [1].
+
+Sources of IIO channels can be represented by any node in the device
+tree. Those nodes are designated as IIO providers. IIO consumer
+nodes use a phandle and IIO specifier pair to connect IIO provider
+outputs to IIO inputs. Similar to the gpio specifiers, an IIO
+specifier is an array of one or more cells identifying the IIO
+output on a device. The length of an IIO specifier is defined by the
+value of a #io-channel-cells property in the IIO provider node.
+
+[1] http://marc.info/?l=linux-iio&m=135902119507483&w=2
+
+==IIO providers==
+
+Required properties:
+#io-channel-cells: Number of cells in an IIO specifier; Typically 0 for nodes
+ with a single IIO output and 1 for nodes with multiple
+ IIO outputs.
+
+Example for a simple configuration with no trigger:
+
+ adc: voltage-sensor@35 {
+ compatible = "maxim,max1139";
+ reg = <0x35>;
+ #io-channel-cells = <1>;
+ };
+
+Example for a configuration with trigger:
+
+ adc@35 {
+ compatible = "some-vendor,some-adc";
+ reg = <0x35>;
+
+ adc1: iio-device@0 {
+ #io-channel-cells = <1>;
+ /* other properties */
+ };
+ adc2: iio-device@1 {
+ #io-channel-cells = <1>;
+ /* other properties */
+ };
+ };
+
+==IIO consumers==
+
+Required properties:
+io-channels: List of phandle and IIO specifier pairs, one pair
+ for each IIO input to the device. Note: if the
+ IIO provider specifies '0' for #io-channel-cells,
+ then only the phandle portion of the pair will appear.
+
+Optional properties:
+io-channel-names:
+ List of IIO input name strings sorted in the same
+ order as the io-channels property. Consumers drivers
+ will use io-channel-names to match IIO input names
+ with IIO specifiers.
+io-channel-ranges:
+ Empty property indicating that child nodes can inherit named
+ IIO channels from this node. Useful for bus nodes to provide
+ and IIO channel to their children.
+
+For example:
+
+ device {
+ io-channels = <&adc 1>, <&ref 0>;
+ io-channel-names = "vcc", "vdd";
+ };
+
+This represents a device with two IIO inputs, named "vcc" and "vdd".
+The vcc channel is connected to output 1 of the &adc device, and the
+vdd channel is connected to output 0 of the &ref device.
+
+==Example==
+
+ adc: max1139@35 {
+ compatible = "maxim,max1139";
+ reg = <0x35>;
+ #io-channel-cells = <1>;
+ };
+
+ ...
+
+ iio_hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 0>, <&adc 1>, <&adc 2>,
+ <&adc 3>, <&adc 4>, <&adc 5>,
+ <&adc 6>, <&adc 7>, <&adc 8>,
+ <&adc 9>;
+ };
+
+ some_consumer {
+ compatible = "some-consumer";
+ io-channels = <&adc 10>, <&adc 11>;
+ io-channel-names = "adc1", "adc2";
+ };
diff --git a/Documentation/devicetree/bindings/staging/dwc2.txt b/Documentation/devicetree/bindings/staging/dwc2.txt
new file mode 100644
index 00000000000..1a1b7cfa484
--- /dev/null
+++ b/Documentation/devicetree/bindings/staging/dwc2.txt
@@ -0,0 +1,15 @@
+Platform DesignWare HS OTG USB 2.0 controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "snps,dwc2"
+- reg : Should contain 1 register range (address and length)
+- interrupts : Should contain 1 interrupt
+
+Example:
+
+ usb@101c0000 {
+ compatible = "ralink,rt3050-usb, snps,dwc2";
+ reg = <0x101c0000 40000>;
+ interrupts = <18>;
+ };
diff --git a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
index 07654f0338b..8071ac20d4b 100644
--- a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
+++ b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
@@ -26,7 +26,7 @@ Required properties:
- crtc: the crtc this display is connected to, see below
Optional properties:
- interface_pix_fmt: How this display is connected to the
- crtc. Currently supported types: "rgb24", "rgb565"
+ crtc. Currently supported types: "rgb24", "rgb565", "bgr666"
- edid: verbatim EDID data block describing attached display.
- ddc: phandle describing the i2c bus handling the display data
channel
diff --git a/MAINTAINERS b/MAINTAINERS
index 8ba3b484d82..f053dd14400 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2459,6 +2459,12 @@ M: Matthew Garrett <mjg59@srcf.ucam.org>
S: Maintained
F: drivers/platform/x86/dell-wmi.c
+DESIGNWARE USB2 DRD IP DRIVER
+M: Paul Zimmerman <paulz@synopsys.com>
+L: linux-usb@vger.kernel.org
+S: Maintained
+F: drivers/staging/dwc2/
+
DESIGNWARE USB3 DRD IP DRIVER
M: Felipe Balbi <balbi@ti.com>
L: linux-usb@vger.kernel.org
@@ -7933,6 +7939,12 @@ T: git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
S: Maintained
F: drivers/platform/x86/thinkpad_acpi.c
+TI BANDGAP AND THERMAL DRIVER
+M: Eduardo Valentin <eduardo.valentin@ti.com>
+L: linux-pm@vger.kernel.org
+S: Maintained
+F: drivers/staging/omap-thermal/
+
TI FLASH MEDIA INTERFACE DRIVER
M: Alex Dubov <oakad@yahoo.com>
S: Maintained
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4f29117651b..f61d98a6296 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -519,6 +519,15 @@ config SENSORS_IBMPEX
This driver can also be built as a module. If so, the module
will be called ibmpex.
+config SENSORS_IIO_HWMON
+ tristate "Hwmon driver that uses channels specified via iio maps"
+ depends on IIO
+ help
+ This is a platform driver that in combination with a suitable
+ map allows IIO devices to provide basic hwmon functionality
+ for those channels specified in the map. This map can be provided
+ either via platform data or the device tree bindings.
+
config SENSORS_IT87
tristate "ITE IT87xx and compatibles"
depends on !PPC
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 5c71fe6a9c7..c51b0dc35dc 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
+obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o
obj-$(CONFIG_SENSORS_INA209) += ina209.o
obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c
index 93af756ba48..aafa4531b96 100644
--- a/drivers/staging/iio/iio_hwmon.c
+++ b/drivers/hwmon/iio_hwmon.c
@@ -13,6 +13,7 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/hwmon.h>
+#include <linux/of.h>
#include <linux/hwmon-sysfs.h>
#include <linux/iio/consumer.h>
#include <linux/iio/types.h>
@@ -58,7 +59,12 @@ static ssize_t iio_hwmon_read_val(struct device *dev,
static ssize_t show_name(struct device *dev, struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "iio_hwmon\n");
+ const char *name = "iio_hwmon";
+
+ if (dev->of_node && dev->of_node->name)
+ name = dev->of_node->name;
+
+ return sprintf(buf, "%s\n", name);
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index dd8ea428493..bbcbd7101f3 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -60,28 +60,28 @@ static const struct iio_chan_spec accel_3d_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_X,
}, {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_Y,
}, {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_Z,
}
};
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index c2229a521ab..7229645bf1d 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -177,8 +177,8 @@ error_ret:
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = KXSD9_REG_##axis, \
}
@@ -186,7 +186,7 @@ static const struct iio_chan_spec kxsd9_channels[] = {
KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z),
{
.type = IIO_VOLTAGE,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.indexed = 1,
.address = KXSD9_REG_AUX,
}
diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c
index 6bd82c7f769..d9b350756f9 100644
--- a/drivers/iio/accel/st_accel_buffer.c
+++ b/drivers/iio/accel/st_accel_buffer.c
@@ -25,7 +25,7 @@
int st_accel_trig_set_state(struct iio_trigger *trig, bool state)
{
- struct iio_dev *indio_dev = trig->private_data;
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
return st_sensors_set_dataready_irq(indio_dev, state);
}
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index e372257a849..ab0767e6727 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -30,6 +30,18 @@ config AD7298
To compile this driver as a module, choose M here: the
module will be called ad7298.
+config AD7923
+ tristate "Analog Devices AD7923 and similar ADCs driver"
+ depends on SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for Analog Devices
+ AD7904, AD7914, AD7923, AD7924 4 Channel ADCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7923.
+
config AD7791
tristate "Analog Devices AD7791 ADC driver"
depends on SPI
@@ -91,6 +103,14 @@ config AT91_ADC
help
Say yes here to build support for Atmel AT91 ADC.
+config EXYNOS_ADC
+ bool "Exynos ADC driver support"
+ depends on OF
+ help
+ Core support for the ADC block found in the Samsung EXYNOS series
+ of SoCs for drivers such as the touchscreen and hwmon to use to share
+ this resource.
+
config LP8788_ADC
bool "LP8788 ADC driver"
depends on MFD_LP8788
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 2d5f10080d8..0a825bed43f 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -5,11 +5,13 @@
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AD7298) += ad7298.o
+obj-$(CONFIG_AD7923) += ad7923.o
obj-$(CONFIG_AD7476) += ad7476.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
+obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index bbad9b94cd7..c2744a75c3b 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -201,9 +201,9 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
.indexed = 1, \
.channel = (_chan), \
.address = (_chan), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT \
- | IIO_CHAN_INFO_SCALE_SHARED_BIT \
- | IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
+ | BIT(IIO_CHAN_INFO_OFFSET), \
.scan_index = (_chan), \
.scan_type = { \
.sign = (_sign), \
@@ -249,9 +249,9 @@ static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(s, 's');
.channel = (_chan) * 2, \
.channel2 = (_chan) * 2 + 1, \
.address = (_chan), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT \
- | IIO_CHAN_INFO_SCALE_SHARED_BIT \
- | IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
+ | BIT(IIO_CHAN_INFO_OFFSET), \
.scan_index = (_chan), \
.scan_type = { \
.sign = _sign, \
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index b34d754994d..03b77189dbf 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -63,8 +63,8 @@ struct ad7298_state {
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = index, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = index, \
.scan_index = index, \
.scan_type = { \
@@ -80,9 +80,9 @@ static const struct iio_chan_spec ad7298_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
.address = AD7298_CH_TEMP,
.scan_index = -1,
.scan_type = {
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 1491fa6debb..2e98bef4af6 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -140,12 +140,12 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
-#define _AD7476_CHAN(bits, _shift, _info_mask) \
+#define _AD7476_CHAN(bits, _shift, _info_mask_sep) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
- .info_mask = _info_mask | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask_separate = _info_mask_sep, \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.scan_type = { \
.sign = 'u', \
.realbits = (bits), \
@@ -156,9 +156,9 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
}
#define AD7476_CHAN(bits) _AD7476_CHAN((bits), 13 - (bits), \
- IIO_CHAN_INFO_RAW_SEPARATE_BIT)
+ BIT(IIO_CHAN_INFO_RAW))
#define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \
- IIO_CHAN_INFO_RAW_SEPARATE_BIT)
+ BIT(IIO_CHAN_INFO_RAW))
#define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0)
static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index a33d5cd1a53..dd15a5b0f70 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -207,8 +207,8 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.address = 1,
.scan_index = 1,
.scan_type = IIO_ST('u', 12, 16, 0),
@@ -217,8 +217,8 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.address = 0,
.scan_index = 0,
.scan_type = IIO_ST('u', 12, 16, 0),
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
new file mode 100644
index 00000000000..97fa0d3dc4a
--- /dev/null
+++ b/drivers/iio/adc/ad7923.c
@@ -0,0 +1,383 @@
+/*
+ * AD7904/AD7914/AD7923/AD7924 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc (from AD7923 Driver)
+ * Copyright 2012 CS Systemes d'Information
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/interrupt.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>
+
+#define AD7923_WRITE_CR (1 << 11) /* write control register */
+#define AD7923_RANGE (1 << 1) /* range to REFin */
+#define AD7923_CODING (1 << 0) /* coding is straight binary */
+#define AD7923_PM_MODE_AS (1) /* auto shutdown */
+#define AD7923_PM_MODE_FS (2) /* full shutdown */
+#define AD7923_PM_MODE_OPS (3) /* normal operation */
+#define AD7923_CHANNEL_0 (0) /* analog input 0 */
+#define AD7923_CHANNEL_1 (1) /* analog input 1 */
+#define AD7923_CHANNEL_2 (2) /* analog input 2 */
+#define AD7923_CHANNEL_3 (3) /* analog input 3 */
+#define AD7923_SEQUENCE_OFF (0) /* no sequence fonction */
+#define AD7923_SEQUENCE_PROTECT (2) /* no interrupt write cycle */
+#define AD7923_SEQUENCE_ON (3) /* continuous sequence */
+
+#define AD7923_MAX_CHAN 4
+
+#define AD7923_PM_MODE_WRITE(mode) (mode << 4) /* write mode */
+#define AD7923_CHANNEL_WRITE(channel) (channel << 6) /* write channel */
+#define AD7923_SEQUENCE_WRITE(sequence) (((sequence & 1) << 3) \
+ + ((sequence & 2) << 9))
+ /* write sequence fonction */
+/* left shift for CR : bit 11 transmit in first */
+#define AD7923_SHIFT_REGISTER 4
+
+/* val = value, dec = left shift, bits = number of bits of the mask */
+#define EXTRACT(val, dec, bits) ((val >> dec) & ((1 << bits) - 1))
+
+struct ad7923_state {
+ struct spi_device *spi;
+ struct spi_transfer ring_xfer[5];
+ struct spi_transfer scan_single_xfer[2];
+ struct spi_message ring_msg;
+ struct spi_message scan_single_msg;
+
+ struct regulator *reg;
+
+ unsigned int settings;
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ __be16 rx_buf[4] ____cacheline_aligned;
+ __be16 tx_buf[4];
+};
+
+struct ad7923_chip_info {
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+};
+
+enum ad7923_id {
+ AD7904,
+ AD7914,
+ AD7924,
+};
+
+#define AD7923_V_CHAN(index, bits) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = index, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .address = index, \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (bits), \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define DECLARE_AD7923_CHANNELS(name, bits) \
+const struct iio_chan_spec name ## _channels[] = { \
+ AD7923_V_CHAN(0, bits), \
+ AD7923_V_CHAN(1, bits), \
+ AD7923_V_CHAN(2, bits), \
+ AD7923_V_CHAN(3, bits), \
+ IIO_CHAN_SOFT_TIMESTAMP(4), \
+}
+
+static DECLARE_AD7923_CHANNELS(ad7904, 8);
+static DECLARE_AD7923_CHANNELS(ad7914, 10);
+static DECLARE_AD7923_CHANNELS(ad7924, 12);
+
+static const struct ad7923_chip_info ad7923_chip_info[] = {
+ [AD7904] = {
+ .channels = ad7904_channels,
+ .num_channels = ARRAY_SIZE(ad7904_channels),
+ },
+ [AD7914] = {
+ .channels = ad7914_channels,
+ .num_channels = ARRAY_SIZE(ad7914_channels),
+ },
+ [AD7924] = {
+ .channels = ad7924_channels,
+ .num_channels = ARRAY_SIZE(ad7924_channels),
+ },
+};
+
+/**
+ * ad7923_update_scan_mode() setup the spi transfer buffer for the new scan mask
+ **/
+static int ad7923_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *active_scan_mask)
+{
+ struct ad7923_state *st = iio_priv(indio_dev);
+ int i, cmd, len;
+
+ len = 0;
+ for_each_set_bit(i, active_scan_mask, AD7923_MAX_CHAN) {
+ cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(i) |
+ AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) |
+ st->settings;
+ cmd <<= AD7923_SHIFT_REGISTER;
+ st->tx_buf[len++] = cpu_to_be16(cmd);
+ }
+ /* build spi ring message */
+ st->ring_xfer[0].tx_buf = &st->tx_buf[0];
+ st->ring_xfer[0].len = len;
+ st->ring_xfer[0].cs_change = 1;
+
+ spi_message_init(&st->ring_msg);
+ spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
+
+ for (i = 0; i < len; i++) {
+ st->ring_xfer[i + 1].rx_buf = &st->rx_buf[i];
+ st->ring_xfer[i + 1].len = 2;
+ st->ring_xfer[i + 1].cs_change = 1;
+ spi_message_add_tail(&st->ring_xfer[i + 1], &st->ring_msg);
+ }
+ /* make sure last transfer cs_change is not set */
+ st->ring_xfer[i + 1].cs_change = 0;
+
+ return 0;
+}
+
+/**
+ * ad7923_trigger_handler() bh of trigger launched polling to ring buffer
+ *
+ * Currently there is no option in this driver to disable the saving of
+ * timestamps within the ring.
+ **/
+static irqreturn_t ad7923_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad7923_state *st = iio_priv(indio_dev);
+ s64 time_ns = 0;
+ int b_sent;
+
+ b_sent = spi_sync(st->spi, &st->ring_msg);
+ if (b_sent)
+ goto done;
+
+ if (indio_dev->scan_timestamp) {
+ time_ns = iio_get_time_ns();
+ memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
+ &time_ns, sizeof(time_ns));
+ }
+
+ iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf);
+
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int ad7923_scan_direct(struct ad7923_state *st, unsigned ch)
+{
+ int ret, cmd;
+
+ cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(ch) |
+ AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) |
+ st->settings;
+ cmd <<= AD7923_SHIFT_REGISTER;
+ st->tx_buf[0] = cpu_to_be16(cmd);
+
+ ret = spi_sync(st->spi, &st->scan_single_msg);
+ if (ret)
+ return ret;
+
+ return be16_to_cpu(st->rx_buf[0]);
+}
+
+static int ad7923_get_range(struct ad7923_state *st)
+{
+ int vref;
+
+ vref = regulator_get_voltage(st->reg);
+ if (vref < 0)
+ return vref;
+
+ vref /= 1000;
+
+ if (!(st->settings & AD7923_RANGE))
+ vref *= 2;
+
+ return vref;
+}
+
+static int ad7923_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
+{
+ int ret;
+ struct ad7923_state *st = iio_priv(indio_dev);
+
+ switch (m) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&indio_dev->mlock);
+ if (iio_buffer_enabled(indio_dev))
+ ret = -EBUSY;
+ else
+ ret = ad7923_scan_direct(st, chan->address);
+ mutex_unlock(&indio_dev->mlock);
+
+ if (ret < 0)
+ return ret;
+
+ if (chan->address == EXTRACT(ret, 12, 4))
+ *val = EXTRACT(ret, 0, 12);
+ else
+ return -EIO;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ ret = ad7923_get_range(st);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ *val2 = chan->scan_type.realbits;
+ return IIO_VAL_FRACTIONAL_LOG2;
+ }
+ return -EINVAL;
+}
+
+static const struct iio_info ad7923_info = {
+ .read_raw = &ad7923_read_raw,
+ .update_scan_mode = ad7923_update_scan_mode,
+ .driver_module = THIS_MODULE,
+};
+
+static int ad7923_probe(struct spi_device *spi)
+{
+ struct ad7923_state *st;
+ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+ const struct ad7923_chip_info *info;
+ int ret;
+
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ spi_set_drvdata(spi, indio_dev);
+
+ st->spi = spi;
+ st->settings = AD7923_CODING | AD7923_RANGE |
+ AD7923_PM_MODE_WRITE(AD7923_PM_MODE_OPS);
+
+ info = &ad7923_chip_info[spi_get_device_id(spi)->driver_data];
+
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = info->channels;
+ indio_dev->num_channels = info->num_channels;
+ indio_dev->info = &ad7923_info;
+
+ /* Setup default message */
+
+ st->scan_single_xfer[0].tx_buf = &st->tx_buf[0];
+ st->scan_single_xfer[0].len = 2;
+ st->scan_single_xfer[0].cs_change = 1;
+ st->scan_single_xfer[1].rx_buf = &st->rx_buf[0];
+ st->scan_single_xfer[1].len = 2;
+
+ spi_message_init(&st->scan_single_msg);
+ spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
+ spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
+
+ st->reg = regulator_get(&spi->dev, "refin");
+ if (IS_ERR(st->reg)) {
+ ret = PTR_ERR(st->reg);
+ goto error_free;
+ }
+ ret = regulator_enable(st->reg);
+ if (ret)
+ goto error_put_reg;
+
+ ret = iio_triggered_buffer_setup(indio_dev, NULL,
+ &ad7923_trigger_handler, NULL);
+ if (ret)
+ goto error_disable_reg;
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_cleanup_ring;
+
+ return 0;
+
+error_cleanup_ring:
+ iio_triggered_buffer_cleanup(indio_dev);
+error_disable_reg:
+ regulator_disable(st->reg);
+error_put_reg:
+ regulator_put(st->reg);
+error_free:
+ iio_device_free(indio_dev);
+
+ return ret;
+}
+
+static int ad7923_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad7923_state *st = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+ regulator_disable(st->reg);
+ regulator_put(st->reg);
+ iio_device_free(indio_dev);
+
+ return 0;
+}
+
+static const struct spi_device_id ad7923_id[] = {
+ {"ad7904", AD7904},
+ {"ad7914", AD7914},
+ {"ad7923", AD7924},
+ {"ad7924", AD7924},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, ad7923_id);
+
+static struct spi_driver ad7923_driver = {
+ .driver = {
+ .name = "ad7923",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad7923_probe,
+ .remove = ad7923_remove,
+ .id_table = ad7923_id,
+};
+module_spi_driver(ad7923_driver);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_AUTHOR("Patrick Vasseur <patrick.vasseur@c-s.fr>");
+MODULE_DESCRIPTION("Analog Devices AD7904/AD7914/AD7923/AD7924 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index afe6d78c8ff..f0d6335ae08 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -470,7 +470,7 @@ static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
disable_irq_nosync(sigma_delta->spi->irq);
}
sigma_delta->trig->dev.parent = &sigma_delta->spi->dev;
- sigma_delta->trig->private_data = sigma_delta;
+ iio_trigger_set_drvdata(sigma_delta->trig, sigma_delta);
ret = iio_trigger_register(sigma_delta->trig);
if (ret)
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 83c836ba600..e5b88d5d3b5 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -52,11 +52,15 @@ struct at91_adc_state {
void __iomem *reg_base;
struct at91_adc_reg_desc *registers;
u8 startup_time;
+ u8 sample_hold_time;
+ bool sleep_mode;
struct iio_trigger **trig;
struct at91_adc_trigger *trigger_list;
u32 trigger_number;
bool use_external;
u32 vref_mv;
+ u32 res; /* resolution used for convertions */
+ bool low_res; /* the resolution corresponds to the lowest one */
wait_queue_head_t wq_data_avail;
};
@@ -138,10 +142,10 @@ static int at91_adc_channel_init(struct iio_dev *idev)
chan->channel = bit;
chan->scan_index = idx;
chan->scan_type.sign = 'u';
- chan->scan_type.realbits = 10;
+ chan->scan_type.realbits = st->res;
chan->scan_type.storagebits = 16;
- chan->info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_RAW_SEPARATE_BIT;
+ chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+ chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
idx++;
}
timestamp = chan_array + idx;
@@ -188,7 +192,7 @@ static u8 at91_adc_get_trigger_value_by_name(struct iio_dev *idev,
static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
{
- struct iio_dev *idev = trig->private_data;
+ struct iio_dev *idev = iio_trigger_get_drvdata(trig);
struct at91_adc_state *st = iio_priv(idev);
struct iio_buffer *buffer = idev->buffer;
struct at91_adc_reg_desc *reg = st->registers;
@@ -254,7 +258,7 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *idev,
return NULL;
trig->dev.parent = idev->dev.parent;
- trig->private_data = idev;
+ iio_trigger_set_drvdata(trig, idev);
trig->ops = &at91_adc_trigger_ops;
ret = iio_trigger_register(trig);
@@ -372,6 +376,59 @@ static int at91_adc_read_raw(struct iio_dev *idev,
return -EINVAL;
}
+static int at91_adc_of_get_resolution(struct at91_adc_state *st,
+ struct platform_device *pdev)
+{
+ struct iio_dev *idev = iio_priv_to_dev(st);
+ struct device_node *np = pdev->dev.of_node;
+ int count, i, ret = 0;
+ char *res_name, *s;
+ u32 *resolutions;
+
+ count = of_property_count_strings(np, "atmel,adc-res-names");
+ if (count < 2) {
+ dev_err(&idev->dev, "You must specified at least two resolution names for "
+ "adc-res-names property in the DT\n");
+ return count;
+ }
+
+ resolutions = kmalloc(count * sizeof(*resolutions), GFP_KERNEL);
+ if (!resolutions)
+ return -ENOMEM;
+
+ if (of_property_read_u32_array(np, "atmel,adc-res", resolutions, count)) {
+ dev_err(&idev->dev, "Missing adc-res property in the DT.\n");
+ ret = -ENODEV;
+ goto ret;
+ }
+
+ if (of_property_read_string(np, "atmel,adc-use-res", (const char **)&res_name))
+ res_name = "highres";
+
+ for (i = 0; i < count; i++) {
+ if (of_property_read_string_index(np, "atmel,adc-res-names", i, (const char **)&s))
+ continue;
+
+ if (strcmp(res_name, s))
+ continue;
+
+ st->res = resolutions[i];
+ if (!strcmp(res_name, "lowres"))
+ st->low_res = true;
+ else
+ st->low_res = false;
+
+ dev_info(&idev->dev, "Resolution used: %u bits\n", st->res);
+ goto ret;
+ }
+
+ dev_err(&idev->dev, "There is no resolution for %s\n", res_name);
+
+ret:
+ kfree(resolutions);
+ return ret;
+}
+
static int at91_adc_probe_dt(struct at91_adc_state *st,
struct platform_device *pdev)
{
@@ -400,6 +457,8 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
}
st->num_channels = prop;
+ st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode");
+
if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n");
ret = -EINVAL;
@@ -407,6 +466,9 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
}
st->startup_time = prop;
+ prop = 0;
+ of_property_read_u32(node, "atmel,adc-sample-hold-time", &prop);
+ st->sample_hold_time = prop;
if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
@@ -415,6 +477,10 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
}
st->vref_mv = prop;
+ ret = at91_adc_of_get_resolution(st, pdev);
+ if (ret)
+ goto error_ret;
+
st->registers = devm_kzalloc(&idev->dev,
sizeof(struct at91_adc_reg_desc),
GFP_KERNEL);
@@ -516,11 +582,12 @@ static const struct iio_info at91_adc_info = {
static int at91_adc_probe(struct platform_device *pdev)
{
- unsigned int prsc, mstrclk, ticks, adc_clk;
+ unsigned int prsc, mstrclk, ticks, adc_clk, shtim;
int ret;
struct iio_dev *idev;
struct at91_adc_state *st;
struct resource *res;
+ u32 reg;
idev = iio_device_alloc(sizeof(struct at91_adc_state));
if (idev == NULL) {
@@ -628,9 +695,22 @@ static int at91_adc_probe(struct platform_device *pdev)
*/
ticks = round_up((st->startup_time * adc_clk /
1000000) - 1, 8) / 8;
- at91_adc_writel(st, AT91_ADC_MR,
- (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
- (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
+ /*
+ * a minimal Sample and Hold Time is necessary for the ADC to guarantee
+ * the best converted final value between two channels selection
+ * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock
+ */
+ shtim = round_up((st->sample_hold_time * adc_clk /
+ 1000000) - 1, 1);
+
+ reg = AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL;
+ reg |= AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP;
+ if (st->low_res)
+ reg |= AT91_ADC_LOWRES;
+ if (st->sleep_mode)
+ reg |= AT91_ADC_SLEEP;
+ reg |= AT91_ADC_SHTIM_(shtim) & AT91_ADC_SHTIM;
+ at91_adc_writel(st, AT91_ADC_MR, reg);
/* Setup the ADC channels available on the board */
ret = at91_adc_channel_init(idev);
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
new file mode 100644
index 00000000000..9f3a8ef1fb3
--- /dev/null
+++ b/drivers/iio/adc/exynos_adc.c
@@ -0,0 +1,452 @@
+/*
+ * exynos_adc.c - Support for ADC in EXYNOS SoCs
+ *
+ * 8 ~ 10 channel, 10/12-bit ADC
+ *
+ * Copyright (C) 2013 Naveen Krishna Chatradhi <ch.naveen@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_platform.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+
+enum adc_version {
+ ADC_V1,
+ ADC_V2
+};
+
+/* EXYNOS4412/5250 ADC_V1 registers definitions */
+#define ADC_V1_CON(x) ((x) + 0x00)
+#define ADC_V1_DLY(x) ((x) + 0x08)
+#define ADC_V1_DATX(x) ((x) + 0x0C)
+#define ADC_V1_INTCLR(x) ((x) + 0x18)
+#define ADC_V1_MUX(x) ((x) + 0x1c)
+
+/* Future ADC_V2 registers definitions */
+#define ADC_V2_CON1(x) ((x) + 0x00)
+#define ADC_V2_CON2(x) ((x) + 0x04)
+#define ADC_V2_STAT(x) ((x) + 0x08)
+#define ADC_V2_INT_EN(x) ((x) + 0x10)
+#define ADC_V2_INT_ST(x) ((x) + 0x14)
+#define ADC_V2_VER(x) ((x) + 0x20)
+
+/* Bit definitions for ADC_V1 */
+#define ADC_V1_CON_RES (1u << 16)
+#define ADC_V1_CON_PRSCEN (1u << 14)
+#define ADC_V1_CON_PRSCLV(x) (((x) & 0xFF) << 6)
+#define ADC_V1_CON_STANDBY (1u << 2)
+
+/* Bit definitions for ADC_V2 */
+#define ADC_V2_CON1_SOFT_RESET (1u << 2)
+
+#define ADC_V2_CON2_OSEL (1u << 10)
+#define ADC_V2_CON2_ESEL (1u << 9)
+#define ADC_V2_CON2_HIGHF (1u << 8)
+#define ADC_V2_CON2_C_TIME(x) (((x) & 7) << 4)
+#define ADC_V2_CON2_ACH_SEL(x) (((x) & 0xF) << 0)
+#define ADC_V2_CON2_ACH_MASK 0xF
+
+#define MAX_ADC_V2_CHANNELS 10
+#define MAX_ADC_V1_CHANNELS 8
+
+/* Bit definitions common for ADC_V1 and ADC_V2 */
+#define ADC_CON_EN_START (1u << 0)
+#define ADC_DATX_MASK 0xFFF
+
+#define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(1000))
+
+struct exynos_adc {
+ void __iomem *regs;
+ void __iomem *enable_reg;
+ struct clk *clk;
+ unsigned int irq;
+ struct regulator *vdd;
+
+ struct completion completion;
+
+ u32 value;
+ unsigned int version;
+};
+
+static const struct of_device_id exynos_adc_match[] = {
+ { .compatible = "samsung,exynos-adc-v1", .data = (void *)ADC_V1 },
+ { .compatible = "samsung,exynos-adc-v2", .data = (void *)ADC_V2 },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_adc_match);
+
+static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+
+ match = of_match_node(exynos_adc_match, pdev->dev.of_node);
+ return (unsigned int)match->data;
+}
+
+static int exynos_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
+{
+ struct exynos_adc *info = iio_priv(indio_dev);
+ unsigned long timeout;
+ u32 con1, con2;
+
+ if (mask != IIO_CHAN_INFO_RAW)
+ return -EINVAL;
+
+ mutex_lock(&indio_dev->mlock);
+
+ /* Select the channel to be used and Trigger conversion */
+ if (info->version == ADC_V2) {
+ con2 = readl(ADC_V2_CON2(info->regs));
+ con2 &= ~ADC_V2_CON2_ACH_MASK;
+ con2 |= ADC_V2_CON2_ACH_SEL(chan->address);
+ writel(con2, ADC_V2_CON2(info->regs));
+
+ con1 = readl(ADC_V2_CON1(info->regs));
+ writel(con1 | ADC_CON_EN_START,
+ ADC_V2_CON1(info->regs));
+ } else {
+ writel(chan->address, ADC_V1_MUX(info->regs));
+
+ con1 = readl(ADC_V1_CON(info->regs));
+ writel(con1 | ADC_CON_EN_START,
+ ADC_V1_CON(info->regs));
+ }
+
+ timeout = wait_for_completion_interruptible_timeout
+ (&info->completion, EXYNOS_ADC_TIMEOUT);
+ *val = info->value;
+
+ mutex_unlock(&indio_dev->mlock);
+
+ if (timeout == 0)
+ return -ETIMEDOUT;
+
+ return IIO_VAL_INT;
+}
+
+static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
+{
+ struct exynos_adc *info = (struct exynos_adc *)dev_id;
+
+ /* Read value */
+ info->value = readl(ADC_V1_DATX(info->regs)) &
+ ADC_DATX_MASK;
+ /* clear irq */
+ if (info->version == ADC_V2)
+ writel(1, ADC_V2_INT_ST(info->regs));
+ else
+ writel(1, ADC_V1_INTCLR(info->regs));
+
+ complete(&info->completion);
+
+ return IRQ_HANDLED;
+}
+
+static int exynos_adc_reg_access(struct iio_dev *indio_dev,
+ unsigned reg, unsigned writeval,
+ unsigned *readval)
+{
+ struct exynos_adc *info = iio_priv(indio_dev);
+
+ if (readval == NULL)
+ return -EINVAL;
+
+ *readval = readl(info->regs + reg);
+
+ return 0;
+}
+
+static const struct iio_info exynos_adc_iio_info = {
+ .read_raw = &exynos_read_raw,
+ .debugfs_reg_access = &exynos_adc_reg_access,
+ .driver_module = THIS_MODULE,
+};
+
+#define ADC_CHANNEL(_index, _id) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = _index, \
+ .address = _index, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .datasheet_name = _id, \
+}
+
+static const struct iio_chan_spec exynos_adc_iio_channels[] = {
+ ADC_CHANNEL(0, "adc0"),
+ ADC_CHANNEL(1, "adc1"),
+ ADC_CHANNEL(2, "adc2"),
+ ADC_CHANNEL(3, "adc3"),
+ ADC_CHANNEL(4, "adc4"),
+ ADC_CHANNEL(5, "adc5"),
+ ADC_CHANNEL(6, "adc6"),
+ ADC_CHANNEL(7, "adc7"),
+ ADC_CHANNEL(8, "adc8"),
+ ADC_CHANNEL(9, "adc9"),
+};
+
+static int exynos_adc_remove_devices(struct device *dev, void *c)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ platform_device_unregister(pdev);
+
+ return 0;
+}
+
+static void exynos_adc_hw_init(struct exynos_adc *info)
+{
+ u32 con1, con2;
+
+ if (info->version == ADC_V2) {
+ con1 = ADC_V2_CON1_SOFT_RESET;
+ writel(con1, ADC_V2_CON1(info->regs));
+
+ con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
+ ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
+ writel(con2, ADC_V2_CON2(info->regs));
+
+ /* Enable interrupts */
+ writel(1, ADC_V2_INT_EN(info->regs));
+ } else {
+ /* set default prescaler values and Enable prescaler */
+ con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+
+ /* Enable 12-bit ADC resolution */
+ con1 |= ADC_V1_CON_RES;
+ writel(con1, ADC_V1_CON(info->regs));
+ }
+}
+
+static int exynos_adc_probe(struct platform_device *pdev)
+{
+ struct exynos_adc *info = NULL;
+ struct device_node *np = pdev->dev.of_node;
+ struct iio_dev *indio_dev = NULL;
+ struct resource *mem;
+ int ret = -ENODEV;
+ int irq;
+
+ if (!np)
+ return ret;
+
+ indio_dev = iio_device_alloc(sizeof(struct exynos_adc));
+ if (!indio_dev) {
+ dev_err(&pdev->dev, "failed allocating iio device\n");
+ return -ENOMEM;
+ }
+
+ info = iio_priv(indio_dev);
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ info->regs = devm_request_and_ioremap(&pdev->dev, mem);
+ if (!info->regs) {
+ ret = -ENOMEM;
+ goto err_iio;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ info->enable_reg = devm_request_and_ioremap(&pdev->dev, mem);
+ if (!info->enable_reg) {
+ ret = -ENOMEM;
+ goto err_iio;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq resource?\n");
+ ret = irq;
+ goto err_iio;
+ }
+
+ info->irq = irq;
+
+ init_completion(&info->completion);
+
+ ret = request_irq(info->irq, exynos_adc_isr,
+ 0, dev_name(&pdev->dev), info);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
+ info->irq);
+ goto err_iio;
+ }
+
+ writel(1, info->enable_reg);
+
+ info->clk = devm_clk_get(&pdev->dev, "adc");
+ if (IS_ERR(info->clk)) {
+ dev_err(&pdev->dev, "failed getting clock, err = %ld\n",
+ PTR_ERR(info->clk));
+ ret = PTR_ERR(info->clk);
+ goto err_irq;
+ }
+
+ info->vdd = devm_regulator_get(&pdev->dev, "vdd");
+ if (IS_ERR(info->vdd)) {
+ dev_err(&pdev->dev, "failed getting regulator, err = %ld\n",
+ PTR_ERR(info->vdd));
+ ret = PTR_ERR(info->vdd);
+ goto err_irq;
+ }
+
+ info->version = exynos_adc_get_version(pdev);
+
+ platform_set_drvdata(pdev, indio_dev);
+
+ indio_dev->name = dev_name(&pdev->dev);
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->dev.of_node = pdev->dev.of_node;
+ indio_dev->info = &exynos_adc_iio_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = exynos_adc_iio_channels;
+
+ if (info->version == ADC_V1)
+ indio_dev->num_channels = MAX_ADC_V1_CHANNELS;
+ else
+ indio_dev->num_channels = MAX_ADC_V2_CHANNELS;
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto err_irq;
+
+ ret = regulator_enable(info->vdd);
+ if (ret)
+ goto err_iio_dev;
+
+ clk_prepare_enable(info->clk);
+
+ exynos_adc_hw_init(info);
+
+ ret = of_platform_populate(np, exynos_adc_match, NULL, &pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed adding child nodes\n");
+ goto err_of_populate;
+ }
+
+ return 0;
+
+err_of_populate:
+ device_for_each_child(&pdev->dev, NULL,
+ exynos_adc_remove_devices);
+ regulator_disable(info->vdd);
+ clk_disable_unprepare(info->clk);
+err_iio_dev:
+ iio_device_unregister(indio_dev);
+err_irq:
+ free_irq(info->irq, info);
+err_iio:
+ iio_device_free(indio_dev);
+ return ret;
+}
+
+static int exynos_adc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct exynos_adc *info = iio_priv(indio_dev);
+
+ device_for_each_child(&pdev->dev, NULL,
+ exynos_adc_remove_devices);
+ regulator_disable(info->vdd);
+ clk_disable_unprepare(info->clk);
+ writel(0, info->enable_reg);
+ iio_device_unregister(indio_dev);
+ free_irq(info->irq, info);
+ iio_device_free(indio_dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos_adc_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct exynos_adc *info = platform_get_drvdata(pdev);
+ u32 con;
+
+ if (info->version == ADC_V2) {
+ con = readl(ADC_V2_CON1(info->regs));
+ con &= ~ADC_CON_EN_START;
+ writel(con, ADC_V2_CON1(info->regs));
+ } else {
+ con = readl(ADC_V1_CON(info->regs));
+ con |= ADC_V1_CON_STANDBY;
+ writel(con, ADC_V1_CON(info->regs));
+ }
+
+ clk_disable_unprepare(info->clk);
+ writel(0, info->enable_reg);
+ regulator_disable(info->vdd);
+
+ return 0;
+}
+
+static int exynos_adc_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct exynos_adc *info = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = regulator_enable(info->vdd);
+ if (ret)
+ return ret;
+
+ writel(1, info->enable_reg);
+ clk_prepare_enable(info->clk);
+
+ exynos_adc_hw_init(info);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops,
+ exynos_adc_suspend,
+ exynos_adc_resume);
+
+static struct platform_driver exynos_adc_driver = {
+ .probe = exynos_adc_probe,
+ .remove = exynos_adc_remove,
+ .driver = {
+ .name = "exynos-adc",
+ .owner = THIS_MODULE,
+ .of_match_table = exynos_adc_match,
+ .pm = &exynos_adc_pm_ops,
+ },
+};
+
+module_platform_driver(exynos_adc_driver);
+
+MODULE_AUTHOR("Naveen Krishna Chatradhi <ch.naveen@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS5 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/lp8788_adc.c b/drivers/iio/adc/lp8788_adc.c
index 763f57565ee..62bc39e9c94 100644
--- a/drivers/iio/adc/lp8788_adc.c
+++ b/drivers/iio/adc/lp8788_adc.c
@@ -132,8 +132,8 @@ static const struct iio_info lp8788_adc_info = {
.type = _type, \
.indexed = 1, \
.channel = LPADC_##_id, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = #_id, \
}
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 6c1cfb74bdf..9e6da72ad82 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -427,15 +427,15 @@ static const enum max1363_modes max1363_mode_list[] = {
#define MAX1363_EV_M \
(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) \
| IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
-#define MAX1363_INFO_MASK (IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT)
+
#define MAX1363_CHAN_U(num, addr, si, bits, evmask) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = num, \
.address = addr, \
- .info_mask = MAX1363_INFO_MASK, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = "AIN"#num, \
.scan_type = { \
.sign = 'u', \
@@ -456,7 +456,8 @@ static const enum max1363_modes max1363_mode_list[] = {
.channel = num, \
.channel2 = num2, \
.address = addr, \
- .info_mask = MAX1363_INFO_MASK, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = "AIN"#num"-AIN"#num2, \
.scan_type = { \
.sign = 's', \
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c
index f4a46dd8f43..2826faae706 100644
--- a/drivers/iio/adc/ti-adc081c.c
+++ b/drivers/iio/adc/ti-adc081c.c
@@ -55,8 +55,8 @@ static int adc081c_read_raw(struct iio_dev *iio,
static const struct iio_chan_spec adc081c_channel = {
.type = IIO_VOLTAGE,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
};
static const struct iio_info adc081c_info = {
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index cd030e100c3..5f9a7e7d313 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -89,7 +89,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
chan->type = IIO_VOLTAGE;
chan->indexed = 1;
chan->channel = i;
- chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
+ chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
}
indio_dev->channels = chan_array;
diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c
index ad0261533de..56ac481c73c 100644
--- a/drivers/iio/adc/viperboard_adc.c
+++ b/drivers/iio/adc/viperboard_adc.c
@@ -41,7 +41,7 @@ struct vprbrd_adc {
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _index, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.scan_index = _index, \
.scan_type = { \
.sign = 'u', \
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c
index d6c0af23a2a..d354554b51b 100644
--- a/drivers/iio/amplifiers/ad8366.c
+++ b/drivers/iio/amplifiers/ad8366.c
@@ -125,7 +125,7 @@ static const struct iio_info ad8366_info = {
.output = 1, \
.indexed = 1, \
.channel = _channel, \
- .info_mask = IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT,\
+ .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN),\
}
static const struct iio_chan_spec ad8366_channels[] = {
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 7a525a91105..87419c41b99 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -31,7 +31,7 @@
static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
- struct hid_sensor_common *st = trig->private_data;
+ struct hid_sensor_common *st = iio_trigger_get_drvdata(trig);
int state_val;
state_val = state ? 1 : 0;
@@ -76,7 +76,7 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
}
trig->dev.parent = indio_dev->dev.parent;
- trig->private_data = attrb;
+ iio_trigger_set_drvdata(trig, attrb);
trig->ops = &hid_sensor_trigger_ops;
ret = iio_trigger_register(trig);
diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c
index f0aa2f10522..251baf6abc2 100644
--- a/drivers/iio/common/st_sensors/st_sensors_spi.c
+++ b/drivers/iio/common/st_sensors/st_sensors_spi.c
@@ -29,7 +29,6 @@ static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev)
static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit)
{
- struct spi_message msg;
int err;
struct spi_transfer xfers[] = {
@@ -51,10 +50,7 @@ static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
else
tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ;
- spi_message_init(&msg);
- spi_message_add_tail(&xfers[0], &msg);
- spi_message_add_tail(&xfers[1], &msg);
- err = spi_sync(to_spi_device(dev), &msg);
+ err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers));
if (err)
goto acc_spi_read_error;
@@ -83,7 +79,6 @@ static int st_sensors_spi_read_multiple_byte(
static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb,
struct device *dev, u8 reg_addr, u8 data)
{
- struct spi_message msg;
int err;
struct spi_transfer xfers = {
@@ -96,9 +91,7 @@ static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb,
tb->tx_buf[0] = reg_addr;
tb->tx_buf[1] = data;
- spi_message_init(&msg);
- spi_message_add_tail(&xfers, &msg);
- err = spi_sync(to_spi_device(dev), &msg);
+ err = spi_sync_transfer(to_spi_device(dev), &xfers, 1);
mutex_unlock(&tb->buf_lock);
return err;
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
index 139ed030abb..8fc3a97eb26 100644
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -40,7 +40,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
if (err)
goto request_irq_error;
- sdata->trig->private_data = indio_dev;
+ iio_trigger_set_drvdata(sdata->trig, indio_dev);
sdata->trig->ops = trigger_ops;
sdata->trig->dev.parent = sdata->dev;
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
index 74f2d52795f..aa26d50ab63 100644
--- a/drivers/iio/dac/ad5064.c
+++ b/drivers/iio/dac/ad5064.c
@@ -296,8 +296,8 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
.indexed = 1, \
.output = 1, \
.channel = (chan), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.address = addr, \
.scan_type = IIO_ST('u', (bits), 16, 20 - (bits)), \
.ext_info = ad5064_ext_info, \
diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c
index 92771217f66..80923af424f 100644
--- a/drivers/iio/dac/ad5360.c
+++ b/drivers/iio/dac/ad5360.c
@@ -102,11 +102,11 @@ enum ad5360_type {
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET) | \
+ BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
.scan_type = IIO_ST('u', (bits), 16, 16 - (bits)) \
}
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 483fc379a2d..bf2db02215c 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -257,10 +257,10 @@ static struct iio_chan_spec_ext_info ad5380_ext_info[] = {
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)), \
.ext_info = ad5380_ext_info, \
}
diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c
index 6b86a638dad..98f24407c3c 100644
--- a/drivers/iio/dac/ad5421.c
+++ b/drivers/iio/dac/ad5421.c
@@ -86,11 +86,11 @@ static const struct iio_chan_spec ad5421_channels[] = {
.indexed = 1,
.output = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_CALIBSCALE) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
.scan_type = IIO_ST('u', 16, 16, 0),
.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index f5583aedfb5..cae8f6056ac 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -143,8 +143,8 @@ static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
.indexed = 1, \
.output = 1, \
.channel = 0, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.scan_type = IIO_ST('u', (bits), (storage), (shift)), \
.ext_info = (ext), \
}
diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c
index c4731b7b577..ba1c914b039 100644
--- a/drivers/iio/dac/ad5449.c
+++ b/drivers/iio/dac/ad5449.c
@@ -206,8 +206,8 @@ static const struct iio_info ad5449_info = {
.indexed = 1, \
.output = 1, \
.channel = (chan), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.address = (chan), \
.scan_type = IIO_ST('u', (bits), 16, 12 - (bits)), \
}
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index e5e59749f10..139206e84cb 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -259,8 +259,8 @@ static const struct iio_chan_spec_ext_info ad5504_ext_info[] = {
.indexed = 1, \
.output = 1, \
.channel = (_chan), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = AD5504_ADDR_DAC(_chan), \
.scan_type = IIO_ST('u', 12, 16, 0), \
.ext_info = ad5504_ext_info, \
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index f6e116627b7..bb298aaff32 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -174,8 +174,8 @@ static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = {
.indexed = 1, \
.output = 1, \
.channel = (_chan), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = (_chan), \
.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \
.ext_info = ad5624r_ext_info, \
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 5e554af2170..06439b1af9b 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -276,9 +276,9 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = {
.indexed = 1, \
.output = 1, \
.channel = chan, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
- .address = AD5686_ADDR_DAC(chan), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
+ .address = AD5686_ADDR_DAC(chan), \
.scan_type = IIO_ST('u', bits, 16, shift), \
.ext_info = ad5686_ext_info, \
}
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
index 71faabc6b14..12bb315e55f 100644
--- a/drivers/iio/dac/ad5755.c
+++ b/drivers/iio/dac/ad5755.c
@@ -393,11 +393,11 @@ static const struct iio_chan_spec_ext_info ad5755_ext_info[] = {
#define AD5755_CHANNEL(_bits) { \
.indexed = 1, \
.output = 1, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET) | \
+ BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \
.ext_info = ad5755_ext_info, \
}
diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c
index 5b7acd3a2c7..7a53f7d70da 100644
--- a/drivers/iio/dac/ad5764.c
+++ b/drivers/iio/dac/ad5764.c
@@ -78,11 +78,11 @@ enum ad5764_type {
.output = 1, \
.channel = (_chan), \
.address = (_chan), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_OFFSET_SHARED_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET), \
.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)) \
}
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index 8dfd3da8a07..97c1e5d780d 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -302,9 +302,9 @@ static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
.indexed = 1, \
.address = AD5791_ADDR_DAC0, \
.channel = 0, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
.scan_type = IIO_ST('u', bits, 24, shift), \
.ext_info = ad5791_ext_info, \
}
diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
index 352abe2004a..ebfaa415624 100644
--- a/drivers/iio/dac/max517.c
+++ b/drivers/iio/dac/max517.c
@@ -146,8 +146,8 @@ static const struct iio_info max517_info = {
.indexed = 1, \
.output = 1, \
.channel = (chan), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.scan_type = IIO_ST('u', 8, 8, 0), \
}
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index 8f88cc4059a..a612ec766d9 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -69,8 +69,8 @@ static const struct iio_chan_spec mcp4725_channel = {
.indexed = 1,
.output = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.scan_type = IIO_ST('u', 12, 16, 0),
};
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index 1ea132e239e..92276deeb02 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -920,10 +920,10 @@ static int ad9523_setup(struct iio_dev *indio_dev)
st->ad9523_channels[i].channel = chan->channel_num;
st->ad9523_channels[i].extend_name =
chan->extended_name;
- st->ad9523_channels[i].info_mask =
- IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_PHASE_SEPARATE_BIT |
- IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT;
+ st->ad9523_channels[i].info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_PHASE) |
+ BIT(IIO_CHAN_INFO_FREQUENCY);
}
}
diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c
index 1861287911f..e1bb5f994a5 100644
--- a/drivers/iio/gyro/adis16080.c
+++ b/drivers/iio/gyro/adis16080.c
@@ -136,32 +136,32 @@ static const struct iio_chan_spec adis16080_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
.address = ADIS16080_DIN_GYRO,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
.address = ADIS16080_DIN_AIN1,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
.address = ADIS16080_DIN_AIN2,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
.address = ADIS16080_DIN_TEMP,
}
};
diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c
index 8cb0bcbfd60..058e6d5c955 100644
--- a/drivers/iio/gyro/adis16136.c
+++ b/drivers/iio/gyro/adis16136.c
@@ -357,10 +357,11 @@ static const struct iio_chan_spec adis16136_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS) |
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+
.address = ADIS16136_REG_GYRO_OUT2,
.scan_index = ADIS16136_SCAN_GYRO,
.scan_type = {
@@ -373,8 +374,8 @@ static const struct iio_chan_spec adis16136_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
.address = ADIS16136_REG_TEMP_OUT,
.scan_index = ADIS16136_SCAN_TEMP,
.scan_type = {
diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c
index 5b79953f701..8bd72b490b7 100644
--- a/drivers/iio/gyro/adxrs450.c
+++ b/drivers/iio/gyro/adxrs450.c
@@ -383,16 +383,16 @@ static const struct iio_chan_spec adxrs450_channels[2][2] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
- IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS) |
+ BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
}
},
[ID_ADXRS453] = {
@@ -400,15 +400,15 @@ static const struct iio_chan_spec adxrs450_channels[2][2] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW),
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
}
},
};
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index fcfc83a9f86..bc943dd47da 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -60,28 +60,28 @@ static const struct iio_chan_spec gyro_3d_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_X,
}, {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_Y,
}, {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_Z,
}
};
diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c
index f667d2c8c00..6c43af9bb0a 100644
--- a/drivers/iio/gyro/itg3200_buffer.c
+++ b/drivers/iio/gyro/itg3200_buffer.c
@@ -81,7 +81,7 @@ void itg3200_buffer_unconfigure(struct iio_dev *indio_dev)
static int itg3200_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
- struct iio_dev *indio_dev = trig->private_data;
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
int ret;
u8 msc;
@@ -129,7 +129,7 @@ int itg3200_probe_trigger(struct iio_dev *indio_dev)
st->trig->dev.parent = &st->i2c->dev;
st->trig->ops = &itg3200_trigger_ops;
- st->trig->private_data = indio_dev;
+ iio_trigger_set_drvdata(st->trig, indio_dev);
ret = iio_trigger_register(st->trig);
if (ret)
goto error_free_irq;
diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c
index df2e6aa5d73..d66605d2629 100644
--- a/drivers/iio/gyro/itg3200_core.c
+++ b/drivers/iio/gyro/itg3200_core.c
@@ -248,12 +248,6 @@ err_ret:
return ret;
}
-#define ITG3200_TEMP_INFO_MASK (IIO_CHAN_INFO_OFFSET_SHARED_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_RAW_SEPARATE_BIT)
-#define ITG3200_GYRO_INFO_MASK (IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_RAW_SEPARATE_BIT)
-
#define ITG3200_ST \
{ .sign = 's', .realbits = 16, .storagebits = 16, .endianness = IIO_BE }
@@ -261,7 +255,8 @@ err_ret:
.type = IIO_ANGL_VEL, \
.modified = 1, \
.channel2 = IIO_MOD_ ## _mod, \
- .info_mask = ITG3200_GYRO_INFO_MASK, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = ITG3200_REG_GYRO_ ## _mod ## OUT_H, \
.scan_index = ITG3200_SCAN_GYRO_ ## _mod, \
.scan_type = ITG3200_ST, \
@@ -271,7 +266,9 @@ static const struct iio_chan_spec itg3200_channels[] = {
{
.type = IIO_TEMP,
.channel2 = IIO_NO_MOD,
- .info_mask = ITG3200_TEMP_INFO_MASK,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE),
.address = ITG3200_REG_TEMP_OUT_H,
.scan_index = ITG3200_SCAN_TEMP,
.scan_type = ITG3200_ST,
diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c
index da4d122ec7d..69017c7ec30 100644
--- a/drivers/iio/gyro/st_gyro_buffer.c
+++ b/drivers/iio/gyro/st_gyro_buffer.c
@@ -25,7 +25,7 @@
int st_gyro_trig_set_state(struct iio_trigger *trig, bool state)
{
- struct iio_dev *indio_dev = trig->private_data;
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
return st_sensors_set_dataready_irq(indio_dev, state);
}
diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index f652e6ae5a3..05c1b74502a 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -18,6 +18,7 @@
struct iio_chan_spec;
struct iio_dev;
+extern struct device_type iio_device_type;
int __iio_add_chan_devattr(const char *postfix,
struct iio_chan_spec const *chan,
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index b7f215eab5d..f60591f0b92 100644
--- a/drivers/iio/imu/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
@@ -484,8 +484,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.indexed = 1, \
.channel = 0, \
.extend_name = name, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.address = (addr), \
.scan_index = (si), \
.scan_type = { \
@@ -507,10 +507,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.type = IIO_ANGL_VEL, \
.modified = 1, \
.channel2 = IIO_MOD_ ## mod, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
.address = addr, \
.scan_index = ADIS16400_SCAN_GYRO_ ## mod, \
.scan_type = { \
@@ -526,10 +526,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_ ## mod, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
.address = (addr), \
.scan_index = ADIS16400_SCAN_ACC_ ## mod, \
.scan_type = { \
@@ -545,9 +545,9 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.type = IIO_MAGN, \
.modified = 1, \
.channel2 = IIO_MOD_ ## mod, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
.address = (addr), \
.scan_index = ADIS16400_SCAN_MAGN_ ## mod, \
.scan_type = { \
@@ -568,10 +568,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.indexed = 1, \
.channel = 0, \
.extend_name = ADIS16400_MOD_TEMP_NAME_ ## mod, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_OFFSET) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_type = \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
.address = (addr), \
.scan_index = ADIS16350_SCAN_TEMP_ ## mod, \
.scan_type = { \
@@ -587,9 +588,9 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.type = IIO_TEMP, \
.indexed = 1, \
.channel = 0, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_OFFSET) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.address = (addr), \
.scan_index = ADIS16350_SCAN_TEMP_X, \
.scan_type = { \
@@ -605,8 +606,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.type = IIO_INCLI, \
.modified = 1, \
.channel2 = IIO_MOD_ ## mod, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = (addr), \
.scan_index = ADIS16300_SCAN_INCLI_ ## mod, \
.scan_type = { \
@@ -646,8 +647,8 @@ static const struct iio_chan_spec adis16448_channels[] = {
ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 16),
{
.type = IIO_PRESSURE,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.address = ADIS16448_BARO_OUT,
.scan_index = ADIS16400_SCAN_BARO,
.scan_type = IIO_ST('s', 16, 16, 0),
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index 8c26a5f7cd5..b7db3837629 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -591,15 +591,15 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
}
}
-#define ADIS16480_MOD_CHANNEL(_type, _mod, _address, _si, _info, _bits) \
+#define ADIS16480_MOD_CHANNEL(_type, _mod, _address, _si, _info_sep, _bits) \
{ \
.type = (_type), \
.modified = 1, \
.channel2 = (_mod), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- _info, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS) | \
+ _info_sep, \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = (_address), \
.scan_index = (_si), \
.scan_type = { \
@@ -613,21 +613,21 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
#define ADIS16480_GYRO_CHANNEL(_mod) \
ADIS16480_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \
ADIS16480_REG_ ## _mod ## _GYRO_OUT, ADIS16480_SCAN_GYRO_ ## _mod, \
- IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \
+ BIT(IIO_CHAN_INFO_CALIBSCALE), \
32)
#define ADIS16480_ACCEL_CHANNEL(_mod) \
ADIS16480_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \
ADIS16480_REG_ ## _mod ## _ACCEL_OUT, ADIS16480_SCAN_ACCEL_ ## _mod, \
- IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \
+ BIT(IIO_CHAN_INFO_CALIBSCALE), \
32)
#define ADIS16480_MAGN_CHANNEL(_mod) \
ADIS16480_MOD_CHANNEL(IIO_MAGN, IIO_MOD_ ## _mod, \
ADIS16480_REG_ ## _mod ## _MAGN_OUT, ADIS16480_SCAN_MAGN_ ## _mod, \
- IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT, \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
16)
#define ADIS16480_PRESSURE_CHANNEL() \
@@ -635,9 +635,9 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
.type = IIO_PRESSURE, \
.indexed = 1, \
.channel = 0, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.address = ADIS16480_REG_BAROM_OUT, \
.scan_index = ADIS16480_SCAN_BARO, \
.scan_type = { \
@@ -652,9 +652,9 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
.type = IIO_TEMP, \
.indexed = 1, \
.channel = 0, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
.address = ADIS16480_REG_TEMP_OUT, \
.scan_index = ADIS16480_SCAN_TEMP, \
.scan_type = { \
diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
index 5a24c9cac34..e0017c22bb9 100644
--- a/drivers/iio/imu/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
@@ -19,7 +19,7 @@
static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
- struct adis *adis = trig->private_data;
+ struct adis *adis = iio_trigger_get_drvdata(trig);
return adis_enable_irq(adis, state);
}
@@ -57,7 +57,7 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
adis->trig->dev.parent = &adis->spi->dev;
adis->trig->ops = &adis_trigger_ops;
- adis->trig->private_data = adis;
+ iio_trigger_set_drvdata(adis->trig, adis);
ret = iio_trigger_register(adis->trig);
indio_dev->trig = adis->trig;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 37ca05b47e4..fe4c61e219f 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -544,8 +544,8 @@ static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev,
.type = _type, \
.modified = 1, \
.channel2 = _channel2, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT \
- | IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.scan_index = _index, \
.scan_type = { \
.sign = 's', \
@@ -564,9 +564,9 @@ static const struct iio_chan_spec inv_mpu_channels[] = {
*/
{
.type = IIO_TEMP,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT
- | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT
- | IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
+ | BIT(IIO_CHAN_INFO_OFFSET)
+ | BIT(IIO_CHAN_INFO_SCALE),
.scan_index = -1,
},
INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 331781ffbb1..7da0832f187 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -105,9 +105,8 @@ irqreturn_t inv_mpu6050_irq_handler(int irq, void *p)
s64 timestamp;
timestamp = iio_get_time_ns();
- spin_lock(&st->time_stamp_lock);
- kfifo_in(&st->timestamps, &timestamp, 1);
- spin_unlock(&st->time_stamp_lock);
+ kfifo_in_spinlocked(&st->timestamps, &timestamp, 1,
+ &st->time_stamp_lock);
return IRQ_WAKE_THREAD;
}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index e1d0869e0ad..03b9372c121 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -103,7 +103,7 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
- return inv_mpu6050_set_enable(trig->private_data, state);
+ return inv_mpu6050_set_enable(iio_trigger_get_drvdata(trig), state);
}
static const struct iio_trigger_ops inv_mpu_trigger_ops = {
@@ -130,8 +130,8 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
if (ret)
goto error_free_trig;
st->trig->dev.parent = &st->client->dev;
- st->trig->private_data = indio_dev;
st->trig->ops = &inv_mpu_trigger_ops;
+ iio_trigger_set_drvdata(st->trig, indio_dev);
ret = iio_trigger_register(st->trig);
if (ret)
goto error_free_irq;
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 8848f16c547..e145931ef1b 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -691,21 +691,34 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
if (chan->channel < 0)
return 0;
- for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
- ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
+ for_each_set_bit(i, &chan->info_mask_separate, sizeof(long)*8) {
+ ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
chan,
&iio_read_channel_info,
&iio_write_channel_info,
- i/2,
- !(i%2),
+ i,
+ 0,
&indio_dev->dev,
&indio_dev->channel_attr_list);
- if (ret == -EBUSY && (i%2 == 0)) {
+ if (ret < 0)
+ goto error_ret;
+ attrcount++;
+ }
+ for_each_set_bit(i, &chan->info_mask_shared_by_type, sizeof(long)*8) {
+ ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
+ chan,
+ &iio_read_channel_info,
+ &iio_write_channel_info,
+ i,
+ 1,
+ &indio_dev->dev,
+ &indio_dev->channel_attr_list);
+ if (ret == -EBUSY) {
ret = 0;
continue;
- }
- if (ret < 0)
+ } else if (ret < 0) {
goto error_ret;
+ }
attrcount++;
}
@@ -847,7 +860,7 @@ static void iio_dev_release(struct device *device)
kfree(indio_dev);
}
-static struct device_type iio_dev_type = {
+struct device_type iio_device_type = {
.name = "iio_device",
.release = iio_dev_release,
};
@@ -869,7 +882,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv)
if (dev) {
dev->dev.groups = dev->groups;
- dev->dev.type = &iio_dev_type;
+ dev->dev.type = &iio_device_type;
dev->dev.bus = &iio_bus_type;
device_initialize(&dev->dev);
dev_set_drvdata(&dev->dev, (void *)dev);
@@ -960,6 +973,10 @@ int iio_device_register(struct iio_dev *indio_dev)
{
int ret;
+ /* If the calling driver did not initialize of_node, do it here */
+ if (!indio_dev->dev.of_node && indio_dev->dev.parent)
+ indio_dev->dev.of_node = indio_dev->dev.parent->of_node;
+
/* configure elements for the chrdev */
indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 261cae00557..10aa9ef86ce 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -46,10 +46,11 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
{
struct iio_event_interface *ev_int = indio_dev->event_interface;
struct iio_event_data ev;
+ unsigned long flags;
int copied;
/* Does anyone care? */
- spin_lock(&ev_int->wait.lock);
+ spin_lock_irqsave(&ev_int->wait.lock, flags);
if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
ev.id = ev_code;
@@ -59,7 +60,7 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
if (copied != 0)
wake_up_locked_poll(&ev_int->wait, POLLIN);
}
- spin_unlock(&ev_int->wait.lock);
+ spin_unlock_irqrestore(&ev_int->wait.lock, flags);
return 0;
}
@@ -76,10 +77,10 @@ static unsigned int iio_event_poll(struct file *filep,
poll_wait(filep, &ev_int->wait, wait);
- spin_lock(&ev_int->wait.lock);
+ spin_lock_irq(&ev_int->wait.lock);
if (!kfifo_is_empty(&ev_int->det_events))
events = POLLIN | POLLRDNORM;
- spin_unlock(&ev_int->wait.lock);
+ spin_unlock_irq(&ev_int->wait.lock);
return events;
}
@@ -96,14 +97,14 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
if (count < sizeof(struct iio_event_data))
return -EINVAL;
- spin_lock(&ev_int->wait.lock);
+ spin_lock_irq(&ev_int->wait.lock);
if (kfifo_is_empty(&ev_int->det_events)) {
if (filep->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
goto error_unlock;
}
/* Blocking on device; waiting for something to be there */
- ret = wait_event_interruptible_locked(ev_int->wait,
+ ret = wait_event_interruptible_locked_irq(ev_int->wait,
!kfifo_is_empty(&ev_int->det_events));
if (ret)
goto error_unlock;
@@ -113,7 +114,7 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied);
error_unlock:
- spin_unlock(&ev_int->wait.lock);
+ spin_unlock_irq(&ev_int->wait.lock);
return ret ? ret : copied;
}
@@ -122,7 +123,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
{
struct iio_event_interface *ev_int = filep->private_data;
- spin_lock(&ev_int->wait.lock);
+ spin_lock_irq(&ev_int->wait.lock);
__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
/*
* In order to maintain a clean state for reopening,
@@ -130,7 +131,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
* any new __iio_push_event calls running.
*/
kfifo_reset_out(&ev_int->det_events);
- spin_unlock(&ev_int->wait.lock);
+ spin_unlock_irq(&ev_int->wait.lock);
return 0;
}
@@ -151,18 +152,18 @@ int iio_event_getfd(struct iio_dev *indio_dev)
if (ev_int == NULL)
return -ENODEV;
- spin_lock(&ev_int->wait.lock);
+ spin_lock_irq(&ev_int->wait.lock);
if (__test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
- spin_unlock(&ev_int->wait.lock);
+ spin_unlock_irq(&ev_int->wait.lock);
return -EBUSY;
}
- spin_unlock(&ev_int->wait.lock);
+ spin_unlock_irq(&ev_int->wait.lock);
fd = anon_inode_getfd("iio:event",
&iio_event_chrdev_fileops, ev_int, O_RDONLY);
if (fd < 0) {
- spin_lock(&ev_int->wait.lock);
+ spin_lock_irq(&ev_int->wait.lock);
__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
- spin_unlock(&ev_int->wait.lock);
+ spin_unlock_irq(&ev_int->wait.lock);
}
return fd;
}
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index b289915b846..795d100b4c3 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -10,6 +10,7 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/mutex.h>
+#include <linux/of.h>
#include <linux/iio/iio.h>
#include "iio_core.h"
@@ -92,6 +93,164 @@ static const struct iio_chan_spec
return chan;
}
+#ifdef CONFIG_OF
+
+static int iio_dev_node_match(struct device *dev, void *data)
+{
+ return dev->of_node == data && dev->type == &iio_device_type;
+}
+
+static int __of_iio_channel_get(struct iio_channel *channel,
+ struct device_node *np, int index)
+{
+ struct device *idev;
+ struct iio_dev *indio_dev;
+ int err;
+ struct of_phandle_args iiospec;
+
+ err = of_parse_phandle_with_args(np, "io-channels",
+ "#io-channel-cells",
+ index, &iiospec);
+ if (err)
+ return err;
+
+ idev = bus_find_device(&iio_bus_type, NULL, iiospec.np,
+ iio_dev_node_match);
+ of_node_put(iiospec.np);
+ if (idev == NULL)
+ return -EPROBE_DEFER;
+
+ indio_dev = dev_to_iio_dev(idev);
+ channel->indio_dev = indio_dev;
+ index = iiospec.args_count ? iiospec.args[0] : 0;
+ if (index >= indio_dev->num_channels) {
+ return -EINVAL;
+ goto err_put;
+ }
+ channel->channel = &indio_dev->channels[index];
+
+ return 0;
+
+err_put:
+ iio_device_put(indio_dev);
+ return err;
+}
+
+static struct iio_channel *of_iio_channel_get(struct device_node *np, int index)
+{
+ struct iio_channel *channel;
+ int err;
+
+ if (index < 0)
+ return ERR_PTR(-EINVAL);
+
+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+ if (channel == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ err = __of_iio_channel_get(channel, np, index);
+ if (err)
+ goto err_free_channel;
+
+ return channel;
+
+err_free_channel:
+ kfree(channel);
+ return ERR_PTR(err);
+}
+
+static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
+ const char *name)
+{
+ struct iio_channel *chan = NULL;
+
+ /* Walk up the tree of devices looking for a matching iio channel */
+ while (np) {
+ int index = 0;
+
+ /*
+ * For named iio channels, first look up the name in the
+ * "io-channel-names" property. If it cannot be found, the
+ * index will be an error code, and of_iio_channel_get()
+ * will fail.
+ */
+ if (name)
+ index = of_property_match_string(np, "io-channel-names",
+ name);
+ chan = of_iio_channel_get(np, index);
+ if (!IS_ERR(chan))
+ break;
+ else if (name && index >= 0) {
+ pr_err("ERROR: could not get IIO channel %s:%s(%i)\n",
+ np->full_name, name ? name : "", index);
+ return chan;
+ }
+
+ /*
+ * No matching IIO channel found on this node.
+ * If the parent node has a "io-channel-ranges" property,
+ * then we can try one of its channels.
+ */
+ np = np->parent;
+ if (np && !of_get_property(np, "io-channel-ranges", NULL))
+ break;
+ }
+ return chan;
+}
+
+static struct iio_channel *of_iio_channel_get_all(struct device *dev)
+{
+ struct iio_channel *chans;
+ int i, mapind, nummaps = 0;
+ int ret;
+
+ do {
+ ret = of_parse_phandle_with_args(dev->of_node,
+ "io-channels",
+ "#io-channel-cells",
+ nummaps, NULL);
+ if (ret < 0)
+ break;
+ } while (++nummaps);
+
+ if (nummaps == 0) /* no error, return NULL to search map table */
+ return NULL;
+
+ /* NULL terminated array to save passing size */
+ chans = kcalloc(nummaps + 1, sizeof(*chans), GFP_KERNEL);
+ if (chans == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ /* Search for OF matches */
+ for (mapind = 0; mapind < nummaps; mapind++) {
+ ret = __of_iio_channel_get(&chans[mapind], dev->of_node,
+ mapind);
+ if (ret)
+ goto error_free_chans;
+ }
+ return chans;
+
+error_free_chans:
+ for (i = 0; i < mapind; i++)
+ iio_device_put(chans[i].indio_dev);
+ kfree(chans);
+ return ERR_PTR(ret);
+}
+
+#else /* CONFIG_OF */
+
+static inline struct iio_channel *
+of_iio_channel_get_by_name(struct device_node *np, const char *name)
+{
+ return NULL;
+}
+
+static inline struct iio_channel *of_iio_channel_get_all(struct device *dev)
+{
+ return NULL;
+}
+
+#endif /* CONFIG_OF */
static struct iio_channel *iio_channel_get_sys(const char *name,
const char *channel_name)
@@ -150,7 +309,14 @@ struct iio_channel *iio_channel_get(struct device *dev,
const char *channel_name)
{
const char *name = dev ? dev_name(dev) : NULL;
+ struct iio_channel *channel;
+ if (dev) {
+ channel = of_iio_channel_get_by_name(dev->of_node,
+ channel_name);
+ if (channel != NULL)
+ return channel;
+ }
return iio_channel_get_sys(name, channel_name);
}
EXPORT_SYMBOL_GPL(iio_channel_get);
@@ -173,6 +339,11 @@ struct iio_channel *iio_channel_get_all(struct device *dev)
if (dev == NULL)
return ERR_PTR(-EINVAL);
+
+ chans = of_iio_channel_get_all(dev);
+ if (chans)
+ return chans;
+
name = dev_name(dev);
mutex_lock(&iio_map_list_lock);
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index d5b9d39d95b..5f4749e60b0 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -207,8 +207,8 @@ static const struct iio_chan_spec_ext_info adjd_s311_ext_info[] = {
.type = IIO_INTENSITY, \
.modified = 1, \
.address = (IDX_##_color), \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
.channel2 = (IIO_MOD_LIGHT_##_color), \
.scan_index = (_scan_idx), \
.scan_type = IIO_ST('u', 10, 16, 0), \
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 3d7e8c9b4be..80d68ff02d2 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -49,10 +49,10 @@ static const struct iio_chan_spec als_channels[] = {
.type = IIO_INTENSITY,
.modified = 1,
.channel2 = IIO_MOD_LIGHT_BOTH,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_ILLUM,
}
};
diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c
index 7503012ce93..5fa31a4ef82 100644
--- a/drivers/iio/light/lm3533-als.c
+++ b/drivers/iio/light/lm3533-als.c
@@ -231,7 +231,7 @@ static int lm3533_als_read_raw(struct iio_dev *indio_dev,
.channel = _channel, \
.indexed = true, \
.output = true, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
}
static const struct iio_chan_spec lm3533_als_channels[] = {
@@ -239,8 +239,8 @@ static const struct iio_chan_spec lm3533_als_channels[] = {
.type = IIO_LIGHT,
.channel = 0,
.indexed = true,
- .info_mask = (IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_RAW_SEPARATE_BIT),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
+ BIT(IIO_CHAN_INFO_RAW),
},
CHANNEL_CURRENT(0),
CHANNEL_CURRENT(1),
diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c
index fd8be69b7d0..1f529f36f13 100644
--- a/drivers/iio/light/tsl2563.c
+++ b/drivers/iio/light/tsl2563.c
@@ -530,14 +530,14 @@ static const struct iio_chan_spec tsl2563_channels[] = {
{
.type = IIO_LIGHT,
.indexed = 1,
- .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
.channel = 0,
}, {
.type = IIO_INTENSITY,
.modified = 1,
.channel2 = IIO_MOD_LIGHT_BOTH,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_CALIBSCALE),
.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH,
@@ -546,8 +546,8 @@ static const struct iio_chan_spec tsl2563_channels[] = {
.type = IIO_INTENSITY,
.modified = 1,
.channel2 = IIO_MOD_LIGHT_IR,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_CALIBSCALE),
}
};
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 2aa748fbdc0..1014943d949 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -93,11 +93,11 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
static const struct iio_chan_spec vcnl4000_channels[] = {
{
.type = IIO_LIGHT,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
}, {
.type = IIO_PROXIMITY,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
}
};
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index cd29be54f64..bd1cfb66669 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -3,6 +3,17 @@
#
menu "Magnetometer sensors"
+config AK8975
+ tristate "Asahi Kasei AK8975 3-Axis Magnetometer"
+ depends on I2C
+ depends on GPIOLIB
+ help
+ Say yes here to build support for Asahi Kasei AK8975 3-Axis
+ Magnetometer.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ak8975.
+
config HID_SENSOR_MAGNETOMETER_3D
depends on HID_SENSOR_HUB
select IIO_BUFFER
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index e78672876dc..7f328e37fba 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -2,6 +2,7 @@
# Makefile for industrial I/O Magnetometer sensor drivers
#
+obj-$(CONFIG_AK8975) += ak8975.o
obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index 28f080e9eee..af6c320a534 100644
--- a/drivers/staging/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -94,7 +94,6 @@ struct ak8975_data {
long raw_to_gauss[3];
u8 reg_cache[AK8975_MAX_REGS];
int eoc_gpio;
- int eoc_irq;
};
static const int ak8975_index_to_reg[] = {
@@ -124,36 +123,6 @@ static int ak8975_write_data(struct i2c_client *client,
}
/*
- * Helper function to read a contiguous set of the I2C device's registers.
- */
-static int ak8975_read_data(struct i2c_client *client,
- u8 reg, u8 length, u8 *buffer)
-{
- int ret;
- struct i2c_msg msg[2] = {
- {
- .addr = client->addr,
- .flags = I2C_M_NOSTART,
- .len = 1,
- .buf = &reg,
- }, {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .len = length,
- .buf = buffer,
- }
- };
-
- ret = i2c_transfer(client->adapter, msg, 2);
- if (ret < 0) {
- dev_err(&client->dev, "Read from device fails\n");
- return ret;
- }
-
- return 0;
-}
-
-/*
* Perform some start-of-day setup, including reading the asa calibration
* values and caching them.
*/
@@ -165,11 +134,12 @@ static int ak8975_setup(struct i2c_client *client)
int ret;
/* Confirm that the device we're talking to is really an AK8975. */
- ret = ak8975_read_data(client, AK8975_REG_WIA, 1, &device_id);
+ ret = i2c_smbus_read_byte_data(client, AK8975_REG_WIA);
if (ret < 0) {
dev_err(&client->dev, "Error reading WIA\n");
return ret;
}
+ device_id = ret;
if (device_id != AK8975_DEVICE_ID) {
dev_err(&client->dev, "Device ak8975 not found\n");
return -ENODEV;
@@ -187,7 +157,8 @@ static int ak8975_setup(struct i2c_client *client)
}
/* Get asa data and store in the device data. */
- ret = ak8975_read_data(client, AK8975_REG_ASAX, 3, data->asa);
+ ret = i2c_smbus_read_i2c_block_data(client, AK8975_REG_ASAX,
+ 3, data->asa);
if (ret < 0) {
dev_err(&client->dev, "Not able to read asa data\n");
return ret;
@@ -249,7 +220,6 @@ static int ak8975_setup(struct i2c_client *client)
static int wait_conversion_complete_gpio(struct ak8975_data *data)
{
struct i2c_client *client = data->client;
- u8 read_status;
u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
int ret;
@@ -265,12 +235,11 @@ static int wait_conversion_complete_gpio(struct ak8975_data *data)
return -EINVAL;
}
- ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status);
- if (ret < 0) {
+ ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1);
+ if (ret < 0)
dev_err(&client->dev, "Error in reading ST1\n");
- return ret;
- }
- return read_status;
+
+ return ret;
}
static int wait_conversion_complete_polled(struct ak8975_data *data)
@@ -283,11 +252,12 @@ static int wait_conversion_complete_polled(struct ak8975_data *data)
/* Wait for the conversion to complete. */
while (timeout_ms) {
msleep(AK8975_CONVERSION_DONE_POLL_TIME);
- ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status);
+ ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1);
if (ret < 0) {
dev_err(&client->dev, "Error in reading ST1\n");
return ret;
}
+ read_status = ret;
if (read_status)
break;
timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
@@ -308,7 +278,6 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
struct i2c_client *client = data->client;
u16 meas_reg;
s16 raw;
- u8 read_status;
int ret;
mutex_lock(&data->lock);
@@ -332,18 +301,15 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
if (ret < 0)
goto exit;
- read_status = ret;
-
- if (read_status & AK8975_REG_ST1_DRDY_MASK) {
- ret = ak8975_read_data(client, AK8975_REG_ST2, 1, &read_status);
+ if (ret & AK8975_REG_ST1_DRDY_MASK) {
+ ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST2);
if (ret < 0) {
dev_err(&client->dev, "Error in reading ST2\n");
goto exit;
}
- if (read_status & (AK8975_REG_ST2_DERR_MASK |
- AK8975_REG_ST2_HOFL_MASK)) {
- dev_err(&client->dev, "ST2 status error 0x%x\n",
- read_status);
+ if (ret & (AK8975_REG_ST2_DERR_MASK |
+ AK8975_REG_ST2_HOFL_MASK)) {
+ dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
ret = -EINVAL;
goto exit;
}
@@ -351,12 +317,12 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
/* Read the flux value from the appropriate register
(the register is specified in the iio device attributes). */
- ret = ak8975_read_data(client, ak8975_index_to_reg[index],
- 2, (u8 *)&meas_reg);
+ ret = i2c_smbus_read_word_data(client, ak8975_index_to_reg[index]);
if (ret < 0) {
dev_err(&client->dev, "Read axis data fails\n");
goto exit;
}
+ meas_reg = ret;
mutex_unlock(&data->lock);
@@ -395,8 +361,8 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
.type = IIO_MAGN, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.address = index, \
}
@@ -452,7 +418,6 @@ static int ak8975_probe(struct i2c_client *client,
data->client = client;
mutex_init(&data->lock);
- data->eoc_irq = client->irq;
data->eoc_gpio = eoc_gpio;
indio_dev->dev.parent = &client->dev;
indio_dev->channels = ak8975_channels;
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index d8d01265220..99f4e494513 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -60,28 +60,28 @@ static const struct iio_chan_spec magn_3d_channels[] = {
.type = IIO_MAGN,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_X,
}, {
.type = IIO_MAGN,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_Y,
}, {
.type = IIO_MAGN,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
- IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_Z,
}
};
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 093f10c88cc..4e8a1794f50 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -110,19 +110,15 @@ source "drivers/staging/nvec/Kconfig"
source "drivers/staging/media/Kconfig"
-source "drivers/staging/net/Kconfig"
-
source "drivers/staging/android/Kconfig"
source "drivers/staging/ozwpan/Kconfig"
-source "drivers/staging/ccg/Kconfig"
-
source "drivers/staging/gdm72xx/Kconfig"
source "drivers/staging/csr/Kconfig"
-source "drivers/staging/omap-thermal/Kconfig"
+source "drivers/staging/ti-soc-thermal/Kconfig"
source "drivers/staging/silicom/Kconfig"
@@ -140,4 +136,8 @@ source "drivers/staging/zcache/Kconfig"
source "drivers/staging/goldfish/Kconfig"
+source "drivers/staging/netlogic/Kconfig"
+
+source "drivers/staging/dwc2/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index fa41b04cf4c..415772ea306 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -4,7 +4,6 @@
obj-$(CONFIG_STAGING) += staging.o
obj-y += media/
-obj-y += net/
obj-$(CONFIG_ET131X) += et131x/
obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_USBIP_CORE) += usbip/
@@ -23,6 +22,7 @@ obj-$(CONFIG_RTS5139) += rts5139/
obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_IDE_PHISON) += phison/
obj-$(CONFIG_LINE6_USB) += line6/
+obj-$(CONFIG_NETLOGIC_XLR_NET) += netlogic/
obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
obj-$(CONFIG_VT6655) += vt6655/
@@ -50,10 +50,9 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
obj-$(CONFIG_MFD_NVEC) += nvec/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
-obj-$(CONFIG_USB_G_CCG) += ccg/
obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
obj-$(CONFIG_CSR_WIFI) += csr/
-obj-$(CONFIG_OMAP_BANDGAP) += omap-thermal/
+obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/
obj-$(CONFIG_CED1401) += ced1401/
obj-$(CONFIG_DRM_IMX) += imx-drm/
@@ -62,3 +61,4 @@ obj-$(CONFIG_SB105X) += sb105x/
obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
obj-$(CONFIG_ZCACHE) += zcache/
obj-$(CONFIG_GOLDFISH) += goldfish/
+obj-$(CONFIG_USB_DWC2) += dwc2/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 465a28c08f2..9f61d46da15 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -22,7 +22,7 @@ config ANDROID_BINDER_IPC
config ASHMEM
bool "Enable the Anonymous Shared Memory Subsystem"
default n
- depends on SHMEM || TINY_SHMEM
+ depends on SHMEM
---help---
The ashmem subsystem is a new shared memory allocator, similar to
POSIX SHM but with different behavior and sporting a simpler
@@ -72,6 +72,33 @@ config ANDROID_INTF_ALARM_DEV
elapsed realtime, and a non-wakeup alarm on the monotonic clock.
Also exports the alarm interface to user-space.
+config SYNC
+ bool "Synchronization framework"
+ default n
+ select ANON_INODES
+ help
+ This option enables the framework for synchronization between multiple
+ drivers. Sync implementations can take advantage of hardware
+ synchronization built into devices like GPUs.
+
+config SW_SYNC
+ bool "Software synchronization objects"
+ default n
+ depends on SYNC
+ help
+ A sync object driver that uses a 32bit counter to coordinate
+ syncrhronization. Useful when there is no hardware primitive backing
+ the synchronization.
+
+config SW_SYNC_USER
+ bool "Userspace API for SW_SYNC"
+ default n
+ depends on SW_SYNC
+ help
+ Provides a user space API to the sw sync object.
+ *WARNING* improper use of this can result in deadlocking kernel
+ drivers from userspace.
+
endif # if ANDROID
endmenu
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index b35a631734d..c136299e05a 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -7,3 +7,5 @@ obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o
+obj-$(CONFIG_SYNC) += sync.o
+obj-$(CONFIG_SW_SYNC) += sw_sync.o
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 634b9ae713e..e681bdd9aa5 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -414,20 +414,29 @@ out:
static int set_name(struct ashmem_area *asma, void __user *name)
{
int ret = 0;
+ char local_name[ASHMEM_NAME_LEN];
- mutex_lock(&ashmem_mutex);
+ /*
+ * Holding the ashmem_mutex while doing a copy_from_user might cause
+ * an data abort which would try to access mmap_sem. If another
+ * thread has invoked ashmem_mmap then it will be holding the
+ * semaphore and will be waiting for ashmem_mutex, there by leading to
+ * deadlock. We'll release the mutex and take the name to a local
+ * variable that does not need protection and later copy the local
+ * variable to the structure member with lock held.
+ */
+ if (copy_from_user(local_name, name, ASHMEM_NAME_LEN))
+ return -EFAULT;
+ mutex_lock(&ashmem_mutex);
/* cannot change an existing mapping's name */
if (unlikely(asma->file)) {
ret = -EINVAL;
goto out;
}
-
- if (unlikely(copy_from_user(asma->name + ASHMEM_NAME_PREFIX_LEN,
- name, ASHMEM_NAME_LEN)))
- ret = -EFAULT;
+ memcpy(asma->name + ASHMEM_NAME_PREFIX_LEN,
+ local_name, ASHMEM_NAME_LEN);
asma->name[ASHMEM_FULL_NAME_LEN-1] = '\0';
-
out:
mutex_unlock(&ashmem_mutex);
@@ -437,26 +446,36 @@ out:
static int get_name(struct ashmem_area *asma, void __user *name)
{
int ret = 0;
+ size_t len;
+ /*
+ * Have a local variable to which we'll copy the content
+ * from asma with the lock held. Later we can copy this to the user
+ * space safely without holding any locks. So even if we proceed to
+ * wait for mmap_sem, it won't lead to deadlock.
+ */
+ char local_name[ASHMEM_NAME_LEN];
mutex_lock(&ashmem_mutex);
if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') {
- size_t len;
/*
* Copying only `len', instead of ASHMEM_NAME_LEN, bytes
* prevents us from revealing one user's stack to another.
*/
len = strlen(asma->name + ASHMEM_NAME_PREFIX_LEN) + 1;
- if (unlikely(copy_to_user(name,
- asma->name + ASHMEM_NAME_PREFIX_LEN, len)))
- ret = -EFAULT;
+ memcpy(local_name, asma->name + ASHMEM_NAME_PREFIX_LEN, len);
} else {
- if (unlikely(copy_to_user(name, ASHMEM_NAME_DEF,
- sizeof(ASHMEM_NAME_DEF))))
- ret = -EFAULT;
+ len = sizeof(ASHMEM_NAME_DEF);
+ memcpy(local_name, ASHMEM_NAME_DEF, len);
}
mutex_unlock(&ashmem_mutex);
+ /*
+ * Now we are just copying from the stack variable to userland
+ * No lock held
+ */
+ if (unlikely(copy_to_user(name, local_name, len)))
+ ret = -EFAULT;
return ret;
}
@@ -683,6 +702,23 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return ret;
}
+/* support of 32bit userspace on 64bit platforms */
+#ifdef CONFIG_COMPAT
+static long compat_ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+
+ switch (cmd) {
+ case COMPAT_ASHMEM_SET_SIZE:
+ cmd = ASHMEM_SET_SIZE;
+ break;
+ case COMPAT_ASHMEM_SET_PROT_MASK:
+ cmd = ASHMEM_SET_PROT_MASK;
+ break;
+ }
+ return ashmem_ioctl(file, cmd, arg);
+}
+#endif
+
static const struct file_operations ashmem_fops = {
.owner = THIS_MODULE,
.open = ashmem_open,
@@ -691,7 +727,9 @@ static const struct file_operations ashmem_fops = {
.llseek = ashmem_llseek,
.mmap = ashmem_mmap,
.unlocked_ioctl = ashmem_ioctl,
- .compat_ioctl = ashmem_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = compat_ashmem_ioctl,
+#endif
};
static struct miscdevice ashmem_misc = {
diff --git a/drivers/staging/android/ashmem.h b/drivers/staging/android/ashmem.h
index 1976b10ef93..8dc0f0d3adf 100644
--- a/drivers/staging/android/ashmem.h
+++ b/drivers/staging/android/ashmem.h
@@ -14,6 +14,7 @@
#include <linux/limits.h>
#include <linux/ioctl.h>
+#include <linux/compat.h>
#define ASHMEM_NAME_LEN 256
@@ -45,4 +46,10 @@ struct ashmem_pin {
#define ASHMEM_GET_PIN_STATUS _IO(__ASHMEMIOC, 9)
#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
+/* support of 32bit userspace on 64bit platforms */
+#ifdef CONFIG_COMPAT
+#define COMPAT_ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, compat_size_t)
+#define COMPAT_ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned int)
+#endif
+
#endif /* _LINUX_ASHMEM_H */
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 24456a0de6b..1567ac296b3 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -2878,82 +2878,109 @@ static int binder_release(struct inode *nodp, struct file *filp)
return 0;
}
+static int binder_node_release(struct binder_node *node, int refs)
+{
+ struct binder_ref *ref;
+ int death = 0;
+
+ list_del_init(&node->work.entry);
+ binder_release_work(&node->async_todo);
+
+ if (hlist_empty(&node->refs)) {
+ kfree(node);
+ binder_stats_deleted(BINDER_STAT_NODE);
+
+ return refs;
+ }
+
+ node->proc = NULL;
+ node->local_strong_refs = 0;
+ node->local_weak_refs = 0;
+ hlist_add_head(&node->dead_node, &binder_dead_nodes);
+
+ hlist_for_each_entry(ref, &node->refs, node_entry) {
+ refs++;
+
+ if (!ref->death)
+ goto out;
+
+ death++;
+
+ if (list_empty(&ref->death->work.entry)) {
+ ref->death->work.type = BINDER_WORK_DEAD_BINDER;
+ list_add_tail(&ref->death->work.entry,
+ &ref->proc->todo);
+ wake_up_interruptible(&ref->proc->wait);
+ } else
+ BUG();
+ }
+
+out:
+ binder_debug(BINDER_DEBUG_DEAD_BINDER,
+ "node %d now dead, refs %d, death %d\n",
+ node->debug_id, refs, death);
+
+ return refs;
+}
+
static void binder_deferred_release(struct binder_proc *proc)
{
struct binder_transaction *t;
struct rb_node *n;
- int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
+ int threads, nodes, incoming_refs, outgoing_refs, buffers,
+ active_transactions, page_count;
BUG_ON(proc->vma);
BUG_ON(proc->files);
hlist_del(&proc->proc_node);
+
if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
binder_debug(BINDER_DEBUG_DEAD_BINDER,
- "binder_release: %d context_mgr_node gone\n",
- proc->pid);
+ "%s: %d context_mgr_node gone\n",
+ __func__, proc->pid);
binder_context_mgr_node = NULL;
}
threads = 0;
active_transactions = 0;
while ((n = rb_first(&proc->threads))) {
- struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
+ struct binder_thread *thread;
+
+ thread = rb_entry(n, struct binder_thread, rb_node);
threads++;
active_transactions += binder_free_thread(proc, thread);
}
+
nodes = 0;
incoming_refs = 0;
while ((n = rb_first(&proc->nodes))) {
- struct binder_node *node = rb_entry(n, struct binder_node, rb_node);
+ struct binder_node *node;
+ node = rb_entry(n, struct binder_node, rb_node);
nodes++;
rb_erase(&node->rb_node, &proc->nodes);
- list_del_init(&node->work.entry);
- binder_release_work(&node->async_todo);
- if (hlist_empty(&node->refs)) {
- kfree(node);
- binder_stats_deleted(BINDER_STAT_NODE);
- } else {
- struct binder_ref *ref;
- int death = 0;
-
- node->proc = NULL;
- node->local_strong_refs = 0;
- node->local_weak_refs = 0;
- hlist_add_head(&node->dead_node, &binder_dead_nodes);
-
- hlist_for_each_entry(ref, &node->refs, node_entry) {
- incoming_refs++;
- if (ref->death) {
- death++;
- if (list_empty(&ref->death->work.entry)) {
- ref->death->work.type = BINDER_WORK_DEAD_BINDER;
- list_add_tail(&ref->death->work.entry, &ref->proc->todo);
- wake_up_interruptible(&ref->proc->wait);
- } else
- BUG();
- }
- }
- binder_debug(BINDER_DEBUG_DEAD_BINDER,
- "node %d now dead, refs %d, death %d\n",
- node->debug_id, incoming_refs, death);
- }
+ incoming_refs = binder_node_release(node, incoming_refs);
}
+
outgoing_refs = 0;
while ((n = rb_first(&proc->refs_by_desc))) {
- struct binder_ref *ref = rb_entry(n, struct binder_ref,
- rb_node_desc);
+ struct binder_ref *ref;
+
+ ref = rb_entry(n, struct binder_ref, rb_node_desc);
outgoing_refs++;
binder_delete_ref(ref);
}
+
binder_release_work(&proc->todo);
binder_release_work(&proc->delivered_death);
- buffers = 0;
+ buffers = 0;
while ((n = rb_first(&proc->allocated_buffers))) {
- struct binder_buffer *buffer = rb_entry(n, struct binder_buffer,
- rb_node);
+ struct binder_buffer *buffer;
+
+ buffer = rb_entry(n, struct binder_buffer, rb_node);
+
t = buffer->transaction;
if (t) {
t->buffer = NULL;
@@ -2962,6 +2989,7 @@ static void binder_deferred_release(struct binder_proc *proc)
proc->pid, t->debug_id);
/*BUG();*/
}
+
binder_free_buf(proc, buffer);
buffers++;
}
@@ -2971,18 +2999,20 @@ static void binder_deferred_release(struct binder_proc *proc)
page_count = 0;
if (proc->pages) {
int i;
+
for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) {
- if (proc->pages[i]) {
- void *page_addr = proc->buffer + i * PAGE_SIZE;
- binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
- "binder_release: %d: page %d at %p not freed\n",
- proc->pid, i,
- page_addr);
- unmap_kernel_range((unsigned long)page_addr,
- PAGE_SIZE);
- __free_page(proc->pages[i]);
- page_count++;
- }
+ void *page_addr;
+
+ if (!proc->pages[i])
+ continue;
+
+ page_addr = proc->buffer + i * PAGE_SIZE;
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "%s: %d: page %d at %p not freed\n",
+ __func__, proc->pid, i, page_addr);
+ unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
+ __free_page(proc->pages[i]);
+ page_count++;
}
kfree(proc->pages);
vfree(proc->buffer);
@@ -2991,9 +3021,9 @@ static void binder_deferred_release(struct binder_proc *proc)
put_task_struct(proc->tsk);
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
- "binder_release: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n",
- proc->pid, threads, nodes, incoming_refs, outgoing_refs,
- active_transactions, buffers, page_count);
+ "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n",
+ __func__, proc->pid, threads, nodes, incoming_refs,
+ outgoing_refs, active_transactions, buffers, page_count);
kfree(proc);
}
diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h
index f240464effd..dbe81ceca1b 100644
--- a/drivers/staging/android/binder.h
+++ b/drivers/staging/android/binder.h
@@ -85,11 +85,11 @@ struct binder_version {
#define BINDER_CURRENT_PROTOCOL_VERSION 7
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
-#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, int64_t)
+#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64)
#define BINDER_SET_MAX_THREADS _IOW('b', 5, size_t)
-#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, int)
-#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int)
-#define BINDER_THREAD_EXIT _IOW('b', 8, int)
+#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32)
+#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32)
+#define BINDER_THREAD_EXIT _IOW('b', 8, __s32)
#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
/*
diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c
index dbc63cbb4d3..b14a5574255 100644
--- a/drivers/staging/android/logger.c
+++ b/drivers/staging/android/logger.c
@@ -68,6 +68,8 @@ static LIST_HEAD(log_list);
* @log: The associated log
* @list: The associated entry in @logger_log's list
* @r_off: The current read head offset.
+ * @r_all: Reader can read all entries
+ * @r_ver: Reader ABI version
*
* This object lives from open to release, so we don't need additional
* reference counting. The structure is protected by log->mutex.
@@ -76,6 +78,8 @@ struct logger_reader {
struct logger_log *log;
struct list_head list;
size_t r_off;
+ bool r_all;
+ int r_ver;
};
/* logger_offset - returns index 'n' into the log via (optimized) modulus */
@@ -109,8 +113,29 @@ static inline struct logger_log *file_get_log(struct file *file)
}
/*
- * get_entry_len - Grabs the length of the payload of the next entry starting
- * from 'off'.
+ * get_entry_header - returns a pointer to the logger_entry header within
+ * 'log' starting at offset 'off'. A temporary logger_entry 'scratch' must
+ * be provided. Typically the return value will be a pointer within
+ * 'logger->buf'. However, a pointer to 'scratch' may be returned if
+ * the log entry spans the end and beginning of the circular buffer.
+ */
+static struct logger_entry *get_entry_header(struct logger_log *log,
+ size_t off, struct logger_entry *scratch)
+{
+ size_t len = min(sizeof(struct logger_entry), log->size - off);
+ if (len != sizeof(struct logger_entry)) {
+ memcpy(((void *) scratch), log->buffer + off, len);
+ memcpy(((void *) scratch) + len, log->buffer,
+ sizeof(struct logger_entry) - len);
+ return scratch;
+ }
+
+ return (struct logger_entry *) (log->buffer + off);
+}
+
+/*
+ * get_entry_msg_len - Grabs the length of the message of the entry
+ * starting from from 'off'.
*
* An entry length is 2 bytes (16 bits) in host endian order.
* In the log, the length does not include the size of the log entry structure.
@@ -118,20 +143,45 @@ static inline struct logger_log *file_get_log(struct file *file)
*
* Caller needs to hold log->mutex.
*/
-static __u32 get_entry_len(struct logger_log *log, size_t off)
+static __u32 get_entry_msg_len(struct logger_log *log, size_t off)
{
- __u16 val;
+ struct logger_entry scratch;
+ struct logger_entry *entry;
- /* copy 2 bytes from buffer, in memcpy order, */
- /* handling possible wrap at end of buffer */
+ entry = get_entry_header(log, off, &scratch);
+ return entry->len;
+}
- ((__u8 *)&val)[0] = log->buffer[off];
- if (likely(off+1 < log->size))
- ((__u8 *)&val)[1] = log->buffer[off+1];
+static size_t get_user_hdr_len(int ver)
+{
+ if (ver < 2)
+ return sizeof(struct user_logger_entry_compat);
else
- ((__u8 *)&val)[1] = log->buffer[0];
+ return sizeof(struct logger_entry);
+}
- return sizeof(struct logger_entry) + val;
+static ssize_t copy_header_to_user(int ver, struct logger_entry *entry,
+ char __user *buf)
+{
+ void *hdr;
+ size_t hdr_len;
+ struct user_logger_entry_compat v1;
+
+ if (ver < 2) {
+ v1.len = entry->len;
+ v1.__pad = 0;
+ v1.pid = entry->pid;
+ v1.tid = entry->tid;
+ v1.sec = entry->sec;
+ v1.nsec = entry->nsec;
+ hdr = &v1;
+ hdr_len = sizeof(struct user_logger_entry_compat);
+ } else {
+ hdr = entry;
+ hdr_len = sizeof(struct logger_entry);
+ }
+
+ return copy_to_user(buf, hdr, hdr_len);
}
/*
@@ -145,15 +195,31 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
char __user *buf,
size_t count)
{
+ struct logger_entry scratch;
+ struct logger_entry *entry;
size_t len;
+ size_t msg_start;
/*
- * We read from the log in two disjoint operations. First, we read from
- * the current read head offset up to 'count' bytes or to the end of
+ * First, copy the header to userspace, using the version of
+ * the header requested
+ */
+ entry = get_entry_header(log, reader->r_off, &scratch);
+ if (copy_header_to_user(reader->r_ver, entry, buf))
+ return -EFAULT;
+
+ count -= get_user_hdr_len(reader->r_ver);
+ buf += get_user_hdr_len(reader->r_ver);
+ msg_start = logger_offset(log,
+ reader->r_off + sizeof(struct logger_entry));
+
+ /*
+ * We read from the msg in two disjoint operations. First, we read from
+ * the current msg head offset up to 'count' bytes or to the end of
* the log, whichever comes first.
*/
- len = min(count, log->size - reader->r_off);
- if (copy_to_user(buf, log->buffer + reader->r_off, len))
+ len = min(count, log->size - msg_start);
+ if (copy_to_user(buf, log->buffer + msg_start, len))
return -EFAULT;
/*
@@ -164,9 +230,34 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
if (copy_to_user(buf + len, log->buffer, count - len))
return -EFAULT;
- reader->r_off = logger_offset(log, reader->r_off + count);
+ reader->r_off = logger_offset(log, reader->r_off +
+ sizeof(struct logger_entry) + count);
- return count;
+ return count + get_user_hdr_len(reader->r_ver);
+}
+
+/*
+ * get_next_entry_by_uid - Starting at 'off', returns an offset into
+ * 'log->buffer' which contains the first entry readable by 'euid'
+ */
+static size_t get_next_entry_by_uid(struct logger_log *log,
+ size_t off, uid_t euid)
+{
+ while (off != log->w_off) {
+ struct logger_entry *entry;
+ struct logger_entry scratch;
+ size_t next_len;
+
+ entry = get_entry_header(log, off, &scratch);
+
+ if (entry->euid == euid)
+ return off;
+
+ next_len = sizeof(struct logger_entry) + entry->len;
+ off = logger_offset(log, off + next_len);
+ }
+
+ return off;
}
/*
@@ -178,7 +269,7 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
* - If there are no log entries to read, blocks until log is written to
* - Atomically reads exactly one log entry
*
- * Optimal read size is LOGGER_ENTRY_MAX_LEN. Will set errno to EINVAL if read
+ * Will set errno to EINVAL if read
* buffer is insufficient to hold next entry.
*/
static ssize_t logger_read(struct file *file, char __user *buf,
@@ -219,6 +310,10 @@ start:
mutex_lock(&log->mutex);
+ if (!reader->r_all)
+ reader->r_off = get_next_entry_by_uid(log,
+ reader->r_off, current_euid());
+
/* is there still something to read or did we race? */
if (unlikely(log->w_off == reader->r_off)) {
mutex_unlock(&log->mutex);
@@ -226,7 +321,8 @@ start:
}
/* get the size of the next entry */
- ret = get_entry_len(log, reader->r_off);
+ ret = get_user_hdr_len(reader->r_ver) +
+ get_entry_msg_len(log, reader->r_off);
if (count < ret) {
ret = -EINVAL;
goto out;
@@ -252,7 +348,8 @@ static size_t get_next_entry(struct logger_log *log, size_t off, size_t len)
size_t count = 0;
do {
- size_t nr = get_entry_len(log, off);
+ size_t nr = sizeof(struct logger_entry) +
+ get_entry_msg_len(log, off);
off = logger_offset(log, off + nr);
count += nr;
} while (count < len);
@@ -382,7 +479,9 @@ static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
header.tid = current->pid;
header.sec = now.tv_sec;
header.nsec = now.tv_nsec;
+ header.euid = current_euid();
header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD);
+ header.hdr_size = sizeof(struct logger_entry);
/* null writes succeed, return zero */
if (unlikely(!header.len))
@@ -463,6 +562,10 @@ static int logger_open(struct inode *inode, struct file *file)
return -ENOMEM;
reader->log = log;
+ reader->r_ver = 1;
+ reader->r_all = in_egroup_p(inode->i_gid) ||
+ capable(CAP_SYSLOG);
+
INIT_LIST_HEAD(&reader->list);
mutex_lock(&log->mutex);
@@ -522,6 +625,10 @@ static unsigned int logger_poll(struct file *file, poll_table *wait)
poll_wait(file, &log->wq, wait);
mutex_lock(&log->mutex);
+ if (!reader->r_all)
+ reader->r_off = get_next_entry_by_uid(log,
+ reader->r_off, current_euid());
+
if (log->w_off != reader->r_off)
ret |= POLLIN | POLLRDNORM;
mutex_unlock(&log->mutex);
@@ -529,11 +636,25 @@ static unsigned int logger_poll(struct file *file, poll_table *wait)
return ret;
}
+static long logger_set_version(struct logger_reader *reader, void __user *arg)
+{
+ int version;
+ if (copy_from_user(&version, arg, sizeof(int)))
+ return -EFAULT;
+
+ if ((version < 1) || (version > 2))
+ return -EINVAL;
+
+ reader->r_ver = version;
+ return 0;
+}
+
static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct logger_log *log = file_get_log(file);
struct logger_reader *reader;
- long ret = -ENOTTY;
+ long ret = -EINVAL;
+ void __user *argp = (void __user *) arg;
mutex_lock(&log->mutex);
@@ -558,8 +679,14 @@ static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
reader = file->private_data;
+
+ if (!reader->r_all)
+ reader->r_off = get_next_entry_by_uid(log,
+ reader->r_off, current_euid());
+
if (log->w_off != reader->r_off)
- ret = get_entry_len(log, reader->r_off);
+ ret = get_user_hdr_len(reader->r_ver) +
+ get_entry_msg_len(log, reader->r_off);
else
ret = 0;
break;
@@ -568,11 +695,32 @@ static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ret = -EBADF;
break;
}
+ if (!(in_egroup_p(file->f_dentry->d_inode->i_gid) ||
+ capable(CAP_SYSLOG))) {
+ ret = -EPERM;
+ break;
+ }
list_for_each_entry(reader, &log->readers, list)
reader->r_off = log->w_off;
log->head = log->w_off;
ret = 0;
break;
+ case LOGGER_GET_VERSION:
+ if (!(file->f_mode & FMODE_READ)) {
+ ret = -EBADF;
+ break;
+ }
+ reader = file->private_data;
+ ret = reader->r_ver;
+ break;
+ case LOGGER_SET_VERSION:
+ if (!(file->f_mode & FMODE_READ)) {
+ ret = -EBADF;
+ break;
+ }
+ reader = file->private_data;
+ ret = logger_set_version(reader, argp);
+ break;
}
mutex_unlock(&log->mutex);
@@ -592,8 +740,8 @@ static const struct file_operations logger_fops = {
};
/*
- * Log size must be a power of two, greater than LOGGER_ENTRY_MAX_LEN,
- * and less than LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
+ * Log size must must be a power of two, and greater than
+ * (LOGGER_ENTRY_MAX_PAYLOAD + sizeof(struct logger_entry)).
*/
static int __init create_log(char *log_name, int size)
{
diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h
index 9b929a8c746..cc6bbd99c8e 100644
--- a/drivers/staging/android/logger.h
+++ b/drivers/staging/android/logger.h
@@ -21,7 +21,7 @@
#include <linux/ioctl.h>
/**
- * struct logger_entry - defines a single entry that is given to a logger
+ * struct user_logger_entry_compat - defines a single entry that is given to a logger
* @len: The length of the payload
* @__pad: Two bytes of padding that appear to be required
* @pid: The generating process' process ID
@@ -29,8 +29,12 @@
* @sec: The number of seconds that have elapsed since the Epoch
* @nsec: The number of nanoseconds that have elapsed since @sec
* @msg: The message that is to be logged
+ *
+ * The userspace structure for version 1 of the logger_entry ABI.
+ * This structure is returned to userspace unless the caller requests
+ * an upgrade to a newer ABI version.
*/
-struct logger_entry {
+struct user_logger_entry_compat {
__u16 len;
__u16 __pad;
__s32 pid;
@@ -40,14 +44,38 @@ struct logger_entry {
char msg[0];
};
+/**
+ * struct logger_entry - defines a single entry that is given to a logger
+ * @len: The length of the payload
+ * @hdr_size: sizeof(struct logger_entry_v2)
+ * @pid: The generating process' process ID
+ * @tid: The generating process' thread ID
+ * @sec: The number of seconds that have elapsed since the Epoch
+ * @nsec: The number of nanoseconds that have elapsed since @sec
+ * @euid: Effective UID of logger
+ * @msg: The message that is to be logged
+ *
+ * The structure for version 2 of the logger_entry ABI.
+ * This structure is returned to userspace if ioctl(LOGGER_SET_VERSION)
+ * is called with version >= 2
+ */
+struct logger_entry {
+ __u16 len;
+ __u16 hdr_size;
+ __s32 pid;
+ __s32 tid;
+ __s32 sec;
+ __s32 nsec;
+ uid_t euid;
+ char msg[0];
+};
+
#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */
#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */
#define LOGGER_LOG_SYSTEM "log_system" /* system/framework messages */
#define LOGGER_LOG_MAIN "log_main" /* everything else */
-#define LOGGER_ENTRY_MAX_LEN (4*1024)
-#define LOGGER_ENTRY_MAX_PAYLOAD \
- (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
+#define LOGGER_ENTRY_MAX_PAYLOAD 4076
#define __LOGGERIO 0xAE
@@ -55,5 +83,7 @@ struct logger_entry {
#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */
#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */
#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */
+#define LOGGER_GET_VERSION _IO(__LOGGERIO, 5) /* abi version */
+#define LOGGER_SET_VERSION _IO(__LOGGERIO, 6) /* abi version */
#endif /* _LINUX_LOGGER_H */
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 3b91b0fd4de..fe74494868e 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -30,16 +30,19 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/oom.h>
#include <linux/sched.h>
+#include <linux/swap.h>
#include <linux/rcupdate.h>
#include <linux/profile.h>
#include <linux/notifier.h>
-static uint32_t lowmem_debug_level = 2;
+static uint32_t lowmem_debug_level = 1;
static short lowmem_adj[6] = {
0,
1,
@@ -60,7 +63,7 @@ static unsigned long lowmem_deathpending_timeout;
#define lowmem_print(level, x...) \
do { \
if (lowmem_debug_level >= (level)) \
- printk(x); \
+ pr_info(x); \
} while (0)
static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
@@ -74,7 +77,7 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
int selected_tasksize = 0;
short selected_oom_score_adj;
int array_size = ARRAY_SIZE(lowmem_adj);
- int other_free = global_page_state(NR_FREE_PAGES);
+ int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
int other_file = global_page_state(NR_FILE_PAGES) -
global_page_state(NR_SHMEM);
diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c
new file mode 100644
index 00000000000..4928f93bdf3
--- /dev/null
+++ b/drivers/staging/android/sw_sync.c
@@ -0,0 +1,264 @@
+/*
+ * drivers/base/sw_sync.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/kernel.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+
+#include "sw_sync.h"
+
+static int sw_sync_cmp(u32 a, u32 b)
+{
+ if (a == b)
+ return 0;
+
+ return ((s32)a - (s32)b) < 0 ? -1 : 1;
+}
+
+struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value)
+{
+ struct sw_sync_pt *pt;
+
+ pt = (struct sw_sync_pt *)
+ sync_pt_create(&obj->obj, sizeof(struct sw_sync_pt));
+
+ pt->value = value;
+
+ return (struct sync_pt *)pt;
+}
+EXPORT_SYMBOL(sw_sync_pt_create);
+
+static struct sync_pt *sw_sync_pt_dup(struct sync_pt *sync_pt)
+{
+ struct sw_sync_pt *pt = (struct sw_sync_pt *) sync_pt;
+ struct sw_sync_timeline *obj =
+ (struct sw_sync_timeline *)sync_pt->parent;
+
+ return (struct sync_pt *) sw_sync_pt_create(obj, pt->value);
+}
+
+static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt)
+{
+ struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+ struct sw_sync_timeline *obj =
+ (struct sw_sync_timeline *)sync_pt->parent;
+
+ return sw_sync_cmp(obj->value, pt->value) >= 0;
+}
+
+static int sw_sync_pt_compare(struct sync_pt *a, struct sync_pt *b)
+{
+ struct sw_sync_pt *pt_a = (struct sw_sync_pt *)a;
+ struct sw_sync_pt *pt_b = (struct sw_sync_pt *)b;
+
+ return sw_sync_cmp(pt_a->value, pt_b->value);
+}
+
+static int sw_sync_fill_driver_data(struct sync_pt *sync_pt,
+ void *data, int size)
+{
+ struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+
+ if (size < sizeof(pt->value))
+ return -ENOMEM;
+
+ memcpy(data, &pt->value, sizeof(pt->value));
+
+ return sizeof(pt->value);
+}
+
+static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline,
+ char *str, int size)
+{
+ struct sw_sync_timeline *timeline =
+ (struct sw_sync_timeline *)sync_timeline;
+ snprintf(str, size, "%d", timeline->value);
+}
+
+static void sw_sync_pt_value_str(struct sync_pt *sync_pt,
+ char *str, int size)
+{
+ struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+ snprintf(str, size, "%d", pt->value);
+}
+
+static struct sync_timeline_ops sw_sync_timeline_ops = {
+ .driver_name = "sw_sync",
+ .dup = sw_sync_pt_dup,
+ .has_signaled = sw_sync_pt_has_signaled,
+ .compare = sw_sync_pt_compare,
+ .fill_driver_data = sw_sync_fill_driver_data,
+ .timeline_value_str = sw_sync_timeline_value_str,
+ .pt_value_str = sw_sync_pt_value_str,
+};
+
+
+struct sw_sync_timeline *sw_sync_timeline_create(const char *name)
+{
+ struct sw_sync_timeline *obj = (struct sw_sync_timeline *)
+ sync_timeline_create(&sw_sync_timeline_ops,
+ sizeof(struct sw_sync_timeline),
+ name);
+
+ return obj;
+}
+EXPORT_SYMBOL(sw_sync_timeline_create);
+
+void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc)
+{
+ obj->value += inc;
+
+ sync_timeline_signal(&obj->obj);
+}
+EXPORT_SYMBOL(sw_sync_timeline_inc);
+
+#ifdef CONFIG_SW_SYNC_USER
+/* *WARNING*
+ *
+ * improper use of this can result in deadlocking kernel drivers from userspace.
+ */
+
+/* opening sw_sync create a new sync obj */
+static int sw_sync_open(struct inode *inode, struct file *file)
+{
+ struct sw_sync_timeline *obj;
+ char task_comm[TASK_COMM_LEN];
+
+ get_task_comm(task_comm, current);
+
+ obj = sw_sync_timeline_create(task_comm);
+ if (obj == NULL)
+ return -ENOMEM;
+
+ file->private_data = obj;
+
+ return 0;
+}
+
+static int sw_sync_release(struct inode *inode, struct file *file)
+{
+ struct sw_sync_timeline *obj = file->private_data;
+ sync_timeline_destroy(&obj->obj);
+ return 0;
+}
+
+static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, unsigned long arg)
+{
+ int fd = get_unused_fd();
+ int err;
+ struct sync_pt *pt;
+ struct sync_fence *fence;
+ struct sw_sync_create_fence_data data;
+
+ if (fd < 0)
+ return fd;
+
+ if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+ err = -EFAULT;
+ goto err;
+ }
+
+ pt = sw_sync_pt_create(obj, data.value);
+ if (pt == NULL) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ data.name[sizeof(data.name) - 1] = '\0';
+ fence = sync_fence_create(data.name, pt);
+ if (fence == NULL) {
+ sync_pt_free(pt);
+ err = -ENOMEM;
+ goto err;
+ }
+
+ data.fence = fd;
+ if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+ sync_fence_put(fence);
+ err = -EFAULT;
+ goto err;
+ }
+
+ sync_fence_install(fence, fd);
+
+ return 0;
+
+err:
+ put_unused_fd(fd);
+ return err;
+}
+
+static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg)
+{
+ u32 value;
+
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+
+ sw_sync_timeline_inc(obj, value);
+
+ return 0;
+}
+
+static long sw_sync_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct sw_sync_timeline *obj = file->private_data;
+
+ switch (cmd) {
+ case SW_SYNC_IOC_CREATE_FENCE:
+ return sw_sync_ioctl_create_fence(obj, arg);
+
+ case SW_SYNC_IOC_INC:
+ return sw_sync_ioctl_inc(obj, arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static const struct file_operations sw_sync_fops = {
+ .owner = THIS_MODULE,
+ .open = sw_sync_open,
+ .release = sw_sync_release,
+ .unlocked_ioctl = sw_sync_ioctl,
+ .compat_ioctl = sw_sync_ioctl,
+};
+
+static struct miscdevice sw_sync_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sw_sync",
+ .fops = &sw_sync_fops,
+};
+
+static int __init sw_sync_device_init(void)
+{
+ return misc_register(&sw_sync_dev);
+}
+
+static void __exit sw_sync_device_remove(void)
+{
+ misc_deregister(&sw_sync_dev);
+}
+
+module_init(sw_sync_device_init);
+module_exit(sw_sync_device_remove);
+
+#endif /* CONFIG_SW_SYNC_USER */
diff --git a/drivers/staging/android/sw_sync.h b/drivers/staging/android/sw_sync.h
new file mode 100644
index 00000000000..585040be5f1
--- /dev/null
+++ b/drivers/staging/android/sw_sync.h
@@ -0,0 +1,58 @@
+/*
+ * include/linux/sw_sync.h
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_SW_SYNC_H
+#define _LINUX_SW_SYNC_H
+
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+
+#include "sync.h"
+
+struct sw_sync_timeline {
+ struct sync_timeline obj;
+
+ u32 value;
+};
+
+struct sw_sync_pt {
+ struct sync_pt pt;
+
+ u32 value;
+};
+
+struct sw_sync_timeline *sw_sync_timeline_create(const char *name);
+void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc);
+
+struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value);
+
+#endif /* __KERNEL __ */
+
+struct sw_sync_create_fence_data {
+ __u32 value;
+ char name[32];
+ __s32 fence; /* fd of new fence */
+};
+
+#define SW_SYNC_IOC_MAGIC 'W'
+
+#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
+ struct sw_sync_create_fence_data)
+#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
+
+
+#endif /* _LINUX_SW_SYNC_H */
diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
new file mode 100644
index 00000000000..3893a357476
--- /dev/null
+++ b/drivers/staging/android/sync.c
@@ -0,0 +1,1017 @@
+/*
+ * drivers/base/sync.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/debugfs.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/anon_inodes.h>
+
+#include "sync.h"
+
+#define CREATE_TRACE_POINTS
+#include "trace/sync.h"
+
+static void sync_fence_signal_pt(struct sync_pt *pt);
+static int _sync_pt_has_signaled(struct sync_pt *pt);
+static void sync_fence_free(struct kref *kref);
+static void sync_dump(void);
+
+static LIST_HEAD(sync_timeline_list_head);
+static DEFINE_SPINLOCK(sync_timeline_list_lock);
+
+static LIST_HEAD(sync_fence_list_head);
+static DEFINE_SPINLOCK(sync_fence_list_lock);
+
+struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
+ int size, const char *name)
+{
+ struct sync_timeline *obj;
+ unsigned long flags;
+
+ if (size < sizeof(struct sync_timeline))
+ return NULL;
+
+ obj = kzalloc(size, GFP_KERNEL);
+ if (obj == NULL)
+ return NULL;
+
+ kref_init(&obj->kref);
+ obj->ops = ops;
+ strlcpy(obj->name, name, sizeof(obj->name));
+
+ INIT_LIST_HEAD(&obj->child_list_head);
+ spin_lock_init(&obj->child_list_lock);
+
+ INIT_LIST_HEAD(&obj->active_list_head);
+ spin_lock_init(&obj->active_list_lock);
+
+ spin_lock_irqsave(&sync_timeline_list_lock, flags);
+ list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head);
+ spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+
+ return obj;
+}
+EXPORT_SYMBOL(sync_timeline_create);
+
+static void sync_timeline_free(struct kref *kref)
+{
+ struct sync_timeline *obj =
+ container_of(kref, struct sync_timeline, kref);
+ unsigned long flags;
+
+ if (obj->ops->release_obj)
+ obj->ops->release_obj(obj);
+
+ spin_lock_irqsave(&sync_timeline_list_lock, flags);
+ list_del(&obj->sync_timeline_list);
+ spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+
+ kfree(obj);
+}
+
+void sync_timeline_destroy(struct sync_timeline *obj)
+{
+ obj->destroyed = true;
+
+ /*
+ * If this is not the last reference, signal any children
+ * that their parent is going away.
+ */
+
+ if (!kref_put(&obj->kref, sync_timeline_free))
+ sync_timeline_signal(obj);
+}
+EXPORT_SYMBOL(sync_timeline_destroy);
+
+static void sync_timeline_add_pt(struct sync_timeline *obj, struct sync_pt *pt)
+{
+ unsigned long flags;
+
+ pt->parent = obj;
+
+ spin_lock_irqsave(&obj->child_list_lock, flags);
+ list_add_tail(&pt->child_list, &obj->child_list_head);
+ spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+
+static void sync_timeline_remove_pt(struct sync_pt *pt)
+{
+ struct sync_timeline *obj = pt->parent;
+ unsigned long flags;
+
+ spin_lock_irqsave(&obj->active_list_lock, flags);
+ if (!list_empty(&pt->active_list))
+ list_del_init(&pt->active_list);
+ spin_unlock_irqrestore(&obj->active_list_lock, flags);
+
+ spin_lock_irqsave(&obj->child_list_lock, flags);
+ if (!list_empty(&pt->child_list)) {
+ list_del_init(&pt->child_list);
+ }
+ spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+
+void sync_timeline_signal(struct sync_timeline *obj)
+{
+ unsigned long flags;
+ LIST_HEAD(signaled_pts);
+ struct list_head *pos, *n;
+
+ trace_sync_timeline(obj);
+
+ spin_lock_irqsave(&obj->active_list_lock, flags);
+
+ list_for_each_safe(pos, n, &obj->active_list_head) {
+ struct sync_pt *pt =
+ container_of(pos, struct sync_pt, active_list);
+
+ if (_sync_pt_has_signaled(pt)) {
+ list_del_init(pos);
+ list_add(&pt->signaled_list, &signaled_pts);
+ kref_get(&pt->fence->kref);
+ }
+ }
+
+ spin_unlock_irqrestore(&obj->active_list_lock, flags);
+
+ list_for_each_safe(pos, n, &signaled_pts) {
+ struct sync_pt *pt =
+ container_of(pos, struct sync_pt, signaled_list);
+
+ list_del_init(pos);
+ sync_fence_signal_pt(pt);
+ kref_put(&pt->fence->kref, sync_fence_free);
+ }
+}
+EXPORT_SYMBOL(sync_timeline_signal);
+
+struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size)
+{
+ struct sync_pt *pt;
+
+ if (size < sizeof(struct sync_pt))
+ return NULL;
+
+ pt = kzalloc(size, GFP_KERNEL);
+ if (pt == NULL)
+ return NULL;
+
+ INIT_LIST_HEAD(&pt->active_list);
+ kref_get(&parent->kref);
+ sync_timeline_add_pt(parent, pt);
+
+ return pt;
+}
+EXPORT_SYMBOL(sync_pt_create);
+
+void sync_pt_free(struct sync_pt *pt)
+{
+ if (pt->parent->ops->free_pt)
+ pt->parent->ops->free_pt(pt);
+
+ sync_timeline_remove_pt(pt);
+
+ kref_put(&pt->parent->kref, sync_timeline_free);
+
+ kfree(pt);
+}
+EXPORT_SYMBOL(sync_pt_free);
+
+/* call with pt->parent->active_list_lock held */
+static int _sync_pt_has_signaled(struct sync_pt *pt)
+{
+ int old_status = pt->status;
+
+ if (!pt->status)
+ pt->status = pt->parent->ops->has_signaled(pt);
+
+ if (!pt->status && pt->parent->destroyed)
+ pt->status = -ENOENT;
+
+ if (pt->status != old_status)
+ pt->timestamp = ktime_get();
+
+ return pt->status;
+}
+
+static struct sync_pt *sync_pt_dup(struct sync_pt *pt)
+{
+ return pt->parent->ops->dup(pt);
+}
+
+/* Adds a sync pt to the active queue. Called when added to a fence */
+static void sync_pt_activate(struct sync_pt *pt)
+{
+ struct sync_timeline *obj = pt->parent;
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&obj->active_list_lock, flags);
+
+ err = _sync_pt_has_signaled(pt);
+ if (err != 0)
+ goto out;
+
+ list_add_tail(&pt->active_list, &obj->active_list_head);
+
+out:
+ spin_unlock_irqrestore(&obj->active_list_lock, flags);
+}
+
+static int sync_fence_release(struct inode *inode, struct file *file);
+static unsigned int sync_fence_poll(struct file *file, poll_table *wait);
+static long sync_fence_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg);
+
+
+static const struct file_operations sync_fence_fops = {
+ .release = sync_fence_release,
+ .poll = sync_fence_poll,
+ .unlocked_ioctl = sync_fence_ioctl,
+ .compat_ioctl = sync_fence_ioctl,
+};
+
+static struct sync_fence *sync_fence_alloc(const char *name)
+{
+ struct sync_fence *fence;
+ unsigned long flags;
+
+ fence = kzalloc(sizeof(struct sync_fence), GFP_KERNEL);
+ if (fence == NULL)
+ return NULL;
+
+ fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops,
+ fence, 0);
+ if (IS_ERR(fence->file))
+ goto err;
+
+ kref_init(&fence->kref);
+ strlcpy(fence->name, name, sizeof(fence->name));
+
+ INIT_LIST_HEAD(&fence->pt_list_head);
+ INIT_LIST_HEAD(&fence->waiter_list_head);
+ spin_lock_init(&fence->waiter_list_lock);
+
+ init_waitqueue_head(&fence->wq);
+
+ spin_lock_irqsave(&sync_fence_list_lock, flags);
+ list_add_tail(&fence->sync_fence_list, &sync_fence_list_head);
+ spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+
+ return fence;
+
+err:
+ kfree(fence);
+ return NULL;
+}
+
+/* TODO: implement a create which takes more that one sync_pt */
+struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
+{
+ struct sync_fence *fence;
+
+ if (pt->fence)
+ return NULL;
+
+ fence = sync_fence_alloc(name);
+ if (fence == NULL)
+ return NULL;
+
+ pt->fence = fence;
+ list_add(&pt->pt_list, &fence->pt_list_head);
+ sync_pt_activate(pt);
+
+ /*
+ * signal the fence in case pt was activated before
+ * sync_pt_activate(pt) was called
+ */
+ sync_fence_signal_pt(pt);
+
+ return fence;
+}
+EXPORT_SYMBOL(sync_fence_create);
+
+static int sync_fence_copy_pts(struct sync_fence *dst, struct sync_fence *src)
+{
+ struct list_head *pos;
+
+ list_for_each(pos, &src->pt_list_head) {
+ struct sync_pt *orig_pt =
+ container_of(pos, struct sync_pt, pt_list);
+ struct sync_pt *new_pt = sync_pt_dup(orig_pt);
+
+ if (new_pt == NULL)
+ return -ENOMEM;
+
+ new_pt->fence = dst;
+ list_add(&new_pt->pt_list, &dst->pt_list_head);
+ }
+
+ return 0;
+}
+
+static int sync_fence_merge_pts(struct sync_fence *dst, struct sync_fence *src)
+{
+ struct list_head *src_pos, *dst_pos, *n;
+
+ list_for_each(src_pos, &src->pt_list_head) {
+ struct sync_pt *src_pt =
+ container_of(src_pos, struct sync_pt, pt_list);
+ bool collapsed = false;
+
+ list_for_each_safe(dst_pos, n, &dst->pt_list_head) {
+ struct sync_pt *dst_pt =
+ container_of(dst_pos, struct sync_pt, pt_list);
+ /* collapse two sync_pts on the same timeline
+ * to a single sync_pt that will signal at
+ * the later of the two
+ */
+ if (dst_pt->parent == src_pt->parent) {
+ if (dst_pt->parent->ops->compare(dst_pt, src_pt)
+ == -1) {
+ struct sync_pt *new_pt =
+ sync_pt_dup(src_pt);
+ if (new_pt == NULL)
+ return -ENOMEM;
+
+ new_pt->fence = dst;
+ list_replace(&dst_pt->pt_list,
+ &new_pt->pt_list);
+ sync_pt_free(dst_pt);
+ }
+ collapsed = true;
+ break;
+ }
+ }
+
+ if (!collapsed) {
+ struct sync_pt *new_pt = sync_pt_dup(src_pt);
+
+ if (new_pt == NULL)
+ return -ENOMEM;
+
+ new_pt->fence = dst;
+ list_add(&new_pt->pt_list, &dst->pt_list_head);
+ }
+ }
+
+ return 0;
+}
+
+static void sync_fence_detach_pts(struct sync_fence *fence)
+{
+ struct list_head *pos, *n;
+
+ list_for_each_safe(pos, n, &fence->pt_list_head) {
+ struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+ sync_timeline_remove_pt(pt);
+ }
+}
+
+static void sync_fence_free_pts(struct sync_fence *fence)
+{
+ struct list_head *pos, *n;
+
+ list_for_each_safe(pos, n, &fence->pt_list_head) {
+ struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+ sync_pt_free(pt);
+ }
+}
+
+struct sync_fence *sync_fence_fdget(int fd)
+{
+ struct file *file = fget(fd);
+
+ if (file == NULL)
+ return NULL;
+
+ if (file->f_op != &sync_fence_fops)
+ goto err;
+
+ return file->private_data;
+
+err:
+ fput(file);
+ return NULL;
+}
+EXPORT_SYMBOL(sync_fence_fdget);
+
+void sync_fence_put(struct sync_fence *fence)
+{
+ fput(fence->file);
+}
+EXPORT_SYMBOL(sync_fence_put);
+
+void sync_fence_install(struct sync_fence *fence, int fd)
+{
+ fd_install(fd, fence->file);
+}
+EXPORT_SYMBOL(sync_fence_install);
+
+static int sync_fence_get_status(struct sync_fence *fence)
+{
+ struct list_head *pos;
+ int status = 1;
+
+ list_for_each(pos, &fence->pt_list_head) {
+ struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+ int pt_status = pt->status;
+
+ if (pt_status < 0) {
+ status = pt_status;
+ break;
+ } else if (status == 1) {
+ status = pt_status;
+ }
+ }
+
+ return status;
+}
+
+struct sync_fence *sync_fence_merge(const char *name,
+ struct sync_fence *a, struct sync_fence *b)
+{
+ struct sync_fence *fence;
+ struct list_head *pos;
+ int err;
+
+ fence = sync_fence_alloc(name);
+ if (fence == NULL)
+ return NULL;
+
+ err = sync_fence_copy_pts(fence, a);
+ if (err < 0)
+ goto err;
+
+ err = sync_fence_merge_pts(fence, b);
+ if (err < 0)
+ goto err;
+
+ list_for_each(pos, &fence->pt_list_head) {
+ struct sync_pt *pt =
+ container_of(pos, struct sync_pt, pt_list);
+ sync_pt_activate(pt);
+ }
+
+ /*
+ * signal the fence in case one of it's pts were activated before
+ * they were activated
+ */
+ sync_fence_signal_pt(list_first_entry(&fence->pt_list_head,
+ struct sync_pt,
+ pt_list));
+
+ return fence;
+err:
+ sync_fence_free_pts(fence);
+ kfree(fence);
+ return NULL;
+}
+EXPORT_SYMBOL(sync_fence_merge);
+
+static void sync_fence_signal_pt(struct sync_pt *pt)
+{
+ LIST_HEAD(signaled_waiters);
+ struct sync_fence *fence = pt->fence;
+ struct list_head *pos;
+ struct list_head *n;
+ unsigned long flags;
+ int status;
+
+ status = sync_fence_get_status(fence);
+
+ spin_lock_irqsave(&fence->waiter_list_lock, flags);
+ /*
+ * this should protect against two threads racing on the signaled
+ * false -> true transition
+ */
+ if (status && !fence->status) {
+ list_for_each_safe(pos, n, &fence->waiter_list_head)
+ list_move(pos, &signaled_waiters);
+
+ fence->status = status;
+ } else {
+ status = 0;
+ }
+ spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+
+ if (status) {
+ list_for_each_safe(pos, n, &signaled_waiters) {
+ struct sync_fence_waiter *waiter =
+ container_of(pos, struct sync_fence_waiter,
+ waiter_list);
+
+ list_del(pos);
+ waiter->callback(fence, waiter);
+ }
+ wake_up(&fence->wq);
+ }
+}
+
+int sync_fence_wait_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter)
+{
+ unsigned long flags;
+ int err = 0;
+
+ spin_lock_irqsave(&fence->waiter_list_lock, flags);
+
+ if (fence->status) {
+ err = fence->status;
+ goto out;
+ }
+
+ list_add_tail(&waiter->waiter_list, &fence->waiter_list_head);
+out:
+ spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+
+ return err;
+}
+EXPORT_SYMBOL(sync_fence_wait_async);
+
+int sync_fence_cancel_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter)
+{
+ struct list_head *pos;
+ struct list_head *n;
+ unsigned long flags;
+ int ret = -ENOENT;
+
+ spin_lock_irqsave(&fence->waiter_list_lock, flags);
+ /*
+ * Make sure waiter is still in waiter_list because it is possible for
+ * the waiter to be removed from the list while the callback is still
+ * pending.
+ */
+ list_for_each_safe(pos, n, &fence->waiter_list_head) {
+ struct sync_fence_waiter *list_waiter =
+ container_of(pos, struct sync_fence_waiter,
+ waiter_list);
+ if (list_waiter == waiter) {
+ list_del(pos);
+ ret = 0;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(sync_fence_cancel_async);
+
+static bool sync_fence_check(struct sync_fence *fence)
+{
+ /*
+ * Make sure that reads to fence->status are ordered with the
+ * wait queue event triggering
+ */
+ smp_rmb();
+ return fence->status != 0;
+}
+
+int sync_fence_wait(struct sync_fence *fence, long timeout)
+{
+ int err = 0;
+ struct sync_pt *pt;
+
+ trace_sync_wait(fence, 1);
+ list_for_each_entry(pt, &fence->pt_list_head, pt_list)
+ trace_sync_pt(pt);
+
+ if (timeout > 0) {
+ timeout = msecs_to_jiffies(timeout);
+ err = wait_event_interruptible_timeout(fence->wq,
+ sync_fence_check(fence),
+ timeout);
+ } else if (timeout < 0) {
+ err = wait_event_interruptible(fence->wq,
+ sync_fence_check(fence));
+ }
+ trace_sync_wait(fence, 0);
+
+ if (err < 0)
+ return err;
+
+ if (fence->status < 0) {
+ pr_info("fence error %d on [%p]\n", fence->status, fence);
+ sync_dump();
+ return fence->status;
+ }
+
+ if (fence->status == 0) {
+ if (timeout > 0) {
+ pr_info("fence timeout on [%p] after %dms\n", fence,
+ jiffies_to_msecs(timeout));
+ sync_dump();
+ }
+ return -ETIME;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(sync_fence_wait);
+
+static void sync_fence_free(struct kref *kref)
+{
+ struct sync_fence *fence = container_of(kref, struct sync_fence, kref);
+
+ sync_fence_free_pts(fence);
+
+ kfree(fence);
+}
+
+static int sync_fence_release(struct inode *inode, struct file *file)
+{
+ struct sync_fence *fence = file->private_data;
+ unsigned long flags;
+
+ /*
+ * We need to remove all ways to access this fence before droping
+ * our ref.
+ *
+ * start with its membership in the global fence list
+ */
+ spin_lock_irqsave(&sync_fence_list_lock, flags);
+ list_del(&fence->sync_fence_list);
+ spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+
+ /*
+ * remove its pts from their parents so that sync_timeline_signal()
+ * can't reference the fence.
+ */
+ sync_fence_detach_pts(fence);
+
+ kref_put(&fence->kref, sync_fence_free);
+
+ return 0;
+}
+
+static unsigned int sync_fence_poll(struct file *file, poll_table *wait)
+{
+ struct sync_fence *fence = file->private_data;
+
+ poll_wait(file, &fence->wq, wait);
+
+ /*
+ * Make sure that reads to fence->status are ordered with the
+ * wait queue event triggering
+ */
+ smp_rmb();
+
+ if (fence->status == 1)
+ return POLLIN;
+ else if (fence->status < 0)
+ return POLLERR;
+ else
+ return 0;
+}
+
+static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg)
+{
+ __s32 value;
+
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+
+ return sync_fence_wait(fence, value);
+}
+
+static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg)
+{
+ int fd = get_unused_fd();
+ int err;
+ struct sync_fence *fence2, *fence3;
+ struct sync_merge_data data;
+
+ if (fd < 0)
+ return fd;
+
+ if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+ err = -EFAULT;
+ goto err_put_fd;
+ }
+
+ fence2 = sync_fence_fdget(data.fd2);
+ if (fence2 == NULL) {
+ err = -ENOENT;
+ goto err_put_fd;
+ }
+
+ data.name[sizeof(data.name) - 1] = '\0';
+ fence3 = sync_fence_merge(data.name, fence, fence2);
+ if (fence3 == NULL) {
+ err = -ENOMEM;
+ goto err_put_fence2;
+ }
+
+ data.fence = fd;
+ if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+ err = -EFAULT;
+ goto err_put_fence3;
+ }
+
+ sync_fence_install(fence3, fd);
+ sync_fence_put(fence2);
+ return 0;
+
+err_put_fence3:
+ sync_fence_put(fence3);
+
+err_put_fence2:
+ sync_fence_put(fence2);
+
+err_put_fd:
+ put_unused_fd(fd);
+ return err;
+}
+
+static int sync_fill_pt_info(struct sync_pt *pt, void *data, int size)
+{
+ struct sync_pt_info *info = data;
+ int ret;
+
+ if (size < sizeof(struct sync_pt_info))
+ return -ENOMEM;
+
+ info->len = sizeof(struct sync_pt_info);
+
+ if (pt->parent->ops->fill_driver_data) {
+ ret = pt->parent->ops->fill_driver_data(pt, info->driver_data,
+ size - sizeof(*info));
+ if (ret < 0)
+ return ret;
+
+ info->len += ret;
+ }
+
+ strlcpy(info->obj_name, pt->parent->name, sizeof(info->obj_name));
+ strlcpy(info->driver_name, pt->parent->ops->driver_name,
+ sizeof(info->driver_name));
+ info->status = pt->status;
+ info->timestamp_ns = ktime_to_ns(pt->timestamp);
+
+ return info->len;
+}
+
+static long sync_fence_ioctl_fence_info(struct sync_fence *fence,
+ unsigned long arg)
+{
+ struct sync_fence_info_data *data;
+ struct list_head *pos;
+ __u32 size;
+ __u32 len = 0;
+ int ret;
+
+ if (copy_from_user(&size, (void __user *)arg, sizeof(size)))
+ return -EFAULT;
+
+ if (size < sizeof(struct sync_fence_info_data))
+ return -EINVAL;
+
+ if (size > 4096)
+ size = 4096;
+
+ data = kzalloc(size, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ strlcpy(data->name, fence->name, sizeof(data->name));
+ data->status = fence->status;
+ len = sizeof(struct sync_fence_info_data);
+
+ list_for_each(pos, &fence->pt_list_head) {
+ struct sync_pt *pt =
+ container_of(pos, struct sync_pt, pt_list);
+
+ ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len);
+
+ if (ret < 0)
+ goto out;
+
+ len += ret;
+ }
+
+ data->len = len;
+
+ if (copy_to_user((void __user *)arg, data, len))
+ ret = -EFAULT;
+ else
+ ret = 0;
+
+out:
+ kfree(data);
+
+ return ret;
+}
+
+static long sync_fence_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sync_fence *fence = file->private_data;
+ switch (cmd) {
+ case SYNC_IOC_WAIT:
+ return sync_fence_ioctl_wait(fence, arg);
+
+ case SYNC_IOC_MERGE:
+ return sync_fence_ioctl_merge(fence, arg);
+
+ case SYNC_IOC_FENCE_INFO:
+ return sync_fence_ioctl_fence_info(fence, arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const char *sync_status_str(int status)
+{
+ if (status > 0)
+ return "signaled";
+ else if (status == 0)
+ return "active";
+ else
+ return "error";
+}
+
+static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
+{
+ int status = pt->status;
+ seq_printf(s, " %s%spt %s",
+ fence ? pt->parent->name : "",
+ fence ? "_" : "",
+ sync_status_str(status));
+ if (pt->status) {
+ struct timeval tv = ktime_to_timeval(pt->timestamp);
+ seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec);
+ }
+
+ if (pt->parent->ops->timeline_value_str &&
+ pt->parent->ops->pt_value_str) {
+ char value[64];
+ pt->parent->ops->pt_value_str(pt, value, sizeof(value));
+ seq_printf(s, ": %s", value);
+ if (fence) {
+ pt->parent->ops->timeline_value_str(pt->parent, value,
+ sizeof(value));
+ seq_printf(s, " / %s", value);
+ }
+ } else if (pt->parent->ops->print_pt) {
+ seq_printf(s, ": ");
+ pt->parent->ops->print_pt(s, pt);
+ }
+
+ seq_printf(s, "\n");
+}
+
+static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
+{
+ struct list_head *pos;
+ unsigned long flags;
+
+ seq_printf(s, "%s %s", obj->name, obj->ops->driver_name);
+
+ if (obj->ops->timeline_value_str) {
+ char value[64];
+ obj->ops->timeline_value_str(obj, value, sizeof(value));
+ seq_printf(s, ": %s", value);
+ } else if (obj->ops->print_obj) {
+ seq_printf(s, ": ");
+ obj->ops->print_obj(s, obj);
+ }
+
+ seq_printf(s, "\n");
+
+ spin_lock_irqsave(&obj->child_list_lock, flags);
+ list_for_each(pos, &obj->child_list_head) {
+ struct sync_pt *pt =
+ container_of(pos, struct sync_pt, child_list);
+ sync_print_pt(s, pt, false);
+ }
+ spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+
+static void sync_print_fence(struct seq_file *s, struct sync_fence *fence)
+{
+ struct list_head *pos;
+ unsigned long flags;
+
+ seq_printf(s, "[%p] %s: %s\n", fence, fence->name,
+ sync_status_str(fence->status));
+
+ list_for_each(pos, &fence->pt_list_head) {
+ struct sync_pt *pt =
+ container_of(pos, struct sync_pt, pt_list);
+ sync_print_pt(s, pt, true);
+ }
+
+ spin_lock_irqsave(&fence->waiter_list_lock, flags);
+ list_for_each(pos, &fence->waiter_list_head) {
+ struct sync_fence_waiter *waiter =
+ container_of(pos, struct sync_fence_waiter,
+ waiter_list);
+
+ seq_printf(s, "waiter %pF\n", waiter->callback);
+ }
+ spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+}
+
+static int sync_debugfs_show(struct seq_file *s, void *unused)
+{
+ unsigned long flags;
+ struct list_head *pos;
+
+ seq_printf(s, "objs:\n--------------\n");
+
+ spin_lock_irqsave(&sync_timeline_list_lock, flags);
+ list_for_each(pos, &sync_timeline_list_head) {
+ struct sync_timeline *obj =
+ container_of(pos, struct sync_timeline,
+ sync_timeline_list);
+
+ sync_print_obj(s, obj);
+ seq_printf(s, "\n");
+ }
+ spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+
+ seq_printf(s, "fences:\n--------------\n");
+
+ spin_lock_irqsave(&sync_fence_list_lock, flags);
+ list_for_each(pos, &sync_fence_list_head) {
+ struct sync_fence *fence =
+ container_of(pos, struct sync_fence, sync_fence_list);
+
+ sync_print_fence(s, fence);
+ seq_printf(s, "\n");
+ }
+ spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+ return 0;
+}
+
+static int sync_debugfs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, sync_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations sync_debugfs_fops = {
+ .open = sync_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static __init int sync_debugfs_init(void)
+{
+ debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops);
+ return 0;
+}
+late_initcall(sync_debugfs_init);
+
+#define DUMP_CHUNK 256
+static char sync_dump_buf[64 * 1024];
+void sync_dump(void)
+{
+ struct seq_file s = {
+ .buf = sync_dump_buf,
+ .size = sizeof(sync_dump_buf) - 1,
+ };
+ int i;
+
+ sync_debugfs_show(&s, NULL);
+
+ for (i = 0; i < s.count; i += DUMP_CHUNK) {
+ if ((s.count - i) > DUMP_CHUNK) {
+ char c = s.buf[i + DUMP_CHUNK];
+ s.buf[i + DUMP_CHUNK] = 0;
+ pr_cont("%s", s.buf + i);
+ s.buf[i + DUMP_CHUNK] = c;
+ } else {
+ s.buf[s.count] = 0;
+ pr_cont("%s", s.buf + i);
+ }
+ }
+}
+#else
+static void sync_dump(void)
+{
+}
+#endif
diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h
new file mode 100644
index 00000000000..38ea986dc70
--- /dev/null
+++ b/drivers/staging/android/sync.h
@@ -0,0 +1,426 @@
+/*
+ * include/linux/sync.h
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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_SYNC_H
+#define _LINUX_SYNC_H
+
+#include <linux/types.h>
+#ifdef __KERNEL__
+
+#include <linux/kref.h>
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+
+struct sync_timeline;
+struct sync_pt;
+struct sync_fence;
+
+/**
+ * struct sync_timeline_ops - sync object implementation ops
+ * @driver_name: name of the implentation
+ * @dup: duplicate a sync_pt
+ * @has_signaled: returns:
+ * 1 if pt has signaled
+ * 0 if pt has not signaled
+ * <0 on error
+ * @compare: returns:
+ * 1 if b will signal before a
+ * 0 if a and b will signal at the same time
+ * -1 if a will signabl before b
+ * @free_pt: called before sync_pt is freed
+ * @release_obj: called before sync_timeline is freed
+ * @print_obj: deprecated
+ * @print_pt: deprecated
+ * @fill_driver_data: write implmentation specific driver data to data.
+ * should return an error if there is not enough room
+ * as specified by size. This information is returned
+ * to userspace by SYNC_IOC_FENCE_INFO.
+ * @timeline_value_str: fill str with the value of the sync_timeline's counter
+ * @pt_value_str: fill str with the value of the sync_pt
+ */
+struct sync_timeline_ops {
+ const char *driver_name;
+
+ /* required */
+ struct sync_pt *(*dup)(struct sync_pt *pt);
+
+ /* required */
+ int (*has_signaled)(struct sync_pt *pt);
+
+ /* required */
+ int (*compare)(struct sync_pt *a, struct sync_pt *b);
+
+ /* optional */
+ void (*free_pt)(struct sync_pt *sync_pt);
+
+ /* optional */
+ void (*release_obj)(struct sync_timeline *sync_timeline);
+
+ /* deprecated */
+ void (*print_obj)(struct seq_file *s,
+ struct sync_timeline *sync_timeline);
+
+ /* deprecated */
+ void (*print_pt)(struct seq_file *s, struct sync_pt *sync_pt);
+
+ /* optional */
+ int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size);
+
+ /* optional */
+ void (*timeline_value_str)(struct sync_timeline *timeline, char *str,
+ int size);
+
+ /* optional */
+ void (*pt_value_str)(struct sync_pt *pt, char *str, int size);
+};
+
+/**
+ * struct sync_timeline - sync object
+ * @kref: reference count on fence.
+ * @ops: ops that define the implementaiton of the sync_timeline
+ * @name: name of the sync_timeline. Useful for debugging
+ * @destoryed: set when sync_timeline is destroyed
+ * @child_list_head: list of children sync_pts for this sync_timeline
+ * @child_list_lock: lock protecting @child_list_head, destroyed, and
+ * sync_pt.status
+ * @active_list_head: list of active (unsignaled/errored) sync_pts
+ * @sync_timeline_list: membership in global sync_timeline_list
+ */
+struct sync_timeline {
+ struct kref kref;
+ const struct sync_timeline_ops *ops;
+ char name[32];
+
+ /* protected by child_list_lock */
+ bool destroyed;
+
+ struct list_head child_list_head;
+ spinlock_t child_list_lock;
+
+ struct list_head active_list_head;
+ spinlock_t active_list_lock;
+
+ struct list_head sync_timeline_list;
+};
+
+/**
+ * struct sync_pt - sync point
+ * @parent: sync_timeline to which this sync_pt belongs
+ * @child_list: membership in sync_timeline.child_list_head
+ * @active_list: membership in sync_timeline.active_list_head
+ * @signaled_list: membership in temorary signaled_list on stack
+ * @fence: sync_fence to which the sync_pt belongs
+ * @pt_list: membership in sync_fence.pt_list_head
+ * @status: 1: signaled, 0:active, <0: error
+ * @timestamp: time which sync_pt status transitioned from active to
+ * singaled or error.
+ */
+struct sync_pt {
+ struct sync_timeline *parent;
+ struct list_head child_list;
+
+ struct list_head active_list;
+ struct list_head signaled_list;
+
+ struct sync_fence *fence;
+ struct list_head pt_list;
+
+ /* protected by parent->active_list_lock */
+ int status;
+
+ ktime_t timestamp;
+};
+
+/**
+ * struct sync_fence - sync fence
+ * @file: file representing this fence
+ * @kref: referenace count on fence.
+ * @name: name of sync_fence. Useful for debugging
+ * @pt_list_head: list of sync_pts in ths fence. immutable once fence
+ * is created
+ * @waiter_list_head: list of asynchronous waiters on this fence
+ * @waiter_list_lock: lock protecting @waiter_list_head and @status
+ * @status: 1: signaled, 0:active, <0: error
+ *
+ * @wq: wait queue for fence signaling
+ * @sync_fence_list: membership in global fence list
+ */
+struct sync_fence {
+ struct file *file;
+ struct kref kref;
+ char name[32];
+
+ /* this list is immutable once the fence is created */
+ struct list_head pt_list_head;
+
+ struct list_head waiter_list_head;
+ spinlock_t waiter_list_lock; /* also protects status */
+ int status;
+
+ wait_queue_head_t wq;
+
+ struct list_head sync_fence_list;
+};
+
+struct sync_fence_waiter;
+typedef void (*sync_callback_t)(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter);
+
+/**
+ * struct sync_fence_waiter - metadata for asynchronous waiter on a fence
+ * @waiter_list: membership in sync_fence.waiter_list_head
+ * @callback: function pointer to call when fence signals
+ * @callback_data: pointer to pass to @callback
+ */
+struct sync_fence_waiter {
+ struct list_head waiter_list;
+
+ sync_callback_t callback;
+};
+
+static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter,
+ sync_callback_t callback)
+{
+ waiter->callback = callback;
+}
+
+/*
+ * API for sync_timeline implementers
+ */
+
+/**
+ * sync_timeline_create() - creates a sync object
+ * @ops: specifies the implemention ops for the object
+ * @size: size to allocate for this obj
+ * @name: sync_timeline name
+ *
+ * Creates a new sync_timeline which will use the implemetation specified by
+ * @ops. @size bytes will be allocated allowing for implemntation specific
+ * data to be kept after the generic sync_timeline stuct.
+ */
+struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
+ int size, const char *name);
+
+/**
+ * sync_timeline_destory() - destorys a sync object
+ * @obj: sync_timeline to destroy
+ *
+ * A sync implemntation should call this when the @obj is going away
+ * (i.e. module unload.) @obj won't actually be freed until all its childern
+ * sync_pts are freed.
+ */
+void sync_timeline_destroy(struct sync_timeline *obj);
+
+/**
+ * sync_timeline_signal() - signal a status change on a sync_timeline
+ * @obj: sync_timeline to signal
+ *
+ * A sync implemntation should call this any time one of it's sync_pts
+ * has signaled or has an error condition.
+ */
+void sync_timeline_signal(struct sync_timeline *obj);
+
+/**
+ * sync_pt_create() - creates a sync pt
+ * @parent: sync_pt's parent sync_timeline
+ * @size: size to allocate for this pt
+ *
+ * Creates a new sync_pt as a chiled of @parent. @size bytes will be
+ * allocated allowing for implemntation specific data to be kept after
+ * the generic sync_timeline struct.
+ */
+struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size);
+
+/**
+ * sync_pt_free() - frees a sync pt
+ * @pt: sync_pt to free
+ *
+ * This should only be called on sync_pts which have been created but
+ * not added to a fence.
+ */
+void sync_pt_free(struct sync_pt *pt);
+
+/**
+ * sync_fence_create() - creates a sync fence
+ * @name: name of fence to create
+ * @pt: sync_pt to add to the fence
+ *
+ * Creates a fence containg @pt. Once this is called, the fence takes
+ * ownership of @pt.
+ */
+struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt);
+
+/*
+ * API for sync_fence consumers
+ */
+
+/**
+ * sync_fence_merge() - merge two fences
+ * @name: name of new fence
+ * @a: fence a
+ * @b: fence b
+ *
+ * Creates a new fence which contains copies of all the sync_pts in both
+ * @a and @b. @a and @b remain valid, independent fences.
+ */
+struct sync_fence *sync_fence_merge(const char *name,
+ struct sync_fence *a, struct sync_fence *b);
+
+/**
+ * sync_fence_fdget() - get a fence from an fd
+ * @fd: fd referencing a fence
+ *
+ * Ensures @fd references a valid fence, increments the refcount of the backing
+ * file, and returns the fence.
+ */
+struct sync_fence *sync_fence_fdget(int fd);
+
+/**
+ * sync_fence_put() - puts a refernnce of a sync fence
+ * @fence: fence to put
+ *
+ * Puts a reference on @fence. If this is the last reference, the fence and
+ * all it's sync_pts will be freed
+ */
+void sync_fence_put(struct sync_fence *fence);
+
+/**
+ * sync_fence_install() - installs a fence into a file descriptor
+ * @fence: fence to instal
+ * @fd: file descriptor in which to install the fence
+ *
+ * Installs @fence into @fd. @fd's should be acquired through get_unused_fd().
+ */
+void sync_fence_install(struct sync_fence *fence, int fd);
+
+/**
+ * sync_fence_wait_async() - registers and async wait on the fence
+ * @fence: fence to wait on
+ * @waiter: waiter callback struck
+ *
+ * Returns 1 if @fence has already signaled.
+ *
+ * Registers a callback to be called when @fence signals or has an error.
+ * @waiter should be initialized with sync_fence_waiter_init().
+ */
+int sync_fence_wait_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter);
+
+/**
+ * sync_fence_cancel_async() - cancels an async wait
+ * @fence: fence to wait on
+ * @waiter: waiter callback struck
+ *
+ * returns 0 if waiter was removed from fence's async waiter list.
+ * returns -ENOENT if waiter was not found on fence's async waiter list.
+ *
+ * Cancels a previously registered async wait. Will fail gracefully if
+ * @waiter was never registered or if @fence has already signaled @waiter.
+ */
+int sync_fence_cancel_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter);
+
+/**
+ * sync_fence_wait() - wait on fence
+ * @fence: fence to wait on
+ * @tiemout: timeout in ms
+ *
+ * Wait for @fence to be signaled or have an error. Waits indefinitely
+ * if @timeout < 0
+ */
+int sync_fence_wait(struct sync_fence *fence, long timeout);
+
+#endif /* __KERNEL__ */
+
+/**
+ * struct sync_merge_data - data passed to merge ioctl
+ * @fd2: file descriptor of second fence
+ * @name: name of new fence
+ * @fence: returns the fd of the new fence to userspace
+ */
+struct sync_merge_data {
+ __s32 fd2; /* fd of second fence */
+ char name[32]; /* name of new fence */
+ __s32 fence; /* fd on newly created fence */
+};
+
+/**
+ * struct sync_pt_info - detailed sync_pt information
+ * @len: length of sync_pt_info including any driver_data
+ * @obj_name: name of parent sync_timeline
+ * @driver_name: name of driver implmenting the parent
+ * @status: status of the sync_pt 0:active 1:signaled <0:error
+ * @timestamp_ns: timestamp of status change in nanoseconds
+ * @driver_data: any driver dependant data
+ */
+struct sync_pt_info {
+ __u32 len;
+ char obj_name[32];
+ char driver_name[32];
+ __s32 status;
+ __u64 timestamp_ns;
+
+ __u8 driver_data[0];
+};
+
+/**
+ * struct sync_fence_info_data - data returned from fence info ioctl
+ * @len: ioctl caller writes the size of the buffer its passing in.
+ * ioctl returns length of sync_fence_data reutnred to userspace
+ * including pt_info.
+ * @name: name of fence
+ * @status: status of fence. 1: signaled 0:active <0:error
+ * @pt_info: a sync_pt_info struct for every sync_pt in the fence
+ */
+struct sync_fence_info_data {
+ __u32 len;
+ char name[32];
+ __s32 status;
+
+ __u8 pt_info[0];
+};
+
+#define SYNC_IOC_MAGIC '>'
+
+/**
+ * DOC: SYNC_IOC_WAIT - wait for a fence to signal
+ *
+ * pass timeout in milliseconds. Waits indefinitely timeout < 0.
+ */
+#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
+
+/**
+ * DOC: SYNC_IOC_MERGE - merge two fences
+ *
+ * Takes a struct sync_merge_data. Creates a new fence containing copies of
+ * the sync_pts in both the calling fd and sync_merge_data.fd2. Returns the
+ * new fence's fd in sync_merge_data.fence
+ */
+#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
+
+/**
+ * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence
+ *
+ * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
+ * Caller should write the size of the buffer into len. On return, len is
+ * updated to reflect the total size of the sync_fence_info_data including
+ * pt_info.
+ *
+ * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
+ * To itterate over the sync_pt_infos, use the sync_pt_info.len field.
+ */
+#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\
+ struct sync_fence_info_data)
+
+#endif /* _LINUX_SYNC_H */
diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h
new file mode 100644
index 00000000000..95462359ba5
--- /dev/null
+++ b/drivers/staging/android/trace/sync.h
@@ -0,0 +1,82 @@
+#undef TRACE_SYSTEM
+#define TRACE_INCLUDE_PATH ../../drivers/staging/android/trace
+#define TRACE_SYSTEM sync
+
+#if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SYNC_H
+
+#include "../sync.h"
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(sync_timeline,
+ TP_PROTO(struct sync_timeline *timeline),
+
+ TP_ARGS(timeline),
+
+ TP_STRUCT__entry(
+ __string(name, timeline->name)
+ __array(char, value, 32)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name, timeline->name);
+ if (timeline->ops->timeline_value_str) {
+ timeline->ops->timeline_value_str(timeline,
+ __entry->value,
+ sizeof(__entry->value));
+ } else {
+ __entry->value[0] = '\0';
+ }
+ ),
+
+ TP_printk("name=%s value=%s", __get_str(name), __entry->value)
+);
+
+TRACE_EVENT(sync_wait,
+ TP_PROTO(struct sync_fence *fence, int begin),
+
+ TP_ARGS(fence, begin),
+
+ TP_STRUCT__entry(
+ __string(name, fence->name)
+ __field(s32, status)
+ __field(u32, begin)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name, fence->name);
+ __entry->status = fence->status;
+ __entry->begin = begin;
+ ),
+
+ TP_printk("%s name=%s state=%d", __entry->begin ? "begin" : "end",
+ __get_str(name), __entry->status)
+);
+
+TRACE_EVENT(sync_pt,
+ TP_PROTO(struct sync_pt *pt),
+
+ TP_ARGS(pt),
+
+ TP_STRUCT__entry(
+ __string(timeline, pt->parent->name)
+ __array(char, value, 32)
+ ),
+
+ TP_fast_assign(
+ __assign_str(timeline, pt->parent->name);
+ if (pt->parent->ops->pt_value_str) {
+ pt->parent->ops->pt_value_str(pt, __entry->value,
+ sizeof(__entry->value));
+ } else {
+ __entry->value[0] = '\0';
+ }
+ ),
+
+ TP_printk("name=%s value=%s", __get_str(timeline), __entry->value)
+);
+
+#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index 491e2bfbc46..35641e52939 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -1148,8 +1148,8 @@ cntrlEnd:
if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
((ULONG)pBulkBuffer->Register & 0x3)) {
- kfree(pvBuffer);
BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)pBulkBuffer->Register);
+ kfree(pvBuffer);
Status = -EINVAL;
break;
}
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c
index 64ea6edb9dc..348ad75b340 100644
--- a/drivers/staging/bcm/InterfaceDld.c
+++ b/drivers/staging/bcm/InterfaceDld.c
@@ -205,30 +205,6 @@ static int bcm_download_config_file(struct bcm_mini_adapter *Adapter, struct bcm
return retval;
}
-static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff, unsigned int len)
-{
- int retval = STATUS_SUCCESS;
- struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- if ((len-sizeof(unsigned int)) < 4) {
- if (memcmp(readbackbuff , buff, len))
- retval = -EINVAL;
- } else {
- len -= 4;
-
- while (len) {
- if (*(unsigned int *)&readbackbuff[len] != *(unsigned int *)&buff[len]) {
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper");
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
- retval = -EINVAL;
- break;
- }
- len -= 4;
- }
- }
- return retval;
-}
-
int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo)
{
int retval = STATUS_SUCCESS;
@@ -321,9 +297,11 @@ static INT buffRdbkVerify(struct bcm_mini_adapter *Adapter, PUCHAR mappedbuffer,
break;
}
- retval = bcm_compare_buff_contents(readbackbuff, mappedbuffer, len);
- if (STATUS_SUCCESS != retval)
- break;
+ if (memcmp(readbackbuff, mappedbuffer, len) != 0) {
+ pr_err("%s() failed. The firmware doesn't match what was written",
+ __func__);
+ retval = -EIO;
+ }
u32StartingAddress += len;
u32FirmwareLength -= len;
diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c
index 7028bc95b4f..af5d22faa7f 100644
--- a/drivers/staging/bcm/PHSModule.c
+++ b/drivers/staging/bcm/PHSModule.c
@@ -1,263 +1,238 @@
#include "headers.h"
-static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId, struct bcm_phs_table *psServiceFlowTable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid, B_UINT16 uiClsId, struct bcm_phs_table *psServiceFlowTable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
-static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId, struct bcm_phs_entry *pstServiceFlowEntry, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid, B_UINT16 uiClsId, struct bcm_phs_entry *pstServiceFlowEntry, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
-static UINT CreateClassifierPHSRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, enum bcm_phs_classifier_context eClsContext,B_UINT8 u8AssociatedPHSI);
+static UINT CreateClassifierPHSRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, enum bcm_phs_classifier_context eClsContext, B_UINT8 u8AssociatedPHSI);
-static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId, struct bcm_phs_classifier_entry *pstClassifierEntry, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId, struct bcm_phs_classifier_entry *pstClassifierEntry, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
static BOOLEAN ValidatePHSRuleComplete(struct bcm_phs_rule *psPhsRule);
-static BOOLEAN DerefPhsRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule);
+static BOOLEAN DerefPhsRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule);
-static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable,B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_classifier_entry **ppstClassifierEntry);
+static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_classifier_entry **ppstClassifierEntry);
-static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable,B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_rule **ppstPhsRule);
+static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_rule **ppstPhsRule);
static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable);
static int phs_compress(struct bcm_phs_rule *phs_members, unsigned char *in_buf,
- unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size );
+ unsigned char *out_buf, unsigned int *header_size, UINT *new_header_size);
+static int verify_suppress_phsf(unsigned char *in_buffer, unsigned char *out_buffer,
+ unsigned char *phsf, unsigned char *phsm, unsigned int phss, unsigned int phsv, UINT *new_header_size);
-static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
- unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size );
-
-static int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\
- struct bcm_phs_rule *phs_rules, UINT *header_size);
-
-
-static ULONG PhsCompress(void* pvContext,
- B_UINT16 uiVcid,
- B_UINT16 uiClsId,
- void *pvInputBuffer,
- void *pvOutputBuffer,
- UINT *pOldHeaderSize,
- UINT *pNewHeaderSize );
-
-static ULONG PhsDeCompress(void* pvContext,
- B_UINT16 uiVcid,
- void *pvInputBuffer,
- void *pvOutputBuffer,
- UINT *pInHeaderSize,
- UINT *pOutHeaderSize);
+static int phs_decompress(unsigned char *in_buf, unsigned char *out_buf,
+ struct bcm_phs_rule *phs_rules, UINT *header_size);
+static ULONG PhsCompress(void *pvContext,
+ B_UINT16 uiVcid,
+ B_UINT16 uiClsId,
+ void *pvInputBuffer,
+ void *pvOutputBuffer,
+ UINT *pOldHeaderSize,
+ UINT *pNewHeaderSize);
+static ULONG PhsDeCompress(void *pvContext,
+ B_UINT16 uiVcid,
+ void *pvInputBuffer,
+ void *pvOutputBuffer,
+ UINT *pInHeaderSize,
+ UINT *pOutHeaderSize);
#define IN
#define OUT
/*
-Function: PHSTransmit
-
-Description: This routine handle PHS(Payload Header Suppression for Tx path.
- It extracts a fragment of the NDIS_PACKET containing the header
- to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
- The header data after suppression is copied back to the NDIS_PACKET.
-
-
-Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
- IN Packet - NDIS packet containing data to be transmitted
- IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to
- identify PHS rule to be applied.
- B_UINT16 uiClassifierRuleID - Classifier Rule ID
- BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
-
-Return: STATUS_SUCCESS - If the send was successful.
- Other - If an error occurred.
-*/
+ * Function: PHSTransmit
+ * Description: This routine handle PHS(Payload Header Suppression for Tx path.
+ * It extracts a fragment of the NDIS_PACKET containing the header
+ * to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
+ * The header data after suppression is copied back to the NDIS_PACKET.
+ *
+ * Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
+ * IN Packet - NDIS packet containing data to be transmitted
+ * IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to
+ * identify PHS rule to be applied.
+ * B_UINT16 uiClassifierRuleID - Classifier Rule ID
+ * BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
+ *
+ * Return: STATUS_SUCCESS - If the send was successful.
+ * Other - If an error occurred.
+ */
int PHSTransmit(struct bcm_mini_adapter *Adapter,
- struct sk_buff **pPacket,
- USHORT Vcid,
- B_UINT16 uiClassifierRuleID,
- BOOLEAN bHeaderSuppressionEnabled,
- UINT *PacketLen,
- UCHAR bEthCSSupport)
+ struct sk_buff **pPacket,
+ USHORT Vcid,
+ B_UINT16 uiClassifierRuleID,
+ BOOLEAN bHeaderSuppressionEnabled,
+ UINT *PacketLen,
+ UCHAR bEthCSSupport)
{
-
- //PHS Sepcific
- UINT unPHSPktHdrBytesCopied = 0;
- UINT unPhsOldHdrSize = 0;
- UINT unPHSNewPktHeaderLen = 0;
+ /* PHS Sepcific */
+ UINT unPHSPktHdrBytesCopied = 0;
+ UINT unPhsOldHdrSize = 0;
+ UINT unPHSNewPktHeaderLen = 0;
/* Pointer to PHS IN Hdr Buffer */
- PUCHAR pucPHSPktHdrInBuf =
- Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
+ PUCHAR pucPHSPktHdrInBuf = Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
/* Pointer to PHS OUT Hdr Buffer */
- PUCHAR pucPHSPktHdrOutBuf =
- Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
- UINT usPacketType;
- UINT BytesToRemove=0;
- BOOLEAN bPHSI = 0;
+ PUCHAR pucPHSPktHdrOutBuf = Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
+ UINT usPacketType;
+ UINT BytesToRemove = 0;
+ BOOLEAN bPHSI = 0;
LONG ulPhsStatus = 0;
- UINT numBytesCompressed = 0;
+ UINT numBytesCompressed = 0;
struct sk_buff *newPacket = NULL;
struct sk_buff *Packet = *pPacket;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit");
- if(!bEthCSSupport)
- BytesToRemove=ETH_HLEN;
+ if (!bEthCSSupport)
+ BytesToRemove = ETH_HLEN;
/*
- Accumulate the header upto the size we support suppression
- from NDIS packet
- */
-
- usPacketType=((struct ethhdr *)(Packet->data))->h_proto;
+ * Accumulate the header upto the size we support suppression
+ * from NDIS packet
+ */
+ usPacketType = ((struct ethhdr *)(Packet->data))->h_proto;
pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
- //considering data after ethernet header
- if((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
- {
-
+ /* considering data after ethernet header */
+ if ((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);
- }
else
- {
unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;
- }
- if( (unPHSPktHdrBytesCopied > 0 ) &&
- (unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS))
- {
-
-
- // Step 2 Suppress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
- // Suppress only if IP Header and PHS Enabled For the Service Flow
- if(((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
- (usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
- (bHeaderSuppressionEnabled))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nTrying to PHS Compress Using Classifier rule 0x%X",uiClassifierRuleID);
-
-
- unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
- ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
- Vcid,
- uiClassifierRuleID,
- pucPHSPktHdrInBuf,
- pucPHSPktHdrOutBuf,
- &unPhsOldHdrSize,
- &unPHSNewPktHeaderLen);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nPHS Old header Size : %d New Header Size %d\n",unPhsOldHdrSize,unPHSNewPktHeaderLen);
-
- if(unPHSNewPktHeaderLen == unPhsOldHdrSize)
- {
- if( ulPhsStatus == STATUS_PHS_COMPRESSED)
- bPHSI = *pucPHSPktHdrOutBuf;
- ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
- }
-
- if( ulPhsStatus == STATUS_PHS_COMPRESSED)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHS Sending packet Compressed");
+ if ((unPHSPktHdrBytesCopied > 0) &&
+ (unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS)) {
- if(skb_cloned(Packet))
- {
- newPacket = skb_copy(Packet, GFP_ATOMIC);
+ /*
+ * Step 2 Suppress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
+ * Suppress only if IP Header and PHS Enabled For the Service Flow
+ */
+ if (((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
+ (usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
+ (bHeaderSuppressionEnabled)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nTrying to PHS Compress Using Classifier rule 0x%X", uiClassifierRuleID);
+ unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
+ ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
+ Vcid,
+ uiClassifierRuleID,
+ pucPHSPktHdrInBuf,
+ pucPHSPktHdrOutBuf,
+ &unPhsOldHdrSize,
+ &unPHSNewPktHeaderLen);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nPHS Old header Size : %d New Header Size %d\n", unPhsOldHdrSize, unPHSNewPktHeaderLen);
+
+ if (unPHSNewPktHeaderLen == unPhsOldHdrSize) {
+
+ if (ulPhsStatus == STATUS_PHS_COMPRESSED)
+ bPHSI = *pucPHSPktHdrOutBuf;
+
+ ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
+ }
- if(newPacket == NULL)
- return STATUS_FAILURE;
+ if (ulPhsStatus == STATUS_PHS_COMPRESSED) {
- dev_kfree_skb(Packet);
- *pPacket = Packet = newPacket;
- pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "PHS Sending packet Compressed");
- numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen+PHSI_LEN);
+ if (skb_cloned(Packet)) {
+ newPacket = skb_copy(Packet, GFP_ATOMIC);
- memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
- memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);
- skb_pull(Packet, numBytesCompressed);
+ if (newPacket == NULL)
+ return STATUS_FAILURE;
- return STATUS_SUCCESS;
+ dev_kfree_skb(Packet);
+ *pPacket = Packet = newPacket;
+ pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
}
- else
- {
- //if one byte headroom is not available, increase it through skb_cow
- if(!(skb_headroom(Packet) > 0))
- {
- if(skb_cow(Packet, 1))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");
- return STATUS_FAILURE;
- }
- }
- skb_push(Packet, 1);
+ numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen + PHSI_LEN);
- // CAUTION: The MAC Header is getting corrupted here for IP CS - can be saved by copying 14 Bytes. not needed .... hence corrupting it.
- *(Packet->data + BytesToRemove) = bPHSI;
- return STATUS_SUCCESS;
- }
- }
- else
- {
- if(!bHeaderSuppressionEnabled)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nHeader Suppression Disabled For SF: No PHS\n");
+ memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
+ memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);
+ skb_pull(Packet, numBytesCompressed);
+
+ return STATUS_SUCCESS;
+ } else {
+ /* if one byte headroom is not available, increase it through skb_cow */
+ if (!(skb_headroom(Packet) > 0)) {
+
+ if (skb_cow(Packet, 1)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");
+ return STATUS_FAILURE;
+ }
+ }
+ skb_push(Packet, 1);
+
+ /*
+ * CAUTION: The MAC Header is getting corrupted
+ * here for IP CS - can be saved by copying 14
+ * Bytes. not needed .... hence corrupting it.
+ */
+ *(Packet->data + BytesToRemove) = bPHSI;
+ return STATUS_SUCCESS;
}
+ } else {
+
+ if (!bHeaderSuppressionEnabled)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nHeader Suppression Disabled For SF: No PHS\n");
return STATUS_SUCCESS;
}
}
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS");
+ /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS"); */
return STATUS_SUCCESS;
}
int PHSReceive(struct bcm_mini_adapter *Adapter,
- USHORT usVcid,
- struct sk_buff *packet,
- UINT *punPacketLen,
- UCHAR *pucEthernetHdr,
- UINT bHeaderSuppressionEnabled)
+ USHORT usVcid,
+ struct sk_buff *packet,
+ UINT *punPacketLen,
+ UCHAR *pucEthernetHdr,
+ UINT bHeaderSuppressionEnabled)
{
- u32 nStandardPktHdrLen = 0;
- u32 nTotalsuppressedPktHdrBytes = 0;
- int ulPhsStatus = 0;
- PUCHAR pucInBuff = NULL ;
+ u32 nStandardPktHdrLen = 0;
+ u32 nTotalsuppressedPktHdrBytes = 0;
+ int ulPhsStatus = 0;
+ PUCHAR pucInBuff = NULL;
UINT TotalBytesAdded = 0;
- if(!bHeaderSuppressionEnabled)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
+
+ if (!bHeaderSuppressionEnabled) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nPhs Disabled for incoming packet");
return ulPhsStatus;
}
pucInBuff = packet->data;
- //Restore PHS suppressed header
+ /* Restore PHS suppressed header */
nStandardPktHdrLen = packet->len;
ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
- usVcid,
- pucInBuff,
- Adapter->ucaPHSPktRestoreBuf,
- &nTotalsuppressedPktHdrBytes,
- &nStandardPktHdrLen);
+ usVcid,
+ pucInBuff,
+ Adapter->ucaPHSPktRestoreBuf,
+ &nTotalsuppressedPktHdrBytes,
+ &nStandardPktHdrLen);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
- nTotalsuppressedPktHdrBytes,nStandardPktHdrLen);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
+ nTotalsuppressedPktHdrBytes, nStandardPktHdrLen);
- if(ulPhsStatus != STATUS_PHS_COMPRESSED)
- {
+ if (ulPhsStatus != STATUS_PHS_COMPRESSED) {
skb_pull(packet, 1);
return STATUS_SUCCESS;
- }
- else
- {
+ } else {
TotalBytesAdded = nStandardPktHdrLen - nTotalsuppressedPktHdrBytes - PHSI_LEN;
- if(TotalBytesAdded)
- {
- if(skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
+
+ if (TotalBytesAdded) {
+ if (skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
skb_push(packet, TotalBytesAdded);
- else
- {
- if(skb_cow(packet, skb_headroom(packet) + TotalBytesAdded))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");
+ else {
+ if (skb_cow(packet, skb_headroom(packet) + TotalBytesAdded)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");
return STATUS_FAILURE;
}
@@ -271,90 +246,80 @@ int PHSReceive(struct bcm_mini_adapter *Adapter,
return STATUS_SUCCESS;
}
-void DumpFullPacket(UCHAR *pBuf,UINT nPktLen)
+void DumpFullPacket(UCHAR *pBuf, UINT nPktLen)
{
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"Dumping Data Packet");
- BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,pBuf,nPktLen);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dumping Data Packet");
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, pBuf, nPktLen);
}
-//-----------------------------------------------------------------------------
-// Procedure: phs_init
-//
-// Description: This routine is responsible for allocating memory for classifier and
-// PHS rules.
-//
-// Arguments:
-// pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
-//
-// Returns:
-// TRUE(1) -If allocation of memory was success full.
-// FALSE -If allocation of memory fails.
-//-----------------------------------------------------------------------------
+/*
+ * Procedure: phs_init
+ *
+ * Description: This routine is responsible for allocating memory for classifier and
+ * PHS rules.
+ *
+ * Arguments:
+ * pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
+ *
+ * Returns:
+ * TRUE(1) -If allocation of memory was successful.
+ * FALSE -If allocation of memory fails.
+ */
int phs_init(struct bcm_phs_extension *pPhsdeviceExtension, struct bcm_mini_adapter *Adapter)
{
int i;
struct bcm_phs_table *pstServiceFlowTable;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function ");
- if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function");
+
+ if (pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
return -EINVAL;
- pPhsdeviceExtension->pstServiceFlowPhsRulesTable =
- kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
+ pPhsdeviceExtension->pstServiceFlowPhsRulesTable = kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
- if(!pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");
+ if (!pPhsdeviceExtension->pstServiceFlowPhsRulesTable) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");
return -ENOMEM;
}
pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
- for(i=0;i<MAX_SERVICEFLOWS;i++)
- {
+ for (i = 0; i < MAX_SERVICEFLOWS; i++) {
struct bcm_phs_entry sServiceFlow = pstServiceFlowTable->stSFList[i];
sServiceFlow.pstClassifierTable = kzalloc(sizeof(struct bcm_phs_classifier_table), GFP_KERNEL);
- if(!sServiceFlow.pstClassifierTable)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
- free_phs_serviceflow_rules(pPhsdeviceExtension->
- pstServiceFlowPhsRulesTable);
+ if (!sServiceFlow.pstClassifierTable) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+ free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
return -ENOMEM;
}
}
pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
-
- if(pPhsdeviceExtension->CompressedTxBuffer == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+ if (pPhsdeviceExtension->CompressedTxBuffer == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
return -ENOMEM;
}
- pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
- if(pPhsdeviceExtension->UnCompressedRxBuffer == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+ pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
+ if (pPhsdeviceExtension->UnCompressedRxBuffer == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
kfree(pPhsdeviceExtension->CompressedTxBuffer);
free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
return -ENOMEM;
}
-
-
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successful");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successful");
return STATUS_SUCCESS;
}
-
int PhsCleanup(IN struct bcm_phs_extension *pPHSDeviceExt)
{
- if(pPHSDeviceExt->pstServiceFlowPhsRulesTable)
- {
+ if (pPHSDeviceExt->pstServiceFlowPhsRulesTable) {
free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);
pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;
}
@@ -368,200 +333,173 @@ int PhsCleanup(IN struct bcm_phs_extension *pPHSDeviceExt)
return 0;
}
-
-
-//PHS functions
-/*++
-PhsUpdateClassifierRule
-
-Routine Description:
- Exported function to add or modify a PHS Rule.
-
-Arguments:
- IN void* pvContext - PHS Driver Specific Context
- IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
- IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
- IN struct bcm_phs_rule *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
-
-Return Value:
-
- 0 if successful,
- >0 Error.
-
---*/
-ULONG PhsUpdateClassifierRule(IN void* pvContext,
- IN B_UINT16 uiVcid ,
- IN B_UINT16 uiClsId ,
- IN struct bcm_phs_rule *psPhsRule,
- IN B_UINT8 u8AssociatedPHSI)
+/*
+ * PHS functions
+ * PhsUpdateClassifierRule
+ *
+ * Routine Description:
+ * Exported function to add or modify a PHS Rule.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context
+ * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
+ * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
+ * IN struct bcm_phs_rule *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsUpdateClassifierRule(IN void *pvContext,
+ IN B_UINT16 uiVcid ,
+ IN B_UINT16 uiClsId ,
+ IN struct bcm_phs_rule *psPhsRule,
+ IN B_UINT8 u8AssociatedPHSI)
{
- ULONG lStatus =0;
- UINT nSFIndex =0 ;
+ ULONG lStatus = 0;
+ UINT nSFIndex = 0;
struct bcm_phs_entry *pstServiceFlowEntry = NULL;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "PHS With Corr2 Changes\n");
-
- struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
-
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS With Corr2 Changes \n");
-
- if(pDeviceExtension == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Invalid Device Extension\n");
+ if (pDeviceExtension == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "Invalid Device Extension\n");
return ERR_PHS_INVALID_DEVICE_EXETENSION;
}
-
- if(u8AssociatedPHSI == 0)
- {
+ if (u8AssociatedPHSI == 0)
return ERR_PHS_INVALID_PHS_RULE;
- }
/* Retrieve the SFID Entry Index for requested Service Flow */
-
nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
- uiVcid,&pstServiceFlowEntry);
+ uiVcid, &pstServiceFlowEntry);
- if(nSFIndex == PHS_INVALID_TABLE_INDEX)
- {
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
/* This is a new SF. Create a mapping entry for this */
lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
- pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);
+ pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);
return lStatus;
}
/* SF already Exists Add PHS Rule to existing SF */
- lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
- pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);
+ lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
+ pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);
- return lStatus;
+ return lStatus;
}
-/*++
-PhsDeletePHSRule
-
-Routine Description:
- Deletes the specified phs Rule within Vcid
-
-Arguments:
- IN void* pvContext - PHS Driver Specific Context
- IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
- IN B_UINT8 u8PHSI - the PHS Index identifying PHS rule to be deleted.
-
-Return Value:
-
- 0 if successful,
- >0 Error.
-
---*/
-
-ULONG PhsDeletePHSRule(IN void* pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI)
+/*
+ * PhsDeletePHSRule
+ *
+ * Routine Description:
+ * Deletes the specified phs Rule within Vcid
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context
+ * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
+ * IN B_UINT8 u8PHSI - the PHS Index identifying PHS rule to be deleted.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeletePHSRule(IN void *pvContext, IN B_UINT16 uiVcid, IN B_UINT8 u8PHSI)
{
- ULONG lStatus =0;
- UINT nSFIndex =0, nClsidIndex =0 ;
+ ULONG lStatus = 0;
+ UINT nSFIndex = 0, nClsidIndex = 0;
struct bcm_phs_entry *pstServiceFlowEntry = NULL;
struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n");
- struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
+ if (pDeviceExtension) {
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n");
-
- if(pDeviceExtension)
- {
-
- //Retrieve the SFID Entry Index for requested Service Flow
- nSFIndex = GetServiceFlowEntry(pDeviceExtension
- ->pstServiceFlowPhsRulesTable,uiVcid,&pstServiceFlowEntry);
-
- if(nSFIndex == PHS_INVALID_TABLE_INDEX)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
return ERR_SF_MATCH_FAIL;
}
- pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
- if(pstClassifierRulesTable)
- {
- for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
- {
- if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
- {
- if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI) {
- if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
+ if (pstClassifierRulesTable) {
+ for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) {
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI) {
+
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
- if(0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+
+ if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
+
memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0,
sizeof(struct bcm_phs_classifier_entry));
}
}
}
}
-
}
return lStatus;
}
-/*++
-PhsDeleteClassifierRule
-
-Routine Description:
- Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
-
-Arguments:
- IN void* pvContext - PHS Driver Specific Context
- IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
- IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
-
-Return Value:
-
- 0 if successful,
- >0 Error.
-
---*/
-ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16 uiClsId)
+/*
+ * PhsDeleteClassifierRule
+ *
+ * Routine Description:
+ * Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context
+ * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
+ * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeleteClassifierRule(IN void *pvContext, IN B_UINT16 uiVcid, IN B_UINT16 uiClsId)
{
- ULONG lStatus =0;
- UINT nSFIndex =0, nClsidIndex =0 ;
+ ULONG lStatus = 0;
+ UINT nSFIndex = 0, nClsidIndex = 0;
struct bcm_phs_entry *pstServiceFlowEntry = NULL;
struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
-
- if(pDeviceExtension)
- {
- //Retrieve the SFID Entry Index for requested Service Flow
- nSFIndex = GetServiceFlowEntry(pDeviceExtension
- ->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
- if(nSFIndex == PHS_INVALID_TABLE_INDEX)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"SFID Match Failed\n");
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+ if (pDeviceExtension) {
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
return ERR_SF_MATCH_FAIL;
}
nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
- uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
- if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
- {
- if(pstClassifierEntry->pstPhsRule)
- {
- if(pstClassifierEntry->pstPhsRule->u8RefCnt)
- pstClassifierEntry->pstPhsRule->u8RefCnt--;
- if(0==pstClassifierEntry->pstPhsRule->u8RefCnt)
- kfree(pstClassifierEntry->pstPhsRule);
+ uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
+ if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) {
+ if (pstClassifierEntry->pstPhsRule) {
+ if (pstClassifierEntry->pstPhsRule->u8RefCnt)
+ pstClassifierEntry->pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierEntry->pstPhsRule->u8RefCnt)
+ kfree(pstClassifierEntry->pstPhsRule);
}
memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry));
}
nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
- uiClsId,eOldClassifierRuleContext,&pstClassifierEntry);
+ uiClsId, eOldClassifierRuleContext, &pstClassifierEntry);
- if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
- {
+ if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) {
kfree(pstClassifierEntry->pstPhsRule);
memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry));
}
@@ -569,261 +507,223 @@ ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16
return lStatus;
}
-/*++
-PhsDeleteSFRules
-
-Routine Description:
- Exported function to Delete a all PHS Rules for the SFID.
-
-Arguments:
- IN void* pvContext - PHS Driver Specific Context
- IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted
-
-Return Value:
-
- 0 if successful,
- >0 Error.
-
---*/
-ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid)
+/*
+ * PhsDeleteSFRules
+ *
+ * Routine Description:
+ * Exported function to Delete a all PHS Rules for the SFID.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context
+ * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeleteSFRules(IN void *pvContext, IN B_UINT16 uiVcid)
{
-
- ULONG lStatus =0;
- UINT nSFIndex =0, nClsidIndex =0 ;
+ ULONG lStatus = 0;
+ UINT nSFIndex = 0, nClsidIndex = 0;
struct bcm_phs_entry *pstServiceFlowEntry = NULL;
struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"====> \n");
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "====>\n");
- if(pDeviceExtension)
- {
- //Retrieve the SFID Entry Index for requested Service Flow
+ if (pDeviceExtension) {
+ /* Retrieve the SFID Entry Index for requested Service Flow */
nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
- uiVcid,&pstServiceFlowEntry);
- if(nSFIndex == PHS_INVALID_TABLE_INDEX)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
+ uiVcid, &pstServiceFlowEntry);
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
return ERR_SF_MATCH_FAIL;
}
- pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
- if(pstClassifierRulesTable)
- {
- for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
- {
- if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
- {
- if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
- .pstPhsRule->u8RefCnt)
- pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
- .pstPhsRule->u8RefCnt--;
- if(0==pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
- .pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
+ if (pstClassifierRulesTable) {
+ for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) {
+
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
- pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
- .pstPhsRule = NULL;
+
+ pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule = NULL;
}
memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry));
- if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule)
- {
- if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
- .pstPhsRule->u8RefCnt)
- pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
- .pstPhsRule->u8RefCnt--;
- if(0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
- .pstPhsRule->u8RefCnt)
- kfree(pstClassifierRulesTable
- ->stOldPhsRulesList[nClsidIndex].pstPhsRule);
- pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
- .pstPhsRule = NULL;
+ if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule) {
+
+ if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ kfree(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule);
+
+ pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule = NULL;
}
memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry));
}
}
pstServiceFlowEntry->bUsed = FALSE;
pstServiceFlowEntry->uiVcid = 0;
-
}
return lStatus;
}
-
-/*++
-PhsCompress
-
-Routine Description:
- Exported function to compress the data using PHS.
-
-Arguments:
- IN void* pvContext - PHS Driver Specific Context.
- IN B_UINT16 uiVcid - The Service Flow ID to which current packet header compression applies.
- IN UINT uiClsId - The Classifier ID to which current packet header compression applies.
- IN void *pvInputBuffer - The Input buffer containg packet header data
- IN void *pvOutputBuffer - The output buffer returned by this function after PHS
- IN UINT *pOldHeaderSize - The actual size of the header before PHS
- IN UINT *pNewHeaderSize - The new size of the header after applying PHS
-
-Return Value:
-
- 0 if successful,
- >0 Error.
-
---*/
-ULONG PhsCompress(IN void* pvContext,
- IN B_UINT16 uiVcid,
- IN B_UINT16 uiClsId,
- IN void *pvInputBuffer,
- OUT void *pvOutputBuffer,
- OUT UINT *pOldHeaderSize,
- OUT UINT *pNewHeaderSize )
+/*
+ * PhsCompress
+ *
+ * Routine Description:
+ * Exported function to compress the data using PHS.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context.
+ * IN B_UINT16 uiVcid - The Service Flow ID to which current packet header compression applies.
+ * IN UINT uiClsId - The Classifier ID to which current packet header compression applies.
+ * IN void *pvInputBuffer - The Input buffer containg packet header data
+ * IN void *pvOutputBuffer - The output buffer returned by this function after PHS
+ * IN UINT *pOldHeaderSize - The actual size of the header before PHS
+ * IN UINT *pNewHeaderSize - The new size of the header after applying PHS
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsCompress(IN void *pvContext,
+ IN B_UINT16 uiVcid,
+ IN B_UINT16 uiClsId,
+ IN void *pvInputBuffer,
+ OUT void *pvOutputBuffer,
+ OUT UINT *pOldHeaderSize,
+ OUT UINT *pNewHeaderSize)
{
- UINT nSFIndex =0, nClsidIndex =0 ;
+ UINT nSFIndex = 0, nClsidIndex = 0;
struct bcm_phs_entry *pstServiceFlowEntry = NULL;
struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
struct bcm_phs_rule *pstPhsRule = NULL;
- ULONG lStatus =0;
+ ULONG lStatus = 0;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
-
-
- struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
-
-
- if(pDeviceExtension == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Invalid Device Extension\n");
- lStatus = STATUS_PHS_NOCOMPRESSION ;
+ if (pDeviceExtension == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Invalid Device Extension\n");
+ lStatus = STATUS_PHS_NOCOMPRESSION;
return lStatus;
-
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Suppressing header \n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Suppressing header\n");
-
- //Retrieve the SFID Entry Index for requested Service Flow
+ /* Retrieve the SFID Entry Index for requested Service Flow */
nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
- uiVcid,&pstServiceFlowEntry);
- if(nSFIndex == PHS_INVALID_TABLE_INDEX)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"SFID Match Failed\n");
- lStatus = STATUS_PHS_NOCOMPRESSION ;
+ uiVcid, &pstServiceFlowEntry);
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "SFID Match Failed\n");
+ lStatus = STATUS_PHS_NOCOMPRESSION;
return lStatus;
}
nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
- uiClsId,eActiveClassifierRuleContext,&pstClassifierEntry);
+ uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
- if(nClsidIndex == PHS_INVALID_TABLE_INDEX)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"No PHS Rule Defined For Classifier\n");
- lStatus = STATUS_PHS_NOCOMPRESSION ;
+ if (nClsidIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "No PHS Rule Defined For Classifier\n");
+ lStatus = STATUS_PHS_NOCOMPRESSION;
return lStatus;
}
-
- //get rule from SF id,Cls ID pair and proceed
- pstPhsRule = pstClassifierEntry->pstPhsRule;
-
- if(!ValidatePHSRuleComplete(pstPhsRule))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS Rule Defined For Classifier But Not Complete\n");
- lStatus = STATUS_PHS_NOCOMPRESSION ;
+ /* get rule from SF id,Cls ID pair and proceed */
+ pstPhsRule = pstClassifierEntry->pstPhsRule;
+ if (!ValidatePHSRuleComplete(pstPhsRule)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "PHS Rule Defined For Classifier But Not Complete\n");
+ lStatus = STATUS_PHS_NOCOMPRESSION;
return lStatus;
}
- //Compress Packet
- lStatus = phs_compress(pstPhsRule,(PUCHAR)pvInputBuffer,
- (PUCHAR)pvOutputBuffer, pOldHeaderSize,pNewHeaderSize);
+ /* Compress Packet */
+ lStatus = phs_compress(pstPhsRule, (PUCHAR)pvInputBuffer,
+ (PUCHAR)pvOutputBuffer, pOldHeaderSize, pNewHeaderSize);
- if(lStatus == STATUS_PHS_COMPRESSED)
- {
+ if (lStatus == STATUS_PHS_COMPRESSED) {
pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1;
pstPhsRule->PHSModifiedNumPackets++;
- }
- else
+ } else
pstPhsRule->PHSErrorNumPackets++;
return lStatus;
}
-/*++
-PhsDeCompress
-
-Routine Description:
- Exported function to restore the packet header in Rx path.
-
-Arguments:
- IN void* pvContext - PHS Driver Specific Context.
- IN B_UINT16 uiVcid - The Service Flow ID to which current packet header restoration applies.
- IN void *pvInputBuffer - The Input buffer containg suppressed packet header data
- OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
- OUT UINT *pHeaderSize - The packet header size after restoration is returned in this parameter.
-
-Return Value:
-
- 0 if successful,
- >0 Error.
-
---*/
-ULONG PhsDeCompress(IN void* pvContext,
- IN B_UINT16 uiVcid,
- IN void *pvInputBuffer,
- OUT void *pvOutputBuffer,
- OUT UINT *pInHeaderSize,
- OUT UINT *pOutHeaderSize )
+/*
+ * PhsDeCompress
+ *
+ * Routine Description:
+ * Exported function to restore the packet header in Rx path.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context.
+ * IN B_UINT16 uiVcid - The Service Flow ID to which current packet header restoration applies.
+ * IN void *pvInputBuffer - The Input buffer containg suppressed packet header data
+ * OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
+ * OUT UINT *pHeaderSize - The packet header size after restoration is returned in this parameter.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeCompress(IN void *pvContext,
+ IN B_UINT16 uiVcid,
+ IN void *pvInputBuffer,
+ OUT void *pvOutputBuffer,
+ OUT UINT *pInHeaderSize,
+ OUT UINT *pOutHeaderSize)
{
- UINT nSFIndex =0, nPhsRuleIndex =0 ;
+ UINT nSFIndex = 0, nPhsRuleIndex = 0;
struct bcm_phs_entry *pstServiceFlowEntry = NULL;
struct bcm_phs_rule *pstPhsRule = NULL;
UINT phsi;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- struct bcm_phs_extension *pDeviceExtension=
- (struct bcm_phs_extension *)pvContext;
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
*pInHeaderSize = 0;
-
- if(pDeviceExtension == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Invalid Device Extension\n");
+ if (pDeviceExtension == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "Invalid Device Extension\n");
return ERR_PHS_INVALID_DEVICE_EXETENSION;
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Restoring header\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "Restoring header\n");
phsi = *((unsigned char *)(pvInputBuffer));
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x\n",phsi);
- if(phsi == UNCOMPRESSED_PACKET )
- {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "PHSI To Be Used For restore : %x\n", phsi);
+ if (phsi == UNCOMPRESSED_PACKET)
return STATUS_PHS_NOCOMPRESSION;
- }
- //Retrieve the SFID Entry Index for requested Service Flow
+ /* Retrieve the SFID Entry Index for requested Service Flow */
nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
- uiVcid,&pstServiceFlowEntry);
- if(nSFIndex == PHS_INVALID_TABLE_INDEX)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
+ uiVcid, &pstServiceFlowEntry);
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "SFID Match Failed During Lookup\n");
return ERR_SF_MATCH_FAIL;
}
- nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,phsi,
- eActiveClassifierRuleContext,&pstPhsRule);
- if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
- {
- //Phs Rule does not exist in active rules table. Lets try in the old rules table.
+ nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable, phsi,
+ eActiveClassifierRuleContext, &pstPhsRule);
+ if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) {
+ /* Phs Rule does not exist in active rules table. Lets try in the old rules table. */
nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
- phsi,eOldClassifierRuleContext,&pstPhsRule);
- if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
- {
+ phsi, eOldClassifierRuleContext, &pstPhsRule);
+ if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
return ERR_PHSRULE_MATCH_FAIL;
- }
-
}
*pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
- (PUCHAR)pvOutputBuffer,pstPhsRule,pOutHeaderSize);
+ (PUCHAR)pvOutputBuffer, pstPhsRule, pOutHeaderSize);
pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
@@ -831,112 +731,94 @@ ULONG PhsDeCompress(IN void* pvContext,
return STATUS_PHS_COMPRESSED;
}
-
-//-----------------------------------------------------------------------------
-// Procedure: free_phs_serviceflow_rules
-//
-// Description: This routine is responsible for freeing memory allocated for PHS rules.
-//
-// Arguments:
-// rules - ptr to S_SERVICEFLOW_TABLE structure.
-//
-// Returns:
-// Does not return any value.
-//-----------------------------------------------------------------------------
-
+/*
+ * Procedure: free_phs_serviceflow_rules
+ *
+ * Description: This routine is responsible for freeing memory allocated for PHS rules.
+ *
+ * Arguments:
+ * rules - ptr to S_SERVICEFLOW_TABLE structure.
+ *
+ * Returns:
+ * Does not return any value.
+ */
static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable)
{
- int i,j;
+ int i, j;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n");
- if(psServiceFlowRulesTable)
- {
- for(i=0;i<MAX_SERVICEFLOWS;i++)
- {
- struct bcm_phs_entry stServiceFlowEntry =
- psServiceFlowRulesTable->stSFList[i];
- struct bcm_phs_classifier_table *pstClassifierRulesTable =
- stServiceFlowEntry.pstClassifierTable;
-
- if(pstClassifierRulesTable)
- {
- for(j=0;j<MAX_PHSRULE_PER_SF;j++)
- {
- if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule)
- {
- if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
- ->u8RefCnt)
- pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
- ->u8RefCnt--;
- if(0==pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
- ->u8RefCnt)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n");
+
+ if (psServiceFlowRulesTable) {
+ for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+ struct bcm_phs_entry stServiceFlowEntry = psServiceFlowRulesTable->stSFList[i];
+ struct bcm_phs_classifier_table *pstClassifierRulesTable = stServiceFlowEntry.pstClassifierTable;
+
+ if (pstClassifierRulesTable) {
+ for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
+ if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule) {
+
+ if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt)
kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule);
+
pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL;
}
- if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule)
- {
- if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
- ->u8RefCnt)
- pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
- ->u8RefCnt--;
- if(0==pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
- ->u8RefCnt)
+
+ if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule) {
+
+ if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt)
kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule);
+
pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL;
}
}
kfree(pstClassifierRulesTable);
- stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
+ stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
}
}
}
- kfree(psServiceFlowRulesTable);
- psServiceFlowRulesTable = NULL;
+ kfree(psServiceFlowRulesTable);
+ psServiceFlowRulesTable = NULL;
}
-
-
static BOOLEAN ValidatePHSRuleComplete(IN struct bcm_phs_rule *psPhsRule)
{
- if(psPhsRule)
- {
- if(!psPhsRule->u8PHSI)
- {
- // PHSI is not valid
+ if (psPhsRule) {
+ if (!psPhsRule->u8PHSI) {
+ /* PHSI is not valid */
return FALSE;
}
- if(!psPhsRule->u8PHSS)
- {
- //PHSS Is Undefined
+ if (!psPhsRule->u8PHSS) {
+ /* PHSS Is Undefined */
return FALSE;
}
- //Check if PHSF is defines for the PHS Rule
- if(!psPhsRule->u8PHSFLength) // If any part of PHSF is valid then Rule contains valid PHSF
- {
+ /* Check if PHSF is defines for the PHS Rule */
+ if (!psPhsRule->u8PHSFLength) /* If any part of PHSF is valid then Rule contains valid PHSF */
return FALSE;
- }
+
return TRUE;
- }
- else
- {
+ } else
return FALSE;
- }
}
UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
- IN B_UINT16 uiVcid, struct bcm_phs_entry **ppstServiceFlowEntry)
+ IN B_UINT16 uiVcid,
+ struct bcm_phs_entry **ppstServiceFlowEntry)
{
- int i;
- for(i=0;i<MAX_SERVICEFLOWS;i++)
- {
- if(psServiceFlowTable->stSFList[i].bUsed)
- {
- if(psServiceFlowTable->stSFList[i].uiVcid == uiVcid)
- {
+ int i;
+
+ for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+ if (psServiceFlowTable->stSFList[i].bUsed) {
+ if (psServiceFlowTable->stSFList[i].uiVcid == uiVcid) {
*ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i];
return i;
}
@@ -947,34 +829,26 @@ UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
return PHS_INVALID_TABLE_INDEX;
}
-
UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
- IN B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext,
- OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
+ IN B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext,
+ OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
{
int i;
struct bcm_phs_classifier_entry *psClassifierRules = NULL;
- for(i=0;i<MAX_PHSRULE_PER_SF;i++)
- {
- if(eClsContext == eActiveClassifierRuleContext)
- {
+ for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
+
+ if (eClsContext == eActiveClassifierRuleContext)
psClassifierRules = &pstClassifierTable->stActivePhsRulesList[i];
- }
else
- {
psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i];
- }
- if(psClassifierRules->bUsed)
- {
- if(psClassifierRules->uiClassifierRuleId == uiClsid)
- {
+ if (psClassifierRules->bUsed) {
+ if (psClassifierRules->uiClassifierRuleId == uiClsid) {
*ppstClassifierEntry = psClassifierRules;
return i;
}
}
-
}
*ppstClassifierEntry = NULL;
@@ -982,254 +856,227 @@ UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
}
static UINT GetPhsRuleEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
- IN B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext,
- OUT struct bcm_phs_rule **ppstPhsRule)
+ IN B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext,
+ OUT struct bcm_phs_rule **ppstPhsRule)
{
int i;
struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
- for(i=0;i<MAX_PHSRULE_PER_SF;i++)
- {
- if(eClsContext == eActiveClassifierRuleContext)
- {
+
+ for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
+ if (eClsContext == eActiveClassifierRuleContext)
pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[i];
- }
else
- {
pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i];
- }
- if(pstClassifierRule->bUsed)
- {
- if(pstClassifierRule->u8PHSI == uiPHSI)
- {
+
+ if (pstClassifierRule->bUsed) {
+ if (pstClassifierRule->u8PHSI == uiPHSI) {
*ppstPhsRule = pstClassifierRule->pstPhsRule;
return i;
}
}
-
}
*ppstPhsRule = NULL;
return PHS_INVALID_TABLE_INDEX;
}
-UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,IN B_UINT16 uiClsId,
- IN struct bcm_phs_table *psServiceFlowTable, struct bcm_phs_rule *psPhsRule,
- B_UINT8 u8AssociatedPHSI)
+UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16 uiClsId,
+ IN struct bcm_phs_table *psServiceFlowTable,
+ struct bcm_phs_rule *psPhsRule,
+ B_UINT8 u8AssociatedPHSI)
{
-
struct bcm_phs_classifier_table *psaClassifiertable = NULL;
UINT uiStatus = 0;
int iSfIndex;
- BOOLEAN bFreeEntryFound =FALSE;
- //Check for a free entry in SFID table
- for(iSfIndex=0;iSfIndex < MAX_SERVICEFLOWS;iSfIndex++)
- {
- if(!psServiceFlowTable->stSFList[iSfIndex].bUsed)
- {
+ BOOLEAN bFreeEntryFound = FALSE;
+
+ /* Check for a free entry in SFID table */
+ for (iSfIndex = 0; iSfIndex < MAX_SERVICEFLOWS; iSfIndex++) {
+ if (!psServiceFlowTable->stSFList[iSfIndex].bUsed) {
bFreeEntryFound = TRUE;
break;
}
}
- if(!bFreeEntryFound)
+ if (!bFreeEntryFound)
return ERR_SFTABLE_FULL;
-
psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable;
- uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,psPhsRule,
- eActiveClassifierRuleContext,u8AssociatedPHSI);
- if(uiStatus == PHS_SUCCESS)
- {
- //Add entry at free index to the SF
+ uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable, psPhsRule,
+ eActiveClassifierRuleContext, u8AssociatedPHSI);
+ if (uiStatus == PHS_SUCCESS) {
+ /* Add entry at free index to the SF */
psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE;
psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid;
}
return uiStatus;
-
}
UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
- IN B_UINT16 uiClsId,IN struct bcm_phs_entry *pstServiceFlowEntry,
- struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI)
+ IN B_UINT16 uiClsId,
+ IN struct bcm_phs_entry *pstServiceFlowEntry,
+ struct bcm_phs_rule *psPhsRule,
+ B_UINT8 u8AssociatedPHSI)
{
struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
- UINT uiStatus =PHS_SUCCESS;
+ UINT uiStatus = PHS_SUCCESS;
UINT nClassifierIndex = 0;
struct bcm_phs_classifier_table *psaClassifiertable = NULL;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>");
+ psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>");
/* Check if the supplied Classifier already exists */
- nClassifierIndex =GetClassifierEntry(
- pstServiceFlowEntry->pstClassifierTable,uiClsId,
- eActiveClassifierRuleContext,&pstClassifierEntry);
- if(nClassifierIndex == PHS_INVALID_TABLE_INDEX)
- {
+ nClassifierIndex = GetClassifierEntry(
+ pstServiceFlowEntry->pstClassifierTable,
+ uiClsId,
+ eActiveClassifierRuleContext,
+ &pstClassifierEntry);
+
+ if (nClassifierIndex == PHS_INVALID_TABLE_INDEX) {
/*
- The Classifier doesn't exist. So its a new classifier being added.
- Add new entry to associate PHS Rule to the Classifier
- */
+ * The Classifier doesn't exist. So its a new classifier being added.
+ * Add new entry to associate PHS Rule to the Classifier
+ */
- uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,
- psPhsRule,eActiveClassifierRuleContext,u8AssociatedPHSI);
+ uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable,
+ psPhsRule,
+ eActiveClassifierRuleContext,
+ u8AssociatedPHSI);
return uiStatus;
}
/*
- The Classifier exists.The PHS Rule for this classifier
- is being modified
- */
- if(pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI)
- {
- if(pstClassifierEntry->pstPhsRule == NULL)
+ * The Classifier exists.The PHS Rule for this classifier
+ * is being modified
+ */
+
+ if (pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI) {
+ if (pstClassifierEntry->pstPhsRule == NULL)
return ERR_PHS_INVALID_PHS_RULE;
/*
- This rule already exists if any fields are changed for this PHS
- rule update them.
+ * This rule already exists if any fields are changed for this PHS
+ * rule update them.
*/
- /* If any part of PHSF is valid then we update PHSF */
- if(psPhsRule->u8PHSFLength)
- {
- //update PHSF
+ /* If any part of PHSF is valid then we update PHSF */
+ if (psPhsRule->u8PHSFLength) {
+ /* update PHSF */
memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
- psPhsRule->u8PHSF , MAX_PHS_LENGTHS);
+ psPhsRule->u8PHSF, MAX_PHS_LENGTHS);
}
- if(psPhsRule->u8PHSFLength)
- {
- //update PHSFLen
- pstClassifierEntry->pstPhsRule->u8PHSFLength =
- psPhsRule->u8PHSFLength;
+
+ if (psPhsRule->u8PHSFLength) {
+ /* update PHSFLen */
+ pstClassifierEntry->pstPhsRule->u8PHSFLength = psPhsRule->u8PHSFLength;
}
- if(psPhsRule->u8PHSMLength)
- {
- //update PHSM
+
+ if (psPhsRule->u8PHSMLength) {
+ /* update PHSM */
memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
- psPhsRule->u8PHSM, MAX_PHS_LENGTHS);
+ psPhsRule->u8PHSM, MAX_PHS_LENGTHS);
}
- if(psPhsRule->u8PHSMLength)
- {
- //update PHSM Len
+
+ if (psPhsRule->u8PHSMLength) {
+ /* update PHSM Len */
pstClassifierEntry->pstPhsRule->u8PHSMLength =
- psPhsRule->u8PHSMLength;
+ psPhsRule->u8PHSMLength;
}
- if(psPhsRule->u8PHSS)
- {
- //update PHSS
+
+ if (psPhsRule->u8PHSS) {
+ /* update PHSS */
pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS;
}
- //update PHSV
+ /* update PHSV */
pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
-
+ } else {
+ /* A new rule is being set for this classifier. */
+ uiStatus = UpdateClassifierPHSRule(uiClsId, pstClassifierEntry,
+ psaClassifiertable, psPhsRule, u8AssociatedPHSI);
}
- else
- {
- /*
- A new rule is being set for this classifier.
- */
- uiStatus=UpdateClassifierPHSRule( uiClsId, pstClassifierEntry,
- psaClassifiertable, psPhsRule, u8AssociatedPHSI);
- }
-
-
return uiStatus;
}
static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId,
- struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule,
- enum bcm_phs_classifier_context eClsContext,B_UINT8 u8AssociatedPHSI)
+ struct bcm_phs_classifier_table *psaClassifiertable,
+ struct bcm_phs_rule *psPhsRule,
+ enum bcm_phs_classifier_context eClsContext,
+ B_UINT8 u8AssociatedPHSI)
{
UINT iClassifierIndex = 0;
BOOLEAN bFreeEntryFound = FALSE;
struct bcm_phs_classifier_entry *psClassifierRules = NULL;
UINT nStatus = PHS_SUCCESS;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Inside CreateClassifierPHSRule");
- if(psaClassifiertable == NULL)
- {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "Inside CreateClassifierPHSRule");
+
+ if (psaClassifiertable == NULL)
return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
- }
- if(eClsContext == eOldClassifierRuleContext)
- {
- /* If An Old Entry for this classifier ID already exists in the
- old rules table replace it. */
+ if (eClsContext == eOldClassifierRuleContext) {
+ /*
+ * If An Old Entry for this classifier ID already exists in the
+ * old rules table replace it.
+ */
iClassifierIndex =
- GetClassifierEntry(psaClassifiertable, uiClsId,
- eClsContext,&psClassifierRules);
- if(iClassifierIndex != PHS_INVALID_TABLE_INDEX)
- {
+ GetClassifierEntry(psaClassifiertable, uiClsId,
+ eClsContext, &psClassifierRules);
+
+ if (iClassifierIndex != PHS_INVALID_TABLE_INDEX) {
/*
- The Classifier already exists in the old rules table
- Lets replace the old classifier with the new one.
- */
+ * The Classifier already exists in the old rules table
+ * Lets replace the old classifier with the new one.
+ */
bFreeEntryFound = TRUE;
}
}
- if(!bFreeEntryFound)
- {
- /*
- Continue to search for a free location to add the rule
- */
- for(iClassifierIndex = 0; iClassifierIndex <
- MAX_PHSRULE_PER_SF; iClassifierIndex++)
- {
- if(eClsContext == eActiveClassifierRuleContext)
- {
- psClassifierRules =
- &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
- }
+ if (!bFreeEntryFound) {
+ /* Continue to search for a free location to add the rule */
+ for (iClassifierIndex = 0; iClassifierIndex <
+ MAX_PHSRULE_PER_SF; iClassifierIndex++) {
+ if (eClsContext == eActiveClassifierRuleContext)
+ psClassifierRules = &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
else
- {
- psClassifierRules =
- &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
- }
+ psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
- if(!psClassifierRules->bUsed)
- {
+ if (!psClassifierRules->bUsed) {
bFreeEntryFound = TRUE;
break;
}
}
}
- if(!bFreeEntryFound)
- {
- if(eClsContext == eActiveClassifierRuleContext)
- {
+ if (!bFreeEntryFound) {
+
+ if (eClsContext == eActiveClassifierRuleContext)
return ERR_CLSASSIFIER_TABLE_FULL;
- }
- else
- {
- //Lets replace the oldest rule if we are looking in old Rule table
- if(psaClassifiertable->uiOldestPhsRuleIndex >=
- MAX_PHSRULE_PER_SF)
- {
- psaClassifiertable->uiOldestPhsRuleIndex =0;
- }
+ else {
+ /* Lets replace the oldest rule if we are looking in old Rule table */
+ if (psaClassifiertable->uiOldestPhsRuleIndex >= MAX_PHSRULE_PER_SF)
+ psaClassifiertable->uiOldestPhsRuleIndex = 0;
iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex;
- psClassifierRules =
- &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
+ psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
- (psaClassifiertable->uiOldestPhsRuleIndex)++;
+ (psaClassifiertable->uiOldestPhsRuleIndex)++;
}
}
- if(eClsContext == eOldClassifierRuleContext)
- {
- if(psClassifierRules->pstPhsRule == NULL)
- {
- psClassifierRules->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule),GFP_KERNEL);
+ if (eClsContext == eOldClassifierRuleContext) {
+
+ if (psClassifierRules->pstPhsRule == NULL) {
- if(NULL == psClassifierRules->pstPhsRule)
+ psClassifierRules->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL);
+
+ if (NULL == psClassifierRules->pstPhsRule)
return ERR_PHSRULE_MEMALLOC_FAIL;
}
@@ -1238,70 +1085,62 @@ static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId,
psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule;
- /* Update The PHS rule */
- memcpy(psClassifierRules->pstPhsRule,
- psPhsRule, sizeof(struct bcm_phs_rule));
- }
- else
- {
- nStatus = UpdateClassifierPHSRule(uiClsId,psClassifierRules,
- psaClassifiertable,psPhsRule,u8AssociatedPHSI);
- }
+ /* Update The PHS rule */
+ memcpy(psClassifierRules->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule));
+ } else
+ nStatus = UpdateClassifierPHSRule(uiClsId, psClassifierRules,
+ psaClassifiertable, psPhsRule, u8AssociatedPHSI);
+
return nStatus;
}
-
static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId,
- IN struct bcm_phs_classifier_entry *pstClassifierEntry,
- struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule,
- B_UINT8 u8AssociatedPHSI)
+ IN struct bcm_phs_classifier_entry *pstClassifierEntry,
+ struct bcm_phs_classifier_table *psaClassifiertable,
+ struct bcm_phs_rule *psPhsRule,
+ B_UINT8 u8AssociatedPHSI)
{
struct bcm_phs_rule *pstAddPhsRule = NULL;
- UINT nPhsRuleIndex = 0;
- BOOLEAN bPHSRuleOrphaned = FALSE;
+ UINT nPhsRuleIndex = 0;
+ BOOLEAN bPHSRuleOrphaned = FALSE;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- psPhsRule->u8RefCnt =0;
-
- /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry*/
- bPHSRuleOrphaned = DerefPhsRule( uiClsId, psaClassifiertable,
- pstClassifierEntry->pstPhsRule);
-
- //Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF
- nPhsRuleIndex =GetPhsRuleEntry(psaClassifiertable,u8AssociatedPHSI,
- eActiveClassifierRuleContext, &pstAddPhsRule);
- if(PHS_INVALID_TABLE_INDEX == nPhsRuleIndex)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier");
-
- if(psPhsRule->u8PHSI == 0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n");
+
+ psPhsRule->u8RefCnt = 0;
+
+ /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry */
+ bPHSRuleOrphaned = DerefPhsRule(uiClsId, psaClassifiertable,
+ pstClassifierEntry->pstPhsRule);
+
+ /* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF */
+ nPhsRuleIndex = GetPhsRuleEntry(psaClassifiertable, u8AssociatedPHSI,
+ eActiveClassifierRuleContext, &pstAddPhsRule);
+ if (PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier");
+
+ if (psPhsRule->u8PHSI == 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n");
return ERR_PHS_INVALID_PHS_RULE;
}
- //Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId
- if(FALSE == bPHSRuleOrphaned)
- {
+
+ /* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId */
+ if (FALSE == bPHSRuleOrphaned) {
+
pstClassifierEntry->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL);
- if(NULL == pstClassifierEntry->pstPhsRule)
- {
+ if (NULL == pstClassifierEntry->pstPhsRule)
return ERR_PHSRULE_MEMALLOC_FAIL;
- }
}
memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule));
-
- }
- else
- {
- //Step 2.b PHS Rule Exists Tie uiClsId with the existing PHS Rule
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule");
- if(bPHSRuleOrphaned)
- {
+ } else {
+ /* Step 2.b PHS Rule Exists Tie uiClsId with the existing PHS Rule */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule");
+ if (bPHSRuleOrphaned) {
kfree(pstClassifierEntry->pstPhsRule);
pstClassifierEntry->pstPhsRule = NULL;
}
pstClassifierEntry->pstPhsRule = pstAddPhsRule;
-
}
+
pstClassifierEntry->bUsed = TRUE;
pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
pstClassifierEntry->uiClassifierRuleId = uiClsId;
@@ -1309,79 +1148,74 @@ static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId,
pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
return PHS_SUCCESS;
-
}
static BOOLEAN DerefPhsRule(IN B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule)
{
- if(pstPhsRule==NULL)
+ if (pstPhsRule == NULL)
return FALSE;
- if(pstPhsRule->u8RefCnt)
+
+ if (pstPhsRule->u8RefCnt)
pstPhsRule->u8RefCnt--;
- if(0==pstPhsRule->u8RefCnt)
- {
- /*if(pstPhsRule->u8PHSI)
- //Store the currently active rule into the old rules list
- CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);*/
+
+ if (0 == pstPhsRule->u8RefCnt) {
+ /*
+ * if(pstPhsRule->u8PHSI)
+ * Store the currently active rule into the old rules list
+ * CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);
+ */
return TRUE;
- }
- else
- {
+ } else
return FALSE;
- }
}
void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
{
- int i,j,k,l;
+ int i, j, k, l;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules : \n");
- for(i=0;i<MAX_SERVICEFLOWS;i++)
- {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules :\n");
+
+ for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+
struct bcm_phs_entry stServFlowEntry =
- pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
- if(stServFlowEntry.bUsed)
- {
- for(j=0;j<MAX_PHSRULE_PER_SF;j++)
- {
- for(l=0;l<2;l++)
- {
+ pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
+ if (stServFlowEntry.bUsed) {
+
+ for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
+
+ for (l = 0; l < 2; l++) {
struct bcm_phs_classifier_entry stClsEntry;
- if(l==0)
- {
+
+ if (l == 0) {
stClsEntry = stServFlowEntry.pstClassifierTable->stActivePhsRulesList[j];
- if(stClsEntry.bUsed)
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule : \n");
- }
- else
- {
+ if (stClsEntry.bUsed)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule :\n");
+ } else {
stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j];
- if(stClsEntry.bUsed)
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule : \n");
+ if (stClsEntry.bUsed)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule :\n");
}
- if(stClsEntry.bUsed)
- {
-
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID : %#X",stServFlowEntry.uiVcid);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID : %#X",stClsEntry.uiClassifierRuleId);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID : %#X",stClsEntry.u8PHSI);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI : %#X",stClsEntry.pstPhsRule->u8PHSI);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ",stClsEntry.pstPhsRule->u8PHSFLength);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
- for(k=0;k<stClsEntry.pstPhsRule->u8PHSFLength;k++)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ",stClsEntry.pstPhsRule->u8PHSF[k]);
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X",stClsEntry.pstPhsRule->u8PHSMLength);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
- for(k=0;k<stClsEntry.pstPhsRule->u8PHSMLength;k++)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ",stClsEntry.pstPhsRule->u8PHSM[k]);
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ",stClsEntry.pstPhsRule->u8PHSS);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV : %#X",stClsEntry.pstPhsRule->u8PHSV);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
+
+ if (stClsEntry.bUsed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID : %#X", stServFlowEntry.uiVcid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID : %#X", stClsEntry.uiClassifierRuleId);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID : %#X", stClsEntry.u8PHSI);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI : %#X", stClsEntry.pstPhsRule->u8PHSI);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ", stClsEntry.pstPhsRule->u8PHSFLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
+
+ for (k = 0 ; k < stClsEntry.pstPhsRule->u8PHSFLength; k++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", stClsEntry.pstPhsRule->u8PHSF[k]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X", stClsEntry.pstPhsRule->u8PHSMLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
+
+ for (k = 0; k < stClsEntry.pstPhsRule->u8PHSMLength; k++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", stClsEntry.pstPhsRule->u8PHSM[k]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ", stClsEntry.pstPhsRule->u8PHSS);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV : %#X", stClsEntry.pstPhsRule->u8PHSV);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
}
}
}
@@ -1389,66 +1223,69 @@ void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
}
}
-
-//-----------------------------------------------------------------------------
-// Procedure: phs_decompress
-//
-// Description: This routine restores the static fields within the packet.
-//
-// Arguments:
-// in_buf - ptr to incoming packet buffer.
-// out_buf - ptr to output buffer where the suppressed header is copied.
-// decomp_phs_rules - ptr to PHS rule.
-// header_size - ptr to field which holds the phss or phsf_length.
-//
-// Returns:
-// size -The number of bytes of dynamic fields present with in the incoming packet
-// header.
-// 0 -If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
-//-----------------------------------------------------------------------------
-
-int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
- struct bcm_phs_rule *decomp_phs_rules, UINT *header_size)
+/*
+ * Procedure: phs_decompress
+ *
+ * Description: This routine restores the static fields within the packet.
+ *
+ * Arguments:
+ * in_buf - ptr to incoming packet buffer.
+ * out_buf - ptr to output buffer where the suppressed header is copied.
+ * decomp_phs_rules - ptr to PHS rule.
+ * header_size - ptr to field which holds the phss or phsf_length.
+ *
+ * Returns:
+ * size -The number of bytes of dynamic fields present with in the incoming packet
+ * header.
+ * 0 -If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
+ */
+int phs_decompress(unsigned char *in_buf,
+ unsigned char *out_buf,
+ struct bcm_phs_rule *decomp_phs_rules,
+ UINT *header_size)
{
- int phss,size=0;
+ int phss, size = 0;
struct bcm_phs_rule *tmp_memb;
- int bit,i=0;
- unsigned char *phsf,*phsm;
- int in_buf_len = *header_size-1;
+ int bit, i = 0;
+ unsigned char *phsf, *phsm;
+ int in_buf_len = *header_size - 1;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
in_buf++;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"====>\n");
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "====>\n");
*header_size = 0;
- if((decomp_phs_rules == NULL ))
+ if ((decomp_phs_rules == NULL))
return 0;
-
tmp_memb = decomp_phs_rules;
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
- //*header_size = tmp_memb->u8PHSFLength;
- phss = tmp_memb->u8PHSS;
- phsf = tmp_memb->u8PHSF;
- phsm = tmp_memb->u8PHSM;
-
- if(phss > MAX_PHS_LENGTHS)
+ /*
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
+ * header_size = tmp_memb->u8PHSFLength;
+ */
+ phss = tmp_memb->u8PHSS;
+ phsf = tmp_memb->u8PHSF;
+ phsm = tmp_memb->u8PHSM;
+
+ if (phss > MAX_PHS_LENGTHS)
phss = MAX_PHS_LENGTHS;
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
- while((phss > 0) && (size < in_buf_len))
- {
- bit = ((*phsm << i)& SUPPRESS);
- if(bit == SUPPRESS)
- {
+ /*
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:
+ * In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
+ */
+ while ((phss > 0) && (size < in_buf_len)) {
+ bit = ((*phsm << i) & SUPPRESS);
+
+ if (bit == SUPPRESS) {
*out_buf = *phsf;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d phsf %d ouput %d",
- phss,*phsf,*out_buf);
- }
- else
- {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nDECOMP:In phss %d phsf %d ouput %d",
+ phss, *phsf, *out_buf);
+ } else {
*out_buf = *in_buf;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss %d input %d ouput %d",
- phss,*in_buf,*out_buf);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nDECOMP:In phss %d input %d ouput %d",
+ phss, *in_buf, *out_buf);
in_buf++;
size++;
}
@@ -1456,156 +1293,159 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
phsf++;
phss--;
i++;
- *header_size=*header_size + 1;
+ *header_size = *header_size + 1;
- if(i > MAX_NO_BIT)
- {
- i=0;
+ if (i > MAX_NO_BIT) {
+ i = 0;
phsm++;
}
}
+
return size;
}
-
-
-
-//-----------------------------------------------------------------------------
-// Procedure: phs_compress
-//
-// Description: This routine suppresses the static fields within the packet.Before
-// that it will verify the fields to be suppressed with the corresponding fields in the
-// phsf. For verification it checks the phsv field of PHS rule. If set and verification
-// succeeds it suppresses the field.If any one static field is found different none of
-// the static fields are suppressed then the packet is sent as uncompressed packet with
-// phsi=0.
-//
-// Arguments:
-// phs_rule - ptr to PHS rule.
-// in_buf - ptr to incoming packet buffer.
-// out_buf - ptr to output buffer where the suppressed header is copied.
-// header_size - ptr to field which holds the phss.
-//
-// Returns:
-// size-The number of bytes copied into the output buffer i.e dynamic fields
-// 0 -If PHS rule is NULL.If PHSV field is not set.If the verification fails.
-//-----------------------------------------------------------------------------
-static int phs_compress(struct bcm_phs_rule *phs_rule, unsigned char *in_buf
- ,unsigned char *out_buf,UINT *header_size,UINT *new_header_size)
+/*
+ * Procedure: phs_compress
+ *
+ * Description: This routine suppresses the static fields within the packet.Before
+ * that it will verify the fields to be suppressed with the corresponding fields in the
+ * phsf. For verification it checks the phsv field of PHS rule. If set and verification
+ * succeeds it suppresses the field.If any one static field is found different none of
+ * the static fields are suppressed then the packet is sent as uncompressed packet with
+ * phsi=0.
+ *
+ * Arguments:
+ * phs_rule - ptr to PHS rule.
+ * in_buf - ptr to incoming packet buffer.
+ * out_buf - ptr to output buffer where the suppressed header is copied.
+ * header_size - ptr to field which holds the phss.
+ *
+ * Returns:
+ * size-The number of bytes copied into the output buffer i.e dynamic fields
+ * 0 -If PHS rule is NULL.If PHSV field is not set.If the verification fails.
+ */
+static int phs_compress(struct bcm_phs_rule *phs_rule,
+ unsigned char *in_buf,
+ unsigned char *out_buf,
+ UINT *header_size,
+ UINT *new_header_size)
{
unsigned char *old_addr = out_buf;
int suppress = 0;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- if(phs_rule == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nphs_compress(): phs_rule null!");
+
+ if (phs_rule == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nphs_compress(): phs_rule null!");
*out_buf = ZERO_PHSI;
return STATUS_PHS_NOCOMPRESSION;
}
-
- if(phs_rule->u8PHSS <= *new_header_size)
- {
+ if (phs_rule->u8PHSS <= *new_header_size)
*header_size = phs_rule->u8PHSS;
- }
else
- {
*header_size = *new_header_size;
- }
- //To copy PHSI
+
+ /* To copy PHSI */
out_buf++;
- suppress = verify_suppress_phsf(in_buf,out_buf,phs_rule->u8PHSF,
- phs_rule->u8PHSM, phs_rule->u8PHSS, phs_rule->u8PHSV,new_header_size);
+ suppress = verify_suppress_phsf(in_buf, out_buf, phs_rule->u8PHSF,
+ phs_rule->u8PHSM, phs_rule->u8PHSS,
+ phs_rule->u8PHSV, new_header_size);
- if(suppress == STATUS_PHS_COMPRESSED)
- {
+ if (suppress == STATUS_PHS_COMPRESSED) {
*old_addr = (unsigned char)phs_rule->u8PHSI;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress phsi %d",phs_rule->u8PHSI);
- }
- else
- {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress phsi %d", phs_rule->u8PHSI);
+ } else {
*old_addr = ZERO_PHSI;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress PHSV Verification failed");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress PHSV Verification failed");
}
+
return suppress;
}
-
-//-----------------------------------------------------------------------------
-// Procedure: verify_suppress_phsf
-//
-// Description: This routine verifies the fields of the packet and if all the
-// static fields are equal it adds the phsi of that PHS rule.If any static
-// field differs it woun't suppress any field.
-//
-// Arguments:
-// rules_set - ptr to classifier_rules.
-// in_buffer - ptr to incoming packet buffer.
-// out_buffer - ptr to output buffer where the suppressed header is copied.
-// phsf - ptr to phsf.
-// phsm - ptr to phsm.
-// phss - variable holding phss.
-//
-// Returns:
-// size-The number of bytes copied into the output buffer i.e dynamic fields.
-// 0 -Packet has failed the verification.
-//-----------------------------------------------------------------------------
-
-static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
- unsigned char *phsf,unsigned char *phsm,unsigned int phss,
- unsigned int phsv,UINT* new_header_size)
+/*
+ * Procedure: verify_suppress_phsf
+ *
+ * Description: This routine verifies the fields of the packet and if all the
+ * static fields are equal it adds the phsi of that PHS rule.If any static
+ * field differs it woun't suppress any field.
+ *
+ * Arguments:
+ * rules_set - ptr to classifier_rules.
+ * in_buffer - ptr to incoming packet buffer.
+ * out_buffer - ptr to output buffer where the suppressed header is copied.
+ * phsf - ptr to phsf.
+ * phsm - ptr to phsm.
+ * phss - variable holding phss.
+ *
+ * Returns:
+ * size-The number of bytes copied into the output buffer i.e dynamic fields.
+ * 0 -Packet has failed the verification.
+ */
+static int verify_suppress_phsf(unsigned char *in_buffer,
+ unsigned char *out_buffer,
+ unsigned char *phsf,
+ unsigned char *phsm,
+ unsigned int phss,
+ unsigned int phsv,
+ UINT *new_header_size)
{
- unsigned int size=0;
- int bit,i=0;
+ unsigned int size = 0;
+ int bit, i = 0;
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf PHSM - 0x%X",*phsm);
-
- if(phss>(*new_header_size))
- {
- phss=*new_header_size;
- }
- while(phss > 0)
- {
- bit = ((*phsm << i)& SUPPRESS);
- if(bit == SUPPRESS)
- {
-
- if(*in_buffer != *phsf)
- {
- if(phsv == VERIFY)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf failed for field %d buf %d phsf %d",phss,*in_buffer,*phsf);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf PHSM - 0x%X", *phsm);
+
+ if (phss > (*new_header_size))
+ phss = *new_header_size;
+
+ while (phss > 0) {
+ bit = ((*phsm << i) & SUPPRESS);
+ if (bit == SUPPRESS) {
+ if (*in_buffer != *phsf) {
+ if (phsv == VERIFY) {
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ PHS_SEND,
+ DBG_LVL_ALL,
+ "\nCOMP:In verify_phsf failed for field %d buf %d phsf %d",
+ phss,
+ *in_buffer,
+ *phsf);
return STATUS_PHS_NOCOMPRESSION;
}
- }
- else
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success for field %d buf %d phsf %d",phss,*in_buffer,*phsf);
- }
- else
- {
+ } else
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ PHS_SEND,
+ DBG_LVL_ALL,
+ "\nCOMP:In verify_phsf success for field %d buf %d phsf %d",
+ phss,
+ *in_buffer,
+ *phsf);
+ } else {
*out_buffer = *in_buffer;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In copying_header input %d out %d",*in_buffer,*out_buffer);
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ PHS_SEND,
+ DBG_LVL_ALL,
+ "\nCOMP:In copying_header input %d out %d",
+ *in_buffer,
+ *out_buffer);
out_buffer++;
size++;
}
+
in_buffer++;
phsf++;
phss--;
i++;
- if(i > MAX_NO_BIT)
- {
- i=0;
+
+ if (i > MAX_NO_BIT) {
+ i = 0;
phsm++;
}
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf success");
*new_header_size = size;
return STATUS_PHS_COMPRESSED;
}
-
-
-
-
-
-
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
index e6152f4df14..bea1330f7ea 100644
--- a/drivers/staging/bcm/nvm.c
+++ b/drivers/staging/bcm/nvm.c
@@ -2228,20 +2228,20 @@ int BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter)
BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL");
return -EINVAL;
}
- psAdapter->psFlashCSInfo = (struct bcm_flash_cs_info *)kzalloc(sizeof(struct bcm_flash_cs_info), GFP_KERNEL);
+ psAdapter->psFlashCSInfo = kzalloc(sizeof(struct bcm_flash_cs_info), GFP_KERNEL);
if (psAdapter->psFlashCSInfo == NULL) {
BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 1.x");
return -ENOMEM;
}
- psAdapter->psFlash2xCSInfo = (struct bcm_flash2x_cs_info *)kzalloc(sizeof(struct bcm_flash2x_cs_info), GFP_KERNEL);
+ psAdapter->psFlash2xCSInfo = kzalloc(sizeof(struct bcm_flash2x_cs_info), GFP_KERNEL);
if (!psAdapter->psFlash2xCSInfo) {
BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 2.x");
kfree(psAdapter->psFlashCSInfo);
return -ENOMEM;
}
- psAdapter->psFlash2xVendorInfo = (struct bcm_flash2x_vendor_info *)kzalloc(sizeof(struct bcm_flash2x_vendor_info), GFP_KERNEL);
+ psAdapter->psFlash2xVendorInfo = kzalloc(sizeof(struct bcm_flash2x_vendor_info), GFP_KERNEL);
if (!psAdapter->psFlash2xVendorInfo) {
BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate Vendor Info Memory for Flash 2.x");
kfree(psAdapter->psFlashCSInfo);
@@ -4074,7 +4074,7 @@ int BcmCopySection(struct bcm_mini_adapter *Adapter,
else
BuffSize = numOfBytes;
- pBuff = (PCHAR)kzalloc(BuffSize, GFP_KERNEL);
+ pBuff = kzalloc(BuffSize, GFP_KERNEL);
if (!pBuff) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed.. ");
return -ENOMEM;
@@ -4154,7 +4154,7 @@ int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned
}
/* If Header is present overwrite passed buffer with this */
if (bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) {
- pTempBuff = (PUCHAR)kzalloc(HeaderSizeToProtect, GFP_KERNEL);
+ pTempBuff = kzalloc(HeaderSizeToProtect, GFP_KERNEL);
if (!pTempBuff) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed");
return -ENOMEM;
@@ -4563,7 +4563,7 @@ static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_sect
}
}
- pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL);
+ pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL);
if (!pBuff) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
return -ENOMEM;
@@ -4622,7 +4622,7 @@ static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_sect
return SECTOR_IS_NOT_WRITABLE;
}
- pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL);
+ pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL);
if (!pBuff) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
return -ENOMEM;
diff --git a/drivers/staging/ccg/Kconfig b/drivers/staging/ccg/Kconfig
deleted file mode 100644
index 7ed5bc6caad..00000000000
--- a/drivers/staging/ccg/Kconfig
+++ /dev/null
@@ -1,25 +0,0 @@
-if USB_GADGET
-
-config USB_G_CCG
- tristate "Configurable Composite Gadget (STAGING)"
- depends on STAGING && BLOCK && NET && !USB_ZERO && !USB_ZERO_HNPTEST && !USB_AUDIO && !GADGET_UAC1 && !USB_ETH && !USB_ETH_RNDIS && !USB_ETH_EEM && !USB_G_NCM && !USB_GADGETFS && !USB_FUNCTIONFS && !USB_FUNCTIONFS_ETH && !USB_FUNCTIONFS_RNDIS && !USB_FUNCTIONFS_GENERIC && !USB_FILE_STORAGE && !USB_FILE_STORAGE_TEST && !USB_MASS_STORAGE && !USB_G_SERIAL && !USB_MIDI_GADGET && !USB_G_PRINTER && !USB_CDC_COMPOSITE && !USB_G_NOKIA && !USB_G_ACM_MS && !USB_G_MULTI && !USB_G_MULTI_RNDIS && !USB_G_MULTI_CDC && !USB_G_HID && !USB_G_DBGP && !USB_G_WEBCAM && TTY
- help
- The Configurable Composite Gadget supports multiple USB
- functions: acm, mass storage, rndis and FunctionFS.
- Each function can be configured and enabled/disabled
- dynamically from userspace through a sysfs interface.
-
- In order to compile this (either as a module or built-in),
- "USB Gadget Drivers" and anything under it must not be
- selected compiled-in in
- Device Drivers->USB Support->USB Gadget Support.
- However, you can say "M" there, if you do, the
- Configurable Composite Gadget can be compiled "M" only
- or not at all.
-
- BIG FAT NOTE: DON'T RELY ON THIS USERINTERFACE HERE! AS PART
- OF THE REWORK DONE HERE WILL BE A NEW USER INTERFACE WITHOUT ANY
- COMPATIBILITY TO THIS SYSFS INTERFACE HERE. BE AWARE OF THIS
- BEFORE SELECTING THIS.
-
-endif # USB_GADGET
diff --git a/drivers/staging/ccg/Makefile b/drivers/staging/ccg/Makefile
deleted file mode 100644
index 814fa9de5f5..00000000000
--- a/drivers/staging/ccg/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-g_ccg-y := ccg.o
-obj-$(CONFIG_USB_G_CCG) += g_ccg.o
diff --git a/drivers/staging/ccg/TODO b/drivers/staging/ccg/TODO
deleted file mode 100644
index 18612fe7017..00000000000
--- a/drivers/staging/ccg/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-TODO:
- - change configuration interface from sysfs to configfs
-
-Please send patches to Greg Kroah-Hartmann <gregkh@linuxfoundation.org>,
-Andrzej Pietrasiewicz <andrzej.p@samsung.com>, and
-Cc: Mike Lockwood <lockwood@android.com>
diff --git a/drivers/staging/ccg/ccg.c b/drivers/staging/ccg/ccg.c
deleted file mode 100644
index ffc5f73a5b5..00000000000
--- a/drivers/staging/ccg/ccg.c
+++ /dev/null
@@ -1,1292 +0,0 @@
-/*
- * Configurable Composite Gadget
- *
- * Initially contributed as "Android Composite Gdaget" by:
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- * Benoit Goby <benoit@android.com>
- *
- * Tailoring it to become a generic Configurable Composite Gadget is
- *
- * Copyright (C) 2012 Samsung Electronics
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/utsname.h>
-#include <linux/platform_device.h>
-
-#include <linux/usb/ch9.h>
-#include "composite.h"
-#include <linux/usb/gadget.h>
-
-#include "gadget_chips.h"
-
-/*
- * Kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module. So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-#include "usbstring.c"
-#include "config.c"
-#include "epautoconf.c"
-#include "composite.c"
-
-#include "f_mass_storage.c"
-#include "u_serial.c"
-#include "f_acm.c"
-#define USB_ETH_RNDIS y
-#include "f_rndis.c"
-#include "rndis.c"
-#include "u_ether.c"
-#include "f_fs.c"
-
-MODULE_AUTHOR("Mike Lockwood, Andrzej Pietrasiewicz");
-MODULE_DESCRIPTION("Configurable Composite USB Gadget");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
-
-static const char longname[] = "Configurable Composite Gadget";
-
-/* Default vendor and product IDs, overridden by userspace */
-#define VENDOR_ID 0x1d6b /* Linux Foundation */
-#define PRODUCT_ID 0x0107
-#define GFS_MAX_DEVS 10
-
-struct ccg_usb_function {
- char *name;
- void *config;
-
- struct device *dev;
- char *dev_name;
- struct device_attribute **attributes;
-
- /* for ccg_dev.enabled_functions */
- struct list_head enabled_list;
-
- /* Optional: initialization during gadget bind */
- int (*init)(struct ccg_usb_function *, struct usb_composite_dev *);
- /* Optional: cleanup during gadget unbind */
- void (*cleanup)(struct ccg_usb_function *);
-
- int (*bind_config)(struct ccg_usb_function *,
- struct usb_configuration *);
-
- /* Optional: called when the configuration is removed */
- void (*unbind_config)(struct ccg_usb_function *,
- struct usb_configuration *);
- /* Optional: handle ctrl requests before the device is configured */
- int (*ctrlrequest)(struct ccg_usb_function *,
- struct usb_composite_dev *,
- const struct usb_ctrlrequest *);
-};
-
-struct ffs_obj {
- const char *name;
- bool mounted;
- bool desc_ready;
- bool used;
- struct ffs_data *ffs_data;
-};
-
-struct ccg_dev {
- struct ccg_usb_function **functions;
- struct list_head enabled_functions;
- struct usb_composite_dev *cdev;
- struct device *dev;
-
- bool enabled;
- struct mutex mutex;
- bool connected;
- bool sw_connected;
- struct work_struct work;
-
- unsigned int max_func_num;
- unsigned int func_num;
- struct ffs_obj ffs_tab[GFS_MAX_DEVS];
-};
-
-static struct class *ccg_class;
-static struct ccg_dev *_ccg_dev;
-static int ccg_bind_config(struct usb_configuration *c);
-static void ccg_unbind_config(struct usb_configuration *c);
-
-static char func_names_buf[256];
-
-static struct usb_device_descriptor device_desc = {
- .bLength = sizeof(device_desc),
- .bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_PER_INTERFACE,
- .idVendor = __constant_cpu_to_le16(VENDOR_ID),
- .idProduct = __constant_cpu_to_le16(PRODUCT_ID),
- .bcdDevice = __constant_cpu_to_le16(0xffff),
- .bNumConfigurations = 1,
-};
-
-static struct usb_configuration ccg_config_driver = {
- .label = "ccg",
- .unbind = ccg_unbind_config,
- .bConfigurationValue = 1,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 0xFA, /* 500ma */
-};
-
-static void ccg_work(struct work_struct *data)
-{
- struct ccg_dev *dev = container_of(data, struct ccg_dev, work);
- struct usb_composite_dev *cdev = dev->cdev;
- static char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
- static char *connected[2] = { "USB_STATE=CONNECTED", NULL };
- static char *configured[2] = { "USB_STATE=CONFIGURED", NULL };
- char **uevent_envp = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&cdev->lock, flags);
- if (cdev->config)
- uevent_envp = configured;
- else if (dev->connected != dev->sw_connected)
- uevent_envp = dev->connected ? connected : disconnected;
- dev->sw_connected = dev->connected;
- spin_unlock_irqrestore(&cdev->lock, flags);
-
- if (uevent_envp) {
- kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);
- pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]);
- } else {
- pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
- dev->connected, dev->sw_connected, cdev->config);
- }
-}
-
-
-/*-------------------------------------------------------------------------*/
-/* Supported functions initialization */
-
-static struct ffs_obj *functionfs_find_dev(struct ccg_dev *dev,
- const char *dev_name)
-{
- int i;
-
- for (i = 0; i < dev->max_func_num; i++)
- if (strcmp(dev->ffs_tab[i].name, dev_name) == 0)
- return &dev->ffs_tab[i];
-
- return NULL;
-}
-
-static bool functionfs_all_ready(struct ccg_dev *dev)
-{
- int i;
-
- for (i = 0; i < dev->max_func_num; i++)
- if (dev->ffs_tab[i].used && !dev->ffs_tab[i].desc_ready)
- return false;
-
- return true;
-}
-
-static int functionfs_ready_callback(struct ffs_data *ffs)
-{
- struct ffs_obj *ffs_obj;
- int ret;
-
- mutex_lock(&_ccg_dev->mutex);
-
- ffs_obj = ffs->private_data;
- if (!ffs_obj) {
- ret = -EINVAL;
- goto done;
- }
- if (WARN_ON(ffs_obj->desc_ready)) {
- ret = -EBUSY;
- goto done;
- }
- ffs_obj->ffs_data = ffs;
-
- if (functionfs_all_ready(_ccg_dev)) {
- ret = -EBUSY;
- goto done;
- }
- ffs_obj->desc_ready = true;
-
-done:
- mutex_unlock(&_ccg_dev->mutex);
- return ret;
-}
-
-static void reset_usb(struct ccg_dev *dev)
-{
- /* Cancel pending control requests */
- usb_ep_dequeue(dev->cdev->gadget->ep0, dev->cdev->req);
- usb_remove_config(dev->cdev, &ccg_config_driver);
- dev->enabled = false;
- usb_gadget_disconnect(dev->cdev->gadget);
-}
-
-static void functionfs_closed_callback(struct ffs_data *ffs)
-{
- struct ffs_obj *ffs_obj;
-
- mutex_lock(&_ccg_dev->mutex);
-
- ffs_obj = ffs->private_data;
- if (!ffs_obj)
- goto done;
-
- ffs_obj->desc_ready = false;
-
- if (_ccg_dev->enabled)
- reset_usb(_ccg_dev);
-
-done:
- mutex_unlock(&_ccg_dev->mutex);
-}
-
-static void *functionfs_acquire_dev_callback(const char *dev_name)
-{
- struct ffs_obj *ffs_dev;
-
- mutex_lock(&_ccg_dev->mutex);
-
- ffs_dev = functionfs_find_dev(_ccg_dev, dev_name);
- if (!ffs_dev) {
- ffs_dev = ERR_PTR(-ENODEV);
- goto done;
- }
-
- if (ffs_dev->mounted) {
- ffs_dev = ERR_PTR(-EBUSY);
- goto done;
- }
- ffs_dev->mounted = true;
-
-done:
- mutex_unlock(&_ccg_dev->mutex);
- return ffs_dev;
-}
-
-static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
-{
- struct ffs_obj *ffs_dev;
-
- mutex_lock(&_ccg_dev->mutex);
-
- ffs_dev = ffs_data->private_data;
- if (ffs_dev)
- ffs_dev->mounted = false;
-
- mutex_unlock(&_ccg_dev->mutex);
-}
-
-static int functionfs_function_init(struct ccg_usb_function *f,
- struct usb_composite_dev *cdev)
-{
- return functionfs_init();
-}
-
-static void functionfs_function_cleanup(struct ccg_usb_function *f)
-{
- functionfs_cleanup();
-}
-
-static int functionfs_function_bind_config(struct ccg_usb_function *f,
- struct usb_configuration *c)
-{
- struct ccg_dev *dev = _ccg_dev;
- int i, ret;
-
- for (i = dev->max_func_num; i--; ) {
- if (!dev->ffs_tab[i].used)
- continue;
- ret = functionfs_bind(dev->ffs_tab[i].ffs_data, c->cdev);
- if (unlikely(ret < 0)) {
- while (++i < dev->max_func_num)
- functionfs_unbind(dev->ffs_tab[i].ffs_data);
- return ret;
- }
- }
-
- for (i = dev->max_func_num; i--; ) {
- if (!dev->ffs_tab[i].used)
- continue;
- ret = functionfs_bind_config(c->cdev, c,
- dev->ffs_tab[i].ffs_data);
- if (unlikely(ret < 0))
- return ret;
- }
-
- return 0;
-}
-
-static void functionfs_function_unbind_config(struct ccg_usb_function *f,
- struct usb_configuration *c)
-{
- struct ccg_dev *dev = _ccg_dev;
- int i;
-
- for (i = dev->max_func_num; i--; )
- if (dev->ffs_tab[i].ffs_data)
- functionfs_unbind(dev->ffs_tab[i].ffs_data);
-}
-
-static ssize_t functionfs_user_functions_show(struct device *_dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ccg_dev *dev = _ccg_dev;
- char *buff = buf;
- int i;
-
- mutex_lock(&dev->mutex);
-
- for (i = 0; i < dev->max_func_num; i++)
- buff += snprintf(buff, PAGE_SIZE + buf - buff, "%s,",
- dev->ffs_tab[i].name);
-
- mutex_unlock(&dev->mutex);
-
- if (buff != buf)
- *(buff - 1) = '\n';
- return buff - buf;
-}
-
-static ssize_t functionfs_user_functions_store(struct device *_dev,
- struct device_attribute *attr,
- const char *buff, size_t size)
-{
- struct ccg_dev *dev = _ccg_dev;
- char *name, *b;
- ssize_t ret = size;
- int i;
-
- buff = skip_spaces(buff);
- if (!*buff)
- return -EINVAL;
-
- mutex_lock(&dev->mutex);
-
- if (dev->enabled) {
- ret = -EBUSY;
- goto end;
- }
-
- for (i = 0; i < dev->max_func_num; i++)
- if (dev->ffs_tab[i].mounted) {
- ret = -EBUSY;
- goto end;
- }
-
- strlcpy(func_names_buf, buff, sizeof(func_names_buf));
- b = strim(func_names_buf);
-
- /* replace the list of functions */
- dev->max_func_num = 0;
- while (b) {
- name = strsep(&b, ",");
- if (dev->max_func_num == GFS_MAX_DEVS) {
- ret = -ENOSPC;
- goto end;
- }
- if (functionfs_find_dev(dev, name)) {
- ret = -EEXIST;
- continue;
- }
- dev->ffs_tab[dev->max_func_num++].name = name;
- }
-
-end:
- mutex_unlock(&dev->mutex);
- return ret;
-}
-
-static DEVICE_ATTR(user_functions, S_IRUGO | S_IWUSR,
- functionfs_user_functions_show,
- functionfs_user_functions_store);
-
-static ssize_t functionfs_max_user_functions_show(struct device *_dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%d", GFS_MAX_DEVS);
-}
-
-static DEVICE_ATTR(max_user_functions, S_IRUGO,
- functionfs_max_user_functions_show, NULL);
-
-static struct device_attribute *functionfs_function_attributes[] = {
- &dev_attr_user_functions,
- &dev_attr_max_user_functions,
- NULL
-};
-
-static struct ccg_usb_function functionfs_function = {
- .name = "fs",
- .init = functionfs_function_init,
- .cleanup = functionfs_function_cleanup,
- .bind_config = functionfs_function_bind_config,
- .unbind_config = functionfs_function_unbind_config,
- .attributes = functionfs_function_attributes,
-};
-
-#define MAX_ACM_INSTANCES 4
-struct acm_function_config {
- int instances;
-};
-
-static int
-acm_function_init(struct ccg_usb_function *f, struct usb_composite_dev *cdev)
-{
- f->config = kzalloc(sizeof(struct acm_function_config), GFP_KERNEL);
- if (!f->config)
- return -ENOMEM;
-
- return gserial_setup(cdev->gadget, MAX_ACM_INSTANCES);
-}
-
-static void acm_function_cleanup(struct ccg_usb_function *f)
-{
- gserial_cleanup();
- kfree(f->config);
- f->config = NULL;
-}
-
-static int
-acm_function_bind_config(struct ccg_usb_function *f,
- struct usb_configuration *c)
-{
- int i;
- int ret = 0;
- struct acm_function_config *config = f->config;
-
- for (i = 0; i < config->instances; i++) {
- ret = acm_bind_config(c, i);
- if (ret) {
- pr_err("Could not bind acm%u config\n", i);
- break;
- }
- }
-
- return ret;
-}
-
-static ssize_t acm_instances_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct acm_function_config *config = f->config;
- return sprintf(buf, "%d\n", config->instances);
-}
-
-static ssize_t acm_instances_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct acm_function_config *config = f->config;
- int value;
- int ret = 0;
-
- ret = kstrtoint(buf, 10, &value);
- if (ret)
- return ret;
-
- if (value > MAX_ACM_INSTANCES)
- return -EINVAL;
-
- config->instances = value;
-
- return size;
-}
-
-static DEVICE_ATTR(instances, S_IRUGO | S_IWUSR, acm_instances_show,
- acm_instances_store);
-static struct device_attribute *acm_function_attributes[] = {
- &dev_attr_instances,
- NULL
-};
-
-static struct ccg_usb_function acm_function = {
- .name = "acm",
- .init = acm_function_init,
- .cleanup = acm_function_cleanup,
- .bind_config = acm_function_bind_config,
- .attributes = acm_function_attributes,
-};
-
-struct rndis_function_config {
- u8 ethaddr[ETH_ALEN];
- u32 vendorID;
- char manufacturer[256];
- /* "Wireless" RNDIS; auto-detected by Windows */
- bool wceis;
-};
-
-static int rndis_function_init(struct ccg_usb_function *f,
- struct usb_composite_dev *cdev)
-{
- f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
- if (!f->config)
- return -ENOMEM;
- return 0;
-}
-
-static void rndis_function_cleanup(struct ccg_usb_function *f)
-{
- kfree(f->config);
- f->config = NULL;
-}
-
-static int rndis_function_bind_config(struct ccg_usb_function *f,
- struct usb_configuration *c)
-{
- int ret;
- struct rndis_function_config *rndis = f->config;
-
- if (!rndis) {
- pr_err("%s: rndis_pdata\n", __func__);
- return -1;
- }
-
- pr_info("%s MAC: %pM\n", __func__, rndis->ethaddr);
-
- ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
- if (ret) {
- pr_err("%s: gether_setup failed\n", __func__);
- return ret;
- }
-
- if (rndis->wceis) {
- /* "Wireless" RNDIS; auto-detected by Windows */
- rndis_iad_descriptor.bFunctionClass =
- USB_CLASS_WIRELESS_CONTROLLER;
- rndis_iad_descriptor.bFunctionSubClass = 0x01;
- rndis_iad_descriptor.bFunctionProtocol = 0x03;
- rndis_control_intf.bInterfaceClass =
- USB_CLASS_WIRELESS_CONTROLLER;
- rndis_control_intf.bInterfaceSubClass = 0x01;
- rndis_control_intf.bInterfaceProtocol = 0x03;
- }
-
- return rndis_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID,
- rndis->manufacturer);
-}
-
-static void rndis_function_unbind_config(struct ccg_usb_function *f,
- struct usb_configuration *c)
-{
- gether_cleanup();
-}
-
-static ssize_t rndis_manufacturer_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- return sprintf(buf, "%s\n", config->manufacturer);
-}
-
-static ssize_t rndis_manufacturer_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
-
- if (size >= sizeof(config->manufacturer))
- return -EINVAL;
- memcpy(config->manufacturer, buf, size);
- config->manufacturer[size] = 0;
-
- return size;
-}
-
-static DEVICE_ATTR(manufacturer, S_IRUGO | S_IWUSR, rndis_manufacturer_show,
- rndis_manufacturer_store);
-
-static ssize_t rndis_wceis_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- return sprintf(buf, "%d\n", config->wceis);
-}
-
-static ssize_t rndis_wceis_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- int value;
- int ret;
-
- ret = kstrtoint(buf, 10, &value);
- if (ret)
- return ret;
-
- config->wceis = value;
-
- return size;
-}
-
-static DEVICE_ATTR(wceis, S_IRUGO | S_IWUSR, rndis_wceis_show,
- rndis_wceis_store);
-
-static ssize_t rndis_ethaddr_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *rndis = f->config;
- return sprintf(buf, "%pM\n", rndis->ethaddr);
-}
-
-static ssize_t rndis_ethaddr_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *rndis = f->config;
- unsigned char tmp[6];
-
- if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
- tmp + 0, tmp + 1, tmp + 2, tmp + 3, tmp + 4, tmp + 5) !=
- ETH_ALEN)
- return -EINVAL;
-
- memcpy(rndis->ethaddr, tmp, ETH_ALEN);
-
- return ETH_ALEN;
-
-}
-
-static DEVICE_ATTR(ethaddr, S_IRUGO | S_IWUSR, rndis_ethaddr_show,
- rndis_ethaddr_store);
-
-static ssize_t rndis_vendorID_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- return sprintf(buf, "%04x\n", config->vendorID);
-}
-
-static ssize_t rndis_vendorID_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct ccg_usb_function *f = dev_get_drvdata(dev);
- struct rndis_function_config *config = f->config;
- int value;
- int ret;
-
- ret = kstrtou32(buf, 16, &value);
- if (ret)
- return ret;
-
- config->vendorID = value;
-
- return size;
-}
-
-static DEVICE_ATTR(vendorID, S_IRUGO | S_IWUSR, rndis_vendorID_show,
- rndis_vendorID_store);
-
-static struct device_attribute *rndis_function_attributes[] = {
- &dev_attr_manufacturer,
- &dev_attr_wceis,
- &dev_attr_ethaddr,
- &dev_attr_vendorID,
- NULL
-};
-
-static struct ccg_usb_function rndis_function = {
- .name = "rndis",
- .init = rndis_function_init,
- .cleanup = rndis_function_cleanup,
- .bind_config = rndis_function_bind_config,
- .unbind_config = rndis_function_unbind_config,
- .attributes = rndis_function_attributes,
-};
-
-static int mass_storage_function_init(struct ccg_usb_function *f,
- struct usb_composite_dev *cdev)
-{
- struct fsg_config fsg;
- struct fsg_common *common;
- int err;
-
- memset(&fsg, 0, sizeof(fsg));
- fsg.nluns = 1;
- fsg.luns[0].removable = 1;
- fsg.vendor_name = iManufacturer;
- fsg.product_name = iProduct;
-
- common = fsg_common_init(NULL, cdev, &fsg);
- if (IS_ERR(common))
- return PTR_ERR(common);
-
- err = sysfs_create_link(&f->dev->kobj,
- &common->luns[0].dev.kobj,
- "lun");
- if (err) {
- fsg_common_put(common);
- return err;
- }
-
- f->config = common;
- return 0;
-}
-
-static void mass_storage_function_cleanup(struct ccg_usb_function *f)
-{
- fsg_common_put(f->config);
- f->config = NULL;
-}
-
-static int mass_storage_function_bind_config(struct ccg_usb_function *f,
- struct usb_configuration *c)
-{
- struct fsg_common *common = f->config;
- return fsg_bind_config(c->cdev, c, common);
-}
-
-static struct ccg_usb_function mass_storage_function = {
- .name = "mass_storage",
- .init = mass_storage_function_init,
- .cleanup = mass_storage_function_cleanup,
- .bind_config = mass_storage_function_bind_config,
-};
-
-static struct ccg_usb_function *supported_functions[] = {
- &functionfs_function,
- &acm_function,
- &rndis_function,
- &mass_storage_function,
- NULL
-};
-
-
-static int ccg_init_functions(struct ccg_usb_function **functions,
- struct usb_composite_dev *cdev)
-{
- struct ccg_dev *dev = _ccg_dev;
- struct ccg_usb_function *f;
- struct device_attribute **attrs;
- struct device_attribute *attr;
- int err;
- int index = 0;
-
- for (; (f = *functions++); index++) {
- f->dev_name = kasprintf(GFP_KERNEL, "f_%s", f->name);
- if (!f->dev_name) {
- pr_err("%s: Failed to alloc name %s", __func__,
- f->name);
- err = -ENOMEM;
- goto err_alloc;
- }
- f->dev = device_create(ccg_class, dev->dev,
- MKDEV(0, index), f, f->dev_name);
- if (IS_ERR(f->dev)) {
- pr_err("%s: Failed to create dev %s", __func__,
- f->dev_name);
- err = PTR_ERR(f->dev);
- f->dev = NULL;
- goto err_create;
- }
-
- if (f->init) {
- err = f->init(f, cdev);
- if (err) {
- pr_err("%s: Failed to init %s", __func__,
- f->name);
- goto err_out;
- }
- }
-
- attrs = f->attributes;
- if (attrs) {
- while ((attr = *attrs++) && !err)
- err = device_create_file(f->dev, attr);
- }
- if (err) {
- pr_err("%s: Failed to create function %s attributes",
- __func__, f->name);
- goto err_uninit;
- }
- }
- return 0;
-
-err_uninit:
- if (f->cleanup)
- f->cleanup(f);
-err_out:
- device_destroy(ccg_class, f->dev->devt);
- f->dev = NULL;
-err_create:
- kfree(f->dev_name);
-err_alloc:
- return err;
-}
-
-static void ccg_cleanup_functions(struct ccg_usb_function **functions)
-{
- struct ccg_usb_function *f;
-
- while (*functions) {
- f = *functions++;
-
- if (f->dev) {
- if (f->cleanup)
- f->cleanup(f);
- device_destroy(ccg_class, f->dev->devt);
- kfree(f->dev_name);
- }
- }
-}
-
-static int ccg_bind_enabled_functions(struct ccg_dev *dev,
- struct usb_configuration *c)
-{
- struct ccg_usb_function *f;
- int ret;
-
- list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
- ret = f->bind_config(f, c);
- if (ret) {
- pr_err("%s: %s failed", __func__, f->name);
- return ret;
- }
- }
- return 0;
-}
-
-static void ccg_unbind_enabled_functions(struct ccg_dev *dev,
- struct usb_configuration *c)
-{
- struct ccg_usb_function *f;
-
- list_for_each_entry(f, &dev->enabled_functions, enabled_list)
- if (f->unbind_config)
- f->unbind_config(f, c);
-}
-
-static int ccg_enable_function(struct ccg_dev *dev, char *name)
-{
- struct ccg_usb_function **functions = dev->functions;
- struct ccg_usb_function *f;
- while ((f = *functions++)) {
- if (!strcmp(name, f->name)) {
- list_add_tail(&f->enabled_list,
- &dev->enabled_functions);
- return 0;
- }
- }
- return -EINVAL;
-}
-
-/*-------------------------------------------------------------------------*/
-/* /sys/class/ccg_usb/ccg%d/ interface */
-
-static ssize_t
-functions_show(struct device *pdev, struct device_attribute *attr, char *buf)
-{
- struct ccg_dev *dev = dev_get_drvdata(pdev);
- struct ccg_usb_function *f;
- char *buff = buf;
- int i;
-
- mutex_lock(&dev->mutex);
-
- list_for_each_entry(f, &dev->enabled_functions, enabled_list)
- buff += sprintf(buff, "%s,", f->name);
- for (i = 0; i < dev->max_func_num; i++)
- if (dev->ffs_tab[i].used)
- buff += sprintf(buff, "%s", dev->ffs_tab[i].name);
-
- mutex_unlock(&dev->mutex);
-
- if (buff != buf)
- *(buff-1) = '\n';
- return buff - buf;
-}
-
-static ssize_t
-functions_store(struct device *pdev, struct device_attribute *attr,
- const char *buff, size_t size)
-{
- struct ccg_dev *dev = dev_get_drvdata(pdev);
- char *name;
- char buf[256], *b;
- int err, i;
- bool functionfs_enabled;
-
- buff = skip_spaces(buff);
- if (!*buff)
- return -EINVAL;
-
- mutex_lock(&dev->mutex);
-
- if (dev->enabled) {
- mutex_unlock(&dev->mutex);
- return -EBUSY;
- }
-
- INIT_LIST_HEAD(&dev->enabled_functions);
- functionfs_enabled = false;
- for (i = 0; i < dev->max_func_num; i++)
- dev->ffs_tab[i].used = false;
-
- strlcpy(buf, buff, sizeof(buf));
- b = strim(buf);
-
- while (b) {
- struct ffs_obj *user_func;
-
- name = strsep(&b, ",");
- /* handle FunctionFS implicitly */
- if (!strcmp(name, functionfs_function.name)) {
- pr_err("ccg_usb: Cannot explicitly enable '%s'", name);
- continue;
- }
- user_func = functionfs_find_dev(dev, name);
- if (user_func)
- name = functionfs_function.name;
- err = 0;
- if (!user_func || !functionfs_enabled)
- err = ccg_enable_function(dev, name);
- if (err)
- pr_err("ccg_usb: Cannot enable '%s'", name);
- else if (user_func) {
- user_func->used = true;
- dev->func_num++;
- functionfs_enabled = true;
- }
- }
-
- mutex_unlock(&dev->mutex);
-
- return size;
-}
-
-static ssize_t enable_show(struct device *pdev, struct device_attribute *attr,
- char *buf)
-{
- struct ccg_dev *dev = dev_get_drvdata(pdev);
- return sprintf(buf, "%d\n", dev->enabled);
-}
-
-static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,
- const char *buff, size_t size)
-{
- struct ccg_dev *dev = dev_get_drvdata(pdev);
- struct usb_composite_dev *cdev = dev->cdev;
- int enabled = 0;
-
- mutex_lock(&dev->mutex);
- sscanf(buff, "%d", &enabled);
- if (enabled && dev->func_num && !functionfs_all_ready(dev)) {
- mutex_unlock(&dev->mutex);
- return -ENODEV;
- }
-
- if (enabled && !dev->enabled) {
- int ret;
-
- cdev->next_string_id = 0;
- /*
- * Update values in composite driver's copy of
- * device descriptor.
- */
- cdev->desc.bDeviceClass = device_desc.bDeviceClass;
- cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;
- cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
- cdev->desc.idVendor = idVendor;
- cdev->desc.idProduct = idProduct;
- cdev->desc.bcdDevice = bcdDevice;
-
- usb_add_config(cdev, &ccg_config_driver, ccg_bind_config);
- dev->enabled = true;
- ret = usb_gadget_connect(cdev->gadget);
- if (ret) {
- dev->enabled = false;
- usb_remove_config(cdev, &ccg_config_driver);
- }
- } else if (!enabled && dev->enabled) {
- reset_usb(dev);
- } else {
- pr_err("ccg_usb: already %s\n",
- dev->enabled ? "enabled" : "disabled");
- }
-
- mutex_unlock(&dev->mutex);
- return size;
-}
-
-static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
- char *buf)
-{
- struct ccg_dev *dev = dev_get_drvdata(pdev);
- struct usb_composite_dev *cdev = dev->cdev;
- char *state = "DISCONNECTED";
- unsigned long flags;
-
- if (!cdev)
- goto out;
-
- spin_lock_irqsave(&cdev->lock, flags);
- if (cdev->config)
- state = "CONFIGURED";
- else if (dev->connected)
- state = "CONNECTED";
- spin_unlock_irqrestore(&cdev->lock, flags);
-out:
- return sprintf(buf, "%s\n", state);
-}
-
-#define DESCRIPTOR_ATTR(field, format_string) \
-static ssize_t \
-field ## _show(struct device *dev, struct device_attribute *attr, \
- char *buf) \
-{ \
- return sprintf(buf, format_string, device_desc.field); \
-} \
-static ssize_t \
-field ## _store(struct device *dev, struct device_attribute *attr, \
- const char *buf, size_t size) \
-{ \
- int value; \
- if (sscanf(buf, format_string, &value) == 1) { \
- device_desc.field = value; \
- return size; \
- } \
- return -1; \
-} \
-static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
-
-DESCRIPTOR_ATTR(bDeviceClass, "%d\n")
-DESCRIPTOR_ATTR(bDeviceSubClass, "%d\n")
-DESCRIPTOR_ATTR(bDeviceProtocol, "%d\n")
-
-static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show,
- functions_store);
-static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
-static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
-
-static struct device_attribute *ccg_usb_attributes[] = {
- &dev_attr_bDeviceClass,
- &dev_attr_bDeviceSubClass,
- &dev_attr_bDeviceProtocol,
- &dev_attr_functions,
- &dev_attr_enable,
- &dev_attr_state,
- NULL
-};
-
-/*-------------------------------------------------------------------------*/
-/* Composite driver */
-
-static int ccg_bind_config(struct usb_configuration *c)
-{
- struct ccg_dev *dev = _ccg_dev;
- return ccg_bind_enabled_functions(dev, c);
-}
-
-static void ccg_unbind_config(struct usb_configuration *c)
-{
- struct ccg_dev *dev = _ccg_dev;
-
- ccg_unbind_enabled_functions(dev, c);
-
- usb_ep_autoconfig_reset(dev->cdev->gadget);
-}
-
-static int ccg_bind(struct usb_composite_dev *cdev)
-{
- struct ccg_dev *dev = _ccg_dev;
- struct usb_gadget *gadget = cdev->gadget;
- int gcnum, ret;
-
- /*
- * Start disconnected. Userspace will connect the gadget once
- * it is done configuring the functions.
- */
- usb_gadget_disconnect(gadget);
-
- ret = ccg_init_functions(dev->functions, cdev);
- if (ret)
- return ret;
-
- gcnum = usb_gadget_controller_number(gadget);
- if (gcnum >= 0)
- device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
- else {
- pr_warn("%s: controller '%s' not recognized\n",
- longname, gadget->name);
- device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
- }
-
- usb_gadget_set_selfpowered(gadget);
- dev->cdev = cdev;
-
- return 0;
-}
-
-static int ccg_usb_unbind(struct usb_composite_dev *cdev)
-{
- struct ccg_dev *dev = _ccg_dev;
-
- cancel_work_sync(&dev->work);
- ccg_cleanup_functions(dev->functions);
- return 0;
-}
-
-static struct usb_composite_driver ccg_usb_driver = {
- .name = "configurable_usb",
- .dev = &device_desc,
- .bind = ccg_bind,
- .unbind = ccg_usb_unbind,
- .needs_serial = true,
- .iManufacturer = "Linux Foundation",
- .iProduct = longname,
- .iSerialNumber = "1234567890123456",
-};
-
-static int ccg_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c)
-{
- struct ccg_dev *dev = _ccg_dev;
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
- struct usb_request *req = cdev->req;
- struct ccg_usb_function *f;
- int value = -EOPNOTSUPP;
- unsigned long flags;
-
- req->zero = 0;
- req->complete = composite_setup_complete;
- req->length = 0;
- gadget->ep0->driver_data = cdev;
-
- list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
- if (f->ctrlrequest) {
- value = f->ctrlrequest(f, cdev, c);
- if (value >= 0)
- break;
- }
- }
-
- if (value < 0)
- value = composite_setup(gadget, c);
-
- spin_lock_irqsave(&cdev->lock, flags);
- if (!dev->connected) {
- dev->connected = 1;
- schedule_work(&dev->work);
- } else if (c->bRequest == USB_REQ_SET_CONFIGURATION &&
- cdev->config) {
- schedule_work(&dev->work);
- }
- spin_unlock_irqrestore(&cdev->lock, flags);
-
- return value;
-}
-
-static void ccg_disconnect(struct usb_gadget *gadget)
-{
- struct ccg_dev *dev = _ccg_dev;
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
- unsigned long flags;
-
- composite_disconnect(gadget);
-
- spin_lock_irqsave(&cdev->lock, flags);
- dev->connected = 0;
- schedule_work(&dev->work);
- spin_unlock_irqrestore(&cdev->lock, flags);
-}
-
-static int ccg_create_device(struct ccg_dev *dev)
-{
- struct device_attribute **attrs = ccg_usb_attributes;
- struct device_attribute *attr;
- int err;
-
- dev->dev = device_create(ccg_class, NULL, MKDEV(0, 0), NULL, "ccg0");
- if (IS_ERR(dev->dev))
- return PTR_ERR(dev->dev);
-
- dev_set_drvdata(dev->dev, dev);
-
- while ((attr = *attrs++)) {
- err = device_create_file(dev->dev, attr);
- if (err) {
- device_destroy(ccg_class, dev->dev->devt);
- return err;
- }
- }
- return 0;
-}
-
-
-static int __init ccg_init(void)
-{
- struct ccg_dev *dev;
- int err;
-
- ccg_class = class_create(THIS_MODULE, "ccg_usb");
- if (IS_ERR(ccg_class))
- return PTR_ERR(ccg_class);
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) {
- class_destroy(ccg_class);
- return -ENOMEM;
- }
-
- dev->functions = supported_functions;
- INIT_LIST_HEAD(&dev->enabled_functions);
- INIT_WORK(&dev->work, ccg_work);
- mutex_init(&dev->mutex);
-
- err = ccg_create_device(dev);
- if (err) {
- class_destroy(ccg_class);
- kfree(dev);
- return err;
- }
-
- _ccg_dev = dev;
-
- /* Override composite driver functions */
- composite_driver.setup = ccg_setup;
- composite_driver.disconnect = ccg_disconnect;
-
- err = usb_composite_probe(&ccg_usb_driver);
- if (err) {
- class_destroy(ccg_class);
- kfree(dev);
- }
-
- return err;
-}
-module_init(ccg_init);
-
-static void __exit ccg_exit(void)
-{
- usb_composite_unregister(&ccg_usb_driver);
- class_destroy(ccg_class);
- kfree(_ccg_dev);
- _ccg_dev = NULL;
-}
-module_exit(ccg_exit);
diff --git a/drivers/staging/ccg/composite.c b/drivers/staging/ccg/composite.c
deleted file mode 100644
index 228b4574f22..00000000000
--- a/drivers/staging/ccg/composite.c
+++ /dev/null
@@ -1,1688 +0,0 @@
-/*
- * composite.c - infrastructure for Composite USB Gadgets
- *
- * Copyright (C) 2006-2008 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-/* #define VERBOSE_DEBUG */
-
-#include <linux/kallsyms.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/utsname.h>
-
-#include <linux/usb/composite.h>
-#include <asm/unaligned.h>
-
-/*
- * The code in this file is utility code, used to build a gadget driver
- * from one or more "function" drivers, one or more "configuration"
- * objects, and a "usb_composite_driver" by gluing them together along
- * with the relevant device-wide data.
- */
-
-/* big enough to hold our biggest descriptor */
-#define USB_BUFSIZ 1024
-
-static struct usb_composite_driver *composite;
-
-/* Some systems will need runtime overrides for the product identifiers
- * published in the device descriptor, either numbers or strings or both.
- * String parameters are in UTF-8 (superset of ASCII's 7 bit characters).
- */
-
-static ushort idVendor;
-module_param(idVendor, ushort, 0644);
-MODULE_PARM_DESC(idVendor, "USB Vendor ID");
-
-static ushort idProduct;
-module_param(idProduct, ushort, 0644);
-MODULE_PARM_DESC(idProduct, "USB Product ID");
-
-static ushort bcdDevice;
-module_param(bcdDevice, ushort, 0644);
-MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
-
-static char *iManufacturer;
-module_param(iManufacturer, charp, 0644);
-MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
-
-static char *iProduct;
-module_param(iProduct, charp, 0644);
-MODULE_PARM_DESC(iProduct, "USB Product string");
-
-static char *iSerialNumber;
-module_param(iSerialNumber, charp, 0644);
-MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
-
-static char composite_manufacturer[50];
-
-/*-------------------------------------------------------------------------*/
-/**
- * next_ep_desc() - advance to the next EP descriptor
- * @t: currect pointer within descriptor array
- *
- * Return: next EP descriptor or NULL
- *
- * Iterate over @t until either EP descriptor found or
- * NULL (that indicates end of list) encountered
- */
-static struct usb_descriptor_header**
-next_ep_desc(struct usb_descriptor_header **t)
-{
- for (; *t; t++) {
- if ((*t)->bDescriptorType == USB_DT_ENDPOINT)
- return t;
- }
- return NULL;
-}
-
-/*
- * for_each_ep_desc()- iterate over endpoint descriptors in the
- * descriptors list
- * @start: pointer within descriptor array.
- * @ep_desc: endpoint descriptor to use as the loop cursor
- */
-#define for_each_ep_desc(start, ep_desc) \
- for (ep_desc = next_ep_desc(start); \
- ep_desc; ep_desc = next_ep_desc(ep_desc+1))
-
-/**
- * config_ep_by_speed() - configures the given endpoint
- * according to gadget speed.
- * @g: pointer to the gadget
- * @f: usb function
- * @_ep: the endpoint to configure
- *
- * Return: error code, 0 on success
- *
- * This function chooses the right descriptors for a given
- * endpoint according to gadget speed and saves it in the
- * endpoint desc field. If the endpoint already has a descriptor
- * assigned to it - overwrites it with currently corresponding
- * descriptor. The endpoint maxpacket field is updated according
- * to the chosen descriptor.
- * Note: the supplied function should hold all the descriptors
- * for supported speeds
- */
-int config_ep_by_speed(struct usb_gadget *g,
- struct usb_function *f,
- struct usb_ep *_ep)
-{
- struct usb_composite_dev *cdev = get_gadget_data(g);
- struct usb_endpoint_descriptor *chosen_desc = NULL;
- struct usb_descriptor_header **speed_desc = NULL;
-
- struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
- int want_comp_desc = 0;
-
- struct usb_descriptor_header **d_spd; /* cursor for speed desc */
-
- if (!g || !f || !_ep)
- return -EIO;
-
- /* select desired speed */
- switch (g->speed) {
- case USB_SPEED_SUPER:
- if (gadget_is_superspeed(g)) {
- speed_desc = f->ss_descriptors;
- want_comp_desc = 1;
- break;
- }
- /* else: Fall trough */
- case USB_SPEED_HIGH:
- if (gadget_is_dualspeed(g)) {
- speed_desc = f->hs_descriptors;
- break;
- }
- /* else: fall through */
- default:
- speed_desc = f->descriptors;
- }
- /* find descriptors */
- for_each_ep_desc(speed_desc, d_spd) {
- chosen_desc = (struct usb_endpoint_descriptor *)*d_spd;
- if (chosen_desc->bEndpointAddress == _ep->address)
- goto ep_found;
- }
- return -EIO;
-
-ep_found:
- /* commit results */
- _ep->maxpacket = usb_endpoint_maxp(chosen_desc);
- _ep->desc = chosen_desc;
- _ep->comp_desc = NULL;
- _ep->maxburst = 0;
- _ep->mult = 0;
- if (!want_comp_desc)
- return 0;
-
- /*
- * Companion descriptor should follow EP descriptor
- * USB 3.0 spec, #9.6.7
- */
- comp_desc = (struct usb_ss_ep_comp_descriptor *)*(++d_spd);
- if (!comp_desc ||
- (comp_desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP))
- return -EIO;
- _ep->comp_desc = comp_desc;
- if (g->speed == USB_SPEED_SUPER) {
- switch (usb_endpoint_type(_ep->desc)) {
- case USB_ENDPOINT_XFER_ISOC:
- /* mult: bits 1:0 of bmAttributes */
- _ep->mult = comp_desc->bmAttributes & 0x3;
- case USB_ENDPOINT_XFER_BULK:
- case USB_ENDPOINT_XFER_INT:
- _ep->maxburst = comp_desc->bMaxBurst + 1;
- break;
- default:
- if (comp_desc->bMaxBurst != 0)
- ERROR(cdev, "ep0 bMaxBurst must be 0\n");
- _ep->maxburst = 1;
- break;
- }
- }
- return 0;
-}
-
-/**
- * usb_add_function() - add a function to a configuration
- * @config: the configuration
- * @function: the function being added
- * Context: single threaded during gadget setup
- *
- * After initialization, each configuration must have one or more
- * functions added to it. Adding a function involves calling its @bind()
- * method to allocate resources such as interface and string identifiers
- * and endpoints.
- *
- * This function returns the value of the function's bind(), which is
- * zero for success else a negative errno value.
- */
-int usb_add_function(struct usb_configuration *config,
- struct usb_function *function)
-{
- int value = -EINVAL;
-
- DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
- function->name, function,
- config->label, config);
-
- if (!function->set_alt || !function->disable)
- goto done;
-
- function->config = config;
- list_add_tail(&function->list, &config->functions);
-
- /* REVISIT *require* function->bind? */
- if (function->bind) {
- value = function->bind(config, function);
- if (value < 0) {
- list_del(&function->list);
- function->config = NULL;
- }
- } else
- value = 0;
-
- /* We allow configurations that don't work at both speeds.
- * If we run into a lowspeed Linux system, treat it the same
- * as full speed ... it's the function drivers that will need
- * to avoid bulk and ISO transfers.
- */
- if (!config->fullspeed && function->descriptors)
- config->fullspeed = true;
- if (!config->highspeed && function->hs_descriptors)
- config->highspeed = true;
- if (!config->superspeed && function->ss_descriptors)
- config->superspeed = true;
-
-done:
- if (value)
- DBG(config->cdev, "adding '%s'/%p --> %d\n",
- function->name, function, value);
- return value;
-}
-
-/**
- * usb_function_deactivate - prevent function and gadget enumeration
- * @function: the function that isn't yet ready to respond
- *
- * Blocks response of the gadget driver to host enumeration by
- * preventing the data line pullup from being activated. This is
- * normally called during @bind() processing to change from the
- * initial "ready to respond" state, or when a required resource
- * becomes available.
- *
- * For example, drivers that serve as a passthrough to a userspace
- * daemon can block enumeration unless that daemon (such as an OBEX,
- * MTP, or print server) is ready to handle host requests.
- *
- * Not all systems support software control of their USB peripheral
- * data pullups.
- *
- * Returns zero on success, else negative errno.
- */
-int usb_function_deactivate(struct usb_function *function)
-{
- struct usb_composite_dev *cdev = function->config->cdev;
- unsigned long flags;
- int status = 0;
-
- spin_lock_irqsave(&cdev->lock, flags);
-
- if (cdev->deactivations == 0)
- status = usb_gadget_disconnect(cdev->gadget);
- if (status == 0)
- cdev->deactivations++;
-
- spin_unlock_irqrestore(&cdev->lock, flags);
- return status;
-}
-
-/**
- * usb_function_activate - allow function and gadget enumeration
- * @function: function on which usb_function_activate() was called
- *
- * Reverses effect of usb_function_deactivate(). If no more functions
- * are delaying their activation, the gadget driver will respond to
- * host enumeration procedures.
- *
- * Returns zero on success, else negative errno.
- */
-int usb_function_activate(struct usb_function *function)
-{
- struct usb_composite_dev *cdev = function->config->cdev;
- unsigned long flags;
- int status = 0;
-
- spin_lock_irqsave(&cdev->lock, flags);
-
- if (WARN_ON(cdev->deactivations == 0))
- status = -EINVAL;
- else {
- cdev->deactivations--;
- if (cdev->deactivations == 0)
- status = usb_gadget_connect(cdev->gadget);
- }
-
- spin_unlock_irqrestore(&cdev->lock, flags);
- return status;
-}
-
-/**
- * usb_interface_id() - allocate an unused interface ID
- * @config: configuration associated with the interface
- * @function: function handling the interface
- * Context: single threaded during gadget setup
- *
- * usb_interface_id() is called from usb_function.bind() callbacks to
- * allocate new interface IDs. The function driver will then store that
- * ID in interface, association, CDC union, and other descriptors. It
- * will also handle any control requests targeted at that interface,
- * particularly changing its altsetting via set_alt(). There may
- * also be class-specific or vendor-specific requests to handle.
- *
- * All interface identifier should be allocated using this routine, to
- * ensure that for example different functions don't wrongly assign
- * different meanings to the same identifier. Note that since interface
- * identifiers are configuration-specific, functions used in more than
- * one configuration (or more than once in a given configuration) need
- * multiple versions of the relevant descriptors.
- *
- * Returns the interface ID which was allocated; or -ENODEV if no
- * more interface IDs can be allocated.
- */
-int usb_interface_id(struct usb_configuration *config,
- struct usb_function *function)
-{
- unsigned id = config->next_interface_id;
-
- if (id < MAX_CONFIG_INTERFACES) {
- config->interface[id] = function;
- config->next_interface_id = id + 1;
- return id;
- }
- return -ENODEV;
-}
-
-static int config_buf(struct usb_configuration *config,
- enum usb_device_speed speed, void *buf, u8 type)
-{
- struct usb_config_descriptor *c = buf;
- void *next = buf + USB_DT_CONFIG_SIZE;
- int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
- struct usb_function *f;
- int status;
-
- /* write the config descriptor */
- c = buf;
- c->bLength = USB_DT_CONFIG_SIZE;
- c->bDescriptorType = type;
- /* wTotalLength is written later */
- c->bNumInterfaces = config->next_interface_id;
- c->bConfigurationValue = config->bConfigurationValue;
- c->iConfiguration = config->iConfiguration;
- c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
- c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2);
-
- /* There may be e.g. OTG descriptors */
- if (config->descriptors) {
- status = usb_descriptor_fillbuf(next, len,
- config->descriptors);
- if (status < 0)
- return status;
- len -= status;
- next += status;
- }
-
- /* add each function's descriptors */
- list_for_each_entry(f, &config->functions, list) {
- struct usb_descriptor_header **descriptors;
-
- switch (speed) {
- case USB_SPEED_SUPER:
- descriptors = f->ss_descriptors;
- break;
- case USB_SPEED_HIGH:
- descriptors = f->hs_descriptors;
- break;
- default:
- descriptors = f->descriptors;
- }
-
- if (!descriptors)
- continue;
- status = usb_descriptor_fillbuf(next, len,
- (const struct usb_descriptor_header **) descriptors);
- if (status < 0)
- return status;
- len -= status;
- next += status;
- }
-
- len = next - buf;
- c->wTotalLength = cpu_to_le16(len);
- return len;
-}
-
-static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
-{
- struct usb_gadget *gadget = cdev->gadget;
- struct usb_configuration *c;
- u8 type = w_value >> 8;
- enum usb_device_speed speed = USB_SPEED_UNKNOWN;
-
- if (gadget->speed == USB_SPEED_SUPER)
- speed = gadget->speed;
- else if (gadget_is_dualspeed(gadget)) {
- int hs = 0;
- if (gadget->speed == USB_SPEED_HIGH)
- hs = 1;
- if (type == USB_DT_OTHER_SPEED_CONFIG)
- hs = !hs;
- if (hs)
- speed = USB_SPEED_HIGH;
-
- }
-
- /* This is a lookup by config *INDEX* */
- w_value &= 0xff;
- list_for_each_entry(c, &cdev->configs, list) {
- /* ignore configs that won't work at this speed */
- switch (speed) {
- case USB_SPEED_SUPER:
- if (!c->superspeed)
- continue;
- break;
- case USB_SPEED_HIGH:
- if (!c->highspeed)
- continue;
- break;
- default:
- if (!c->fullspeed)
- continue;
- }
-
- if (w_value == 0)
- return config_buf(c, speed, cdev->req->buf, type);
- w_value--;
- }
- return -EINVAL;
-}
-
-static int count_configs(struct usb_composite_dev *cdev, unsigned type)
-{
- struct usb_gadget *gadget = cdev->gadget;
- struct usb_configuration *c;
- unsigned count = 0;
- int hs = 0;
- int ss = 0;
-
- if (gadget_is_dualspeed(gadget)) {
- if (gadget->speed == USB_SPEED_HIGH)
- hs = 1;
- if (gadget->speed == USB_SPEED_SUPER)
- ss = 1;
- if (type == USB_DT_DEVICE_QUALIFIER)
- hs = !hs;
- }
- list_for_each_entry(c, &cdev->configs, list) {
- /* ignore configs that won't work at this speed */
- if (ss) {
- if (!c->superspeed)
- continue;
- } else if (hs) {
- if (!c->highspeed)
- continue;
- } else {
- if (!c->fullspeed)
- continue;
- }
- count++;
- }
- return count;
-}
-
-/**
- * bos_desc() - prepares the BOS descriptor.
- * @cdev: pointer to usb_composite device to generate the bos
- * descriptor for
- *
- * This function generates the BOS (Binary Device Object)
- * descriptor and its device capabilities descriptors. The BOS
- * descriptor should be supported by a SuperSpeed device.
- */
-static int bos_desc(struct usb_composite_dev *cdev)
-{
- struct usb_ext_cap_descriptor *usb_ext;
- struct usb_ss_cap_descriptor *ss_cap;
- struct usb_dcd_config_params dcd_config_params;
- struct usb_bos_descriptor *bos = cdev->req->buf;
-
- bos->bLength = USB_DT_BOS_SIZE;
- bos->bDescriptorType = USB_DT_BOS;
-
- bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE);
- bos->bNumDeviceCaps = 0;
-
- /*
- * A SuperSpeed device shall include the USB2.0 extension descriptor
- * and shall support LPM when operating in USB2.0 HS mode.
- */
- usb_ext = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
- bos->bNumDeviceCaps++;
- le16_add_cpu(&bos->wTotalLength, USB_DT_USB_EXT_CAP_SIZE);
- usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
- usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
- usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
- usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
-
- /*
- * The Superspeed USB Capability descriptor shall be implemented by all
- * SuperSpeed devices.
- */
- ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
- bos->bNumDeviceCaps++;
- le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
- ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
- ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
- ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
- ss_cap->bmAttributes = 0; /* LTM is not supported yet */
- ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
- USB_FULL_SPEED_OPERATION |
- USB_HIGH_SPEED_OPERATION |
- USB_5GBPS_OPERATION);
- ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
-
- /* Get Controller configuration */
- if (cdev->gadget->ops->get_config_params)
- cdev->gadget->ops->get_config_params(&dcd_config_params);
- else {
- dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT;
- dcd_config_params.bU2DevExitLat =
- cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
- }
- ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
- ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
-
- return le16_to_cpu(bos->wTotalLength);
-}
-
-static void device_qual(struct usb_composite_dev *cdev)
-{
- struct usb_qualifier_descriptor *qual = cdev->req->buf;
-
- qual->bLength = sizeof(*qual);
- qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER;
- /* POLICY: same bcdUSB and device type info at both speeds */
- qual->bcdUSB = cdev->desc.bcdUSB;
- qual->bDeviceClass = cdev->desc.bDeviceClass;
- qual->bDeviceSubClass = cdev->desc.bDeviceSubClass;
- qual->bDeviceProtocol = cdev->desc.bDeviceProtocol;
- /* ASSUME same EP0 fifo size at both speeds */
- qual->bMaxPacketSize0 = cdev->gadget->ep0->maxpacket;
- qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER);
- qual->bRESERVED = 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void reset_config(struct usb_composite_dev *cdev)
-{
- struct usb_function *f;
-
- DBG(cdev, "reset config\n");
-
- list_for_each_entry(f, &cdev->config->functions, list) {
- if (f->disable)
- f->disable(f);
-
- bitmap_zero(f->endpoints, 32);
- }
- cdev->config = NULL;
-}
-
-static int set_config(struct usb_composite_dev *cdev,
- const struct usb_ctrlrequest *ctrl, unsigned number)
-{
- struct usb_gadget *gadget = cdev->gadget;
- struct usb_configuration *c = NULL;
- int result = -EINVAL;
- unsigned power = gadget_is_otg(gadget) ? 8 : 100;
- int tmp;
-
- if (number) {
- list_for_each_entry(c, &cdev->configs, list) {
- if (c->bConfigurationValue == number) {
- /*
- * We disable the FDs of the previous
- * configuration only if the new configuration
- * is a valid one
- */
- if (cdev->config)
- reset_config(cdev);
- result = 0;
- break;
- }
- }
- if (result < 0)
- goto done;
- } else { /* Zero configuration value - need to reset the config */
- if (cdev->config)
- reset_config(cdev);
- result = 0;
- }
-
- INFO(cdev, "%s config #%d: %s\n",
- usb_speed_string(gadget->speed),
- number, c ? c->label : "unconfigured");
-
- if (!c)
- goto done;
-
- cdev->config = c;
-
- /* Initialize all interfaces by setting them to altsetting zero. */
- for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {
- struct usb_function *f = c->interface[tmp];
- struct usb_descriptor_header **descriptors;
-
- if (!f)
- break;
-
- /*
- * Record which endpoints are used by the function. This is used
- * to dispatch control requests targeted at that endpoint to the
- * function's setup callback instead of the current
- * configuration's setup callback.
- */
- switch (gadget->speed) {
- case USB_SPEED_SUPER:
- descriptors = f->ss_descriptors;
- break;
- case USB_SPEED_HIGH:
- descriptors = f->hs_descriptors;
- break;
- default:
- descriptors = f->descriptors;
- }
-
- for (; *descriptors; ++descriptors) {
- struct usb_endpoint_descriptor *ep;
- int addr;
-
- if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT)
- continue;
-
- ep = (struct usb_endpoint_descriptor *)*descriptors;
- addr = ((ep->bEndpointAddress & 0x80) >> 3)
- | (ep->bEndpointAddress & 0x0f);
- set_bit(addr, f->endpoints);
- }
-
- result = f->set_alt(f, tmp, 0);
- if (result < 0) {
- DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n",
- tmp, f->name, f, result);
-
- reset_config(cdev);
- goto done;
- }
-
- if (result == USB_GADGET_DELAYED_STATUS) {
- DBG(cdev,
- "%s: interface %d (%s) requested delayed status\n",
- __func__, tmp, f->name);
- cdev->delayed_status++;
- DBG(cdev, "delayed_status count %d\n",
- cdev->delayed_status);
- }
- }
-
- /* when we return, be sure our power usage is valid */
- power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;
-done:
- usb_gadget_vbus_draw(gadget, power);
- if (result >= 0 && cdev->delayed_status)
- result = USB_GADGET_DELAYED_STATUS;
- return result;
-}
-
-/**
- * usb_add_config() - add a configuration to a device.
- * @cdev: wraps the USB gadget
- * @config: the configuration, with bConfigurationValue assigned
- * @bind: the configuration's bind function
- * Context: single threaded during gadget setup
- *
- * One of the main tasks of a composite @bind() routine is to
- * add each of the configurations it supports, using this routine.
- *
- * This function returns the value of the configuration's @bind(), which
- * is zero for success else a negative errno value. Binding configurations
- * assigns global resources including string IDs, and per-configuration
- * resources such as interface IDs and endpoints.
- */
-int usb_add_config(struct usb_composite_dev *cdev,
- struct usb_configuration *config,
- int (*bind)(struct usb_configuration *))
-{
- int status = -EINVAL;
- struct usb_configuration *c;
-
- DBG(cdev, "adding config #%u '%s'/%p\n",
- config->bConfigurationValue,
- config->label, config);
-
- if (!config->bConfigurationValue || !bind)
- goto done;
-
- /* Prevent duplicate configuration identifiers */
- list_for_each_entry(c, &cdev->configs, list) {
- if (c->bConfigurationValue == config->bConfigurationValue) {
- status = -EBUSY;
- goto done;
- }
- }
-
- config->cdev = cdev;
- list_add_tail(&config->list, &cdev->configs);
-
- INIT_LIST_HEAD(&config->functions);
- config->next_interface_id = 0;
- memset(config->interface, 0, sizeof(config->interface));
-
- status = bind(config);
- if (status < 0) {
- while (!list_empty(&config->functions)) {
- struct usb_function *f;
-
- f = list_first_entry(&config->functions,
- struct usb_function, list);
- list_del(&f->list);
- if (f->unbind) {
- DBG(cdev, "unbind function '%s'/%p\n",
- f->name, f);
- f->unbind(config, f);
- /* may free memory for "f" */
- }
- }
- list_del(&config->list);
- config->cdev = NULL;
- } else {
- unsigned i;
-
- DBG(cdev, "cfg %d/%p speeds:%s%s%s\n",
- config->bConfigurationValue, config,
- config->superspeed ? " super" : "",
- config->highspeed ? " high" : "",
- config->fullspeed
- ? (gadget_is_dualspeed(cdev->gadget)
- ? " full"
- : " full/low")
- : "");
-
- for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
- struct usb_function *f = config->interface[i];
-
- if (!f)
- continue;
- DBG(cdev, " interface %d = %s/%p\n",
- i, f->name, f);
- }
- }
-
- /* set_alt(), or next bind(), sets up
- * ep->driver_data as needed.
- */
- usb_ep_autoconfig_reset(cdev->gadget);
-
-done:
- if (status)
- DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
- config->bConfigurationValue, status);
- return status;
-}
-
-static void remove_config(struct usb_composite_dev *cdev,
- struct usb_configuration *config)
-{
- while (!list_empty(&config->functions)) {
- struct usb_function *f;
-
- f = list_first_entry(&config->functions,
- struct usb_function, list);
- list_del(&f->list);
- if (f->unbind) {
- DBG(cdev, "unbind function '%s'/%p\n", f->name, f);
- f->unbind(config, f);
- /* may free memory for "f" */
- }
- }
- list_del(&config->list);
- if (config->unbind) {
- DBG(cdev, "unbind config '%s'/%p\n", config->label, config);
- config->unbind(config);
- /* may free memory for "c" */
- }
-}
-
-/**
- * usb_remove_config() - remove a configuration from a device.
- * @cdev: wraps the USB gadget
- * @config: the configuration
- *
- * Drivers must call usb_gadget_disconnect before calling this function
- * to disconnect the device from the host and make sure the host will not
- * try to enumerate the device while we are changing the config list.
- */
-void usb_remove_config(struct usb_composite_dev *cdev,
- struct usb_configuration *config)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cdev->lock, flags);
-
- if (cdev->config == config)
- reset_config(cdev);
-
- spin_unlock_irqrestore(&cdev->lock, flags);
-
- remove_config(cdev, config);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* We support strings in multiple languages ... string descriptor zero
- * says which languages are supported. The typical case will be that
- * only one language (probably English) is used, with I18N handled on
- * the host side.
- */
-
-static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)
-{
- const struct usb_gadget_strings *s;
- __le16 language;
- __le16 *tmp;
-
- while (*sp) {
- s = *sp;
- language = cpu_to_le16(s->language);
- for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) {
- if (*tmp == language)
- goto repeat;
- }
- *tmp++ = language;
-repeat:
- sp++;
- }
-}
-
-static int lookup_string(
- struct usb_gadget_strings **sp,
- void *buf,
- u16 language,
- int id
-)
-{
- struct usb_gadget_strings *s;
- int value;
-
- while (*sp) {
- s = *sp++;
- if (s->language != language)
- continue;
- value = usb_gadget_get_string(s, id, buf);
- if (value > 0)
- return value;
- }
- return -EINVAL;
-}
-
-static int get_string(struct usb_composite_dev *cdev,
- void *buf, u16 language, int id)
-{
- struct usb_configuration *c;
- struct usb_function *f;
- int len;
- const char *str;
-
- /* Yes, not only is USB's I18N support probably more than most
- * folk will ever care about ... also, it's all supported here.
- * (Except for UTF8 support for Unicode's "Astral Planes".)
- */
-
- /* 0 == report all available language codes */
- if (id == 0) {
- struct usb_string_descriptor *s = buf;
- struct usb_gadget_strings **sp;
-
- memset(s, 0, 256);
- s->bDescriptorType = USB_DT_STRING;
-
- sp = composite->strings;
- if (sp)
- collect_langs(sp, s->wData);
-
- list_for_each_entry(c, &cdev->configs, list) {
- sp = c->strings;
- if (sp)
- collect_langs(sp, s->wData);
-
- list_for_each_entry(f, &c->functions, list) {
- sp = f->strings;
- if (sp)
- collect_langs(sp, s->wData);
- }
- }
-
- for (len = 0; len <= 126 && s->wData[len]; len++)
- continue;
- if (!len)
- return -EINVAL;
-
- s->bLength = 2 * (len + 1);
- return s->bLength;
- }
-
- /* Otherwise, look up and return a specified string. First
- * check if the string has not been overridden.
- */
- if (cdev->manufacturer_override == id)
- str = iManufacturer ?: composite->iManufacturer ?:
- composite_manufacturer;
- else if (cdev->product_override == id)
- str = iProduct ?: composite->iProduct;
- else if (cdev->serial_override == id)
- str = iSerialNumber ?: composite->iSerialNumber;
- else
- str = NULL;
- if (str) {
- struct usb_gadget_strings strings = {
- .language = language,
- .strings = &(struct usb_string) { 0xff, str }
- };
- return usb_gadget_get_string(&strings, 0xff, buf);
- }
-
- /* String IDs are device-scoped, so we look up each string
- * table we're told about. These lookups are infrequent;
- * simpler-is-better here.
- */
- if (composite->strings) {
- len = lookup_string(composite->strings, buf, language, id);
- if (len > 0)
- return len;
- }
- list_for_each_entry(c, &cdev->configs, list) {
- if (c->strings) {
- len = lookup_string(c->strings, buf, language, id);
- if (len > 0)
- return len;
- }
- list_for_each_entry(f, &c->functions, list) {
- if (!f->strings)
- continue;
- len = lookup_string(f->strings, buf, language, id);
- if (len > 0)
- return len;
- }
- }
- return -EINVAL;
-}
-
-/**
- * usb_string_id() - allocate an unused string ID
- * @cdev: the device whose string descriptor IDs are being allocated
- * Context: single threaded during gadget setup
- *
- * @usb_string_id() is called from bind() callbacks to allocate
- * string IDs. Drivers for functions, configurations, or gadgets will
- * then store that ID in the appropriate descriptors and string table.
- *
- * All string identifier should be allocated using this,
- * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure
- * that for example different functions don't wrongly assign different
- * meanings to the same identifier.
- */
-int usb_string_id(struct usb_composite_dev *cdev)
-{
- if (cdev->next_string_id < 254) {
- /* string id 0 is reserved by USB spec for list of
- * supported languages */
- /* 255 reserved as well? -- mina86 */
- cdev->next_string_id++;
- return cdev->next_string_id;
- }
- return -ENODEV;
-}
-
-/**
- * usb_string_ids() - allocate unused string IDs in batch
- * @cdev: the device whose string descriptor IDs are being allocated
- * @str: an array of usb_string objects to assign numbers to
- * Context: single threaded during gadget setup
- *
- * @usb_string_ids() is called from bind() callbacks to allocate
- * string IDs. Drivers for functions, configurations, or gadgets will
- * then copy IDs from the string table to the appropriate descriptors
- * and string table for other languages.
- *
- * All string identifier should be allocated using this,
- * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for
- * example different functions don't wrongly assign different meanings
- * to the same identifier.
- */
-int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
-{
- int next = cdev->next_string_id;
-
- for (; str->s; ++str) {
- if (unlikely(next >= 254))
- return -ENODEV;
- str->id = ++next;
- }
-
- cdev->next_string_id = next;
-
- return 0;
-}
-
-/**
- * usb_string_ids_n() - allocate unused string IDs in batch
- * @c: the device whose string descriptor IDs are being allocated
- * @n: number of string IDs to allocate
- * Context: single threaded during gadget setup
- *
- * Returns the first requested ID. This ID and next @n-1 IDs are now
- * valid IDs. At least provided that @n is non-zero because if it
- * is, returns last requested ID which is now very useful information.
- *
- * @usb_string_ids_n() is called from bind() callbacks to allocate
- * string IDs. Drivers for functions, configurations, or gadgets will
- * then store that ID in the appropriate descriptors and string table.
- *
- * All string identifier should be allocated using this,
- * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for
- * example different functions don't wrongly assign different meanings
- * to the same identifier.
- */
-int usb_string_ids_n(struct usb_composite_dev *c, unsigned n)
-{
- unsigned next = c->next_string_id;
- if (unlikely(n > 254 || (unsigned)next + n > 254))
- return -ENODEV;
- c->next_string_id += n;
- return next + 1;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
- if (req->status || req->actual != req->length)
- DBG((struct usb_composite_dev *) ep->driver_data,
- "setup complete --> %d, %d/%d\n",
- req->status, req->actual, req->length);
-}
-
-/*
- * The setup() callback implements all the ep0 functionality that's
- * not handled lower down, in hardware or the hardware driver(like
- * device and endpoint feature flags, and their status). It's all
- * housekeeping for the gadget function we're implementing. Most of
- * the work is in config and function specific setup.
- */
-static int
-composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
-{
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
- struct usb_request *req = cdev->req;
- int value = -EOPNOTSUPP;
- int status = 0;
- u16 w_index = le16_to_cpu(ctrl->wIndex);
- u8 intf = w_index & 0xFF;
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u16 w_length = le16_to_cpu(ctrl->wLength);
- struct usb_function *f = NULL;
- u8 endp;
-
- /* partial re-init of the response message; the function or the
- * gadget might need to intercept e.g. a control-OUT completion
- * when we delegate to it.
- */
- req->zero = 0;
- req->complete = composite_setup_complete;
- req->length = 0;
- gadget->ep0->driver_data = cdev;
-
- switch (ctrl->bRequest) {
-
- /* we handle all standard USB descriptors */
- case USB_REQ_GET_DESCRIPTOR:
- if (ctrl->bRequestType != USB_DIR_IN)
- goto unknown;
- switch (w_value >> 8) {
-
- case USB_DT_DEVICE:
- cdev->desc.bNumConfigurations =
- count_configs(cdev, USB_DT_DEVICE);
- cdev->desc.bMaxPacketSize0 =
- cdev->gadget->ep0->maxpacket;
- if (gadget_is_superspeed(gadget)) {
- if (gadget->speed >= USB_SPEED_SUPER) {
- cdev->desc.bcdUSB = cpu_to_le16(0x0300);
- cdev->desc.bMaxPacketSize0 = 9;
- } else {
- cdev->desc.bcdUSB = cpu_to_le16(0x0210);
- }
- }
-
- value = min(w_length, (u16) sizeof cdev->desc);
- memcpy(req->buf, &cdev->desc, value);
- break;
- case USB_DT_DEVICE_QUALIFIER:
- if (!gadget_is_dualspeed(gadget) ||
- gadget->speed >= USB_SPEED_SUPER)
- break;
- device_qual(cdev);
- value = min_t(int, w_length,
- sizeof(struct usb_qualifier_descriptor));
- break;
- case USB_DT_OTHER_SPEED_CONFIG:
- if (!gadget_is_dualspeed(gadget) ||
- gadget->speed >= USB_SPEED_SUPER)
- break;
- /* FALLTHROUGH */
- case USB_DT_CONFIG:
- value = config_desc(cdev, w_value);
- if (value >= 0)
- value = min(w_length, (u16) value);
- break;
- case USB_DT_STRING:
- value = get_string(cdev, req->buf,
- w_index, w_value & 0xff);
- if (value >= 0)
- value = min(w_length, (u16) value);
- break;
- case USB_DT_BOS:
- if (gadget_is_superspeed(gadget)) {
- value = bos_desc(cdev);
- value = min(w_length, (u16) value);
- }
- break;
- }
- break;
-
- /* any number of configs can work */
- case USB_REQ_SET_CONFIGURATION:
- if (ctrl->bRequestType != 0)
- goto unknown;
- if (gadget_is_otg(gadget)) {
- if (gadget->a_hnp_support)
- DBG(cdev, "HNP available\n");
- else if (gadget->a_alt_hnp_support)
- DBG(cdev, "HNP on another port\n");
- else
- VDBG(cdev, "HNP inactive\n");
- }
- spin_lock(&cdev->lock);
- value = set_config(cdev, ctrl, w_value);
- spin_unlock(&cdev->lock);
- break;
- case USB_REQ_GET_CONFIGURATION:
- if (ctrl->bRequestType != USB_DIR_IN)
- goto unknown;
- if (cdev->config)
- *(u8 *)req->buf = cdev->config->bConfigurationValue;
- else
- *(u8 *)req->buf = 0;
- value = min(w_length, (u16) 1);
- break;
-
- /* function drivers must handle get/set altsetting; if there's
- * no get() method, we know only altsetting zero works.
- */
- case USB_REQ_SET_INTERFACE:
- if (ctrl->bRequestType != USB_RECIP_INTERFACE)
- goto unknown;
- if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
- break;
- f = cdev->config->interface[intf];
- if (!f)
- break;
- if (w_value && !f->set_alt)
- break;
- value = f->set_alt(f, w_index, w_value);
- if (value == USB_GADGET_DELAYED_STATUS) {
- DBG(cdev,
- "%s: interface %d (%s) requested delayed status\n",
- __func__, intf, f->name);
- cdev->delayed_status++;
- DBG(cdev, "delayed_status count %d\n",
- cdev->delayed_status);
- }
- break;
- case USB_REQ_GET_INTERFACE:
- if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
- goto unknown;
- if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
- break;
- f = cdev->config->interface[intf];
- if (!f)
- break;
- /* lots of interfaces only need altsetting zero... */
- value = f->get_alt ? f->get_alt(f, w_index) : 0;
- if (value < 0)
- break;
- *((u8 *)req->buf) = value;
- value = min(w_length, (u16) 1);
- break;
-
- /*
- * USB 3.0 additions:
- * Function driver should handle get_status request. If such cb
- * wasn't supplied we respond with default value = 0
- * Note: function driver should supply such cb only for the first
- * interface of the function
- */
- case USB_REQ_GET_STATUS:
- if (!gadget_is_superspeed(gadget))
- goto unknown;
- if (ctrl->bRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE))
- goto unknown;
- value = 2; /* This is the length of the get_status reply */
- put_unaligned_le16(0, req->buf);
- if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
- break;
- f = cdev->config->interface[intf];
- if (!f)
- break;
- status = f->get_status ? f->get_status(f) : 0;
- if (status < 0)
- break;
- put_unaligned_le16(status & 0x0000ffff, req->buf);
- break;
- /*
- * Function drivers should handle SetFeature/ClearFeature
- * (FUNCTION_SUSPEND) request. function_suspend cb should be supplied
- * only for the first interface of the function
- */
- case USB_REQ_CLEAR_FEATURE:
- case USB_REQ_SET_FEATURE:
- if (!gadget_is_superspeed(gadget))
- goto unknown;
- if (ctrl->bRequestType != (USB_DIR_OUT | USB_RECIP_INTERFACE))
- goto unknown;
- switch (w_value) {
- case USB_INTRF_FUNC_SUSPEND:
- if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
- break;
- f = cdev->config->interface[intf];
- if (!f)
- break;
- value = 0;
- if (f->func_suspend)
- value = f->func_suspend(f, w_index >> 8);
- if (value < 0) {
- ERROR(cdev,
- "func_suspend() returned error %d\n",
- value);
- value = 0;
- }
- break;
- }
- break;
- default:
-unknown:
- VDBG(cdev,
- "non-core control req%02x.%02x v%04x i%04x l%d\n",
- ctrl->bRequestType, ctrl->bRequest,
- w_value, w_index, w_length);
-
- /* functions always handle their interfaces and endpoints...
- * punt other recipients (other, WUSB, ...) to the current
- * configuration code.
- *
- * REVISIT it could make sense to let the composite device
- * take such requests too, if that's ever needed: to work
- * in config 0, etc.
- */
- switch (ctrl->bRequestType & USB_RECIP_MASK) {
- case USB_RECIP_INTERFACE:
- if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
- break;
- f = cdev->config->interface[intf];
- break;
-
- case USB_RECIP_ENDPOINT:
- endp = ((w_index & 0x80) >> 3) | (w_index & 0x0f);
- list_for_each_entry(f, &cdev->config->functions, list) {
- if (test_bit(endp, f->endpoints))
- break;
- }
- if (&f->list == &cdev->config->functions)
- f = NULL;
- break;
- }
-
- if (f && f->setup)
- value = f->setup(f, ctrl);
- else {
- struct usb_configuration *c;
-
- c = cdev->config;
- if (c && c->setup)
- value = c->setup(c, ctrl);
- }
-
- goto done;
- }
-
- /* respond with data transfer before status phase? */
- if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) {
- req->length = value;
- req->zero = value < w_length;
- value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
- if (value < 0) {
- DBG(cdev, "ep_queue --> %d\n", value);
- req->status = 0;
- composite_setup_complete(gadget->ep0, req);
- }
- } else if (value == USB_GADGET_DELAYED_STATUS && w_length != 0) {
- WARN(cdev,
- "%s: Delayed status not supported for w_length != 0",
- __func__);
- }
-
-done:
- /* device either stalls (value < 0) or reports success */
- return value;
-}
-
-static void composite_disconnect(struct usb_gadget *gadget)
-{
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
- unsigned long flags;
-
- /* REVISIT: should we have config and device level
- * disconnect callbacks?
- */
- spin_lock_irqsave(&cdev->lock, flags);
- if (cdev->config)
- reset_config(cdev);
- if (composite->disconnect)
- composite->disconnect(cdev);
- spin_unlock_irqrestore(&cdev->lock, flags);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static ssize_t composite_show_suspended(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct usb_gadget *gadget = dev_to_usb_gadget(dev);
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
-
- return sprintf(buf, "%d\n", cdev->suspended);
-}
-
-static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL);
-
-static void
-composite_unbind(struct usb_gadget *gadget)
-{
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
-
- /* composite_disconnect() must already have been called
- * by the underlying peripheral controller driver!
- * so there's no i/o concurrency that could affect the
- * state protected by cdev->lock.
- */
- WARN_ON(cdev->config);
-
- while (!list_empty(&cdev->configs)) {
- struct usb_configuration *c;
- c = list_first_entry(&cdev->configs,
- struct usb_configuration, list);
- remove_config(cdev, c);
- }
- if (composite->unbind)
- composite->unbind(cdev);
-
- if (cdev->req) {
- kfree(cdev->req->buf);
- usb_ep_free_request(gadget->ep0, cdev->req);
- }
- device_remove_file(&gadget->dev, &dev_attr_suspended);
- kfree(cdev);
- set_gadget_data(gadget, NULL);
- composite = NULL;
-}
-
-static u8 override_id(struct usb_composite_dev *cdev, u8 *desc)
-{
- if (!*desc) {
- int ret = usb_string_id(cdev);
- if (unlikely(ret < 0))
- WARNING(cdev, "failed to override string ID\n");
- else
- *desc = ret;
- }
-
- return *desc;
-}
-
-static int composite_bind(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
-{
- struct usb_composite_dev *cdev;
- int status = -ENOMEM;
-
- cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
- if (!cdev)
- return status;
-
- spin_lock_init(&cdev->lock);
- cdev->gadget = gadget;
- set_gadget_data(gadget, cdev);
- INIT_LIST_HEAD(&cdev->configs);
-
- /* preallocate control response and buffer */
- cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
- if (!cdev->req)
- goto fail;
- cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
- if (!cdev->req->buf)
- goto fail;
- cdev->req->complete = composite_setup_complete;
- gadget->ep0->driver_data = cdev;
-
- cdev->bufsiz = USB_BUFSIZ;
- cdev->driver = composite;
-
- /*
- * As per USB compliance update, a device that is actively drawing
- * more than 100mA from USB must report itself as bus-powered in
- * the GetStatus(DEVICE) call.
- */
- if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW)
- usb_gadget_set_selfpowered(gadget);
-
- /* interface and string IDs start at zero via kzalloc.
- * we force endpoints to start unassigned; few controller
- * drivers will zero ep->driver_data.
- */
- usb_ep_autoconfig_reset(cdev->gadget);
-
- /* composite gadget needs to assign strings for whole device (like
- * serial number), register function drivers, potentially update
- * power state and consumption, etc
- */
- status = composite->bind(cdev);
- if (status < 0)
- goto fail;
-
- cdev->desc = *composite->dev;
-
- /* standardized runtime overrides for device ID data */
- if (idVendor)
- cdev->desc.idVendor = cpu_to_le16(idVendor);
- else
- idVendor = le16_to_cpu(cdev->desc.idVendor);
- if (idProduct)
- cdev->desc.idProduct = cpu_to_le16(idProduct);
- else
- idProduct = le16_to_cpu(cdev->desc.idProduct);
- if (bcdDevice)
- cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
- else
- bcdDevice = le16_to_cpu(cdev->desc.bcdDevice);
-
- /* string overrides */
- if (iManufacturer || !cdev->desc.iManufacturer) {
- if (!iManufacturer && !composite->iManufacturer &&
- !*composite_manufacturer)
- snprintf(composite_manufacturer,
- sizeof composite_manufacturer,
- "%s %s with %s",
- init_utsname()->sysname,
- init_utsname()->release,
- gadget->name);
-
- cdev->manufacturer_override =
- override_id(cdev, &cdev->desc.iManufacturer);
- }
-
- if (iProduct || (!cdev->desc.iProduct && composite->iProduct))
- cdev->product_override =
- override_id(cdev, &cdev->desc.iProduct);
-
- if (iSerialNumber ||
- (!cdev->desc.iSerialNumber && composite->iSerialNumber))
- cdev->serial_override =
- override_id(cdev, &cdev->desc.iSerialNumber);
-
- /* has userspace failed to provide a serial number? */
- if (composite->needs_serial && !cdev->desc.iSerialNumber)
- WARNING(cdev, "userspace failed to provide iSerialNumber\n");
-
- /* finish up */
- status = device_create_file(&gadget->dev, &dev_attr_suspended);
- if (status)
- goto fail;
-
- INFO(cdev, "%s ready\n", composite->name);
- return 0;
-
-fail:
- composite_unbind(gadget);
- return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-composite_suspend(struct usb_gadget *gadget)
-{
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
- struct usb_function *f;
-
- /* REVISIT: should we have config level
- * suspend/resume callbacks?
- */
- DBG(cdev, "suspend\n");
- if (cdev->config) {
- list_for_each_entry(f, &cdev->config->functions, list) {
- if (f->suspend)
- f->suspend(f);
- }
- }
- if (composite->suspend)
- composite->suspend(cdev);
-
- cdev->suspended = 1;
-
- usb_gadget_vbus_draw(gadget, 2);
-}
-
-static void
-composite_resume(struct usb_gadget *gadget)
-{
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
- struct usb_function *f;
- u8 maxpower;
-
- /* REVISIT: should we have config level
- * suspend/resume callbacks?
- */
- DBG(cdev, "resume\n");
- if (composite->resume)
- composite->resume(cdev);
- if (cdev->config) {
- list_for_each_entry(f, &cdev->config->functions, list) {
- if (f->resume)
- f->resume(f);
- }
-
- maxpower = cdev->config->bMaxPower;
-
- usb_gadget_vbus_draw(gadget, maxpower ?
- (2 * maxpower) : CONFIG_USB_GADGET_VBUS_DRAW);
- }
-
- cdev->suspended = 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver composite_driver = {
- .bind = composite_bind,
- .unbind = composite_unbind,
-
- .setup = composite_setup,
- .disconnect = composite_disconnect,
-
- .suspend = composite_suspend,
- .resume = composite_resume,
-
- .driver = {
- .owner = THIS_MODULE,
- },
-};
-
-/**
- * usb_composite_probe() - register a composite driver
- * @driver: the driver to register
- * @bind: the callback used to allocate resources that are shared across the
- * whole device, such as string IDs, and add its configurations using
- * @usb_add_config(). This may fail by returning a negative errno
- * value; it should return zero on successful initialization.
- * Context: single threaded during gadget setup
- *
- * This function is used to register drivers using the composite driver
- * framework. The return value is zero, or a negative errno value.
- * Those values normally come from the driver's @bind method, which does
- * all the work of setting up the driver to match the hardware.
- *
- * On successful return, the gadget is ready to respond to requests from
- * the host, unless one of its components invokes usb_gadget_disconnect()
- * while it was binding. That would usually be done in order to wait for
- * some userspace participation.
- */
-int usb_composite_probe(struct usb_composite_driver *driver)
-{
- if (!driver || !driver->dev || composite || !driver->bind)
- return -EINVAL;
-
- if (!driver->name)
- driver->name = "composite";
- if (!driver->iProduct)
- driver->iProduct = driver->name;
- composite_driver.function = (char *) driver->name;
- composite_driver.driver.name = driver->name;
- composite_driver.max_speed = driver->max_speed;
- composite = driver;
-
- return usb_gadget_probe_driver(&composite_driver);
-}
-
-/**
- * usb_composite_unregister() - unregister a composite driver
- * @driver: the driver to unregister
- *
- * This function is used to unregister drivers using the composite
- * driver framework.
- */
-void usb_composite_unregister(struct usb_composite_driver *driver)
-{
- if (composite != driver)
- return;
- usb_gadget_unregister_driver(&composite_driver);
-}
-
-/**
- * usb_composite_setup_continue() - Continue with the control transfer
- * @cdev: the composite device who's control transfer was kept waiting
- *
- * This function must be called by the USB function driver to continue
- * with the control transfer's data/status stage in case it had requested to
- * delay the data/status stages. A USB function's setup handler (e.g. set_alt())
- * can request the composite framework to delay the setup request's data/status
- * stages by returning USB_GADGET_DELAYED_STATUS.
- */
-void usb_composite_setup_continue(struct usb_composite_dev *cdev)
-{
- int value;
- struct usb_request *req = cdev->req;
- unsigned long flags;
-
- DBG(cdev, "%s\n", __func__);
- spin_lock_irqsave(&cdev->lock, flags);
-
- if (cdev->delayed_status == 0) {
- WARN(cdev, "%s: Unexpected call\n", __func__);
-
- } else if (--cdev->delayed_status == 0) {
- DBG(cdev, "%s: Completing delayed status\n", __func__);
- req->length = 0;
- value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
- if (value < 0) {
- DBG(cdev, "ep_queue --> %d\n", value);
- req->status = 0;
- composite_setup_complete(cdev->gadget->ep0, req);
- }
- }
-
- spin_unlock_irqrestore(&cdev->lock, flags);
-}
-
diff --git a/drivers/staging/ccg/composite.h b/drivers/staging/ccg/composite.h
deleted file mode 100644
index 19a5adf18bf..00000000000
--- a/drivers/staging/ccg/composite.h
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * composite.h -- framework for usb gadgets which are composite devices
- *
- * Copyright (C) 2006-2008 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef __LINUX_USB_COMPOSITE_H
-#define __LINUX_USB_COMPOSITE_H
-
-/*
- * This framework is an optional layer on top of the USB Gadget interface,
- * making it easier to build (a) Composite devices, supporting multiple
- * functions within any single configuration, and (b) Multi-configuration
- * devices, also supporting multiple functions but without necessarily
- * having more than one function per configuration.
- *
- * Example: a device with a single configuration supporting both network
- * link and mass storage functions is a composite device. Those functions
- * might alternatively be packaged in individual configurations, but in
- * the composite model the host can use both functions at the same time.
- */
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-/*
- * USB function drivers should return USB_GADGET_DELAYED_STATUS if they
- * wish to delay the data/status stages of the control transfer till they
- * are ready. The control transfer will then be kept from completing till
- * all the function drivers that requested for USB_GADGET_DELAYED_STAUS
- * invoke usb_composite_setup_continue().
- */
-#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */
-
-struct usb_configuration;
-
-/**
- * struct usb_function - describes one function of a configuration
- * @name: For diagnostics, identifies the function.
- * @strings: tables of strings, keyed by identifiers assigned during bind()
- * and by language IDs provided in control requests
- * @descriptors: Table of full (or low) speed descriptors, using interface and
- * string identifiers assigned during @bind(). If this pointer is null,
- * the function will not be available at full speed (or at low speed).
- * @hs_descriptors: Table of high speed descriptors, using interface and
- * string identifiers assigned during @bind(). If this pointer is null,
- * the function will not be available at high speed.
- * @ss_descriptors: Table of super speed descriptors, using interface and
- * string identifiers assigned during @bind(). If this
- * pointer is null after initiation, the function will not
- * be available at super speed.
- * @config: assigned when @usb_add_function() is called; this is the
- * configuration with which this function is associated.
- * @bind: Before the gadget can register, all of its functions bind() to the
- * available resources including string and interface identifiers used
- * in interface or class descriptors; endpoints; I/O buffers; and so on.
- * @unbind: Reverses @bind; called as a side effect of unregistering the
- * driver which added this function.
- * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
- * initialize usb_ep.driver data at this time (when it is used).
- * Note that setting an interface to its current altsetting resets
- * interface state, and that all interfaces have a disabled state.
- * @get_alt: Returns the active altsetting. If this is not provided,
- * then only altsetting zero is supported.
- * @disable: (REQUIRED) Indicates the function should be disabled. Reasons
- * include host resetting or reconfiguring the gadget, and disconnection.
- * @setup: Used for interface-specific control requests.
- * @suspend: Notifies functions when the host stops sending USB traffic.
- * @resume: Notifies functions when the host restarts USB traffic.
- * @get_status: Returns function status as a reply to
- * GetStatus() request when the recepient is Interface.
- * @func_suspend: callback to be called when
- * SetFeature(FUNCTION_SUSPEND) is reseived
- *
- * A single USB function uses one or more interfaces, and should in most
- * cases support operation at both full and high speeds. Each function is
- * associated by @usb_add_function() with a one configuration; that function
- * causes @bind() to be called so resources can be allocated as part of
- * setting up a gadget driver. Those resources include endpoints, which
- * should be allocated using @usb_ep_autoconfig().
- *
- * To support dual speed operation, a function driver provides descriptors
- * for both high and full speed operation. Except in rare cases that don't
- * involve bulk endpoints, each speed needs different endpoint descriptors.
- *
- * Function drivers choose their own strategies for managing instance data.
- * The simplest strategy just declares it "static', which means the function
- * can only be activated once. If the function needs to be exposed in more
- * than one configuration at a given speed, it needs to support multiple
- * usb_function structures (one for each configuration).
- *
- * A more complex strategy might encapsulate a @usb_function structure inside
- * a driver-specific instance structure to allows multiple activations. An
- * example of multiple activations might be a CDC ACM function that supports
- * two or more distinct instances within the same configuration, providing
- * several independent logical data links to a USB host.
- */
-struct usb_function {
- const char *name;
- struct usb_gadget_strings **strings;
- struct usb_descriptor_header **descriptors;
- struct usb_descriptor_header **hs_descriptors;
- struct usb_descriptor_header **ss_descriptors;
-
- struct usb_configuration *config;
-
- /* REVISIT: bind() functions can be marked __init, which
- * makes trouble for section mismatch analysis. See if
- * we can't restructure things to avoid mismatching.
- * Related: unbind() may kfree() but bind() won't...
- */
-
- /* configuration management: bind/unbind */
- int (*bind)(struct usb_configuration *,
- struct usb_function *);
- void (*unbind)(struct usb_configuration *,
- struct usb_function *);
-
- /* runtime state management */
- int (*set_alt)(struct usb_function *,
- unsigned interface, unsigned alt);
- int (*get_alt)(struct usb_function *,
- unsigned interface);
- void (*disable)(struct usb_function *);
- int (*setup)(struct usb_function *,
- const struct usb_ctrlrequest *);
- void (*suspend)(struct usb_function *);
- void (*resume)(struct usb_function *);
-
- /* USB 3.0 additions */
- int (*get_status)(struct usb_function *);
- int (*func_suspend)(struct usb_function *,
- u8 suspend_opt);
- /* private: */
- /* internals */
- struct list_head list;
- DECLARE_BITMAP(endpoints, 32);
-};
-
-int usb_add_function(struct usb_configuration *, struct usb_function *);
-
-int usb_function_deactivate(struct usb_function *);
-int usb_function_activate(struct usb_function *);
-
-int usb_interface_id(struct usb_configuration *, struct usb_function *);
-
-int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
- struct usb_ep *_ep);
-
-#define MAX_CONFIG_INTERFACES 16 /* arbitrary; max 255 */
-
-/**
- * struct usb_configuration - represents one gadget configuration
- * @label: For diagnostics, describes the configuration.
- * @strings: Tables of strings, keyed by identifiers assigned during @bind()
- * and by language IDs provided in control requests.
- * @descriptors: Table of descriptors preceding all function descriptors.
- * Examples include OTG and vendor-specific descriptors.
- * @unbind: Reverses @bind; called as a side effect of unregistering the
- * driver which added this configuration.
- * @setup: Used to delegate control requests that aren't handled by standard
- * device infrastructure or directed at a specific interface.
- * @bConfigurationValue: Copied into configuration descriptor.
- * @iConfiguration: Copied into configuration descriptor.
- * @bmAttributes: Copied into configuration descriptor.
- * @bMaxPower: Copied into configuration descriptor.
- * @cdev: assigned by @usb_add_config() before calling @bind(); this is
- * the device associated with this configuration.
- *
- * Configurations are building blocks for gadget drivers structured around
- * function drivers. Simple USB gadgets require only one function and one
- * configuration, and handle dual-speed hardware by always providing the same
- * functionality. Slightly more complex gadgets may have more than one
- * single-function configuration at a given speed; or have configurations
- * that only work at one speed.
- *
- * Composite devices are, by definition, ones with configurations which
- * include more than one function.
- *
- * The lifecycle of a usb_configuration includes allocation, initialization
- * of the fields described above, and calling @usb_add_config() to set up
- * internal data and bind it to a specific device. The configuration's
- * @bind() method is then used to initialize all the functions and then
- * call @usb_add_function() for them.
- *
- * Those functions would normally be independent of each other, but that's
- * not mandatory. CDC WMC devices are an example where functions often
- * depend on other functions, with some functions subsidiary to others.
- * Such interdependency may be managed in any way, so long as all of the
- * descriptors complete by the time the composite driver returns from
- * its bind() routine.
- */
-struct usb_configuration {
- const char *label;
- struct usb_gadget_strings **strings;
- const struct usb_descriptor_header **descriptors;
-
- /* REVISIT: bind() functions can be marked __init, which
- * makes trouble for section mismatch analysis. See if
- * we can't restructure things to avoid mismatching...
- */
-
- /* configuration management: unbind/setup */
- void (*unbind)(struct usb_configuration *);
- int (*setup)(struct usb_configuration *,
- const struct usb_ctrlrequest *);
-
- /* fields in the config descriptor */
- u8 bConfigurationValue;
- u8 iConfiguration;
- u8 bmAttributes;
- u8 bMaxPower;
-
- struct usb_composite_dev *cdev;
-
- /* private: */
- /* internals */
- struct list_head list;
- struct list_head functions;
- u8 next_interface_id;
- unsigned superspeed:1;
- unsigned highspeed:1;
- unsigned fullspeed:1;
- struct usb_function *interface[MAX_CONFIG_INTERFACES];
-};
-
-int usb_add_config(struct usb_composite_dev *,
- struct usb_configuration *,
- int (*)(struct usb_configuration *));
-
-void usb_remove_config(struct usb_composite_dev *,
- struct usb_configuration *);
-
-/**
- * struct usb_composite_driver - groups configurations into a gadget
- * @name: For diagnostics, identifies the driver.
- * @iProduct: Used as iProduct override if @dev->iProduct is not set.
- * If NULL value of @name is taken.
- * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is
- * not set. If NULL a default "<system> <release> with <udc>" value
- * will be used.
- * @iSerialNumber: Used as iSerialNumber override if @dev->iSerialNumber is
- * not set.
- * @dev: Template descriptor for the device, including default device
- * identifiers.
- * @strings: tables of strings, keyed by identifiers assigned during @bind
- * and language IDs provided in control requests
- * @max_speed: Highest speed the driver supports.
- * @needs_serial: set to 1 if the gadget needs userspace to provide
- * a serial number. If one is not provided, warning will be printed.
- * @bind: (REQUIRED) Used to allocate resources that are shared across the
- * whole device, such as string IDs, and add its configurations using
- * @usb_add_config(). This may fail by returning a negative errno
- * value; it should return zero on successful initialization.
- * @unbind: Reverses @bind; called as a side effect of unregistering
- * this driver.
- * @disconnect: optional driver disconnect method
- * @suspend: Notifies when the host stops sending USB traffic,
- * after function notifications
- * @resume: Notifies configuration when the host restarts USB traffic,
- * before function notifications
- *
- * Devices default to reporting self powered operation. Devices which rely
- * on bus powered operation should report this in their @bind method.
- *
- * Before returning from @bind, various fields in the template descriptor
- * may be overridden. These include the idVendor/idProduct/bcdDevice values
- * normally to bind the appropriate host side driver, and the three strings
- * (iManufacturer, iProduct, iSerialNumber) normally used to provide user
- * meaningful device identifiers. (The strings will not be defined unless
- * they are defined in @dev and @strings.) The correct ep0 maxpacket size
- * is also reported, as defined by the underlying controller driver.
- */
-struct usb_composite_driver {
- const char *name;
- const char *iProduct;
- const char *iManufacturer;
- const char *iSerialNumber;
- const struct usb_device_descriptor *dev;
- struct usb_gadget_strings **strings;
- enum usb_device_speed max_speed;
- unsigned needs_serial:1;
-
- int (*bind)(struct usb_composite_dev *cdev);
- int (*unbind)(struct usb_composite_dev *);
-
- void (*disconnect)(struct usb_composite_dev *);
-
- /* global suspend hooks */
- void (*suspend)(struct usb_composite_dev *);
- void (*resume)(struct usb_composite_dev *);
-};
-
-extern int usb_composite_probe(struct usb_composite_driver *driver);
-extern void usb_composite_unregister(struct usb_composite_driver *driver);
-extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
-
-
-/**
- * struct usb_composite_device - represents one composite usb gadget
- * @gadget: read-only, abstracts the gadget's usb peripheral controller
- * @req: used for control responses; buffer is pre-allocated
- * @bufsiz: size of buffer pre-allocated in @req
- * @config: the currently active configuration
- *
- * One of these devices is allocated and initialized before the
- * associated device driver's bind() is called.
- *
- * OPEN ISSUE: it appears that some WUSB devices will need to be
- * built by combining a normal (wired) gadget with a wireless one.
- * This revision of the gadget framework should probably try to make
- * sure doing that won't hurt too much.
- *
- * One notion for how to handle Wireless USB devices involves:
- * (a) a second gadget here, discovery mechanism TBD, but likely
- * needing separate "register/unregister WUSB gadget" calls;
- * (b) updates to usb_gadget to include flags "is it wireless",
- * "is it wired", plus (presumably in a wrapper structure)
- * bandgroup and PHY info;
- * (c) presumably a wireless_ep wrapping a usb_ep, and reporting
- * wireless-specific parameters like maxburst and maxsequence;
- * (d) configurations that are specific to wireless links;
- * (e) function drivers that understand wireless configs and will
- * support wireless for (additional) function instances;
- * (f) a function to support association setup (like CBAF), not
- * necessarily requiring a wireless adapter;
- * (g) composite device setup that can create one or more wireless
- * configs, including appropriate association setup support;
- * (h) more, TBD.
- */
-struct usb_composite_dev {
- struct usb_gadget *gadget;
- struct usb_request *req;
- unsigned bufsiz;
-
- struct usb_configuration *config;
-
- /* private: */
- /* internals */
- unsigned int suspended:1;
- struct usb_device_descriptor desc;
- struct list_head configs;
- struct usb_composite_driver *driver;
- u8 next_string_id;
- u8 manufacturer_override;
- u8 product_override;
- u8 serial_override;
-
- /* the gadget driver won't enable the data pullup
- * while the deactivation count is nonzero.
- */
- unsigned deactivations;
-
- /* the composite driver won't complete the control transfer's
- * data/status stages till delayed_status is zero.
- */
- int delayed_status;
-
- /* protects deactivations and delayed_status counts*/
- spinlock_t lock;
-};
-
-extern int usb_string_id(struct usb_composite_dev *c);
-extern int usb_string_ids_tab(struct usb_composite_dev *c,
- struct usb_string *str);
-extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
-
-
-/* messaging utils */
-#define DBG(d, fmt, args...) \
- dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...) \
- dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...) \
- dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARNING(d, fmt, args...) \
- dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...) \
- dev_info(&(d)->gadget->dev , fmt , ## args)
-
-#endif /* __LINUX_USB_COMPOSITE_H */
diff --git a/drivers/staging/ccg/config.c b/drivers/staging/ccg/config.c
deleted file mode 100644
index 7542a72ce51..00000000000
--- a/drivers/staging/ccg/config.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * usb/gadget/config.c -- simplify building config descriptors
- *
- * Copyright (C) 2003 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/string.h>
-#include <linux/device.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-
-/**
- * usb_descriptor_fillbuf - fill buffer with descriptors
- * @buf: Buffer to be filled
- * @buflen: Size of buf
- * @src: Array of descriptor pointers, terminated by null pointer.
- *
- * Copies descriptors into the buffer, returning the length or a
- * negative error code if they can't all be copied. Useful when
- * assembling descriptors for an associated set of interfaces used
- * as part of configuring a composite device; or in other cases where
- * sets of descriptors need to be marshaled.
- */
-int
-usb_descriptor_fillbuf(void *buf, unsigned buflen,
- const struct usb_descriptor_header **src)
-{
- u8 *dest = buf;
-
- if (!src)
- return -EINVAL;
-
- /* fill buffer from src[] until null descriptor ptr */
- for (; NULL != *src; src++) {
- unsigned len = (*src)->bLength;
-
- if (len > buflen)
- return -EINVAL;
- memcpy(dest, *src, len);
- buflen -= len;
- dest += len;
- }
- return dest - (u8 *)buf;
-}
-
-
-/**
- * usb_gadget_config_buf - builts a complete configuration descriptor
- * @config: Header for the descriptor, including characteristics such
- * as power requirements and number of interfaces.
- * @desc: Null-terminated vector of pointers to the descriptors (interface,
- * endpoint, etc) defining all functions in this device configuration.
- * @buf: Buffer for the resulting configuration descriptor.
- * @length: Length of buffer. If this is not big enough to hold the
- * entire configuration descriptor, an error code will be returned.
- *
- * This copies descriptors into the response buffer, building a descriptor
- * for that configuration. It returns the buffer length or a negative
- * status code. The config.wTotalLength field is set to match the length
- * of the result, but other descriptor fields (including power usage and
- * interface count) must be set by the caller.
- *
- * Gadget drivers could use this when constructing a config descriptor
- * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the
- * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
- */
-int usb_gadget_config_buf(
- const struct usb_config_descriptor *config,
- void *buf,
- unsigned length,
- const struct usb_descriptor_header **desc
-)
-{
- struct usb_config_descriptor *cp = buf;
- int len;
-
- /* config descriptor first */
- if (length < USB_DT_CONFIG_SIZE || !desc)
- return -EINVAL;
- *cp = *config;
-
- /* then interface/endpoint/class/vendor/... */
- len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
- length - USB_DT_CONFIG_SIZE, desc);
- if (len < 0)
- return len;
- len += USB_DT_CONFIG_SIZE;
- if (len > 0xffff)
- return -EINVAL;
-
- /* patch up the config descriptor */
- cp->bLength = USB_DT_CONFIG_SIZE;
- cp->bDescriptorType = USB_DT_CONFIG;
- cp->wTotalLength = cpu_to_le16(len);
- cp->bmAttributes |= USB_CONFIG_ATT_ONE;
- return len;
-}
-
-/**
- * usb_copy_descriptors - copy a vector of USB descriptors
- * @src: null-terminated vector to copy
- * Context: initialization code, which may sleep
- *
- * This makes a copy of a vector of USB descriptors. Its primary use
- * is to support usb_function objects which can have multiple copies,
- * each needing different descriptors. Functions may have static
- * tables of descriptors, which are used as templates and customized
- * with identifiers (for interfaces, strings, endpoints, and more)
- * as needed by a given function instance.
- */
-struct usb_descriptor_header **
-usb_copy_descriptors(struct usb_descriptor_header **src)
-{
- struct usb_descriptor_header **tmp;
- unsigned bytes;
- unsigned n_desc;
- void *mem;
- struct usb_descriptor_header **ret;
-
- /* count descriptors and their sizes; then add vector size */
- for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++)
- bytes += (*tmp)->bLength;
- bytes += (n_desc + 1) * sizeof(*tmp);
-
- mem = kmalloc(bytes, GFP_KERNEL);
- if (!mem)
- return NULL;
-
- /* fill in pointers starting at "tmp",
- * to descriptors copied starting at "mem";
- * and return "ret"
- */
- tmp = mem;
- ret = mem;
- mem += (n_desc + 1) * sizeof(*tmp);
- while (*src) {
- memcpy(mem, *src, (*src)->bLength);
- *tmp = mem;
- tmp++;
- mem += (*src)->bLength;
- src++;
- }
- *tmp = NULL;
-
- return ret;
-}
-
diff --git a/drivers/staging/ccg/epautoconf.c b/drivers/staging/ccg/epautoconf.c
deleted file mode 100644
index 51f3d42f5a6..00000000000
--- a/drivers/staging/ccg/epautoconf.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers
- *
- * Copyright (C) 2004 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-
-#include <linux/ctype.h>
-#include <linux/string.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "gadget_chips.h"
-
-
-/* we must assign addresses for configurable endpoints (like net2280) */
-static unsigned epnum;
-
-// #define MANY_ENDPOINTS
-#ifdef MANY_ENDPOINTS
-/* more than 15 configurable endpoints */
-static unsigned in_epnum;
-#endif
-
-
-/*
- * This should work with endpoints from controller drivers sharing the
- * same endpoint naming convention. By example:
- *
- * - ep1, ep2, ... address is fixed, not direction or type
- * - ep1in, ep2out, ... address and direction are fixed, not type
- * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
- * - ep1in-bulk, ep2out-iso, ... all three are fixed
- * - ep-* ... no functionality restrictions
- *
- * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
- * Less common restrictions are implied by gadget_is_*().
- *
- * NOTE: each endpoint is unidirectional, as specified by its USB
- * descriptor; and isn't specific to a configuration or altsetting.
- */
-static int
-ep_matches (
- struct usb_gadget *gadget,
- struct usb_ep *ep,
- struct usb_endpoint_descriptor *desc,
- struct usb_ss_ep_comp_descriptor *ep_comp
-)
-{
- u8 type;
- const char *tmp;
- u16 max;
-
- int num_req_streams = 0;
-
- /* endpoint already claimed? */
- if (NULL != ep->driver_data)
- return 0;
-
- /* only support ep0 for portable CONTROL traffic */
- type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
- if (USB_ENDPOINT_XFER_CONTROL == type)
- return 0;
-
- /* some other naming convention */
- if ('e' != ep->name[0])
- return 0;
-
- /* type-restriction: "-iso", "-bulk", or "-int".
- * direction-restriction: "in", "out".
- */
- if ('-' != ep->name[2]) {
- tmp = strrchr (ep->name, '-');
- if (tmp) {
- switch (type) {
- case USB_ENDPOINT_XFER_INT:
- /* bulk endpoints handle interrupt transfers,
- * except the toggle-quirky iso-synch kind
- */
- if ('s' == tmp[2]) // == "-iso"
- return 0;
- /* for now, avoid PXA "interrupt-in";
- * it's documented as never using DATA1.
- */
- if (gadget_is_pxa (gadget)
- && 'i' == tmp [1])
- return 0;
- break;
- case USB_ENDPOINT_XFER_BULK:
- if ('b' != tmp[1]) // != "-bulk"
- return 0;
- break;
- case USB_ENDPOINT_XFER_ISOC:
- if ('s' != tmp[2]) // != "-iso"
- return 0;
- }
- } else {
- tmp = ep->name + strlen (ep->name);
- }
-
- /* direction-restriction: "..in-..", "out-.." */
- tmp--;
- if (!isdigit (*tmp)) {
- if (desc->bEndpointAddress & USB_DIR_IN) {
- if ('n' != *tmp)
- return 0;
- } else {
- if ('t' != *tmp)
- return 0;
- }
- }
- }
-
- /*
- * Get the number of required streams from the EP companion
- * descriptor and see if the EP matches it
- */
- if (usb_endpoint_xfer_bulk(desc)) {
- if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
- num_req_streams = ep_comp->bmAttributes & 0x1f;
- if (num_req_streams > ep->max_streams)
- return 0;
- }
-
- }
-
- /*
- * If the protocol driver hasn't yet decided on wMaxPacketSize
- * and wants to know the maximum possible, provide the info.
- */
- if (desc->wMaxPacketSize == 0)
- desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket);
-
- /* endpoint maxpacket size is an input parameter, except for bulk
- * where it's an output parameter representing the full speed limit.
- * the usb spec fixes high speed bulk maxpacket at 512 bytes.
- */
- max = 0x7ff & usb_endpoint_maxp(desc);
- switch (type) {
- case USB_ENDPOINT_XFER_INT:
- /* INT: limit 64 bytes full speed, 1024 high/super speed */
- if (!gadget_is_dualspeed(gadget) && max > 64)
- return 0;
- /* FALLTHROUGH */
-
- case USB_ENDPOINT_XFER_ISOC:
- /* ISO: limit 1023 bytes full speed, 1024 high/super speed */
- if (ep->maxpacket < max)
- return 0;
- if (!gadget_is_dualspeed(gadget) && max > 1023)
- return 0;
-
- /* BOTH: "high bandwidth" works only at high speed */
- if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
- if (!gadget_is_dualspeed(gadget))
- return 0;
- /* configure your hardware with enough buffering!! */
- }
- break;
- }
-
- /* MATCH!! */
-
- /* report address */
- desc->bEndpointAddress &= USB_DIR_IN;
- if (isdigit (ep->name [2])) {
- u8 num = simple_strtoul (&ep->name [2], NULL, 10);
- desc->bEndpointAddress |= num;
-#ifdef MANY_ENDPOINTS
- } else if (desc->bEndpointAddress & USB_DIR_IN) {
- if (++in_epnum > 15)
- return 0;
- desc->bEndpointAddress = USB_DIR_IN | in_epnum;
-#endif
- } else {
- if (++epnum > 15)
- return 0;
- desc->bEndpointAddress |= epnum;
- }
-
- /* report (variable) full speed bulk maxpacket */
- if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
- int size = ep->maxpacket;
-
- /* min() doesn't work on bitfields with gcc-3.5 */
- if (size > 64)
- size = 64;
- desc->wMaxPacketSize = cpu_to_le16(size);
- }
- ep->address = desc->bEndpointAddress;
- return 1;
-}
-
-static struct usb_ep *
-find_ep (struct usb_gadget *gadget, const char *name)
-{
- struct usb_ep *ep;
-
- list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- if (0 == strcmp (ep->name, name))
- return ep;
- }
- return NULL;
-}
-
-/**
- * usb_ep_autoconfig_ss() - choose an endpoint matching the ep
- * descriptor and ep companion descriptor
- * @gadget: The device to which the endpoint must belong.
- * @desc: Endpoint descriptor, with endpoint direction and transfer mode
- * initialized. For periodic transfers, the maximum packet
- * size must also be initialized. This is modified on
- * success.
- * @ep_comp: Endpoint companion descriptor, with the required
- * number of streams. Will be modified when the chosen EP
- * supports a different number of streams.
- *
- * This routine replaces the usb_ep_autoconfig when needed
- * superspeed enhancments. If such enhancemnets are required,
- * the FD should call usb_ep_autoconfig_ss directly and provide
- * the additional ep_comp parameter.
- *
- * By choosing an endpoint to use with the specified descriptor,
- * this routine simplifies writing gadget drivers that work with
- * multiple USB device controllers. The endpoint would be
- * passed later to usb_ep_enable(), along with some descriptor.
- *
- * That second descriptor won't always be the same as the first one.
- * For example, isochronous endpoints can be autoconfigured for high
- * bandwidth, and then used in several lower bandwidth altsettings.
- * Also, high and full speed descriptors will be different.
- *
- * Be sure to examine and test the results of autoconfiguration
- * on your hardware. This code may not make the best choices
- * about how to use the USB controller, and it can't know all
- * the restrictions that may apply. Some combinations of driver
- * and hardware won't be able to autoconfigure.
- *
- * On success, this returns an un-claimed usb_ep, and modifies the endpoint
- * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
- * is initialized as if the endpoint were used at full speed and
- * the bmAttribute field in the ep companion descriptor is
- * updated with the assigned number of streams if it is
- * different from the original value. To prevent the endpoint
- * from being returned by a later autoconfig call, claim it by
- * assigning ep->driver_data to some non-null value.
- *
- * On failure, this returns a null endpoint descriptor.
- */
-struct usb_ep *usb_ep_autoconfig_ss(
- struct usb_gadget *gadget,
- struct usb_endpoint_descriptor *desc,
- struct usb_ss_ep_comp_descriptor *ep_comp
-)
-{
- struct usb_ep *ep;
- u8 type;
-
- type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-
- /* First, apply chip-specific "best usage" knowledge.
- * This might make a good usb_gadget_ops hook ...
- */
- if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
- /* ep-e, ep-f are PIO with only 64 byte fifos */
- ep = find_ep (gadget, "ep-e");
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
- ep = find_ep (gadget, "ep-f");
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
-
- } else if (gadget_is_goku (gadget)) {
- if (USB_ENDPOINT_XFER_INT == type) {
- /* single buffering is enough */
- ep = find_ep(gadget, "ep3-bulk");
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
- } else if (USB_ENDPOINT_XFER_BULK == type
- && (USB_DIR_IN & desc->bEndpointAddress)) {
- /* DMA may be available */
- ep = find_ep(gadget, "ep2-bulk");
- if (ep && ep_matches(gadget, ep, desc,
- ep_comp))
- goto found_ep;
- }
-
-#ifdef CONFIG_BLACKFIN
- } else if (gadget_is_musbhdrc(gadget)) {
- if ((USB_ENDPOINT_XFER_BULK == type) ||
- (USB_ENDPOINT_XFER_ISOC == type)) {
- if (USB_DIR_IN & desc->bEndpointAddress)
- ep = find_ep (gadget, "ep5in");
- else
- ep = find_ep (gadget, "ep6out");
- } else if (USB_ENDPOINT_XFER_INT == type) {
- if (USB_DIR_IN & desc->bEndpointAddress)
- ep = find_ep(gadget, "ep1in");
- else
- ep = find_ep(gadget, "ep2out");
- } else
- ep = NULL;
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
-#endif
- }
-
- /* Second, look at endpoints until an unclaimed one looks usable */
- list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- if (ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
- }
-
- /* Fail */
- return NULL;
-found_ep:
- ep->desc = NULL;
- ep->comp_desc = NULL;
- return ep;
-}
-
-/**
- * usb_ep_autoconfig() - choose an endpoint matching the
- * descriptor
- * @gadget: The device to which the endpoint must belong.
- * @desc: Endpoint descriptor, with endpoint direction and transfer mode
- * initialized. For periodic transfers, the maximum packet
- * size must also be initialized. This is modified on success.
- *
- * By choosing an endpoint to use with the specified descriptor, this
- * routine simplifies writing gadget drivers that work with multiple
- * USB device controllers. The endpoint would be passed later to
- * usb_ep_enable(), along with some descriptor.
- *
- * That second descriptor won't always be the same as the first one.
- * For example, isochronous endpoints can be autoconfigured for high
- * bandwidth, and then used in several lower bandwidth altsettings.
- * Also, high and full speed descriptors will be different.
- *
- * Be sure to examine and test the results of autoconfiguration on your
- * hardware. This code may not make the best choices about how to use the
- * USB controller, and it can't know all the restrictions that may apply.
- * Some combinations of driver and hardware won't be able to autoconfigure.
- *
- * On success, this returns an un-claimed usb_ep, and modifies the endpoint
- * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
- * is initialized as if the endpoint were used at full speed. To prevent
- * the endpoint from being returned by a later autoconfig call, claim it
- * by assigning ep->driver_data to some non-null value.
- *
- * On failure, this returns a null endpoint descriptor.
- */
-struct usb_ep *usb_ep_autoconfig(
- struct usb_gadget *gadget,
- struct usb_endpoint_descriptor *desc
-)
-{
- return usb_ep_autoconfig_ss(gadget, desc, NULL);
-}
-
-
-/**
- * usb_ep_autoconfig_reset - reset endpoint autoconfig state
- * @gadget: device for which autoconfig state will be reset
- *
- * Use this for devices where one configuration may need to assign
- * endpoint resources very differently from the next one. It clears
- * state such as ep->driver_data and the record of assigned endpoints
- * used by usb_ep_autoconfig().
- */
-void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
-{
- struct usb_ep *ep;
-
- list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- ep->driver_data = NULL;
- }
-#ifdef MANY_ENDPOINTS
- in_epnum = 0;
-#endif
- epnum = 0;
-}
-
diff --git a/drivers/staging/ccg/f_acm.c b/drivers/staging/ccg/f_acm.c
deleted file mode 100644
index d672250a61f..00000000000
--- a/drivers/staging/ccg/f_acm.c
+++ /dev/null
@@ -1,814 +0,0 @@
-/*
- * f_acm.c -- USB CDC serial (ACM) function driver
- *
- * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
- * Copyright (C) 2008 by David Brownell
- * Copyright (C) 2008 by Nokia Corporation
- * Copyright (C) 2009 by Samsung Electronics
- * Author: Michal Nazarewicz (mina86@mina86.com)
- *
- * This software is distributed under the terms of the GNU General
- * Public License ("GPL") as published by the Free Software Foundation,
- * either version 2 of that License or (at your option) any later version.
- */
-
-/* #define VERBOSE_DEBUG */
-
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-
-#include "u_serial.h"
-#include "gadget_chips.h"
-
-
-/*
- * This CDC ACM function support just wraps control functions and
- * notifications around the generic serial-over-usb code.
- *
- * Because CDC ACM is standardized by the USB-IF, many host operating
- * systems have drivers for it. Accordingly, ACM is the preferred
- * interop solution for serial-port type connections. The control
- * models are often not necessary, and in any case don't do much in
- * this bare-bones implementation.
- *
- * Note that even MS-Windows has some support for ACM. However, that
- * support is somewhat broken because when you use ACM in a composite
- * device, having multiple interfaces confuses the poor OS. It doesn't
- * seem to understand CDC Union descriptors. The new "association"
- * descriptors (roughly equivalent to CDC Unions) may sometimes help.
- */
-
-struct f_acm {
- struct gserial port;
- u8 ctrl_id, data_id;
- u8 port_num;
-
- u8 pending;
-
- /* lock is mostly for pending and notify_req ... they get accessed
- * by callbacks both from tty (open/close/break) under its spinlock,
- * and notify_req.complete() which can't use that lock.
- */
- spinlock_t lock;
-
- struct usb_ep *notify;
- struct usb_request *notify_req;
-
- struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
-
- /* SetControlLineState request -- CDC 1.1 section 6.2.14 (INPUT) */
- u16 port_handshake_bits;
-#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
-#define ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */
-
- /* SerialState notification -- CDC 1.1 section 6.3.5 (OUTPUT) */
- u16 serial_state;
-#define ACM_CTRL_OVERRUN (1 << 6)
-#define ACM_CTRL_PARITY (1 << 5)
-#define ACM_CTRL_FRAMING (1 << 4)
-#define ACM_CTRL_RI (1 << 3)
-#define ACM_CTRL_BRK (1 << 2)
-#define ACM_CTRL_DSR (1 << 1)
-#define ACM_CTRL_DCD (1 << 0)
-};
-
-static inline struct f_acm *func_to_acm(struct usb_function *f)
-{
- return container_of(f, struct f_acm, port.func);
-}
-
-static inline struct f_acm *port_to_acm(struct gserial *p)
-{
- return container_of(p, struct f_acm, port);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* notification endpoint uses smallish and infrequent fixed-size messages */
-
-#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
-#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
-
-/* interface and class descriptors: */
-
-static struct usb_interface_assoc_descriptor
-acm_iad_descriptor = {
- .bLength = sizeof acm_iad_descriptor,
- .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
-
- /* .bFirstInterface = DYNAMIC, */
- .bInterfaceCount = 2, // control + data
- .bFunctionClass = USB_CLASS_COMM,
- .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
- .bFunctionProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
- /* .iFunction = DYNAMIC */
-};
-
-
-static struct usb_interface_descriptor acm_control_interface_desc = {
- .bLength = USB_DT_INTERFACE_SIZE,
- .bDescriptorType = USB_DT_INTERFACE,
- /* .bInterfaceNumber = DYNAMIC */
- .bNumEndpoints = 1,
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
- .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
- /* .iInterface = DYNAMIC */
-};
-
-static struct usb_interface_descriptor acm_data_interface_desc = {
- .bLength = USB_DT_INTERFACE_SIZE,
- .bDescriptorType = USB_DT_INTERFACE,
- /* .bInterfaceNumber = DYNAMIC */
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_CDC_DATA,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
- /* .iInterface = DYNAMIC */
-};
-
-static struct usb_cdc_header_desc acm_header_desc = {
- .bLength = sizeof(acm_header_desc),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_HEADER_TYPE,
- .bcdCDC = cpu_to_le16(0x0110),
-};
-
-static struct usb_cdc_call_mgmt_descriptor
-acm_call_mgmt_descriptor = {
- .bLength = sizeof(acm_call_mgmt_descriptor),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
- .bmCapabilities = 0,
- /* .bDataInterface = DYNAMIC */
-};
-
-static struct usb_cdc_acm_descriptor acm_descriptor = {
- .bLength = sizeof(acm_descriptor),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_ACM_TYPE,
- .bmCapabilities = USB_CDC_CAP_LINE,
-};
-
-static struct usb_cdc_union_desc acm_union_desc = {
- .bLength = sizeof(acm_union_desc),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_UNION_TYPE,
- /* .bMasterInterface0 = DYNAMIC */
- /* .bSlaveInterface0 = DYNAMIC */
-};
-
-/* full speed support: */
-
-static struct usb_endpoint_descriptor acm_fs_notify_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
- .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
-};
-
-static struct usb_endpoint_descriptor acm_fs_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor acm_fs_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_descriptor_header *acm_fs_function[] = {
- (struct usb_descriptor_header *) &acm_iad_descriptor,
- (struct usb_descriptor_header *) &acm_control_interface_desc,
- (struct usb_descriptor_header *) &acm_header_desc,
- (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
- (struct usb_descriptor_header *) &acm_descriptor,
- (struct usb_descriptor_header *) &acm_union_desc,
- (struct usb_descriptor_header *) &acm_fs_notify_desc,
- (struct usb_descriptor_header *) &acm_data_interface_desc,
- (struct usb_descriptor_header *) &acm_fs_in_desc,
- (struct usb_descriptor_header *) &acm_fs_out_desc,
- NULL,
-};
-
-/* high speed support: */
-
-static struct usb_endpoint_descriptor acm_hs_notify_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
- .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
-};
-
-static struct usb_endpoint_descriptor acm_hs_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor acm_hs_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(512),
-};
-
-static struct usb_descriptor_header *acm_hs_function[] = {
- (struct usb_descriptor_header *) &acm_iad_descriptor,
- (struct usb_descriptor_header *) &acm_control_interface_desc,
- (struct usb_descriptor_header *) &acm_header_desc,
- (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
- (struct usb_descriptor_header *) &acm_descriptor,
- (struct usb_descriptor_header *) &acm_union_desc,
- (struct usb_descriptor_header *) &acm_hs_notify_desc,
- (struct usb_descriptor_header *) &acm_data_interface_desc,
- (struct usb_descriptor_header *) &acm_hs_in_desc,
- (struct usb_descriptor_header *) &acm_hs_out_desc,
- NULL,
-};
-
-static struct usb_endpoint_descriptor acm_ss_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(1024),
-};
-
-static struct usb_endpoint_descriptor acm_ss_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(1024),
-};
-
-static struct usb_ss_ep_comp_descriptor acm_ss_bulk_comp_desc = {
- .bLength = sizeof acm_ss_bulk_comp_desc,
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
-};
-
-static struct usb_descriptor_header *acm_ss_function[] = {
- (struct usb_descriptor_header *) &acm_iad_descriptor,
- (struct usb_descriptor_header *) &acm_control_interface_desc,
- (struct usb_descriptor_header *) &acm_header_desc,
- (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
- (struct usb_descriptor_header *) &acm_descriptor,
- (struct usb_descriptor_header *) &acm_union_desc,
- (struct usb_descriptor_header *) &acm_hs_notify_desc,
- (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
- (struct usb_descriptor_header *) &acm_data_interface_desc,
- (struct usb_descriptor_header *) &acm_ss_in_desc,
- (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
- (struct usb_descriptor_header *) &acm_ss_out_desc,
- (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
- NULL,
-};
-
-/* string descriptors: */
-
-#define ACM_CTRL_IDX 0
-#define ACM_DATA_IDX 1
-#define ACM_IAD_IDX 2
-
-/* static strings, in UTF-8 */
-static struct usb_string acm_string_defs[] = {
- [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
- [ACM_DATA_IDX].s = "CDC ACM Data",
- [ACM_IAD_IDX ].s = "CDC Serial",
- { /* ZEROES END LIST */ },
-};
-
-static struct usb_gadget_strings acm_string_table = {
- .language = 0x0409, /* en-us */
- .strings = acm_string_defs,
-};
-
-static struct usb_gadget_strings *acm_strings[] = {
- &acm_string_table,
- NULL,
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* ACM control ... data handling is delegated to tty library code.
- * The main task of this function is to activate and deactivate
- * that code based on device state; track parameters like line
- * speed, handshake state, and so on; and issue notifications.
- */
-
-static void acm_complete_set_line_coding(struct usb_ep *ep,
- struct usb_request *req)
-{
- struct f_acm *acm = ep->driver_data;
- struct usb_composite_dev *cdev = acm->port.func.config->cdev;
-
- if (req->status != 0) {
- DBG(cdev, "acm ttyGS%d completion, err %d\n",
- acm->port_num, req->status);
- return;
- }
-
- /* normal completion */
- if (req->actual != sizeof(acm->port_line_coding)) {
- DBG(cdev, "acm ttyGS%d short resp, len %d\n",
- acm->port_num, req->actual);
- usb_ep_set_halt(ep);
- } else {
- struct usb_cdc_line_coding *value = req->buf;
-
- /* REVISIT: we currently just remember this data.
- * If we change that, (a) validate it first, then
- * (b) update whatever hardware needs updating,
- * (c) worry about locking. This is information on
- * the order of 9600-8-N-1 ... most of which means
- * nothing unless we control a real RS232 line.
- */
- acm->port_line_coding = *value;
- }
-}
-
-static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
-{
- struct f_acm *acm = func_to_acm(f);
- struct usb_composite_dev *cdev = f->config->cdev;
- struct usb_request *req = cdev->req;
- int value = -EOPNOTSUPP;
- u16 w_index = le16_to_cpu(ctrl->wIndex);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u16 w_length = le16_to_cpu(ctrl->wLength);
-
- /* composite driver infrastructure handles everything except
- * CDC class messages; interface activation uses set_alt().
- *
- * Note CDC spec table 4 lists the ACM request profile. It requires
- * encapsulated command support ... we don't handle any, and respond
- * to them by stalling. Options include get/set/clear comm features
- * (not that useful) and SEND_BREAK.
- */
- switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
-
- /* SET_LINE_CODING ... just read and save what the host sends */
- case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
- | USB_CDC_REQ_SET_LINE_CODING:
- if (w_length != sizeof(struct usb_cdc_line_coding)
- || w_index != acm->ctrl_id)
- goto invalid;
-
- value = w_length;
- cdev->gadget->ep0->driver_data = acm;
- req->complete = acm_complete_set_line_coding;
- break;
-
- /* GET_LINE_CODING ... return what host sent, or initial value */
- case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
- | USB_CDC_REQ_GET_LINE_CODING:
- if (w_index != acm->ctrl_id)
- goto invalid;
-
- value = min_t(unsigned, w_length,
- sizeof(struct usb_cdc_line_coding));
- memcpy(req->buf, &acm->port_line_coding, value);
- break;
-
- /* SET_CONTROL_LINE_STATE ... save what the host sent */
- case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
- | USB_CDC_REQ_SET_CONTROL_LINE_STATE:
- if (w_index != acm->ctrl_id)
- goto invalid;
-
- value = 0;
-
- /* FIXME we should not allow data to flow until the
- * host sets the ACM_CTRL_DTR bit; and when it clears
- * that bit, we should return to that no-flow state.
- */
- acm->port_handshake_bits = w_value;
- break;
-
- default:
-invalid:
- VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
- ctrl->bRequestType, ctrl->bRequest,
- w_value, w_index, w_length);
- }
-
- /* respond with data transfer or status phase? */
- if (value >= 0) {
- DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
- acm->port_num, ctrl->bRequestType, ctrl->bRequest,
- w_value, w_index, w_length);
- req->zero = 0;
- req->length = value;
- value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
- if (value < 0)
- ERROR(cdev, "acm response on ttyGS%d, err %d\n",
- acm->port_num, value);
- }
-
- /* device either stalls (value < 0) or reports success */
- return value;
-}
-
-static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
-{
- struct f_acm *acm = func_to_acm(f);
- struct usb_composite_dev *cdev = f->config->cdev;
-
- /* we know alt == 0, so this is an activation or a reset */
-
- if (intf == acm->ctrl_id) {
- if (acm->notify->driver_data) {
- VDBG(cdev, "reset acm control interface %d\n", intf);
- usb_ep_disable(acm->notify);
- } else {
- VDBG(cdev, "init acm ctrl interface %d\n", intf);
- if (config_ep_by_speed(cdev->gadget, f, acm->notify))
- return -EINVAL;
- }
- usb_ep_enable(acm->notify);
- acm->notify->driver_data = acm;
-
- } else if (intf == acm->data_id) {
- if (acm->port.in->driver_data) {
- DBG(cdev, "reset acm ttyGS%d\n", acm->port_num);
- gserial_disconnect(&acm->port);
- }
- if (!acm->port.in->desc || !acm->port.out->desc) {
- DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
- if (config_ep_by_speed(cdev->gadget, f,
- acm->port.in) ||
- config_ep_by_speed(cdev->gadget, f,
- acm->port.out)) {
- acm->port.in->desc = NULL;
- acm->port.out->desc = NULL;
- return -EINVAL;
- }
- }
- gserial_connect(&acm->port, acm->port_num);
-
- } else
- return -EINVAL;
-
- return 0;
-}
-
-static void acm_disable(struct usb_function *f)
-{
- struct f_acm *acm = func_to_acm(f);
- struct usb_composite_dev *cdev = f->config->cdev;
-
- DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
- gserial_disconnect(&acm->port);
- usb_ep_disable(acm->notify);
- acm->notify->driver_data = NULL;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/**
- * acm_cdc_notify - issue CDC notification to host
- * @acm: wraps host to be notified
- * @type: notification type
- * @value: Refer to cdc specs, wValue field.
- * @data: data to be sent
- * @length: size of data
- * Context: irqs blocked, acm->lock held, acm_notify_req non-null
- *
- * Returns zero on success or a negative errno.
- *
- * See section 6.3.5 of the CDC 1.1 specification for information
- * about the only notification we issue: SerialState change.
- */
-static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
- void *data, unsigned length)
-{
- struct usb_ep *ep = acm->notify;
- struct usb_request *req;
- struct usb_cdc_notification *notify;
- const unsigned len = sizeof(*notify) + length;
- void *buf;
- int status;
-
- req = acm->notify_req;
- acm->notify_req = NULL;
- acm->pending = false;
-
- req->length = len;
- notify = req->buf;
- buf = notify + 1;
-
- notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
- | USB_RECIP_INTERFACE;
- notify->bNotificationType = type;
- notify->wValue = cpu_to_le16(value);
- notify->wIndex = cpu_to_le16(acm->ctrl_id);
- notify->wLength = cpu_to_le16(length);
- memcpy(buf, data, length);
-
- /* ep_queue() can complete immediately if it fills the fifo... */
- spin_unlock(&acm->lock);
- status = usb_ep_queue(ep, req, GFP_ATOMIC);
- spin_lock(&acm->lock);
-
- if (status < 0) {
- ERROR(acm->port.func.config->cdev,
- "acm ttyGS%d can't notify serial state, %d\n",
- acm->port_num, status);
- acm->notify_req = req;
- }
-
- return status;
-}
-
-static int acm_notify_serial_state(struct f_acm *acm)
-{
- struct usb_composite_dev *cdev = acm->port.func.config->cdev;
- int status;
-
- spin_lock(&acm->lock);
- if (acm->notify_req) {
- DBG(cdev, "acm ttyGS%d serial state %04x\n",
- acm->port_num, acm->serial_state);
- status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
- 0, &acm->serial_state, sizeof(acm->serial_state));
- } else {
- acm->pending = true;
- status = 0;
- }
- spin_unlock(&acm->lock);
- return status;
-}
-
-static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct f_acm *acm = req->context;
- u8 doit = false;
-
- /* on this call path we do NOT hold the port spinlock,
- * which is why ACM needs its own spinlock
- */
- spin_lock(&acm->lock);
- if (req->status != -ESHUTDOWN)
- doit = acm->pending;
- acm->notify_req = req;
- spin_unlock(&acm->lock);
-
- if (doit)
- acm_notify_serial_state(acm);
-}
-
-/* connect == the TTY link is open */
-
-static void acm_connect(struct gserial *port)
-{
- struct f_acm *acm = port_to_acm(port);
-
- acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
- acm_notify_serial_state(acm);
-}
-
-static void acm_disconnect(struct gserial *port)
-{
- struct f_acm *acm = port_to_acm(port);
-
- acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
- acm_notify_serial_state(acm);
-}
-
-static int acm_send_break(struct gserial *port, int duration)
-{
- struct f_acm *acm = port_to_acm(port);
- u16 state;
-
- state = acm->serial_state;
- state &= ~ACM_CTRL_BRK;
- if (duration)
- state |= ACM_CTRL_BRK;
-
- acm->serial_state = state;
- return acm_notify_serial_state(acm);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* ACM function driver setup/binding */
-static int
-acm_bind(struct usb_configuration *c, struct usb_function *f)
-{
- struct usb_composite_dev *cdev = c->cdev;
- struct f_acm *acm = func_to_acm(f);
- int status;
- struct usb_ep *ep;
-
- /* allocate instance-specific interface IDs, and patch descriptors */
- status = usb_interface_id(c, f);
- if (status < 0)
- goto fail;
- acm->ctrl_id = status;
- acm_iad_descriptor.bFirstInterface = status;
-
- acm_control_interface_desc.bInterfaceNumber = status;
- acm_union_desc .bMasterInterface0 = status;
-
- status = usb_interface_id(c, f);
- if (status < 0)
- goto fail;
- acm->data_id = status;
-
- acm_data_interface_desc.bInterfaceNumber = status;
- acm_union_desc.bSlaveInterface0 = status;
- acm_call_mgmt_descriptor.bDataInterface = status;
-
- status = -ENODEV;
-
- /* allocate instance-specific endpoints */
- ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc);
- if (!ep)
- goto fail;
- acm->port.in = ep;
- ep->driver_data = cdev; /* claim */
-
- ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
- if (!ep)
- goto fail;
- acm->port.out = ep;
- ep->driver_data = cdev; /* claim */
-
- ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
- if (!ep)
- goto fail;
- acm->notify = ep;
- ep->driver_data = cdev; /* claim */
-
- /* allocate notification */
- acm->notify_req = gs_alloc_req(ep,
- sizeof(struct usb_cdc_notification) + 2,
- GFP_KERNEL);
- if (!acm->notify_req)
- goto fail;
-
- acm->notify_req->complete = acm_cdc_notify_complete;
- acm->notify_req->context = acm;
-
- /* copy descriptors */
- f->descriptors = usb_copy_descriptors(acm_fs_function);
- if (!f->descriptors)
- goto fail;
-
- /* support all relevant hardware speeds... we expect that when
- * hardware is dual speed, all bulk-capable endpoints work at
- * both speeds
- */
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- acm_hs_in_desc.bEndpointAddress =
- acm_fs_in_desc.bEndpointAddress;
- acm_hs_out_desc.bEndpointAddress =
- acm_fs_out_desc.bEndpointAddress;
- acm_hs_notify_desc.bEndpointAddress =
- acm_fs_notify_desc.bEndpointAddress;
-
- /* copy descriptors */
- f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
- }
- if (gadget_is_superspeed(c->cdev->gadget)) {
- acm_ss_in_desc.bEndpointAddress =
- acm_fs_in_desc.bEndpointAddress;
- acm_ss_out_desc.bEndpointAddress =
- acm_fs_out_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
- if (!f->ss_descriptors)
- goto fail;
- }
-
- DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
- acm->port_num,
- gadget_is_superspeed(c->cdev->gadget) ? "super" :
- gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
- acm->port.in->name, acm->port.out->name,
- acm->notify->name);
- return 0;
-
-fail:
- if (acm->notify_req)
- gs_free_req(acm->notify, acm->notify_req);
-
- /* we might as well release our claims on endpoints */
- if (acm->notify)
- acm->notify->driver_data = NULL;
- if (acm->port.out)
- acm->port.out->driver_data = NULL;
- if (acm->port.in)
- acm->port.in->driver_data = NULL;
-
- ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
-
- return status;
-}
-
-static void
-acm_unbind(struct usb_configuration *c, struct usb_function *f)
-{
- struct f_acm *acm = func_to_acm(f);
-
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- if (gadget_is_superspeed(c->cdev->gadget))
- usb_free_descriptors(f->ss_descriptors);
- usb_free_descriptors(f->descriptors);
- gs_free_req(acm->notify, acm->notify_req);
- kfree(acm);
-}
-
-/* Some controllers can't support CDC ACM ... */
-static inline bool can_support_cdc(struct usb_configuration *c)
-{
- /* everything else is *probably* fine ... */
- return true;
-}
-
-/**
- * acm_bind_config - add a CDC ACM function to a configuration
- * @c: the configuration to support the CDC ACM instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- * Caller must have called @gserial_setup() with enough ports to
- * handle all the ones it binds. Caller is also responsible
- * for calling @gserial_cleanup() before module unload.
- */
-int acm_bind_config(struct usb_configuration *c, u8 port_num)
-{
- struct f_acm *acm;
- int status;
-
- if (!can_support_cdc(c))
- return -EINVAL;
-
- /* REVISIT might want instance-specific strings to help
- * distinguish instances ...
- */
-
- /* maybe allocate device-global string IDs, and patch descriptors */
- if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- acm_string_defs[ACM_CTRL_IDX].id = status;
-
- acm_control_interface_desc.iInterface = status;
-
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- acm_string_defs[ACM_DATA_IDX].id = status;
-
- acm_data_interface_desc.iInterface = status;
-
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- acm_string_defs[ACM_IAD_IDX].id = status;
-
- acm_iad_descriptor.iFunction = status;
- }
-
- /* allocate and initialize one new instance */
- acm = kzalloc(sizeof *acm, GFP_KERNEL);
- if (!acm)
- return -ENOMEM;
-
- spin_lock_init(&acm->lock);
-
- acm->port_num = port_num;
-
- acm->port.connect = acm_connect;
- acm->port.disconnect = acm_disconnect;
- acm->port.send_break = acm_send_break;
-
- acm->port.func.name = "acm";
- acm->port.func.strings = acm_strings;
- /* descriptors are per-instance copies */
- acm->port.func.bind = acm_bind;
- acm->port.func.unbind = acm_unbind;
- acm->port.func.set_alt = acm_set_alt;
- acm->port.func.setup = acm_setup;
- acm->port.func.disable = acm_disable;
-
- status = usb_add_function(c, &acm->port.func);
- if (status)
- kfree(acm);
- return status;
-}
diff --git a/drivers/staging/ccg/f_fs.c b/drivers/staging/ccg/f_fs.c
deleted file mode 100644
index f6373dade7f..00000000000
--- a/drivers/staging/ccg/f_fs.c
+++ /dev/null
@@ -1,2456 +0,0 @@
-/*
- * f_fs.c -- user mode file system API for USB composite function controllers
- *
- * Copyright (C) 2010 Samsung Electronics
- * Author: Michal Nazarewicz <mina86@mina86.com>
- *
- * Based on inode.c (GadgetFS) which was:
- * Copyright (C) 2003-2004 David Browne