summaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/Kconfig8
-rw-r--r--drivers/staging/Makefile4
-rw-r--r--drivers/staging/android/Kconfig110
-rw-r--r--drivers/staging/android/Makefile9
-rw-r--r--drivers/staging/android/TODO10
-rw-r--r--drivers/staging/android/android_pmem.h93
-rw-r--r--drivers/staging/android/ashmem.c752
-rw-r--r--drivers/staging/android/ashmem.h48
-rw-r--r--drivers/staging/android/binder.c3600
-rw-r--r--drivers/staging/android/binder.h330
-rw-r--r--drivers/staging/android/logger.c616
-rw-r--r--drivers/staging/android/logger.h49
-rw-r--r--drivers/staging/android/lowmemorykiller.c219
-rw-r--r--drivers/staging/android/pmem.c1345
-rw-r--r--drivers/staging/android/ram_console.c443
-rw-r--r--drivers/staging/android/ram_console.h22
-rw-r--r--drivers/staging/android/switch/Kconfig11
-rw-r--r--drivers/staging/android/switch/Makefile4
-rw-r--r--drivers/staging/android/switch/switch.h53
-rw-r--r--drivers/staging/android/switch/switch_class.c174
-rw-r--r--drivers/staging/android/switch/switch_gpio.c172
-rw-r--r--drivers/staging/android/timed_gpio.c176
-rw-r--r--drivers/staging/android/timed_gpio.h33
-rw-r--r--drivers/staging/android/timed_output.c123
-rw-r--r--drivers/staging/android/timed_output.h37
-rw-r--r--drivers/staging/asus_oled/asus_oled.c4
-rw-r--r--drivers/staging/bcm/Bcmchar.c376
-rw-r--r--drivers/staging/bcm/HandleControlPacket.c323
-rw-r--r--drivers/staging/bcm/InterfaceDld.c12
-rw-r--r--drivers/staging/bcm/InterfaceIdleMode.c33
-rw-r--r--drivers/staging/bcm/InterfaceInit.c12
-rw-r--r--drivers/staging/bcm/InterfaceMisc.c24
-rw-r--r--drivers/staging/bcm/Misc.c32
-rw-r--r--drivers/staging/bcm/hostmibs.c178
-rw-r--r--drivers/staging/bcm/led_control.c1131
-rw-r--r--drivers/staging/bcm/nvm.c95
-rw-r--r--drivers/staging/comedi/comedi_fops.c86
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c137
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7230.c10
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7296.c6
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7432.c6
-rw-r--r--drivers/staging/comedi/drivers/adl_pci8164.c6
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c6
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c32
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c23
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c9
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.c6
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc263.c6
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c9
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c9
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c20
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c42
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c26
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidda.c18
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidio.c23
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c50
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdda.c30
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c19
-rw-r--r--drivers/staging/comedi/drivers/daqboard2000.c73
-rw-r--r--drivers/staging/comedi/drivers/das08.c6
-rw-r--r--drivers/staging/comedi/drivers/das08_cs.c8
-rw-r--r--drivers/staging/comedi/drivers/das16m1.c37
-rw-r--r--drivers/staging/comedi/drivers/das1800.c65
-rw-r--r--drivers/staging/comedi/drivers/das6402.c23
-rw-r--r--drivers/staging/comedi/drivers/das800.c43
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c38
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c81
-rw-r--r--drivers/staging/comedi/drivers/ke_counter.c6
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c9
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c8
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_dio24.c19
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c29
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c4
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c108
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c26
-rw-r--r--drivers/staging/comedi/drivers/pcmuio.c40
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c7
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c16
-rw-r--r--drivers/staging/crystalhd/bc_dts_defs.h262
-rw-r--r--drivers/staging/cxt1e1/comet.h22
-rw-r--r--drivers/staging/cxt1e1/comet_tables.c24
-rw-r--r--drivers/staging/cxt1e1/comet_tables.h24
-rw-r--r--drivers/staging/cxt1e1/libsbew.h32
-rw-r--r--drivers/staging/cxt1e1/musycc.c49
-rw-r--r--drivers/staging/cxt1e1/musycc.h31
-rw-r--r--drivers/staging/cxt1e1/ossiRelease.c10
-rw-r--r--drivers/staging/cxt1e1/pmc93x6_eeprom.h21
-rw-r--r--drivers/staging/cxt1e1/pmcc4.h42
-rw-r--r--drivers/staging/cxt1e1/pmcc4_cpld.h33
-rw-r--r--drivers/staging/cxt1e1/pmcc4_defs.h14
-rw-r--r--drivers/staging/cxt1e1/pmcc4_drv.c70
-rw-r--r--drivers/staging/cxt1e1/pmcc4_ioctls.h16
-rw-r--r--drivers/staging/cxt1e1/sbe_bid.h14
-rw-r--r--drivers/staging/cxt1e1/sbe_promformat.h27
-rw-r--r--drivers/staging/cxt1e1/sbecom_inline_linux.h20
-rw-r--r--drivers/staging/cxt1e1/sbeproc.h20
-rw-r--r--drivers/staging/cxt1e1/sbew_ioc.h55
-rw-r--r--drivers/staging/et131x/et131x.c370
-rw-r--r--drivers/staging/frontier/tranzport.c2
-rw-r--r--drivers/staging/gma500/Kconfig2
-rw-r--r--drivers/staging/gma500/accel_2d.c2
-rw-r--r--drivers/staging/gma500/cdv_intel_display.c4
-rw-r--r--drivers/staging/gma500/framebuffer.c41
-rw-r--r--drivers/staging/gma500/mdfld_intel_display.c4
-rw-r--r--drivers/staging/gma500/mrst_crtc.c4
-rw-r--r--drivers/staging/gma500/power.c2
-rw-r--r--drivers/staging/gma500/psb_drv.c23
-rw-r--r--drivers/staging/gma500/psb_intel_display.c4
-rw-r--r--drivers/staging/hv/Kconfig12
-rw-r--r--drivers/staging/hv/Makefile3
-rw-r--r--drivers/staging/hv/TODO4
-rw-r--r--drivers/staging/hv/hv_mouse.c599
-rw-r--r--drivers/staging/hv/hyperv_net.h1058
-rw-r--r--drivers/staging/hv/netvsc.c944
-rw-r--r--drivers/staging/hv/netvsc_drv.c456
-rw-r--r--drivers/staging/hv/rndis_filter.c855
-rw-r--r--drivers/staging/hv/storvsc_drv.c310
-rw-r--r--drivers/staging/iio/Documentation/generic_buffer.c8
-rw-r--r--drivers/staging/iio/Documentation/iio_utils.h26
-rw-r--r--drivers/staging/iio/Documentation/ring.txt10
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio10
-rw-r--r--drivers/staging/iio/Kconfig1
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c36
-rw-r--r--drivers/staging/iio/accel/adis16201_ring.c14
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c24
-rw-r--r--drivers/staging/iio/accel/adis16203_ring.c14
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c35
-rw-r--r--drivers/staging/iio/accel/adis16204_ring.c14
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c32
-rw-r--r--drivers/staging/iio/accel/adis16209_ring.c9
-rw-r--r--drivers/staging/iio/accel/adis16220_core.c27
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c32
-rw-r--r--drivers/staging/iio/accel/adis16240_ring.c9
-rw-r--r--drivers/staging/iio/accel/kxsd9.c10
-rw-r--r--drivers/staging/iio/accel/lis3l02dq.h12
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c35
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c61
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c24
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c17
-rw-r--r--drivers/staging/iio/adc/ad7192.c80
-rw-r--r--drivers/staging/iio/adc/ad7280a.c28
-rw-r--r--drivers/staging/iio/adc/ad7291.c39
-rw-r--r--drivers/staging/iio/adc/ad7298.h5
-rw-r--r--drivers/staging/iio/adc/ad7298_core.c67
-rw-r--r--drivers/staging/iio/adc/ad7298_ring.c45
-rw-r--r--drivers/staging/iio/adc/ad7476.h5
-rw-r--r--drivers/staging/iio/adc/ad7476_core.c25
-rw-r--r--drivers/staging/iio/adc/ad7476_ring.c31
-rw-r--r--drivers/staging/iio/adc/ad7606.h1
-rw-r--r--drivers/staging/iio/adc/ad7606_core.c6
-rw-r--r--drivers/staging/iio/adc/ad7606_par.c1
-rw-r--r--drivers/staging/iio/adc/ad7606_ring.c30
-rw-r--r--drivers/staging/iio/adc/ad7606_spi.c3
-rw-r--r--drivers/staging/iio/adc/ad7780.c8
-rw-r--r--drivers/staging/iio/adc/ad7793.c95
-rw-r--r--drivers/staging/iio/adc/ad7816.c2
-rw-r--r--drivers/staging/iio/adc/ad7887.h5
-rw-r--r--drivers/staging/iio/adc/ad7887_core.c13
-rw-r--r--drivers/staging/iio/adc/ad7887_ring.c46
-rw-r--r--drivers/staging/iio/adc/ad799x.h6
-rw-r--r--drivers/staging/iio/adc/ad799x_core.c9
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c47
-rw-r--r--drivers/staging/iio/adc/adt7310.c3
-rw-r--r--drivers/staging/iio/adc/adt7410.c1
-rw-r--r--drivers/staging/iio/adc/max1363.h14
-rw-r--r--drivers/staging/iio/adc/max1363_core.c78
-rw-r--r--drivers/staging/iio/adc/max1363_ring.c92
-rw-r--r--drivers/staging/iio/addac/adt7316-spi.c1
-rw-r--r--drivers/staging/iio/addac/adt7316.c1
-rw-r--r--drivers/staging/iio/buffer.h (renamed from drivers/staging/iio/buffer_generic.h)87
-rw-r--r--drivers/staging/iio/cdc/ad7150.c8
-rw-r--r--drivers/staging/iio/cdc/ad7152.c38
-rw-r--r--drivers/staging/iio/cdc/ad7746.c50
-rw-r--r--drivers/staging/iio/chrdev.h25
-rw-r--r--drivers/staging/iio/dac/Kconfig39
-rw-r--r--drivers/staging/iio/dac/Makefile3
-rw-r--r--drivers/staging/iio/dac/ad5064.c6
-rw-r--r--drivers/staging/iio/dac/ad5360.c24
-rw-r--r--drivers/staging/iio/dac/ad5380.c676
-rw-r--r--drivers/staging/iio/dac/ad5421.c555
-rw-r--r--drivers/staging/iio/dac/ad5421.h32
-rw-r--r--drivers/staging/iio/dac/ad5446.c184
-rw-r--r--drivers/staging/iio/dac/ad5446.h10
-rw-r--r--drivers/staging/iio/dac/ad5504.c132
-rw-r--r--drivers/staging/iio/dac/ad5504.h5
-rw-r--r--drivers/staging/iio/dac/ad5624r.h4
-rw-r--r--drivers/staging/iio/dac/ad5624r_spi.c127
-rw-r--r--drivers/staging/iio/dac/ad5686.c5
-rw-r--r--drivers/staging/iio/dac/ad5764.c393
-rw-r--r--drivers/staging/iio/dac/ad5791.c15
-rw-r--r--drivers/staging/iio/dds/ad5930.c1
-rw-r--r--drivers/staging/iio/dds/ad9832.c5
-rw-r--r--drivers/staging/iio/dds/ad9834.c7
-rw-r--r--drivers/staging/iio/dds/ad9850.c1
-rw-r--r--drivers/staging/iio/dds/ad9852.c1
-rw-r--r--drivers/staging/iio/dds/ad9910.c1
-rw-r--r--drivers/staging/iio/dds/ad9951.c1
-rw-r--r--drivers/staging/iio/events.h103
-rw-r--r--drivers/staging/iio/gyro/Kconfig6
-rw-r--r--drivers/staging/iio/gyro/adis16060_core.c8
-rw-r--r--drivers/staging/iio/gyro/adis16080_core.c1
-rw-r--r--drivers/staging/iio/gyro/adis16130_core.c1
-rw-r--r--drivers/staging/iio/gyro/adis16260_core.c45
-rw-r--r--drivers/staging/iio/gyro/adis16260_ring.c9
-rw-r--r--drivers/staging/iio/gyro/adxrs450.h5
-rw-r--r--drivers/staging/iio/gyro/adxrs450_core.c88
-rw-r--r--drivers/staging/iio/iio.h144
-rw-r--r--drivers/staging/iio/iio_core.h11
-rw-r--r--drivers/staging/iio/iio_core_trigger.h3
-rw-r--r--drivers/staging/iio/iio_dummy_evgen.c4
-rw-r--r--drivers/staging/iio/iio_simple_dummy.c49
-rw-r--r--drivers/staging/iio/iio_simple_dummy_buffer.c12
-rw-r--r--drivers/staging/iio/iio_simple_dummy_events.c1
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c30
-rw-r--r--drivers/staging/iio/imu/adis16400.h2
-rw-r--r--drivers/staging/iio/imu/adis16400_core.c269
-rw-r--r--drivers/staging/iio/imu/adis16400_ring.c23
-rw-r--r--drivers/staging/iio/industrialio-buffer.c346
-rw-r--r--drivers/staging/iio/industrialio-core.c70
-rw-r--r--drivers/staging/iio/industrialio-trigger.c34
-rw-r--r--drivers/staging/iio/kfifo_buf.c72
-rw-r--r--drivers/staging/iio/kfifo_buf.h2
-rw-r--r--drivers/staging/iio/light/isl29018.c7
-rw-r--r--drivers/staging/iio/light/tsl2563.c11
-rw-r--r--drivers/staging/iio/light/tsl2583.c17
-rw-r--r--drivers/staging/iio/magnetometer/ak8975.c4
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c5
-rw-r--r--drivers/staging/iio/meter/ade7753.c1
-rw-r--r--drivers/staging/iio/meter/ade7754.c1
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c37
-rw-r--r--drivers/staging/iio/meter/ade7758_ring.c10
-rw-r--r--drivers/staging/iio/meter/ade7759.c1
-rw-r--r--drivers/staging/iio/meter/ade7854-spi.c1
-rw-r--r--drivers/staging/iio/resolver/ad2s1200.c1
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c1
-rw-r--r--drivers/staging/iio/resolver/ad2s90.c1
-rw-r--r--drivers/staging/iio/ring_sw.c151
-rw-r--r--drivers/staging/iio/ring_sw.h2
-rw-r--r--drivers/staging/iio/sysfs.h43
-rw-r--r--drivers/staging/iio/trigger.h2
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c1
-rw-r--r--drivers/staging/iio/types.h49
-rw-r--r--drivers/staging/intel_sst/Kconfig19
-rw-r--r--drivers/staging/intel_sst/Makefile7
-rw-r--r--drivers/staging/intel_sst/TODO13
-rw-r--r--drivers/staging/intel_sst/intel_sst.c649
-rw-r--r--drivers/staging/intel_sst/intel_sst.h162
-rw-r--r--drivers/staging/intel_sst/intel_sst_app_interface.c1460
-rw-r--r--drivers/staging/intel_sst/intel_sst_common.h623
-rw-r--r--drivers/staging/intel_sst/intel_sst_drv_interface.c564
-rw-r--r--drivers/staging/intel_sst/intel_sst_dsp.c496
-rw-r--r--drivers/staging/intel_sst/intel_sst_fw_ipc.h416
-rw-r--r--drivers/staging/intel_sst/intel_sst_ioctl.h440
-rw-r--r--drivers/staging/intel_sst/intel_sst_ipc.c774
-rw-r--r--drivers/staging/intel_sst/intel_sst_pvt.c313
-rw-r--r--drivers/staging/intel_sst/intel_sst_stream.c583
-rw-r--r--drivers/staging/intel_sst/intel_sst_stream_encoded.c1273
-rw-r--r--drivers/staging/intel_sst/intelmid.c1022
-rw-r--r--drivers/staging/intel_sst/intelmid.h209
-rw-r--r--drivers/staging/intel_sst/intelmid_adc_control.h193
-rw-r--r--drivers/staging/intel_sst/intelmid_ctrl.c921
-rw-r--r--drivers/staging/intel_sst/intelmid_msic_control.c1047
-rw-r--r--drivers/staging/intel_sst/intelmid_pvt.c173
-rw-r--r--drivers/staging/intel_sst/intelmid_snd_control.h123
-rw-r--r--drivers/staging/intel_sst/intelmid_v0_control.c866
-rw-r--r--drivers/staging/intel_sst/intelmid_v1_control.c978
-rw-r--r--drivers/staging/intel_sst/intelmid_v2_control.c1156
-rw-r--r--drivers/staging/line6/Makefile3
-rw-r--r--drivers/staging/line6/capture.c44
-rw-r--r--drivers/staging/line6/capture.h2
-rw-r--r--drivers/staging/line6/driver.c74
-rw-r--r--drivers/staging/line6/driver.h10
-rw-r--r--drivers/staging/line6/midi.c37
-rw-r--r--drivers/staging/line6/midi.h4
-rw-r--r--drivers/staging/line6/pcm.c115
-rw-r--r--drivers/staging/line6/pcm.h8
-rw-r--r--drivers/staging/line6/playback.c53
-rw-r--r--drivers/staging/line6/playback.h2
-rw-r--r--drivers/staging/line6/pod.c6
-rw-r--r--drivers/staging/line6/podhd.c154
-rw-r--r--drivers/staging/line6/podhd.h30
-rw-r--r--drivers/staging/line6/revision.h2
-rw-r--r--drivers/staging/line6/toneport.c6
-rw-r--r--drivers/staging/line6/usbdefs.h91
-rw-r--r--drivers/staging/line6/variax.c6
-rw-r--r--drivers/staging/mei/init.c49
-rw-r--r--drivers/staging/mei/interface.c8
-rw-r--r--drivers/staging/mei/interface.h11
-rw-r--r--drivers/staging/mei/interrupt.c322
-rw-r--r--drivers/staging/mei/iorw.c77
-rw-r--r--drivers/staging/mei/main.c576
-rw-r--r--drivers/staging/mei/mei.txt226
-rw-r--r--drivers/staging/mei/mei_dev.h13
-rw-r--r--drivers/staging/mei/wd.c32
-rw-r--r--drivers/staging/nvec/nvec.c30
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c18
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.h2
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon_xo_1.c10
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c10
-rw-r--r--drivers/staging/omapdrm/Kconfig25
-rw-r--r--drivers/staging/omapdrm/Makefile21
-rw-r--r--drivers/staging/omapdrm/TODO38
-rw-r--r--drivers/staging/omapdrm/omap_connector.c371
-rw-r--r--drivers/staging/omapdrm/omap_crtc.c326
-rw-r--r--drivers/staging/omapdrm/omap_debugfs.c42
-rw-r--r--drivers/staging/omapdrm/omap_dmm_priv.h187
-rw-r--r--drivers/staging/omapdrm/omap_dmm_tiler.c830
-rw-r--r--drivers/staging/omapdrm/omap_dmm_tiler.h135
-rw-r--r--drivers/staging/omapdrm/omap_drm.h123
-rw-r--r--drivers/staging/omapdrm/omap_drv.c821
-rw-r--r--drivers/staging/omapdrm/omap_drv.h135
-rw-r--r--drivers/staging/omapdrm/omap_encoder.c171
-rw-r--r--drivers/staging/omapdrm/omap_fb.c243
-rw-r--r--drivers/staging/omapdrm/omap_fbdev.c372
-rw-r--r--drivers/staging/omapdrm/omap_gem.c1231
-rw-r--r--drivers/staging/omapdrm/omap_gem_helpers.c169
-rw-r--r--drivers/staging/omapdrm/omap_priv.h47
-rw-r--r--drivers/staging/omapdrm/tcm-sita.c703
-rw-r--r--drivers/staging/omapdrm/tcm-sita.h95
-rw-r--r--drivers/staging/omapdrm/tcm.h326
-rw-r--r--drivers/staging/phison/phison.c2
-rw-r--r--drivers/staging/rtl8192e/Kconfig50
-rw-r--r--drivers/staging/rtl8192e/Makefile46
-rw-r--r--drivers/staging/rtl8192e/dot11d.c4
-rw-r--r--drivers/staging/rtl8192e/dot11d.h2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/Kconfig9
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/Makefile21
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_def.h (renamed from drivers/staging/rtl8192e/r8190P_def.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c (renamed from drivers/staging/rtl8192e/r8190P_rtl8256.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h (renamed from drivers/staging/rtl8192e/r8190P_rtl8256.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c (renamed from drivers/staging/rtl8192e/r8192E_cmdpkt.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h (renamed from drivers/staging/rtl8192e/r8192E_cmdpkt.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c (renamed from drivers/staging/rtl8192e/r8192E_dev.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h (renamed from drivers/staging/rtl8192e/r8192E_dev.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c (renamed from drivers/staging/rtl8192e/r8192E_firmware.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h (renamed from drivers/staging/rtl8192e/r8192E_firmware.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h (renamed from drivers/staging/rtl8192e/r8192E_hw.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c (renamed from drivers/staging/rtl8192e/r8192E_hwimg.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.h (renamed from drivers/staging/rtl8192e/r8192E_hwimg.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c (renamed from drivers/staging/rtl8192e/r8192E_phy.c)3
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h (renamed from drivers/staging/rtl8192e/r8192E_phy.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h (renamed from drivers/staging/rtl8192e/r8192E_phyreg.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h (renamed from drivers/staging/rtl8192e/r819xE_phyreg.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_cam.c (renamed from drivers/staging/rtl8192e/rtl_cam.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_cam.h (renamed from drivers/staging/rtl8192e/rtl_cam.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c (renamed from drivers/staging/rtl8192e/rtl_core.c)68
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.h (renamed from drivers/staging/rtl8192e/rtl_core.h)53
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_crypto.h (renamed from drivers/staging/rtl8192e/rtl_crypto.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_debug.c (renamed from drivers/staging/rtl8192e/rtl_debug.c)79
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c (renamed from drivers/staging/rtl8192e/rtl_dm.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.h (renamed from drivers/staging/rtl8192e/rtl_dm.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c (renamed from drivers/staging/rtl8192e/rtl_eeprom.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h (renamed from drivers/staging/rtl8192e/rtl_eeprom.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c (renamed from drivers/staging/rtl8192e/rtl_ethtool.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pci.c (renamed from drivers/staging/rtl8192e/rtl_pci.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pci.h (renamed from drivers/staging/rtl8192e/rtl_pci.h)1
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pm.c (renamed from drivers/staging/rtl8192e/rtl_pm.c)2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pm.h (renamed from drivers/staging/rtl8192e/rtl_pm.h)4
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ps.c (renamed from drivers/staging/rtl8192e/rtl_ps.c)0
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ps.h (renamed from drivers/staging/rtl8192e/rtl_ps.h)2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.c (renamed from drivers/staging/rtl8192e/rtl_wx.c)3
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.h (renamed from drivers/staging/rtl8192e/rtl_wx.h)0
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BAProc.c1
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HTProc.c5
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TSProc.c1
-rw-r--r--drivers/staging/rtl8192e/rtl_debug.h299
-rw-r--r--drivers/staging/rtl8192e/rtllib.h113
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt.c80
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt.h64
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_ccmp.c26
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_tkip.c38
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_wep.c25
-rw-r--r--drivers/staging/rtl8192e/rtllib_debug.h86
-rw-r--r--drivers/staging/rtl8192e/rtllib_module.c38
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c21
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c96
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac_wx.c19
-rw-r--r--drivers/staging/rtl8192e/rtllib_tx.c19
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c109
-rw-r--r--drivers/staging/rtl8192u/ieee80211/api.c244
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c2
-rw-r--r--drivers/staging/rts5139/rts51x.h1
-rw-r--r--drivers/staging/rts5139/rts51x_transport.h1
-rw-r--r--drivers/staging/sep/sep_driver.c2
-rw-r--r--drivers/staging/serial/68360serial.c4
-rw-r--r--drivers/staging/sm7xx/smtcfb.c6
-rw-r--r--drivers/staging/speakup/kobjects.c3
-rw-r--r--drivers/staging/speakup/main.c5
-rw-r--r--drivers/staging/spectra/Kconfig41
-rw-r--r--drivers/staging/spectra/Makefile11
-rw-r--r--drivers/staging/spectra/README29
-rw-r--r--drivers/staging/spectra/ffsdefs.h58
-rw-r--r--drivers/staging/spectra/ffsport.c834
-rw-r--r--drivers/staging/spectra/ffsport.h85
-rw-r--r--drivers/staging/spectra/flash.c4305
-rw-r--r--drivers/staging/spectra/flash.h198
-rw-r--r--drivers/staging/spectra/lld.c339
-rw-r--r--drivers/staging/spectra/lld.h111
-rw-r--r--drivers/staging/spectra/lld_cdma.c910
-rw-r--r--drivers/staging/spectra/lld_cdma.h123
-rw-r--r--drivers/staging/spectra/lld_emu.c776
-rw-r--r--drivers/staging/spectra/lld_emu.h51
-rw-r--r--drivers/staging/spectra/lld_mtd.c683
-rw-r--r--drivers/staging/spectra/lld_mtd.h51
-rw-r--r--drivers/staging/spectra/lld_nand.c2619
-rw-r--r--drivers/staging/spectra/lld_nand.h131
-rw-r--r--drivers/staging/spectra/nand_regs.h619
-rw-r--r--drivers/staging/spectra/spectraswconfig.h82
-rw-r--r--drivers/staging/usbip/stub_dev.c5
-rw-r--r--drivers/staging/usbip/stub_rx.c2
-rw-r--r--drivers/staging/usbip/usbip_common.c61
-rw-r--r--drivers/staging/usbip/usbip_common.h17
-rw-r--r--drivers/staging/usbip/vhci_rx.c2
-rw-r--r--drivers/staging/vme/TODO67
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.c31
-rw-r--r--drivers/staging/vme/bridges/vme_tsi148.c36
-rw-r--r--drivers/staging/vme/devices/Kconfig13
-rw-r--r--drivers/staging/vme/devices/Makefile3
-rw-r--r--drivers/staging/vme/devices/vme_pio2.h249
-rw-r--r--drivers/staging/vme/devices/vme_pio2_cntr.c71
-rw-r--r--drivers/staging/vme/devices/vme_pio2_core.c524
-rw-r--r--drivers/staging/vme/devices/vme_pio2_gpio.c232
-rw-r--r--drivers/staging/vme/devices/vme_user.h10
-rw-r--r--drivers/staging/vme/vme.c69
-rw-r--r--drivers/staging/vme/vme.h38
-rw-r--r--drivers/staging/vme/vme_api.txt61
-rw-r--r--drivers/staging/vme/vme_bridge.h38
-rw-r--r--drivers/staging/vt6655/device_main.c6
-rw-r--r--drivers/staging/vt6655/ioctl.c8
-rw-r--r--drivers/staging/vt6655/iwctl.c12
-rw-r--r--drivers/staging/vt6655/iwctl.h5
-rw-r--r--drivers/staging/vt6656/80211mgr.c35
-rw-r--r--drivers/staging/vt6656/baseband.c61
-rw-r--r--drivers/staging/vt6656/bssdb.c100
-rw-r--r--drivers/staging/vt6656/card.c14
-rw-r--r--drivers/staging/vt6656/card.h4
-rw-r--r--drivers/staging/vt6656/int.c5
-rw-r--r--drivers/staging/vt6656/int.h2
-rw-r--r--drivers/staging/vt6656/ioctl.c8
-rw-r--r--drivers/staging/vt6656/iwctl.c12
-rw-r--r--drivers/staging/vt6656/iwctl.h5
-rw-r--r--drivers/staging/vt6656/mac.c4
-rw-r--r--drivers/staging/vt6656/mac.h2
-rw-r--r--drivers/staging/vt6656/main_usb.c12
-rw-r--r--drivers/staging/wlags49_h2/wl_pci.c13
-rw-r--r--drivers/staging/xgifb/Makefile2
-rw-r--r--drivers/staging/xgifb/XGI_main.h13
-rw-r--r--drivers/staging/xgifb/XGI_main_26.c158
-rw-r--r--drivers/staging/xgifb/XGIfb.h3
-rw-r--r--drivers/staging/xgifb/vb_ext.c444
-rw-r--r--drivers/staging/xgifb/vb_ext.h9
-rw-r--r--drivers/staging/xgifb/vb_init.c276
-rw-r--r--drivers/staging/xgifb/vb_setmode.c1003
-rw-r--r--drivers/staging/xgifb/vb_setmode.h52
-rw-r--r--drivers/staging/xgifb/vb_struct.h4
-rw-r--r--drivers/staging/xgifb/vb_table.h27
-rw-r--r--drivers/staging/xgifb/vgatypes.h2
-rw-r--r--drivers/staging/zcache/zcache-main.c6
-rw-r--r--drivers/staging/zram/zram_drv.c3
-rw-r--r--drivers/staging/zram/zram_sysfs.c6
461 files changed, 24061 insertions, 39158 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 25cdff36a78a..21e2f4b87f14 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -72,8 +72,6 @@ source "drivers/staging/octeon/Kconfig"
source "drivers/staging/serqt_usb2/Kconfig"
-source "drivers/staging/spectra/Kconfig"
-
source "drivers/staging/quatech_usb2/Kconfig"
source "drivers/staging/vt6655/Kconfig"
@@ -116,8 +114,6 @@ source "drivers/staging/bcm/Kconfig"
source "drivers/staging/ft1000/Kconfig"
-source "drivers/staging/intel_sst/Kconfig"
-
source "drivers/staging/speakup/Kconfig"
source "drivers/staging/cptm1217/Kconfig"
@@ -132,4 +128,8 @@ source "drivers/staging/nvec/Kconfig"
source "drivers/staging/media/Kconfig"
+source "drivers/staging/omapdrm/Kconfig"
+
+source "drivers/staging/android/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index a25f3f26c7ff..7c5808d7212d 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_R8712U) += rtl8712/
obj-$(CONFIG_RTS_PSTOR) += rts_pstor/
obj-$(CONFIG_RTS5139) += rts5139/
-obj-$(CONFIG_SPECTRA) += spectra/
obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_POHMELFS) += pohmelfs/
obj-$(CONFIG_IDE_PHISON) += phison/
@@ -50,10 +49,11 @@ obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/
obj-$(CONFIG_USB_ENESTORAGE) += keucr/
obj-$(CONFIG_BCM_WIMAX) += bcm/
obj-$(CONFIG_FT1000) += ft1000/
-obj-$(CONFIG_SND_INTEL_SST) += intel_sst/
obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
obj-$(CONFIG_DRM_PSB) += gma500/
obj-$(CONFIG_INTEL_MEI) += mei/
obj-$(CONFIG_MFD_NVEC) += nvec/
+obj-$(CONFIG_DRM_OMAP) += omapdrm/
+obj-$(CONFIG_ANDROID) += android/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
new file mode 100644
index 000000000000..becf711117ef
--- /dev/null
+++ b/drivers/staging/android/Kconfig
@@ -0,0 +1,110 @@
+menu "Android"
+
+config ANDROID
+ bool "Android Drivers"
+ default N
+ ---help---
+ Enable support for various drivers needed on the Android platform
+
+if ANDROID
+
+config ANDROID_BINDER_IPC
+ bool "Android Binder IPC Driver"
+ default n
+
+config ASHMEM
+ bool "Enable the Anonymous Shared Memory Subsystem"
+ default n
+ depends on SHMEM || TINY_SHMEM
+ help
+ The ashmem subsystem is a new shared memory allocator, similar to
+ POSIX SHM but with different behavior and sporting a simpler
+ file-based API.
+
+config ANDROID_LOGGER
+ tristate "Android log driver"
+ default n
+
+config ANDROID_RAM_CONSOLE
+ bool "Android RAM buffer console"
+ default n
+
+config ANDROID_RAM_CONSOLE_ENABLE_VERBOSE
+ bool "Enable verbose console messages on Android RAM console"
+ default y
+ depends on ANDROID_RAM_CONSOLE
+
+menuconfig ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ bool "Android RAM Console Enable error correction"
+ default n
+ depends on ANDROID_RAM_CONSOLE
+ depends on !ANDROID_RAM_CONSOLE_EARLY_INIT
+ select REED_SOLOMON
+ select REED_SOLOMON_ENC8
+ select REED_SOLOMON_DEC8
+
+if ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+
+config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE
+ int "Android RAM Console Data data size"
+ default 128
+ help
+ Must be a power of 2.
+
+config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE
+ int "Android RAM Console ECC size"
+ default 16
+
+config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE
+ int "Android RAM Console Symbol size"
+ default 8
+
+config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL
+ hex "Android RAM Console Polynomial"
+ default 0x19 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 4)
+ default 0x29 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 5)
+ default 0x61 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 6)
+ default 0x89 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 7)
+ default 0x11d if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 8)
+
+endif # ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+
+config ANDROID_RAM_CONSOLE_EARLY_INIT
+ bool "Start Android RAM console early"
+ default n
+ depends on ANDROID_RAM_CONSOLE
+
+config ANDROID_RAM_CONSOLE_EARLY_ADDR
+ hex "Android RAM console virtual address"
+ default 0
+ depends on ANDROID_RAM_CONSOLE_EARLY_INIT
+
+config ANDROID_RAM_CONSOLE_EARLY_SIZE
+ hex "Android RAM console buffer size"
+ default 0
+ depends on ANDROID_RAM_CONSOLE_EARLY_INIT
+
+config ANDROID_TIMED_OUTPUT
+ bool "Timed output class driver"
+ default y
+
+config ANDROID_TIMED_GPIO
+ tristate "Android timed gpio driver"
+ depends on GENERIC_GPIO && ANDROID_TIMED_OUTPUT
+ default n
+
+config ANDROID_LOW_MEMORY_KILLER
+ bool "Android Low Memory Killer"
+ default N
+ ---help---
+ Register processes to be killed when memory is low
+
+config ANDROID_PMEM
+ bool "Android pmem allocator"
+ depends on ARM
+
+source "drivers/staging/android/switch/Kconfig"
+
+endif # if ANDROID
+
+endmenu
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
new file mode 100644
index 000000000000..eaed1ff64f0f
--- /dev/null
+++ b/drivers/staging/android/Makefile
@@ -0,0 +1,9 @@
+obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
+obj-$(CONFIG_ASHMEM) += ashmem.o
+obj-$(CONFIG_ANDROID_LOGGER) += logger.o
+obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o
+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_PMEM) += pmem.o
+obj-$(CONFIG_ANDROID_SWITCH) += switch/
diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO
new file mode 100644
index 000000000000..e59c5be4be2b
--- /dev/null
+++ b/drivers/staging/android/TODO
@@ -0,0 +1,10 @@
+TODO:
+ - checkpatch.pl cleanups
+ - sparse fixes
+ - rename files to be not so "generic"
+ - make sure things build as modules properly
+ - add proper arch dependancies as needed
+ - audit userspace interfaces to make sure they are sane
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
+Brian Swetland <swetland@google.com>
diff --git a/drivers/staging/android/android_pmem.h b/drivers/staging/android/android_pmem.h
new file mode 100644
index 000000000000..f633621f5be3
--- /dev/null
+++ b/drivers/staging/android/android_pmem.h
@@ -0,0 +1,93 @@
+/* include/linux/android_pmem.h
+ *
+ * Copyright (C) 2007 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 _ANDROID_PMEM_H_
+#define _ANDROID_PMEM_H_
+
+#define PMEM_IOCTL_MAGIC 'p'
+#define PMEM_GET_PHYS _IOW(PMEM_IOCTL_MAGIC, 1, unsigned int)
+#define PMEM_MAP _IOW(PMEM_IOCTL_MAGIC, 2, unsigned int)
+#define PMEM_GET_SIZE _IOW(PMEM_IOCTL_MAGIC, 3, unsigned int)
+#define PMEM_UNMAP _IOW(PMEM_IOCTL_MAGIC, 4, unsigned int)
+/* This ioctl will allocate pmem space, backing the file, it will fail
+ * if the file already has an allocation, pass it the len as the argument
+ * to the ioctl */
+#define PMEM_ALLOCATE _IOW(PMEM_IOCTL_MAGIC, 5, unsigned int)
+/* This will connect a one pmem file to another, pass the file that is already
+ * backed in memory as the argument to the ioctl
+ */
+#define PMEM_CONNECT _IOW(PMEM_IOCTL_MAGIC, 6, unsigned int)
+/* Returns the total size of the pmem region it is sent to as a pmem_region
+ * struct (with offset set to 0).
+ */
+#define PMEM_GET_TOTAL_SIZE _IOW(PMEM_IOCTL_MAGIC, 7, unsigned int)
+#define PMEM_CACHE_FLUSH _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int)
+
+struct android_pmem_platform_data
+{
+ const char* name;
+ /* starting physical address of memory region */
+ unsigned long start;
+ /* size of memory region */
+ unsigned long size;
+ /* set to indicate the region should not be managed with an allocator */
+ unsigned no_allocator;
+ /* set to indicate maps of this region should be cached, if a mix of
+ * cached and uncached is desired, set this and open the device with
+ * O_SYNC to get an uncached region */
+ unsigned cached;
+ /* The MSM7k has bits to enable a write buffer in the bus controller*/
+ unsigned buffered;
+};
+
+struct pmem_region {
+ unsigned long offset;
+ unsigned long len;
+};
+
+#ifdef CONFIG_ANDROID_PMEM
+int is_pmem_file(struct file *file);
+int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
+ unsigned long *end, struct file **filp);
+int get_pmem_user_addr(struct file *file, unsigned long *start,
+ unsigned long *end);
+void put_pmem_file(struct file* file);
+void flush_pmem_file(struct file *file, unsigned long start, unsigned long len);
+int pmem_setup(struct android_pmem_platform_data *pdata,
+ long (*ioctl)(struct file *, unsigned int, unsigned long),
+ int (*release)(struct inode *, struct file *));
+int pmem_remap(struct pmem_region *region, struct file *file,
+ unsigned operation);
+
+#else
+static inline int is_pmem_file(struct file *file) { return 0; }
+static inline int get_pmem_file(int fd, unsigned long *start,
+ unsigned long *vstart, unsigned long *end,
+ struct file **filp) { return -ENOSYS; }
+static inline int get_pmem_user_addr(struct file *file, unsigned long *start,
+ unsigned long *end) { return -ENOSYS; }
+static inline void put_pmem_file(struct file* file) { return; }
+static inline void flush_pmem_file(struct file *file, unsigned long start,
+ unsigned long len) { return; }
+static inline int pmem_setup(struct android_pmem_platform_data *pdata,
+ long (*ioctl)(struct file *, unsigned int, unsigned long),
+ int (*release)(struct inode *, struct file *)) { return -ENOSYS; }
+
+static inline int pmem_remap(struct pmem_region *region, struct file *file,
+ unsigned operation) { return -ENOSYS; }
+#endif
+
+#endif //_ANDROID_PPP_H_
+
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
new file mode 100644
index 000000000000..99052bfd3a2d
--- /dev/null
+++ b/drivers/staging/android/ashmem.c
@@ -0,0 +1,752 @@
+/* mm/ashmem.c
+**
+** Anonymous Shared Memory Subsystem, ashmem
+**
+** Copyright (C) 2008 Google, Inc.
+**
+** Robert Love <rlove@google.com>
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#include <linux/module.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/security.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/uaccess.h>
+#include <linux/personality.h>
+#include <linux/bitops.h>
+#include <linux/mutex.h>
+#include <linux/shmem_fs.h>
+#include "ashmem.h"
+
+#define ASHMEM_NAME_PREFIX "dev/ashmem/"
+#define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1)
+#define ASHMEM_FULL_NAME_LEN (ASHMEM_NAME_LEN + ASHMEM_NAME_PREFIX_LEN)
+
+/*
+ * ashmem_area - anonymous shared memory area
+ * Lifecycle: From our parent file's open() until its release()
+ * Locking: Protected by `ashmem_mutex'
+ * Big Note: Mappings do NOT pin this structure; it dies on close()
+ */
+struct ashmem_area {
+ char name[ASHMEM_FULL_NAME_LEN]; /* optional name in /proc/pid/maps */
+ struct list_head unpinned_list; /* list of all ashmem areas */
+ struct file *file; /* the shmem-based backing file */
+ size_t size; /* size of the mapping, in bytes */
+ unsigned long prot_mask; /* allowed prot bits, as vm_flags */
+};
+
+/*
+ * ashmem_range - represents an interval of unpinned (evictable) pages
+ * Lifecycle: From unpin to pin
+ * Locking: Protected by `ashmem_mutex'
+ */
+struct ashmem_range {
+ struct list_head lru; /* entry in LRU list */
+ struct list_head unpinned; /* entry in its area's unpinned list */
+ struct ashmem_area *asma; /* associated area */
+ size_t pgstart; /* starting page, inclusive */
+ size_t pgend; /* ending page, inclusive */
+ unsigned int purged; /* ASHMEM_NOT or ASHMEM_WAS_PURGED */
+};
+
+/* LRU list of unpinned pages, protected by ashmem_mutex */
+static LIST_HEAD(ashmem_lru_list);
+
+/* Count of pages on our LRU list, protected by ashmem_mutex */
+static unsigned long lru_count;
+
+/*
+ * ashmem_mutex - protects the list of and each individual ashmem_area
+ *
+ * Lock Ordering: ashmex_mutex -> i_mutex -> i_alloc_sem
+ */
+static DEFINE_MUTEX(ashmem_mutex);
+
+static struct kmem_cache *ashmem_area_cachep __read_mostly;
+static struct kmem_cache *ashmem_range_cachep __read_mostly;
+
+#define range_size(range) \
+ ((range)->pgend - (range)->pgstart + 1)
+
+#define range_on_lru(range) \
+ ((range)->purged == ASHMEM_NOT_PURGED)
+
+#define page_range_subsumes_range(range, start, end) \
+ (((range)->pgstart >= (start)) && ((range)->pgend <= (end)))
+
+#define page_range_subsumed_by_range(range, start, end) \
+ (((range)->pgstart <= (start)) && ((range)->pgend >= (end)))
+
+#define page_in_range(range, page) \
+ (((range)->pgstart <= (page)) && ((range)->pgend >= (page)))
+
+#define page_range_in_range(range, start, end) \
+ (page_in_range(range, start) || page_in_range(range, end) || \
+ page_range_subsumes_range(range, start, end))
+
+#define range_before_page(range, page) \
+ ((range)->pgend < (page))
+
+#define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE)
+
+static inline void lru_add(struct ashmem_range *range)
+{
+ list_add_tail(&range->lru, &ashmem_lru_list);
+ lru_count += range_size(range);
+}
+
+static inline void lru_del(struct ashmem_range *range)
+{
+ list_del(&range->lru);
+ lru_count -= range_size(range);
+}
+
+/*
+ * range_alloc - allocate and initialize a new ashmem_range structure
+ *
+ * 'asma' - associated ashmem_area
+ * 'prev_range' - the previous ashmem_range in the sorted asma->unpinned list
+ * 'purged' - initial purge value (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED)
+ * 'start' - starting page, inclusive
+ * 'end' - ending page, inclusive
+ *
+ * Caller must hold ashmem_mutex.
+ */
+static int range_alloc(struct ashmem_area *asma,
+ struct ashmem_range *prev_range, unsigned int purged,
+ size_t start, size_t end)
+{
+ struct ashmem_range *range;
+
+ range = kmem_cache_zalloc(ashmem_range_cachep, GFP_KERNEL);
+ if (unlikely(!range))
+ return -ENOMEM;
+
+ range->asma = asma;
+ range->pgstart = start;
+ range->pgend = end;
+ range->purged = purged;
+
+ list_add_tail(&range->unpinned, &prev_range->unpinned);
+
+ if (range_on_lru(range))
+ lru_add(range);
+
+ return 0;
+}
+
+static void range_del(struct ashmem_range *range)
+{
+ list_del(&range->unpinned);
+ if (range_on_lru(range))
+ lru_del(range);
+ kmem_cache_free(ashmem_range_cachep, range);
+}
+
+/*
+ * range_shrink - shrinks a range
+ *
+ * Caller must hold ashmem_mutex.
+ */
+static inline void range_shrink(struct ashmem_range *range,
+ size_t start, size_t end)
+{
+ size_t pre = range_size(range);
+
+ range->pgstart = start;
+ range->pgend = end;
+
+ if (range_on_lru(range))
+ lru_count -= pre - range_size(range);
+}
+
+static int ashmem_open(struct inode *inode, struct file *file)
+{
+ struct ashmem_area *asma;
+ int ret;
+
+ ret = generic_file_open(inode, file);
+ if (unlikely(ret))
+ return ret;
+
+ asma = kmem_cache_zalloc(ashmem_area_cachep, GFP_KERNEL);
+ if (unlikely(!asma))
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&asma->unpinned_list);
+ memcpy(asma->name, ASHMEM_NAME_PREFIX, ASHMEM_NAME_PREFIX_LEN);
+ asma->prot_mask = PROT_MASK;
+ file->private_data = asma;
+
+ return 0;
+}
+
+static int ashmem_release(struct inode *ignored, struct file *file)
+{
+ struct ashmem_area *asma = file->private_data;
+ struct ashmem_range *range, *next;
+
+ mutex_lock(&ashmem_mutex);
+ list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned)
+ range_del(range);
+ mutex_unlock(&ashmem_mutex);
+
+ if (asma->file)
+ fput(asma->file);
+ kmem_cache_free(ashmem_area_cachep, asma);
+
+ return 0;
+}
+
+static ssize_t ashmem_read(struct file *file, char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct ashmem_area *asma = file->private_data;
+ int ret = 0;
+
+ mutex_lock(&ashmem_mutex);
+
+ /* If size is not set, or set to 0, always return EOF. */
+ if (asma->size == 0)
+ goto out;
+
+ if (!asma->file) {
+ ret = -EBADF;
+ goto out;
+ }
+
+ ret = asma->file->f_op->read(asma->file, buf, len, pos);
+ if (ret < 0)
+ goto out;
+
+ /** Update backing file pos, since f_ops->read() doesn't */
+ asma->file->f_pos = *pos;
+
+out:
+ mutex_unlock(&ashmem_mutex);
+ return ret;
+}
+
+static loff_t ashmem_llseek(struct file *file, loff_t offset, int origin)
+{
+ struct ashmem_area *asma = file->private_data;
+ int ret;
+
+ mutex_lock(&ashmem_mutex);
+
+ if (asma->size == 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!asma->file) {
+ ret = -EBADF;
+ goto out;
+ }
+
+ ret = asma->file->f_op->llseek(asma->file, offset, origin);
+ if (ret < 0)
+ goto out;
+
+ /** Copy f_pos from backing file, since f_ops->llseek() sets it */
+ file->f_pos = asma->file->f_pos;
+
+out:
+ mutex_unlock(&ashmem_mutex);
+ return ret;
+}
+
+static inline unsigned long calc_vm_may_flags(unsigned long prot)
+{
+ return _calc_vm_trans(prot, PROT_READ, VM_MAYREAD) |
+ _calc_vm_trans(prot, PROT_WRITE, VM_MAYWRITE) |
+ _calc_vm_trans(prot, PROT_EXEC, VM_MAYEXEC);
+}
+
+static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct ashmem_area *asma = file->private_data;
+ int ret = 0;
+
+ mutex_lock(&ashmem_mutex);
+
+ /* user needs to SET_SIZE before mapping */
+ if (unlikely(!asma->size)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* requested protection bits must match our allowed protection mask */
+ if (unlikely((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask)) &
+ calc_vm_prot_bits(PROT_MASK))) {
+ ret = -EPERM;
+ goto out;
+ }
+ vma->vm_flags &= ~calc_vm_may_flags(~asma->prot_mask);
+
+ if (!asma->file) {
+ char *name = ASHMEM_NAME_DEF;
+ struct file *vmfile;
+
+ if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0')
+ name = asma->name;
+
+ /* ... and allocate the backing shmem file */
+ vmfile = shmem_file_setup(name, asma->size, vma->vm_flags);
+ if (unlikely(IS_ERR(vmfile))) {
+ ret = PTR_ERR(vmfile);
+ goto out;
+ }
+ asma->file = vmfile;
+ }
+ get_file(asma->file);
+
+ /*
+ * XXX - Reworked to use shmem_zero_setup() instead of
+ * shmem_set_file while we're in staging. -jstultz
+ */
+ if (vma->vm_flags & VM_SHARED) {
+ ret = shmem_zero_setup(vma);
+ if (ret) {
+ fput(asma->file);
+ goto out;
+ }
+ }
+
+ if (vma->vm_file)
+ fput(vma->vm_file);
+ vma->vm_file = asma->file;
+ vma->vm_flags |= VM_CAN_NONLINEAR;
+
+out:
+ mutex_unlock(&ashmem_mutex);
+ return ret;
+}
+
+/*
+ * ashmem_shrink - our cache shrinker, called from mm/vmscan.c :: shrink_slab
+ *
+ * 'nr_to_scan' is the number of objects (pages) to prune, or 0 to query how
+ * many objects (pages) we have in total.
+ *
+ * 'gfp_mask' is the mask of the allocation that got us into this mess.
+ *
+ * Return value is the number of objects (pages) remaining, or -1 if we cannot
+ * proceed without risk of deadlock (due to gfp_mask).
+ *
+ * We approximate LRU via least-recently-unpinned, jettisoning unpinned partial
+ * chunks of ashmem regions LRU-wise one-at-a-time until we hit 'nr_to_scan'
+ * pages freed.
+ */
+static int ashmem_shrink(struct shrinker *s, struct shrink_control *sc)
+{
+ struct ashmem_range *range, *next;
+
+ /* We might recurse into filesystem code, so bail out if necessary */
+ if (sc->nr_to_scan && !(sc->gfp_mask & __GFP_FS))
+ return -1;
+ if (!sc->nr_to_scan)
+ return lru_count;
+
+ mutex_lock(&ashmem_mutex);
+ list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) {
+ struct inode *inode = range->asma->file->f_dentry->d_inode;
+ loff_t start = range->pgstart * PAGE_SIZE;
+ loff_t end = (range->pgend + 1) * PAGE_SIZE - 1;
+
+ vmtruncate_range(inode, start, end);
+ range->purged = ASHMEM_WAS_PURGED;
+ lru_del(range);
+
+ sc->nr_to_scan -= range_size(range);
+ if (sc->nr_to_scan <= 0)
+ break;
+ }
+ mutex_unlock(&ashmem_mutex);
+
+ return lru_count;
+}
+
+static struct shrinker ashmem_shrinker = {
+ .shrink = ashmem_shrink,
+ .seeks = DEFAULT_SEEKS * 4,
+};
+
+static int set_prot_mask(struct ashmem_area *asma, unsigned long prot)
+{
+ int ret = 0;
+
+ mutex_lock(&ashmem_mutex);
+
+ /* the user can only remove, not add, protection bits */
+ if (unlikely((asma->prot_mask & prot) != prot)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* does the application expect PROT_READ to imply PROT_EXEC? */
+ if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
+ prot |= PROT_EXEC;
+
+ asma->prot_mask = prot;
+
+out:
+ mutex_unlock(&ashmem_mutex);
+ return ret;
+}
+
+static int set_name(struct ashmem_area *asma, void __user *name)
+{
+ int ret = 0;
+
+ 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;
+ asma->name[ASHMEM_FULL_NAME_LEN-1] = '\0';
+
+out:
+ mutex_unlock(&ashmem_mutex);
+
+ return ret;
+}
+
+static int get_name(struct ashmem_area *asma, void __user *name)
+{
+ int ret = 0;
+
+ 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;
+ } else {
+ if (unlikely(copy_to_user(name, ASHMEM_NAME_DEF,
+ sizeof(ASHMEM_NAME_DEF))))
+ ret = -EFAULT;
+ }
+ mutex_unlock(&ashmem_mutex);
+
+ return ret;
+}
+
+/*
+ * ashmem_pin - pin the given ashmem region, returning whether it was
+ * previously purged (ASHMEM_WAS_PURGED) or not (ASHMEM_NOT_PURGED).
+ *
+ * Caller must hold ashmem_mutex.
+ */
+static int ashmem_pin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
+{
+ struct ashmem_range *range, *next;
+ int ret = ASHMEM_NOT_PURGED;
+
+ list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) {
+ /* moved past last applicable page; we can short circuit */
+ if (range_before_page(range, pgstart))
+ break;
+
+ /*
+ * The user can ask us to pin pages that span multiple ranges,
+ * or to pin pages that aren't even unpinned, so this is messy.
+ *
+ * Four cases:
+ * 1. The requested range subsumes an existing range, so we
+ * just remove the entire matching range.
+ * 2. The requested range overlaps the start of an existing
+ * range, so we just update that range.
+ * 3. The requested range overlaps the end of an existing
+ * range, so we just update that range.
+ * 4. The requested range punches a hole in an existing range,
+ * so we have to update one side of the range and then
+ * create a new range for the other side.
+ */
+ if (page_range_in_range(range, pgstart, pgend)) {
+ ret |= range->purged;
+
+ /* Case #1: Easy. Just nuke the whole thing. */
+ if (page_range_subsumes_range(range, pgstart, pgend)) {
+ range_del(range);
+ continue;
+ }
+
+ /* Case #2: We overlap from the start, so adjust it */
+ if (range->pgstart >= pgstart) {
+ range_shrink(range, pgend + 1, range->pgend);
+ continue;
+ }
+
+ /* Case #3: We overlap from the rear, so adjust it */
+ if (range->pgend <= pgend) {
+ range_shrink(range, range->pgstart, pgstart-1);
+ continue;
+ }
+
+ /*
+ * Case #4: We eat a chunk out of the middle. A bit
+ * more complicated, we allocate a new range for the
+ * second half and adjust the first chunk's endpoint.
+ */
+ range_alloc(asma, range, range->purged,
+ pgend + 1, range->pgend);
+ range_shrink(range, range->pgstart, pgstart - 1);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * ashmem_unpin - unpin the given range of pages. Returns zero on success.
+ *
+ * Caller must hold ashmem_mutex.
+ */
+static int ashmem_unpin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
+{
+ struct ashmem_range *range, *next;
+ unsigned int purged = ASHMEM_NOT_PURGED;
+
+restart:
+ list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) {
+ /* short circuit: this is our insertion point */
+ if (range_before_page(range, pgstart))
+ break;
+
+ /*
+ * The user can ask us to unpin pages that are already entirely
+ * or partially pinned. We handle those two cases here.
+ */
+ if (page_range_subsumed_by_range(range, pgstart, pgend))
+ return 0;
+ if (page_range_in_range(range, pgstart, pgend)) {
+ pgstart = min_t(size_t, range->pgstart, pgstart),
+ pgend = max_t(size_t, range->pgend, pgend);
+ purged |= range->purged;
+ range_del(range);
+ goto restart;
+ }
+ }
+
+ return range_alloc(asma, range, purged, pgstart, pgend);
+}
+
+/*
+ * ashmem_get_pin_status - Returns ASHMEM_IS_UNPINNED if _any_ pages in the
+ * given interval are unpinned and ASHMEM_IS_PINNED otherwise.
+ *
+ * Caller must hold ashmem_mutex.
+ */
+static int ashmem_get_pin_status(struct ashmem_area *asma, size_t pgstart,
+ size_t pgend)
+{
+ struct ashmem_range *range;
+ int ret = ASHMEM_IS_PINNED;
+
+ list_for_each_entry(range, &asma->unpinned_list, unpinned) {
+ if (range_before_page(range, pgstart))
+ break;
+ if (page_range_in_range(range, pgstart, pgend)) {
+ ret = ASHMEM_IS_UNPINNED;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
+ void __user *p)
+{
+ struct ashmem_pin pin;
+ size_t pgstart, pgend;
+ int ret = -EINVAL;
+
+ if (unlikely(!asma->file))
+ return -EINVAL;
+
+ if (unlikely(copy_from_user(&pin, p, sizeof(pin))))
+ return -EFAULT;
+
+ /* per custom, you can pass zero for len to mean "everything onward" */
+ if (!pin.len)
+ pin.len = PAGE_ALIGN(asma->size) - pin.offset;
+
+ if (unlikely((pin.offset | pin.len) & ~PAGE_MASK))
+ return -EINVAL;
+
+ if (unlikely(((__u32) -1) - pin.offset < pin.len))
+ return -EINVAL;
+
+ if (unlikely(PAGE_ALIGN(asma->size) < pin.offset + pin.len))
+ return -EINVAL;
+
+ pgstart = pin.offset / PAGE_SIZE;
+ pgend = pgstart + (pin.len / PAGE_SIZE) - 1;
+
+ mutex_lock(&ashmem_mutex);
+
+ switch (cmd) {
+ case ASHMEM_PIN:
+ ret = ashmem_pin(asma, pgstart, pgend);
+ break;
+ case ASHMEM_UNPIN:
+ ret = ashmem_unpin(asma, pgstart, pgend);
+ break;
+ case ASHMEM_GET_PIN_STATUS:
+ ret = ashmem_get_pin_status(asma, pgstart, pgend);
+ break;
+ }
+
+ mutex_unlock(&ashmem_mutex);
+
+ return ret;
+}
+
+static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct ashmem_area *asma = file->private_data;
+ long ret = -ENOTTY;
+
+ switch (cmd) {
+ case ASHMEM_SET_NAME:
+ ret = set_name(asma, (void __user *) arg);
+ break;
+ case ASHMEM_GET_NAME:
+ ret = get_name(asma, (void __user *) arg);
+ break;
+ case ASHMEM_SET_SIZE:
+ ret = -EINVAL;
+ if (!asma->file) {
+ ret = 0;
+ asma->size = (size_t) arg;
+ }
+ break;
+ case ASHMEM_GET_SIZE:
+ ret = asma->size;
+ break;
+ case ASHMEM_SET_PROT_MASK:
+ ret = set_prot_mask(asma, arg);
+ break;
+ case ASHMEM_GET_PROT_MASK:
+ ret = asma->prot_mask;
+ break;
+ case ASHMEM_PIN:
+ case ASHMEM_UNPIN:
+ case ASHMEM_GET_PIN_STATUS:
+ ret = ashmem_pin_unpin(asma, cmd, (void __user *) arg);
+ break;
+ case ASHMEM_PURGE_ALL_CACHES:
+ ret = -EPERM;
+ if (capable(CAP_SYS_ADMIN)) {
+ struct shrink_control sc = {
+ .gfp_mask = GFP_KERNEL,
+ .nr_to_scan = 0,
+ };
+ ret = ashmem_shrink(&ashmem_shrinker, &sc);
+ sc.nr_to_scan = ret;
+ ashmem_shrink(&ashmem_shrinker, &sc);
+ }
+ break;
+ }
+
+ return ret;
+}
+
+static struct file_operations ashmem_fops = {
+ .owner = THIS_MODULE,
+ .open = ashmem_open,
+ .release = ashmem_release,
+ .read = ashmem_read,
+ .llseek = ashmem_llseek,
+ .mmap = ashmem_mmap,
+ .unlocked_ioctl = ashmem_ioctl,
+ .compat_ioctl = ashmem_ioctl,
+};
+
+static struct miscdevice ashmem_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "ashmem",
+ .fops = &ashmem_fops,
+};
+
+static int __init ashmem_init(void)
+{
+ int ret;
+
+ ashmem_area_cachep = kmem_cache_create("ashmem_area_cache",
+ sizeof(struct ashmem_area),
+ 0, 0, NULL);
+ if (unlikely(!ashmem_area_cachep)) {
+ printk(KERN_ERR "ashmem: failed to create slab cache\n");
+ return -ENOMEM;
+ }
+
+ ashmem_range_cachep = kmem_cache_create("ashmem_range_cache",
+ sizeof(struct ashmem_range),
+ 0, 0, NULL);
+ if (unlikely(!ashmem_range_cachep)) {
+ printk(KERN_ERR "ashmem: failed to create slab cache\n");
+ return -ENOMEM;
+ }
+
+ ret = misc_register(&ashmem_misc);
+ if (unlikely(ret)) {
+ printk(KERN_ERR "ashmem: failed to register misc device!\n");
+ return ret;
+ }
+
+ register_shrinker(&ashmem_shrinker);
+
+ printk(KERN_INFO "ashmem: initialized\n");
+
+ return 0;
+}
+
+static void __exit ashmem_exit(void)
+{
+ int ret;
+
+ unregister_shrinker(&ashmem_shrinker);
+
+ ret = misc_deregister(&ashmem_misc);
+ if (unlikely(ret))
+ printk(KERN_ERR "ashmem: failed to unregister misc device!\n");
+
+ kmem_cache_destroy(ashmem_range_cachep);
+ kmem_cache_destroy(ashmem_area_cachep);
+
+ printk(KERN_INFO "ashmem: unloaded\n");
+}
+
+module_init(ashmem_init);
+module_exit(ashmem_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/android/ashmem.h b/drivers/staging/android/ashmem.h
new file mode 100644
index 000000000000..1976b10ef93e
--- /dev/null
+++ b/drivers/staging/android/ashmem.h
@@ -0,0 +1,48 @@
+/*
+ * include/linux/ashmem.h
+ *
+ * Copyright 2008 Google Inc.
+ * Author: Robert Love
+ *
+ * This file is dual licensed. It may be redistributed and/or modified
+ * under the terms of the Apache 2.0 License OR version 2 of the GNU
+ * General Public License.
+ */
+
+#ifndef _LINUX_ASHMEM_H
+#define _LINUX_ASHMEM_H
+
+#include <linux/limits.h>
+#include <linux/ioctl.h>
+
+#define ASHMEM_NAME_LEN 256
+
+#define ASHMEM_NAME_DEF "dev/ashmem"
+
+/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
+#define ASHMEM_NOT_PURGED 0
+#define ASHMEM_WAS_PURGED 1
+
+/* Return values from ASHMEM_GET_PIN_STATUS: Is the mapping pinned? */
+#define ASHMEM_IS_UNPINNED 0
+#define ASHMEM_IS_PINNED 1
+
+struct ashmem_pin {
+ __u32 offset; /* offset into region, in bytes, page-aligned */
+ __u32 len; /* length forward from offset, in bytes, page-aligned */
+};
+
+#define __ASHMEMIOC 0x77
+
+#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
+#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
+#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t)
+#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4)
+#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long)
+#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6)
+#define ASHMEM_PIN _IOW(__ASHMEMIOC, 7, struct ashmem_pin)
+#define ASHMEM_UNPIN _IOW(__ASHMEMIOC, 8, struct ashmem_pin)
+#define ASHMEM_GET_PIN_STATUS _IO(__ASHMEMIOC, 9)
+#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
+
+#endif /* _LINUX_ASHMEM_H */
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
new file mode 100644
index 000000000000..7491801a661c
--- /dev/null
+++ b/drivers/staging/android/binder.c
@@ -0,0 +1,3600 @@
+/* binder.c
+ *
+ * Android IPC Subsystem
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/fdtable.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/nsproxy.h>
+#include <linux/poll.h>
+#include <linux/debugfs.h>
+#include <linux/rbtree.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+#include "binder.h"
+
+static DEFINE_MUTEX(binder_lock);
+static DEFINE_MUTEX(binder_deferred_lock);
+
+static HLIST_HEAD(binder_procs);
+static HLIST_HEAD(binder_deferred_list);
+static HLIST_HEAD(binder_dead_nodes);
+
+static struct dentry *binder_debugfs_dir_entry_root;
+static struct dentry *binder_debugfs_dir_entry_proc;
+static struct binder_node *binder_context_mgr_node;
+static uid_t binder_context_mgr_uid = -1;
+static int binder_last_id;
+static struct workqueue_struct *binder_deferred_workqueue;
+
+#define BINDER_DEBUG_ENTRY(name) \
+static int binder_##name##_open(struct inode *inode, struct file *file) \
+{ \
+ return single_open(file, binder_##name##_show, inode->i_private); \
+} \
+\
+static const struct file_operations binder_##name##_fops = { \
+ .owner = THIS_MODULE, \
+ .open = binder_##name##_open, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+}
+
+static int binder_proc_show(struct seq_file *m, void *unused);
+BINDER_DEBUG_ENTRY(proc);
+
+/* This is only defined in include/asm-arm/sizes.h */
+#ifndef SZ_1K
+#define SZ_1K 0x400
+#endif
+
+#ifndef SZ_4M
+#define SZ_4M 0x400000
+#endif
+
+#define FORBIDDEN_MMAP_FLAGS (VM_WRITE)
+
+#define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64)
+
+enum {
+ BINDER_DEBUG_USER_ERROR = 1U << 0,
+ BINDER_DEBUG_FAILED_TRANSACTION = 1U << 1,
+ BINDER_DEBUG_DEAD_TRANSACTION = 1U << 2,
+ BINDER_DEBUG_OPEN_CLOSE = 1U << 3,
+ BINDER_DEBUG_DEAD_BINDER = 1U << 4,
+ BINDER_DEBUG_DEATH_NOTIFICATION = 1U << 5,
+ BINDER_DEBUG_READ_WRITE = 1U << 6,
+ BINDER_DEBUG_USER_REFS = 1U << 7,
+ BINDER_DEBUG_THREADS = 1U << 8,
+ BINDER_DEBUG_TRANSACTION = 1U << 9,
+ BINDER_DEBUG_TRANSACTION_COMPLETE = 1U << 10,
+ BINDER_DEBUG_FREE_BUFFER = 1U << 11,
+ BINDER_DEBUG_INTERNAL_REFS = 1U << 12,
+ BINDER_DEBUG_BUFFER_ALLOC = 1U << 13,
+ BINDER_DEBUG_PRIORITY_CAP = 1U << 14,
+ BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 15,
+};
+static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
+ BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
+module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
+
+static int binder_debug_no_lock;
+module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO);
+
+static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
+static int binder_stop_on_user_error;
+
+static int binder_set_stop_on_user_error(const char *val,
+ struct kernel_param *kp)
+{
+ int ret;
+ ret = param_set_int(val, kp);
+ if (binder_stop_on_user_error < 2)
+ wake_up(&binder_user_error_wait);
+ return ret;
+}
+module_param_call(stop_on_user_error, binder_set_stop_on_user_error,
+ param_get_int, &binder_stop_on_user_error, S_IWUSR | S_IRUGO);
+
+#define binder_debug(mask, x...) \
+ do { \
+ if (binder_debug_mask & mask) \
+ printk(KERN_INFO x); \
+ } while (0)
+
+#define binder_user_error(x...) \
+ do { \
+ if (binder_debug_mask & BINDER_DEBUG_USER_ERROR) \
+ printk(KERN_INFO x); \
+ if (binder_stop_on_user_error) \
+ binder_stop_on_user_error = 2; \
+ } while (0)
+
+enum binder_stat_types {
+ BINDER_STAT_PROC,
+ BINDER_STAT_THREAD,
+ BINDER_STAT_NODE,
+ BINDER_STAT_REF,
+ BINDER_STAT_DEATH,
+ BINDER_STAT_TRANSACTION,
+ BINDER_STAT_TRANSACTION_COMPLETE,
+ BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+ int br[_IOC_NR(BR_FAILED_REPLY) + 1];
+ int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1];
+ int obj_created[BINDER_STAT_COUNT];
+ int obj_deleted[BINDER_STAT_COUNT];
+};
+
+static struct binder_stats binder_stats;
+
+static inline void binder_stats_deleted(enum binder_stat_types type)
+{
+ binder_stats.obj_deleted[type]++;
+}
+
+static inline void binder_stats_created(enum binder_stat_types type)
+{
+ binder_stats.obj_created[type]++;
+}
+
+struct binder_transaction_log_entry {
+ int debug_id;
+ int call_type;
+ int from_proc;
+ int from_thread;
+ int target_handle;
+ int to_proc;
+ int to_thread;
+ int to_node;
+ int data_size;
+ int offsets_size;
+};
+struct binder_transaction_log {
+ int next;
+ int full;
+ struct binder_transaction_log_entry entry[32];
+};
+static struct binder_transaction_log binder_transaction_log;
+static struct binder_transaction_log binder_transaction_log_failed;
+
+static struct binder_transaction_log_entry *binder_transaction_log_add(
+ struct binder_transaction_log *log)
+{
+ struct binder_transaction_log_entry *e;
+ e = &log->entry[log->next];
+ memset(e, 0, sizeof(*e));
+ log->next++;
+ if (log->next == ARRAY_SIZE(log->entry)) {
+ log->next = 0;
+ log->full = 1;
+ }
+ return e;
+}
+
+struct binder_work {
+ struct list_head entry;
+ enum {
+ BINDER_WORK_TRANSACTION = 1,
+ BINDER_WORK_TRANSACTION_COMPLETE,
+ BINDER_WORK_NODE,
+ BINDER_WORK_DEAD_BINDER,
+ BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+ BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+ } type;
+};
+
+struct binder_node {
+ int debug_id;
+ struct binder_work work;
+ union {
+ struct rb_node rb_node;
+ struct hlist_node dead_node;
+ };
+ struct binder_proc *proc;
+ struct hlist_head refs;
+ int internal_strong_refs;
+ int local_weak_refs;
+ int local_strong_refs;
+ void __user *ptr;
+ void __user *cookie;
+ unsigned has_strong_ref:1;
+ unsigned pending_strong_ref:1;
+ unsigned has_weak_ref:1;
+ unsigned pending_weak_ref:1;
+ unsigned has_async_transaction:1;
+ unsigned accept_fds:1;
+ unsigned min_priority:8;
+ struct list_head async_todo;
+};
+
+struct binder_ref_death {
+ struct binder_work work;
+ void __user *cookie;
+};
+
+struct binder_ref {
+ /* Lookups needed: */
+ /* node + proc => ref (transaction) */
+ /* desc + proc => ref (transaction, inc/dec ref) */
+ /* node => refs + procs (proc exit) */
+ int debug_id;
+ struct rb_node rb_node_desc;
+ struct rb_node rb_node_node;
+ struct hlist_node node_entry;
+ struct binder_proc *proc;
+ struct binder_node *node;
+ uint32_t desc;
+ int strong;
+ int weak;
+ struct binder_ref_death *death;
+};
+
+struct binder_buffer {
+ struct list_head entry; /* free and allocated entries by addesss */
+ struct rb_node rb_node; /* free entry by size or allocated entry */
+ /* by address */
+ unsigned free:1;
+ unsigned allow_user_free:1;
+ unsigned async_transaction:1;
+ unsigned debug_id:29;
+
+ struct binder_transaction *transaction;
+
+ struct binder_node *target_node;
+ size_t data_size;
+ size_t offsets_size;
+ uint8_t data[0];
+};
+
+enum binder_deferred_state {
+ BINDER_DEFERRED_PUT_FILES = 0x01,
+ BINDER_DEFERRED_FLUSH = 0x02,
+ BINDER_DEFERRED_RELEASE = 0x04,
+};
+
+struct binder_proc {
+ struct hlist_node proc_node;
+ struct rb_root threads;
+ struct rb_root nodes;
+ struct rb_root refs_by_desc;
+ struct rb_root refs_by_node;
+ int pid;
+ struct vm_area_struct *vma;
+ struct task_struct *tsk;
+ struct files_struct *files;
+ struct hlist_node deferred_work_node;
+ int deferred_work;
+ void *buffer;
+ ptrdiff_t user_buffer_offset;
+
+ struct list_head buffers;
+ struct rb_root free_buffers;
+ struct rb_root allocated_buffers;
+ size_t free_async_space;
+
+ struct page **pages;
+ size_t buffer_size;
+ uint32_t buffer_free;
+ struct list_head todo;
+ wait_queue_head_t wait;
+ struct binder_stats stats;
+ struct list_head delivered_death;
+ int max_threads;
+ int requested_threads;
+ int requested_threads_started;
+ int ready_threads;
+ long default_priority;
+ struct dentry *debugfs_entry;
+};
+
+enum {
+ BINDER_LOOPER_STATE_REGISTERED = 0x01,
+ BINDER_LOOPER_STATE_ENTERED = 0x02,
+ BINDER_LOOPER_STATE_EXITED = 0x04,
+ BINDER_LOOPER_STATE_INVALID = 0x08,
+ BINDER_LOOPER_STATE_WAITING = 0x10,
+ BINDER_LOOPER_STATE_NEED_RETURN = 0x20
+};
+
+struct binder_thread {
+ struct binder_proc *proc;
+ struct rb_node rb_node;
+ int pid;
+ int looper;
+ struct binder_transaction *transaction_stack;
+ struct list_head todo;
+ uint32_t return_error; /* Write failed, return error code in read buf */
+ uint32_t return_error2; /* Write failed, return error code in read */
+ /* buffer. Used when sending a reply to a dead process that */
+ /* we are also waiting on */
+ wait_queue_head_t wait;
+ struct binder_stats stats;
+};
+
+struct binder_transaction {
+ int debug_id;
+ struct binder_work work;
+ struct binder_thread *from;
+ struct binder_transaction *from_parent;
+ struct binder_proc *to_proc;
+ struct binder_thread *to_thread;
+ struct binder_transaction *to_parent;
+ unsigned need_reply:1;
+ /* unsigned is_dead:1; */ /* not used at the moment */
+
+ struct binder_buffer *buffer;
+ unsigned int code;
+ unsigned int flags;
+ long priority;
+ long saved_priority;
+ uid_t sender_euid;
+};
+
+static void
+binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer);
+
+/*
+ * copied from get_unused_fd_flags
+ */
+int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
+{
+ struct files_struct *files = proc->files;
+ int fd, error;
+ struct fdtable *fdt;
+ unsigned long rlim_cur;
+ unsigned long irqs;
+
+ if (files == NULL)
+ return -ESRCH;
+
+ error = -EMFILE;
+ spin_lock(&files->file_lock);
+
+repeat:
+ fdt = files_fdtable(files);
+ fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
+ files->next_fd);
+
+ /*
+ * N.B. For clone tasks sharing a files structure, this test
+ * will limit the total number of files that can be opened.
+ */
+ rlim_cur = 0;
+ if (lock_task_sighand(proc->tsk, &irqs)) {
+ rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+ unlock_task_sighand(proc->tsk, &irqs);
+ }
+ if (fd >= rlim_cur)
+ goto out;
+
+ /* Do we need to expand the fd array or fd set? */
+ error = expand_files(files, fd);
+ if (error < 0)
+ goto out;
+
+ if (error) {
+ /*
+ * If we needed to expand the fs array we
+ * might have blocked - try again.
+ */
+ error = -EMFILE;
+ goto repeat;
+ }
+
+ FD_SET(fd, fdt->open_fds);
+ if (flags & O_CLOEXEC)
+ FD_SET(fd, fdt->close_on_exec);
+ else
+ FD_CLR(fd, fdt->close_on_exec);
+ files->next_fd = fd + 1;
+#if 1
+ /* Sanity check */
+ if (fdt->fd[fd] != NULL) {
+ printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
+ fdt->fd[fd] = NULL;
+ }
+#endif
+ error = fd;
+
+out:
+ spin_unlock(&files->file_lock);
+ return error;
+}
+
+/*
+ * copied from fd_install
+ */
+static void task_fd_install(
+ struct binder_proc *proc, unsigned int fd, struct file *file)
+{
+ struct files_struct *files = proc->files;
+ struct fdtable *fdt;
+
+ if (files == NULL)
+ return;
+
+ spin_lock(&files->file_lock);
+ fdt = files_fdtable(files);
+ BUG_ON(fdt->fd[fd] != NULL);
+ rcu_assign_pointer(fdt->fd[fd], file);
+ spin_unlock(&files->file_lock);
+}
+
+/*
+ * copied from __put_unused_fd in open.c
+ */
+static void __put_unused_fd(struct files_struct *files, unsigned int fd)
+{
+ struct fdtable *fdt = files_fdtable(files);
+ __FD_CLR(fd, fdt->open_fds);
+ if (fd < files->next_fd)
+ files->next_fd = fd;
+}
+
+/*
+ * copied from sys_close
+ */
+static long task_close_fd(struct binder_proc *proc, unsigned int fd)
+{
+ struct file *filp;
+ struct files_struct *files = proc->files;
+ struct fdtable *fdt;
+ int retval;
+
+ if (files == NULL)
+ return -ESRCH;
+
+ spin_lock(&files->file_lock);
+ fdt = files_fdtable(files);
+ if (fd >= fdt->max_fds)
+ goto out_unlock;
+ filp = fdt->fd[fd];
+ if (!filp)
+ goto out_unlock;
+ rcu_assign_pointer(fdt->fd[fd], NULL);
+ FD_CLR(fd, fdt->close_on_exec);
+ __put_unused_fd(files, fd);
+ spin_unlock(&files->file_lock);
+ retval = filp_close(filp, files);
+
+ /* can't restart close syscall because file table entry was cleared */
+ if (unlikely(retval == -ERESTARTSYS ||
+ retval == -ERESTARTNOINTR ||
+ retval == -ERESTARTNOHAND ||
+ retval == -ERESTART_RESTARTBLOCK))
+ retval = -EINTR;
+
+ return retval;
+
+out_unlock:
+ spin_unlock(&files->file_lock);
+ return -EBADF;
+}
+
+static void binder_set_nice(long nice)
+{
+ long min_nice;
+ if (can_nice(current, nice)) {
+ set_user_nice(current, nice);
+ return;
+ }
+ min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur;
+ binder_debug(BINDER_DEBUG_PRIORITY_CAP,
+ "binder: %d: nice value %ld not allowed use "
+ "%ld instead\n", current->pid, nice, min_nice);
+ set_user_nice(current, min_nice);
+ if (min_nice < 20)
+ return;
+ binder_user_error("binder: %d RLIMIT_NICE not set\n", current->pid);
+}
+
+static size_t binder_buffer_size(struct binder_proc *proc,
+ struct binder_buffer *buffer)
+{
+ if (list_is_last(&buffer->entry, &proc->buffers))
+ return proc->buffer + proc->buffer_size - (void *)buffer->data;
+ else
+ return (size_t)list_entry(buffer->entry.next,
+ struct binder_buffer, entry) - (size_t)buffer->data;
+}
+
+static void binder_insert_free_buffer(struct binder_proc *proc,
+ struct binder_buffer *new_buffer)
+{
+ struct rb_node **p = &proc->free_buffers.rb_node;
+ struct rb_node *parent = NULL;
+ struct binder_buffer *buffer;
+ size_t buffer_size;
+ size_t new_buffer_size;
+
+ BUG_ON(!new_buffer->free);
+
+ new_buffer_size = binder_buffer_size(proc, new_buffer);
+
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "binder: %d: add free buffer, size %zd, "
+ "at %p\n", proc->pid, new_buffer_size, new_buffer);
+
+ while (*p) {
+ parent = *p;
+ buffer = rb_entry(parent, struct binder_buffer, rb_node);
+ BUG_ON(!buffer->free);
+
+ buffer_size = binder_buffer_size(proc, buffer);
+
+ if (new_buffer_size < buffer_size)
+ p = &parent->rb_left;
+ else
+ p = &parent->rb_right;
+ }
+ rb_link_node(&new_buffer->rb_node, parent, p);
+ rb_insert_color(&new_buffer->rb_node, &proc->free_buffers);
+}
+
+static void binder_insert_allocated_buffer(struct binder_proc *proc,
+ struct binder_buffer *new_buffer)
+{
+ struct rb_node **p = &proc->allocated_buffers.rb_node;
+ struct rb_node *parent = NULL;
+ struct binder_buffer *buffer;
+
+ BUG_ON(new_buffer->free);
+
+ while (*p) {
+ parent = *p;
+ buffer = rb_entry(parent, struct binder_buffer, rb_node);
+ BUG_ON(buffer->free);
+
+ if (new_buffer < buffer)
+ p = &parent->rb_left;
+ else if (new_buffer > buffer)
+ p = &parent->rb_right;
+ else
+ BUG();
+ }
+ rb_link_node(&new_buffer->rb_node, parent, p);
+ rb_insert_color(&new_buffer->rb_node, &proc->allocated_buffers);
+}
+
+static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc,
+ void __user *user_ptr)
+{
+ struct rb_node *n = proc->allocated_buffers.rb_node;
+ struct binder_buffer *buffer;
+ struct binder_buffer *kern_ptr;
+
+ kern_ptr = user_ptr - proc->user_buffer_offset
+ - offsetof(struct binder_buffer, data);
+
+ while (n) {
+ buffer = rb_entry(n, struct binder_buffer, rb_node);
+ BUG_ON(buffer->free);
+
+ if (kern_ptr < buffer)
+ n = n->rb_left;
+ else if (kern_ptr > buffer)
+ n = n->rb_right;
+ else
+ return buffer;
+ }
+ return NULL;
+}
+
+static int binder_update_page_range(struct binder_proc *proc, int allocate,
+ void *start, void *end,
+ struct vm_area_struct *vma)
+{
+ void *page_addr;
+ unsigned long user_page_addr;
+ struct vm_struct tmp_area;
+ struct page **page;
+ struct mm_struct *mm;
+
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "binder: %d: %s pages %p-%p\n", proc->pid,
+ allocate ? "allocate" : "free", start, end);
+
+ if (end <= start)
+ return 0;
+
+ if (vma)
+ mm = NULL;
+ else
+ mm = get_task_mm(proc->tsk);
+
+ if (mm) {
+ down_write(&mm->mmap_sem);
+ vma = proc->vma;
+ }
+
+ if (allocate == 0)
+ goto free_range;
+
+ if (vma == NULL) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf failed to "
+ "map pages in userspace, no vma\n", proc->pid);
+ goto err_no_vma;
+ }
+
+ for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
+ int ret;
+ struct page **page_array_ptr;
+ page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
+
+ BUG_ON(*page);
+ *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (*page == NULL) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+ "for page at %p\n", proc->pid, page_addr);
+ goto err_alloc_page_failed;
+ }
+ tmp_area.addr = page_addr;
+ tmp_area.size = PAGE_SIZE + PAGE_SIZE /* guard page? */;
+ page_array_ptr = page;
+ ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);
+ if (ret) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+ "to map page at %p in kernel\n",
+ proc->pid, page_addr);
+ goto err_map_kernel_failed;
+ }
+ user_page_addr =
+ (uintptr_t)page_addr + proc->user_buffer_offset;
+ ret = vm_insert_page(vma, user_page_addr, page[0]);
+ if (ret) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+ "to map page at %lx in userspace\n",
+ proc->pid, user_page_addr);
+ goto err_vm_insert_page_failed;
+ }
+ /* vm_insert_page does not seem to increment the refcount */
+ }
+ if (mm) {
+ up_write(&mm->mmap_sem);
+ mmput(mm);
+ }
+ return 0;
+
+free_range:
+ for (page_addr = end - PAGE_SIZE; page_addr >= start;
+ page_addr -= PAGE_SIZE) {
+ page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
+ if (vma)
+ zap_page_range(vma, (uintptr_t)page_addr +
+ proc->user_buffer_offset, PAGE_SIZE, NULL);
+err_vm_insert_page_failed:
+ unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
+err_map_kernel_failed:
+ __free_page(*page);
+ *page = NULL;
+err_alloc_page_failed:
+ ;
+ }
+err_no_vma:
+ if (mm) {
+ up_write(&mm->mmap_sem);
+ mmput(mm);
+ }
+ return -ENOMEM;
+}
+
+static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
+ size_t data_size,
+ size_t offsets_size, int is_async)
+{
+ struct rb_node *n = proc->free_buffers.rb_node;
+ struct binder_buffer *buffer;
+ size_t buffer_size;
+ struct rb_node *best_fit = NULL;
+ void *has_page_addr;
+ void *end_page_addr;
+ size_t size;
+
+ if (proc->vma == NULL) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf, no vma\n",
+ proc->pid);
+ return NULL;
+ }
+
+ size = ALIGN(data_size, sizeof(void *)) +
+ ALIGN(offsets_size, sizeof(void *));
+
+ if (size < data_size || size < offsets_size) {
+ binder_user_error("binder: %d: got transaction with invalid "
+ "size %zd-%zd\n", proc->pid, data_size, offsets_size);
+ return NULL;
+ }
+
+ if (is_async &&
+ proc->free_async_space < size + sizeof(struct binder_buffer)) {
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "binder: %d: binder_alloc_buf size %zd"
+ "failed, no async space left\n", proc->pid, size);
+ return NULL;
+ }
+
+ while (n) {
+ buffer = rb_entry(n, struct binder_buffer, rb_node);
+ BUG_ON(!buffer->free);
+ buffer_size = binder_buffer_size(proc, buffer);
+
+ if (size < buffer_size) {
+ best_fit = n;
+ n = n->rb_left;
+ } else if (size > buffer_size)
+ n = n->rb_right;
+ else {
+ best_fit = n;
+ break;
+ }
+ }
+ if (best_fit == NULL) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd failed, "
+ "no address space\n", proc->pid, size);
+ return NULL;
+ }
+ if (n == NULL) {
+ buffer = rb_entry(best_fit, struct binder_buffer, rb_node);
+ buffer_size = binder_buffer_size(proc, buffer);
+ }
+
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "binder: %d: binder_alloc_buf size %zd got buff"
+ "er %p size %zd\n", proc->pid, size, buffer, buffer_size);
+
+ has_page_addr =
+ (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
+ if (n == NULL) {
+ if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
+ buffer_size = size; /* no room for other buffers */
+ else
+ buffer_size = size + sizeof(struct binder_buffer);
+ }
+ end_page_addr =
+ (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
+ if (end_page_addr > has_page_addr)
+ end_page_addr = has_page_addr;
+ if (binder_update_page_range(proc, 1,
+ (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL))
+ return NULL;
+
+ rb_erase(best_fit, &proc->free_buffers);
+ buffer->free = 0;
+ binder_insert_allocated_buffer(proc, buffer);
+ if (buffer_size != size) {
+ struct binder_buffer *new_buffer = (void *)buffer->data + size;
+ list_add(&new_buffer->entry, &buffer->entry);
+ new_buffer->free = 1;
+ binder_insert_free_buffer(proc, new_buffer);
+ }
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "binder: %d: binder_alloc_buf size %zd got "
+ "%p\n", proc->pid, size, buffer);
+ buffer->data_size = data_size;
+ buffer->offsets_size = offsets_size;
+ buffer->async_transaction = is_async;
+ if (is_async) {
+ proc->free_async_space -= size + sizeof(struct binder_buffer);
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
+ "binder: %d: binder_alloc_buf size %zd "
+ "async free %zd\n", proc->pid, size,
+ proc->free_async_space);
+ }
+
+ return buffer;
+}
+
+static void *buffer_start_page(struct binder_buffer *buffer)
+{
+ return (void *)((uintptr_t)buffer & PAGE_MASK);
+}
+
+static void *buffer_end_page(struct binder_buffer *buffer)
+{
+ return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK);
+}
+
+static void binder_delete_free_buffer(struct binder_proc *proc,
+ struct binder_buffer *buffer)
+{
+ struct binder_buffer *prev, *next = NULL;
+ int free_page_end = 1;
+ int free_page_start = 1;
+
+ BUG_ON(proc->buffers.next == &buffer->entry);
+ prev = list_entry(buffer->entry.prev, struct binder_buffer, entry);
+ BUG_ON(!prev->free);
+ if (buffer_end_page(prev) == buffer_start_page(buffer)) {
+ free_page_start = 0;
+ if (buffer_end_page(prev) == buffer_end_page(buffer))
+ free_page_end = 0;
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "binder: %d: merge free, buffer %p "
+ "share page with %p\n", proc->pid, buffer, prev);
+ }
+
+ if (!list_is_last(&buffer->entry, &proc->buffers)) {
+ next = list_entry(buffer->entry.next,
+ struct binder_buffer, entry);
+ if (buffer_start_page(next) == buffer_end_page(buffer)) {
+ free_page_end = 0;
+ if (buffer_start_page(next) ==
+ buffer_start_page(buffer))
+ free_page_start = 0;
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "binder: %d: merge free, buffer"
+ " %p share page with %p\n", proc->pid,
+ buffer, prev);
+ }
+ }
+ list_del(&buffer->entry);
+ if (free_page_start || free_page_end) {
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "binder: %d: merge free, buffer %p do "
+ "not share page%s%s with with %p or %p\n",
+ proc->pid, buffer, free_page_start ? "" : " end",
+ free_page_end ? "" : " start", prev, next);
+ binder_update_page_range(proc, 0, free_page_start ?
+ buffer_start_page(buffer) : buffer_end_page(buffer),
+ (free_page_end ? buffer_end_page(buffer) :
+ buffer_start_page(buffer)) + PAGE_SIZE, NULL);
+ }
+}
+
+static void binder_free_buf(struct binder_proc *proc,
+ struct binder_buffer *buffer)
+{
+ size_t size, buffer_size;
+
+ buffer_size = binder_buffer_size(proc, buffer);
+
+ size = ALIGN(buffer->data_size, sizeof(void *)) +
+ ALIGN(buffer->offsets_size, sizeof(void *));
+
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "binder: %d: binder_free_buf %p size %zd buffer"
+ "_size %zd\n", proc->pid, buffer, size, buffer_size);
+
+ BUG_ON(buffer->free);
+ BUG_ON(size > buffer_size);
+ BUG_ON(buffer->transaction != NULL);
+ BUG_ON((void *)buffer < proc->buffer);
+ BUG_ON((void *)buffer > proc->buffer + proc->buffer_size);
+
+ if (buffer->async_transaction) {
+ proc->free_async_space += size + sizeof(struct binder_buffer);
+
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
+ "binder: %d: binder_free_buf size %zd "
+ "async free %zd\n", proc->pid, size,
+ proc->free_async_space);
+ }
+
+ binder_update_page_range(proc, 0,
+ (void *)PAGE_ALIGN((uintptr_t)buffer->data),
+ (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK),
+ NULL);
+ rb_erase(&buffer->rb_node, &proc->allocated_buffers);
+ buffer->free = 1;
+ if (!list_is_last(&buffer->entry, &proc->buffers)) {
+ struct binder_buffer *next = list_entry(buffer->entry.next,
+ struct binder_buffer, entry);
+ if (next->free) {
+ rb_erase(&next->rb_node, &proc->free_buffers);
+ binder_delete_free_buffer(proc, next);
+ }
+ }
+ if (proc->buffers.next != &buffer->entry) {
+ struct binder_buffer *prev = list_entry(buffer->entry.prev,
+ struct binder_buffer, entry);
+ if (prev->free) {
+ binder_delete_free_buffer(proc, buffer);
+ rb_erase(&prev->rb_node, &proc->free_buffers);
+ buffer = prev;
+ }
+ }
+ binder_insert_free_buffer(proc, buffer);
+}
+
+static struct binder_node *binder_get_node(struct binder_proc *proc,
+ void __user *ptr)
+{
+ struct rb_node *n = proc->nodes.rb_node;
+ struct binder_node *node;
+
+ while (n) {
+ node = rb_entry(n, struct binder_node, rb_node);
+
+ if (ptr < node->ptr)
+ n = n->rb_left;
+ else if (ptr > node->ptr)
+ n = n->rb_right;
+ else
+ return node;
+ }
+ return NULL;
+}
+
+static struct binder_node *binder_new_node(struct binder_proc *proc,
+ void __user *ptr,
+ void __user *cookie)
+{
+ struct rb_node **p = &proc->nodes.rb_node;
+ struct rb_node *parent = NULL;
+ struct binder_node *node;
+
+ while (*p) {
+ parent = *p;
+ node = rb_entry(parent, struct binder_node, rb_node);
+
+ if (ptr < node->ptr)
+ p = &(*p)->rb_left;
+ else if (ptr > node->ptr)
+ p = &(*p)->rb_right;
+ else
+ return NULL;
+ }
+
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (node == NULL)
+ return NULL;
+ binder_stats_created(BINDER_STAT_NODE);
+ rb_link_node(&node->rb_node, parent, p);
+ rb_insert_color(&node->rb_node, &proc->nodes);
+ node->debug_id = ++binder_last_id;
+ node->proc = proc;
+ node->ptr = ptr;
+ node->cookie = cookie;
+ node->work.type = BINDER_WORK_NODE;
+ INIT_LIST_HEAD(&node->work.entry);
+ INIT_LIST_HEAD(&node->async_todo);
+ binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+ "binder: %d:%d node %d u%p c%p created\n",
+ proc->pid, current->pid, node->debug_id,
+ node->ptr, node->cookie);
+ return node;
+}
+
+static int binder_inc_node(struct binder_node *node, int strong, int internal,
+ struct list_head *target_list)
+{
+ if (strong) {
+ if (internal) {
+ if (target_list == NULL &&
+ node->internal_strong_refs == 0 &&
+ !(node == binder_context_mgr_node &&
+ node->has_strong_ref)) {
+ printk(KERN_ERR "binder: invalid inc strong "
+ "node for %d\n", node->debug_id);
+ return -EINVAL;
+ }
+ node->internal_strong_refs++;
+ } else
+ node->local_strong_refs++;
+ if (!node->has_strong_ref && target_list) {
+ list_del_init(&node->work.entry);
+ list_add_tail(&node->work.entry, target_list);
+ }
+ } else {
+ if (!internal)
+ node->local_weak_refs++;
+ if (!node->has_weak_ref && list_empty(&node->work.entry)) {
+ if (target_list == NULL) {
+ printk(KERN_ERR "binder: invalid inc weak node "
+ "for %d\n", node->debug_id);
+ return -EINVAL;
+ }
+ list_add_tail(&node->work.entry, target_list);
+ }
+ }
+ return 0;
+}
+
+static int binder_dec_node(struct binder_node *node, int strong, int internal)
+{
+ if (strong) {
+ if (internal)
+ node->internal_strong_refs--;
+ else
+ node->local_strong_refs--;
+ if (node->local_strong_refs || node->internal_strong_refs)
+ return 0;
+ } else {
+ if (!internal)
+ node->local_weak_refs--;
+ if (node->local_weak_refs || !hlist_empty(&node->refs))
+ return 0;
+ }
+ if (node->proc && (node->has_strong_ref || node->has_weak_ref)) {
+ if (list_empty(&node->work.entry)) {
+ list_add_tail(&node->work.entry, &node->proc->todo);
+ wake_up_interruptible(&node->proc->wait);
+ }
+ } else {
+ if (hlist_empty(&node->refs) && !node->local_strong_refs &&
+ !node->local_weak_refs) {
+ list_del_init(&node->work.entry);
+ if (node->proc) {
+ rb_erase(&node->rb_node, &node->proc->nodes);
+ binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+ "binder: refless node %d deleted\n",
+ node->debug_id);
+ } else {
+ hlist_del(&node->dead_node);
+ binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+ "binder: dead node %d deleted\n",
+ node->debug_id);
+ }
+ kfree(node);
+ binder_stats_deleted(BINDER_STAT_NODE);
+ }
+ }
+
+ return 0;
+}
+
+
+static struct binder_ref *binder_get_ref(struct binder_proc *proc,
+ uint32_t desc)
+{
+ struct rb_node *n = proc->refs_by_desc.rb_node;
+ struct binder_ref *ref;
+
+ while (n) {
+ ref = rb_entry(n, struct binder_ref, rb_node_desc);
+
+ if (desc < ref->desc)
+ n = n->rb_left;
+ else if (desc > ref->desc)
+ n = n->rb_right;
+ else
+ return ref;
+ }
+ return NULL;
+}
+
+static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
+ struct binder_node *node)
+{
+ struct rb_node *n;
+ struct rb_node **p = &proc->refs_by_node.rb_node;
+ struct rb_node *parent = NULL;
+ struct binder_ref *ref, *new_ref;
+
+ while (*p) {
+ parent = *p;
+ ref = rb_entry(parent, struct binder_ref, rb_node_node);
+
+ if (node < ref->node)
+ p = &(*p)->rb_left;
+ else if (node > ref->node)
+ p = &(*p)->rb_right;
+ else
+ return ref;
+ }
+ new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+ if (new_ref == NULL)
+ return NULL;
+ binder_stats_created(BINDER_STAT_REF);
+ new_ref->debug_id = ++binder_last_id;
+ new_ref->proc = proc;
+ new_ref->node = node;
+ rb_link_node(&new_ref->rb_node_node, parent, p);
+ rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
+
+ new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1;
+ for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
+ ref = rb_entry(n, struct binder_ref, rb_node_desc);
+ if (ref->desc > new_ref->desc)
+ break;
+ new_ref->desc = ref->desc + 1;
+ }
+
+ p = &proc->refs_by_desc.rb_node;
+ while (*p) {
+ parent = *p;
+ ref = rb_entry(parent, struct binder_ref, rb_node_desc);
+
+ if (new_ref->desc < ref->desc)
+ p = &(*p)->rb_left;
+ else if (new_ref->desc > ref->desc)
+ p = &(*p)->rb_right;
+ else
+ BUG();
+ }
+ rb_link_node(&new_ref->rb_node_desc, parent, p);
+ rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc);
+ if (node) {
+ hlist_add_head(&new_ref->node_entry, &node->refs);
+
+ binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+ "binder: %d new ref %d desc %d for "
+ "node %d\n", proc->pid, new_ref->debug_id,
+ new_ref->desc, node->debug_id);
+ } else {
+ binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+ "binder: %d new ref %d desc %d for "
+ "dead node\n", proc->pid, new_ref->debug_id,
+ new_ref->desc);
+ }
+ return new_ref;
+}
+
+static void binder_delete_ref(struct binder_ref *ref)
+{
+ binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+ "binder: %d delete ref %d desc %d for "
+ "node %d\n", ref->proc->pid, ref->debug_id,
+ ref->desc, ref->node->debug_id);
+
+ rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);
+ rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);
+ if (ref->strong)
+ binder_dec_node(ref->node, 1, 1);
+ hlist_del(&ref->node_entry);
+ binder_dec_node(ref->node, 0, 1);
+ if (ref->death) {
+ binder_debug(BINDER_DEBUG_DEAD_BINDER,
+ "binder: %d delete ref %d desc %d "
+ "has death notification\n", ref->proc->pid,
+ ref->debug_id, ref->desc);
+ list_del(&ref->death->work.entry);
+ kfree(ref->death);
+ binder_stats_deleted(BINDER_STAT_DEATH);
+ }
+ kfree(ref);
+ binder_stats_deleted(BINDER_STAT_REF);
+}
+
+static int binder_inc_ref(struct binder_ref *ref, int strong,
+ struct list_head *target_list)
+{
+ int ret;
+ if (strong) {
+ if (ref->strong == 0) {
+ ret = binder_inc_node(ref->node, 1, 1, target_list);
+ if (ret)
+ return ret;
+ }
+ ref->strong++;
+ } else {
+ if (ref->weak == 0) {
+ ret = binder_inc_node(ref->node, 0, 1, target_list);
+ if (ret)
+ return ret;
+ }
+ ref->weak++;
+ }
+ return 0;
+}
+
+
+static int binder_dec_ref(struct binder_ref *ref, int strong)
+{
+ if (strong) {
+ if (ref->strong == 0) {
+ binder_user_error("binder: %d invalid dec strong, "
+ "ref %d desc %d s %d w %d\n",
+ ref->proc->pid, ref->debug_id,
+ ref->desc, ref->strong, ref->weak);
+ return -EINVAL;
+ }
+ ref->strong--;
+ if (ref->strong == 0) {
+ int ret;
+ ret = binder_dec_node(ref->node, strong, 1);
+ if (ret)
+ return ret;
+ }
+ } else {
+ if (ref->weak == 0) {
+ binder_user_error("binder: %d invalid dec weak, "
+ "ref %d desc %d s %d w %d\n",
+ ref->proc->pid, ref->debug_id,
+ ref->desc, ref->strong, ref->weak);
+ return -EINVAL;
+ }
+ ref->weak--;
+ }
+ if (ref->strong == 0 && ref->weak == 0)
+ binder_delete_ref(ref);
+ return 0;
+}
+
+static void binder_pop_transaction(struct binder_thread *target_thread,
+ struct binder_transaction *t)
+{
+ if (target_thread) {
+ BUG_ON(target_thread->transaction_stack != t);
+ BUG_ON(target_thread->transaction_stack->from != target_thread);
+ target_thread->transaction_stack =
+ target_thread->transaction_stack->from_parent;
+ t->from = NULL;
+ }
+ t->need_reply = 0;
+ if (t->buffer)
+ t->buffer->transaction = NULL;
+ kfree(t);
+ binder_stats_deleted(BINDER_STAT_TRANSACTION);
+}
+
+static void binder_send_failed_reply(struct binder_transaction *t,
+ uint32_t error_code)
+{
+ struct binder_thread *target_thread;
+ BUG_ON(t->flags & TF_ONE_WAY);
+ while (1) {
+ target_thread = t->from;
+ if (target_thread) {
+ if (target_thread->return_error != BR_OK &&
+ target_thread->return_error2 == BR_OK) {
+ target_thread->return_error2 =
+ target_thread->return_error;
+ target_thread->return_error = BR_OK;
+ }
+ if (target_thread->return_error == BR_OK) {
+ binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+ "binder: send failed reply for "
+ "transaction %d to %d:%d\n",
+ t->debug_id, target_thread->proc->pid,
+ target_thread->pid);
+
+ binder_pop_transaction(target_thread, t);
+ target_thread->return_error = error_code;
+ wake_up_interruptible(&target_thread->wait);
+ } else {
+ printk(KERN_ERR "binder: reply failed, target "
+ "thread, %d:%d, has error code %d "
+ "already\n", target_thread->proc->pid,
+ target_thread->pid,
+ target_thread->return_error);
+ }
+ return;
+ } else {
+ struct binder_transaction *next = t->from_parent;
+
+ binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+ "binder: send failed reply "
+ "for transaction %d, target dead\n",
+ t->debug_id);
+
+ binder_pop_transaction(target_thread, t);
+ if (next == NULL) {
+ binder_debug(BINDER_DEBUG_DEAD_BINDER,
+ "binder: reply failed,"
+ " no target thread at root\n");
+ return;
+ }
+ t = next;
+ binder_debug(BINDER_DEBUG_DEAD_BINDER,
+ "binder: reply failed, no target "
+ "thread -- retry %d\n", t->debug_id);
+ }
+ }
+}
+
+static void binder_transaction_buffer_release(struct binder_proc *proc,
+ struct binder_buffer *buffer,
+ size_t *failed_at)
+{
+ size_t *offp, *off_end;
+ int debug_id = buffer->debug_id;
+
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ "binder: %d buffer release %d, size %zd-%zd, failed at %p\n",
+ proc->pid, buffer->debug_id,
+ buffer->data_size, buffer->offsets_size, failed_at);
+
+ if (buffer->target_node)
+ binder_dec_node(buffer->target_node, 1, 0);
+
+ offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *)));
+ if (failed_at)
+ off_end = failed_at;
+ else
+ off_end = (void *)offp + buffer->offsets_size;
+ for (; offp < off_end; offp++) {
+ struct flat_binder_object *fp;
+ if (*offp > buffer->data_size - sizeof(*fp) ||
+ buffer->data_size < sizeof(*fp) ||
+ !IS_ALIGNED(*offp, sizeof(void *))) {
+ printk(KERN_ERR "binder: transaction release %d bad"
+ "offset %zd, size %zd\n", debug_id,
+ *offp, buffer->data_size);
+ continue;
+ }
+ fp = (struct flat_binder_object *)(buffer->data + *offp);
+ switch (fp->type) {
+ case BINDER_TYPE_BINDER:
+ case BINDER_TYPE_WEAK_BINDER: {
+ struct binder_node *node = binder_get_node(proc, fp->binder);
+ if (node == NULL) {
+ printk(KERN_ERR "binder: transaction release %d"
+ " bad node %p\n", debug_id, fp->binder);
+ break;
+ }
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ " node %d u%p\n",
+ node->debug_id, node->ptr);
+ binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
+ } break;
+ case BINDER_TYPE_HANDLE:
+ case BINDER_TYPE_WEAK_HANDLE: {
+ struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+ if (ref == NULL) {
+ printk(KERN_ERR "binder: transaction release %d"
+ " bad handle %ld\n", debug_id,
+ fp->handle);
+ break;
+ }
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ " ref %d desc %d (node %d)\n",
+ ref->debug_id, ref->desc, ref->node->debug_id);
+ binder_dec_ref(ref, fp->type == BINDER_TYPE_HANDLE);
+ } break;
+
+ case BINDER_TYPE_FD:
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ " fd %ld\n", fp->handle);
+ if (failed_at)
+ task_close_fd(proc, fp->handle);
+ break;
+
+ default:
+ printk(KERN_ERR "binder: transaction release %d bad "
+ "object type %lx\n", debug_id, fp->type);
+ break;
+ }
+ }
+}
+
+static void binder_transaction(struct binder_proc *proc,
+ struct binder_thread *thread,
+ struct binder_transaction_data *tr, int reply)
+{
+ struct binder_transaction *t;
+ struct binder_work *tcomplete;
+ size_t *offp, *off_end;
+ struct binder_proc *target_proc;
+ struct binder_thread *target_thread = NULL;
+ struct binder_node *target_node = NULL;
+ struct list_head *target_list;
+ wait_queue_head_t *target_wait;
+ struct binder_transaction *in_reply_to = NULL;
+ struct binder_transaction_log_entry *e;
+ uint32_t return_error;
+
+ e = binder_transaction_log_add(&binder_transaction_log);
+ e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
+ e->from_proc = proc->pid;
+ e->from_thread = thread->pid;
+ e->target_handle = tr->target.handle;
+ e->data_size = tr->data_size;
+ e->offsets_size = tr->offsets_size;
+
+ if (reply) {
+ in_reply_to = thread->transaction_stack;
+ if (in_reply_to == NULL) {
+ binder_user_error("binder: %d:%d got reply transaction "
+ "with no transaction stack\n",
+ proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ goto err_empty_call_stack;
+ }
+ binder_set_nice(in_reply_to->saved_priority);
+ if (in_reply_to->to_thread != thread) {
+ binder_user_error("binder: %d:%d got reply transaction "
+ "with bad transaction stack,"
+ " transaction %d has target %d:%d\n",
+ proc->pid, thread->pid, in_reply_to->debug_id,
+ in_reply_to->to_proc ?
+ in_reply_to->to_proc->pid : 0,
+ in_reply_to->to_thread ?
+ in_reply_to->to_thread->pid : 0);
+ return_error = BR_FAILED_REPLY;
+ in_reply_to = NULL;
+ goto err_bad_call_stack;
+ }
+ thread->transaction_stack = in_reply_to->to_parent;
+ target_thread = in_reply_to->from;
+ if (target_thread == NULL) {
+ return_error = BR_DEAD_REPLY;
+ goto err_dead_binder;
+ }
+ if (target_thread->transaction_stack != in_reply_to) {
+ binder_user_error("binder: %d:%d got reply transaction "
+ "with bad target transaction stack %d, "
+ "expected %d\n",
+ proc->pid, thread->pid,
+ target_thread->transaction_stack ?
+ target_thread->transaction_stack->debug_id : 0,
+ in_reply_to->debug_id);
+ return_error = BR_FAILED_REPLY;
+ in_reply_to = NULL;
+ target_thread = NULL;
+ goto err_dead_binder;
+ }
+ target_proc = target_thread->proc;
+ } else {
+ if (tr->target.handle) {
+ struct binder_ref *ref;
+ ref = binder_get_ref(proc, tr->target.handle);
+ if (ref == NULL) {
+ binder_user_error("binder: %d:%d got "
+ "transaction to invalid handle\n",
+ proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ goto err_invalid_target_handle;
+ }
+ target_node = ref->node;
+ } else {
+ target_node = binder_context_mgr_node;
+ if (target_node == NULL) {
+ return_error = BR_DEAD_REPLY;
+ goto err_no_context_mgr_node;
+ }
+ }
+ e->to_node = target_node->debug_id;
+ target_proc = target_node->proc;
+ if (target_proc == NULL) {
+ return_error = BR_DEAD_REPLY;
+ goto err_dead_binder;
+ }
+ if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
+ struct binder_transaction *tmp;
+ tmp = thread->transaction_stack;
+ if (tmp->to_thread != thread) {
+ binder_user_error("binder: %d:%d got new "
+ "transaction with bad transaction stack"
+ ", transaction %d has target %d:%d\n",
+ proc->pid, thread->pid, tmp->debug_id,
+ tmp->to_proc ? tmp->to_proc->pid : 0,
+ tmp->to_thread ?
+ tmp->to_thread->pid : 0);
+ return_error = BR_FAILED_REPLY;
+ goto err_bad_call_stack;
+ }
+ while (tmp) {
+ if (tmp->from && tmp->from->proc == target_proc)
+ target_thread = tmp->from;
+ tmp = tmp->from_parent;
+ }
+ }
+ }
+ if (target_thread) {
+ e->to_thread = target_thread->pid;
+ target_list = &target_thread->todo;
+ target_wait = &target_thread->wait;
+ } else {
+ target_list = &target_proc->todo;
+ target_wait = &target_proc->wait;
+ }
+ e->to_proc = target_proc->pid;
+
+ /* TODO: reuse incoming transaction for reply */
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
+ if (t == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_alloc_t_failed;
+ }
+ binder_stats_created(BINDER_STAT_TRANSACTION);
+
+ tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
+ if (tcomplete == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_alloc_tcomplete_failed;
+ }
+ binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
+
+ t->debug_id = ++binder_last_id;
+ e->debug_id = t->debug_id;
+
+ if (reply)
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ "binder: %d:%d BC_REPLY %d -> %d:%d, "
+ "data %p-%p size %zd-%zd\n",
+ proc->pid, thread->pid, t->debug_id,
+ target_proc->pid, target_thread->pid,
+ tr->data.ptr.buffer, tr->data.ptr.offsets,
+ tr->data_size, tr->offsets_size);
+ else
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ "binder: %d:%d BC_TRANSACTION %d -> "
+ "%d - node %d, data %p-%p size %zd-%zd\n",
+ proc->pid, thread->pid, t->debug_id,
+ target_proc->pid, target_node->debug_id,
+ tr->data.ptr.buffer, tr->data.ptr.offsets,
+ tr->data_size, tr->offsets_size);
+
+ if (!reply && !(tr->flags & TF_ONE_WAY))
+ t->from = thread;
+ else
+ t->from = NULL;
+ t->sender_euid = proc->tsk->cred->euid;
+ t->to_proc = target_proc;
+ t->to_thread = target_thread;
+ t->code = tr->code;
+ t->flags = tr->flags;
+ t->priority = task_nice(current);
+ t->buffer = binder_alloc_buf(target_proc, tr->data_size,
+ tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
+ if (t->buffer == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_alloc_buf_failed;
+ }
+ t->buffer->allow_user_free = 0;
+ t->buffer->debug_id = t->debug_id;
+ t->buffer->transaction = t;
+ t->buffer->target_node = target_node;
+ if (target_node)
+ binder_inc_node(target_node, 1, 0, NULL);
+
+ offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
+
+ if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
+ binder_user_error("binder: %d:%d got transaction with invalid "
+ "data ptr\n", proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ goto err_copy_data_failed;
+ }
+ if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
+ binder_user_error("binder: %d:%d got transaction with invalid "
+ "offsets ptr\n", proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ goto err_copy_data_failed;
+ }
+ if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
+ binder_user_error("binder: %d:%d got transaction with "
+ "invalid offsets size, %zd\n",
+ proc->pid, thread->pid, tr->offsets_size);
+ return_error = BR_FAILED_REPLY;
+ goto err_bad_offset;
+ }
+ off_end = (void *)offp + tr->offsets_size;
+ for (; offp < off_end; offp++) {
+ struct flat_binder_object *fp;
+ if (*offp > t->buffer->data_size - sizeof(*fp) ||
+ t->buffer->data_size < sizeof(*fp) ||
+ !IS_ALIGNED(*offp, sizeof(void *))) {
+ binder_user_error("binder: %d:%d got transaction with "
+ "invalid offset, %zd\n",
+ proc->pid, thread->pid, *offp);
+ return_error = BR_FAILED_REPLY;
+ goto err_bad_offset;
+ }
+ fp = (struct flat_binder_object *)(t->buffer->data + *offp);
+ switch (fp->type) {
+ case BINDER_TYPE_BINDER:
+ case BINDER_TYPE_WEAK_BINDER: {
+ struct binder_ref *ref;
+ struct binder_node *node = binder_get_node(proc, fp->binder);
+ if (node == NULL) {
+ node = binder_new_node(proc, fp->binder, fp->cookie);
+ if (node == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_new_node_failed;
+ }
+ node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
+ node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+ }
+ if (fp->cookie != node->cookie) {
+ binder_user_error("binder: %d:%d sending u%p "
+ "node %d, cookie mismatch %p != %p\n",
+ proc->pid, thread->pid,
+ fp->binder, node->debug_id,
+ fp->cookie, node->cookie);
+ goto err_binder_get_ref_for_node_failed;
+ }
+ ref = binder_get_ref_for_node(target_proc, node);
+ if (ref == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_get_ref_for_node_failed;
+ }
+ if (fp->type == BINDER_TYPE_BINDER)
+ fp->type = BINDER_TYPE_HANDLE;
+ else
+ fp->type = BINDER_TYPE_WEAK_HANDLE;
+ fp->handle = ref->desc;
+ binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
+ &thread->todo);
+
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ " node %d u%p -> ref %d desc %d\n",
+ node->debug_id, node->ptr, ref->debug_id,
+ ref->desc);
+ } break;
+ case BINDER_TYPE_HANDLE:
+ case BINDER_TYPE_WEAK_HANDLE: {
+ struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+ if (ref == NULL) {
+ binder_user_error("binder: %d:%d got "
+ "transaction with invalid "
+ "handle, %ld\n", proc->pid,
+ thread->pid, fp->handle);
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_get_ref_failed;
+ }
+ if (ref->node->proc == target_proc) {
+ if (fp->type == BINDER_TYPE_HANDLE)
+ fp->type = BINDER_TYPE_BINDER;
+ else
+ fp->type = BINDER_TYPE_WEAK_BINDER;
+ fp->binder = ref->node->ptr;
+ fp->cookie = ref->node->cookie;
+ binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ " ref %d desc %d -> node %d u%p\n",
+ ref->debug_id, ref->desc, ref->node->debug_id,
+ ref->node->ptr);
+ } else {
+ struct binder_ref *new_ref;
+ new_ref = binder_get_ref_for_node(target_proc, ref->node);
+ if (new_ref == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_get_ref_for_node_failed;
+ }
+ fp->handle = new_ref->desc;
+ binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ " ref %d desc %d -> ref %d desc %d (node %d)\n",
+ ref->debug_id, ref->desc, new_ref->debug_id,
+ new_ref->desc, ref->node->debug_id);
+ }
+ } break;
+
+ case BINDER_TYPE_FD: {
+ int target_fd;
+ struct file *file;
+
+ if (reply) {
+ if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
+ binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
+ proc->pid, thread->pid, fp->handle);
+ return_error = BR_FAILED_REPLY;
+ goto err_fd_not_allowed;
+ }
+ } else if (!target_node->accept_fds) {
+ binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
+ proc->pid, thread->pid, fp->handle);
+ return_error = BR_FAILED_REPLY;
+ goto err_fd_not_allowed;
+ }
+
+ file = fget(fp->handle);
+ if (file == NULL) {
+ binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
+ proc->pid, thread->pid, fp->handle);
+ return_error = BR_FAILED_REPLY;
+ goto err_fget_failed;
+ }
+ target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
+ if (target_fd < 0) {
+ fput(file);
+ return_error = BR_FAILED_REPLY;
+ goto err_get_unused_fd_failed;
+ }
+ task_fd_install(target_proc, target_fd, file);
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ " fd %ld -> %d\n", fp->handle, target_fd);
+ /* TODO: fput? */
+ fp->handle = target_fd;
+ } break;
+
+ default:
+ binder_user_error("binder: %d:%d got transactio"
+ "n with invalid object type, %lx\n",
+ proc->pid, thread->pid, fp->type);
+ return_error = BR_FAILED_REPLY;
+ goto err_bad_object_type;
+ }
+ }
+ if (reply) {
+ BUG_ON(t->buffer->async_transaction != 0);
+ binder_pop_transaction(target_thread, in_reply_to);
+ } else if (!(t->flags & TF_ONE_WAY)) {
+ BUG_ON(t->buffer->async_transaction != 0);
+ t->need_reply = 1;
+ t->from_parent = thread->transaction_stack;
+ thread->transaction_stack = t;
+ } else {
+ BUG_ON(target_node == NULL);
+ BUG_ON(t->buffer->async_transaction != 1);
+ if (target_node->has_async_transaction) {
+ target_list = &target_node->async_todo;
+ target_wait = NULL;
+ } else
+ target_node->has_async_transaction = 1;
+ }
+ t->work.type = BINDER_WORK_TRANSACTION;
+ list_add_tail(&t->work.entry, target_list);
+ tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
+ list_add_tail(&tcomplete->entry, &thread->todo);
+ if (target_wait)
+ wake_up_interruptible(target_wait);
+ return;
+
+err_get_unused_fd_failed:
+err_fget_failed:
+err_fd_not_allowed:
+err_binder_get_ref_for_node_failed:
+err_binder_get_ref_failed:
+err_binder_new_node_failed:
+err_bad_object_type:
+err_bad_offset:
+err_copy_data_failed:
+ binder_transaction_buffer_release(target_proc, t->buffer, offp);
+ t->buffer->transaction = NULL;
+ binder_free_buf(target_proc, t->buffer);
+err_binder_alloc_buf_failed:
+ kfree(tcomplete);
+ binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
+err_alloc_tcomplete_failed:
+ kfree(t);
+ binder_stats_deleted(BINDER_STAT_TRANSACTION);
+err_alloc_t_failed:
+err_bad_call_stack:
+err_empty_call_stack:
+err_dead_binder:
+err_invalid_target_handle:
+err_no_context_mgr_node:
+ binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+ "binder: %d:%d transaction failed %d, size %zd-%zd\n",
+ proc->pid, thread->pid, return_error,
+ tr->data_size, tr->offsets_size);
+
+ {
+ struct binder_transaction_log_entry *fe;
+ fe = binder_transaction_log_add(&binder_transaction_log_failed);
+ *fe = *e;
+ }
+
+ BUG_ON(thread->return_error != BR_OK);
+ if (in_reply_to) {
+ thread->return_error = BR_TRANSACTION_COMPLETE;
+ binder_send_failed_reply(in_reply_to, return_error);
+ } else
+ thread->return_error = return_error;
+}
+
+int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
+ void __user *buffer, int size, signed long *consumed)
+{
+ uint32_t cmd;
+ void __user *ptr = buffer + *consumed;
+ void __user *end = buffer + size;
+
+ while (ptr < end && thread->return_error == BR_OK) {
+ if (get_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
+ binder_stats.bc[_IOC_NR(cmd)]++;
+ proc->stats.bc[_IOC_NR(cmd)]++;
+ thread->stats.bc[_IOC_NR(cmd)]++;
+ }
+ switch (cmd) {
+ case BC_INCREFS:
+ case BC_ACQUIRE:
+ case BC_RELEASE:
+ case BC_DECREFS: {
+ uint32_t target;
+ struct binder_ref *ref;
+ const char *debug_string;
+
+ if (get_user(target, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (target == 0 && binder_context_mgr_node &&
+ (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
+ ref = binder_get_ref_for_node(proc,
+ binder_context_mgr_node);
+ if (ref->desc != target) {
+ binder_user_error("binder: %d:"
+ "%d tried to acquire "
+ "reference to desc 0, "
+ "got %d instead\n",
+ proc->pid, thread->pid,
+ ref->desc);
+ }
+ } else
+ ref = binder_get_ref(proc, target);
+ if (ref == NULL) {
+ binder_user_error("binder: %d:%d refcou"
+ "nt change on invalid ref %d\n",
+ proc->pid, thread->pid, target);
+ break;
+ }
+ switch (cmd) {
+ case BC_INCREFS:
+ debug_string = "IncRefs";
+ binder_inc_ref(ref, 0, NULL);
+ break;
+ case BC_ACQUIRE:
+ debug_string = "Acquire";
+ binder_inc_ref(ref, 1, NULL);
+ break;
+ case BC_RELEASE:
+ debug_string = "Release";
+ binder_dec_ref(ref, 1);
+ break;
+ case BC_DECREFS:
+ default:
+ debug_string = "DecRefs";
+ binder_dec_ref(ref, 0);
+ break;
+ }
+ binder_debug(BINDER_DEBUG_USER_REFS,
+ "binder: %d:%d %s ref %d desc %d s %d w %d for node %d\n",
+ proc->pid, thread->pid, debug_string, ref->debug_id,
+ ref->desc, ref->strong, ref->weak, ref->node->debug_id);
+ break;
+ }
+ case BC_INCREFS_DONE:
+ case BC_ACQUIRE_DONE: {
+ void __user *node_ptr;
+ void *cookie;
+ struct binder_node *node;
+
+ if (get_user(node_ptr, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ if (get_user(cookie, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ node = binder_get_node(proc, node_ptr);
+ if (node == NULL) {
+ binder_user_error("binder: %d:%d "
+ "%s u%p no match\n",
+ proc->pid, thread->pid,
+ cmd == BC_INCREFS_DONE ?
+ "BC_INCREFS_DONE" :
+ "BC_ACQUIRE_DONE",
+ node_ptr);
+ break;
+ }
+ if (cookie != node->cookie) {
+ binder_user_error("binder: %d:%d %s u%p node %d"
+ " cookie mismatch %p != %p\n",
+ proc->pid, thread->pid,
+ cmd == BC_INCREFS_DONE ?
+ "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
+ node_ptr, node->debug_id,
+ cookie, node->cookie);
+ break;
+ }
+ if (cmd == BC_ACQUIRE_DONE) {
+ if (node->pending_strong_ref == 0) {
+ binder_user_error("binder: %d:%d "
+ "BC_ACQUIRE_DONE node %d has "
+ "no pending acquire request\n",
+ proc->pid, thread->pid,
+ node->debug_id);
+ break;
+ }
+ node->pending_strong_ref = 0;
+ } else {
+ if (node->pending_weak_ref == 0) {
+ binder_user_error("binder: %d:%d "
+ "BC_INCREFS_DONE node %d has "
+ "no pending increfs request\n",
+ proc->pid, thread->pid,
+ node->debug_id);
+ break;
+ }
+ node->pending_weak_ref = 0;
+ }
+ binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0);
+ binder_debug(BINDER_DEBUG_USER_REFS,
+ "binder: %d:%d %s node %d ls %d lw %d\n",
+ proc->pid, thread->pid,
+ cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
+ node->debug_id, node->local_strong_refs, node->local_weak_refs);
+ break;
+ }
+ case BC_ATTEMPT_ACQUIRE:
+ printk(KERN_ERR "binder: BC_ATTEMPT_ACQUIRE not supported\n");
+ return -EINVAL;
+ case BC_ACQUIRE_RESULT:
+ printk(KERN_ERR "binder: BC_ACQUIRE_RESULT not supported\n");
+ return -EINVAL;
+
+ case BC_FREE_BUFFER: {
+ void __user *data_ptr;
+ struct binder_buffer *buffer;
+
+ if (get_user(data_ptr, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+
+ buffer = binder_buffer_lookup(proc, data_ptr);
+ if (buffer == NULL) {
+ binder_user_error("binder: %d:%d "
+ "BC_FREE_BUFFER u%p no match\n",
+ proc->pid, thread->pid, data_ptr);
+ break;
+ }
+ if (!buffer->allow_user_free) {
+ binder_user_error("binder: %d:%d "
+ "BC_FREE_BUFFER u%p matched "
+ "unreturned buffer\n",
+ proc->pid, thread->pid, data_ptr);
+ break;
+ }
+ binder_debug(BINDER_DEBUG_FREE_BUFFER,
+ "binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
+ proc->pid, thread->pid, data_ptr, buffer->debug_id,
+ buffer->transaction ? "active" : "finished");
+
+ if (buffer->transaction) {
+ buffer->transaction->buffer = NULL;
+ buffer->transaction = NULL;
+ }
+ if (buffer->async_transaction && buffer->target_node) {
+ BUG_ON(!buffer->target_node->has_async_transaction);
+ if (list_empty(&buffer->target_node->async_todo))
+ buffer->target_node->has_async_transaction = 0;
+ else
+ list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
+ }
+ binder_transaction_buffer_release(proc, buffer, NULL);
+ binder_free_buf(proc, buffer);
+ break;
+ }
+
+ case BC_TRANSACTION:
+ case BC_REPLY: {
+ struct binder_transaction_data tr;
+
+ if (copy_from_user(&tr, ptr, sizeof(tr)))
+ return -EFAULT;
+ ptr += sizeof(tr);
+ binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
+ break;
+ }
+
+ case BC_REGISTER_LOOPER:
+ binder_debug(BINDER_DEBUG_THREADS,
+ "binder: %d:%d BC_REGISTER_LOOPER\n",
+ proc->pid, thread->pid);
+ if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
+ thread->looper |= BINDER_LOOPER_STATE_INVALID;
+ binder_user_error("binder: %d:%d ERROR:"
+ " BC_REGISTER_LOOPER called "
+ "after BC_ENTER_LOOPER\n",
+ proc->pid, thread->pid);
+ } else if (proc->requested_threads == 0) {
+ thread->looper |= BINDER_LOOPER_STATE_INVALID;
+ binder_user_error("binder: %d:%d ERROR:"
+ " BC_REGISTER_LOOPER called "
+ "without request\n",
+ proc->pid, thread->pid);
+ } else {
+ proc->requested_threads--;
+ proc->requested_threads_started++;
+ }
+ thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
+ break;
+ case BC_ENTER_LOOPER:
+ binder_debug(BINDER_DEBUG_THREADS,
+ "binder: %d:%d BC_ENTER_LOOPER\n",
+ proc->pid, thread->pid);
+ if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
+ thread->looper |= BINDER_LOOPER_STATE_INVALID;
+ binder_user_error("binder: %d:%d ERROR:"
+ " BC_ENTER_LOOPER called after "
+ "BC_REGISTER_LOOPER\n",
+ proc->pid, thread->pid);
+ }
+ thread->looper |= BINDER_LOOPER_STATE_ENTERED;
+ break;
+ case BC_EXIT_LOOPER:
+ binder_debug(BINDER_DEBUG_THREADS,
+ "binder: %d:%d BC_EXIT_LOOPER\n",
+ proc->pid, thread->pid);
+ thread->looper |= BINDER_LOOPER_STATE_EXITED;
+ break;
+
+ case BC_REQUEST_DEATH_NOTIFICATION:
+ case BC_CLEAR_DEATH_NOTIFICATION: {
+ uint32_t target;
+ void __user *cookie;
+ struct binder_ref *ref;
+ struct binder_ref_death *death;
+
+ if (get_user(target, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (get_user(cookie, (void __user * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ ref = binder_get_ref(proc, target);
+ if (ref == NULL) {
+ binder_user_error("binder: %d:%d %s "
+ "invalid ref %d\n",
+ proc->pid, thread->pid,
+ cmd == BC_REQUEST_DEATH_NOTIFICATION ?
+ "BC_REQUEST_DEATH_NOTIFICATION" :
+ "BC_CLEAR_DEATH_NOTIFICATION",
+ target);
+ break;
+ }
+
+ binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
+ "binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
+ proc->pid, thread->pid,
+ cmd == BC_REQUEST_DEATH_NOTIFICATION ?
+ "BC_REQUEST_DEATH_NOTIFICATION" :
+ "BC_CLEAR_DEATH_NOTIFICATION",
+ cookie, ref->debug_id, ref->desc,
+ ref->strong, ref->weak, ref->node->debug_id);
+
+ if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
+ if (ref->death) {
+ binder_user_error("binder: %d:%"
+ "d BC_REQUEST_DEATH_NOTI"
+ "FICATION death notific"
+ "ation already set\n",
+ proc->pid, thread->pid);
+ break;
+ }
+ death = kzalloc(sizeof(*death), GFP_KERNEL);
+ if (death == NULL) {
+ thread->return_error = BR_ERROR;
+ binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+ "binder: %d:%d "
+ "BC_REQUEST_DEATH_NOTIFICATION failed\n",
+ proc->pid, thread->pid);
+ break;
+ }
+ binder_stats_created(BINDER_STAT_DEATH);
+ INIT_LIST_HEAD(&death->work.entry);
+ death->cookie = cookie;
+ ref->death = death;
+ if (ref->node->proc == NULL) {
+ ref->death->work.type = BINDER_WORK_DEAD_BINDER;
+ if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
+ list_add_tail(&ref->death->work.entry, &thread->todo);
+ } else {
+ list_add_tail(&ref->death->work.entry, &proc->todo);
+ wake_up_interruptible(&proc->wait);
+ }
+ }
+ } else {
+ if (ref->death == NULL) {
+ binder_user_error("binder: %d:%"
+ "d BC_CLEAR_DEATH_NOTIFI"
+ "CATION death notificat"
+ "ion not active\n",
+ proc->pid, thread->pid);
+ break;
+ }
+ death = ref->death;
+ if (death->cookie != cookie) {
+ binder_user_error("binder: %d:%"
+ "d BC_CLEAR_DEATH_NOTIFI"
+ "CATION death notificat"
+ "ion cookie mismatch "
+ "%p != %p\n",
+ proc->pid, thread->pid,
+ death->cookie, cookie);
+ break;
+ }
+ ref->death = NULL;
+ if (list_empty(&death->work.entry)) {
+ death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
+ if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
+ list_add_tail(&death->work.entry, &thread->todo);
+ } else {
+ list_add_tail(&death->work.entry, &proc->todo);
+ wake_up_interruptible(&proc->wait);
+ }
+ } else {
+ BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
+ death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
+ }
+ }
+ } break;
+ case BC_DEAD_BINDER_DONE: {
+ struct binder_work *w;
+ void __user *cookie;
+ struct binder_ref_death *death = NULL;
+ if (get_user(cookie, (void __user * __user *)ptr))
+ return -EFAULT;
+
+ ptr += sizeof(void *);
+ list_for_each_entry(w, &proc->delivered_death, entry) {
+ struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
+ if (tmp_death->cookie == cookie) {
+ death = tmp_death;
+ break;
+ }
+ }
+ binder_debug(BINDER_DEBUG_DEAD_BINDER,
+ "binder: %d:%d BC_DEAD_BINDER_DONE %p found %p\n",
+ proc->pid, thread->pid, cookie, death);
+ if (death == NULL) {
+ binder_user_error("binder: %d:%d BC_DEAD"
+ "_BINDER_DONE %p not found\n",
+ proc->pid, thread->pid, cookie);
+ break;
+ }
+
+ list_del_init(&death->work.entry);
+ if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) {
+ death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
+ if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
+ list_add_tail(&death->work.entry, &thread->todo);
+ } else {
+ list_add_tail(&death->work.entry, &proc->todo);
+ wake_up_interruptible(&proc->wait);
+ }
+ }
+ } break;
+
+ default:
+ printk(KERN_ERR "binder: %d:%d unknown command %d\n",
+ proc->pid, thread->pid, cmd);
+ return -EINVAL;
+ }
+ *consumed = ptr - buffer;
+ }
+ return 0;
+}
+
+void binder_stat_br(struct binder_proc *proc, struct binder_thread *thread,
+ uint32_t cmd)
+{
+ if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
+ binder_stats.br[_IOC_NR(cmd)]++;
+ proc->stats.br[_IOC_NR(cmd)]++;
+ thread->stats.br[_IOC_NR(cmd)]++;
+ }
+}
+
+static int binder_has_proc_work(struct binder_proc *proc,
+ struct binder_thread *thread)
+{
+ return !list_empty(&proc->todo) ||
+ (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
+}
+
+static int binder_has_thread_work(struct binder_thread *thread)
+{
+ return !list_empty(&thread->todo) || thread->return_error != BR_OK ||
+ (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
+}
+
+static int binder_thread_read(struct binder_proc *proc,
+ struct binder_thread *thread,
+ void __user *buffer, int size,
+ signed long *consumed, int non_block)
+{
+ void __user *ptr = buffer + *consumed;
+ void __user *end = buffer + size;
+
+ int ret = 0;
+ int wait_for_proc_work;
+
+ if (*consumed == 0) {
+ if (put_user(BR_NOOP, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ }
+
+retry:
+ wait_for_proc_work = thread->transaction_stack == NULL &&
+ list_empty(&thread->todo);
+
+ if (thread->return_error != BR_OK && ptr < end) {
+ if (thread->return_error2 != BR_OK) {
+ if (put_user(thread->return_error2, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (ptr == end)
+ goto done;
+ thread->return_error2 = BR_OK;
+ }
+ if (put_user(thread->return_error, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ thread->return_error = BR_OK;
+ goto done;
+ }
+
+
+ thread->looper |= BINDER_LOOPER_STATE_WAITING;
+ if (wait_for_proc_work)
+ proc->ready_threads++;
+ mutex_unlock(&binder_lock);
+ if (wait_for_proc_work) {
+ if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
+ BINDER_LOOPER_STATE_ENTERED))) {
+ binder_user_error("binder: %d:%d ERROR: Thread waiting "
+ "for process work before calling BC_REGISTER_"
+ "LOOPER or BC_ENTER_LOOPER (state %x)\n",
+ proc->pid, thread->pid, thread->looper);
+ wait_event_interruptible(binder_user_error_wait,
+ binder_stop_on_user_error < 2);
+ }
+ binder_set_nice(proc->default_priority);
+ if (non_block) {
+ if (!binder_has_proc_work(proc, thread))
+ ret = -EAGAIN;
+ } else
+ ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread));
+ } else {
+ if (non_block) {
+ if (!binder_has_thread_work(thread))
+ ret = -EAGAIN;
+ } else
+ ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));
+ }
+ mutex_lock(&binder_lock);
+ if (wait_for_proc_work)
+ proc->ready_threads--;
+ thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
+
+ if (ret)
+ return ret;
+
+ while (1) {
+ uint32_t cmd;
+ struct binder_transaction_data tr;
+ struct binder_work *w;
+ struct binder_transaction *t = NULL;
+
+ if (!list_empty(&thread->todo))
+ w = list_first_entry(&thread->todo, struct binder_work, entry);
+ else if (!list_empty(&proc->todo) && wait_for_proc_work)
+ w = list_first_entry(&proc->todo, struct binder_work, entry);
+ else {
+ if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */
+ goto retry;
+ break;
+ }
+
+ if (end - ptr < sizeof(tr) + 4)
+ break;
+
+ switch (w->type) {
+ case BINDER_WORK_TRANSACTION: {
+ t = container_of(w, struct binder_transaction, work);
+ } break;
+ case BINDER_WORK_TRANSACTION_COMPLETE: {
+ cmd = BR_TRANSACTION_COMPLETE;
+ if (put_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+
+ binder_stat_br(proc, thread, cmd);
+ binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE,
+ "binder: %d:%d BR_TRANSACTION_COMPLETE\n",
+ proc->pid, thread->pid);
+
+ list_del(&w->entry);
+ kfree(w);
+ binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
+ } break;
+ case BINDER_WORK_NODE: {
+ struct binder_node *node = container_of(w, struct binder_node, work);
+ uint32_t cmd = BR_NOOP;
+ const char *cmd_name;
+ int strong = node->internal_strong_refs || node->local_strong_refs;
+ int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;
+ if (weak && !node->has_weak_ref) {
+ cmd = BR_INCREFS;
+ cmd_name = "BR_INCREFS";
+ node->has_weak_ref = 1;
+ node->pending_weak_ref = 1;
+ node->local_weak_refs++;
+ } else if (strong && !node->has_strong_ref) {
+ cmd = BR_ACQUIRE;
+ cmd_name = "BR_ACQUIRE";
+ node->has_strong_ref = 1;
+ node->pending_strong_ref = 1;
+ node->local_strong_refs++;
+ } else if (!strong && node->has_strong_ref) {
+ cmd = BR_RELEASE;
+ cmd_name = "BR_RELEASE";
+ node->has_strong_ref = 0;
+ } else if (!weak && node->has_weak_ref) {
+ cmd = BR_DECREFS;
+ cmd_name = "BR_DECREFS";
+ node->has_weak_ref = 0;
+ }
+ if (cmd != BR_NOOP) {
+ if (put_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (put_user(node->ptr, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ if (put_user(node->cookie, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+
+ binder_stat_br(proc, thread, cmd);
+ binder_debug(BINDER_DEBUG_USER_REFS,
+ "binder: %d:%d %s %d u%p c%p\n",
+ proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie);
+ } else {
+ list_del_init(&w->entry);
+ if (!weak && !strong) {
+ binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+ "binder: %d:%d node %d u%p c%p deleted\n",
+ proc->pid, thread->pid, node->debug_id,
+ node->ptr, node->cookie);
+ rb_erase(&node->rb_node, &proc->nodes);
+ kfree(node);
+ binder_stats_deleted(BINDER_STAT_NODE);
+ } else {
+ binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+ "binder: %d:%d node %d u%p c%p state unchanged\n",
+ proc->pid, thread->pid, node->debug_id, node->ptr,
+ node->cookie);
+ }
+ }
+ } break;
+ case BINDER_WORK_DEAD_BINDER:
+ case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+ case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
+ struct binder_ref_death *death;
+ uint32_t cmd;
+
+ death = container_of(w, struct binder_ref_death, work);
+ if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
+ cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
+ else
+ cmd = BR_DEAD_BINDER;
+ if (put_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (put_user(death->cookie, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
+ "binder: %d:%d %s %p\n",
+ proc->pid, thread->pid,
+ cmd == BR_DEAD_BINDER ?
+ "BR_DEAD_BINDER" :
+ "BR_CLEAR_DEATH_NOTIFICATION_DONE",
+ death->cookie);
+
+ if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
+ list_del(&w->entry);
+ kfree(death);
+ binder_stats_deleted(BINDER_STAT_DEATH);
+ } else
+ list_move(&w->entry, &proc->delivered_death);
+ if (cmd == BR_DEAD_BINDER)
+ goto done; /* DEAD_BINDER notifications can cause transactions */
+ } break;
+ }
+
+ if (!t)
+ continue;
+
+ BUG_ON(t->buffer == NULL);
+ if (t->buffer->target_node) {
+ struct binder_node *target_node = t->buffer->target_node;
+ tr.target.ptr = target_node->ptr;
+ tr.cookie = target_node->cookie;
+ t->saved_priority = task_nice(current);
+ if (t->priority < target_node->min_priority &&
+ !(t->flags & TF_ONE_WAY))
+ binder_set_nice(t->priority);
+ else if (!(t->flags & TF_ONE_WAY) ||
+ t->saved_priority > target_node->min_priority)
+ binder_set_nice(target_node->min_priority);
+ cmd = BR_TRANSACTION;
+ } else {
+ tr.target.ptr = NULL;
+ tr.cookie = NULL;
+ cmd = BR_REPLY;
+ }
+ tr.code = t->code;
+ tr.flags = t->flags;
+ tr.sender_euid = t->sender_euid;
+
+ if (t->from) {
+ struct task_struct *sender = t->from->proc->tsk;
+ tr.sender_pid = task_tgid_nr_ns(sender,
+ current->nsproxy->pid_ns);
+ } else {
+ tr.sender_pid = 0;
+ }
+
+ tr.data_size = t->buffer->data_size;
+ tr.offsets_size = t->buffer->offsets_size;
+ tr.data.ptr.buffer = (void *)t->buffer->data +
+ proc->user_buffer_offset;
+ tr.data.ptr.offsets = tr.data.ptr.buffer +
+ ALIGN(t->buffer->data_size,
+ sizeof(void *));
+
+ if (put_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (copy_to_user(ptr, &tr, sizeof(tr)))
+ return -EFAULT;
+ ptr += sizeof(tr);
+
+ binder_stat_br(proc, thread, cmd);
+ binder_debug(BINDER_DEBUG_TRANSACTION,
+ "binder: %d:%d %s %d %d:%d, cmd %d"
+ "size %zd-%zd ptr %p-%p\n",
+ proc->pid, thread->pid,
+ (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
+ "BR_REPLY",
+ t->debug_id, t->from ? t->from->proc->pid : 0,
+ t->from ? t->from->pid : 0, cmd,
+ t->buffer->data_size, t->buffer->offsets_size,
+ tr.data.ptr.buffer, tr.data.ptr.offsets);
+
+ list_del(&t->work.entry);
+ t->buffer->allow_user_free = 1;
+ if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
+ t->to_parent = thread->transaction_stack;
+ t->to_thread = thread;
+ thread->transaction_stack = t;
+ } else {
+ t->buffer->transaction = NULL;
+ kfree(t);
+ binder_stats_deleted(BINDER_STAT_TRANSACTION);
+ }
+ break;
+ }
+
+done:
+
+ *consumed = ptr - buffer;
+ if (proc->requested_threads + proc->ready_threads == 0 &&
+ proc->requested_threads_started < proc->max_threads &&
+ (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
+ BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
+ /*spawn a new thread if we leave this out */) {
+ proc->requested_threads++;
+ binder_debug(BINDER_DEBUG_THREADS,
+ "binder: %d:%d BR_SPAWN_LOOPER\n",
+ proc->pid, thread->pid);
+ if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static void binder_release_work(struct list_head *list)
+{
+ struct binder_work *w;
+ while (!list_empty(list)) {
+ w = list_first_entry(list, struct binder_work, entry);
+ list_del_init(&w->entry);
+ switch (w->type) {
+ case BINDER_WORK_TRANSACTION: {
+ struct binder_transaction *t;
+
+ t = container_of(w, struct binder_transaction, work);
+ if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
+ binder_send_failed_reply(t, BR_DEAD_REPLY);
+ } break;
+ case BINDER_WORK_TRANSACTION_COMPLETE: {
+ kfree(w);
+ binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
+ } break;
+ default:
+ break;
+ }
+ }
+
+}
+
+static struct binder_thread *binder_get_thread(struct binder_proc *proc)
+{
+ struct binder_thread *thread = NULL;
+ struct rb_node *parent = NULL;
+ struct rb_node **p = &proc->threads.rb_node;
+
+ while (*p) {
+ parent = *p;
+ thread = rb_entry(parent, struct binder_thread, rb_node);
+
+ if (current->pid < thread->pid)
+ p = &(*p)->rb_left;
+ else if (current->pid > thread->pid)
+ p = &(*p)->rb_right;
+ else
+ break;
+ }
+ if (*p == NULL) {
+ thread = kzalloc(sizeof(*thread), GFP_KERNEL);
+ if (thread == NULL)
+ return NULL;
+ binder_stats_created(BINDER_STAT_THREAD);
+ thread->proc = proc;
+ thread->pid = current->pid;
+ init_waitqueue_head(&thread->wait);
+ INIT_LIST_HEAD(&thread->todo);
+ rb_link_node(&thread->rb_node, parent, p);
+ rb_insert_color(&thread->rb_node, &proc->threads);
+ thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
+ thread->return_error = BR_OK;
+ thread->return_error2 = BR_OK;
+ }
+ return thread;
+}
+
+static int binder_free_thread(struct binder_proc *proc,
+ struct binder_thread *thread)
+{
+ struct binder_transaction *t;
+ struct binder_transaction *send_reply = NULL;
+ int active_transactions = 0;
+
+ rb_erase(&thread->rb_node, &proc->threads);
+ t = thread->transaction_stack;
+ if (t && t->to_thread == thread)
+ send_reply = t;
+ while (t) {
+ active_transactions++;
+ binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+ "binder: release %d:%d transaction %d "
+ "%s, still active\n", proc->pid, thread->pid,
+ t->debug_id,
+ (t->to_thread == thread) ? "in" : "out");
+
+ if (t->to_thread == thread) {
+ t->to_proc = NULL;
+ t->to_thread = NULL;
+ if (t->buffer) {
+ t->buffer->transaction = NULL;
+ t->buffer = NULL;
+ }
+ t = t->to_parent;
+ } else if (t->from == thread) {
+ t->from = NULL;
+ t = t->from_parent;
+ } else
+ BUG();
+ }
+ if (send_reply)
+ binder_send_failed_reply(send_reply, BR_DEAD_REPLY);
+ binder_release_work(&thread->todo);
+ kfree(thread);
+ binder_stats_deleted(BINDER_STAT_THREAD);
+ return active_transactions;
+}
+
+static unsigned int binder_poll(struct file *filp,
+ struct poll_table_struct *wait)
+{
+ struct binder_proc *proc = filp->private_data;
+ struct binder_thread *thread = NULL;
+ int wait_for_proc_work;
+
+ mutex_lock(&binder_lock);
+ thread = binder_get_thread(proc);
+
+ wait_for_proc_work = thread->transaction_stack == NULL &&
+ list_empty(&thread->todo) && thread->return_error == BR_OK;
+ mutex_unlock(&binder_lock);
+
+ if (wait_for_proc_work) {
+ if (binder_has_proc_work(proc, thread))
+ return POLLIN;
+ poll_wait(filp, &proc->wait, wait);
+ if (binder_has_proc_work(proc, thread))
+ return POLLIN;
+ } else {
+ if (binder_has_thread_work(thread))
+ return POLLIN;
+ poll_wait(filp, &thread->wait, wait);
+ if (binder_has_thread_work(thread))
+ return POLLIN;
+ }
+ return 0;
+}
+
+static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret;
+ struct binder_proc *proc = filp->private_data;
+ struct binder_thread *thread;
+ unsigned int size = _IOC_SIZE(cmd);
+ void __user *ubuf = (void __user *)arg;
+
+ /*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
+
+ ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
+ if (ret)
+ return ret;
+
+ mutex_lock(&binder_lock);
+ thread = binder_get_thread(proc);
+ if (thread == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ switch (cmd) {
+ case BINDER_WRITE_READ: {
+ struct binder_write_read bwr;
+ if (size != sizeof(struct binder_write_read)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
+ ret = -EFAULT;
+ goto err;
+ }
+ binder_debug(BINDER_DEBUG_READ_WRITE,
+ "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n",
+ proc->pid, thread->pid, bwr.write_size, bwr.write_buffer,
+ bwr.read_size, bwr.read_buffer);
+
+ if (bwr.write_size > 0) {
+ ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
+ if (ret < 0) {
+ bwr.read_consumed = 0;
+ if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
+ ret = -EFAULT;
+ goto err;
+ }
+ }
+ if (bwr.read_size > 0) {
+ ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
+ if (!list_empty(&proc->todo))
+ wake_up_interruptible(&proc->wait);
+ if (ret < 0) {
+ if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
+ ret = -EFAULT;
+ goto err;
+ }
+ }
+ binder_debug(BINDER_DEBUG_READ_WRITE,
+ "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n",
+ proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
+ bwr.read_consumed, bwr.read_size);
+ if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
+ ret = -EFAULT;
+ goto err;
+ }
+ break;
+ }
+ case BINDER_SET_MAX_THREADS:
+ if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
+ ret = -EINVAL;
+ goto err;
+ }
+ break;
+ case BINDER_SET_CONTEXT_MGR:
+ if (binder_context_mgr_node != NULL) {
+ printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");
+ ret = -EBUSY;
+ goto err;
+ }
+ if (binder_context_mgr_uid != -1) {
+ if (binder_context_mgr_uid != current->cred->euid) {
+ printk(KERN_ERR "binder: BINDER_SET_"
+ "CONTEXT_MGR bad uid %d != %d\n",
+ current->cred->euid,
+ binder_context_mgr_uid);
+ ret = -EPERM;
+ goto err;
+ }
+ } else
+ binder_context_mgr_uid = current->cred->euid;
+ binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
+ if (binder_context_mgr_node == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ binder_context_mgr_node->local_weak_refs++;
+ binder_context_mgr_node->local_strong_refs++;
+ binder_context_mgr_node->has_strong_ref = 1;
+ binder_context_mgr_node->has_weak_ref = 1;
+ break;
+ case BINDER_THREAD_EXIT:
+ binder_debug(BINDER_DEBUG_THREADS, "binder: %d:%d exit\n",
+ proc->pid, thread->pid);
+ binder_free_thread(proc, thread);
+ thread = NULL;
+ break;
+ case BINDER_VERSION:
+ if (size != sizeof(struct binder_version)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
+ }
+ ret = 0;
+err:
+ if (thread)
+ thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
+ mutex_unlock(&binder_lock);
+ wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
+ if (ret && ret != -ERESTARTSYS)
+ printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
+ return ret;
+}
+
+static void binder_vma_open(struct vm_area_struct *vma)
+{
+ struct binder_proc *proc = vma->vm_private_data;
+ binder_debug(BINDER_DEBUG_OPEN_CLOSE,
+ "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
+ proc->pid, vma->vm_start, vma->vm_end,
+ (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
+ (unsigned long)pgprot_val(vma->vm_page_prot));
+ dump_stack();
+}
+
+static void binder_vma_close(struct vm_area_struct *vma)
+{
+ struct binder_proc *proc = vma->vm_private_data;
+ binder_debug(BINDER_DEBUG_OPEN_CLOSE,
+ "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
+ proc->pid, vma->vm_start, vma->vm_end,
+ (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
+ (unsigned long)pgprot_val(vma->vm_page_prot));
+ proc->vma = NULL;
+ binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
+}
+
+static struct vm_operations_struct binder_vm_ops = {
+ .open = binder_vma_open,
+ .close = binder_vma_close,
+};
+
+static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ int ret;
+ struct vm_struct *area;
+ struct binder_proc *proc = filp->private_data;
+ const char *failure_string;
+ struct binder_buffer *buffer;
+
+ if ((vma->vm_end - vma->vm_start) > SZ_4M)
+ vma->vm_end = vma->vm_start + SZ_4M;
+
+ binder_debug(BINDER_DEBUG_OPEN_CLOSE,
+ "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
+ proc->pid, vma->vm_start, vma->vm_end,
+ (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
+ (unsigned long)pgprot_val(vma->vm_page_prot));
+
+ if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
+ ret = -EPERM;
+ failure_string = "bad vm_flags";
+ goto err_bad_arg;
+ }
+ vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
+
+ if (proc->buffer) {
+ ret = -EBUSY;
+ failure_string = "already mapped";
+ goto err_already_mapped;
+ }
+
+ area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
+ if (area == NULL) {
+ ret = -ENOMEM;
+ failure_string = "get_vm_area";
+ goto err_get_vm_area_failed;
+ }
+ proc->buffer = area->addr;
+ proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
+
+#ifdef CONFIG_CPU_CACHE_VIPT
+ if (cache_is_vipt_aliasing()) {
+ while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) {
+ printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);
+ vma->vm_start += PAGE_SIZE;
+ }
+ }
+#endif
+ proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);
+ if (proc->pages == NULL) {
+ ret = -ENOMEM;
+ failure_string = "alloc page array";
+ goto err_alloc_pages_failed;
+ }
+ proc->buffer_size = vma->vm_end - vma->vm_start;
+
+ vma->vm_ops = &binder_vm_ops;
+ vma->vm_private_data = proc;
+
+ if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {
+ ret = -ENOMEM;
+ failure_string = "alloc small buf";
+ goto err_alloc_small_buf_failed;
+ }
+ buffer = proc->buffer;
+ INIT_LIST_HEAD(&proc->buffers);
+ list_add(&buffer->entry, &proc->buffers);
+ buffer->free = 1;
+ binder_insert_free_buffer(proc, buffer);
+ proc->free_async_space = proc->buffer_size / 2;
+ barrier();
+ proc->files = get_files_struct(current);
+ proc->vma = vma;
+
+ /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n",
+ proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
+ return 0;
+
+err_alloc_small_buf_failed:
+ kfree(proc->pages);
+ proc->pages = NULL;
+err_alloc_pages_failed:
+ vfree(proc->buffer);
+ proc->buffer = NULL;
+err_get_vm_area_failed:
+err_already_mapped:
+err_bad_arg:
+ printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n",
+ proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
+ return ret;
+}
+
+static int binder_open(struct inode *nodp, struct file *filp)
+{
+ struct binder_proc *proc;
+
+ binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
+ current->group_leader->pid, current->pid);
+
+ proc = kzalloc(sizeof(*proc), GFP_KERNEL);
+ if (proc == NULL)
+ return -ENOMEM;
+ get_task_struct(current);
+ proc->tsk = current;
+ INIT_LIST_HEAD(&proc->todo);
+ init_waitqueue_head(&proc->wait);
+ proc->default_priority = task_nice(current);
+ mutex_lock(&binder_lock);
+ binder_stats_created(BINDER_STAT_PROC);
+ hlist_add_head(&proc->proc_node, &binder_procs);
+ proc->pid = current->group_leader->pid;
+ INIT_LIST_HEAD(&proc->delivered_death);
+ filp->private_data = proc;
+ mutex_unlock(&binder_lock);
+
+ if (binder_debugfs_dir_entry_proc) {
+ char strbuf[11];
+ snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
+ proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO,
+ binder_debugfs_dir_entry_proc, proc, &binder_proc_fops);
+ }
+
+ return 0;
+}
+
+static int binder_flush(struct file *filp, fl_owner_t id)
+{
+ struct binder_proc *proc = filp->private_data;
+
+ binder_defer_work(proc, BINDER_DEFERRED_FLUSH);
+
+ return 0;
+}
+
+static void binder_deferred_flush(struct binder_proc *proc)
+{
+ struct rb_node *n;
+ int wake_count = 0;
+ for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
+ struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
+ thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
+ if (thread->looper & BINDER_LOOPER_STATE_WAITING) {
+ wake_up_interruptible(&thread->wait);
+ wake_count++;
+ }
+ }
+ wake_up_interruptible_all(&proc->wait);
+
+ binder_debug(BINDER_DEBUG_OPEN_CLOSE,
+ "binder_flush: %d woke %d threads\n", proc->pid,
+ wake_count);
+}
+
+static int binder_release(struct inode *nodp, struct file *filp)
+{
+ struct binder_proc *proc = filp->private_data;
+ debugfs_remove(proc->debugfs_entry);
+ binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
+
+ return 0;
+}
+
+static void binder_deferred_release(struct binder_proc *proc)
+{
+ struct hlist_node *pos;
+ struct binder_transaction *t;
+ struct rb_node *n;
+ 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);
+ 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);
+ 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);
+
+ nodes++;
+ rb_erase(&node->rb_node, &proc->nodes);
+ list_del_init(&node->work.entry);
+ 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, pos, &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,
+ "binder: node %d now dead, "
+ "refs %d, death %d\n", node->debug_id,
+ incoming_refs, death);
+ }
+ }
+ outgoing_refs = 0;
+ while ((n = rb_first(&proc->refs_by_desc))) {
+ struct binder_ref *ref = rb_entry(n, struct binder_ref,
+ rb_node_desc);
+ outgoing_refs++;
+ binder_delete_ref(ref);
+ }
+ binder_release_work(&proc->todo);
+ buffers = 0;
+
+ while ((n = rb_first(&proc->allocated_buffers))) {
+ struct binder_buffer *buffer = rb_entry(n, struct binder_buffer,
+ rb_node);
+ t = buffer->transaction;
+ if (t) {
+ t->buffer = NULL;
+ buffer->transaction = NULL;
+ printk(KERN_ERR "binder: release proc %d, "
+ "transaction %d, not freed\n",
+ proc->pid, t->debug_id);
+ /*BUG();*/
+ }
+ binder_free_buf(proc, buffer);
+ buffers++;
+ }
+
+ binder_stats_deleted(BINDER_STAT_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++;
+ }
+ }
+ kfree(proc->pages);
+ vfree(proc->buffer);
+ }
+
+ 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);
+
+ kfree(proc);
+}
+
+static void binder_deferred_func(struct work_struct *work)
+{
+ struct binder_proc *proc;
+ struct files_struct *files;
+
+ int defer;
+ do {
+ mutex_lock(&binder_lock);
+ mutex_lock(&binder_deferred_lock);
+ if (!hlist_empty(&binder_deferred_list)) {
+ proc = hlist_entry(binder_deferred_list.first,
+ struct binder_proc, deferred_work_node);
+ hlist_del_init(&proc->deferred_work_node);
+ defer = proc->deferred_work;
+ proc->deferred_work = 0;
+ } else {
+ proc = NULL;
+ defer = 0;
+ }
+ mutex_unlock(&binder_deferred_lock);
+
+ files = NULL;
+ if (defer & BINDER_DEFERRED_PUT_FILES) {
+ files = proc->files;
+ if (files)
+ proc->files = NULL;
+ }
+
+ if (defer & BINDER_DEFERRED_FLUSH)
+ binder_deferred_flush(proc);
+
+ if (defer & BINDER_DEFERRED_RELEASE)
+ binder_deferred_release(proc); /* frees proc */
+
+ mutex_unlock(&binder_lock);
+ if (files)
+ put_files_struct(files);
+ } while (proc);
+}
+static DECLARE_WORK(binder_deferred_work, binder_deferred_func);
+
+static void
+binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer)
+{
+ mutex_lock(&binder_deferred_lock);
+ proc->deferred_work |= defer;
+ if (hlist_unhashed(&proc->deferred_work_node)) {
+ hlist_add_head(&proc->deferred_work_node,
+ &binder_deferred_list);
+ queue_work(binder_deferred_workqueue, &binder_deferred_work);
+ }
+ mutex_unlock(&binder_deferred_lock);
+}
+
+static void print_binder_transaction(struct seq_file *m, const char *prefix,
+ struct binder_transaction *t)
+{
+ seq_printf(m,
+ "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
+ prefix, t->debug_id, t,
+ t->from ? t->from->proc->pid : 0,
+ t->from ? t->from->pid : 0,
+ t->to_proc ? t->to_proc->pid : 0,
+ t->to_thread ? t->to_thread->pid : 0,
+ t->code, t->flags, t->priority, t->need_reply);
+ if (t->buffer == NULL) {
+ seq_puts(m, " buffer free\n");
+ return;
+ }
+ if (t->buffer->target_node)
+ seq_printf(m, " node %d",
+ t->buffer->target_node->debug_id);
+ seq_printf(m, " size %zd:%zd data %p\n",
+ t->buffer->data_size, t->buffer->offsets_size,
+ t->buffer->data);
+}
+
+static void print_binder_buffer(struct seq_file *m, const char *prefix,
+ struct binder_buffer *buffer)
+{
+ seq_printf(m, "%s %d: %p size %zd:%zd %s\n",
+ prefix, buffer->debug_id, buffer->data,
+ buffer->data_size, buffer->offsets_size,
+ buffer->transaction ? "active" : "delivered");
+}
+
+static void print_binder_work(struct seq_file *m, const char *prefix,
+ const char *transaction_prefix,
+ struct binder_work *w)
+{
+ struct binder_node *node;
+ struct binder_transaction *t;
+
+ switch (w->type) {
+ case BINDER_WORK_TRANSACTION:
+ t = container_of(w, struct binder_transaction, work);
+ print_binder_transaction(m, transaction_prefix, t);
+ break;
+ case BINDER_WORK_TRANSACTION_COMPLETE:
+ seq_printf(m, "%stransaction complete\n", prefix);
+ break;
+ case BINDER_WORK_NODE:
+ node = container_of(w, struct binder_node, work);
+ seq_printf(m, "%snode work %d: u%p c%p\n",
+ prefix, node->debug_id, node->ptr, node->cookie);
+ break;
+ case BINDER_WORK_DEAD_BINDER:
+ seq_printf(m, "%shas dead binder\n", prefix);
+ break;
+ case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+ seq_printf(m, "%shas cleared dead binder\n", prefix);
+ break;
+ case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
+ seq_printf(m, "%shas cleared death notification\n", prefix);
+ break;
+ default:
+ seq_printf(m, "%sunknown work: type %d\n", prefix, w->type);
+ break;
+ }
+}
+
+static void print_binder_thread(struct seq_file *m,
+ struct binder_thread *thread,
+ int print_always)
+{
+ struct binder_transaction *t;
+ struct binder_work *w;
+ size_t start_pos = m->count;
+ size_t header_pos;
+
+ seq_printf(m, " thread %d: l %02x\n", thread->pid, thread->looper);
+ header_pos = m->count;
+ t = thread->transaction_stack;
+ while (t) {
+ if (t->from == thread) {
+ print_binder_transaction(m,
+ " outgoing transaction", t);
+ t = t->from_parent;
+ } else if (t->to_thread == thread) {
+ print_binder_transaction(m,
+ " incoming transaction", t);
+ t = t->to_parent;
+ } else {
+ print_binder_transaction(m, " bad transaction", t);
+ t = NULL;
+ }
+ }
+ list_for_each_entry(w, &thread->todo, entry) {
+ print_binder_work(m, " ", " pending transaction", w);
+ }
+ if (!print_always && m->count == header_pos)
+ m->count = start_pos;
+}
+
+static void print_binder_node(struct seq_file *m, struct binder_node *node)
+{
+ struct binder_ref *ref;
+ struct hlist_node *pos;
+ struct binder_work *w;
+ int count;
+
+ count = 0;
+ hlist_for_each_entry(ref, pos, &node->refs, node_entry)
+ count++;
+
+ seq_printf(m, " node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d",
+ node->debug_id, node->ptr, node->cookie,
+ node->has_strong_ref, node->has_weak_ref,
+ node->local_strong_refs, node->local_weak_refs,
+ node->internal_strong_refs, count);
+ if (count) {
+ seq_puts(m, " proc");
+ hlist_for_each_entry(ref, pos, &node->refs, node_entry)
+ seq_printf(m, " %d", ref->proc->pid);
+ }
+ seq_puts(m, "\n");
+ list_for_each_entry(w, &node->async_todo, entry)
+ print_binder_work(m, " ",
+ " pending async transaction", w);
+}
+
+static void print_binder_ref(struct seq_file *m, struct binder_ref *ref)
+{
+ seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %p\n",
+ ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ",
+ ref->node->debug_id, ref->strong, ref->weak, ref->death);
+}
+
+static void print_binder_proc(struct seq_file *m,
+ struct binder_proc *proc, int print_all)
+{
+ struct binder_work *w;
+ struct rb_node *n;
+ size_t start_pos = m->count;
+ size_t header_pos;
+
+ seq_printf(m, "proc %d\n", proc->pid);
+ header_pos = m->count;
+
+ for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
+ print_binder_thread(m, rb_entry(n, struct binder_thread,
+ rb_node), print_all);
+ for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) {
+ struct binder_node *node = rb_entry(n, struct binder_node,
+ rb_node);
+ if (print_all || node->has_async_transaction)
+ print_binder_node(m, node);
+ }
+ if (print_all) {
+ for (n = rb_first(&proc->refs_by_desc);
+ n != NULL;
+ n = rb_next(n))
+ print_binder_ref(m, rb_entry(n, struct binder_ref,
+ rb_node_desc));
+ }
+ for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n))
+ print_binder_buffer(m, " buffer",
+ rb_entry(n, struct binder_buffer, rb_node));
+ list_for_each_entry(w, &proc->todo, entry)
+ print_binder_work(m, " ", " pending transaction", w);
+ list_for_each_entry(w, &proc->delivered_death, entry) {
+ seq_puts(m, " has delivered dead binder\n");
+ break;
+ }
+ if (!print_all && m->count == header_pos)
+ m->count = start_pos;
+}
+
+static const char *binder_return_strings[] = {
+ "BR_ERROR",
+ "BR_OK",
+ "BR_TRANSACTION",
+ "BR_REPLY",
+ "BR_ACQUIRE_RESULT",
+ "BR_DEAD_REPLY",
+ "BR_TRANSACTION_COMPLETE",
+ "BR_INCREFS",
+ "BR_ACQUIRE",
+ "BR_RELEASE",
+ "BR_DECREFS",
+ "BR_ATTEMPT_ACQUIRE",
+ "BR_NOOP",
+ "BR_SPAWN_LOOPER",
+ "BR_FINISHED",
+ "BR_DEAD_BINDER",
+ "BR_CLEAR_DEATH_NOTIFICATION_DONE",
+ "BR_FAILED_REPLY"
+};
+
+static const char *binder_command_strings[] = {
+ "BC_TRANSACTION",
+ "BC_REPLY",
+ "BC_ACQUIRE_RESULT",
+ "BC_FREE_BUFFER",
+ "BC_INCREFS",
+ "BC_ACQUIRE",
+ "BC_RELEASE",
+ "BC_DECREFS",
+ "BC_INCREFS_DONE",
+ "BC_ACQUIRE_DONE",
+ "BC_ATTEMPT_ACQUIRE",
+ "BC_REGISTER_LOOPER",
+ "BC_ENTER_LOOPER",
+ "BC_EXIT_LOOPER",
+ "BC_REQUEST_DEATH_NOTIFICATION",
+ "BC_CLEAR_DEATH_NOTIFICATION",
+ "BC_DEAD_BINDER_DONE"
+};
+
+static const char *binder_objstat_strings[] = {
+ "proc",
+ "thread",
+ "node",
+ "ref",
+ "death",
+ "transaction",
+ "transaction_complete"
+};
+
+static void print_binder_stats(struct seq_file *m, const char *prefix,
+ struct binder_stats *stats)
+{
+ int i;
+
+ BUILD_BUG_ON(ARRAY_SIZE(stats->bc) !=
+ ARRAY_SIZE(binder_command_strings));
+ for (i = 0; i < ARRAY_SIZE(stats->bc); i++) {
+ if (stats->bc[i])
+ seq_printf(m, "%s%s: %d\n", prefix,
+ binder_command_strings[i], stats->bc[i]);
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(stats->br) !=
+ ARRAY_SIZE(binder_return_strings));
+ for (i = 0; i < ARRAY_SIZE(stats->br); i++) {
+ if (stats->br[i])
+ seq_printf(m, "%s%s: %d\n", prefix,
+ binder_return_strings[i], stats->br[i]);
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
+ ARRAY_SIZE(binder_objstat_strings));
+ BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
+ ARRAY_SIZE(stats->obj_deleted));
+ for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) {
+ if (stats->obj_created[i] || stats->obj_deleted[i])
+ seq_printf(m, "%s%s: active %d total %d\n", prefix,
+ binder_objstat_strings[i],
+ stats->obj_created[i] - stats->obj_deleted[i],
+ stats->obj_created[i]);
+ }
+}
+
+static void print_binder_proc_stats(struct seq_file *m,
+ struct binder_proc *proc)
+{
+ struct binder_work *w;
+ struct rb_node *n;
+ int count, strong, weak;
+
+ seq_printf(m, "proc %d\n", proc->pid);
+ count = 0;
+ for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
+ count++;
+ seq_printf(m, " threads: %d\n", count);
+ seq_printf(m, " requested threads: %d+%d/%d\n"
+ " ready threads %d\n"
+ " free async space %zd\n", proc->requested_threads,
+ proc->requested_threads_started, proc->max_threads,
+ proc->ready_threads, proc->free_async_space);
+ count = 0;
+ for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n))
+ count++;
+ seq_printf(m, " nodes: %d\n", count);
+ count = 0;
+ strong = 0;
+ weak = 0;
+ for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
+ struct binder_ref *ref = rb_entry(n, struct binder_ref,
+ rb_node_desc);
+ count++;
+ strong += ref->strong;
+ weak += ref->weak;
+ }
+ seq_printf(m, " refs: %d s %d w %d\n", count, strong, weak);
+
+ count = 0;
+ for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n))
+ count++;
+ seq_printf(m, " buffers: %d\n", count);
+
+ count = 0;
+ list_for_each_entry(w, &proc->todo, entry) {
+ switch (w->type) {
+ case BINDER_WORK_TRANSACTION:
+ count++;
+ break;
+ default:
+ break;
+ }
+ }
+ seq_printf(m, " pending transactions: %d\n", count);
+
+ print_binder_stats(m, " ", &proc->stats);
+}
+
+
+static int binder_state_show(struct seq_file *m, void *unused)
+{
+ struct binder_proc *proc;
+ struct hlist_node *pos;
+ struct binder_node *node;
+ int do_lock = !binder_debug_no_lock;
+
+ if (do_lock)
+ mutex_lock(&binder_lock);
+
+ seq_puts(m, "binder state:\n");
+
+ if (!hlist_empty(&binder_dead_nodes))
+ seq_puts(m, "dead nodes:\n");
+ hlist_for_each_entry(node, pos, &binder_dead_nodes, dead_node)
+ print_binder_node(m, node);
+
+ hlist_for_each_entry(proc, pos, &binder_procs, proc_node)
+ print_binder_proc(m, proc, 1);
+ if (do_lock)
+ mutex_unlock(&binder_lock);
+ return 0;
+}
+
+static int binder_stats_show(struct seq_file *m, void *unused)
+{
+ struct binder_proc *proc;
+ struct hlist_node *pos;
+ int do_lock = !binder_debug_no_lock;
+
+ if (do_lock)
+ mutex_lock(&binder_lock);
+
+ seq_puts(m, "binder stats:\n");
+
+ print_binder_stats(m, "", &binder_stats);
+
+ hlist_for_each_entry(proc, pos, &binder_procs, proc_node)
+ print_binder_proc_stats(m, proc);
+ if (do_lock)
+ mutex_unlock(&binder_lock);
+ return 0;
+}
+
+static int binder_transactions_show(struct seq_file *m, void *unused)
+{
+ struct binder_proc *proc;
+ struct hlist_node *pos;
+ int do_lock = !binder_debug_no_lock;
+
+ if (do_lock)
+ mutex_lock(&binder_lock);
+
+ seq_puts(m, "binder transactions:\n");
+ hlist_for_each_entry(proc, pos, &binder_procs, proc_node)
+ print_binder_proc(m, proc, 0);
+ if (do_lock)
+ mutex_unlock(&binder_lock);
+ return 0;
+}
+
+static int binder_proc_show(struct seq_file *m, void *unused)
+{
+ struct binder_proc *proc = m->private;
+ int do_lock = !binder_debug_no_lock;
+
+ if (do_lock)
+ mutex_lock(&binder_lock);
+ seq_puts(m, "binder proc state:\n");
+ print_binder_proc(m, proc, 1);
+ if (do_lock)
+ mutex_unlock(&binder_lock);
+ return 0;
+}
+
+static void print_binder_transaction_log_entry(struct seq_file *m,
+ struct binder_transaction_log_entry *e)
+{
+ seq_printf(m,
+ "%d: %s from %d:%d to %d:%d node %d handle %d size %d:%d\n",
+ e->debug_id, (e->call_type == 2) ? "reply" :
+ ((e->call_type == 1) ? "async" : "call "), e->from_proc,
+ e->from_thread, e->to_proc, e->to_thread, e->to_node,
+ e->target_handle, e->data_size, e->offsets_size);
+}
+
+static int binder_transaction_log_show(struct seq_file *m, void *unused)
+{
+ struct binder_transaction_log *log = m->private;
+ int i;
+
+ if (log->full) {
+ for (i = log->next; i < ARRAY_SIZE(log->entry); i++)
+ print_binder_transaction_log_entry(m, &log->entry[i]);
+ }
+ for (i = 0; i < log->next; i++)
+ print_binder_transaction_log_entry(m, &log->entry[i]);
+ return 0;
+}
+
+static const struct file_operations binder_fops = {
+ .owner = THIS_MODULE,
+ .poll = binder_poll,
+ .unlocked_ioctl = binder_ioctl,
+ .mmap = binder_mmap,
+ .open = binder_open,
+ .flush = binder_flush,
+ .release = binder_release,
+};
+
+static struct miscdevice binder_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "binder",
+ .fops = &binder_fops
+};
+
+BINDER_DEBUG_ENTRY(state);
+BINDER_DEBUG_ENTRY(stats);
+BINDER_DEBUG_ENTRY(transactions);
+BINDER_DEBUG_ENTRY(transaction_log);
+
+static int __init binder_init(void)
+{
+ int ret;
+
+ binder_deferred_workqueue = create_singlethread_workqueue("binder");
+ if (!binder_deferred_workqueue)
+ return -ENOMEM;
+
+ binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
+ if (binder_debugfs_dir_entry_root)
+ binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
+ binder_debugfs_dir_entry_root);
+ ret = misc_register(&binder_miscdev);
+ if (binder_debugfs_dir_entry_root) {
+ debugfs_create_file("state",
+ S_IRUGO,
+ binder_debugfs_dir_entry_root,
+ NULL,
+ &binder_state_fops);
+ debugfs_create_file("stats",
+ S_IRUGO,
+ binder_debugfs_dir_entry_root,
+ NULL,
+ &binder_stats_fops);
+ debugfs_create_file("transactions",
+ S_IRUGO,
+ binder_debugfs_dir_entry_root,
+ NULL,
+ &binder_transactions_fops);
+ debugfs_create_file("transaction_log",
+ S_IRUGO,
+ binder_debugfs_dir_entry_root,
+ &binder_transaction_log,
+ &binder_transaction_log_fops);
+ debugfs_create_file("failed_transaction_log",
+ S_IRUGO,
+ binder_debugfs_dir_entry_root,
+ &binder_transaction_log_failed,
+ &binder_transaction_log_fops);
+ }
+ return ret;
+}
+
+device_initcall(binder_init);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h
new file mode 100644
index 000000000000..25ab6f2759e9
--- /dev/null
+++ b/drivers/staging/android/binder.h
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * Based on, but no longer compatible with, the original
+ * OpenBinder.org binder driver interface, which is:
+ *
+ * Copyright (c) 2005 Palmsource, 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_BINDER_H
+#define _LINUX_BINDER_H
+
+#include <linux/ioctl.h>
+
+#define B_PACK_CHARS(c1, c2, c3, c4) \
+ ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
+#define B_TYPE_LARGE 0x85
+
+enum {
+ BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
+ BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
+ BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
+ BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
+ BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
+};
+
+enum {
+ FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
+ FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
+};
+
+/*
+ * This is the flattened representation of a Binder object for transfer
+ * between processes. The 'offsets' supplied as part of a binder transaction
+ * contains offsets into the data where these structures occur. The Binder
+ * driver takes care of re-writing the structure type and data as it moves
+ * between processes.
+ */
+struct flat_binder_object {
+ /* 8 bytes for large_flat_header. */
+ unsigned long type;
+ unsigned long flags;
+
+ /* 8 bytes of data. */
+ union {
+ void *binder; /* local object */
+ signed long handle; /* remote object */
+ };
+
+ /* extra data associated with local object */
+ void *cookie;
+};
+
+/*
+ * On 64-bit platforms where user code may run in 32-bits the driver must
+ * translate the buffer (and local binder) addresses apropriately.
+ */
+
+struct binder_write_read {
+ signed long write_size; /* bytes to write */
+ signed long write_consumed; /* bytes consumed by driver */
+ unsigned long write_buffer;
+ signed long read_size; /* bytes to read */
+ signed long read_consumed; /* bytes consumed by driver */
+ unsigned long read_buffer;
+};
+
+/* Use with BINDER_VERSION, driver fills in fields. */
+struct binder_version {
+ /* driver protocol version -- increment with incompatible change */
+ signed long protocol_version;
+};
+
+/* This is the current protocol 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_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_VERSION _IOWR('b', 9, struct binder_version)
+
+/*
+ * NOTE: Two special error codes you should check for when calling
+ * in to the driver are:
+ *
+ * EINTR -- The operation has been interupted. This should be
+ * handled by retrying the ioctl() until a different error code
+ * is returned.
+ *
+ * ECONNREFUSED -- The driver is no longer accepting operations
+ * from your process. That is, the process is being destroyed.
+ * You should handle this by exiting from your process. Note
+ * that once this error code is returned, all further calls to
+ * the driver from any thread will return this same code.
+ */
+
+enum transaction_flags {
+ TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */
+ TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */
+ TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */
+ TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
+};
+
+struct binder_transaction_data {
+ /* The first two are only used for bcTRANSACTION and brTRANSACTION,
+ * identifying the target and contents of the transaction.
+ */
+ union {
+ size_t handle; /* target descriptor of command transaction */
+ void *ptr; /* target descriptor of return transaction */
+ } target;
+ void *cookie; /* target object cookie */
+ unsigned int code; /* transaction command */
+
+ /* General information about the transaction. */
+ unsigned int flags;
+ pid_t sender_pid;
+ uid_t sender_euid;
+ size_t data_size; /* number of bytes of data */
+ size_t offsets_size; /* number of bytes of offsets */
+
+ /* If this transaction is inline, the data immediately
+ * follows here; otherwise, it ends with a pointer to
+ * the data buffer.
+ */
+ union {
+ struct {
+ /* transaction data */
+ const void *buffer;
+ /* offsets from buffer to flat_binder_object structs */
+ const void *offsets;
+ } ptr;
+ uint8_t buf[8];
+ } data;
+};
+
+struct binder_ptr_cookie {
+ void *ptr;
+ void *cookie;
+};
+
+struct binder_pri_desc {
+ int priority;
+ int desc;
+};
+
+struct binder_pri_ptr_cookie {
+ int priority;
+ void *ptr;
+ void *cookie;
+};
+
+enum BinderDriverReturnProtocol {
+ BR_ERROR = _IOR('r', 0, int),
+ /*
+ * int: error code
+ */
+
+ BR_OK = _IO('r', 1),
+ /* No parameters! */
+
+ BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
+ BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
+ /*
+ * binder_transaction_data: the received command.
+ */
+
+ BR_ACQUIRE_RESULT = _IOR('r', 4, int),
+ /*
+ * not currently supported
+ * int: 0 if the last bcATTEMPT_ACQUIRE was not successful.
+ * Else the remote object has acquired a primary reference.
+ */
+
+ BR_DEAD_REPLY = _IO('r', 5),
+ /*
+ * The target of the last transaction (either a bcTRANSACTION or
+ * a bcATTEMPT_ACQUIRE) is no longer with us. No parameters.
+ */
+
+ BR_TRANSACTION_COMPLETE = _IO('r', 6),
+ /*
+ * No parameters... always refers to the last transaction requested
+ * (including replies). Note that this will be sent even for
+ * asynchronous transactions.
+ */
+
+ BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
+ BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
+ BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
+ BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
+ /*
+ * void *: ptr to binder
+ * void *: cookie for binder
+ */
+
+ BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
+ /*
+ * not currently supported
+ * int: priority
+ * void *: ptr to binder
+ * void *: cookie for binder
+ */
+
+ BR_NOOP = _IO('r', 12),
+ /*
+ * No parameters. Do nothing and examine the next command. It exists
+ * primarily so that we can replace it with a BR_SPAWN_LOOPER command.
+ */
+
+ BR_SPAWN_LOOPER = _IO('r', 13),
+ /*
+ * No parameters. The driver has determined that a process has no
+ * threads waiting to service incomming transactions. When a process
+ * receives this command, it must spawn a new service thread and
+ * register it via bcENTER_LOOPER.
+ */
+
+ BR_FINISHED = _IO('r', 14),
+ /*
+ * not currently supported
+ * stop threadpool thread
+ */
+
+ BR_DEAD_BINDER = _IOR('r', 15, void *),
+ /*
+ * void *: cookie
+ */
+ BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *),
+ /*
+ * void *: cookie
+ */
+
+ BR_FAILED_REPLY = _IO('r', 17),
+ /*
+ * The the last transaction (either a bcTRANSACTION or
+ * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters.
+ */
+};
+
+enum BinderDriverCommandProtocol {
+ BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
+ BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
+ /*
+ * binder_transaction_data: the sent command.
+ */
+
+ BC_ACQUIRE_RESULT = _IOW('c', 2, int),
+ /*
+ * not currently supported
+ * int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful.
+ * Else you have acquired a primary reference on the object.
+ */
+
+ BC_FREE_BUFFER = _IOW('c', 3, int),
+ /*
+ * void *: ptr to transaction data received on a read
+ */
+
+ BC_INCREFS = _IOW('c', 4, int),
+ BC_ACQUIRE = _IOW('c', 5, int),
+ BC_RELEASE = _IOW('c', 6, int),
+ BC_DECREFS = _IOW('c', 7, int),
+ /*
+ * int: descriptor
+ */
+
+ BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
+ BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
+ /*
+ * void *: ptr to binder
+ * void *: cookie for binder
+ */
+
+ BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
+ /*
+ * not currently supported
+ * int: priority
+ * int: descriptor
+ */
+
+ BC_REGISTER_LOOPER = _IO('c', 11),
+ /*
+ * No parameters.
+ * Register a spawned looper thread with the device.
+ */
+
+ BC_ENTER_LOOPER = _IO('c', 12),
+ BC_EXIT_LOOPER = _IO('c', 13),
+ /*
+ * No parameters.
+ * These two commands are sent as an application-level thread
+ * enters and exits the binder loop, respectively. They are
+ * used so the binder can have an accurate count of the number
+ * of looping threads it has available.
+ */
+
+ BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie),
+ /*
+ * void *: ptr to binder
+ * void *: cookie
+ */
+
+ BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie),
+ /*
+ * void *: ptr to binder
+ * void *: cookie
+ */
+
+ BC_DEAD_BINDER_DONE = _IOW('c', 16, void *),
+ /*
+ * void *: cookie
+ */
+};
+
+#endif /* _LINUX_BINDER_H */
+
diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c
new file mode 100644
index 000000000000..ffc2d043dd8e
--- /dev/null
+++ b/drivers/staging/android/logger.c
@@ -0,0 +1,616 @@
+/*
+ * drivers/misc/logger.c
+ *
+ * A Logging Subsystem
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ *
+ * Robert Love <rlove@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include "logger.h"
+
+#include <asm/ioctls.h>
+
+/*
+ * struct logger_log - represents a specific log, such as 'main' or 'radio'
+ *
+ * This structure lives from module insertion until module removal, so it does
+ * not need additional reference counting. The structure is protected by the
+ * mutex 'mutex'.
+ */
+struct logger_log {
+ unsigned char *buffer;/* the ring buffer itself */
+ struct miscdevice misc; /* misc device representing the log */
+ wait_queue_head_t wq; /* wait queue for readers */
+ struct list_head readers; /* this log's readers */
+ struct mutex mutex; /* mutex protecting buffer */
+ size_t w_off; /* current write head offset */
+ size_t head; /* new readers start here */
+ size_t size; /* size of the log */
+};
+
+/*
+ * struct logger_reader - a logging device open for reading
+ *
+ * This object lives from open to release, so we don't need additional
+ * reference counting. The structure is protected by log->mutex.
+ */
+struct logger_reader {
+ struct logger_log *log; /* associated log */
+ struct list_head list; /* entry in logger_log's list */
+ size_t r_off; /* current read head offset */
+};
+
+/* logger_offset - returns index 'n' into the log via (optimized) modulus */
+#define logger_offset(n) ((n) & (log->size - 1))
+
+/*
+ * file_get_log - Given a file structure, return the associated log
+ *
+ * This isn't aesthetic. We have several goals:
+ *
+ * 1) Need to quickly obtain the associated log during an I/O operation
+ * 2) Readers need to maintain state (logger_reader)
+ * 3) Writers need to be very fast (open() should be a near no-op)
+ *
+ * In the reader case, we can trivially go file->logger_reader->logger_log.
+ * For a writer, we don't want to maintain a logger_reader, so we just go
+ * file->logger_log. Thus what file->private_data points at depends on whether
+ * or not the file was opened for reading. This function hides that dirtiness.
+ */
+static inline struct logger_log *file_get_log(struct file *file)
+{
+ if (file->f_mode & FMODE_READ) {
+ struct logger_reader *reader = file->private_data;
+ return reader->log;
+ } else
+ return file->private_data;
+}
+
+/*
+ * get_entry_len - Grabs the length of the payload of the next entry starting
+ * from 'off'.
+ *
+ * Caller needs to hold log->mutex.
+ */
+static __u32 get_entry_len(struct logger_log *log, size_t off)
+{
+ __u16 val;
+
+ switch (log->size - off) {
+ case 1:
+ memcpy(&val, log->buffer + off, 1);
+ memcpy(((char *) &val) + 1, log->buffer, 1);
+ break;
+ default:
+ memcpy(&val, log->buffer + off, 2);
+ }
+
+ return sizeof(struct logger_entry) + val;
+}
+
+/*
+ * do_read_log_to_user - reads exactly 'count' bytes from 'log' into the
+ * user-space buffer 'buf'. Returns 'count' on success.
+ *
+ * Caller must hold log->mutex.
+ */
+static ssize_t do_read_log_to_user(struct logger_log *log,
+ struct logger_reader *reader,
+ char __user *buf,
+ size_t count)
+{
+ size_t len;
+
+ /*
+ * 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
+ * the log, whichever comes first.
+ */
+ len = min(count, log->size - reader->r_off);
+ if (copy_to_user(buf, log->buffer + reader->r_off, len))
+ return -EFAULT;
+
+ /*
+ * Second, we read any remaining bytes, starting back at the head of
+ * the log.
+ */
+ if (count != len)
+ if (copy_to_user(buf + len, log->buffer, count - len))
+ return -EFAULT;
+
+ reader->r_off = logger_offset(reader->r_off + count);
+
+ return count;
+}
+
+/*
+ * logger_read - our log's read() method
+ *
+ * Behavior:
+ *
+ * - O_NONBLOCK works
+ * - 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
+ * buffer is insufficient to hold next entry.
+ */
+static ssize_t logger_read(struct file *file, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ struct logger_reader *reader = file->private_data;
+ struct logger_log *log = reader->log;
+ ssize_t ret;
+ DEFINE_WAIT(wait);
+
+start:
+ while (1) {
+ prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE);
+
+ mutex_lock(&log->mutex);
+ ret = (log->w_off == reader->r_off);
+ mutex_unlock(&log->mutex);
+ if (!ret)
+ break;
+
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
+
+ schedule();
+ }
+
+ finish_wait(&log->wq, &wait);
+ if (ret)
+ return ret;
+
+ mutex_lock(&log->mutex);
+
+ /* is there still something to read or did we race? */
+ if (unlikely(log->w_off == reader->r_off)) {
+ mutex_unlock(&log->mutex);
+ goto start;
+ }
+
+ /* get the size of the next entry */
+ ret = get_entry_len(log, reader->r_off);
+ if (count < ret) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* get exactly one entry from the log */
+ ret = do_read_log_to_user(log, reader, buf, ret);
+
+out:
+ mutex_unlock(&log->mutex);
+
+ return ret;
+}
+
+/*
+ * get_next_entry - return the offset of the first valid entry at least 'len'
+ * bytes after 'off'.
+ *
+ * Caller must hold log->mutex.
+ */
+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);
+ off = logger_offset(off + nr);
+ count += nr;
+ } while (count < len);
+
+ return off;
+}
+
+/*
+ * clock_interval - is a < c < b in mod-space? Put another way, does the line
+ * from a to b cross c?
+ */
+static inline int clock_interval(size_t a, size_t b, size_t c)
+{
+ if (b < a) {
+ if (a < c || b >= c)
+ return 1;
+ } else {
+ if (a < c && b >= c)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * fix_up_readers - walk the list of all readers and "fix up" any who were
+ * lapped by the writer; also do the same for the default "start head".
+ * We do this by "pulling forward" the readers and start head to the first
+ * entry after the new write head.
+ *
+ * The caller needs to hold log->mutex.
+ */
+static void fix_up_readers(struct logger_log *log, size_t len)
+{
+ size_t old = log->w_off;
+ size_t new = logger_offset(old + len);
+ struct logger_reader *reader;
+
+ if (clock_interval(old, new, log->head))
+ log->head = get_next_entry(log, log->head, len);
+
+ list_for_each_entry(reader, &log->readers, list)
+ if (clock_interval(old, new, reader->r_off))
+ reader->r_off = get_next_entry(log, reader->r_off, len);
+}
+
+/*
+ * do_write_log - writes 'len' bytes from 'buf' to 'log'
+ *
+ * The caller needs to hold log->mutex.
+ */
+static void do_write_log(struct logger_log *log, const void *buf, size_t count)
+{
+ size_t len;
+
+ len = min(count, log->size - log->w_off);
+ memcpy(log->buffer + log->w_off, buf, len);
+
+ if (count != len)
+ memcpy(log->buffer, buf + len, count - len);
+
+ log->w_off = logger_offset(log->w_off + count);
+
+}
+
+/*
+ * do_write_log_user - writes 'len' bytes from the user-space buffer 'buf' to
+ * the log 'log'
+ *
+ * The caller needs to hold log->mutex.
+ *
+ * Returns 'count' on success, negative error code on failure.
+ */
+static ssize_t do_write_log_from_user(struct logger_log *log,
+ const void __user *buf, size_t count)
+{
+ size_t len;
+
+ len = min(count, log->size - log->w_off);
+ if (len && copy_from_user(log->buffer + log->w_off, buf, len))
+ return -EFAULT;
+
+ if (count != len)
+ if (copy_from_user(log->buffer, buf + len, count - len))
+ return -EFAULT;
+
+ log->w_off = logger_offset(log->w_off + count);
+
+ return count;
+}
+
+/*
+ * logger_aio_write - our write method, implementing support for write(),
+ * writev(), and aio_write(). Writes are our fast path, and we try to optimize
+ * them above all else.
+ */
+ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t ppos)
+{
+ struct logger_log *log = file_get_log(iocb->ki_filp);
+ size_t orig = log->w_off;
+ struct logger_entry header;
+ struct timespec now;
+ ssize_t ret = 0;
+
+ now = current_kernel_time();
+
+ header.pid = current->tgid;
+ header.tid = current->pid;
+ header.sec = now.tv_sec;
+ header.nsec = now.tv_nsec;
+ header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD);
+
+ /* null writes succeed, return zero */
+ if (unlikely(!header.len))
+ return 0;
+
+ mutex_lock(&log->mutex);
+
+ /*
+ * Fix up any readers, pulling them forward to the first readable
+ * entry after (what will be) the new write offset. We do this now
+ * because if we partially fail, we can end up with clobbered log
+ * entries that encroach on readable buffer.
+ */
+ fix_up_readers(log, sizeof(struct logger_entry) + header.len);
+
+ do_write_log(log, &header, sizeof(struct logger_entry));
+
+ while (nr_segs-- > 0) {
+ size_t len;
+ ssize_t nr;
+
+ /* figure out how much of this vector we can keep */
+ len = min_t(size_t, iov->iov_len, header.len - ret);
+
+ /* write out this segment's payload */
+ nr = do_write_log_from_user(log, iov->iov_base, len);
+ if (unlikely(nr < 0)) {
+ log->w_off = orig;
+ mutex_unlock(&log->mutex);
+ return nr;
+ }
+
+ iov++;
+ ret += nr;
+ }
+
+ mutex_unlock(&log->mutex);
+
+ /* wake up any blocked readers */
+ wake_up_interruptible(&log->wq);
+
+ return ret;
+}
+
+static struct logger_log *get_log_from_minor(int);
+
+/*
+ * logger_open - the log's open() file operation
+ *
+ * Note how near a no-op this is in the write-only case. Keep it that way!
+ */
+static int logger_open(struct inode *inode, struct file *file)
+{
+ struct logger_log *log;
+ int ret;
+
+ ret = nonseekable_open(inode, file);
+ if (ret)
+ return ret;
+
+ log = get_log_from_minor(MINOR(inode->i_rdev));
+ if (!log)
+ return -ENODEV;
+
+ if (file->f_mode & FMODE_READ) {
+ struct logger_reader *reader;
+
+ reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL);
+ if (!reader)
+ return -ENOMEM;
+
+ reader->log = log;
+ INIT_LIST_HEAD(&reader->list);
+
+ mutex_lock(&log->mutex);
+ reader->r_off = log->head;
+ list_add_tail(&reader->list, &log->readers);
+ mutex_unlock(&log->mutex);
+
+ file->private_data = reader;
+ } else
+ file->private_data = log;
+
+ return 0;
+}
+
+/*
+ * logger_release - the log's release file operation
+ *
+ * Note this is a total no-op in the write-only case. Keep it that way!
+ */
+static int logger_release(struct inode *ignored, struct file *file)
+{
+ if (file->f_mode & FMODE_READ) {
+ struct logger_reader *reader = file->private_data;
+ list_del(&reader->list);
+ kfree(reader);
+ }
+
+ return 0;
+}
+
+/*
+ * logger_poll - the log's poll file operation, for poll/select/epoll
+ *
+ * Note we always return POLLOUT, because you can always write() to the log.
+ * Note also that, strictly speaking, a return value of POLLIN does not
+ * guarantee that the log is readable without blocking, as there is a small
+ * chance that the writer can lap the reader in the interim between poll()
+ * returning and the read() request.
+ */
+static unsigned int logger_poll(struct file *file, poll_table *wait)
+{
+ struct logger_reader *reader;
+ struct logger_log *log;
+ unsigned int ret = POLLOUT | POLLWRNORM;
+
+ if (!(file->f_mode & FMODE_READ))
+ return ret;
+
+ reader = file->private_data;
+ log = reader->log;
+
+ poll_wait(file, &log->wq, wait);
+
+ mutex_lock(&log->mutex);
+ if (log->w_off != reader->r_off)
+ ret |= POLLIN | POLLRDNORM;
+ mutex_unlock(&log->mutex);
+
+ return ret;
+}
+
+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;
+
+ mutex_lock(&log->mutex);
+
+ switch (cmd) {
+ case LOGGER_GET_LOG_BUF_SIZE:
+ ret = log->size;
+ break;
+ case LOGGER_GET_LOG_LEN:
+ if (!(file->f_mode & FMODE_READ)) {
+ ret = -EBADF;
+ break;
+ }
+ reader = file->private_data;
+ if (log->w_off >= reader->r_off)
+ ret = log->w_off - reader->r_off;
+ else
+ ret = (log->size - reader->r_off) + log->w_off;
+ break;
+ case LOGGER_GET_NEXT_ENTRY_LEN:
+ if (!(file->f_mode & FMODE_READ)) {
+ ret = -EBADF;
+ break;
+ }
+ reader = file->private_data;
+ if (log->w_off != reader->r_off)
+ ret = get_entry_len(log, reader->r_off);
+ else
+ ret = 0;
+ break;
+ case LOGGER_FLUSH_LOG:
+ if (!(file->f_mode & FMODE_WRITE)) {
+ ret = -EBADF;
+ break;
+ }
+ list_for_each_entry(reader, &log->readers, list)
+ reader->r_off = log->w_off;
+ log->head = log->w_off;
+ ret = 0;
+ break;
+ }
+
+ mutex_unlock(&log->mutex);
+
+ return ret;
+}
+
+static const struct file_operations logger_fops = {
+ .owner = THIS_MODULE,
+ .read = logger_read,
+ .aio_write = logger_aio_write,
+ .poll = logger_poll,
+ .unlocked_ioctl = logger_ioctl,
+ .compat_ioctl = logger_ioctl,
+ .open = logger_open,
+ .release = logger_release,
+};
+
+/*
+ * Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which
+ * must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than
+ * LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
+ */
+#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \
+static unsigned char _buf_ ## VAR[SIZE]; \
+static struct logger_log VAR = { \
+ .buffer = _buf_ ## VAR, \
+ .misc = { \
+ .minor = MISC_DYNAMIC_MINOR, \
+ .name = NAME, \
+ .fops = &logger_fops, \
+ .parent = NULL, \
+ }, \
+ .wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \
+ .readers = LIST_HEAD_INIT(VAR .readers), \
+ .mutex = __MUTEX_INITIALIZER(VAR .mutex), \
+ .w_off = 0, \
+ .head = 0, \
+ .size = SIZE, \
+};
+
+DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 256*1024)
+DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)
+DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 256*1024)
+DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 256*1024)
+
+static struct logger_log *get_log_from_minor(int minor)
+{
+ if (log_main.misc.minor == minor)
+ return &log_main;
+ if (log_events.misc.minor == minor)
+ return &log_events;
+ if (log_radio.misc.minor == minor)
+ return &log_radio;
+ if (log_system.misc.minor == minor)
+ return &log_system;
+ return NULL;
+}
+
+static int __init init_log(struct logger_log *log)
+{
+ int ret;
+
+ ret = misc_register(&log->misc);
+ if (unlikely(ret)) {
+ printk(KERN_ERR "logger: failed to register misc "
+ "device for log '%s'!\n", log->misc.name);
+ return ret;
+ }
+
+ printk(KERN_INFO "logger: created %luK log '%s'\n",
+ (unsigned long) log->size >> 10, log->misc.name);
+
+ return 0;
+}
+
+static int __init logger_init(void)
+{
+ int ret;
+
+ ret = init_log(&log_main);
+ if (unlikely(ret))
+ goto out;
+
+ ret = init_log(&log_events);
+ if (unlikely(ret))
+ goto out;
+
+ ret = init_log(&log_radio);
+ if (unlikely(ret))
+ goto out;
+
+ ret = init_log(&log_system);
+ if (unlikely(ret))
+ goto out;
+
+out:
+ return ret;
+}
+device_initcall(logger_init);
diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h
new file mode 100644
index 000000000000..2cb06e9d8f98
--- /dev/null
+++ b/drivers/staging/android/logger.h
@@ -0,0 +1,49 @@
+/* include/linux/logger.h
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ * Author: Robert Love <rlove@android.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.
+ *
+ */
+
+#ifndef _LINUX_LOGGER_H
+#define _LINUX_LOGGER_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+struct logger_entry {
+ __u16 len; /* length of the payload */
+ __u16 __pad; /* no matter what, we get 2 bytes of padding */
+ __s32 pid; /* generating process's pid */
+ __s32 tid; /* generating process's tid */
+ __s32 sec; /* seconds since Epoch */
+ __s32 nsec; /* nanoseconds */
+ char msg[0]; /* the entry's payload */
+};
+
+#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 __LOGGERIO 0xAE
+
+#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */
+#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 */
+
+#endif /* _LINUX_LOGGER_H */
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
new file mode 100644
index 000000000000..2d8d2b796101
--- /dev/null
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -0,0 +1,219 @@
+/* drivers/misc/lowmemorykiller.c
+ *
+ * The lowmemorykiller driver lets user-space specify a set of memory thresholds
+ * where processes with a range of oom_adj values will get killed. Specify the
+ * minimum oom_adj values in /sys/module/lowmemorykiller/parameters/adj and the
+ * number of free pages in /sys/module/lowmemorykiller/parameters/minfree. Both
+ * files take a comma separated list of numbers in ascending order.
+ *
+ * For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and
+ * "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill
+ * processes with a oom_adj value of 8 or higher when the free memory drops
+ * below 4096 pages and kill processes with a oom_adj value of 0 or higher
+ * when the free memory drops below 1024 pages.
+ *
+ * The driver considers memory used for caches to be free, but if a large
+ * percentage of the cached memory is locked this can be very inaccurate
+ * and processes may not get killed until the normal oom killer is triggered.
+ *
+ * Copyright (C) 2007-2008 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/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/oom.h>
+#include <linux/sched.h>
+#include <linux/profile.h>
+#include <linux/notifier.h>
+
+static uint32_t lowmem_debug_level = 2;
+static int lowmem_adj[6] = {
+ 0,
+ 1,
+ 6,
+ 12,
+};
+static int lowmem_adj_size = 4;
+static size_t lowmem_minfree[6] = {
+ 3 * 512, /* 6MB */
+ 2 * 1024, /* 8MB */
+ 4 * 1024, /* 16MB */
+ 16 * 1024, /* 64MB */
+};
+static int lowmem_minfree_size = 4;
+
+static struct task_struct *lowmem_deathpending;
+
+#define lowmem_print(level, x...) \
+ do { \
+ if (lowmem_debug_level >= (level)) \
+ printk(x); \
+ } while (0)
+
+static int
+task_notify_func(struct notifier_block *self, unsigned long val, void *data);
+
+static struct notifier_block task_nb = {
+ .notifier_call = task_notify_func,
+};
+
+static int
+task_notify_func(struct notifier_block *self, unsigned long val, void *data)
+{
+ struct task_struct *task = data;
+ if (task == lowmem_deathpending) {
+ lowmem_deathpending = NULL;
+ task_handoff_unregister(&task_nb);
+ }
+ return NOTIFY_OK;
+}
+
+static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
+{
+ struct task_struct *p;
+ struct task_struct *selected = NULL;
+ int rem = 0;
+ int tasksize;
+ int i;
+ int min_adj = OOM_ADJUST_MAX + 1;
+ int selected_tasksize = 0;
+ int selected_oom_adj;
+ int array_size = ARRAY_SIZE(lowmem_adj);
+ int other_free = global_page_state(NR_FREE_PAGES);
+ int other_file = global_page_state(NR_FILE_PAGES) -
+ global_page_state(NR_SHMEM);
+
+ /*
+ * If we already have a death outstanding, then
+ * bail out right away; indicating to vmscan
+ * that we have nothing further to offer on
+ * this pass.
+ *
+ * Note: Currently you need CONFIG_PROFILING
+ * for this to work correctly.
+ */
+ if (lowmem_deathpending)
+ return 0;
+
+ if (lowmem_adj_size < array_size)
+ array_size = lowmem_adj_size;
+ if (lowmem_minfree_size < array_size)
+ array_size = lowmem_minfree_size;
+ for (i = 0; i < array_size; i++) {
+ if (other_free < lowmem_minfree[i] &&
+ other_file < lowmem_minfree[i]) {
+ min_adj = lowmem_adj[i];
+ break;
+ }
+ }
+ if (sc->nr_to_scan > 0)
+ lowmem_print(3, "lowmem_shrink %lu, %x, ofree %d %d, ma %d\n",
+ sc->nr_to_scan, sc->gfp_mask, other_free,
+ other_file, min_adj);
+ rem = global_page_state(NR_ACTIVE_ANON) +
+ global_page_state(NR_ACTIVE_FILE) +
+ global_page_state(NR_INACTIVE_ANON) +
+ global_page_state(NR_INACTIVE_FILE);
+ if (sc->nr_to_scan <= 0 || min_adj == OOM_ADJUST_MAX + 1) {
+ lowmem_print(5, "lowmem_shrink %lu, %x, return %d\n",
+ sc->nr_to_scan, sc->gfp_mask, rem);
+ return rem;
+ }
+ selected_oom_adj = min_adj;
+
+ read_lock(&tasklist_lock);
+ for_each_process(p) {
+ struct mm_struct *mm;
+ struct signal_struct *sig;
+ int oom_adj;
+
+ task_lock(p);
+ mm = p->mm;
+ sig = p->signal;
+ if (!mm || !sig) {
+ task_unlock(p);
+ continue;
+ }
+ oom_adj = sig->oom_adj;
+ if (oom_adj < min_adj) {
+ task_unlock(p);
+ continue;
+ }
+ tasksize = get_mm_rss(mm);
+ task_unlock(p);
+ if (tasksize <= 0)
+ continue;
+ if (selected) {
+ if (oom_adj < selected_oom_adj)
+ continue;
+ if (oom_adj == selected_oom_adj &&
+ tasksize <= selected_tasksize)
+ continue;
+ }
+ selected = p;
+ selected_tasksize = tasksize;
+ selected_oom_adj = oom_adj;
+ lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
+ p->pid, p->comm, oom_adj, tasksize);
+ }
+ if (selected) {
+ lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
+ selected->pid, selected->comm,
+ selected_oom_adj, selected_tasksize);
+ /*
+ * If CONFIG_PROFILING is off, then task_handoff_register()
+ * is a nop. In that case we don't want to stall the killer
+ * by setting lowmem_deathpending.
+ */
+#ifdef CONFIG_PROFILING
+ lowmem_deathpending = selected;
+ task_handoff_register(&task_nb);
+#endif
+ force_sig(SIGKILL, selected);
+ rem -= selected_tasksize;
+ }
+ lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",
+ sc->nr_to_scan, sc->gfp_mask, rem);
+ read_unlock(&tasklist_lock);
+ return rem;
+}
+
+static struct shrinker lowmem_shrinker = {
+ .shrink = lowmem_shrink,
+ .seeks = DEFAULT_SEEKS * 16
+};
+
+static int __init lowmem_init(void)
+{
+ register_shrinker(&lowmem_shrinker);
+ return 0;
+}
+
+static void __exit lowmem_exit(void)
+{
+ unregister_shrinker(&lowmem_shrinker);
+}
+
+module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
+module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size,
+ S_IRUGO | S_IWUSR);
+module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
+ S_IRUGO | S_IWUSR);
+module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
+
+module_init(lowmem_init);
+module_exit(lowmem_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/staging/android/pmem.c b/drivers/staging/android/pmem.c
new file mode 100644
index 000000000000..7d97032c6508
--- /dev/null
+++ b/drivers/staging/android/pmem.c
@@ -0,0 +1,1345 @@
+/* pmem.c
+ *
+ * Copyright (C) 2007 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/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/mempolicy.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+#include "android_pmem.h"
+
+#define PMEM_MAX_DEVICES 10
+#define PMEM_MAX_ORDER 128
+#define PMEM_MIN_ALLOC PAGE_SIZE
+
+#define PMEM_DEBUG 1
+
+/* indicates that a refernce to this file has been taken via get_pmem_file,
+ * the file should not be released until put_pmem_file is called */
+#define PMEM_FLAGS_BUSY 0x1
+/* indicates that this is a suballocation of a larger master range */
+#define PMEM_FLAGS_CONNECTED 0x1 << 1
+/* indicates this is a master and not a sub allocation and that it is mmaped */
+#define PMEM_FLAGS_MASTERMAP 0x1 << 2
+/* submap and unsubmap flags indicate:
+ * 00: subregion has never been mmaped
+ * 10: subregion has been mmaped, reference to the mm was taken
+ * 11: subretion has ben released, refernece to the mm still held
+ * 01: subretion has been released, reference to the mm has been released
+ */
+#define PMEM_FLAGS_SUBMAP 0x1 << 3
+#define PMEM_FLAGS_UNSUBMAP 0x1 << 4
+
+
+struct pmem_data {
+ /* in alloc mode: an index into the bitmap
+ * in no_alloc mode: the size of the allocation */
+ int index;
+ /* see flags above for descriptions */
+ unsigned int flags;
+ /* protects this data field, if the mm_mmap sem will be held at the
+ * same time as this sem, the mm sem must be taken first (as this is
+ * the order for vma_open and vma_close ops */
+ struct rw_semaphore sem;
+ /* info about the mmaping process */
+ struct vm_area_struct *vma;
+ /* task struct of the mapping process */
+ struct task_struct *task;
+ /* process id of teh mapping process */
+ pid_t pid;
+ /* file descriptor of the master */
+ int master_fd;
+ /* file struct of the master */
+ struct file *master_file;
+ /* a list of currently available regions if this is a suballocation */
+ struct list_head region_list;
+ /* a linked list of data so we can access them for debugging */
+ struct list_head list;
+#if PMEM_DEBUG
+ int ref;
+#endif
+};
+
+struct pmem_bits {
+ unsigned allocated:1; /* 1 if allocated, 0 if free */
+ unsigned order:7; /* size of the region in pmem space */
+};
+
+struct pmem_region_node {
+ struct pmem_region region;
+ struct list_head list;
+};
+
+#define PMEM_DEBUG_MSGS 0
+#if PMEM_DEBUG_MSGS
+#define DLOG(fmt,args...) \
+ do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
+ ##args); } \
+ while (0)
+#else
+#define DLOG(x...) do {} while (0)
+#endif
+
+struct pmem_info {
+ struct miscdevice dev;
+ /* physical start address of the remaped pmem space */
+ unsigned long base;
+ /* vitual start address of the remaped pmem space */
+ unsigned char __iomem *vbase;
+ /* total size of the pmem space */
+ unsigned long size;
+ /* number of entries in the pmem space */
+ unsigned long num_entries;
+ /* pfn of the garbage page in memory */
+ unsigned long garbage_pfn;
+ /* index of the garbage page in the pmem space */
+ int garbage_index;
+ /* the bitmap for the region indicating which entries are allocated
+ * and which are free */
+ struct pmem_bits *bitmap;
+ /* indicates the region should not be managed with an allocator */
+ unsigned no_allocator;
+ /* indicates maps of this region should be cached, if a mix of
+ * cached and uncached is desired, set this and open the device with
+ * O_SYNC to get an uncached region */
+ unsigned cached;
+ unsigned buffered;
+ /* in no_allocator mode the first mapper gets the whole space and sets
+ * this flag */
+ unsigned allocated;
+ /* for debugging, creates a list of pmem file structs, the
+ * data_list_lock should be taken before pmem_data->sem if both are
+ * needed */
+ struct mutex data_list_lock;
+ struct list_head data_list;
+ /* pmem_sem protects the bitmap array
+ * a write lock should be held when modifying entries in bitmap
+ * a read lock should be held when reading data from bits or
+ * dereferencing a pointer into bitmap
+ *
+ * pmem_data->sem protects the pmem data of a particular file
+ * Many of the function that require the pmem_data->sem have a non-
+ * locking version for when the caller is already holding that sem.
+ *
+ * IF YOU TAKE BOTH LOCKS TAKE THEM IN THIS ORDER:
+ * down(pmem_data->sem) => down(bitmap_sem)
+ */
+ struct rw_semaphore bitmap_sem;
+
+ long (*ioctl)(struct file *, unsigned int, unsigned long);
+ int (*release)(struct inode *, struct file *);
+};
+
+static struct pmem_info pmem[PMEM_MAX_DEVICES];
+static int id_count;
+
+#define PMEM_IS_FREE(id, index) !(pmem[id].bitmap[index].allocated)
+#define PMEM_ORDER(id, index) pmem[id].bitmap[index].order
+#define PMEM_BUDDY_INDEX(id, index) (index ^ (1 << PMEM_ORDER(id, index)))
+#define PMEM_NEXT_INDEX(id, index) (index + (1 << PMEM_ORDER(id, index)))
+#define PMEM_OFFSET(index) (index * PMEM_MIN_ALLOC)
+#define PMEM_START_ADDR(id, index) (PMEM_OFFSET(index) + pmem[id].base)
+#define PMEM_LEN(id, index) ((1 << PMEM_ORDER(id, index)) * PMEM_MIN_ALLOC)
+#define PMEM_END_ADDR(id, index) (PMEM_START_ADDR(id, index) + \
+ PMEM_LEN(id, index))
+#define PMEM_START_VADDR(id, index) (PMEM_OFFSET(id, index) + pmem[id].vbase)
+#define PMEM_END_VADDR(id, index) (PMEM_START_VADDR(id, index) + \
+ PMEM_LEN(id, index))
+#define PMEM_REVOKED(data) (data->flags & PMEM_FLAGS_REVOKED)
+#define PMEM_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
+#define PMEM_IS_SUBMAP(data) ((data->flags & PMEM_FLAGS_SUBMAP) && \
+ (!(data->flags & PMEM_FLAGS_UNSUBMAP)))
+
+static int pmem_release(struct inode *, struct file *);
+static int pmem_mmap(struct file *, struct vm_area_struct *);
+static int pmem_open(struct inode *, struct file *);
+static long pmem_ioctl(struct file *, unsigned int, unsigned long);
+
+struct file_operations pmem_fops = {
+ .release = pmem_release,
+ .mmap = pmem_mmap,
+ .open = pmem_open,
+ .unlocked_ioctl = pmem_ioctl,
+};
+
+static int get_id(struct file *file)
+{
+ return MINOR(file->f_dentry->d_inode->i_rdev);
+}
+
+int is_pmem_file(struct file *file)
+{
+ int id;
+
+ if (unlikely(!file || !file->f_dentry || !file->f_dentry->d_inode))
+ return 0;
+ id = get_id(file);
+ if (unlikely(id >= PMEM_MAX_DEVICES))
+ return 0;
+ if (unlikely(file->f_dentry->d_inode->i_rdev !=
+ MKDEV(MISC_MAJOR, pmem[id].dev.minor)))
+ return 0;
+ return 1;
+}
+
+static int has_allocation(struct file *file)
+{
+ struct pmem_data *data;
+ /* check is_pmem_file first if not accessed via pmem_file_ops */
+
+ if (unlikely(!file->private_data))
+ return 0;
+ data = (struct pmem_data *)file->private_data;
+ if (unlikely(data->index < 0))
+ return 0;
+ return 1;
+}
+
+static int is_master_owner(struct file *file)
+{
+ struct file *master_file;
+ struct pmem_data *data;
+ int put_needed, ret = 0;
+
+ if (!is_pmem_file(file) || !has_allocation(file))
+ return 0;
+ data = (struct pmem_data *)file->private_data;
+ if (PMEM_FLAGS_MASTERMAP & data->flags)
+ return 1;
+ master_file = fget_light(data->master_fd, &put_needed);
+ if (master_file && data->master_file == master_file)
+ ret = 1;
+ fput_light(master_file, put_needed);
+ return ret;
+}
+
+static int pmem_free(int id, int index)
+{
+ /* caller should hold the write lock on pmem_sem! */
+ int buddy, curr = index;
+ DLOG("index %d\n", index);
+
+ if (pmem[id].no_allocator) {
+ pmem[id].allocated = 0;
+ return 0;
+ }
+ /* clean up the bitmap, merging any buddies */
+ pmem[id].bitmap[curr].allocated = 0;
+ /* find a slots buddy Buddy# = Slot# ^ (1 << order)
+ * if the buddy is also free merge them
+ * repeat until the buddy is not free or end of the bitmap is reached
+ */
+ do {
+ buddy = PMEM_BUDDY_INDEX(id, curr);
+ if (PMEM_IS_FREE(id, buddy) &&
+ PMEM_ORDER(id, buddy) == PMEM_ORDER(id, curr)) {
+ PMEM_ORDER(id, buddy)++;
+ PMEM_ORDER(id, curr)++;
+ curr = min(buddy, curr);
+ } else {
+ break;
+ }
+ } while (curr < pmem[id].num_entries);
+
+ return 0;
+}
+
+static void pmem_revoke(struct file *file, struct pmem_data *data);
+
+static int pmem_release(struct inode *inode, struct file *file)
+{
+ struct pmem_data *data = (struct pmem_data *)file->private_data;
+ struct pmem_region_node *region_node;
+ struct list_head *elt, *elt2;
+ int id = get_id(file), ret = 0;
+
+
+ mutex_lock(&pmem[id].data_list_lock);
+ /* if this file is a master, revoke all the memory in the connected
+ * files */
+ if (PMEM_FLAGS_MASTERMAP & data->flags) {
+ struct pmem_data *sub_data;
+ list_for_each(elt, &pmem[id].data_list) {
+ sub_data = list_entry(elt, struct pmem_data, list);
+ down_read(&sub_data->sem);
+ if (PMEM_IS_SUBMAP(sub_data) &&
+ file == sub_data->master_file) {
+ up_read(&sub_data->sem);
+ pmem_revoke(file, sub_data);
+ } else
+ up_read(&sub_data->sem);
+ }
+ }
+ list_del(&data->list);
+ mutex_unlock(&pmem[id].data_list_lock);
+
+
+ down_write(&data->sem);
+
+ /* if its not a conencted file and it has an allocation, free it */
+ if (!(PMEM_FLAGS_CONNECTED & data->flags) && has_allocation(file)) {
+ down_write(&pmem[id].bitmap_sem);
+ ret = pmem_free(id, data->index);
+ up_write(&pmem[id].bitmap_sem);
+ }
+
+ /* if this file is a submap (mapped, connected file), downref the
+ * task struct */
+ if (PMEM_FLAGS_SUBMAP & data->flags)
+ if (data->task) {
+ put_task_struct(data->task);
+ data->task = NULL;
+ }
+
+ file->private_data = NULL;
+
+ list_for_each_safe(elt, elt2, &data->region_list) {
+ region_node = list_entry(elt, struct pmem_region_node, list);
+ list_del(elt);
+ kfree(region_node);
+ }
+ BUG_ON(!list_empty(&data->region_list));
+
+ up_write(&data->sem);
+ kfree(data);
+ if (pmem[id].release)
+ ret = pmem[id].release(inode, file);
+
+ return ret;
+}
+
+static int pmem_open(struct inode *inode, struct file *file)
+{
+ struct pmem_data *data;
+ int id = get_id(file);
+ int ret = 0;
+
+ DLOG("current %u file %p(%d)\n", current->pid, file, file_count(file));
+ /* setup file->private_data to indicate its unmapped */
+ /* you can only open a pmem device one time */
+ if (file->private_data != NULL)
+ return -1;
+ data = kmalloc(sizeof(struct pmem_data), GFP_KERNEL);
+ if (!data) {
+ printk("pmem: unable to allocate memory for pmem metadata.");
+ return -1;
+ }
+ data->flags = 0;
+ data->index = -1;
+ data->task = NULL;
+ data->vma = NULL;
+ data->pid = 0;
+ data->master_file = NULL;
+#if PMEM_DEBUG
+ data->ref = 0;
+#endif
+ INIT_LIST_HEAD(&data->region_list);
+ init_rwsem(&data->sem);
+
+ file->private_data = data;
+ INIT_LIST_HEAD(&data->list);
+
+ mutex_lock(&pmem[id].data_list_lock);
+ list_add(&data->list, &pmem[id].data_list);
+ mutex_unlock(&pmem[id].data_list_lock);
+ return ret;
+}
+
+static unsigned long pmem_order(unsigned long len)
+{
+ int i;
+
+ len = (len + PMEM_MIN_ALLOC - 1)/PMEM_MIN_ALLOC;
+ len--;
+ for (i = 0; i < sizeof(len)*8; i++)
+ if (len >> i == 0)
+ break;
+ return i;
+}
+
+static int pmem_allocate(int id, unsigned long len)
+{
+ /* caller should hold the write lock on pmem_sem! */
+ /* return the corresponding pdata[] entry */
+ int curr = 0;
+ int end = pmem[id].num_entries;
+ int best_fit = -1;
+ unsigned long order = pmem_order(len);
+
+ if (pmem[id].no_allocator) {
+ DLOG("no allocator");
+ if ((len > pmem[id].size) || pmem[id].allocated)
+ return -1;
+ pmem[id].allocated = 1;
+ return len;
+ }
+
+ if (order > PMEM_MAX_ORDER)
+ return -1;
+ DLOG("order %lx\n", order);
+
+ /* look through the bitmap:
+ * if you find a free slot of the correct order use it
+ * otherwise, use the best fit (smallest with size > order) slot
+ */
+ while (curr < end) {
+ if (PMEM_IS_FREE(id, curr)) {
+ if (PMEM_ORDER(id, curr) == (unsigned char)order) {
+ /* set the not free bit and clear others */
+ best_fit = curr;
+ break;
+ }
+ if (PMEM_ORDER(id, curr) > (unsigned char)order &&
+ (best_fit < 0 ||
+ PMEM_ORDER(id, curr) < PMEM_ORDER(id, best_fit)))
+ best_fit = curr;
+ }
+ curr = PMEM_NEXT_INDEX(id, curr);
+ }
+
+ /* if best_fit < 0, there are no suitable slots,
+ * return an error
+ */
+ if (best_fit < 0) {
+ printk("pmem: no space left to allocate!\n");
+ return -1;
+ }
+
+ /* now partition the best fit:
+ * split the slot into 2 buddies of order - 1
+ * repeat until the slot is of the correct order
+ */
+ while (PMEM_ORDER(id, best_fit) > (unsigned char)order) {
+ int buddy;
+ PMEM_ORDER(id, best_fit) -= 1;
+ buddy = PMEM_BUDDY_INDEX(id, best_fit);
+ PMEM_ORDER(id, buddy) = PMEM_ORDER(id, best_fit);
+ }
+ pmem[id].bitmap[best_fit].allocated = 1;
+ return best_fit;
+}
+
+static pgprot_t pmem_access_prot(struct file *file, pgprot_t vma_prot)
+{
+ int id = get_id(file);
+#ifdef pgprot_noncached
+ if (pmem[id].cached == 0 || file->f_flags & O_SYNC)
+ return pgprot_noncached(vma_prot);
+#endif
+#ifdef pgprot_ext_buffered
+ else if (pmem[id].buffered)
+ return pgprot_ext_buffered(vma_prot);
+#endif
+ return vma_prot;
+}
+
+static unsigned long pmem_start_addr(int id, struct pmem_data *data)
+{
+ if (pmem[id].no_allocator)
+ return PMEM_START_ADDR(id, 0);
+ else
+ return PMEM_START_ADDR(id, data->index);
+
+}
+
+static void *pmem_start_vaddr(int id, struct pmem_data *data)
+{
+ return pmem_start_addr(id, data) - pmem[id].base + pmem[id].vbase;
+}
+
+static unsigned long pmem_len(int id, struct pmem_data *data)
+{
+ if (pmem[id].no_allocator)
+ return data->index;
+ else
+ return PMEM_LEN(id, data->index);
+}
+
+static int pmem_map_garbage(int id, struct vm_area_struct *vma,
+ struct pmem_data *data, unsigned long offset,
+ unsigned long len)
+{
+ int i, garbage_pages = len >> PAGE_SHIFT;
+
+ vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP | VM_SHARED | VM_WRITE;
+ for (i = 0; i < garbage_pages; i++) {
+ if (vm_insert_pfn(vma, vma->vm_start + offset + (i * PAGE_SIZE),
+ pmem[id].garbage_pfn))
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static int pmem_unmap_pfn_range(int id, struct vm_area_struct *vma,
+ struct pmem_data *data, unsigned long offset,
+ unsigned long len)
+{
+ int garbage_pages;
+ DLOG("unmap offset %lx len %lx\n", offset, len);
+
+ BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
+
+ garbage_pages = len >> PAGE_SHIFT;
+ zap_page_range(vma, vma->vm_start + offset, len, NULL);
+ pmem_map_garbage(id, vma, data, offset, len);
+ return 0;
+}
+
+static int pmem_map_pfn_range(int id, struct vm_area_struct *vma,
+ struct pmem_data *data, unsigned long offset,
+ unsigned long len)
+{
+ DLOG("map offset %lx len %lx\n", offset, len);
+ BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_start));
+ BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_end));
+ BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
+ BUG_ON(!PMEM_IS_PAGE_ALIGNED(offset));
+
+ if (io_remap_pfn_range(vma, vma->vm_start + offset,
+ (pmem_start_addr(id, data) + offset) >> PAGE_SHIFT,
+ len, vma->vm_page_prot)) {
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static int pmem_remap_pfn_range(int id, struct vm_area_struct *vma,
+ struct pmem_data *data, unsigned long offset,
+ unsigned long len)
+{
+ /* hold the mm semp for the vma you are modifying when you call this */
+ BUG_ON(!vma);
+ zap_page_range(vma, vma->vm_start + offset, len, NULL);
+ return pmem_map_pfn_range(id, vma, data, offset, len);
+}
+
+static void pmem_vma_open(struct vm_area_struct *vma)
+{
+ struct file *file = vma->vm_file;
+ struct pmem_data *data = file->private_data;
+ int id = get_id(file);
+ /* this should never be called as we don't support copying pmem
+ * ranges via fork */
+ BUG_ON(!has_allocation(file));
+ down_write(&data->sem);
+ /* remap the garbage pages, forkers don't get access to the data */
+ pmem_unmap_pfn_range(id, vma, data, 0, vma->vm_start - vma->vm_end);
+ up_write(&data->sem);
+}
+
+static void pmem_vma_close(struct vm_area_struct *vma)
+{
+ struct file *file = vma->vm_file;
+ struct pmem_data *data = file->private_data;
+
+ DLOG("current %u ppid %u file %p count %d\n", current->pid,
+ current->parent->pid, file, file_count(file));
+ if (unlikely(!is_pmem_file(file) || !has_allocation(file))) {
+ printk(KERN_WARNING "pmem: something is very wrong, you are "
+ "closing a vm backing an allocation that doesn't "
+ "exist!\n");
+ return;
+ }
+ down_write(&data->sem);
+ if (data->vma == vma) {
+ data->vma = NULL;
+ if ((data->flags & PMEM_FLAGS_CONNECTED) &&
+ (data->flags & PMEM_FLAGS_SUBMAP))
+ data->flags |= PMEM_FLAGS_UNSUBMAP;
+ }
+ /* the kernel is going to free this vma now anyway */
+ up_write(&data->sem);
+}
+
+static struct vm_operations_struct vm_ops = {
+ .open = pmem_vma_open,
+ .close = pmem_vma_close,
+};
+
+static int pmem_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct pmem_data *data;
+ int index;
+ unsigned long vma_size = vma->vm_end - vma->vm_start;
+ int ret = 0, id = get_id(file);
+
+ if (vma->vm_pgoff || !PMEM_IS_PAGE_ALIGNED(vma_size)) {
+#if PMEM_DEBUG
+ printk(KERN_ERR "pmem: mmaps must be at offset zero, aligned"
+ " and a multiple of pages_size.\n");
+#endif
+ return -EINVAL;
+ }
+
+ data = (struct pmem_data *)file->private_data;
+ down_write(&data->sem);
+ /* check this file isn't already mmaped, for submaps check this file
+ * has never been mmaped */
+ if ((data->flags & PMEM_FLAGS_SUBMAP) ||
+ (data->flags & PMEM_FLAGS_UNSUBMAP)) {
+#if PMEM_DEBUG
+ printk(KERN_ERR "pmem: you can only mmap a pmem file once, "
+ "this file is already mmaped. %x\n", data->flags);
+#endif
+ ret = -EINVAL;
+ goto error;
+ }
+ /* if file->private_data == unalloced, alloc*/
+ if (data && data->index == -1) {
+ down_write(&pmem[id].bitmap_sem);
+ index = pmem_allocate(id, vma->vm_end - vma->vm_start);
+ up_write(&pmem[id].bitmap_sem);
+ data->index = index;
+ }
+ /* either no space was available or an error occured */
+ if (!has_allocation(file)) {
+ ret = -EINVAL;
+ printk("pmem: could not find allocation for map.\n");
+ goto error;
+ }
+
+ if (pmem_len(id, data) < vma_size) {
+#if PMEM_DEBUG
+ printk(KERN_WARNING "pmem: mmap size [%lu] does not match"
+ "size of backing region [%lu].\n", vma_size,
+ pmem_len(id, data));
+#endif
+ ret = -EINVAL;
+ goto error;
+ }
+
+ vma->vm_pgoff = pmem_start_addr(id, data) >> PAGE_SHIFT;
+ vma->vm_page_prot = pmem_access_prot(file, vma->vm_page_prot);
+
+ if (data->flags & PMEM_FLAGS_CONNECTED) {
+ struct pmem_region_node *region_node;
+ struct list_head *elt;
+ if (pmem_map_garbage(id, vma, data, 0, vma_size)) {
+ printk("pmem: mmap failed in kernel!\n");
+ ret = -EAGAIN;
+ goto error;
+ }
+ list_for_each(elt, &data->region_list) {
+ region_node = list_entry(elt, struct pmem_region_node,
+ list);
+ DLOG("remapping file: %p %lx %lx\n", file,
+ region_node->region.offset,
+ region_node->region.len);
+ if (pmem_remap_pfn_range(id, vma, data,
+ region_node->region.offset,
+ region_node->region.len)) {
+ ret = -EAGAIN;
+ goto error;
+ }
+ }
+ data->flags |= PMEM_FLAGS_SUBMAP;
+ get_task_struct(current->group_leader);
+ data->task = current->group_leader;
+ data->vma = vma;
+#if PMEM_DEBUG
+ data->pid = current->pid;
+#endif
+ DLOG("submmapped file %p vma %p pid %u\n", file, vma,
+ current->pid);
+ } else {
+ if (pmem_map_pfn_range(id, vma, data, 0, vma_size)) {
+ printk(KERN_INFO "pmem: mmap failed in kernel!\n");
+ ret = -EAGAIN;
+ goto error;
+ }
+ data->flags |= PMEM_FLAGS_MASTERMAP;
+ data->pid = current->pid;
+ }
+ vma->vm_ops = &vm_ops;
+error:
+ up_write(&data->sem);
+ return ret;
+}
+
+/* the following are the api for accessing pmem regions by other drivers
+ * from inside the kernel */
+int get_pmem_user_addr(struct file *file, unsigned long *start,
+ unsigned long *len)
+{
+ struct pmem_data *data;
+ if (!is_pmem_file(file) || !has_allocation(file)) {
+#if PMEM_DEBUG
+ printk(KERN_INFO "pmem: requested pmem data from invalid"
+ "file.\n");
+#endif
+ return -1;
+ }
+ data = (struct pmem_data *)file->private_data;
+ down_read(&data->sem);
+ if (data->vma) {
+ *start = data->vma->vm_start;
+ *len = data->vma->vm_end - data->vma->vm_start;
+ } else {
+ *start = 0;
+ *len = 0;
+ }
+ up_read(&data->sem);
+ return 0;
+}
+
+int get_pmem_addr(struct file *file, unsigned long *start,
+ unsigned long *vstart, unsigned long *len)
+{
+ struct pmem_data *data;
+ int id;
+
+ if (!is_pmem_file(file) || !has_allocation(file)) {
+ return -1;
+ }
+
+ data = (struct pmem_data *)file->private_data;
+ if (data->index == -1) {
+#if PMEM_DEBUG
+ printk(KERN_INFO "pmem: requested pmem data from file with no "
+ "allocation.\n");
+ return -1;
+#endif
+ }
+ id = get_id(file);
+
+ down_read(&data->sem);
+ *start = pmem_start_addr(id, data);
+ *len = pmem_len(id, data);
+ *vstart = (unsigned long)pmem_start_vaddr(id, data);
+ up_read(&data->sem);
+#if PMEM_DEBUG
+ down_write(&data->sem);
+ data->ref++;
+ up_write(&data->sem);
+#endif
+ return 0;
+}
+
+int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
+ unsigned long *len, struct file **filp)
+{
+ struct file *file;
+
+ file = fget(fd);
+ if (unlikely(file == NULL)) {
+ printk(KERN_INFO "pmem: requested data from file descriptor "
+ "that doesn't exist.");
+ return -1;
+ }
+
+ if (get_pmem_addr(file, start, vstart, len))
+ goto end;
+
+ if (filp)
+ *filp = file;
+ return 0;
+end:
+ fput(file);
+ return -1;
+}
+
+void put_pmem_file(struct file *file)
+{
+ struct pmem_data *data;
+ int id;
+
+ if (!is_pmem_file(file))
+ return;
+ id = get_id(file);
+ data = (struct pmem_data *)file->private_data;
+#if PMEM_DEBUG
+ down_write(&data->sem);
+ if (data->ref == 0) {
+ printk("pmem: pmem_put > pmem_get %s (pid %d)\n",
+ pmem[id].dev.name, data->pid);
+ BUG();
+ }
+ data->ref--;
+ up_write(&data->sem);
+#endif
+ fput(file);
+}
+
+void flush_pmem_file(struct file *file, unsigned long offset, unsigned long len)
+{
+ struct pmem_data *data;
+ int id;
+ void *vaddr;
+ struct pmem_region_node *region_node;
+ struct list_head *elt;
+ void *flush_start, *flush_end;
+
+ if (!is_pmem_file(file) || !has_allocation(file)) {
+ return;
+ }
+
+ id = get_id(file);
+ data = (struct pmem_data *)file->private_data;
+ if (!pmem[id].cached || file->f_flags & O_SYNC)
+ return;
+
+ down_read(&data->sem);
+ vaddr = pmem_start_vaddr(id, data);
+ /* if this isn't a submmapped file, flush the whole thing */
+ if (unlikely(!(data->flags & PMEM_FLAGS_CONNECTED))) {
+ dmac_flush_range(vaddr, vaddr + pmem_len(id, data));
+ goto end;
+ }
+ /* otherwise, flush the region of the file we are drawing */
+ list_for_each(elt, &data->region_list) {
+ region_node = list_entry(elt, struct pmem_region_node, list);
+ if ((offset >= region_node->region.offset) &&
+ ((offset + len) <= (region_node->region.offset +
+ region_node->region.len))) {
+ flush_start = vaddr + region_node->region.offset;
+ flush_end = flush_start + region_node->region.len;
+ dmac_flush_range(flush_start, flush_end);
+ break;
+ }
+ }
+end:
+ up_read(&data->sem);
+}
+
+static int pmem_connect(unsigned long connect, struct file *file)
+{
+ struct pmem_data *data = (struct pmem_data *)file->private_data;
+ struct pmem_data *src_data;
+ struct file *src_file;
+ int ret = 0, put_needed;
+
+ down_write(&data->sem);
+ /* retrieve the src file and check it is a pmem file with an alloc */
+ src_file = fget_light(connect, &put_needed);
+ DLOG("connect %p to %p\n", file, src_file);
+ if (!src_file) {
+ printk("pmem: src file not found!\n");
+ ret = -EINVAL;
+ goto err_no_file;
+ }
+ if (unlikely(!is_pmem_file(src_file) || !has_allocation(src_file))) {
+ printk(KERN_INFO "pmem: src file is not a pmem file or has no "
+ "alloc!\n");
+ ret = -EINVAL;
+ goto err_bad_file;
+ }
+ src_data = (struct pmem_data *)src_file->private_data;
+
+ if (has_allocation(file) && (data->index != src_data->index)) {
+ printk("pmem: file is already mapped but doesn't match this"
+ " src_file!\n");
+ ret = -EINVAL;
+ goto err_bad_file;
+ }
+ data->index = src_data->index;
+ data->flags |= PMEM_FLAGS_CONNECTED;
+ data->master_fd = connect;
+ data->master_file = src_file;
+
+err_bad_file:
+ fput_light(src_file, put_needed);
+err_no_file:
+ up_write(&data->sem);
+ return ret;
+}
+
+static void pmem_unlock_data_and_mm(struct pmem_data *data,
+ struct mm_struct *mm)
+{
+ up_write(&data->sem);
+ if (mm != NULL) {
+ up_write(&mm->mmap_sem);
+ mmput(mm);
+ }
+}
+
+static int pmem_lock_data_and_mm(struct file *file, struct pmem_data *data,
+ struct mm_struct **locked_mm)
+{
+ int ret = 0;
+ struct mm_struct *mm = NULL;
+ *locked_mm = NULL;
+lock_mm:
+ down_read(&data->sem);
+ if (PMEM_IS_SUBMAP(data)) {
+ mm = get_task_mm(data->task);
+ if (!mm) {
+#if PMEM_DEBUG
+ printk("pmem: can't remap task is gone!\n");
+#endif
+ up_read(&data->sem);
+ return -1;
+ }
+ }
+ up_read(&data->sem);
+
+ if (mm)
+ down_write(&mm->mmap_sem);
+
+ down_write(&data->sem);
+ /* check that the file didn't get mmaped before we could take the
+ * data sem, this should be safe b/c you can only submap each file
+ * once */
+ if (PMEM_IS_SUBMAP(data) && !mm) {
+ pmem_unlock_data_and_mm(data, mm);
+ up_write(&data->sem);
+ goto lock_mm;
+ }
+ /* now check that vma.mm is still there, it could have been
+ * deleted by vma_close before we could get the data->sem */
+ if ((data->flags & PMEM_FLAGS_UNSUBMAP) && (mm != NULL)) {
+ /* might as well release this */
+ if (data->flags & PMEM_FLAGS_SUBMAP) {
+ put_task_struct(data->task);
+ data->task = NULL;
+ /* lower the submap flag to show the mm is gone */
+ data->flags &= ~(PMEM_FLAGS_SUBMAP);
+ }
+ pmem_unlock_data_and_mm(data, mm);
+ return -1;
+ }
+ *locked_mm = mm;
+ return ret;
+}
+
+int pmem_remap(struct pmem_region *region, struct file *file,
+ unsigned operation)
+{
+ int ret;
+ struct pmem_region_node *region_node;
+ struct mm_struct *mm = NULL;
+ struct list_head *elt, *elt2;
+ int id = get_id(file);
+ struct pmem_data *data = (struct pmem_data *)file->private_data;
+
+ /* pmem region must be aligned on a page boundry */
+ if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) ||
+ !PMEM_IS_PAGE_ALIGNED(region->len))) {
+#if PMEM_DEBUG
+ printk("pmem: request for unaligned pmem suballocation "
+ "%lx %lx\n", region->offset, region->len);
+#endif
+ return -EINVAL;
+ }
+
+ /* if userspace requests a region of len 0, there's nothing to do */
+ if (region->len == 0)
+ return 0;
+
+ /* lock the mm and data */
+ ret = pmem_lock_data_and_mm(file, data, &mm);
+ if (ret)
+ return 0;
+
+ /* only the owner of the master file can remap the client fds
+ * that back in it */
+ if (!is_master_owner(file)) {
+#if PMEM_DEBUG
+ printk("pmem: remap requested from non-master process\n");
+#endif
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* check that the requested range is within the src allocation */
+ if (unlikely((region->offset > pmem_len(id, data)) ||
+ (region->len > pmem_len(id, data)) ||
+ (region->offset + region->len > pmem_len(id, data)))) {
+#if PMEM_DEBUG
+ printk(KERN_INFO "pmem: suballoc doesn't fit in src_file!\n");
+#endif
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (operation == PMEM_MAP) {
+ region_node = kmalloc(sizeof(struct pmem_region_node),
+ GFP_KERNEL);
+ if (!region_node) {
+ ret = -ENOMEM;
+#if PMEM_DEBUG
+ printk(KERN_INFO "No space to allocate metadata!");
+#endif
+ goto err;
+ }
+ region_node->region = *region;
+ list_add(&region_node->list, &data->region_list);
+ } else if (operation == PMEM_UNMAP) {
+ int found = 0;
+ list_for_each_safe(elt, elt2, &data->region_list) {
+ region_node = list_entry(elt, struct pmem_region_node,
+ list);
+ if (region->len == 0 ||
+ (region_node->region.offset == region->offset &&
+ region_node->region.len == region->len)) {
+ list_del(elt);
+ kfree(region_node);
+ found = 1;
+ }
+ }
+ if (!found) {
+#if PMEM_DEBUG
+ printk("pmem: Unmap region does not map any mapped "
+ "region!");
+#endif
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ if (data->vma && PMEM_IS_SUBMAP(data)) {
+ if (operation == PMEM_MAP)
+ ret = pmem_remap_pfn_range(id, data->vma, data,
+ region->offset, region->len);
+ else if (operation == PMEM_UNMAP)
+ ret = pmem_unmap_pfn_range(id, data->vma, data,
+ region->offset, region->len);
+ }
+
+err:
+ pmem_unlock_data_and_mm(data, mm);
+ return ret;
+}
+
+static void pmem_revoke(struct file *file, struct pmem_data *data)
+{
+ struct pmem_region_node *region_node;
+ struct list_head *elt, *elt2;
+ struct mm_struct *mm = NULL;
+ int id = get_id(file);
+ int ret = 0;
+
+ data->master_file = NULL;
+ ret = pmem_lock_data_and_mm(file, data, &mm);
+ /* if lock_data_and_mm fails either the task that mapped the fd, or
+ * the vma that mapped it have already gone away, nothing more
+ * needs to be done */
+ if (ret)
+ return;
+ /* unmap everything */
+ /* delete the regions and region list nothing is mapped any more */
+ if (data->vma)
+ list_for_each_safe(elt, elt2, &data->region_list) {
+ region_node = list_entry(elt, struct pmem_region_node,
+ list);
+ pmem_unmap_pfn_range(id, data->vma, data,
+ region_node->region.offset,
+ region_node->region.len);
+ list_del(elt);
+ kfree(region_node);
+ }
+ /* delete the master file */
+ pmem_unlock_data_and_mm(data, mm);
+}
+
+static void pmem_get_size(struct pmem_region *region, struct file *file)
+{
+ struct pmem_data *data = (struct pmem_data *)file->private_data;
+ int id = get_id(file);
+
+ if (!has_allocation(file)) {
+ region->offset = 0;
+ region->len = 0;
+ return;
+ } else {
+ region->offset = pmem_start_addr(id, data);
+ region->len = pmem_len(id, data);
+ }
+ DLOG("offset %lx len %lx\n", region->offset, region->len);
+}
+
+
+static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct pmem_data *data;
+ int id = get_id(file);
+
+ switch (cmd) {
+ case PMEM_GET_PHYS:
+ {
+ struct pmem_region region;
+ DLOG("get_phys\n");
+ if (!has_allocation(file)) {
+ region.offset = 0;
+ region.len = 0;
+ } else {
+ data = (struct pmem_data *)file->private_data;
+ region.offset = pmem_start_addr(id, data);
+ region.len = pmem_len(id, data);
+ }
+ printk(KERN_INFO "pmem: request for physical address of pmem region "
+ "from process %d.\n", current->pid);
+ if (copy_to_user((void __user *)arg, &region,
+ sizeof(struct pmem_region)))
+ return -EFAULT;
+ break;
+ }
+ case PMEM_MAP:
+ {
+ struct pmem_region region;
+ if (copy_from_user(&region, (void __user *)arg,
+ sizeof(struct pmem_region)))
+ return -EFAULT;
+ data = (struct pmem_data *)file->private_data;
+ return pmem_remap(&region, file, PMEM_MAP);
+ }
+ break;
+ case PMEM_UNMAP:
+ {
+ struct pmem_region region;
+ if (copy_from_user(&region, (void __user *)arg,
+ sizeof(struct pmem_region)))
+ return -EFAULT;
+ data = (struct pmem_data *)file->private_data;
+ return pmem_remap(&region, file, PMEM_UNMAP);
+ break;
+ }
+ case PMEM_GET_SIZE:
+ {
+ struct pmem_region region;
+ DLOG("get_size\n");
+ pmem_get_size(&region, file);
+ if (copy_to_user((void __user *)arg, &region,
+ sizeof(struct pmem_region)))
+ return -EFAULT;
+ break;
+ }
+ case PMEM_GET_TOTAL_SIZE:
+ {
+ struct pmem_region region;
+ DLOG("get total size\n");
+ region.offset = 0;
+ get_id(file);
+ region.len = pmem[id].size;
+ if (copy_to_user((void __user *)arg, &region,
+ sizeof(struct pmem_region)))
+ return -EFAULT;
+ break;
+ }
+ case PMEM_ALLOCATE:
+ {
+ if (has_allocation(file))
+ return -EINVAL;
+ data = (struct pmem_data *)file->private_data;
+ data->index = pmem_allocate(id, arg);
+ break;
+ }
+ case PMEM_CONNECT:
+ DLOG("connect\n");
+ return pmem_connect(arg, file);
+ break;
+ case PMEM_CACHE_FLUSH:
+ {
+ struct pmem_region region;
+ DLOG("flush\n");
+ if (copy_from_user(&region, (void __user *)arg,
+ sizeof(struct pmem_region)))
+ return -EFAULT;
+ flush_pmem_file(file, region.offset, region.len);
+ break;
+ }
+ default:
+ if (pmem[id].ioctl)
+ return pmem[id].ioctl(file, cmd, arg);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+#if PMEM_DEBUG
+static ssize_t debug_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct list_head *elt, *elt2;
+ struct pmem_data *data;
+ struct pmem_region_node *region_node;
+ int id = (int)file->private_data;
+ const int debug_bufmax = 4096;
+ static char buffer[4096];
+ int n = 0;
+
+ DLOG("debug open\n");
+ n = scnprintf(buffer, debug_bufmax,
+ "pid #: mapped regions (offset, len) (offset,len)...\n");
+
+ mutex_lock(&pmem[id].data_list_lock);
+ list_for_each(elt, &pmem[id].data_list) {
+ data = list_entry(elt, struct pmem_data, list);
+ down_read(&data->sem);
+ n += scnprintf(buffer + n, debug_bufmax - n, "pid %u:",
+ data->pid);
+ list_for_each(elt2, &data->region_list) {
+ region_node = list_entry(elt2, struct pmem_region_node,
+ list);
+ n += scnprintf(buffer + n, debug_bufmax - n,
+ "(%lx,%lx) ",
+ region_node->region.offset,
+ region_node->region.len);
+ }
+ n += scnprintf(buffer + n, debug_bufmax - n, "\n");
+ up_read(&data->sem);
+ }
+ mutex_unlock(&pmem[id].data_list_lock);
+
+ n++;
+ buffer[n] = 0;
+ return simple_read_from_buffer(buf, count, ppos, buffer, n);
+}
+
+static struct file_operations debug_fops = {
+ .read = debug_read,
+ .open = debug_open,
+};
+#endif
+
+#if 0
+static struct miscdevice pmem_dev = {
+ .name = "pmem",
+ .fops = &pmem_fops,
+};
+#endif
+
+int pmem_setup(struct android_pmem_platform_data *pdata,
+ long (*ioctl)(struct file *, unsigned int, unsigned long),
+ int (*release)(struct inode *, struct file *))
+{
+ int err = 0;
+ int i, index = 0;
+ int id = id_count;
+ id_count++;
+
+ pmem[id].no_allocator = pdata->no_allocator;
+ pmem[id].cached = pdata->cached;
+ pmem[id].buffered = pdata->buffered;
+ pmem[id].base = pdata->start;
+ pmem[id].size = pdata->size;
+ pmem[id].ioctl = ioctl;
+ pmem[id].release = release;
+ init_rwsem(&pmem[id].bitmap_sem);
+ mutex_init(&pmem[id].data_list_lock);
+ INIT_LIST_HEAD(&pmem[id].data_list);
+ pmem[id].dev.name = pdata->name;
+ pmem[id].dev.minor = id;
+ pmem[id].dev.fops = &pmem_fops;
+ printk(KERN_INFO "%s: %d init\n", pdata->name, pdata->cached);
+
+ err = misc_register(&pmem[id].dev);
+ if (err) {
+ printk(KERN_ALERT "Unable to register pmem driver!\n");
+ goto err_cant_register_device;
+ }
+ pmem[id].num_entries = pmem[id].size / PMEM_MIN_ALLOC;
+
+ pmem[id].bitmap = kmalloc(pmem[id].num_entries *
+ sizeof(struct pmem_bits), GFP_KERNEL);
+ if (!pmem[id].bitmap)
+ goto err_no_mem_for_metadata;
+
+ memset(pmem[id].bitmap, 0, sizeof(struct pmem_bits) *
+ pmem[id].num_entries);
+
+ for (i = sizeof(pmem[id].num_entries) * 8 - 1; i >= 0; i--) {
+ if ((pmem[id].num_entries) & 1<<i) {
+ PMEM_ORDER(id, index) = i;
+ index = PMEM_NEXT_INDEX(id, index);
+ }
+ }
+
+ if (pmem[id].cached)
+ pmem[id].vbase = ioremap_cached(pmem[id].base,
+ pmem[id].size);
+#ifdef ioremap_ext_buffered
+ else if (pmem[id].buffered)
+ pmem[id].vbase = ioremap_ext_buffered(pmem[id].base,
+ pmem[id].size);
+#endif
+ else
+ pmem[id].vbase = ioremap(pmem[id].base, pmem[id].size);
+
+ if (pmem[id].vbase == 0)
+ goto error_cant_remap;
+
+ pmem[id].garbage_pfn = page_to_pfn(alloc_page(GFP_KERNEL));
+ if (pmem[id].no_allocator)
+ pmem[id].allocated = 0;
+
+#if PMEM_DEBUG
+ debugfs_create_file(pdata->name, S_IFREG | S_IRUGO, NULL, (void *)id,
+ &debug_fops);
+#endif
+ return 0;
+error_cant_remap:
+ kfree(pmem[id].bitmap);
+err_no_mem_for_metadata:
+ misc_deregister(&pmem[id].dev);
+err_cant_register_device:
+ return -1;
+}
+
+static int pmem_probe(struct platform_device *pdev)
+{
+ struct android_pmem_platform_data *pdata;
+
+ if (!pdev || !pdev->dev.platform_data) {
+ printk(KERN_ALERT "Unable to probe pmem!\n");
+ return -1;
+ }
+ pdata = pdev->dev.platform_data;
+ return pmem_setup(pdata, NULL, NULL);
+}
+
+
+static int pmem_remove(struct platform_device *pdev)
+{
+ int id = pdev->id;
+ __free_page(pfn_to_page(pmem[id].garbage_pfn));
+ misc_deregister(&pmem[id].dev);
+ return 0;
+}
+
+static struct platform_driver pmem_driver = {
+ .probe = pmem_probe,
+ .remove = pmem_remove,
+ .driver = { .name = "android_pmem" }
+};
+
+
+static int __init pmem_init(void)
+{
+ return platform_driver_register(&pmem_driver);
+}
+
+static void __exit pmem_exit(void)
+{
+ platform_driver_unregister(&pmem_driver);
+}
+
+module_init(pmem_init);
+module_exit(pmem_exit);
+
diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c
new file mode 100644
index 000000000000..6d4d67924f22
--- /dev/null
+++ b/drivers/staging/android/ram_console.c
@@ -0,0 +1,443 @@
+/* drivers/android/ram_console.c
+ *
+ * Copyright (C) 2007-2008 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/console.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include "ram_console.h"
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+#include <linux/rslib.h>
+#endif
+
+struct ram_console_buffer {
+ uint32_t sig;
+ uint32_t start;
+ uint32_t size;
+ uint8_t data[0];
+};
+
+#define RAM_CONSOLE_SIG (0x43474244) /* DBGC */
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
+static char __initdata
+ ram_console_old_log_init_buffer[CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE];
+#endif
+static char *ram_console_old_log;
+static size_t ram_console_old_log_size;
+
+static struct ram_console_buffer *ram_console_buffer;
+static size_t ram_console_buffer_size;
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+static char *ram_console_par_buffer;
+static struct rs_control *ram_console_rs_decoder;
+static int ram_console_corrected_bytes;
+static int ram_console_bad_blocks;
+#define ECC_BLOCK_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE
+#define ECC_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE
+#define ECC_SYMSIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE
+#define ECC_POLY CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL
+#endif
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+static void ram_console_encode_rs8(uint8_t *data, size_t len, uint8_t *ecc)
+{
+ int i;
+ uint16_t par[ECC_SIZE];
+ /* Initialize the parity buffer */
+ memset(par, 0, sizeof(par));
+ encode_rs8(ram_console_rs_decoder, data, len, par, 0);
+ for (i = 0; i < ECC_SIZE; i++)
+ ecc[i] = par[i];
+}
+
+static int ram_console_decode_rs8(void *data, size_t len, uint8_t *ecc)
+{
+ int i;
+ uint16_t par[ECC_SIZE];
+ for (i = 0; i < ECC_SIZE; i++)
+ par[i] = ecc[i];
+ return decode_rs8(ram_console_rs_decoder, data, par, len,
+ NULL, 0, NULL, 0, NULL);
+}
+#endif
+
+static void ram_console_update(const char *s, unsigned int count)
+{
+ struct ram_console_buffer *buffer = ram_console_buffer;
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ uint8_t *buffer_end = buffer->data + ram_console_buffer_size;
+ uint8_t *block;
+ uint8_t *par;
+ int size = ECC_BLOCK_SIZE;
+#endif
+ memcpy(buffer->data + buffer->start, s, count);
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ block = buffer->data + (buffer->start & ~(ECC_BLOCK_SIZE - 1));
+ par = ram_console_par_buffer +
+ (buffer->start / ECC_BLOCK_SIZE) * ECC_SIZE;
+ do {
+ if (block + ECC_BLOCK_SIZE > buffer_end)
+ size = buffer_end - block;
+ ram_console_encode_rs8(block, size, par);
+ block += ECC_BLOCK_SIZE;
+ par += ECC_SIZE;
+ } while (block < buffer->data + buffer->start + count);
+#endif
+}
+
+static void ram_console_update_header(void)
+{
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ struct ram_console_buffer *buffer = ram_console_buffer;
+ uint8_t *par;
+ par = ram_console_par_buffer +
+ DIV_ROUND_UP(ram_console_buffer_size, ECC_BLOCK_SIZE) * ECC_SIZE;
+ ram_console_encode_rs8((uint8_t *)buffer, sizeof(*buffer), par);
+#endif
+}
+
+static void
+ram_console_write(struct console *console, const char *s, unsigned int count)
+{
+ int rem;
+ struct ram_console_buffer *buffer = ram_console_buffer;
+
+ if (count > ram_console_buffer_size) {
+ s += count - ram_console_buffer_size;
+ count = ram_console_buffer_size;
+ }
+ rem = ram_console_buffer_size - buffer->start;
+ if (rem < count) {
+ ram_console_update(s, rem);
+ s += rem;
+ count -= rem;
+ buffer->start = 0;
+ buffer->size = ram_console_buffer_size;
+ }
+ ram_console_update(s, count);
+
+ buffer->start += count;
+ if (buffer->size < ram_console_buffer_size)
+ buffer->size += count;
+ ram_console_update_header();
+}
+
+static struct console ram_console = {
+ .name = "ram",
+ .write = ram_console_write,
+ .flags = CON_PRINTBUFFER | CON_ENABLED,
+ .index = -1,
+};
+
+void ram_console_enable_console(int enabled)
+{
+ if (enabled)
+ ram_console.flags |= CON_ENABLED;
+ else
+ ram_console.flags &= ~CON_ENABLED;
+}
+
+static void __init
+ram_console_save_old(struct ram_console_buffer *buffer, const char *bootinfo,
+ char *dest)
+{
+ size_t old_log_size = buffer->size;
+ size_t bootinfo_size = 0;
+ size_t total_size = old_log_size;
+ char *ptr;
+ const char *bootinfo_label = "Boot info:\n";
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ uint8_t *block;
+ uint8_t *par;
+ char strbuf[80];
+ int strbuf_len = 0;
+
+ block = buffer->data;
+ par = ram_console_par_buffer;
+ while (block < buffer->data + buffer->size) {
+ int numerr;
+ int size = ECC_BLOCK_SIZE;
+ if (block + size > buffer->data + ram_console_buffer_size)
+ size = buffer->data + ram_console_buffer_size - block;
+ numerr = ram_console_decode_rs8(block, size, par);
+ if (numerr > 0) {
+#if 0
+ printk(KERN_INFO "ram_console: error in block %p, %d\n",
+ block, numerr);
+#endif
+ ram_console_corrected_bytes += numerr;
+ } else if (numerr < 0) {
+#if 0
+ printk(KERN_INFO "ram_console: uncorrectable error in "
+ "block %p\n", block);
+#endif
+ ram_console_bad_blocks++;
+ }
+ block += ECC_BLOCK_SIZE;
+ par += ECC_SIZE;
+ }
+ if (ram_console_corrected_bytes || ram_console_bad_blocks)
+ strbuf_len = snprintf(strbuf, sizeof(strbuf),
+ "\n%d Corrected bytes, %d unrecoverable blocks\n",
+ ram_console_corrected_bytes, ram_console_bad_blocks);
+ else
+ strbuf_len = snprintf(strbuf, sizeof(strbuf),
+ "\nNo errors detected\n");
+ if (strbuf_len >= sizeof(strbuf))
+ strbuf_len = sizeof(strbuf) - 1;
+ total_size += strbuf_len;
+#endif
+
+ if (bootinfo)
+ bootinfo_size = strlen(bootinfo) + strlen(bootinfo_label);
+ total_size += bootinfo_size;
+
+ if (dest == NULL) {
+ dest = kmalloc(total_size, GFP_KERNEL);
+ if (dest == NULL) {
+ printk(KERN_ERR
+ "ram_console: failed to allocate buffer\n");
+ return;
+ }
+ }
+
+ ram_console_old_log = dest;
+ ram_console_old_log_size = total_size;
+ memcpy(ram_console_old_log,
+ &buffer->data[buffer->start], buffer->size - buffer->start);
+ memcpy(ram_console_old_log + buffer->size - buffer->start,
+ &buffer->data[0], buffer->start);
+ ptr = ram_console_old_log + old_log_size;
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ memcpy(ptr, strbuf, strbuf_len);
+ ptr += strbuf_len;
+#endif
+ if (bootinfo) {
+ memcpy(ptr, bootinfo_label, strlen(bootinfo_label));
+ ptr += strlen(bootinfo_label);
+ memcpy(ptr, bootinfo, bootinfo_size);
+ ptr += bootinfo_size;
+ }
+}
+
+static int __init ram_console_init(struct ram_console_buffer *buffer,
+ size_t buffer_size, const char *bootinfo,
+ char *old_buf)
+{
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ int numerr;
+ uint8_t *par;
+#endif
+ ram_console_buffer = buffer;
+ ram_console_buffer_size =
+ buffer_size - sizeof(struct ram_console_buffer);
+
+ if (ram_console_buffer_size > buffer_size) {
+ pr_err("ram_console: buffer %p, invalid size %zu, "
+ "datasize %zu\n", buffer, buffer_size,
+ ram_console_buffer_size);
+ return 0;
+ }
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ ram_console_buffer_size -= (DIV_ROUND_UP(ram_console_buffer_size,
+ ECC_BLOCK_SIZE) + 1) * ECC_SIZE;
+
+ if (ram_console_buffer_size > buffer_size) {
+ pr_err("ram_console: buffer %p, invalid size %zu, "
+ "non-ecc datasize %zu\n",
+ buffer, buffer_size, ram_console_buffer_size);
+ return 0;
+ }
+
+ ram_console_par_buffer = buffer->data + ram_console_buffer_size;
+
+
+ /* first consecutive root is 0
+ * primitive element to generate roots = 1
+ */
+ ram_console_rs_decoder = init_rs(ECC_SYMSIZE, ECC_POLY, 0, 1, ECC_SIZE);
+ if (ram_console_rs_decoder == NULL) {
+ printk(KERN_INFO "ram_console: init_rs failed\n");
+ return 0;
+ }
+
+ ram_console_corrected_bytes = 0;
+ ram_console_bad_blocks = 0;
+
+ par = ram_console_par_buffer +
+ DIV_ROUND_UP(ram_console_buffer_size, ECC_BLOCK_SIZE) * ECC_SIZE;
+
+ numerr = ram_console_decode_rs8(buffer, sizeof(*buffer), par);
+ if (numerr > 0) {
+ printk(KERN_INFO "ram_console: error in header, %d\n", numerr);
+ ram_console_corrected_bytes += numerr;
+ } else if (numerr < 0) {
+ printk(KERN_INFO
+ "ram_console: uncorrectable error in header\n");
+ ram_console_bad_blocks++;
+ }
+#endif
+
+ if (buffer->sig == RAM_CONSOLE_SIG) {
+ if (buffer->size > ram_console_buffer_size
+ || buffer->start > buffer->size)
+ printk(KERN_INFO "ram_console: found existing invalid "
+ "buffer, size %d, start %d\n",
+ buffer->size, buffer->start);
+ else {
+ printk(KERN_INFO "ram_console: found existing buffer, "
+ "size %d, start %d\n",
+ buffer->size, buffer->start);
+ ram_console_save_old(buffer, bootinfo, old_buf);
+ }
+ } else {
+ printk(KERN_INFO "ram_console: no valid data in buffer "
+ "(sig = 0x%08x)\n", buffer->sig);
+ }
+
+ buffer->sig = RAM_CONSOLE_SIG;
+ buffer->start = 0;
+ buffer->size = 0;
+
+ register_console(&ram_console);
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE
+ console_verbose();
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
+static int __init ram_console_early_init(void)
+{
+ return ram_console_init((struct ram_console_buffer *)
+ CONFIG_ANDROID_RAM_CONSOLE_EARLY_ADDR,
+ CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE,
+ NULL,
+ ram_console_old_log_init_buffer);
+}
+#else
+static int ram_console_driver_probe(struct platform_device *pdev)
+{
+ struct resource *res = pdev->resource;
+ size_t start;
+ size_t buffer_size;
+ void *buffer;
+ const char *bootinfo = NULL;
+ struct ram_console_platform_data *pdata = pdev->dev.platform_data;
+
+ if (res == NULL || pdev->num_resources != 1 ||
+ !(res->flags & IORESOURCE_MEM)) {
+ printk(KERN_ERR "ram_console: invalid resource, %p %d flags "
+ "%lx\n", res, pdev->num_resources, res ? res->flags : 0);
+ return -ENXIO;
+ }
+ buffer_size = res->end - res->start + 1;
+ start = res->start;
+ printk(KERN_INFO "ram_console: got buffer at %zx, size %zx\n",
+ start, buffer_size);
+ buffer = ioremap(res->start, buffer_size);
+ if (buffer == NULL) {
+ printk(KERN_ERR "ram_console: failed to map memory\n");
+ return -ENOMEM;
+ }
+
+ if (pdata)
+ bootinfo = pdata->bootinfo;
+
+ return ram_console_init(buffer, buffer_size, bootinfo, NULL/* allocate */);
+}
+
+static struct platform_driver ram_console_driver = {
+ .probe = ram_console_driver_probe,
+ .driver = {
+ .name = "ram_console",
+ },
+};
+
+static int __init ram_console_module_init(void)
+{
+ int err;
+ err = platform_driver_register(&ram_console_driver);
+ return err;
+}
+#endif
+
+static ssize_t ram_console_read_old(struct file *file, char __user *buf,
+ size_t len, loff_t *offset)
+{
+ loff_t pos = *offset;
+ ssize_t count;
+
+ if (pos >= ram_console_old_log_size)
+ return 0;
+
+ count = min(len, (size_t)(ram_console_old_log_size - pos));
+ if (copy_to_user(buf, ram_console_old_log + pos, count))
+ return -EFAULT;
+
+ *offset += count;
+ return count;
+}
+
+static const struct file_operations ram_console_file_ops = {
+ .owner = THIS_MODULE,
+ .read = ram_console_read_old,
+};
+
+static int __init ram_console_late_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ if (ram_console_old_log == NULL)
+ return 0;
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
+ ram_console_old_log = kmalloc(ram_console_old_log_size, GFP_KERNEL);
+ if (ram_console_old_log == NULL) {
+ printk(KERN_ERR
+ "ram_console: failed to allocate buffer for old log\n");
+ ram_console_old_log_size = 0;
+ return 0;
+ }
+ memcpy(ram_console_old_log,
+ ram_console_old_log_init_buffer, ram_console_old_log_size);
+#endif
+ entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL);
+ if (!entry) {
+ printk(KERN_ERR "ram_console: failed to create proc entry\n");
+ kfree(ram_console_old_log);
+ ram_console_old_log = NULL;
+ return 0;
+ }
+
+ entry->proc_fops = &ram_console_file_ops;
+ entry->size = ram_console_old_log_size;
+ return 0;
+}
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
+console_initcall(ram_console_early_init);
+#else
+postcore_initcall(ram_console_module_init);
+#endif
+late_initcall(ram_console_late_init);
+
diff --git a/drivers/staging/android/ram_console.h b/drivers/staging/android/ram_console.h
new file mode 100644
index 000000000000..9f1125c11066
--- /dev/null
+++ b/drivers/staging/android/ram_console.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_
+#define _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_
+
+struct ram_console_platform_data {
+ const char *bootinfo;
+};
+
+#endif /* _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_ */
diff --git a/drivers/staging/android/switch/Kconfig b/drivers/staging/android/switch/Kconfig
new file mode 100644
index 000000000000..36846f62f4bc
--- /dev/null
+++ b/drivers/staging/android/switch/Kconfig
@@ -0,0 +1,11 @@
+menuconfig ANDROID_SWITCH
+ tristate "Android Switch class support"
+ help
+ Say Y here to enable Android switch class support. This allows
+ monitoring switches by userspace via sysfs and uevent.
+
+config ANDROID_SWITCH_GPIO
+ tristate "Android GPIO Switch support"
+ depends on GENERIC_GPIO && ANDROID_SWITCH
+ help
+ Say Y here to enable GPIO based switch support.
diff --git a/drivers/staging/android/switch/Makefile b/drivers/staging/android/switch/Makefile
new file mode 100644
index 000000000000..d76bfdcedfaf
--- /dev/null
+++ b/drivers/staging/android/switch/Makefile
@@ -0,0 +1,4 @@
+# Android Switch Class Driver
+obj-$(CONFIG_ANDROID_SWITCH) += switch_class.o
+obj-$(CONFIG_ANDROID_SWITCH_GPIO) += switch_gpio.o
+
diff --git a/drivers/staging/android/switch/switch.h b/drivers/staging/android/switch/switch.h
new file mode 100644
index 000000000000..4fcb3109875a
--- /dev/null
+++ b/drivers/staging/android/switch/switch.h
@@ -0,0 +1,53 @@
+/*
+ * Switch class driver
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.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.
+ *
+*/
+
+#ifndef __LINUX_SWITCH_H__
+#define __LINUX_SWITCH_H__
+
+struct switch_dev {
+ const char *name;
+ struct device *dev;
+ int index;
+ int state;
+
+ ssize_t (*print_name)(struct switch_dev *sdev, char *buf);
+ ssize_t (*print_state)(struct switch_dev *sdev, char *buf);
+};
+
+struct gpio_switch_platform_data {
+ const char *name;
+ unsigned gpio;
+
+ /* if NULL, switch_dev.name will be printed */
+ const char *name_on;
+ const char *name_off;
+ /* if NULL, "0" or "1" will be printed */
+ const char *state_on;
+ const char *state_off;
+};
+
+extern int switch_dev_register(struct switch_dev *sdev);
+extern void switch_dev_unregister(struct switch_dev *sdev);
+
+static inline int switch_get_state(struct switch_dev *sdev)
+{
+ return sdev->state;
+}
+
+extern void switch_set_state(struct switch_dev *sdev, int state);
+
+#endif /* __LINUX_SWITCH_H__ */
diff --git a/drivers/staging/android/switch/switch_class.c b/drivers/staging/android/switch/switch_class.c
new file mode 100644
index 000000000000..74680446fc66
--- /dev/null
+++ b/drivers/staging/android/switch/switch_class.c
@@ -0,0 +1,174 @@
+/*
+ * switch_class.c
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.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/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include "switch.h"
+
+struct class *switch_class;
+static atomic_t device_count;
+
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct switch_dev *sdev = (struct switch_dev *)
+ dev_get_drvdata(dev);
+
+ if (sdev->print_state) {
+ int ret = sdev->print_state(sdev, buf);
+ if (ret >= 0)
+ return ret;
+ }
+ return sprintf(buf, "%d\n", sdev->state);
+}
+
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct switch_dev *sdev = (struct switch_dev *)
+ dev_get_drvdata(dev);
+
+ if (sdev->print_name) {
+ int ret = sdev->print_name(sdev, buf);
+ if (ret >= 0)
+ return ret;
+ }
+ return sprintf(buf, "%s\n", sdev->name);
+}
+
+static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, state_show, NULL);
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, name_show, NULL);
+
+void switch_set_state(struct switch_dev *sdev, int state)
+{
+ char name_buf[120];
+ char state_buf[120];
+ char *prop_buf;
+ char *envp[3];
+ int env_offset = 0;
+ int length;
+
+ if (sdev->state != state) {
+ sdev->state = state;
+
+ prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
+ if (prop_buf) {
+ length = name_show(sdev->dev, NULL, prop_buf);
+ if (length > 0) {
+ if (prop_buf[length - 1] == '\n')
+ prop_buf[length - 1] = 0;
+ snprintf(name_buf, sizeof(name_buf),
+ "SWITCH_NAME=%s", prop_buf);
+ envp[env_offset++] = name_buf;
+ }
+ length = state_show(sdev->dev, NULL, prop_buf);
+ if (length > 0) {
+ if (prop_buf[length - 1] == '\n')
+ prop_buf[length - 1] = 0;
+ snprintf(state_buf, sizeof(state_buf),
+ "SWITCH_STATE=%s", prop_buf);
+ envp[env_offset++] = state_buf;
+ }
+ envp[env_offset] = NULL;
+ kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp);
+ free_page((unsigned long)prop_buf);
+ } else {
+ printk(KERN_ERR "out of memory in switch_set_state\n");
+ kobject_uevent(&sdev->dev->kobj, KOBJ_CHANGE);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(switch_set_state);
+
+static int create_switch_class(void)
+{
+ if (!switch_class) {
+ switch_class = class_create(THIS_MODULE, "switch");
+ if (IS_ERR(switch_class))
+ return PTR_ERR(switch_class);
+ atomic_set(&device_count, 0);
+ }
+
+ return 0;
+}
+
+int switch_dev_register(struct switch_dev *sdev)
+{
+ int ret;
+
+ if (!switch_class) {
+ ret = create_switch_class();
+ if (ret < 0)
+ return ret;
+ }
+
+ sdev->index = atomic_inc_return(&device_count);
+ sdev->dev = device_create(switch_class, NULL,
+ MKDEV(0, sdev->index), NULL, sdev->name);
+ if (IS_ERR(sdev->dev))
+ return PTR_ERR(sdev->dev);
+
+ ret = device_create_file(sdev->dev, &dev_attr_state);
+ if (ret < 0)
+ goto err_create_file_1;
+ ret = device_create_file(sdev->dev, &dev_attr_name);
+ if (ret < 0)
+ goto err_create_file_2;
+
+ dev_set_drvdata(sdev->dev, sdev);
+ sdev->state = 0;
+ return 0;
+
+err_create_file_2:
+ device_remove_file(sdev->dev, &dev_attr_state);
+err_create_file_1:
+ device_destroy(switch_class, MKDEV(0, sdev->index));
+ printk(KERN_ERR "switch: Failed to register driver %s\n", sdev->name);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(switch_dev_register);
+
+void switch_dev_unregister(struct switch_dev *sdev)
+{
+ device_remove_file(sdev->dev, &dev_attr_name);
+ device_remove_file(sdev->dev, &dev_attr_state);
+ device_destroy(switch_class, MKDEV(0, sdev->index));
+ dev_set_drvdata(sdev->dev, NULL);
+}
+EXPORT_SYMBOL_GPL(switch_dev_unregister);
+
+static int __init switch_class_init(void)
+{
+ return create_switch_class();
+}
+
+static void __exit switch_class_exit(void)
+{
+ class_destroy(switch_class);
+}
+
+module_init(switch_class_init);
+module_exit(switch_class_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_DESCRIPTION("Switch class driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/android/switch/switch_gpio.c b/drivers/staging/android/switch/switch_gpio.c
new file mode 100644
index 000000000000..38b2c2f6004e
--- /dev/null
+++ b/drivers/staging/android/switch/switch_gpio.c
@@ -0,0 +1,172 @@
+/*
+ * switch_gpio.c
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include "switch.h"
+
+struct gpio_switch_data {
+ struct switch_dev sdev;
+ unsigned gpio;
+ const char *name_on;
+ const char *name_off;
+ const char *state_on;
+ const char *state_off;
+ int irq;
+ struct work_struct work;
+};
+
+static void gpio_switch_work(struct work_struct *work)
+{
+ int state;
+ struct gpio_switch_data *data =
+ container_of(work, struct gpio_switch_data, work);
+
+ state = gpio_get_value(data->gpio);
+ switch_set_state(&data->sdev, state);
+}
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+ struct gpio_switch_data *switch_data =
+ (struct gpio_switch_data *)dev_id;
+
+ schedule_work(&switch_data->work);
+ return IRQ_HANDLED;
+}
+
+static ssize_t switch_gpio_print_state(struct switch_dev *sdev, char *buf)
+{
+ struct gpio_switch_data *switch_data =
+ container_of(sdev, struct gpio_switch_data, sdev);
+ const char *state;
+ if (switch_get_state(sdev))
+ state = switch_data->state_on;
+ else
+ state = switch_data->state_off;
+
+ if (state)
+ return sprintf(buf, "%s\n", state);
+ return -1;
+}
+
+static int gpio_switch_probe(struct platform_device *pdev)
+{
+ struct gpio_switch_platform_data *pdata = pdev->dev.platform_data;
+ struct gpio_switch_data *switch_data;
+ int ret = 0;
+
+ if (!pdata)
+ return -EBUSY;
+
+ switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL);
+ if (!switch_data)
+ return -ENOMEM;
+
+ switch_data->sdev.name = pdata->name;
+ switch_data->gpio = pdata->gpio;
+ switch_data->name_on = pdata->name_on;
+ switch_data->name_off = pdata->name_off;
+ switch_data->state_on = pdata->state_on;
+ switch_data->state_off = pdata->state_off;
+ switch_data->sdev.print_state = switch_gpio_print_state;
+
+ ret = switch_dev_register(&switch_data->sdev);
+ if (ret < 0)
+ goto err_switch_dev_register;
+
+ ret = gpio_request(switch_data->gpio, pdev->name);
+ if (ret < 0)
+ goto err_request_gpio;
+
+ ret = gpio_direction_input(switch_data->gpio);
+ if (ret < 0)
+ goto err_set_gpio_input;
+
+ INIT_WORK(&switch_data->work, gpio_switch_work);
+
+ switch_data->irq = gpio_to_irq(switch_data->gpio);
+ if (switch_data->irq < 0) {
+ ret = switch_data->irq;
+ goto err_detect_irq_num_failed;
+ }
+
+ ret = request_irq(switch_data->irq, gpio_irq_handler,
+ IRQF_TRIGGER_LOW, pdev->name, switch_data);
+ if (ret < 0)
+ goto err_request_irq;
+
+ /* Perform initial detection */
+ gpio_switch_work(&switch_data->work);
+
+ return 0;
+
+err_request_irq:
+err_detect_irq_num_failed:
+err_set_gpio_input:
+ gpio_free(switch_data->gpio);
+err_request_gpio:
+ switch_dev_unregister(&switch_data->sdev);
+err_switch_dev_register:
+ kfree(switch_data);
+
+ return ret;
+}
+
+static int __devexit gpio_switch_remove(struct platform_device *pdev)
+{
+ struct gpio_switch_data *switch_data = platform_get_drvdata(pdev);
+
+ cancel_work_sync(&switch_data->work);
+ gpio_free(switch_data->gpio);
+ switch_dev_unregister(&switch_data->sdev);
+ kfree(switch_data);
+
+ return 0;
+}
+
+static struct platform_driver gpio_switch_driver = {
+ .probe = gpio_switch_probe,
+ .remove = __devexit_p(gpio_switch_remove),
+ .driver = {
+ .name = "switch-gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init gpio_switch_init(void)
+{
+ return platform_driver_register(&gpio_switch_driver);
+}
+
+static void __exit gpio_switch_exit(void)
+{
+ platform_driver_unregister(&gpio_switch_driver);
+}
+
+module_init(gpio_switch_init);
+module_exit(gpio_switch_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_DESCRIPTION("GPIO Switch driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c
new file mode 100644
index 000000000000..a64481c3e86d
--- /dev/null
+++ b/drivers/staging/android/timed_gpio.c
@@ -0,0 +1,176 @@
+/* drivers/misc/timed_gpio.c
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.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/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/hrtimer.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+
+#include "timed_output.h"
+#include "timed_gpio.h"
+
+
+struct timed_gpio_data {
+ struct timed_output_dev dev;
+ struct hrtimer timer;
+ spinlock_t lock;
+ unsigned gpio;
+ int max_timeout;
+ u8 active_low;
+};
+
+static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)
+{
+ struct timed_gpio_data *data =
+ container_of(timer, struct timed_gpio_data, timer);
+
+ gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
+ return HRTIMER_NORESTART;
+}
+
+static int gpio_get_time(struct timed_output_dev *dev)
+{
+ struct timed_gpio_data *data =
+ container_of(dev, struct timed_gpio_data, dev);
+
+ if (hrtimer_active(&data->timer)) {
+ ktime_t r = hrtimer_get_remaining(&data->timer);
+ struct timeval t = ktime_to_timeval(r);
+ return t.tv_sec * 1000 + t.tv_usec / 1000;
+ } else
+ return 0;
+}
+
+static void gpio_enable(struct timed_output_dev *dev, int value)
+{
+ struct timed_gpio_data *data =
+ container_of(dev, struct timed_gpio_data, dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&data->lock, flags);
+
+ /* cancel previous timer and set GPIO according to value */
+ hrtimer_cancel(&data->timer);
+ gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
+
+ if (value > 0) {
+ if (value > data->max_timeout)
+ value = data->max_timeout;
+
+ hrtimer_start(&data->timer,
+ ktime_set(value / 1000, (value % 1000) * 1000000),
+ HRTIMER_MODE_REL);
+ }
+
+ spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static int timed_gpio_probe(struct platform_device *pdev)
+{
+ struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct timed_gpio *cur_gpio;
+ struct timed_gpio_data *gpio_data, *gpio_dat;
+ int i, j, ret = 0;
+
+ if (!pdata)
+ return -EBUSY;
+
+ gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios,
+ GFP_KERNEL);
+ if (!gpio_data)
+ return -ENOMEM;
+
+ for (i = 0; i < pdata->num_gpios; i++) {
+ cur_gpio = &pdata->gpios[i];
+ gpio_dat = &gpio_data[i];
+
+ hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ gpio_dat->timer.function = gpio_timer_func;
+ spin_lock_init(&gpio_dat->lock);
+
+ gpio_dat->dev.name = cur_gpio->name;
+ gpio_dat->dev.get_time = gpio_get_time;
+ gpio_dat->dev.enable = gpio_enable;
+ ret = gpio_request(cur_gpio->gpio, cur_gpio->name);
+ if (ret >= 0) {
+ ret = timed_output_dev_register(&gpio_dat->dev);
+ if (ret < 0)
+ gpio_free(cur_gpio->gpio);
+ }
+ if (ret < 0) {
+ for (j = 0; j < i; j++) {
+ timed_output_dev_unregister(&gpio_data[i].dev);
+ gpio_free(gpio_data[i].gpio);
+ }
+ kfree(gpio_data);
+ return ret;
+ }
+
+ gpio_dat->gpio = cur_gpio->gpio;
+ gpio_dat->max_timeout = cur_gpio->max_timeout;
+ gpio_dat->active_low = cur_gpio->active_low;
+ gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);
+ }
+
+ platform_set_drvdata(pdev, gpio_data);
+
+ return 0;
+}
+
+static int timed_gpio_remove(struct platform_device *pdev)
+{
+ struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < pdata->num_gpios; i++) {
+ timed_output_dev_unregister(&gpio_data[i].dev);
+ gpio_free(gpio_data[i].gpio);
+ }
+
+ kfree(gpio_data);
+
+ return 0;
+}
+
+static struct platform_driver timed_gpio_driver = {
+ .probe = timed_gpio_probe,
+ .remove = timed_gpio_remove,
+ .driver = {
+ .name = TIMED_GPIO_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init timed_gpio_init(void)
+{
+ return platform_driver_register(&timed_gpio_driver);
+}
+
+static void __exit timed_gpio_exit(void)
+{
+ platform_driver_unregister(&timed_gpio_driver);
+}
+
+module_init(timed_gpio_init);
+module_exit(timed_gpio_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_DESCRIPTION("timed gpio driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/android/timed_gpio.h b/drivers/staging/android/timed_gpio.h
new file mode 100644
index 000000000000..a0e15f8be3f7
--- /dev/null
+++ b/drivers/staging/android/timed_gpio.h
@@ -0,0 +1,33 @@
+/* include/linux/timed_gpio.h
+ *
+ * Copyright (C) 2008 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_TIMED_GPIO_H
+#define _LINUX_TIMED_GPIO_H
+
+#define TIMED_GPIO_NAME "timed-gpio"
+
+struct timed_gpio {
+ const char *name;
+ unsigned gpio;
+ int max_timeout;
+ u8 active_low;
+};
+
+struct timed_gpio_platform_data {
+ int num_gpios;
+ struct timed_gpio *gpios;
+};
+
+#endif
diff --git a/drivers/staging/android/timed_output.c b/drivers/staging/android/timed_output.c
new file mode 100644
index 000000000000..f373422308e0
--- /dev/null
+++ b/drivers/staging/android/timed_output.c
@@ -0,0 +1,123 @@
+/* drivers/misc/timed_output.c
+ *
+ * Copyright (C) 2009 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.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/module.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+
+#include "timed_output.h"
+
+static struct class *timed_output_class;
+static atomic_t device_count;
+
+static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct timed_output_dev *tdev = dev_get_drvdata(dev);
+ int remaining = tdev->get_time(tdev);
+
+ return sprintf(buf, "%d\n", remaining);
+}
+
+static ssize_t enable_store(
+ struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct timed_output_dev *tdev = dev_get_drvdata(dev);
+ int value;
+
+ if (sscanf(buf, "%d", &value) != 1)
+ return -EINVAL;
+
+ tdev->enable(tdev, value);
+
+ return size;
+}
+
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
+
+static int create_timed_output_class(void)
+{
+ if (!timed_output_class) {
+ timed_output_class = class_create(THIS_MODULE, "timed_output");
+ if (IS_ERR(timed_output_class))
+ return PTR_ERR(timed_output_class);
+ atomic_set(&device_count, 0);
+ }
+
+ return 0;
+}
+
+int timed_output_dev_register(struct timed_output_dev *tdev)
+{
+ int ret;
+
+ if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time)
+ return -EINVAL;
+
+ ret = create_timed_output_class();
+ if (ret < 0)
+ return ret;
+
+ tdev->index = atomic_inc_return(&device_count);
+ tdev->dev = device_create(timed_output_class, NULL,
+ MKDEV(0, tdev->index), NULL, tdev->name);
+ if (IS_ERR(tdev->dev))
+ return PTR_ERR(tdev->dev);
+
+ ret = device_create_file(tdev->dev, &dev_attr_enable);
+ if (ret < 0)
+ goto err_create_file;
+
+ dev_set_drvdata(tdev->dev, tdev);
+ tdev->state = 0;
+ return 0;
+
+err_create_file:
+ device_destroy(timed_output_class, MKDEV(0, tdev->index));
+ printk(KERN_ERR "timed_output: Failed to register driver %s\n",
+ tdev->name);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(timed_output_dev_register);
+
+void timed_output_dev_unregister(struct timed_output_dev *tdev)
+{
+ device_remove_file(tdev->dev, &dev_attr_enable);
+ device_destroy(timed_output_class, MKDEV(0, tdev->index));
+ dev_set_drvdata(tdev->dev, NULL);
+}
+EXPORT_SYMBOL_GPL(timed_output_dev_unregister);
+
+static int __init timed_output_init(void)
+{
+ return create_timed_output_class();
+}
+
+static void __exit timed_output_exit(void)
+{
+ class_destroy(timed_output_class);
+}
+
+module_init(timed_output_init);
+module_exit(timed_output_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_DESCRIPTION("timed output class driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/android/timed_output.h b/drivers/staging/android/timed_output.h
new file mode 100644
index 000000000000..ec907ab2ff54
--- /dev/null
+++ b/drivers/staging/android/timed_output.h
@@ -0,0 +1,37 @@
+/* include/linux/timed_output.h
+ *
+ * Copyright (C) 2008 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_TIMED_OUTPUT_H
+#define _LINUX_TIMED_OUTPUT_H
+
+struct timed_output_dev {
+ const char *name;
+
+ /* enable the output and set the timer */
+ void (*enable)(struct timed_output_dev *sdev, int timeout);
+
+ /* returns the current number of milliseconds remaining on the timer */
+ int (*get_time)(struct timed_output_dev *sdev);
+
+ /* private data */
+ struct device *dev;
+ int index;
+ int state;
+};
+
+extern int timed_output_dev_register(struct timed_output_dev *dev);
+extern void timed_output_dev_unregister(struct timed_output_dev *dev);
+
+#endif
diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c
index 7bb7da7959a2..e77e4e0396cf 100644
--- a/drivers/staging/asus_oled/asus_oled.c
+++ b/drivers/staging/asus_oled/asus_oled.c
@@ -201,7 +201,7 @@ static ssize_t set_enabled(struct device *dev, struct device_attribute *attr,
struct usb_interface *intf = to_usb_interface(dev);
struct asus_oled_dev *odev = usb_get_intfdata(intf);
unsigned long value;
- if (strict_strtoul(buf, 10, &value))
+ if (kstrtoul(buf, 10, &value))
return -EINVAL;
enable_oled(odev, value);
@@ -217,7 +217,7 @@ static ssize_t class_set_enabled(struct device *device,
(struct asus_oled_dev *) dev_get_drvdata(device);
unsigned long value;
- if (strict_strtoul(buf, 10, &value))
+ if (kstrtoul(buf, 10, &value))
return -EINVAL;
enable_oled(odev, value);
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index 2fa658eb74dc..179707b5e7c7 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -161,6 +161,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
INT Status = STATUS_FAILURE;
int timeout = 0;
IOCTL_BUFFER IoBuffer;
+ int bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg);
@@ -230,11 +231,16 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
if (!temp_buff)
return -ENOMEM;
- Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
+ bytes = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
(PUINT)temp_buff, Bufflen);
- if (Status == STATUS_SUCCESS) {
- if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
- Status = -EFAULT;
+ if (bytes > 0) {
+ Status = STATUS_SUCCESS;
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) {
+ kfree(temp_buff);
+ return -EFAULT;
+ }
+ } else {
+ Status = bytes;
}
kfree(temp_buff);
@@ -302,7 +308,11 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
return -EFAULT;
- /* FIXME: don't trust user supplied length */
+ if (IoBuffer.OutputLength > USHRT_MAX ||
+ IoBuffer.OutputLength == 0) {
+ return -EINVAL;
+ }
+
temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
if (!temp_buff)
return STATUS_FAILURE;
@@ -318,11 +328,17 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
}
uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
- Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength);
+ bytes = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength);
- if (Status == STATUS_SUCCESS)
- if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
- Status = -EFAULT;
+ if (bytes > 0) {
+ Status = STATUS_SUCCESS;
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) {
+ kfree(temp_buff);
+ return -EFAULT;
+ }
+ } else {
+ Status = bytes;
+ }
kfree(temp_buff);
break;
@@ -437,12 +453,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
}
}
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
-
- if (STATUS_SUCCESS != Status) {
+ bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+ if (bytes < 0) {
+ Status = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
"GPIO_MODE_REGISTER read failed");
break;
+ } else {
+ Status = STATUS_SUCCESS;
}
/* Set the gpio mode register to output */
@@ -519,12 +537,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
uiBit = gpio_info.uiGpioNumber;
/* Set the gpio output register */
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
+ bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
(PUINT)ucRead, sizeof(UINT));
- if (Status != STATUS_SUCCESS) {
+ if (bytes < 0) {
+ Status = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n");
return Status;
+ } else {
+ Status = STATUS_SUCCESS;
}
}
break;
@@ -590,11 +611,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
}
if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+ bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
- if (Status != STATUS_SUCCESS) {
+ if (bytes < 0) {
+ Status = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM to GPIO_PIN_STATE_REGISTER Failed.");
return Status;
+ } else {
+ Status = STATUS_SUCCESS;
}
pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue &
@@ -605,7 +629,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
"Failed while copying Content to IOBufer for user space err:%d", Status);
- break;
+ return -EFAULT;
}
}
break;
@@ -629,11 +653,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength))
return -EFAULT;
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+ bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
- if (STATUS_SUCCESS != Status) {
+ if (bytes < 0) {
+ Status = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed");
return Status;
+ } else {
+ Status = STATUS_SUCCESS;
}
/* Validating the request */
@@ -678,7 +705,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
"Failed while copying Content to IOBufer for user space err:%d", Status);
- break;
+ return -EFAULT;
}
}
break;
@@ -706,9 +733,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
return -ENOMEM;
if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
- Status = -EFAULT;
kfree(pvBuffer);
- break;
+ return -EFAULT;
}
down(&Adapter->LowPowerModeSync);
@@ -733,8 +759,7 @@ cntrlEnd:
}
case IOCTL_BCM_BUFFER_DOWNLOAD_START: {
- INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
- if (NVMAccess) {
+ if (down_trylock(&Adapter->NVMRdmWrmLock)) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
"IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
return -EACCES;
@@ -743,157 +768,162 @@ cntrlEnd:
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
"Starting the firmware download PID =0x%x!!!!\n", current->pid);
- if (!down_trylock(&Adapter->fw_download_sema)) {
- Adapter->bBinDownloaded = FALSE;
- Adapter->fw_download_process_pid = current->pid;
- Adapter->bCfgDownloaded = FALSE;
- Adapter->fw_download_done = FALSE;
- netif_carrier_off(Adapter->dev);
- netif_stop_queue(Adapter->dev);
- Status = reset_card_proc(Adapter);
- if (Status) {
- pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
- up(&Adapter->fw_download_sema);
- up(&Adapter->NVMRdmWrmLock);
- break;
- }
- mdelay(10);
- } else {
- Status = -EBUSY;
+ if (down_trylock(&Adapter->fw_download_sema))
+ return -EBUSY;
+
+ Adapter->bBinDownloaded = FALSE;
+ Adapter->fw_download_process_pid = current->pid;
+ Adapter->bCfgDownloaded = FALSE;
+ Adapter->fw_download_done = FALSE;
+ netif_carrier_off(Adapter->dev);
+ netif_stop_queue(Adapter->dev);
+ Status = reset_card_proc(Adapter);
+ if (Status) {
+ pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
}
+ mdelay(10);
up(&Adapter->NVMRdmWrmLock);
- break;
+ return Status;
}
case IOCTL_BCM_BUFFER_DOWNLOAD: {
FIRMWARE_INFO *psFwInfo = NULL;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
- do {
- if (!down_trylock(&Adapter->fw_download_sema)) {
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
- "Invalid way to download buffer. Use Start and then call this!!!\n");
- Status = -EINVAL;
- break;
- }
-
- /* Copy Ioctl Buffer structure */
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ if (!down_trylock(&Adapter->fw_download_sema)) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
- "Length for FW DLD is : %lx\n", IoBuffer.InputLength);
+ "Invalid way to download buffer. Use Start and then call this!!!\n");
+ up(&Adapter->fw_download_sema);
+ Status = -EINVAL;
+ return Status;
+ }
- if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO))
- return -EINVAL;
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+ up(&Adapter->fw_download_sema);
+ return -EFAULT;
+ }
- psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
- if (!psFwInfo)
- return -ENOMEM;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Length for FW DLD is : %lx\n", IoBuffer.InputLength);
- if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) {
+ up(&Adapter->fw_download_sema);
+ return -EINVAL;
+ }
- if (!psFwInfo->pvMappedFirmwareAddress ||
- (psFwInfo->u32FirmwareLength == 0)) {
+ psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
+ if (!psFwInfo) {
+ up(&Adapter->fw_download_sema);
+ return -ENOMEM;
+ }
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
- psFwInfo->u32FirmwareLength);
- Status = -EINVAL;
- break;
- }
+ if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
+ up(&Adapter->fw_download_sema);
+ return -EFAULT;
+ }
- Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
+ if (!psFwInfo->pvMappedFirmwareAddress ||
+ (psFwInfo->u32FirmwareLength == 0)) {
- if (Status != STATUS_SUCCESS) {
- if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
- else
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
+ psFwInfo->u32FirmwareLength);
+ up(&Adapter->fw_download_sema);
+ Status = -EINVAL;
+ return Status;
+ }
- /* up(&Adapter->fw_download_sema); */
+ Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
- if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
- Adapter->DriverState = DRIVER_INIT;
- Adapter->LEDInfo.bLedInitDone = FALSE;
- wake_up(&Adapter->LEDInfo.notify_led_event);
- }
- }
- break;
+ if (Status != STATUS_SUCCESS) {
+ if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
+ else
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n");
+
+ /* up(&Adapter->fw_download_sema); */
- } while (0);
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = DRIVER_INIT;
+ Adapter->LEDInfo.bLedInitDone = FALSE;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+ }
if (Status != STATUS_SUCCESS)
up(&Adapter->fw_download_sema);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n");
kfree(psFwInfo);
- break;
+ return Status;
}
case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: {
- INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ if (!down_trylock(&Adapter->fw_download_sema)) {
+ up(&Adapter->fw_download_sema);
+ return -EINVAL;
+ }
- if (NVMAccess) {
+ if (down_trylock(&Adapter->NVMRdmWrmLock)) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
"FW download blocked as EEPROM Read/Write is in progress\n");
up(&Adapter->fw_download_sema);
return -EACCES;
}
- if (down_trylock(&Adapter->fw_download_sema)) {
- Adapter->bBinDownloaded = TRUE;
- Adapter->bCfgDownloaded = TRUE;
- atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
- Adapter->CurrNumRecvDescs = 0;
- Adapter->downloadDDR = 0;
-
- /* setting the Mips to Run */
- Status = run_card_proc(Adapter);
+ Adapter->bBinDownloaded = TRUE;
+ Adapter->bCfgDownloaded = TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->downloadDDR = 0;
- if (Status) {
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
- up(&Adapter->fw_download_sema);
- up(&Adapter->NVMRdmWrmLock);
- break;
- } else {
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
- DBG_LVL_ALL, "Firm Download Over...\n");
- }
-
- mdelay(10);
-
- /* Wait for MailBox Interrupt */
- if (StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter))
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
-
- timeout = 5*HZ;
- Adapter->waiting_to_fw_download_done = FALSE;
- wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
- Adapter->waiting_to_fw_download_done, timeout);
- Adapter->fw_download_process_pid = INVALID_PID;
- Adapter->fw_download_done = TRUE;
- atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
- Adapter->CurrNumRecvDescs = 0;
- Adapter->PrevNumRecvDescs = 0;
- atomic_set(&Adapter->cntrlpktCnt, 0);
- Adapter->LinkUpStatus = 0;
- Adapter->LinkStatus = 0;
+ /* setting the Mips to Run */
+ Status = run_card_proc(Adapter);
- if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
- Adapter->DriverState = FW_DOWNLOAD_DONE;
- wake_up(&Adapter->LEDInfo.notify_led_event);
- }
-
- if (!timeout)
- Status = -ENODEV;
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
} else {
- Status = -EINVAL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, "Firm Download Over...\n");
+ }
+
+ mdelay(10);
+
+ /* Wait for MailBox Interrupt */
+ if (StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter))
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
+
+ timeout = 5*HZ;
+ Adapter->waiting_to_fw_download_done = FALSE;
+ wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
+ Adapter->waiting_to_fw_download_done, timeout);
+ Adapter->fw_download_process_pid = INVALID_PID;
+ Adapter->fw_download_done = TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->PrevNumRecvDescs = 0;
+ atomic_set(&Adapter->cntrlpktCnt, 0);
+ Adapter->LinkUpStatus = 0;
+ Adapter->LinkStatus = 0;
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = FW_DOWNLOAD_DONE;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
}
+ if (!timeout)
+ Status = -ENODEV;
+
up(&Adapter->fw_download_sema);
up(&Adapter->NVMRdmWrmLock);
- break;
+ return Status;
}
case IOCTL_BE_BUCKET_SIZE:
@@ -969,11 +999,15 @@ cntrlEnd:
}
case IOCTL_BCM_GET_DRIVER_VERSION: {
+ ulong len;
+
/* Copy Ioctl Buffer structure */
if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
return -EFAULT;
- if (copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength))
+ len = min_t(ulong, IoBuffer.OutputLength, strlen(VER_FILEVERSION_STR) + 1);
+
+ if (copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, len))
return -EFAULT;
Status = STATUS_SUCCESS;
break;
@@ -985,8 +1019,7 @@ cntrlEnd:
/* Copy Ioctl Buffer structure */
if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
- Status = -EFAULT;
- break;
+ return -EFAULT;
}
if (IoBuffer.OutputLength != sizeof(link_state)) {
@@ -1001,8 +1034,7 @@ cntrlEnd:
if (copy_to_user(IoBuffer.OutputBuffer, &link_state, min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n");
- Status = -EFAULT;
- break;
+ return -EFAULT;
}
Status = STATUS_SUCCESS;
break;
@@ -1068,8 +1100,10 @@ cntrlEnd:
GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
if (Status != STATUS_FAILURE)
- if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS)))
- Status = -EFAULT;
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS))) {
+ kfree(temp_buff);
+ return -EFAULT;
+ }
kfree(temp_buff);
break;
@@ -1103,7 +1137,9 @@ cntrlEnd:
if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
return -EFAULT;
- /* FIXME: restrict length */
+ if (IoBuffer.InputLength < sizeof(ULONG) * 2)
+ return -EINVAL;
+
pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
if (!pvBuffer)
return -ENOMEM;
@@ -1111,8 +1147,7 @@ cntrlEnd:
/* Get WrmBuffer structure */
if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
kfree(pvBuffer);
- Status = -EFAULT;
- break;
+ return -EFAULT;
}
pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer;
@@ -1242,8 +1277,7 @@ cntrlEnd:
memset(&tv1, 0, sizeof(struct timeval));
if ((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
- Status = -EFAULT;
- break;
+ return -EFAULT;
}
if (IsFlash2x(Adapter)) {
@@ -1252,7 +1286,7 @@ cntrlEnd:
(Adapter->eActiveDSD != DSD2)) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No DSD is active..hence NVM Command is blocked");
- return STATUS_FAILURE ;
+ return STATUS_FAILURE;
}
}
@@ -1271,8 +1305,7 @@ cntrlEnd:
if ((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) {
/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); */
- Status = STATUS_FAILURE;
- break;
+ return STATUS_FAILURE;
}
pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL);
@@ -1280,9 +1313,8 @@ cntrlEnd:
return -ENOMEM;
if (copy_from_user(pReadData, stNVMReadWrite.pBuffer, stNVMReadWrite.uiNumBytes)) {
- Status = -EFAULT;
kfree(pReadData);
- break;
+ return -EFAULT;
}
do_gettimeofday(&tv0);
@@ -1309,7 +1341,7 @@ cntrlEnd:
if (copy_to_user(stNVMReadWrite.pBuffer, pReadData, stNVMReadWrite.uiNumBytes)) {
kfree(pReadData);
- Status = -EFAULT;
+ return -EFAULT;
}
} else {
down(&Adapter->NVMRdmWrmLock);
@@ -1377,9 +1409,8 @@ cntrlEnd:
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n", (tv1.tv_sec - tv0.tv_sec)*1000 + (tv1.tv_usec - tv0.tv_usec)/1000);
kfree(pReadData);
- Status = STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
- break;
case IOCTL_BCM_FLASH2X_SECTION_READ: {
FLASH2X_READWRITE sFlash2xRead = {0};
@@ -1456,7 +1487,9 @@ cntrlEnd:
Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy to use failed with status :%d", Status);
- break;
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ return -EFAULT;
}
NOB = NOB - ReadBytes;
if (NOB) {
@@ -1548,7 +1581,9 @@ cntrlEnd:
Status = copy_from_user(pWriteBuff, InputAddr, WriteBytes);
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to user failed with status :%d", Status);
- break;
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pWriteBuff);
+ return -EFAULT;
}
BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pWriteBuff, WriteBytes);
@@ -1608,8 +1643,10 @@ cntrlEnd:
BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
up(&Adapter->NVMRdmWrmLock);
- if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP)))
- Status = -EFAULT;
+ if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP))) {
+ kfree(psFlash2xBitMap);
+ return -EFAULT;
+ }
kfree(psFlash2xBitMap);
}
@@ -1627,13 +1664,13 @@ cntrlEnd:
Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
- return Status;
+ return -EFAULT;
}
Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
- return Status;
+ return -EFAULT;
}
down(&Adapter->NVMRdmWrmLock);
@@ -1677,13 +1714,13 @@ cntrlEnd:
Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
- return Status;
+ return -EFAULT;
}
Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION));
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
- return Status;
+ return -EFAULT;
}
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection);
@@ -1744,7 +1781,7 @@ cntrlEnd:
Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
- break;
+ return -EFAULT;
}
if (Adapter->eNVMType != NVM_FLASH) {
@@ -1783,12 +1820,12 @@ cntrlEnd:
Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
- return Status;
+ return -EFAULT;
}
Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
- return Status;
+ return -EFAULT;
}
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read Section :%d", eFlash2xSectionVal);
@@ -1830,8 +1867,7 @@ cntrlEnd:
/* Copy Ioctl Buffer structure */
if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
- Status = -EFAULT;
- break;
+ return -EFAULT;
}
if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(NVM_READWRITE)))
@@ -1886,7 +1922,9 @@ cntrlEnd:
Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to use failed with status :%d", Status);
- break;
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ return -EFAULT;
}
NOB = NOB - ReadBytes;
if (NOB) {
@@ -1907,8 +1945,7 @@ cntrlEnd:
Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space");
- Status = -EFAULT;
- break;
+ return -EFAULT;
}
if (IoBuffer.InputLength != sizeof(unsigned long)) {
@@ -1919,8 +1956,7 @@ cntrlEnd:
Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength);
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of control bit mask failed from user space");
- Status = -EFAULT;
- break;
+ return -EFAULT;
}
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask;
diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c
index 2b1e9e17e11c..b058e30b2ca6 100644
--- a/drivers/staging/bcm/HandleControlPacket.c
+++ b/drivers/staging/bcm/HandleControlPacket.c
@@ -1,195 +1,208 @@
/**
-@file HandleControlPacket.c
-This file contains the routines to deal with
-sending and receiving of control packets.
-*/
+ * @file HandleControlPacket.c
+ * This file contains the routines to deal with
+ * sending and receiving of control packets.
+ */
#include "headers.h"
/**
-When a control packet is received, analyze the
-"status" and call appropriate response function.
-Enqueue the control packet for Application.
-@return None
-*/
+ * When a control packet is received, analyze the
+ * "status" and call appropriate response function.
+ * Enqueue the control packet for Application.
+ * @return None
+ */
static VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, struct sk_buff *skb)
{
- PPER_TARANG_DATA pTarang = NULL;
+ PPER_TARANG_DATA pTarang = NULL;
BOOLEAN HighPriorityMessage = FALSE;
- struct sk_buff * newPacket = NULL;
+ struct sk_buff *newPacket = NULL;
CHAR cntrl_msg_mask_bit = 0;
- BOOLEAN drop_pkt_flag = TRUE ;
+ BOOLEAN drop_pkt_flag = TRUE;
USHORT usStatus = *(PUSHORT)(skb->data);
if (netif_msg_pktdata(Adapter))
print_hex_dump(KERN_DEBUG, PFX "rx control: ", DUMP_PREFIX_NONE,
- 16, 1, skb->data, skb->len, 0);
-
- switch(usStatus)
- {
- case CM_RESPONSES: // 0xA0
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "MAC Version Seems to be Non Multi-Classifier, rejected by Driver");
- HighPriorityMessage = TRUE ;
- break;
- case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
- HighPriorityMessage = TRUE ;
- if(Adapter->LinkStatus==LINKUP_DONE)
- {
- CmControlResponseMessage(Adapter,(skb->data +sizeof(USHORT)));
- }
- break;
- case LINK_CONTROL_RESP: //0xA2
- case STATUS_RSP: //0xA1
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"LINK_CONTROL_RESP");
- HighPriorityMessage = TRUE ;
- LinkControlResponseMessage(Adapter,(skb->data + sizeof(USHORT)));
- break;
- case STATS_POINTER_RESP: //0xA6
- HighPriorityMessage = TRUE ;
- StatisticsResponse(Adapter, (skb->data + sizeof(USHORT)));
- break;
- case IDLE_MODE_STATUS: //0xA3
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"IDLE_MODE_STATUS Type Message Got from F/W");
- InterfaceIdleModeRespond(Adapter, (PUINT)(skb->data +
- sizeof(USHORT)));
- HighPriorityMessage = TRUE ;
- break;
-
- case AUTH_SS_HOST_MSG:
- HighPriorityMessage = TRUE ;
- break;
-
- default:
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"Got Default Response");
- /* Let the Application Deal with This Packet */
- break;
+ 16, 1, skb->data, skb->len, 0);
+
+ switch (usStatus) {
+ case CM_RESPONSES: /* 0xA0 */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL,
+ "MAC Version Seems to be Non Multi-Classifier, rejected by Driver");
+ HighPriorityMessage = TRUE;
+ break;
+ case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
+ HighPriorityMessage = TRUE;
+ if (Adapter->LinkStatus == LINKUP_DONE)
+ CmControlResponseMessage(Adapter,
+ (skb->data + sizeof(USHORT)));
+ break;
+ case LINK_CONTROL_RESP: /* 0xA2 */
+ case STATUS_RSP: /* 0xA1 */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL, "LINK_CONTROL_RESP");
+ HighPriorityMessage = TRUE;
+ LinkControlResponseMessage(Adapter,
+ (skb->data + sizeof(USHORT)));
+ break;
+ case STATS_POINTER_RESP: /* 0xA6 */
+ HighPriorityMessage = TRUE;
+ StatisticsResponse(Adapter, (skb->data + sizeof(USHORT)));
+ break;
+ case IDLE_MODE_STATUS: /* 0xA3 */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL,
+ "IDLE_MODE_STATUS Type Message Got from F/W");
+ InterfaceIdleModeRespond(Adapter, (PUINT)(skb->data +
+ sizeof(USHORT)));
+ HighPriorityMessage = TRUE;
+ break;
+
+ case AUTH_SS_HOST_MSG:
+ HighPriorityMessage = TRUE;
+ break;
+
+ default:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL, "Got Default Response");
+ /* Let the Application Deal with This Packet */
+ break;
}
- //Queue The Control Packet to The Application Queues
+ /* Queue The Control Packet to The Application Queues */
down(&Adapter->RxAppControlQueuelock);
- for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next)
- {
- if(Adapter->device_removed)
- {
+ for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next) {
+ if (Adapter->device_removed)
break;
- }
- drop_pkt_flag = TRUE ;
+ drop_pkt_flag = TRUE;
/*
- There are cntrl msg from A0 to AC. It has been mapped to 0 to C bit in the cntrl mask.
- Also, by default AD to BF has been masked to the rest of the bits... which wil be ON by default.
- if mask bit is enable to particular pkt status, send it out to app else stop it.
- */
+ * There are cntrl msg from A0 to AC. It has been mapped to 0 to
+ * C bit in the cntrl mask.
+ * Also, by default AD to BF has been masked to the rest of the
+ * bits... which wil be ON by default.
+ * if mask bit is enable to particular pkt status, send it out
+ * to app else stop it.
+ */
cntrl_msg_mask_bit = (usStatus & 0x1F);
- //printk("\ninew msg mask bit which is disable in mask:%X", cntrl_msg_mask_bit);
- if(pTarang->RxCntrlMsgBitMask & (1<<cntrl_msg_mask_bit))
- drop_pkt_flag = FALSE;
-
- if ((drop_pkt_flag == TRUE) || (pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN) ||
- ((pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN/2) && (HighPriorityMessage == FALSE)))
- {
+ /*
+ * printk("\ninew msg mask bit which is disable in mask:%X",
+ * cntrl_msg_mask_bit);
+ */
+ if (pTarang->RxCntrlMsgBitMask & (1 << cntrl_msg_mask_bit))
+ drop_pkt_flag = FALSE;
+
+ if ((drop_pkt_flag == TRUE) ||
+ (pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN)
+ || ((pTarang->AppCtrlQueueLen >
+ MAX_APP_QUEUE_LEN / 2) &&
+ (HighPriorityMessage == FALSE))) {
/*
- Assumption:-
- 1. every tarang manages it own dropped pkt statitistics
- 2. Total packet dropped per tarang will be equal to the sum of all types of dropped
- pkt by that tarang only.
-
- */
- switch(*(PUSHORT)skb->data)
- {
- case CM_RESPONSES:
- pTarang->stDroppedAppCntrlMsgs.cm_responses++;
- break;
- case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
- pTarang->stDroppedAppCntrlMsgs.cm_control_newdsx_multiclassifier_resp++;
- break;
- case LINK_CONTROL_RESP:
- pTarang->stDroppedAppCntrlMsgs.link_control_resp++;
- break;
- case STATUS_RSP:
- pTarang->stDroppedAppCntrlMsgs.status_rsp++;
- break;
- case STATS_POINTER_RESP:
- pTarang->stDroppedAppCntrlMsgs.stats_pointer_resp++;
- break;
- case IDLE_MODE_STATUS:
- pTarang->stDroppedAppCntrlMsgs.idle_mode_status++ ;
- break;
- case AUTH_SS_HOST_MSG:
- pTarang->stDroppedAppCntrlMsgs.auth_ss_host_msg++ ;
- break;
+ * Assumption:-
+ * 1. every tarang manages it own dropped pkt
+ * statitistics
+ * 2. Total packet dropped per tarang will be equal to
+ * the sum of all types of dropped pkt by that
+ * tarang only.
+ */
+ switch (*(PUSHORT)skb->data) {
+ case CM_RESPONSES:
+ pTarang->stDroppedAppCntrlMsgs.cm_responses++;
+ break;
+ case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
+ pTarang->stDroppedAppCntrlMsgs.cm_control_newdsx_multiclassifier_resp++;
+ break;
+ case LINK_CONTROL_RESP:
+ pTarang->stDroppedAppCntrlMsgs.link_control_resp++;
+ break;
+ case STATUS_RSP:
+ pTarang->stDroppedAppCntrlMsgs.status_rsp++;
+ break;
+ case STATS_POINTER_RESP:
+ pTarang->stDroppedAppCntrlMsgs.stats_pointer_resp++;
+ break;
+ case IDLE_MODE_STATUS:
+ pTarang->stDroppedAppCntrlMsgs.idle_mode_status++;
+ break;
+ case AUTH_SS_HOST_MSG:
+ pTarang->stDroppedAppCntrlMsgs.auth_ss_host_msg++;
+ break;
default:
- pTarang->stDroppedAppCntrlMsgs.low_priority_message++ ;
- break;
+ pTarang->stDroppedAppCntrlMsgs.low_priority_message++;
+ break;
}
continue;
}
- newPacket = skb_clone(skb, GFP_KERNEL);
- if (!newPacket)
- break;
- ENQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail,
- newPacket);
- pTarang->AppCtrlQueueLen++;
- }
+ newPacket = skb_clone(skb, GFP_KERNEL);
+ if (!newPacket)
+ break;
+ ENQUEUEPACKET(pTarang->RxAppControlHead,
+ pTarang->RxAppControlTail, newPacket);
+ pTarang->AppCtrlQueueLen++;
+ }
up(&Adapter->RxAppControlQueuelock);
- wake_up(&Adapter->process_read_wait_queue);
- dev_kfree_skb(skb);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "After wake_up_interruptible");
+ wake_up(&Adapter->process_read_wait_queue);
+ dev_kfree_skb(skb);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,
+ "After wake_up_interruptible");
}
/**
-@ingroup ctrl_pkt_functions
-Thread to handle control pkt reception
-*/
-int control_packet_handler (PMINI_ADAPTER Adapter /**< pointer to adapter object*/
- )
+ * @ingroup ctrl_pkt_functions
+ * Thread to handle control pkt reception
+ */
+int control_packet_handler(PMINI_ADAPTER Adapter /* pointer to adapter object*/)
{
- struct sk_buff *ctrl_packet= NULL;
+ struct sk_buff *ctrl_packet = NULL;
unsigned long flags = 0;
- //struct timeval tv ;
- //int *puiBuffer = NULL ;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Entering to make thread wait on control packet event!");
- while(1)
- {
+ /* struct timeval tv; */
+ /* int *puiBuffer = NULL; */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,
+ "Entering to make thread wait on control packet event!");
+ while (1) {
wait_event_interruptible(Adapter->process_rx_cntrlpkt,
- atomic_read(&Adapter->cntrlpktCnt) ||
- Adapter->bWakeUpDevice ||
- kthread_should_stop()
- );
+ atomic_read(&Adapter->cntrlpktCnt) ||
+ Adapter->bWakeUpDevice ||
+ kthread_should_stop());
- if(kthread_should_stop())
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Exiting \n");
+ if (kthread_should_stop()) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL, "Exiting\n");
return 0;
}
- if(TRUE == Adapter->bWakeUpDevice)
- {
+ if (TRUE == Adapter->bWakeUpDevice) {
Adapter->bWakeUpDevice = FALSE;
- if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) &&
- ((TRUE == Adapter->IdleMode)|| (TRUE == Adapter->bShutStatus)))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Calling InterfaceAbortIdlemode\n");
- // Adapter->bTriedToWakeUpFromlowPowerMode = TRUE;
- InterfaceIdleModeWakeup (Adapter);
+ if ((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode)
+ && ((TRUE == Adapter->IdleMode) ||
+ (TRUE == Adapter->bShutStatus))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ CP_CTRL_PKT, DBG_LVL_ALL,
+ "Calling InterfaceAbortIdlemode\n");
+ /*
+ * Adapter->bTriedToWakeUpFromlowPowerMode
+ * = TRUE;
+ */
+ InterfaceIdleModeWakeup(Adapter);
}
continue;
}
- while(atomic_read(&Adapter->cntrlpktCnt))
- {
+ while (atomic_read(&Adapter->cntrlpktCnt)) {
spin_lock_irqsave(&Adapter->control_queue_lock, flags);
ctrl_packet = Adapter->RxControlHead;
- if(ctrl_packet)
- {
- DEQUEUEPACKET(Adapter->RxControlHead,Adapter->RxControlTail);
-// Adapter->RxControlHead=ctrl_packet->next;
+ if (ctrl_packet) {
+ DEQUEUEPACKET(Adapter->RxControlHead,
+ Adapter->RxControlTail);
+ /* Adapter->RxControlHead=ctrl_packet->next; */
}
- spin_unlock_irqrestore (&Adapter->control_queue_lock, flags);
- handle_rx_control_packet(Adapter, ctrl_packet);
+ spin_unlock_irqrestore(&Adapter->control_queue_lock,
+ flags);
+ handle_rx_control_packet(Adapter, ctrl_packet);
atomic_dec(&Adapter->cntrlpktCnt);
}
@@ -201,22 +214,22 @@ int control_packet_handler (PMINI_ADAPTER Adapter /**< pointer to adapter obje
INT flushAllAppQ(void)
{
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
- PPER_TARANG_DATA pTarang = NULL;
+ PPER_TARANG_DATA pTarang = NULL;
struct sk_buff *PacketToDrop = NULL;
- for(pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next)
- {
- while(pTarang->RxAppControlHead != NULL)
- {
- PacketToDrop=pTarang->RxAppControlHead;
- DEQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail);
+ for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next) {
+ while (pTarang->RxAppControlHead != NULL) {
+ PacketToDrop = pTarang->RxAppControlHead;
+ DEQUEUEPACKET(pTarang->RxAppControlHead,
+ pTarang->RxAppControlTail);
dev_kfree_skb(PacketToDrop);
}
pTarang->AppCtrlQueueLen = 0;
- //dropped contrl packet statistics also should be reset.
- memset((PVOID)&pTarang->stDroppedAppCntrlMsgs, 0, sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES));
+ /* dropped contrl packet statistics also should be reset. */
+ memset((PVOID)&pTarang->stDroppedAppCntrlMsgs, 0,
+ sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES));
}
- return STATUS_SUCCESS ;
+ return STATUS_SUCCESS;
}
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c
index bcd86bbef2fd..65c352f35681 100644
--- a/drivers/staging/bcm/InterfaceDld.c
+++ b/drivers/staging/bcm/InterfaceDld.c
@@ -62,6 +62,7 @@ int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_c
static int fw_down;
INT Status = STATUS_SUCCESS;
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
+ int bytes;
buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
@@ -94,8 +95,9 @@ int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_c
break;
}
- Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
- if (Status) {
+ bytes = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
+ if (bytes < 0) {
+ Status = bytes;
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
goto exit;
}
@@ -302,6 +304,7 @@ static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32Fi
UINT len = u32FirmwareLength;
INT retval = STATUS_SUCCESS;
PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
+ int bytes;
if (NULL == readbackbuff) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
@@ -310,9 +313,10 @@ static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32Fi
while (u32FirmwareLength && !retval) {
len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
- retval = rdm(Adapter, u32StartingAddress, readbackbuff, len);
+ bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len);
- if (retval) {
+ if (bytes < 0) {
+ retval = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval);
break;
}
diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c
index 96fa4ead7930..faeb03e62c06 100644
--- a/drivers/staging/bcm/InterfaceIdleMode.c
+++ b/drivers/staging/bcm/InterfaceIdleMode.c
@@ -46,6 +46,7 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer)
{
int status = STATUS_SUCCESS;
unsigned int uiRegRead = 0;
+ int bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"SubType of Message :0x%X", ntohl(*puiBuffer));
@@ -77,16 +78,16 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer)
else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
{
//clear on read Register
- status = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead));
- if(status)
- {
+ bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead));
+ if (bytes < 0) {
+ status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg0");
return status;
}
//clear on read Register
- status = rdmalt (Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead));
- if(status)
- {
+ bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead));
+ if (bytes < 0) {
+ status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg1");
return status;
}
@@ -117,9 +118,9 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer)
Adapter->chip_id== BCS220_3)
{
- status = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
- if(status)
- {
+ bytes = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
+ if (bytes < 0) {
+ status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0\n");
return status;
}
@@ -266,6 +267,8 @@ void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter)
{
unsigned int uiRegVal = 0;
INT Status = 0;
+ int bytes;
+
if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
{
// clear idlemode interrupt.
@@ -282,16 +285,16 @@ void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter)
{
//clear Interrupt EP registers.
- Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal));
- if(Status)
- {
+ bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal));
+ if (bytes < 0) {
+ Status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG0 failed with Err :%d", Status);
return;
}
- Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal));
- if(Status)
- {
+ bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal));
+ if (bytes < 0) {
+ Status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG1 failed with Err :%d", Status);
return;
}
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
index a09d35108f04..8e3c586a699c 100644
--- a/drivers/staging/bcm/InterfaceInit.c
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -68,7 +68,7 @@ static void InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter)
static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter)
{
unsigned long ulReg = 0;
- int ret;
+ int bytes;
/* Program EP2 MAX_PKT_SIZE */
ulReg = ntohl(EP2_MPS_REG);
@@ -94,8 +94,8 @@ static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter)
BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x140, 4, TRUE);
/* Program TX EP as interrupt(Alternate Setting) */
- ret = rdmalt(Adapter, 0x0F0110F8, (u32 *)&ulReg, sizeof(u32));
- if (ret) {
+ bytes = rdmalt(Adapter, 0x0F0110F8, (u32 *)&ulReg, sizeof(u32));
+ if (bytes < 0) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
"reading of Tx EP failed\n");
return;
@@ -430,6 +430,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
int usedIntOutForBulkTransfer = 0 ;
BOOLEAN bBcm16 = FALSE;
UINT uiData = 0;
+ int bytes;
/* Store the usb dev into interface adapter */
psIntfAdapter->udev = usb_get_dev(interface_to_usbdev(psIntfAdapter->interface));
@@ -438,9 +439,10 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
psIntfAdapter->psAdapter->interface_rdm = BcmRDM;
psIntfAdapter->psAdapter->interface_wrm = BcmWRM;
- retval = rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG,
+ bytes = rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG,
(u32 *)&(psIntfAdapter->psAdapter->chip_id), sizeof(u32));
- if (retval) {
+ if (bytes < 0) {
+ retval = bytes;
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "CHIP ID Read Failed\n");
return retval;
}
diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c
index 61f878b4f56c..2218faeaf8ac 100644
--- a/drivers/staging/bcm/InterfaceMisc.c
+++ b/drivers/staging/bcm/InterfaceMisc.c
@@ -5,7 +5,7 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
PVOID buff,
INT len)
{
- int retval = 0;
+ int bytes;
USHORT usRetries = 0;
if (psIntfAdapter == NULL) {
@@ -30,7 +30,7 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
psIntfAdapter->psAdapter->DeviceAccess = TRUE;
do {
- retval = usb_control_msg(psIntfAdapter->udev,
+ bytes = usb_control_msg(psIntfAdapter->udev,
usb_rcvctrlpipe(psIntfAdapter->udev, 0),
0x02,
0xC2,
@@ -41,22 +41,20 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
5000);
usRetries++;
- if (-ENODEV == retval) {
+ if (-ENODEV == bytes) {
psIntfAdapter->psAdapter->device_removed = TRUE;
break;
}
- } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
+ } while ((bytes < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
- if (retval < 0) {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval, usRetries);
- psIntfAdapter->psAdapter->DeviceAccess = FALSE;
- return retval;
- } else {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval);
- psIntfAdapter->psAdapter->DeviceAccess = FALSE;
- return STATUS_SUCCESS;
- }
+ if (bytes < 0)
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", bytes, usRetries);
+ else
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes);
+
+ psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+ return bytes;
}
INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
index e9f29d597518..c7725e141fd5 100644
--- a/drivers/staging/bcm/Misc.c
+++ b/drivers/staging/bcm/Misc.c
@@ -814,6 +814,7 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter)
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
unsigned int value = 0, uiResetValue = 0;
+ int bytes;
psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter));
ps_adapter->bDDRInitDone = FALSE;
@@ -848,8 +849,9 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter)
ps_adapter->chip_id == BCS250_BC ||
ps_adapter->chip_id == BCS220_3) {
- retval = rdmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value));
- if (retval < 0) {
+ bytes = rdmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value));
+ if (bytes < 0) {
+ retval = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval);
goto err_exit;
}
@@ -862,8 +864,9 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter)
}
}
} else {
- retval = rdmalt(ps_adapter, 0x0f007018, &value, sizeof(value));
- if (retval < 0) {
+ bytes = rdmalt(ps_adapter, 0x0f007018, &value, sizeof(value));
+ if (bytes < 0) {
+ retval = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval);
goto err_exit;
}
@@ -925,11 +928,16 @@ err_exit:
int run_card_proc(PMINI_ADAPTER ps_adapter)
{
+ int status = STATUS_SUCCESS;
+ int bytes;
+
unsigned int value = 0;
{
- if (rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
+ bytes = rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value));
+ if (bytes < 0) {
+ status = bytes;
BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__);
- return STATUS_FAILURE;
+ return status;
}
if (ps_adapter->bFlashBoot)
@@ -942,7 +950,7 @@ int run_card_proc(PMINI_ADAPTER ps_adapter)
return STATUS_FAILURE;
}
}
- return STATUS_SUCCESS;
+ return status;
}
int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter)
@@ -1215,6 +1223,7 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress)
int status = 0, i = 0;
unsigned int temp = 0;
unsigned char *pucmacaddr = kmalloc(MAC_ADDRESS_SIZE, GFP_KERNEL);
+ int bytes;
if (!pucmacaddr) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n");
@@ -1231,8 +1240,9 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress)
}
for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
- status = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp, sizeof(temp));
- if (status != STATUS_SUCCESS) {
+ bytes = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp, sizeof(temp));
+ if (bytes < 0) {
+ status = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n");
kfree(pucmacaddr);
pucmacaddr = NULL;
@@ -1574,11 +1584,13 @@ void update_per_sf_desc_cnts(PMINI_ADAPTER Adapter)
{
INT iIndex = 0;
u32 uibuff[MAX_TARGET_DSX_BUFFERS];
+ int bytes;
if (!atomic_read(&Adapter->uiMBupdate))
return;
- if (rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS) < 0) {
+ bytes = rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS);
+ if (bytes < 0) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed\n");
return;
}
diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c
index c13ea5c9a2aa..101c4e31249e 100644
--- a/drivers/staging/bcm/hostmibs.c
+++ b/drivers/staging/bcm/hostmibs.c
@@ -1,4 +1,3 @@
-
/*
* File Name: hostmibs.c
*
@@ -6,73 +5,72 @@
*
* Abstract: This file contains the routines to copy the statistics used by
* the driver to the Host MIBS structure and giving the same to Application.
- *
*/
+
#include "headers.h"
-INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMibs)
+INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMibs)
{
- S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
- S_PHS_RULE *pstPhsRule = NULL;
- S_CLASSIFIER_TABLE *pstClassifierTable = NULL;
- S_CLASSIFIER_ENTRY *pstClassifierRule = NULL;
- PPHS_DEVICE_EXTENSION pDeviceExtension = (PPHS_DEVICE_EXTENSION)&Adapter->stBCMPhsContext;
+ S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
+ S_PHS_RULE *pstPhsRule = NULL;
+ S_CLASSIFIER_TABLE *pstClassifierTable = NULL;
+ S_CLASSIFIER_ENTRY *pstClassifierRule = NULL;
+ PPHS_DEVICE_EXTENSION pDeviceExtension = (PPHS_DEVICE_EXTENSION) &Adapter->stBCMPhsContext;
- UINT nClassifierIndex = 0, nPhsTableIndex = 0,nSfIndex = 0, uiIndex = 0;
+ UINT nClassifierIndex = 0, nPhsTableIndex = 0, nSfIndex = 0, uiIndex = 0;
- if(pDeviceExtension == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, HOST_MIBS, DBG_LVL_ALL, "Invalid Device Extension\n");
+ if (pDeviceExtension == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, HOST_MIBS, DBG_LVL_ALL, "Invalid Device Extension\n");
return STATUS_FAILURE;
}
- //Copy the classifier Table
- for(nClassifierIndex=0; nClassifierIndex < MAX_CLASSIFIERS;
- nClassifierIndex++)
- {
- if(Adapter->astClassifierTable[nClassifierIndex].bUsed == TRUE)
- memcpy((PVOID)&pstHostMibs->astClassifierTable[nClassifierIndex],
- (PVOID)&Adapter->astClassifierTable[nClassifierIndex],
- sizeof(S_MIBS_CLASSIFIER_RULE));
+ /* Copy the classifier Table */
+ for (nClassifierIndex = 0; nClassifierIndex < MAX_CLASSIFIERS; nClassifierIndex++) {
+ if (Adapter->astClassifierTable[nClassifierIndex].bUsed == TRUE)
+ memcpy((PVOID) & pstHostMibs->
+ astClassifierTable[nClassifierIndex],
+ (PVOID) & Adapter->
+ astClassifierTable[nClassifierIndex],
+ sizeof(S_MIBS_CLASSIFIER_RULE));
}
- //Copy the SF Table
- for(nSfIndex=0; nSfIndex < NO_OF_QUEUES ; nSfIndex++)
- {
- if(Adapter->PackInfo[nSfIndex].bValid)
- {
- memcpy((PVOID)&pstHostMibs->astSFtable[nSfIndex],(PVOID)&Adapter->PackInfo[nSfIndex],sizeof(S_MIBS_SERVICEFLOW_TABLE));
- }
- else
- {
- //if index in not valid, don't process this for the PHS table. Go For the next entry.
- continue ;
- }
+ /* Copy the SF Table */
+ for (nSfIndex = 0; nSfIndex < NO_OF_QUEUES; nSfIndex++) {
+ if (Adapter->PackInfo[nSfIndex].bValid) {
+ memcpy((PVOID) & pstHostMibs->astSFtable[nSfIndex],
+ (PVOID) & Adapter->PackInfo[nSfIndex],
+ sizeof(S_MIBS_SERVICEFLOW_TABLE));
+ } else {
+ /* If index in not valid,
+ * don't process this for the PHS table.
+ * Go For the next entry.
+ */
+ continue;
+ }
- //Retrieve the SFID Entry Index for requested Service Flow
- if(PHS_INVALID_TABLE_INDEX == GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
- Adapter->PackInfo[nSfIndex].usVCID_Value ,&pstServiceFlowEntry))
- {
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ if (PHS_INVALID_TABLE_INDEX ==
+ GetServiceFlowEntry(pDeviceExtension->
+ pstServiceFlowPhsRulesTable,
+ Adapter->PackInfo[nSfIndex].
+ usVCID_Value, &pstServiceFlowEntry))
- continue;
- }
+ continue;
pstClassifierTable = pstServiceFlowEntry->pstClassifierTable;
-
- for(uiIndex = 0; uiIndex < MAX_PHSRULE_PER_SF; uiIndex++)
- {
+ for (uiIndex = 0; uiIndex < MAX_PHSRULE_PER_SF; uiIndex++) {
pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[uiIndex];
- if(pstClassifierRule->bUsed)
- {
- pstPhsRule = pstClassifierRule->pstPhsRule;
+ if (pstClassifierRule->bUsed) {
+ pstPhsRule = pstClassifierRule->pstPhsRule;
- pstHostMibs->astPhsRulesTable[nPhsTableIndex].ulSFID = Adapter->PackInfo[nSfIndex].ulSFID;
+ pstHostMibs->astPhsRulesTable[nPhsTableIndex].
+ ulSFID = Adapter->PackInfo[nSfIndex].ulSFID;
- memcpy(&pstHostMibs->astPhsRulesTable[nPhsTableIndex].u8PHSI,
- &pstPhsRule->u8PHSI,
- sizeof(S_PHS_RULE));
+ memcpy(&pstHostMibs->
+ astPhsRulesTable[nPhsTableIndex].u8PHSI,
+ &pstPhsRule->u8PHSI, sizeof(S_PHS_RULE));
nPhsTableIndex++;
}
@@ -81,65 +79,63 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMi
}
-
- //copy other Host Statistics parameters
+ /* Copy other Host Statistics parameters */
pstHostMibs->stHostInfo.GoodTransmits = Adapter->dev->stats.tx_packets;
pstHostMibs->stHostInfo.GoodReceives = Adapter->dev->stats.rx_packets;
- pstHostMibs->stHostInfo.CurrNumFreeDesc =
- atomic_read(&Adapter->CurrNumFreeTxDesc);
+ pstHostMibs->stHostInfo.CurrNumFreeDesc = atomic_read(&Adapter->CurrNumFreeTxDesc);
pstHostMibs->stHostInfo.BEBucketSize = Adapter->BEBucketSize;
pstHostMibs->stHostInfo.rtPSBucketSize = Adapter->rtPSBucketSize;
pstHostMibs->stHostInfo.TimerActive = Adapter->TimerActive;
pstHostMibs->stHostInfo.u32TotalDSD = Adapter->u32TotalDSD;
- memcpy(pstHostMibs->stHostInfo.aTxPktSizeHist,Adapter->aTxPktSizeHist,sizeof(UINT32)*MIBS_MAX_HIST_ENTRIES);
- memcpy(pstHostMibs->stHostInfo.aRxPktSizeHist,Adapter->aRxPktSizeHist,sizeof(UINT32)*MIBS_MAX_HIST_ENTRIES);
+ memcpy(pstHostMibs->stHostInfo.aTxPktSizeHist, Adapter->aTxPktSizeHist, sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
+ memcpy(pstHostMibs->stHostInfo.aRxPktSizeHist, Adapter->aRxPktSizeHist, sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
return STATUS_SUCCESS;
}
-
VOID GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *pstHostMibs, const PPER_TARANG_DATA pTarang)
{
memcpy(&(pstHostMibs->stDroppedAppCntrlMsgs),
- &(pTarang->stDroppedAppCntrlMsgs),sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES));
+ &(pTarang->stDroppedAppCntrlMsgs),
+ sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES));
}
-
-VOID CopyMIBSExtendedSFParameters(PMINI_ADAPTER Adapter,
- CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex)
+VOID CopyMIBSExtendedSFParameters(PMINI_ADAPTER Adapter, CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex)
{
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfSfid = psfLocalSet->u32SFID;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxSustainedRate = psfLocalSet->u32MaxSustainedTrafficRate;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxTrafficBurst = psfLocalSet->u32MaxTrafficBurst;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMinReservedRate = psfLocalSet->u32MinReservedTrafficRate;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsToleratedJitter = psfLocalSet->u32ToleratedJitter;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxLatency = psfLocalSet->u32MaximumLatency;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsFixedVsVariableSduInd = psfLocalSet->u8FixedLengthVSVariableLengthSDUIndicator;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsFixedVsVariableSduInd = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsFixedVsVariableSduInd);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSduSize = psfLocalSet->u8SDUSize;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSduSize = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSduSize);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSfSchedulingType = psfLocalSet->u8ServiceFlowSchedulingType;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSfSchedulingType = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSfSchedulingType);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqEnable = psfLocalSet->u8ARQEnable;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqEnable = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqEnable);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqWindowSize = ntohs(psfLocalSet->u16ARQWindowSize);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqWindowSize = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqWindowSize);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockLifetime = ntohs(psfLocalSet->u16ARQBlockLifeTime);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockLifetime = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockLifetime);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqSyncLossTimeout = ntohs(psfLocalSet->u16ARQSyncLossTimeOut);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqSyncLossTimeout = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqSyncLossTimeout);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqDeliverInOrder = psfLocalSet->u8ARQDeliverInOrder;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqDeliverInOrder = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqDeliverInOrder);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqRxPurgeTimeout = ntohs(psfLocalSet->u16ARQRxPurgeTimeOut);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqRxPurgeTimeout = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqRxPurgeTimeout);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockSize = ntohs(psfLocalSet->u16ARQBlockSize);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockSize = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockSize);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsReqTxPolicy = psfLocalSet->u8RequesttransmissionPolicy;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsReqTxPolicy = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsReqTxPolicy);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnSfCsSpecification = psfLocalSet->u8CSSpecification;
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnSfCsSpecification = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnSfCsSpecification);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsTargetSaid = ntohs(psfLocalSet->u16TargetSAID);
- Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsTargetSaid = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsTargetSaid);
+ S_MIBS_EXTSERVICEFLOW_PARAMETERS *t = &Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable;
+
+ t->wmanIfSfid = psfLocalSet->u32SFID;
+ t->wmanIfCmnCpsMaxSustainedRate = psfLocalSet->u32MaxSustainedTrafficRate;
+ t->wmanIfCmnCpsMaxTrafficBurst = psfLocalSet->u32MaxTrafficBurst;
+ t->wmanIfCmnCpsMinReservedRate = psfLocalSet->u32MinReservedTrafficRate;
+ t->wmanIfCmnCpsToleratedJitter = psfLocalSet->u32ToleratedJitter;
+ t->wmanIfCmnCpsMaxLatency = psfLocalSet->u32MaximumLatency;
+ t->wmanIfCmnCpsFixedVsVariableSduInd = psfLocalSet->u8FixedLengthVSVariableLengthSDUIndicator;
+ t->wmanIfCmnCpsFixedVsVariableSduInd = ntohl(t->wmanIfCmnCpsFixedVsVariableSduInd);
+ t->wmanIfCmnCpsSduSize = psfLocalSet->u8SDUSize;
+ t->wmanIfCmnCpsSduSize = ntohl(t->wmanIfCmnCpsSduSize);
+ t->wmanIfCmnCpsSfSchedulingType = psfLocalSet->u8ServiceFlowSchedulingType;
+ t->wmanIfCmnCpsSfSchedulingType = ntohl(t->wmanIfCmnCpsSfSchedulingType);
+ t->wmanIfCmnCpsArqEnable = psfLocalSet->u8ARQEnable;
+ t->wmanIfCmnCpsArqEnable = ntohl(t->wmanIfCmnCpsArqEnable);
+ t->wmanIfCmnCpsArqWindowSize = ntohs(psfLocalSet->u16ARQWindowSize);
+ t->wmanIfCmnCpsArqWindowSize = ntohl(t->wmanIfCmnCpsArqWindowSize);
+ t->wmanIfCmnCpsArqBlockLifetime = ntohs(psfLocalSet->u16ARQBlockLifeTime);
+ t->wmanIfCmnCpsArqBlockLifetime = ntohl(t->wmanIfCmnCpsArqBlockLifetime);
+ t->wmanIfCmnCpsArqSyncLossTimeout = ntohs(psfLocalSet->u16ARQSyncLossTimeOut);
+ t->wmanIfCmnCpsArqSyncLossTimeout = ntohl(t->wmanIfCmnCpsArqSyncLossTimeout);
+ t->wmanIfCmnCpsArqDeliverInOrder = psfLocalSet->u8ARQDeliverInOrder;
+ t->wmanIfCmnCpsArqDeliverInOrder = ntohl(t->wmanIfCmnCpsArqDeliverInOrder);
+ t->wmanIfCmnCpsArqRxPurgeTimeout = ntohs(psfLocalSet->u16ARQRxPurgeTimeOut);
+ t->wmanIfCmnCpsArqRxPurgeTimeout = ntohl(t->wmanIfCmnCpsArqRxPurgeTimeout);
+ t->wmanIfCmnCpsArqBlockSize = ntohs(psfLocalSet->u16ARQBlockSize);
+ t->wmanIfCmnCpsArqBlockSize = ntohl(t->wmanIfCmnCpsArqBlockSize);
+ t->wmanIfCmnCpsReqTxPolicy = psfLocalSet->u8RequesttransmissionPolicy;
+ t->wmanIfCmnCpsReqTxPolicy = ntohl(t->wmanIfCmnCpsReqTxPolicy);
+ t->wmanIfCmnSfCsSpecification = psfLocalSet->u8CSSpecification;
+ t->wmanIfCmnSfCsSpecification = ntohl(t->wmanIfCmnSfCsSpecification);
+ t->wmanIfCmnCpsTargetSaid = ntohs(psfLocalSet->u16TargetSAID);
+ t->wmanIfCmnCpsTargetSaid = ntohl(t->wmanIfCmnCpsTargetSaid);
}
diff --git a/drivers/staging/bcm/led_control.c b/drivers/staging/bcm/led_control.c
index 16e939fa15d6..c7f488629722 100644
--- a/drivers/staging/bcm/led_control.c
+++ b/drivers/staging/bcm/led_control.c
@@ -5,65 +5,69 @@
static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size)
{
- B_UINT16 u16CheckSum=0;
- while(u32Size--) {
+ B_UINT16 u16CheckSum = 0;
+ while (u32Size--) {
u16CheckSum += (B_UINT8)~(*pu8Buffer);
- pu8Buffer++;
+ pu8Buffer++;
}
return u16CheckSum;
}
+
BOOLEAN IsReqGpioIsLedInNVM(PMINI_ADAPTER Adapter, UINT gpios)
{
- INT Status ;
- Status = (Adapter->gpioBitMap & gpios) ^ gpios ;
- if(Status)
+ INT Status;
+ Status = (Adapter->gpioBitMap & gpios) ^ gpios;
+ if (Status)
return FALSE;
else
return TRUE;
}
-static INT LED_Blink(PMINI_ADAPTER Adapter, UINT GPIO_Num, UCHAR uiLedIndex, ULONG timeout, INT num_of_time, LedEventInfo_t currdriverstate)
+static INT LED_Blink(PMINI_ADAPTER Adapter, UINT GPIO_Num, UCHAR uiLedIndex,
+ ULONG timeout, INT num_of_time, LedEventInfo_t currdriverstate)
{
int Status = STATUS_SUCCESS;
BOOLEAN bInfinite = FALSE;
- /*Check if num_of_time is -ve. If yes, blink led in infinite loop*/
- if(num_of_time < 0)
- {
+ /* Check if num_of_time is -ve. If yes, blink led in infinite loop */
+ if (num_of_time < 0) {
bInfinite = TRUE;
num_of_time = 1;
}
- while(num_of_time)
- {
-
- if(currdriverstate == Adapter->DriverState)
+ while (num_of_time) {
+ if (currdriverstate == Adapter->DriverState)
TURN_ON_LED(GPIO_Num, uiLedIndex);
- /*Wait for timeout after setting on the LED*/
- Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
- currdriverstate != Adapter->DriverState || kthread_should_stop(),
- msecs_to_jiffies(timeout));
-
- if(kthread_should_stop())
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
- Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
+ /* Wait for timeout after setting on the LED */
+ Status = wait_event_interruptible_timeout(
+ Adapter->LEDInfo.notify_led_event,
+ currdriverstate != Adapter->DriverState ||
+ kthread_should_stop(),
+ msecs_to_jiffies(timeout));
+
+ if (kthread_should_stop()) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "Led thread got signal to exit..hence exiting");
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
TURN_OFF_LED(GPIO_Num, uiLedIndex);
- Status=EVENT_SIGNALED;
+ Status = EVENT_SIGNALED;
break;
}
- if(Status)
- {
+ if (Status) {
TURN_OFF_LED(GPIO_Num, uiLedIndex);
- Status=EVENT_SIGNALED;
+ Status = EVENT_SIGNALED;
break;
}
TURN_OFF_LED(GPIO_Num, uiLedIndex);
- Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
- currdriverstate!= Adapter->DriverState || kthread_should_stop(),
- msecs_to_jiffies(timeout));
- if(bInfinite == FALSE)
+ Status = wait_event_interruptible_timeout(
+ Adapter->LEDInfo.notify_led_event,
+ currdriverstate != Adapter->DriverState ||
+ kthread_should_stop(),
+ msecs_to_jiffies(timeout));
+ if (bInfinite == FALSE)
num_of_time--;
}
return Status;
@@ -71,19 +75,19 @@ static INT LED_Blink(PMINI_ADAPTER Adapter, UINT GPIO_Num, UCHAR uiLedIndex, ULO
static INT ScaleRateofTransfer(ULONG rate)
{
- if(rate <= 3)
+ if (rate <= 3)
return rate;
- else if((rate > 3) && (rate <= 100))
+ else if ((rate > 3) && (rate <= 100))
return 5;
- else if((rate > 100) && (rate <= 200))
+ else if ((rate > 100) && (rate <= 200))
return 6;
- else if((rate > 200) && (rate <= 300))
+ else if ((rate > 200) && (rate <= 300))
return 7;
- else if((rate > 300) && (rate <= 400))
+ else if ((rate > 300) && (rate <= 400))
return 8;
- else if((rate > 400) && (rate <= 500))
+ else if ((rate > 400) && (rate <= 500))
return 9;
- else if((rate > 500) && (rate <= 600))
+ else if ((rate > 500) && (rate <= 600))
return 10;
else
return MAX_NUM_OF_BLINKS;
@@ -92,215 +96,232 @@ static INT ScaleRateofTransfer(ULONG rate)
static INT LED_Proportional_Blink(PMINI_ADAPTER Adapter, UCHAR GPIO_Num_tx,
- UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex, LedEventInfo_t currdriverstate)
+ UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex,
+ LedEventInfo_t currdriverstate)
{
- /* Initial values of TX and RX packets*/
+ /* Initial values of TX and RX packets */
ULONG64 Initial_num_of_packts_tx = 0, Initial_num_of_packts_rx = 0;
- /*values of TX and RX packets after 1 sec*/
+ /* values of TX and RX packets after 1 sec */
ULONG64 Final_num_of_packts_tx = 0, Final_num_of_packts_rx = 0;
- /*Rate of transfer of Tx and Rx in 1 sec*/
+ /* Rate of transfer of Tx and Rx in 1 sec */
ULONG64 rate_of_transfer_tx = 0, rate_of_transfer_rx = 0;
int Status = STATUS_SUCCESS;
INT num_of_time = 0, num_of_time_tx = 0, num_of_time_rx = 0;
UINT remDelay = 0;
BOOLEAN bBlinkBothLED = TRUE;
- //UINT GPIO_num = DISABLE_GPIO_NUM;
+ /* UINT GPIO_num = DISABLE_GPIO_NUM; */
ulong timeout = 0;
- /*Read initial value of packets sent/received */
+ /* Read initial value of packets sent/received */
Initial_num_of_packts_tx = Adapter->dev->stats.tx_packets;
Initial_num_of_packts_rx = Adapter->dev->stats.rx_packets;
- /*Scale the rate of transfer to no of blinks.*/
- num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
- num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
+ /* Scale the rate of transfer to no of blinks. */
+ num_of_time_tx = ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
+ num_of_time_rx = ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
- while((Adapter->device_removed == FALSE))
- {
+ while ((Adapter->device_removed == FALSE)) {
timeout = 50;
- /*Blink Tx and Rx LED when both Tx and Rx is in normal bandwidth*/
- if(bBlinkBothLED)
- {
- /*Assign minimum number of blinks of either Tx or Rx.*/
- if(num_of_time_tx > num_of_time_rx)
+ /*
+ * Blink Tx and Rx LED when both Tx and Rx is
+ * in normal bandwidth
+ */
+ if (bBlinkBothLED) {
+ /*
+ * Assign minimum number of blinks of
+ * either Tx or Rx.
+ */
+ if (num_of_time_tx > num_of_time_rx)
num_of_time = num_of_time_rx;
else
num_of_time = num_of_time_tx;
- if(num_of_time > 0)
- {
- /*Blink both Tx and Rx LEDs*/
- if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout, num_of_time,currdriverstate)
+ if (num_of_time > 0) {
+ /* Blink both Tx and Rx LEDs */
+ if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
+ uiTxLedIndex, timeout,
+ num_of_time, currdriverstate)
== EVENT_SIGNALED)
- {
return EVENT_SIGNALED;
- }
- if(LED_Blink(Adapter, 1<<GPIO_Num_rx, uiRxLedIndex, timeout, num_of_time,currdriverstate)
+
+ if (LED_Blink(Adapter, 1 << GPIO_Num_rx,
+ uiRxLedIndex, timeout,
+ num_of_time, currdriverstate)
== EVENT_SIGNALED)
- {
return EVENT_SIGNALED;
- }
}
- if(num_of_time == num_of_time_tx)
- {
- /*Blink pending rate of Rx*/
- if(LED_Blink(Adapter, (1 << GPIO_Num_rx), uiRxLedIndex, timeout,
- num_of_time_rx-num_of_time,currdriverstate) == EVENT_SIGNALED)
- {
+ if (num_of_time == num_of_time_tx) {
+ /* Blink pending rate of Rx */
+ if (LED_Blink(Adapter, (1 << GPIO_Num_rx),
+ uiRxLedIndex, timeout,
+ num_of_time_rx-num_of_time,
+ currdriverstate)
+ == EVENT_SIGNALED)
return EVENT_SIGNALED;
- }
+
num_of_time = num_of_time_rx;
- }
- else
- {
- /*Blink pending rate of Tx*/
- if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout,
- num_of_time_tx-num_of_time,currdriverstate) == EVENT_SIGNALED)
- {
+ } else {
+ /* Blink pending rate of Tx */
+ if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
+ uiTxLedIndex, timeout,
+ num_of_time_tx-num_of_time,
+ currdriverstate)
+ == EVENT_SIGNALED)
return EVENT_SIGNALED;
- }
+
num_of_time = num_of_time_tx;
}
- }
- else
- {
- if(num_of_time == num_of_time_tx)
- {
- /*Blink pending rate of Rx*/
- if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout, num_of_time,currdriverstate)
+ } else {
+ if (num_of_time == num_of_time_tx) {
+ /* Blink pending rate of Rx */
+ if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
+ uiTxLedIndex, timeout,
+ num_of_time, currdriverstate)
== EVENT_SIGNALED)
- {
return EVENT_SIGNALED;
- }
- }
- else
- {
- /*Blink pending rate of Tx*/
- if(LED_Blink(Adapter, 1<<GPIO_Num_rx, uiRxLedIndex, timeout,
- num_of_time,currdriverstate) == EVENT_SIGNALED)
- {
+ } else {
+ /* Blink pending rate of Tx */
+ if (LED_Blink(Adapter, 1 << GPIO_Num_rx,
+ uiRxLedIndex, timeout,
+ num_of_time, currdriverstate)
+ == EVENT_SIGNALED)
return EVENT_SIGNALED;
- }
}
}
- /* If Tx/Rx rate is less than maximum blinks per second,
- * wait till delay completes to 1 second
- */
+
+ /*
+ * If Tx/Rx rate is less than maximum blinks per second,
+ * wait till delay completes to 1 second
+ */
remDelay = MAX_NUM_OF_BLINKS - num_of_time;
- if(remDelay > 0)
- {
- timeout= 100 * remDelay;
- Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
- currdriverstate!= Adapter->DriverState ||kthread_should_stop() ,
- msecs_to_jiffies (timeout));
-
- if(kthread_should_stop())
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
- Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
+ if (remDelay > 0) {
+ timeout = 100 * remDelay;
+ Status = wait_event_interruptible_timeout(
+ Adapter->LEDInfo.notify_led_event,
+ currdriverstate != Adapter->DriverState
+ || kthread_should_stop(),
+ msecs_to_jiffies(timeout));
+
+ if (kthread_should_stop()) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ LED_DUMP_INFO, DBG_LVL_ALL,
+ "Led thread got signal to exit..hence exiting");
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
return EVENT_SIGNALED;
}
- if(Status)
+ if (Status)
return EVENT_SIGNALED;
}
- /*Turn off both Tx and Rx LEDs before next second*/
- TURN_OFF_LED(1<<GPIO_Num_tx, uiTxLedIndex);
- TURN_OFF_LED(1<<GPIO_Num_rx, uiTxLedIndex);
+ /* Turn off both Tx and Rx LEDs before next second */
+ TURN_OFF_LED(1 << GPIO_Num_tx, uiTxLedIndex);
+ TURN_OFF_LED(1 << GPIO_Num_rx, uiTxLedIndex);
/*
- * Read the Tx & Rx packets transmission after 1 second and
- * calculate rate of transfer
- */
+ * Read the Tx & Rx packets transmission after 1 second and
+ * calculate rate of transfer
+ */
Final_num_of_packts_tx = Adapter->dev->stats.tx_packets;
Final_num_of_packts_rx = Adapter->dev->stats.rx_packets;
- rate_of_transfer_tx = Final_num_of_packts_tx - Initial_num_of_packts_tx;
- rate_of_transfer_rx = Final_num_of_packts_rx - Initial_num_of_packts_rx;
+ rate_of_transfer_tx = Final_num_of_packts_tx -
+ Initial_num_of_packts_tx;
+ rate_of_transfer_rx = Final_num_of_packts_rx -
+ Initial_num_of_packts_rx;
- /*Read initial value of packets sent/received */
+ /* Read initial value of packets sent/received */
Initial_num_of_packts_tx = Final_num_of_packts_tx;
- Initial_num_of_packts_rx = Final_num_of_packts_rx ;
+ Initial_num_of_packts_rx = Final_num_of_packts_rx;
- /*Scale the rate of transfer to no of blinks.*/
- num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
- num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
+ /* Scale the rate of transfer to no of blinks. */
+ num_of_time_tx =
+ ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
+ num_of_time_rx =
+ ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
}
return Status;
}
-
-//-----------------------------------------------------------------------------
-// Procedure: ValidateDSDParamsChecksum
-//
-// Description: Reads DSD Params and validates checkusm.
-//
-// Arguments:
-// Adapter - Pointer to Adapter structure.
-// ulParamOffset - Start offset of the DSD parameter to be read and validated.
-// usParamLen - Length of the DSD Parameter.
-//
-// Returns:
-// <OSAL_STATUS_CODE>
-//-----------------------------------------------------------------------------
-
-static INT ValidateDSDParamsChecksum(
- PMINI_ADAPTER Adapter,
- ULONG ulParamOffset,
- USHORT usParamLen )
+/*
+ * -----------------------------------------------------------------------------
+ * Procedure: ValidateDSDParamsChecksum
+ *
+ * Description: Reads DSD Params and validates checkusm.
+ *
+ * Arguments:
+ * Adapter - Pointer to Adapter structure.
+ * ulParamOffset - Start offset of the DSD parameter to be read and
+ * validated.
+ * usParamLen - Length of the DSD Parameter.
+ *
+ * Returns:
+ * <OSAL_STATUS_CODE>
+ * -----------------------------------------------------------------------------
+ */
+static INT ValidateDSDParamsChecksum(PMINI_ADAPTER Adapter, ULONG ulParamOffset,
+ USHORT usParamLen)
{
INT Status = STATUS_SUCCESS;
- PUCHAR puBuffer = NULL;
- USHORT usChksmOrg = 0;
+ PUCHAR puBuffer = NULL;
+ USHORT usChksmOrg = 0;
USHORT usChecksumCalculated = 0;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",ulParamOffset, usParamLen);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",
+ ulParamOffset, usParamLen);
puBuffer = kmalloc(usParamLen, GFP_KERNEL);
- if(!puBuffer)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum Allocation failed");
+ if (!puBuffer) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: ValidateDSDParamsChecksum Allocation failed");
return -ENOMEM;
}
- //
- // Read the DSD data from the parameter offset.
- //
- if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)puBuffer,ulParamOffset,usParamLen))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
- Status=STATUS_IMAGE_CHECKSUM_MISMATCH;
+ /* Read the DSD data from the parameter offset. */
+ if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)puBuffer,
+ ulParamOffset, usParamLen)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
+ Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
goto exit;
}
- //
- // Calculate the checksum of the data read from the DSD parameter.
- //
- usChecksumCalculated = CFG_CalculateChecksum(puBuffer,usParamLen);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usCheckSumCalculated = 0x%x\n", usChecksumCalculated);
-
- //
- // End of the DSD parameter will have a TWO bytes checksum stored in it. Read it and compare with the calculated
- // Checksum.
- //
- if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)&usChksmOrg,ulParamOffset+usParamLen,2))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
- Status=STATUS_IMAGE_CHECKSUM_MISMATCH;
+ /* Calculate the checksum of the data read from the DSD parameter. */
+ usChecksumCalculated = CFG_CalculateChecksum(puBuffer, usParamLen);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread: usCheckSumCalculated = 0x%x\n",
+ usChecksumCalculated);
+
+ /*
+ * End of the DSD parameter will have a TWO bytes checksum stored in it.
+ * Read it and compare with the calculated Checksum.
+ */
+ if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)&usChksmOrg,
+ ulParamOffset+usParamLen, 2)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
+ Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
goto exit;
}
usChksmOrg = ntohs(usChksmOrg);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usChksmOrg = 0x%x", usChksmOrg);
-
- //
- // Compare the checksum calculated with the checksum read from DSD section
- //
- if(usChecksumCalculated ^ usChksmOrg)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread: usChksmOrg = 0x%x", usChksmOrg);
+
+ /*
+ * Compare the checksum calculated with the checksum read
+ * from DSD section
+ */
+ if (usChecksumCalculated ^ usChksmOrg) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
goto exit;
}
@@ -311,523 +332,526 @@ exit:
}
-//-----------------------------------------------------------------------------
-// Procedure: ValidateHWParmStructure
-//
-// Description: Validates HW Parameters.
-//
-// Arguments:
-// Adapter - Pointer to Adapter structure.
-// ulHwParamOffset - Start offset of the HW parameter Section to be read and validated.
-//
-// Returns:
-// <OSAL_STATUS_CODE>
-//-----------------------------------------------------------------------------
-
+/*
+ * -----------------------------------------------------------------------------
+ * Procedure: ValidateHWParmStructure
+ *
+ * Description: Validates HW Parameters.
+ *
+ * Arguments:
+ * Adapter - Pointer to Adapter structure.
+ * ulHwParamOffset - Start offset of the HW parameter Section to be read
+ * and validated.
+ *
+ * Returns:
+ * <OSAL_STATUS_CODE>
+ * -----------------------------------------------------------------------------
+ */
static INT ValidateHWParmStructure(PMINI_ADAPTER Adapter, ULONG ulHwParamOffset)
{
- INT Status = STATUS_SUCCESS ;
+ INT Status = STATUS_SUCCESS;
USHORT HwParamLen = 0;
- // Add DSD start offset to the hwParamOffset to get the actual address.
+ /*
+ * Add DSD start offset to the hwParamOffset to get
+ * the actual address.
+ */
ulHwParamOffset += DSD_START_OFFSET;
- /*Read the Length of HW_PARAM structure*/
- BeceemNVMRead(Adapter,(PUINT)&HwParamLen,ulHwParamOffset,2);
+ /* Read the Length of HW_PARAM structure */
+ BeceemNVMRead(Adapter, (PUINT)&HwParamLen, ulHwParamOffset, 2);
HwParamLen = ntohs(HwParamLen);
- if(0==HwParamLen || HwParamLen > Adapter->uiNVMDSDSize)
- {
+ if (0 == HwParamLen || HwParamLen > Adapter->uiNVMDSDSize)
return STATUS_IMAGE_CHECKSUM_MISMATCH;
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "LED Thread:HwParamLen = 0x%x", HwParamLen);
- Status =ValidateDSDParamsChecksum(Adapter,ulHwParamOffset,HwParamLen);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread:HwParamLen = 0x%x", HwParamLen);
+ Status = ValidateDSDParamsChecksum(Adapter, ulHwParamOffset,
+ HwParamLen);
return Status;
} /* ValidateHWParmStructure() */
-static int ReadLEDInformationFromEEPROM(PMINI_ADAPTER Adapter, UCHAR GPIO_Array[])
+static int ReadLEDInformationFromEEPROM(PMINI_ADAPTER Adapter,
+ UCHAR GPIO_Array[])
{
int Status = STATUS_SUCCESS;
- ULONG dwReadValue = 0;
- USHORT usHwParamData = 0;
- USHORT usEEPROMVersion = 0;
- UCHAR ucIndex = 0;
- UCHAR ucGPIOInfo[32] = {0};
+ ULONG dwReadValue = 0;
+ USHORT usHwParamData = 0;
+ USHORT usEEPROMVersion = 0;
+ UCHAR ucIndex = 0;
+ UCHAR ucGPIOInfo[32] = {0};
- BeceemNVMRead(Adapter,(PUINT)&usEEPROMVersion,EEPROM_VERSION_OFFSET,2);
+ BeceemNVMRead(Adapter, (PUINT)&usEEPROMVersion,
+ EEPROM_VERSION_OFFSET, 2);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"usEEPROMVersion: Minor:0x%X Major:0x%x",usEEPROMVersion&0xFF, ((usEEPROMVersion>>8)&0xFF));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "usEEPROMVersion: Minor:0x%X Major:0x%x",
+ usEEPROMVersion&0xFF, ((usEEPROMVersion>>8)&0xFF));
- if(((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION)
- {
- BeceemNVMRead(Adapter,(PUINT)&usHwParamData,EEPROM_HW_PARAM_POINTER_ADDRESS,2);
+ if (((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION) {
+ BeceemNVMRead(Adapter, (PUINT)&usHwParamData,
+ EEPROM_HW_PARAM_POINTER_ADDRESS, 2);
usHwParamData = ntohs(usHwParamData);
dwReadValue = usHwParamData;
- }
- else
- {
- //
- // Validate Compatibility section and then read HW param if compatibility section is valid.
- //
+ } else {
+ /*
+ * Validate Compatibility section and then read HW param
+ * if compatibility section is valid.
+ */
Status = ValidateDSDParamsChecksum(Adapter,
- DSD_START_OFFSET,
- COMPATIBILITY_SECTION_LENGTH_MAP5);
+ DSD_START_OFFSET,
+ COMPATIBILITY_SECTION_LENGTH_MAP5);
- if(Status != STATUS_SUCCESS)
- {
+ if (Status != STATUS_SUCCESS)
return Status;
- }
- BeceemNVMRead(Adapter,(PUINT)&dwReadValue,EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5,4);
+
+ BeceemNVMRead(Adapter, (PUINT)&dwReadValue,
+ EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5, 4);
dwReadValue = ntohl(dwReadValue);
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Start address of HW_PARAM structure = 0x%lx",dwReadValue);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread: Start address of HW_PARAM structure = 0x%lx",
+ dwReadValue);
- //
- // Validate if the address read out is within the DSD.
- // Adapter->uiNVMDSDSize gives whole DSD size inclusive of Autoinit.
- // lower limit should be above DSD_START_OFFSET and
- // upper limit should be below (Adapter->uiNVMDSDSize-DSD_START_OFFSET)
- //
- if(dwReadValue < DSD_START_OFFSET ||
- dwReadValue > (Adapter->uiNVMDSDSize-DSD_START_OFFSET))
- {
+ /*
+ * Validate if the address read out is within the DSD.
+ * Adapter->uiNVMDSDSize gives whole DSD size inclusive of Autoinit.
+ * lower limit should be above DSD_START_OFFSET and
+ * upper limit should be below (Adapter->uiNVMDSDSize-DSD_START_OFFSET)
+ */
+ if (dwReadValue < DSD_START_OFFSET ||
+ dwReadValue > (Adapter->uiNVMDSDSize-DSD_START_OFFSET))
return STATUS_IMAGE_CHECKSUM_MISMATCH;
- }
Status = ValidateHWParmStructure(Adapter, dwReadValue);
- if(Status){
+ if (Status)
return Status;
- }
/*
- Add DSD_START_OFFSET to the offset read from the EEPROM.
- This will give the actual start HW Parameters start address.
- To read GPIO section, add GPIO offset further.
- */
-
- dwReadValue += DSD_START_OFFSET; // = start address of hw param section.
- dwReadValue += GPIO_SECTION_START_OFFSET; // = GPIO start offset within HW Param section.
-
- /* Read the GPIO values for 32 GPIOs from EEPROM and map the function
- * number to GPIO pin number to GPIO_Array
- */
- BeceemNVMRead(Adapter, (UINT *)ucGPIOInfo,dwReadValue,32);
- for(ucIndex = 0; ucIndex < 32; ucIndex++)
- {
-
- switch(ucGPIOInfo[ucIndex])
- {
- case RED_LED:
- {
- GPIO_Array[RED_LED] = ucIndex;
- Adapter->gpioBitMap |= (1<<ucIndex);
- break;
- }
- case BLUE_LED:
- {
- GPIO_Array[BLUE_LED] = ucIndex;
- Adapter->gpioBitMap |= (1<<ucIndex);
- break;
- }
- case YELLOW_LED:
- {
- GPIO_Array[YELLOW_LED] = ucIndex;
- Adapter->gpioBitMap |= (1<<ucIndex);
- break;
- }
- case GREEN_LED:
- {
- GPIO_Array[GREEN_LED] = ucIndex;
- Adapter->gpioBitMap |= (1<<ucIndex);
- break;
- }
- default:
- break;
- }
+ * Add DSD_START_OFFSET to the offset read from the EEPROM.
+ * This will give the actual start HW Parameters start address.
+ * To read GPIO section, add GPIO offset further.
+ */
+
+ dwReadValue +=
+ DSD_START_OFFSET; /* = start address of hw param section. */
+ dwReadValue += GPIO_SECTION_START_OFFSET;
+ /* = GPIO start offset within HW Param section. */
+ /*
+ * Read the GPIO values for 32 GPIOs from EEPROM and map the function
+ * number to GPIO pin number to GPIO_Array
+ */
+ BeceemNVMRead(Adapter, (UINT *)ucGPIOInfo, dwReadValue, 32);
+ for (ucIndex = 0; ucIndex < 32; ucIndex++) {
+
+ switch (ucGPIOInfo[ucIndex]) {
+ case RED_LED:
+ GPIO_Array[RED_LED] = ucIndex;
+ Adapter->gpioBitMap |= (1 << ucIndex);
+ break;
+ case BLUE_LED:
+ GPIO_Array[BLUE_LED] = ucIndex;
+ Adapter->gpioBitMap |= (1 << ucIndex);
+ break;
+ case YELLOW_LED:
+ GPIO_Array[YELLOW_LED] = ucIndex;
+ Adapter->gpioBitMap |= (1 << ucIndex);
+ break;
+ case GREEN_LED:
+ GPIO_Array[GREEN_LED] = ucIndex;
+ Adapter->gpioBitMap |= (1 << ucIndex);
+ break;
+ default:
+ break;
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"GPIO's bit map correspond to LED :0x%X",Adapter->gpioBitMap);
- return Status;
+
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "GPIO's bit map correspond to LED :0x%X", Adapter->gpioBitMap);
+ return Status;
}
-static int ReadConfigFileStructure(PMINI_ADAPTER Adapter, BOOLEAN *bEnableThread)
+static int ReadConfigFileStructure(PMINI_ADAPTER Adapter,
+ BOOLEAN *bEnableThread)
{
int Status = STATUS_SUCCESS;
- UCHAR GPIO_Array[NUM_OF_LEDS+1]; /*Array to store GPIO numbers from EEPROM*/
+ /* Array to store GPIO numbers from EEPROM */
+ UCHAR GPIO_Array[NUM_OF_LEDS+1];
UINT uiIndex = 0;
UINT uiNum_of_LED_Type = 0;
PUCHAR puCFGData = NULL;
UCHAR bData = 0;
memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1);
- if(!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams))
- {
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Target Params not Avail.\n");
+ if (!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams)) {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "Target Params not Avail.\n");
return -ENOENT;
}
- /*Populate GPIO_Array with GPIO numbers for LED functions*/
- /*Read the GPIO numbers from EEPROM*/
+ /* Populate GPIO_Array with GPIO numbers for LED functions */
+ /* Read the GPIO numbers from EEPROM */
Status = ReadLEDInformationFromEEPROM(Adapter, GPIO_Array);
- if(Status == STATUS_IMAGE_CHECKSUM_MISMATCH)
- {
+ if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH) {
*bEnableThread = FALSE;
return STATUS_SUCCESS;
- }
- else if(Status)
- {
+ } else if (Status) {
*bEnableThread = FALSE;
return Status;
}
- /*
- * CONFIG file read successfully. Deallocate the memory of
- * uiFileNameBufferSize
- */
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Config file read successfully\n");
+
+ /*
+ * CONFIG file read successfully. Deallocate the memory of
+ * uiFileNameBufferSize
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread: Config file read successfully\n");
puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1;
/*
- * Offset for HostDrvConfig1, HostDrvConfig2, HostDrvConfig3 which
- * will have the information of LED type, LED on state for different
- * driver state and LED blink state.
- */
+ * Offset for HostDrvConfig1, HostDrvConfig2, HostDrvConfig3 which
+ * will have the information of LED type, LED on state for different
+ * driver state and LED blink state.
+ */
- for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
- {
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
bData = *puCFGData;
- /*Check Bit 8 for polarity. If it is set, polarity is reverse polarity*/
- if(bData & 0x80)
- {
+ /*
+ * Check Bit 8 for polarity. If it is set,
+ * polarity is reverse polarity
+ */
+ if (bData & 0x80) {
Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0;
- /*unset the bit 8*/
+ /* unset the bit 8 */
bData = bData & 0x7f;
}
Adapter->LEDInfo.LEDState[uiIndex].LED_Type = bData;
- if(bData <= NUM_OF_LEDS)
- Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = GPIO_Array[bData];
+ if (bData <= NUM_OF_LEDS)
+ Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num =
+ GPIO_Array[bData];
else
- Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = DISABLE_GPIO_NUM;
+ Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num =
+ DISABLE_GPIO_NUM;
puCFGData++;
bData = *puCFGData;
Adapter->LEDInfo.LEDState[uiIndex].LED_On_State = bData;
puCFGData++;
bData = *puCFGData;
- Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State= bData;
+ Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State = bData;
puCFGData++;
}
- /*Check if all the LED settings are disabled. If it is disabled, dont launch the LED control thread.*/
- for(uiIndex = 0; uiIndex<NUM_OF_LEDS; uiIndex++)
- {
- if((Adapter->LEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) ||
- (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) ||
+ /*
+ * Check if all the LED settings are disabled. If it is disabled,
+ * dont launch the LED control thread.
+ */
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if ((Adapter->LEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) ||
+ (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) ||
(Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0))
uiNum_of_LED_Type++;
}
- if(uiNum_of_LED_Type >= NUM_OF_LEDS)
+ if (uiNum_of_LED_Type >= NUM_OF_LEDS)
*bEnableThread = FALSE;
return Status;
}
-//--------------------------------------------------------------------------
-// Procedure: LedGpioInit
-//
-// Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode and make the
-// initial state to be OFF.
-//
-// Arguments:
-// Adapter - Pointer to MINI_ADAPTER structure.
-//
-// Returns: VOID
-//
-//-----------------------------------------------------------------------------
+/*
+ * -----------------------------------------------------------------------------
+ * Procedure: LedGpioInit
+ *
+ * Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode
+ * and make the initial state to be OFF.
+ *
+ * Arguments:
+ * Adapter - Pointer to MINI_ADAPTER structure.
+ *
+ * Returns: VOID
+ *
+ * -----------------------------------------------------------------------------
+ */
static VOID LedGpioInit(PMINI_ADAPTER Adapter)
{
UINT uiResetValue = 0;
UINT uiIndex = 0;
/* Set all LED GPIO Mode to output mode */
- if(rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) <0)
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: RDM Failed\n");
- for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
- {
- if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
+ if (rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
+ sizeof(uiResetValue)) < 0)
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "LED Thread: RDM Failed\n");
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
+ DISABLE_GPIO_NUM)
uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
- TURN_OFF_LED(1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,uiIndex);
+ TURN_OFF_LED(1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,
+ uiIndex);
}
- if(wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) < 0)
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: WRM Failed\n");
+ if (wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
+ sizeof(uiResetValue)) < 0)
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "LED Thread: WRM Failed\n");
- Adapter->LEDInfo.bIdle_led_off = FALSE;
+ Adapter->LEDInfo.bIdle_led_off = FALSE;
}
-//-----------------------------------------------------------------------------
-static INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx, UCHAR *GPIO_num_rx ,UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,LedEventInfo_t currdriverstate)
+static INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx,
+ UCHAR *GPIO_num_rx, UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,
+ LedEventInfo_t currdriverstate)
{
UINT uiIndex = 0;
*GPIO_num_tx = DISABLE_GPIO_NUM;
*GPIO_num_rx = DISABLE_GPIO_NUM;
- for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
- {
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
- if((currdriverstate == NORMAL_OPERATION)||
- (currdriverstate == IDLEMODE_EXIT)||
- (currdriverstate == FW_DOWNLOAD))
- {
- if(Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State & currdriverstate)
- {
- if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
- {
- if(*GPIO_num_tx == DISABLE_GPIO_NUM)
- {
+ if ((currdriverstate == NORMAL_OPERATION) ||
+ (currdriverstate == IDLEMODE_EXIT) ||
+ (currdriverstate == FW_DOWNLOAD)) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State &
+ currdriverstate) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
+ != DISABLE_GPIO_NUM) {
+ if (*GPIO_num_tx == DISABLE_GPIO_NUM) {
*GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
*uiLedTxIndex = uiIndex;
- }
- else
- {
+ } else {
*GPIO_num_rx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
*uiLedRxIndex = uiIndex;
}
}
}
- }
- else
- {
- if(Adapter->LEDInfo.LEDState[uiIndex].LED_On_State & currdriverstate)
- {
- if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
- {
+ } else {
+ if (Adapter->LEDInfo.LEDState[uiIndex].LED_On_State
+ & currdriverstate) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
+ != DISABLE_GPIO_NUM) {
*GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
*uiLedTxIndex = uiIndex;
}
}
}
}
- return STATUS_SUCCESS ;
+ return STATUS_SUCCESS;
}
static VOID LEDControlThread(PMINI_ADAPTER Adapter)
{
UINT uiIndex = 0;
UCHAR GPIO_num = 0;
- UCHAR uiLedIndex = 0 ;
+ UCHAR uiLedIndex = 0;
UINT uiResetValue = 0;
LedEventInfo_t currdriverstate = 0;
ulong timeout = 0;
INT Status = 0;
- UCHAR dummyGPIONum = 0;
- UCHAR dummyIndex = 0;
+ UCHAR dummyGPIONum = 0;
+ UCHAR dummyIndex = 0;
- //currdriverstate = Adapter->DriverState;
+ /* currdriverstate = Adapter->DriverState; */
Adapter->LEDInfo.bIdleMode_tx_from_host = FALSE;
- /*Wait till event is triggered*/
- //wait_event(Adapter->LEDInfo.notify_led_event,
- // currdriverstate!= Adapter->DriverState);
+ /*
+ * Wait till event is triggered
+ *
+ * wait_event(Adapter->LEDInfo.notify_led_event,
+ * currdriverstate!= Adapter->DriverState);
+ */
- GPIO_num = DISABLE_GPIO_NUM ;
+ GPIO_num = DISABLE_GPIO_NUM;
- while(TRUE)
- {
- /*Wait till event is triggered*/
- if( (GPIO_num == DISABLE_GPIO_NUM)
+ while (TRUE) {
+ /* Wait till event is triggered */
+ if ((GPIO_num == DISABLE_GPIO_NUM)
||
- ((currdriverstate != FW_DOWNLOAD) &&
- (currdriverstate != NORMAL_OPERATION) &&
- (currdriverstate != LOWPOWER_MODE_ENTER))
- ||
- (currdriverstate == LED_THREAD_INACTIVE) )
- {
- Status = wait_event_interruptible(Adapter->LEDInfo.notify_led_event,
- currdriverstate != Adapter->DriverState || kthread_should_stop());
- }
-
- if(kthread_should_stop() || Adapter->device_removed )
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
- Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
- TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
- return ;//STATUS_FAILURE;
+ ((currdriverstate != FW_DOWNLOAD) &&
+ (currdriverstate != NORMAL_OPERATION) &&
+ (currdriverstate != LOWPOWER_MODE_ENTER))
+ ||
+ (currdriverstate == LED_THREAD_INACTIVE))
+ Status = wait_event_interruptible(
+ Adapter->LEDInfo.notify_led_event,
+ currdriverstate != Adapter->DriverState
+ || kthread_should_stop());
+
+ if (kthread_should_stop() || Adapter->device_removed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "Led thread got signal to exit..hence exiting");
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
+ TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
+ return; /* STATUS_FAILURE; */
}
- if(GPIO_num != DISABLE_GPIO_NUM)
- {
- TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
- }
+ if (GPIO_num != DISABLE_GPIO_NUM)
+ TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
- if(Adapter->LEDInfo.bLedInitDone == FALSE)
- {
+ if (Adapter->LEDInfo.bLedInitDone == FALSE) {
LedGpioInit(Adapter);
Adapter->LEDInfo.bLedInitDone = TRUE;
}
- switch(Adapter->DriverState)
- {
- case DRIVER_INIT:
- {
- currdriverstate = DRIVER_INIT;//Adapter->DriverState;
- BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate);
+ switch (Adapter->DriverState) {
+ case DRIVER_INIT:
+ currdriverstate = DRIVER_INIT;
+ /* Adapter->DriverState; */
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
+ &uiLedIndex, &dummyIndex, currdriverstate);
+
+ if (GPIO_num != DISABLE_GPIO_NUM)
+ TURN_ON_LED(1 << GPIO_num, uiLedIndex);
- if(GPIO_num != DISABLE_GPIO_NUM)
- {
- TURN_ON_LED(1<<GPIO_num, uiLedIndex);
- }
- }
break;
- case FW_DOWNLOAD:
- {
- //BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FW_DN_DONE called\n");
- currdriverstate = FW_DOWNLOAD;
- BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate);
-
- if(GPIO_num != DISABLE_GPIO_NUM)
- {
- timeout = 50;
- LED_Blink(Adapter, 1<<GPIO_num, uiLedIndex, timeout, -1,currdriverstate);
- }
+ case FW_DOWNLOAD:
+ /*
+ * BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ * LED_DUMP_INFO, DBG_LVL_ALL,
+ * "LED Thread: FW_DN_DONE called\n");
+ */
+ currdriverstate = FW_DOWNLOAD;
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
+ &uiLedIndex, &dummyIndex, currdriverstate);
+
+ if (GPIO_num != DISABLE_GPIO_NUM) {
+ timeout = 50;
+ LED_Blink(Adapter, 1 << GPIO_num, uiLedIndex,
+ timeout, -1, currdriverstate);
}
break;
- case FW_DOWNLOAD_DONE:
- {
- currdriverstate = FW_DOWNLOAD_DONE;
- BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex,currdriverstate);
- if(GPIO_num != DISABLE_GPIO_NUM)
- {
- TURN_ON_LED(1<<GPIO_num, uiLedIndex);
- }
- }
+ case FW_DOWNLOAD_DONE:
+ currdriverstate = FW_DOWNLOAD_DONE;
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
+ &uiLedIndex, &dummyIndex, currdriverstate);
+ if (GPIO_num != DISABLE_GPIO_NUM)
+ TURN_ON_LED(1 << GPIO_num, uiLedIndex);
break;
- case SHUTDOWN_EXIT:
- //no break, continue to NO_NETWORK_ENTRY state as well.
-
- case NO_NETWORK_ENTRY:
- {
- currdriverstate = NO_NETWORK_ENTRY;
- BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex,&dummyGPIONum,currdriverstate);
- if(GPIO_num != DISABLE_GPIO_NUM)
- {
- TURN_ON_LED(1<<GPIO_num, uiLedIndex);
- }
- }
+ case SHUTDOWN_EXIT:
+ /*
+ * no break, continue to NO_NETWORK_ENTRY
+ * state as well.
+ */
+ case NO_NETWORK_ENTRY:
+ currdriverstate = NO_NETWORK_ENTRY;
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
+ &uiLedIndex, &dummyGPIONum, currdriverstate);
+ if (GPIO_num != DISABLE_GPIO_NUM)
+ TURN_ON_LED(1 << GPIO_num, uiLedIndex);
break;
- case NORMAL_OPERATION:
+ case NORMAL_OPERATION:
{
UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
UCHAR uiLEDTx = 0;
UCHAR uiLEDRx = 0;
currdriverstate = NORMAL_OPERATION;
- Adapter->LEDInfo.bIdle_led_off = FALSE;
-
- BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiLEDTx,&uiLEDRx,currdriverstate);
- if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM))
- {
- GPIO_num = DISABLE_GPIO_NUM ;
- }
- else
- {
- /*If single LED is selected, use same for both Tx and Rx*/
- if(GPIO_num_tx == DISABLE_GPIO_NUM)
- {
+ Adapter->LEDInfo.bIdle_led_off = FALSE;
+
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx,
+ &GPIO_num_rx, &uiLEDTx, &uiLEDRx,
+ currdriverstate);
+ if ((GPIO_num_tx == DISABLE_GPIO_NUM) &&
+ (GPIO_num_rx ==
+ DISABLE_GPIO_NUM)) {
+ GPIO_num = DISABLE_GPIO_NUM;
+ } else {
+ /*
+ * If single LED is selected, use same
+ * for both Tx and Rx
+ */
+ if (GPIO_num_tx == DISABLE_GPIO_NUM) {
GPIO_num_tx = GPIO_num_rx;
uiLEDTx = uiLEDRx;
- }
- else if(GPIO_num_rx == DISABLE_GPIO_NUM)
- {
+ } else if (GPIO_num_rx ==
+ DISABLE_GPIO_NUM) {
GPIO_num_rx = GPIO_num_tx;
uiLEDRx = uiLEDTx;
}
- /*Blink the LED in proportionate to Tx and Rx transmissions.*/
- LED_Proportional_Blink(Adapter, GPIO_num_tx, uiLEDTx, GPIO_num_rx, uiLEDRx,currdriverstate);
+ /*
+ * Blink the LED in proportionate
+ * to Tx and Rx transmissions.
+ */
+ LED_Proportional_Blink(Adapter,
+ GPIO_num_tx, uiLEDTx,
+ GPIO_num_rx, uiLEDRx,
+ currdriverstate);
}
}
break;
- case LOWPOWER_MODE_ENTER:
- {
- currdriverstate = LOWPOWER_MODE_ENTER;
- if( DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING == Adapter->ulPowerSaveMode)
- {
- /* Turn OFF all the LED */
- uiResetValue = 0;
- for(uiIndex =0; uiIndex < NUM_OF_LEDS; uiIndex++)
- {
- if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
- TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
- }
-
+ case LOWPOWER_MODE_ENTER:
+ currdriverstate = LOWPOWER_MODE_ENTER;
+ if (DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING ==
+ Adapter->ulPowerSaveMode) {
+ /* Turn OFF all the LED */
+ uiResetValue = 0;
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
+ TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
}
- /* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
- Adapter->LEDInfo.bLedInitDone = FALSE;
- Adapter->LEDInfo.bIdle_led_off = TRUE;
- wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
- GPIO_num = DISABLE_GPIO_NUM;
- break;
- }
- case IDLEMODE_CONTINUE:
- {
- currdriverstate = IDLEMODE_CONTINUE;
- GPIO_num = DISABLE_GPIO_NUM;
+
}
+ /* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
+ Adapter->LEDInfo.bLedInitDone = FALSE;
+ Adapter->LEDInfo.bIdle_led_off = TRUE;
+ wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
+ GPIO_num = DISABLE_GPIO_NUM;
break;
- case IDLEMODE_EXIT:
- {
- }
+ case IDLEMODE_CONTINUE:
+ currdriverstate = IDLEMODE_CONTINUE;
+ GPIO_num = DISABLE_GPIO_NUM;
break;
- case DRIVER_HALT:
- {
- currdriverstate = DRIVER_HALT;
- GPIO_num = DISABLE_GPIO_NUM;
- for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
- {
- if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
- DISABLE_GPIO_NUM)
- TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
- }
- //Adapter->DriverState = DRIVER_INIT;
+ case IDLEMODE_EXIT:
+ break;
+ case DRIVER_HALT:
+ currdriverstate = DRIVER_HALT;
+ GPIO_num = DISABLE_GPIO_NUM;
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
+ != DISABLE_GPIO_NUM)
+ TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
}
+ /* Adapter->DriverState = DRIVER_INIT; */
break;
- case LED_THREAD_INACTIVE :
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"InActivating LED thread...");
- currdriverstate = LED_THREAD_INACTIVE;
- Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_INACTIVELY ;
- Adapter->LEDInfo.bLedInitDone = FALSE ;
- //disable ALL LED
- for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
- {
- if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
- DISABLE_GPIO_NUM)
- TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
- }
+ case LED_THREAD_INACTIVE:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "InActivating LED thread...");
+ currdriverstate = LED_THREAD_INACTIVE;
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_RUNNING_INACTIVELY;
+ Adapter->LEDInfo.bLedInitDone = FALSE;
+ /* disable ALL LED */
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
+ != DISABLE_GPIO_NUM)
+ TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
}
break;
- case LED_THREAD_ACTIVE :
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Activating LED thread again...");
- if(Adapter->LinkUpStatus == FALSE)
- Adapter->DriverState = NO_NETWORK_ENTRY;
- else
- Adapter->DriverState = NORMAL_OPERATION;
+ case LED_THREAD_ACTIVE:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "Activating LED thread again...");
+ if (Adapter->LinkUpStatus == FALSE)
+ Adapter->DriverState = NO_NETWORK_ENTRY;
+ else
+ Adapter->DriverState = NORMAL_OPERATION;
- Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY ;
- }
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_RUNNING_ACTIVELY;
+ break;
+ /* return; */
+ default:
break;
- //return;
- default:
- break;
}
}
Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
@@ -839,49 +863,54 @@ int InitLedSettings(PMINI_ADAPTER Adapter)
BOOLEAN bEnableThread = TRUE;
UCHAR uiIndex = 0;
- /*Initially set BitPolarity to normal polarity. The bit 8 of LED type
- * is used to change the polarity of the LED.*/
+ /*
+ * Initially set BitPolarity to normal polarity. The bit 8 of LED type
+ * is used to change the polarity of the LED.
+ */
- for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 1;
- }
- /*Read the LED settings of CONFIG file and map it to GPIO numbers in EEPROM*/
+ /*
+ * Read the LED settings of CONFIG file and map it
+ * to GPIO numbers in EEPROM
+ */
Status = ReadConfigFileStructure(Adapter, &bEnableThread);
- if(STATUS_SUCCESS != Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FAILED in ReadConfigFileStructure\n");
+ if (STATUS_SUCCESS != Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: FAILED in ReadConfigFileStructure\n");
return Status;
}
- if(Adapter->LEDInfo.led_thread_running)
- {
- if(bEnableThread)
+ if (Adapter->LEDInfo.led_thread_running) {
+ if (bEnableThread) {
;
- else
- {
+ } else {
Adapter->DriverState = DRIVER_HALT;
wake_up(&Adapter->LEDInfo.notify_led_event);
- Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
}
- }
-
- else if(bEnableThread)
- {
- /*Create secondary thread to handle the LEDs*/
+ } else if (bEnableThread) {
+ /* Create secondary thread to handle the LEDs */
init_waitqueue_head(&Adapter->LEDInfo.notify_led_event);
init_waitqueue_head(&Adapter->LEDInfo.idleModeSyncEvent);
- Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY;
- Adapter->LEDInfo.bIdle_led_off = FALSE;
- Adapter->LEDInfo.led_cntrl_threadid = kthread_run((int (*)(void *))
- LEDControlThread, Adapter, "led_control_thread");
- if(IS_ERR(Adapter->LEDInfo.led_cntrl_threadid))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Not able to spawn Kernel Thread\n");
- Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
- return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
- }
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_RUNNING_ACTIVELY;
+ Adapter->LEDInfo.bIdle_led_off = FALSE;
+ Adapter->LEDInfo.led_cntrl_threadid =
+ kthread_run((int (*)(void *)) LEDControlThread,
+ Adapter, "led_control_thread");
+ if (IS_ERR(Adapter->LEDInfo.led_cntrl_threadid)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "Not able to spawn Kernel Thread\n");
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
+ return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
+ }
}
return Status;
}
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
index 3de0daf5edb2..7d703cb3c5e0 100644
--- a/drivers/staging/bcm/nvm.c
+++ b/drivers/staging/bcm/nvm.c
@@ -78,7 +78,7 @@ static UCHAR ReadEEPROMStatusRegister( PMINI_ADAPTER Adapter )
{
value=0;
uiStatus = 0 ;
- rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&uiStatus, sizeof(uiStatus));
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
if(Adapter->device_removed == TRUE)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem has got removed hence exiting....");
@@ -93,7 +93,7 @@ static UCHAR ReadEEPROMStatusRegister( PMINI_ADAPTER Adapter )
wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
value =0;
- rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value));
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
uiData = (UCHAR)value;
break;
@@ -102,8 +102,8 @@ static UCHAR ReadEEPROMStatusRegister( PMINI_ADAPTER Adapter )
dwRetries-- ;
if ( dwRetries == 0 )
{
- rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value));
- rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG,&value1, sizeof(value1));
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1));
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"0x3004 = %x 0x3008 = %x, retries = %d failed.\n",value,value1, MAX_EEPROM_RETRIES*RETRIES_PER_DELAY);
return uiData;
}
@@ -158,7 +158,7 @@ INT ReadBeceemEEPROMBulk( PMINI_ADAPTER Adapter,
{
uiStatus = 0;
- rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
if(Adapter->device_removed == TRUE)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem has got Removed.hence exiting from loop...");
@@ -202,8 +202,8 @@ INT ReadBeceemEEPROMBulk( PMINI_ADAPTER Adapter,
{
value=0;
value1=0;
- rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value));
- rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG,&value1, sizeof(value1));
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1));
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "dwNumWords %d 0x3004 = %x 0x3008 = %x retries = %d failed.\n", dwNumWords, value, value1, MAX_EEPROM_RETRIES*RETRIES_PER_DELAY);
return STATUS_FAILURE;
}
@@ -217,22 +217,22 @@ INT ReadBeceemEEPROMBulk( PMINI_ADAPTER Adapter,
pvalue = (PUCHAR)(pdwData + dwIndex);
value =0;
- rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value));
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
pvalue[0] = value;
value = 0;
- rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value));
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
pvalue[1] = value;
value =0;
- rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value));
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
pvalue[2] = value;
value = 0;
- rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value));
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
pvalue[3] = value;
}
@@ -445,6 +445,7 @@ static INT BeceemFlashBulkRead(
UINT uiBytesToRead = uiNumBytes;
INT Status = 0;
UINT uiPartOffset = 0;
+ int bytes;
if(Adapter->device_removed )
{
@@ -469,9 +470,9 @@ static INT BeceemFlashBulkRead(
uiBytesToRead = MAX_RW_SIZE - (uiOffset%MAX_RW_SIZE);
uiBytesToRead = MIN(uiNumBytes,uiBytesToRead);
- if(rdm(Adapter,uiPartOffset, (PCHAR)pBuffer+uiIndex,uiBytesToRead))
- {
- Status = -1;
+ bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer+uiIndex, uiBytesToRead);
+ if (bytes < 0) {
+ Status = bytes;
Adapter->SelectedChip = RESET_CHIP_SELECT;
return Status;
}
@@ -488,9 +489,9 @@ static INT BeceemFlashBulkRead(
uiBytesToRead = MIN(uiNumBytes,MAX_RW_SIZE);
- if(rdm(Adapter,uiPartOffset, (PCHAR)pBuffer+uiIndex,uiBytesToRead))
- {
- Status = -1;
+ bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer+uiIndex, uiBytesToRead);
+ if (bytes < 0) {
+ Status = bytes;
break;
}
@@ -613,6 +614,7 @@ static INT FlashSectorErase(PMINI_ADAPTER Adapter,
UINT iIndex = 0, iRetries = 0;
UINT uiStatus = 0;
UINT value;
+ int bytes;
for(iIndex=0;iIndex<numOfSectors;iIndex++)
{
@@ -632,10 +634,11 @@ static INT FlashSectorErase(PMINI_ADAPTER Adapter,
return STATUS_FAILURE;
}
- if(rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)) < 0 )
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Reading status of FLASH_SPI_READQ_REG fails");
- return STATUS_FAILURE;
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
}
iRetries++;
//After every try lets make the CPU free for 10 ms. generally time taken by the
@@ -679,6 +682,7 @@ static INT flashByteWrite(
UINT value;
ULONG ulData = *(PUCHAR)pData;
+ int bytes;
//
// need not write 0xFF because write requires an erase and erase will
@@ -720,10 +724,11 @@ static INT flashByteWrite(
return STATUS_FAILURE;
}
//__udelay(1);
- if(rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)) < 0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Reading status of FLASH_SPI_READQ_REG fails");
- return STATUS_FAILURE;
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
}
iRetries--;
if( iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0))
@@ -771,6 +776,7 @@ static INT flashWrite(
UINT value;
UINT uiErasePattern[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
+ int bytes;
//
// need not write 0xFFFFFFFF because write requires an erase and erase will
// make whole sector 0xFFFFFFFF.
@@ -803,10 +809,11 @@ static INT flashWrite(
return STATUS_FAILURE;
}
//__udelay(1);
- if(rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)) < 0 )
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Reading status of FLASH_SPI_READQ_REG fails");
- return STATUS_FAILURE;
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
}
iRetries--;
@@ -849,6 +856,7 @@ static INT flashByteWriteStatus(
INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3
ULONG ulData = *(PUCHAR)pData;
UINT value;
+ int bytes;
//
// need not write 0xFFFFFFFF because write requires an erase and erase will
@@ -891,10 +899,11 @@ static INT flashByteWriteStatus(
return STATUS_FAILURE;
}
//__udelay(1);
- if(rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)) < 0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Reading status of FLASH_SPI_READQ_REG fails");
- return STATUS_FAILURE;
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
}
iRetries--;
@@ -935,6 +944,7 @@ static INT flashWriteStatus(
//UINT uiReadBack = 0;
UINT value;
UINT uiErasePattern[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
+ int bytes;
//
// need not write 0xFFFFFFFF because write requires an erase and erase will
@@ -967,10 +977,11 @@ static INT flashWriteStatus(
return STATUS_FAILURE;
}
//__udelay(1);
- if(rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)) < 0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Reading status of FLASH_SPI_READQ_REG fails");
- return STATUS_FAILURE;
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
}
iRetries--;
//this will ensure that in there will be no changes in the current path.
@@ -1841,7 +1852,7 @@ static INT BeceemEEPROMWritePage( PMINI_ADAPTER Adapter, UINT uiData[], UINT uiO
* What we are checking if the previous write has completed, and this
* may take time. We should wait till the Empty bit is set. */
uiStatus = 0;
- rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&uiStatus, sizeof(uiStatus)) ;
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
while ( ( uiStatus & EEPROM_WRITE_QUEUE_EMPTY ) == 0 )
{
uiRetries--;
@@ -1855,7 +1866,7 @@ static INT BeceemEEPROMWritePage( PMINI_ADAPTER Adapter, UINT uiData[], UINT uiO
msleep(1);
uiStatus = 0;
- rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&uiStatus, sizeof(uiStatus)) ;
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
if(Adapter->device_removed == TRUE)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem got removed hence exiting from loop....");
@@ -2500,7 +2511,7 @@ static ULONG BcmReadFlashRDID(PMINI_ADAPTER Adapter)
// Read SPI READQ REG. The output will be WWXXYYZZ.
// The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored.
//
- rdmalt(Adapter, FLASH_SPI_READQ_REG,(PUINT)&ulRDID, sizeof(ulRDID));
+ rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID));
return (ulRDID >>8);
@@ -4735,8 +4746,8 @@ static INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset)
Adapter->SelectedChip = ChipNum ;
//bit[13..12] will select the appropriate chip
- rdmalt(Adapter,FLASH_CONFIG_REG, &FlashConfig, 4);
- rdmalt(Adapter,FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4);
+ rdmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4);
+ rdmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4);
{
switch(ChipNum)
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 5e78c77d5a08..0d18d80bcd25 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1479,10 +1479,10 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
dev_file_info = comedi_get_device_file_info(minor);
if (dev_file_info == NULL)
- return -ENODEV;
+ return -ENODEV;
dev = dev_file_info->device;
if (dev == NULL)
- return -ENODEV;
+ return -ENODEV;
mutex_lock(&dev->mutex);
if (!dev->attached) {
@@ -1556,10 +1556,10 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait)
dev_file_info = comedi_get_device_file_info(minor);
if (dev_file_info == NULL)
- return -ENODEV;
+ return -ENODEV;
dev = dev_file_info->device;
if (dev == NULL)
- return -ENODEV;
+ return -ENODEV;
mutex_lock(&dev->mutex);
if (!dev->attached) {
@@ -1610,10 +1610,10 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
dev_file_info = comedi_get_device_file_info(minor);
if (dev_file_info == NULL)
- return -ENODEV;
+ return -ENODEV;
dev = dev_file_info->device;
if (dev == NULL)
- return -ENODEV;
+ return -ENODEV;
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
@@ -1721,10 +1721,10 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
dev_file_info = comedi_get_device_file_info(minor);
if (dev_file_info == NULL)
- return -ENODEV;
+ return -ENODEV;
dev = dev_file_info->device;
if (dev == NULL)
- return -ENODEV;
+ return -ENODEV;
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
@@ -1931,10 +1931,10 @@ static int comedi_close(struct inode *inode, struct file *file)
dev_file_info = comedi_get_device_file_info(minor);
if (dev_file_info == NULL)
- return -ENODEV;
+ return -ENODEV;
dev = dev_file_info->device;
if (dev == NULL)
- return -ENODEV;
+ return -ENODEV;
mutex_lock(&dev->mutex);
@@ -1973,10 +1973,10 @@ static int comedi_fasync(int fd, struct file *file, int on)
dev_file_info = comedi_get_device_file_info(minor);
if (dev_file_info == NULL)
- return -ENODEV;
+ return -ENODEV;
dev = dev_file_info->device;
if (dev == NULL)
- return -ENODEV;
+ return -ENODEV;
return fasync_helper(fd, file, on, &dev->async_queue);
}
@@ -2479,18 +2479,18 @@ static ssize_t store_max_read_buffer_kb(struct device *dev,
const char *buf, size_t count)
{
struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned long new_max_size_kb;
- uint64_t new_max_size;
+ unsigned int new_max_size_kb;
+ unsigned int new_max_size;
+ int ret;
struct comedi_subdevice *const read_subdevice =
comedi_get_read_subdevice(info);
- if (strict_strtoul(buf, 10, &new_max_size_kb))
- return -EINVAL;
- if (new_max_size_kb != (uint32_t) new_max_size_kb)
- return -EINVAL;
- new_max_size = ((uint64_t) new_max_size_kb) * bytes_per_kibi;
- if (new_max_size != (uint32_t) new_max_size)
+ ret = kstrtouint(buf, 10, &new_max_size_kb);
+ if (ret)
+ return ret;
+ if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
return -EINVAL;
+ new_max_size = new_max_size_kb * bytes_per_kibi;
mutex_lock(&info->device->mutex);
if (read_subdevice == NULL ||
@@ -2540,19 +2540,19 @@ static ssize_t store_read_buffer_kb(struct device *dev,
const char *buf, size_t count)
{
struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned long new_size_kb;
- uint64_t new_size;
+ unsigned int new_size_kb;
+ unsigned int new_size;
int retval;
+ int ret;
struct comedi_subdevice *const read_subdevice =
comedi_get_read_subdevice(info);
- if (strict_strtoul(buf, 10, &new_size_kb))
- return -EINVAL;
- if (new_size_kb != (uint32_t) new_size_kb)
- return -EINVAL;
- new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
- if (new_size != (uint32_t) new_size)
+ ret = kstrtouint(buf, 10, &new_size_kb);
+ if (ret)
+ return ret;
+ if (new_size_kb > (UINT_MAX / bytes_per_kibi))
return -EINVAL;
+ new_size = new_size_kb * bytes_per_kibi;
mutex_lock(&info->device->mutex);
if (read_subdevice == NULL ||
@@ -2606,18 +2606,18 @@ static ssize_t store_max_write_buffer_kb(struct device *dev,
const char *buf, size_t count)
{
struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned long new_max_size_kb;
- uint64_t new_max_size;
+ unsigned int new_max_size_kb;
+ unsigned int new_max_size;
+ int ret;
struct comedi_subdevice *const write_subdevice =
comedi_get_write_subdevice(info);
- if (strict_strtoul(buf, 10, &new_max_size_kb))
- return -EINVAL;
- if (new_max_size_kb != (uint32_t) new_max_size_kb)
- return -EINVAL;
- new_max_size = ((uint64_t) new_max_size_kb) * bytes_per_kibi;
- if (new_max_size != (uint32_t) new_max_size)
+ ret = kstrtouint(buf, 10, &new_max_size_kb);
+ if (ret)
+ return ret;
+ if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
return -EINVAL;
+ new_max_size = new_max_size_kb * bytes_per_kibi;
mutex_lock(&info->device->mutex);
if (write_subdevice == NULL ||
@@ -2667,19 +2667,19 @@ static ssize_t store_write_buffer_kb(struct device *dev,
const char *buf, size_t count)
{
struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned long new_size_kb;
- uint64_t new_size;
+ unsigned int new_size_kb;
+ unsigned int new_size;
int retval;
+ int ret;
struct comedi_subdevice *const write_subdevice =
comedi_get_write_subdevice(info);
- if (strict_strtoul(buf, 10, &new_size_kb))
- return -EINVAL;
- if (new_size_kb != (uint32_t) new_size_kb)
+ ret = kstrtouint(buf, 10, &new_size_kb);
+ if (ret)
+ return ret;
+ if (new_size_kb > (UINT_MAX / bytes_per_kibi))
return -EINVAL;
new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
- if (new_size != (uint32_t) new_size)
- return -EINVAL;
mutex_lock(&info->device->mutex);
if (write_subdevice == NULL ||
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 6fb7594319c6..ca5bd9b8704a 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -145,78 +145,77 @@ void fpu_end(void)
static DEFINE_PCI_DEVICE_TABLE(addi_apci_tbl) = {
#ifdef CONFIG_APCI_3120
- {APCI3120_BOARD_VENDOR_ID, 0x818D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI3120_BOARD_VENDOR_ID, 0x818D)},
#endif
#ifdef CONFIG_APCI_1032
- {APCI1032_BOARD_VENDOR_ID, 0x1003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI1032_BOARD_VENDOR_ID, 0x1003)},
#endif
#ifdef CONFIG_APCI_1516
- {APCI1516_BOARD_VENDOR_ID, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI1516_BOARD_VENDOR_ID, 0x1001)},
#endif
#ifdef CONFIG_APCI_2016
- {APCI2016_BOARD_VENDOR_ID, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI2016_BOARD_VENDOR_ID, 0x1002)},
#endif
#ifdef CONFIG_APCI_2032
- {APCI2032_BOARD_VENDOR_ID, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI2032_BOARD_VENDOR_ID, 0x1004)},
#endif
#ifdef CONFIG_APCI_2200
- {APCI2200_BOARD_VENDOR_ID, 0x1005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI2200_BOARD_VENDOR_ID, 0x1005)},
#endif
#ifdef CONFIG_APCI_1564
- {APCI1564_BOARD_VENDOR_ID, 0x1006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI1564_BOARD_VENDOR_ID, 0x1006)},
#endif
#ifdef CONFIG_APCI_1500
- {APCI1500_BOARD_VENDOR_ID, 0x80fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI1500_BOARD_VENDOR_ID, 0x80fc)},
#endif
#ifdef CONFIG_APCI_3001
- {APCI3120_BOARD_VENDOR_ID, 0x828D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI3120_BOARD_VENDOR_ID, 0x828D)},
#endif
#ifdef CONFIG_APCI_3501
- {APCI3501_BOARD_VENDOR_ID, 0x3001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI3501_BOARD_VENDOR_ID, 0x3001)},
#endif
#ifdef CONFIG_APCI_035
- {APCI035_BOARD_VENDOR_ID, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI035_BOARD_VENDOR_ID, 0x0300)},
#endif
#ifdef CONFIG_APCI_3200
- {APCI3200_BOARD_VENDOR_ID, 0x3000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI3200_BOARD_VENDOR_ID, 0x3000)},
#endif
#ifdef CONFIG_APCI_3300
- {APCI3200_BOARD_VENDOR_ID, 0x3007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI3200_BOARD_VENDOR_ID, 0x3007)},
#endif
#ifdef CONFIG_APCI_1710
- {APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID)},
#endif
#ifdef CONFIG_APCI_16XX
- {0x15B8, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x100A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1009)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x100A)},
#endif
#ifdef CONFIG_APCI_3XXX
- {0x15B8, 0x3010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x300F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x300E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x301A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x301B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x301C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x301D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x301E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x301F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x300B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x15B8, 0x3024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3010)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300F)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300E)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3013)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3014)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3015)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3016)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3017)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3018)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3019)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301A)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301B)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301C)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301D)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301E)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301F)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3020)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3021)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3022)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3023)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300B)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3002)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3003)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3004)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3024)},
#endif
{0}
};
@@ -1019,7 +1018,7 @@ static const struct addi_board boardtypes[] = {
#endif
#ifdef CONFIG_APCI_16XX
{"apci1648",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x1009,
128,
0,
@@ -1075,7 +1074,7 @@ static const struct addi_board boardtypes[] = {
i_APCI16XX_InsnBitsWriteTTLIO},
{"apci1696",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x100A,
128,
0,
@@ -1132,7 +1131,7 @@ static const struct addi_board boardtypes[] = {
#endif
#ifdef CONFIG_APCI_3XXX
{"apci3000-16",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3010,
256,
256,
@@ -1188,7 +1187,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3000-8",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x300F,
256,
256,
@@ -1244,7 +1243,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3000-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x300E,
256,
256,
@@ -1300,7 +1299,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3006-16",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3013,
256,
256,
@@ -1356,7 +1355,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3006-8",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3014,
256,
256,
@@ -1412,7 +1411,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3006-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3015,
256,
256,
@@ -1468,7 +1467,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3010-16",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3016,
256,
256,
@@ -1524,7 +1523,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3010-8",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3017,
256,
256,
@@ -1580,7 +1579,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3010-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3018,
256,
256,
@@ -1636,7 +1635,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3016-16",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3019,
256,
256,
@@ -1692,7 +1691,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3016-8",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x301A,
256,
256,
@@ -1748,7 +1747,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3016-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x301B,
256,
256,
@@ -1804,7 +1803,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3100-16-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x301C,
256,
256,
@@ -1860,7 +1859,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3100-8-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x301D,
256,
256,
@@ -1916,7 +1915,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3106-16-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x301E,
256,
256,
@@ -1972,7 +1971,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3106-8-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x301F,
256,
256,
@@ -2028,7 +2027,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3110-16-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3020,
256,
256,
@@ -2084,7 +2083,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3110-8-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3021,
256,
256,
@@ -2140,7 +2139,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3116-16-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3022,
256,
256,
@@ -2196,7 +2195,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3116-8-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3023,
256,
256,
@@ -2252,7 +2251,7 @@ static const struct addi_board boardtypes[] = {
i_APCI3XXX_InsnWriteTTLIO},
{"apci3003",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x300B,
256,
256,
@@ -2307,7 +2306,7 @@ static const struct addi_board boardtypes[] = {
NULL},
{"apci3002-16",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3002,
256,
256,
@@ -2362,7 +2361,7 @@ static const struct addi_board boardtypes[] = {
NULL},
{"apci3002-8",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3003,
256,
256,
@@ -2417,7 +2416,7 @@ static const struct addi_board boardtypes[] = {
NULL},
{"apci3002-4",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3004,
256,
256,
@@ -2472,7 +2471,7 @@ static const struct addi_board boardtypes[] = {
NULL},
{"apci3500",
- 0x15B8,
+ PCI_VENDOR_ID_ADDIDATA,
0x3024,
256,
256,
diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c
index 72a7258b5b92..20d570554fa4 100644
--- a/drivers/staging/comedi/drivers/adl_pci7230.c
+++ b/drivers/staging/comedi/drivers/adl_pci7230.c
@@ -44,15 +44,7 @@ Configuration Options:
#define PCI_DEVICE_ID_PCI7230 0x7230
static DEFINE_PCI_DEVICE_TABLE(adl_pci7230_pci_table) = {
- {
- PCI_VENDOR_ID_ADLINK,
- PCI_DEVICE_ID_PCI7230,
- PCI_ANY_ID,
- PCI_ANY_ID,
- 0,
- 0,
- 0
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
{0}
};
diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
index f28fe6bec050..9a2320537bdb 100644
--- a/drivers/staging/comedi/drivers/adl_pci7296.c
+++ b/drivers/staging/comedi/drivers/adl_pci7296.c
@@ -49,10 +49,8 @@ Configuration Options:
#define PCI_DEVICE_ID_PCI7296 0x7296
static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = {
- {
- PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table);
diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
index 262da7b29b28..86ee21976041 100644
--- a/drivers/staging/comedi/drivers/adl_pci7432.c
+++ b/drivers/staging/comedi/drivers/adl_pci7432.c
@@ -44,10 +44,8 @@ Configuration Options:
#define PCI_DEVICE_ID_PCI7432 0x7432
static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = {
- {
- PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
index 767a594935c7..3b83d65bc1bc 100644
--- a/drivers/staging/comedi/drivers/adl_pci8164.c
+++ b/drivers/staging/comedi/drivers/adl_pci8164.c
@@ -57,10 +57,8 @@ Configuration Options:
#define PCI_DEVICE_ID_PCI8164 0x8164
static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = {
- {
- PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table);
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index fc48bae42ab7..2a9bd88a4abb 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -311,10 +311,8 @@ static const struct comedi_lrange pci9111_hr_ai_range = {
};
static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
- { PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
- 0, 0, 0 },
- /* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
- * 0, 0, 0 }, */
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
+ /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
{ 0 }
};
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index da2b75b15d4e..8318c82a555a 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -1382,16 +1382,14 @@ static int pci1710_attach(struct comedi_device *dev,
int i;
int board_index;
- printk("comedi%d: adv_pci1710: ", dev->minor);
+ dev_info(dev->hw_dev, "comedi%d: adv_pci1710:\n", dev->minor);
opt_bus = it->options[0];
opt_slot = it->options[1];
ret = alloc_private(dev, sizeof(struct pci1710_private));
- if (ret < 0) {
- printk(" - Allocation failed!\n");
+ if (ret < 0)
return -ENOMEM;
- }
/* Look for matching PCI device */
errstr = "not found!";
@@ -1436,10 +1434,10 @@ static int pci1710_attach(struct comedi_device *dev,
if (!pcidev) {
if (opt_bus || opt_slot) {
- printk(" - Card at b:s %d:%d %s\n",
- opt_bus, opt_slot, errstr);
+ dev_err(dev->hw_dev, "- Card at b:s %d:%d %s\n",
+ opt_bus, opt_slot, errstr);
} else {
- printk(" - Card %s\n", errstr);
+ dev_err(dev->hw_dev, "- Card %s\n", errstr);
}
return -EIO;
}
@@ -1450,8 +1448,8 @@ static int pci1710_attach(struct comedi_device *dev,
irq = pcidev->irq;
iobase = pci_resource_start(pcidev, 2);
- printk(", b:s:f=%d:%d:%d, io=0x%4lx", pci_bus, pci_slot, pci_func,
- iobase);
+ dev_dbg(dev->hw_dev, "b:s:f=%d:%d:%d, io=0x%4lx\n", pci_bus, pci_slot,
+ pci_func, iobase);
dev->iobase = iobase;
@@ -1471,10 +1469,8 @@ static int pci1710_attach(struct comedi_device *dev,
n_subdevices++;
ret = alloc_subdevices(dev, n_subdevices);
- if (ret < 0) {
- printk(" - Allocation failed!\n");
+ if (ret < 0)
return ret;
- }
pci1710_reset(dev);
@@ -1483,24 +1479,20 @@ static int pci1710_attach(struct comedi_device *dev,
if (request_irq(irq, interrupt_service_pci1710,
IRQF_SHARED, "Advantech PCI-1710",
dev)) {
- printk
- (", unable to allocate IRQ %d, DISABLING IT",
- irq);
+ dev_dbg(dev->hw_dev, "unable to allocate IRQ %d, DISABLING IT",
+ irq);
irq = 0; /* Can't use IRQ */
} else {
- printk(", irq=%u", irq);
+ dev_dbg(dev->hw_dev, "irq=%u", irq);
}
} else {
- printk(", IRQ disabled");
+ dev_dbg(dev->hw_dev, "IRQ disabled");
}
} else {
irq = 0;
}
dev->irq = irq;
-
- printk(".\n");
-
subdev = 0;
if (this_board->n_aichan) {
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 69334f6f64e8..537e58534275 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -1106,13 +1106,10 @@ static int pci_dio_attach(struct comedi_device *dev,
unsigned long iobase;
struct pci_dev *pcidev = NULL;
- printk("comedi%d: adv_pci_dio: ", dev->minor);
ret = alloc_private(dev, sizeof(struct pci_dio_private));
- if (ret < 0) {
- printk(", Error: Cann't allocate private memory!\n");
+ if (ret < 0)
return -ENOMEM;
- }
for_each_pci_dev(pcidev) {
/* loop through cards supported by this driver */
@@ -1140,19 +1137,18 @@ static int pci_dio_attach(struct comedi_device *dev,
}
if (!dev->board_ptr) {
- printk(", Error: Requested type of the card was not found!\n");
+ dev_err(dev->hw_dev, "Error: Requested type of the card was not found!\n");
return -EIO;
}
if (comedi_pci_enable(pcidev, driver_pci_dio.driver_name)) {
- printk
- (", Error: Can't enable PCI device and request regions!\n");
+ dev_err(dev->hw_dev, "Error: Can't enable PCI device and request regions!\n");
return -EIO;
}
iobase = pci_resource_start(pcidev, this_board->main_pci_region);
- printk(", b:s:f=%d:%d:%d, io=0x%4lx",
- pcidev->bus->number, PCI_SLOT(pcidev->devfn),
- PCI_FUNC(pcidev->devfn), iobase);
+ dev_dbg(dev->hw_dev, "b:s:f=%d:%d:%d, io=0x%4lx\n",
+ pcidev->bus->number, PCI_SLOT(pcidev->devfn),
+ PCI_FUNC(pcidev->devfn), iobase);
dev->iobase = iobase;
dev->board_name = this_board->name;
@@ -1177,15 +1173,10 @@ static int pci_dio_attach(struct comedi_device *dev,
}
ret = alloc_subdevices(dev, n_subdevices);
- if (ret < 0) {
- printk(", Error: Cann't allocate subdevice memory!\n");
+ if (ret < 0)
return ret;
- }
-
- printk(".\n");
subdev = 0;
-
for (i = 0; i < MAX_DI_SUBDEVS; i++)
if (this_board->sdi[i].chans) {
s = dev->subdevices + subdev;
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 93bbe4ec318d..566cc4411452 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -421,12 +421,9 @@ static const struct dio200_layout_struct dio200_layouts[] = {
#ifdef CONFIG_COMEDI_PCI
static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
- {
- PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, dio200_pci_table);
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 48246cd50d47..7972cadd403e 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -134,10 +134,8 @@ static const struct pc236_board pc236_boards[] = {
#ifdef CONFIG_COMEDI_PCI
static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = {
- {
- PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, pc236_pci_table);
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index 8a3388079094..191ac0d23ce7 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -101,10 +101,8 @@ static const struct pc263_board pc263_boards[] = {
#ifdef CONFIG_COMEDI_PCI
static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = {
- {
- PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, pc263_pci_table);
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index 1b5ba1c27259..b278917cec25 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -384,12 +384,9 @@ static const struct pci224_board pci224_boards[] = {
*/
static DEFINE_PCI_DEVICE_TABLE(pci224_pci_table) = {
- {
- PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, pci224_pci_table);
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 7edeb1103dc8..538979551c8e 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -501,12 +501,9 @@ static const struct pci230_board pci230_boards[] = {
};
static DEFINE_PCI_DEVICE_TABLE(pci230_pci_table) = {
- {
- PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0}, {
- PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, pci230_pci_table);
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index e171c56112d8..49404f49f7b7 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -99,7 +99,7 @@ static struct comedi_driver driver_das16cs = {
.detach = das16cs_detach,
};
-static struct pcmcia_device *cur_dev = NULL;
+static struct pcmcia_device *cur_dev;
static const struct comedi_lrange das16cs_ai_range = { 4, {
RANGE(-10, 10),
@@ -150,7 +150,7 @@ static const struct das16cs_board *das16cs_probe(struct comedi_device *dev,
return das16cs_boards + i;
}
- printk("unknown board!\n");
+ dev_dbg(dev->hw_dev, "unknown board!\n");
return NULL;
}
@@ -163,20 +163,19 @@ static int das16cs_attach(struct comedi_device *dev,
int ret;
int i;
- printk("comedi%d: cb_das16_cs: ", dev->minor);
+ dev_dbg(dev->hw_dev, "comedi%d: cb_das16_cs: attached\n", dev->minor);
link = cur_dev; /* XXX hack */
if (!link)
return -EIO;
dev->iobase = link->resource[0]->start;
- printk("I/O base=0x%04lx ", dev->iobase);
+ dev_dbg(dev->hw_dev, "I/O base=0x%04lx\n", dev->iobase);
- printk("fingerprint:\n");
+ dev_dbg(dev->hw_dev, "fingerprint:\n");
for (i = 0; i < 48; i += 2)
- printk("%04x ", inw(dev->iobase + i));
+ dev_dbg(dev->hw_dev, "%04x\n", inw(dev->iobase + i));
- printk("\n");
ret = request_irq(link->irq, das16cs_interrupt,
IRQF_SHARED, "cb_das16_cs", dev);
@@ -185,7 +184,7 @@ static int das16cs_attach(struct comedi_device *dev,
dev->irq = link->irq;
- printk("irq=%u ", dev->irq);
+ dev_dbg(dev->hw_dev, "irq=%u\n", dev->irq);
dev->board_ptr = das16cs_probe(dev, link);
if (!dev->board_ptr)
@@ -252,14 +251,13 @@ static int das16cs_attach(struct comedi_device *dev,
s->type = COMEDI_SUBD_UNUSED;
}
- printk("attached\n");
return 1;
}
static int das16cs_detach(struct comedi_device *dev)
{
- printk("comedi%d: das16cs: remove\n", dev->minor);
+ dev_dbg(dev->hw_dev, "comedi%d: das16cs: remove\n", dev->minor);
if (dev->irq)
free_irq(dev->irq, dev);
@@ -312,7 +310,7 @@ static int das16cs_ai_rinsn(struct comedi_device *dev,
break;
}
if (to == TIMEOUT) {
- printk("cb_das16_cs: ai timeout\n");
+ dev_dbg(dev->hw_dev, "cb_das16_cs: ai timeout\n");
return -ETIME;
}
data[i] = (unsigned short)inw(dev->iobase + 0);
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 61968a505f24..7e4ffcfdac62 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -565,8 +565,6 @@ static int cb_pcidas_attach(struct comedi_device *dev,
int index;
int i;
- printk("comedi%d: cb_pcidas: ", dev->minor);
-
/*
* Allocate the private structure area.
*/
@@ -576,7 +574,6 @@ static int cb_pcidas_attach(struct comedi_device *dev,
/*
* Probe the device to determine what device in the series it is.
*/
- printk("\n");
for_each_pci_dev(pcidev) {
/* is it not a computer boards card? */
@@ -600,20 +597,20 @@ static int cb_pcidas_attach(struct comedi_device *dev,
}
}
- printk("No supported ComputerBoards/MeasurementComputing card found on "
- "requested position\n");
+ dev_err(dev->hw_dev, "No supported ComputerBoards/MeasurementComputing card found on requested position\n");
return -EIO;
found:
- printk("Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name,
- pcidev->bus->number, PCI_SLOT(pcidev->devfn));
+ dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n",
+ cb_pcidas_boards[index].name, pcidev->bus->number,
+ PCI_SLOT(pcidev->devfn));
/*
* Enable PCI device and reserve I/O ports.
*/
if (comedi_pci_enable(pcidev, "cb_pcidas")) {
- printk(" Failed to enable PCI device and request regions\n");
+ dev_err(dev->hw_dev, "Failed to enable PCI device and request regions\n");
return -EIO;
}
/*
@@ -639,7 +636,8 @@ found:
/* get irq */
if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt,
IRQF_SHARED, "cb_pcidas", dev)) {
- printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq);
+ dev_dbg(dev->hw_dev, "unable to allocate irq %d\n",
+ devpriv->pci_dev->irq);
return -EINVAL;
}
dev->irq = devpriv->pci_dev->irq;
@@ -768,7 +766,6 @@ found:
*/
static int cb_pcidas_detach(struct comedi_device *dev)
{
- printk("comedi%d: cb_pcidas: remove\n", dev->minor);
if (devpriv) {
if (devpriv->s5933_config) {
@@ -776,8 +773,8 @@ static int cb_pcidas_detach(struct comedi_device *dev)
outl(INTCSR_INBOX_INTR_STATUS,
devpriv->s5933_config + AMCC_OP_REG_INTCSR);
#ifdef CB_PCIDAS_DEBUG
- printk("detaching, incsr is 0x%x\n",
- inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR));
+ dev_dbg(dev->hw_dev, "detaching, incsr is 0x%x\n",
+ inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR));
#endif
}
}
@@ -858,7 +855,8 @@ static int ai_config_calibration_source(struct comedi_device *dev,
unsigned int source = data[1];
if (source >= num_calibration_sources) {
- printk("invalid calibration source: %i\n", source);
+ dev_err(dev->hw_dev, "invalid calibration source: %i\n",
+ source);
return -EINVAL;
}
@@ -1279,7 +1277,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
outw(bits, devpriv->control_status + ADCMUX_CONT);
#ifdef CB_PCIDAS_DEBUG
- printk("comedi: sent 0x%x to adcmux control\n", bits);
+ dev_dbg(dev->hw_dev, "comedi: sent 0x%x to adcmux control\n", bits);
#endif
/* load counters */
@@ -1306,7 +1304,8 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
devpriv->adc_fifo_bits |= INT_FHF; /* interrupt fifo half full */
}
#ifdef CB_PCIDAS_DEBUG
- printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
+ dev_dbg(dev->hw_dev, "comedi: adc_fifo_bits are 0x%x\n",
+ devpriv->adc_fifo_bits);
#endif
/* enable (and clear) interrupts */
outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
@@ -1332,7 +1331,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
bits |= BURSTE;
outw(bits, devpriv->control_status + TRIG_CONTSTAT);
#ifdef CB_PCIDAS_DEBUG
- printk("comedi: sent 0x%x to trig control\n", bits);
+ dev_dbg(dev->hw_dev, "comedi: sent 0x%x to trig control\n", bits);
#endif
return 0;
@@ -1549,7 +1548,8 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
#ifdef CB_PCIDAS_DEBUG
- printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
+ dev_dbg(dev->hw_dev, "comedi: adc_fifo_bits are 0x%x\n",
+ devpriv->adc_fifo_bits);
#endif
/* enable and clear interrupts */
outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
@@ -1559,7 +1559,8 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
#ifdef CB_PCIDAS_DEBUG
- printk("comedi: sent 0x%x to dac control\n", devpriv->ao_control_bits);
+ dev_dbg(dev->hw_dev, "comedi: sent 0x%x to dac control\n",
+ devpriv->ao_control_bits);
#endif
spin_unlock_irqrestore(&dev->spinlock, flags);
@@ -1587,8 +1588,9 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
#ifdef CB_PCIDAS_DEBUG
- printk("intcsr 0x%x\n", s5933_status);
- printk("mbef 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_MBEF));
+ dev_dbg(dev->hw_dev, "intcsr 0x%x\n", s5933_status);
+ dev_dbg(dev->hw_dev, "mbef 0x%x\n",
+ inl(devpriv->s5933_config + AMCC_OP_REG_MBEF));
#endif
if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 1e324198996c..c9e8c4785768 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -1739,8 +1739,6 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
uint32_t local_range, local_decode;
int retval;
- printk("comedi%d: cb_pcidas64\n", dev->minor);
-
/*
* Allocate the private structure area.
*/
@@ -1781,12 +1779,11 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
return -EIO;
}
- printk("Found %s on bus %i, slot %i\n", board(dev)->name,
- pcidev->bus->number, PCI_SLOT(pcidev->devfn));
+ dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n", board(dev)->name,
+ pcidev->bus->number, PCI_SLOT(pcidev->devfn));
if (comedi_pci_enable(pcidev, driver_cb_pcidas.driver_name)) {
- printk(KERN_WARNING
- " failed to enable PCI device and request regions\n");
+ dev_warn(dev->hw_dev, "failed to enable PCI device and request regions\n");
return -EIO;
}
pci_set_master(pcidev);
@@ -1814,7 +1811,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!priv(dev)->plx9080_iobase || !priv(dev)->main_iobase
|| !priv(dev)->dio_counter_iobase) {
- printk(" failed to remap io memory\n");
+ dev_warn(dev->hw_dev, "failed to remap io memory\n");
return -ENOMEM;
}
@@ -1850,17 +1847,19 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
priv(dev)->hw_revision =
hw_revision(dev, readw(priv(dev)->main_iobase + HW_STATUS_REG));
- printk(" stc hardware revision %i\n", priv(dev)->hw_revision);
+ dev_dbg(dev->hw_dev, "stc hardware revision %i\n",
+ priv(dev)->hw_revision);
init_plx9080(dev);
init_stc_registers(dev);
/* get irq */
if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
"cb_pcidas64", dev)) {
- printk(" unable to allocate irq %u\n", pcidev->irq);
+ dev_dbg(dev->hw_dev, "unable to allocate irq %u\n",
+ pcidev->irq);
return -EINVAL;
}
dev->irq = pcidev->irq;
- printk(" irq %u\n", dev->irq);
+ dev_dbg(dev->hw_dev, "irq %u\n", dev->irq);
retval = setup_subdevices(dev);
if (retval < 0)
@@ -1882,8 +1881,6 @@ static int detach(struct comedi_device *dev)
{
unsigned int i;
- printk("comedi%d: cb_pcidas: remove\n", dev->minor);
-
if (dev->irq)
free_irq(dev->irq, dev);
if (priv(dev)) {
@@ -2093,7 +2090,8 @@ static int ai_config_calibration_source(struct comedi_device *dev,
else
num_calibration_sources = 8;
if (source >= num_calibration_sources) {
- printk("invalid calibration source: %i\n", source);
+ dev_dbg(dev->hw_dev, "invalid calibration source: %i\n",
+ source);
return -EINVAL;
}
@@ -2924,7 +2922,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
}
if (num_samples < 0) {
- printk(" cb_pcidas64: bug! num_samples < 0\n");
+ dev_err(dev->hw_dev, "cb_pcidas64: bug! num_samples < 0\n");
break;
}
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 49102b3a6c4a..abba220a767f 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -282,7 +282,6 @@ static int cb_pcidda_attach(struct comedi_device *dev,
struct pci_dev *pcidev = NULL;
int index;
- printk("comedi%d: cb_pcidda: ", dev->minor);
/*
* Allocate the private structure area.
@@ -293,7 +292,6 @@ static int cb_pcidda_attach(struct comedi_device *dev,
/*
* Probe the device to determine what device in the series it is.
*/
- printk("\n");
for_each_pci_dev(pcidev) {
if (pcidev->vendor == PCI_VENDOR_ID_CB) {
@@ -312,22 +310,21 @@ static int cb_pcidda_attach(struct comedi_device *dev,
}
}
if (!pcidev) {
- printk
- ("Not a ComputerBoards/MeasurementComputing card on requested position\n");
+ dev_err(dev->hw_dev, "Not a ComputerBoards/MeasurementComputing card on requested position\n");
return -EIO;
}
found:
devpriv->pci_dev = pcidev;
dev->board_ptr = cb_pcidda_boards + index;
/* "thisboard" macro can be used from here. */
- printk("Found %s at requested position\n", thisboard->name);
+ dev_dbg(dev->hw_dev, "Found %s at requested position\n",
+ thisboard->name);
/*
* Enable PCI device and request regions.
*/
if (comedi_pci_enable(pcidev, thisboard->name)) {
- printk
- ("cb_pcidda: failed to enable PCI device and request regions\n");
+ dev_err(dev->hw_dev, "cb_pcidda: failed to enable PCI device and request regions\n");
return -EIO;
}
@@ -377,12 +374,11 @@ found:
s = dev->subdevices + 2;
subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
- printk(" eeprom:");
+ dev_dbg(dev->hw_dev, "eeprom:\n");
for (index = 0; index < EEPROM_SIZE; index++) {
devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
- printk(" %i:0x%x ", index, devpriv->eeprom_data[index]);
+ dev_dbg(dev->hw_dev, "%i:0x%x\n", index, devpriv->eeprom_data[index]);
}
- printk("\n");
/* set calibrations dacs */
for (index = 0; index < thisboard->ao_chans; index++)
@@ -417,8 +413,6 @@ static int cb_pcidda_detach(struct comedi_device *dev)
subdev_8255_cleanup(dev, dev->subdevices + 2);
}
- printk("comedi%d: cb_pcidda: remove\n", dev->minor);
-
return 0;
}
diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
index 79477a595ef9..8f3215239a15 100644
--- a/drivers/staging/comedi/drivers/cb_pcidio.c
+++ b/drivers/staging/comedi/drivers/cb_pcidio.c
@@ -184,8 +184,6 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
int index;
int i;
- printk("comedi%d: cb_pcidio: \n", dev->minor);
-
/*
* Allocate the private structure area. alloc_private() is a
* convenient macro defined in comedidev.h.
@@ -223,8 +221,7 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
}
- printk("No supported ComputerBoards/MeasurementComputing card found on "
- "requested position\n");
+ dev_err(dev->hw_dev, "No supported ComputerBoards/MeasurementComputing card found on requested position\n");
return -EIO;
found:
@@ -236,14 +233,12 @@ found:
dev->board_name = thisboard->name;
devpriv->pci_dev = pcidev;
- printk("Found %s on bus %i, slot %i\n", thisboard->name,
- devpriv->pci_dev->bus->number,
- PCI_SLOT(devpriv->pci_dev->devfn));
- if (comedi_pci_enable(pcidev, thisboard->name)) {
- printk
- ("cb_pcidio: failed to enable PCI device and request regions\n");
+ dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n", thisboard->name,
+ devpriv->pci_dev->bus->number,
+ PCI_SLOT(devpriv->pci_dev->devfn));
+ if (comedi_pci_enable(pcidev, thisboard->name))
return -EIO;
- }
+
devpriv->dio_reg_base
=
pci_resource_start(devpriv->pci_dev,
@@ -259,11 +254,10 @@ found:
for (i = 0; i < thisboard->n_8255; i++) {
subdev_8255_init(dev, dev->subdevices + i,
NULL, devpriv->dio_reg_base + i * 4);
- printk(" subdev %d: base = 0x%lx\n", i,
- devpriv->dio_reg_base + i * 4);
+ dev_dbg(dev->hw_dev, "subdev %d: base = 0x%lx\n", i,
+ devpriv->dio_reg_base + i * 4);
}
- printk("attached\n");
return 1;
}
@@ -277,7 +271,6 @@ found:
*/
static int pcidio_detach(struct comedi_device *dev)
{
- printk("comedi%d: cb_pcidio: remove\n", dev->minor);
if (devpriv) {
if (devpriv->pci_dev) {
if (devpriv->dio_reg_base)
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index b1b832b65bc1..8ba694263bd3 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -212,8 +212,6 @@ static int cb_pcimdas_attach(struct comedi_device *dev,
int index;
/* int i; */
- printk("comedi%d: cb_pcimdas: ", dev->minor);
-
/*
* Allocate the private structure area.
*/
@@ -223,7 +221,6 @@ static int cb_pcimdas_attach(struct comedi_device *dev,
/*
* Probe the device to determine what device in the series it is.
*/
- printk("\n");
for_each_pci_dev(pcidev) {
/* is it not a computer boards card? */
@@ -248,26 +245,26 @@ static int cb_pcimdas_attach(struct comedi_device *dev,
}
}
- printk("No supported ComputerBoards/MeasurementComputing card found on "
- "requested position\n");
+ dev_err(dev->hw_dev, "No supported ComputerBoards/MeasurementComputing card found on requested position\n");
return -EIO;
found:
- printk("Found %s on bus %i, slot %i\n", cb_pcimdas_boards[index].name,
- pcidev->bus->number, PCI_SLOT(pcidev->devfn));
+ dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n",
+ cb_pcimdas_boards[index].name, pcidev->bus->number,
+ PCI_SLOT(pcidev->devfn));
/* Warn about non-tested features */
switch (thisboard->device_id) {
case 0x56:
break;
default:
- printk("THIS CARD IS UNSUPPORTED.\n"
- "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
+ dev_dbg(dev->hw_dev, "THIS CARD IS UNSUPPORTED.\n"
+ "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
}
if (comedi_pci_enable(pcidev, "cb_pcimdas")) {
- printk(" Failed to enable PCI device and request regions\n");
+ dev_err(dev->hw_dev, "Failed to enable PCI device and request regions\n");
return -EIO;
}
@@ -277,13 +274,11 @@ found:
devpriv->BADR3 = pci_resource_start(devpriv->pci_dev, 3);
devpriv->BADR4 = pci_resource_start(devpriv->pci_dev, 4);
-#ifdef CBPCIMDAS_DEBUG
- printk("devpriv->BADR0 = 0x%lx\n", devpriv->BADR0);
- printk("devpriv->BADR1 = 0x%lx\n", devpriv->BADR1);
- printk("devpriv->BADR2 = 0x%lx\n", devpriv->BADR2);
- printk("devpriv->BADR3 = 0x%lx\n", devpriv->BADR3);
- printk("devpriv->BADR4 = 0x%lx\n", devpriv->BADR4);
-#endif
+ dev_dbg(dev->hw_dev, "devpriv->BADR0 = 0x%lx\n", devpriv->BADR0);
+ dev_dbg(dev->hw_dev, "devpriv->BADR1 = 0x%lx\n", devpriv->BADR1);
+ dev_dbg(dev->hw_dev, "devpriv->BADR2 = 0x%lx\n", devpriv->BADR2);
+ dev_dbg(dev->hw_dev, "devpriv->BADR3 = 0x%lx\n", devpriv->BADR3);
+ dev_dbg(dev->hw_dev, "devpriv->BADR4 = 0x%lx\n", devpriv->BADR4);
/* Dont support IRQ yet */
/* get irq */
@@ -333,8 +328,6 @@ found:
else
s->type = COMEDI_SUBD_UNUSED;
- printk("attached\n");
-
return 1;
}
@@ -348,16 +341,19 @@ found:
*/
static int cb_pcimdas_detach(struct comedi_device *dev)
{
-#ifdef CBPCIMDAS_DEBUG
if (devpriv) {
- printk("devpriv->BADR0 = 0x%lx\n", devpriv->BADR0);
- printk("devpriv->BADR1 = 0x%lx\n", devpriv->BADR1);
- printk("devpriv->BADR2 = 0x%lx\n", devpriv->BADR2);
- printk("devpriv->BADR3 = 0x%lx\n", devpriv->BADR3);
- printk("devpriv->BADR4 = 0x%lx\n", devpriv->BADR4);
+ dev_dbg(dev->hw_dev, "devpriv->BADR0 = 0x%lx\n",
+ devpriv->BADR0);
+ dev_dbg(dev->hw_dev, "devpriv->BADR1 = 0x%lx\n",
+ devpriv->BADR1);
+ dev_dbg(dev->hw_dev, "devpriv->BADR2 = 0x%lx\n",
+ devpriv->BADR2);
+ dev_dbg(dev->hw_dev, "devpriv->BADR3 = 0x%lx\n",
+ devpriv->BADR3);
+ dev_dbg(dev->hw_dev, "devpriv->BADR4 = 0x%lx\n",
+ devpriv->BADR4);
}
-#endif
- printk("comedi%d: cb_pcimdas: remove\n", dev->minor);
+
if (dev->irq)
free_irq(dev->irq, dev);
if (devpriv) {
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 8c981a89ab63..40bddfa22220 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -105,7 +105,8 @@ struct board_struct {
int ao_bits;
int dio_chans;
int dio_method;
- int dio_offset; /* how many bytes into the BADR are the DIO ports */
+ /* how many bytes into the BADR are the DIO ports */
+ int dio_offset;
int regs_badrindex; /* IO Region for the control, analog output,
and DIO registers */
int reg_sz; /* number of bytes of registers in io region */
@@ -144,17 +145,18 @@ static const struct board_struct boards[] = {
/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded
* upstream. */
static DEFINE_PCI_DEVICE_TABLE(pci_table) = {
- {
- PCI_VENDOR_ID_COMPUTERBOARDS, PCI_ID_PCIM_DDA06_16, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_ID_PCIM_DDA06_16) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, pci_table);
-/* this structure is for data unique to this hardware driver. If
- several hardware drivers keep similar information in this structure,
- feel free to suggest moving the variable to the struct comedi_device struct. */
+/*
+ * this structure is for data unique to this hardware driver. If
+ * several hardware drivers keep similar information in this structure,
+ * feel free to suggest moving the variable to the struct comedi_device
+ * struct.
+ */
struct board_private_struct {
unsigned long registers; /* set by probe */
unsigned long dio_registers;
@@ -335,7 +337,10 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (thisboard->dio_chans) {
switch (thisboard->dio_method) {
case DIO_8255:
- /* this is a straight 8255, so register us with the 8255 driver */
+ /*
+ * this is a straight 8255, so register us with
+ * the 8255 driver
+ */
subdev_8255_init(dev, s, NULL, devpriv->dio_registers);
devpriv->attached_to_8255 = 1;
break;
@@ -436,8 +441,11 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
for (i = 0; i < insn->n; i++) {
inw(devpriv->registers + chan * 2);
- /* should I set data[i] to the result of the actual read on the register
- or the cached unsigned int in devpriv->ao_readback[]? */
+ /*
+ * should I set data[i] to the result of the actual read
+ * on the register or the cached unsigned int in
+ * devpriv->ao_readback[]?
+ */
data[i] = devpriv->ao_readback[chan];
}
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index 871f109bcfa3..e3659bd6e85e 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -57,10 +57,9 @@ static const struct contec_board contec_boards[] = {
#define PCI_DEVICE_ID_PIO1616L 0x8172
static DEFINE_PCI_DEVICE_TABLE(contec_pci_table) = {
- {
- PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, PIO1616L}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L),
+ .driver_data = PIO1616L },
+ {0}
};
MODULE_DEVICE_TABLE(pci, contec_pci_table);
@@ -197,8 +196,8 @@ static int contec_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn, unsigned int *data)
{
- printk("contec_do_insn_bits called\n");
- printk(" data: %d %d\n", data[0], data[1]);
+ dev_dbg(dev->hw_dev, "contec_do_insn_bits called\n");
+ dev_dbg(dev->hw_dev, "data: %d %d\n", data[0], data[1]);
if (insn->n != 2)
return -EINVAL;
@@ -206,8 +205,8 @@ static int contec_do_insn_bits(struct comedi_device *dev,
if (data[0]) {
s->state &= ~data[0];
s->state |= data[0] & data[1];
- printk(" out: %d on %lx\n", s->state,
- dev->iobase + thisboard->out_offs);
+ dev_dbg(dev->hw_dev, "out: %d on %lx\n", s->state,
+ dev->iobase + thisboard->out_offs);
outw(s->state, dev->iobase + thisboard->out_offs);
}
return 2;
@@ -218,8 +217,8 @@ static int contec_di_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn, unsigned int *data)
{
- printk("contec_di_insn_bits called\n");
- printk(" data: %d %d\n", data[0], data[1]);
+ dev_dbg(dev->hw_dev, "contec_di_insn_bits called\n");
+ dev_dbg(dev->hw_dev, "data: %d %d\n", data[0], data[1]);
if (insn->n != 2)
return -EINVAL;
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index 82be77daa7d7..e61c6a8f2857 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -325,9 +325,8 @@ static const struct daq200_boardtype boardtypes[] = {
#define this_board ((const struct daq200_boardtype *)dev->board_ptr)
static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = {
- {
- 0x1616, 0x0409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(0x1616, 0x0409) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, daqboard2000_pci_table);
@@ -430,16 +429,14 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev,
/* Enable reading from the scanlist FIFO */
fpga->acqControl = DAQBOARD2000_SeqStartScanList;
for (timeout = 0; timeout < 20; timeout++) {
- if (fpga->acqControl & DAQBOARD2000_AcqConfigPipeFull) {
+ if (fpga->acqControl & DAQBOARD2000_AcqConfigPipeFull)
break;
- }
/* udelay(2); */
}
fpga->acqControl = DAQBOARD2000_AdcPacerEnable;
for (timeout = 0; timeout < 20; timeout++) {
- if (fpga->acqControl & DAQBOARD2000_AcqLogicScanning) {
+ if (fpga->acqControl & DAQBOARD2000_AcqLogicScanning)
break;
- }
/* udelay(2); */
}
for (timeout = 0; timeout < 20; timeout++) {
@@ -465,9 +462,8 @@ static int daqboard2000_ao_insn_read(struct comedi_device *dev,
int i;
int chan = CR_CHAN(insn->chanspec);
- for (i = 0; i < insn->n; i++) {
+ for (i = 0; i < insn->n; i++)
data[i] = devpriv->ao_readback[chan];
- }
return i;
}
@@ -490,9 +486,8 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev,
/* fpga->dacControl = (chan + 2) * 0x0010 | 0x0001; udelay(1000); */
fpga->dacSetting[chan] = data[i];
for (timeout = 0; timeout < 20; timeout++) {
- if ((fpga->dacControl & ((chan + 1) * 0x0010)) == 0) {
+ if ((fpga->dacControl & ((chan + 1) * 0x0010)) == 0)
break;
- }
/* udelay(2); */
}
devpriv->ao_readback[chan] = data[i];
@@ -507,7 +502,7 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev,
static void daqboard2000_resetLocalBus(struct comedi_device *dev)
{
- printk("daqboard2000_resetLocalBus\n");
+ dev_dbg(dev->hw_dev, "daqboard2000_resetLocalBus\n");
writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c);
udelay(10000);
writel(DAQBOARD2000_SECRLocalBusLo, devpriv->plx + 0x6c);
@@ -516,7 +511,7 @@ static void daqboard2000_resetLocalBus(struct comedi_device *dev)
static void daqboard2000_reloadPLX(struct comedi_device *dev)
{
- printk("daqboard2000_reloadPLX\n");
+ dev_dbg(dev->hw_dev, "daqboard2000_reloadPLX\n");
writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c);
udelay(10000);
writel(DAQBOARD2000_SECRReloadHi, devpriv->plx + 0x6c);
@@ -527,7 +522,7 @@ static void daqboard2000_reloadPLX(struct comedi_device *dev)
static void daqboard2000_pulseProgPin(struct comedi_device *dev)
{
- printk("daqboard2000_pulseProgPin 1\n");
+ dev_dbg(dev->hw_dev, "daqboard2000_pulseProgPin 1\n");
writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c);
udelay(10000);
writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c);
@@ -579,14 +574,14 @@ static int initialize_daqboard2000(struct comedi_device *dev,
secr = readl(devpriv->plx + 0x6c);
if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) {
#ifdef DEBUG_EEPROM
- printk("no serial eeprom\n");
+ dev_dbg(dev->hw_dev, "no serial eeprom\n");
#endif
return -EIO;
}
for (retry = 0; retry < 3; retry++) {
#ifdef DEBUG_EEPROM
- printk("Programming EEPROM try %x\n", retry);
+ dev_dbg(dev->hw_dev, "Programming EEPROM try %x\n", retry);
#endif
daqboard2000_resetLocalBus(dev);
@@ -597,7 +592,8 @@ static int initialize_daqboard2000(struct comedi_device *dev,
if (cpld_array[i] == 0xff
&& cpld_array[i + 1] == 0x20) {
#ifdef DEBUG_EEPROM
- printk("Preamble found at %d\n", i);
+ dev_dbg(dev->hw_dev, "Preamble found at %d\n",
+ i);
#endif
break;
}
@@ -605,13 +601,12 @@ static int initialize_daqboard2000(struct comedi_device *dev,
for (; i < len; i += 2) {
int data =
(cpld_array[i] << 8) + cpld_array[i + 1];
- if (!daqboard2000_writeCPLD(dev, data)) {
+ if (!daqboard2000_writeCPLD(dev, data))
break;
- }
}
if (i >= len) {
#ifdef DEBUG_EEPROM
- printk("Programmed\n");
+ dev_dbg(dev->hw_dev, "Programmed\n");
#endif
daqboard2000_resetLocalBus(dev);
daqboard2000_reloadPLX(dev);
@@ -658,9 +653,8 @@ static void daqboard2000_activateReferenceDacs(struct comedi_device *dev)
/* Set the + reference dac value in the FPGA */
fpga->refDacs = 0x80 | DAQBOARD2000_PosRefDacSelect;
for (timeout = 0; timeout < 20; timeout++) {
- if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) {
+ if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0)
break;
- }
udelay(2);
}
/* printk("DAQBOARD2000_PosRefDacSelect %d\n", timeout);*/
@@ -668,9 +662,8 @@ static void daqboard2000_activateReferenceDacs(struct comedi_device *dev)
/* Set the - reference dac value in the FPGA */
fpga->refDacs = 0x80 | DAQBOARD2000_NegRefDacSelect;
for (timeout = 0; timeout < 20; timeout++) {
- if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) {
+ if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0)
break;
- }
udelay(2);
}
/* printk("DAQBOARD2000_NegRefDacSelect %d\n", timeout);*/
@@ -737,15 +730,13 @@ static int daqboard2000_attach(struct comedi_device *dev,
unsigned int aux_len;
int bus, slot;
- printk("comedi%d: daqboard2000:", dev->minor);
-
bus = it->options[0];
slot = it->options[1];
result = alloc_private(dev, sizeof(struct daqboard2000_private));
- if (result < 0) {
+ if (result < 0)
return -ENOMEM;
- }
+
for (card = pci_get_device(0x1616, 0x0409, NULL);
card != NULL; card = pci_get_device(0x1616, 0x0409, card)) {
if (bus || slot) {
@@ -759,10 +750,10 @@ static int daqboard2000_attach(struct comedi_device *dev,
}
if (!card) {
if (bus || slot)
- printk(" no daqboard2000 found at bus/slot: %d/%d\n",
- bus, slot);
+ dev_err(dev->hw_dev, "no daqboard2000 found at bus/slot: %d/%d\n",
+ bus, slot);
else
- printk(" no daqboard2000 found\n");
+ dev_err(dev->hw_dev, "no daqboard2000 found\n");
return -EIO;
} else {
u32 id;
@@ -772,7 +763,8 @@ static int daqboard2000_attach(struct comedi_device *dev,
subsystem_device << 16) | card->subsystem_vendor;
for (i = 0; i < n_boardtypes; i++) {
if (boardtypes[i].id == id) {
- printk(" %s", boardtypes[i].name);
+ dev_dbg(dev->hw_dev, "%s\n",
+ boardtypes[i].name);
dev->board_ptr = boardtypes + i;
}
}
@@ -786,7 +778,7 @@ static int daqboard2000_attach(struct comedi_device *dev,
result = comedi_pci_enable(card, "daqboard2000");
if (result < 0) {
- printk(" failed to enable PCI device and request regions\n");
+ dev_err(dev->hw_dev, "failed to enable PCI device and request regions\n");
return -EIO;
}
devpriv->got_regions = 1;
@@ -794,9 +786,8 @@ static int daqboard2000_attach(struct comedi_device *dev,
ioremap(pci_resource_start(card, 0), DAQBOARD2000_PLX_SIZE);
devpriv->daq =
ioremap(pci_resource_start(card, 2), DAQBOARD2000_DAQ_SIZE);
- if (!devpriv->plx || !devpriv->daq) {
+ if (!devpriv->plx || !devpriv->daq)
return -ENOMEM;
- }
result = alloc_subdevices(dev, 3);
if (result < 0)
@@ -817,7 +808,7 @@ static int daqboard2000_attach(struct comedi_device *dev,
if (aux_data && aux_len) {
result = initialize_daqboard2000(dev, aux_data, aux_len);
} else {
- printk("no FPGA initialization code, aborting\n");
+ dev_dbg(dev->hw_dev, "no FPGA initialization code, aborting\n");
result = -EIO;
}
if (result < 0)
@@ -857,30 +848,26 @@ static int daqboard2000_attach(struct comedi_device *dev,
result = subdev_8255_init(dev, s, daqboard2000_8255_cb,
(unsigned long)(dev->iobase + 0x40));
- printk("\n");
out:
return result;
}
static int daqboard2000_detach(struct comedi_device *dev)
{
- printk("comedi%d: daqboard2000: remove\n", dev->minor);
-
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 2);
- if (dev->irq) {
+ if (dev->irq)
free_irq(dev->irq, dev);
- }
+
if (devpriv) {
if (devpriv->daq)
iounmap(devpriv->daq);
if (devpriv->plx)
iounmap(devpriv->plx);
if (devpriv->pci_dev) {
- if (devpriv->got_regions) {
+ if (devpriv->got_regions)
comedi_pci_disable(devpriv->pci_dev);
- }
pci_dev_put(devpriv->pci_dev);
}
}
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index 3141dc80fe74..c2dd0ed36a73 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -506,10 +506,8 @@ struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = {
#ifdef CONFIG_COMEDI_PCI
static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = {
- {
- PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, das08_pci_table);
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 6d91d3028178..4ad398aad72c 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -79,22 +79,20 @@ static int das08_cs_attach(struct comedi_device *dev,
if (ret < 0)
return ret;
- printk("comedi%d: das08_cs: ", dev->minor);
+ dev_info(dev->hw_dev, "comedi%d: das08_cs:\n", dev->minor);
/* deal with a pci board */
if (thisboard->bustype == pcmcia) {
if (link == NULL) {
- printk(" no pcmcia cards found\n");
+ dev_err(dev->hw_dev, "no pcmcia cards found\n");
return -EIO;
}
iobase = link->resource[0]->start;
} else {
- printk(" bug! board does not have PCMCIA bustype\n");
+ dev_err(dev->hw_dev, "bug! board does not have PCMCIA bustype\n");
return -EINVAL;
}
- printk("\n");
-
return das08_common_attach(dev, iobase);
}
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index a5ce3b2abe4a..5376e718e3d7 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -384,20 +384,20 @@ static int das16m1_cmd_exec(struct comedi_device *dev,
byte = 0;
/* if we are using external start trigger (also board dislikes having
* both start and conversion triggers external simultaneously) */
- if (cmd->start_src == TRIG_EXT && cmd->convert_src != TRIG_EXT) {
+ if (cmd->start_src == TRIG_EXT && cmd->convert_src != TRIG_EXT)
byte |= EXT_TRIG_BIT;
- }
+
outb(byte, dev->iobase + DAS16M1_CS);
/* clear interrupt bit */
outb(0, dev->iobase + DAS16M1_CLEAR_INTR);
/* enable interrupts and internal pacer */
devpriv->control_state &= ~PACER_MASK;
- if (cmd->convert_src == TRIG_TIMER) {
+ if (cmd->convert_src == TRIG_TIMER)
devpriv->control_state |= INT_PACER;
- } else {
+ else
devpriv->control_state |= EXT_PACER;
- }
+
devpriv->control_state |= INTE;
outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL);
@@ -531,9 +531,8 @@ static void munge_sample_array(short *array, unsigned int num_elements)
{
unsigned int i;
- for (i = 0; i < num_elements; i++) {
+ for (i = 0; i < num_elements; i++)
array[i] = munge_sample(array[i]);
- }
}
static void das16m1_handler(struct comedi_device *dev, unsigned int status)
@@ -668,25 +667,20 @@ static int das16m1_attach(struct comedi_device *dev,
iobase = it->options[0];
- printk("comedi%d: das16m1:", dev->minor);
-
ret = alloc_private(dev, sizeof(struct das16m1_private_struct));
if (ret < 0)
return ret;
dev->board_name = thisboard->name;
- printk(" io 0x%lx-0x%lx 0x%lx-0x%lx",
- iobase, iobase + DAS16M1_SIZE,
- iobase + DAS16M1_82C55, iobase + DAS16M1_82C55 + DAS16M1_SIZE2);
if (!request_region(iobase, DAS16M1_SIZE, driver_das16m1.driver_name)) {
- printk(" I/O port conflict\n");
+ comedi_error(dev, "I/O port conflict\n");
return -EIO;
}
if (!request_region(iobase + DAS16M1_82C55, DAS16M1_SIZE2,
driver_das16m1.driver_name)) {
release_region(iobase, DAS16M1_SIZE);
- printk(" I/O port conflict\n");
+ comedi_error(dev, "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
@@ -697,17 +691,17 @@ static int das16m1_attach(struct comedi_device *dev,
if (das16m1_irq_bits(irq) >= 0) {
ret = request_irq(irq, das16m1_interrupt, 0,
driver_das16m1.driver_name, dev);
- if (ret < 0) {
- printk(", irq unavailable\n");
+ if (ret < 0)
return ret;
- }
dev->irq = irq;
- printk(", irq %u\n", irq);
+ printk
+ ("irq %u\n", irq);
} else if (irq == 0) {
- printk(", no irq\n");
+ printk
+ (", no irq\n");
} else {
- printk(", invalid irq\n"
- " valid irqs are 2, 3, 5, 7, 10, 11, 12, or 15\n");
+ comedi_error(dev, "invalid irq\n"
+ " valid irqs are 2, 3, 5, 7, 10, 11, 12, or 15\n");
return -EINVAL;
}
@@ -771,7 +765,6 @@ static int das16m1_attach(struct comedi_device *dev,
static int das16m1_detach(struct comedi_device *dev)
{
- printk("comedi%d: das16m1: remove\n", dev->minor);
/* das16m1_reset(dev); */
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index a6df30b7fd7c..99ada5a53b9e 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -573,22 +573,23 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
devpriv->dma_bits |= DMA_CH7_CH5;
break;
default:
- printk(" only supports dma channels 5 through 7\n"
- " Dual dma only allows the following combinations:\n"
- " dma 5,6 / 6,7 / or 7,5\n");
+ dev_err(dev->hw_dev, " only supports dma channels 5 through 7\n"
+ " Dual dma only allows the following combinations:\n"
+ " dma 5,6 / 6,7 / or 7,5\n");
return -EINVAL;
break;
}
if (request_dma(dma0, driver_das1800.driver_name)) {
- printk(" failed to allocate dma channel %i\n", dma0);
+ dev_err(dev->hw_dev, "failed to allocate dma channel %i\n",
+ dma0);
return -EINVAL;
}
devpriv->dma0 = dma0;
devpriv->dma_current = dma0;
if (dma1) {
if (request_dma(dma1, driver_das1800.driver_name)) {
- printk(" failed to allocate dma channel %i\n",
- dma1);
+ dev_err(dev->hw_dev, "failed to allocate dma channel %i\n",
+ dma1);
return -EINVAL;
}
devpriv->dma1 = dma1;
@@ -631,20 +632,20 @@ static int das1800_attach(struct comedi_device *dev,
if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
return -ENOMEM;
- printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name,
- iobase);
+ printk(KERN_DEBUG "comedi%d: %s: io 0x%lx", dev->minor,
+ driver_das1800.driver_name, iobase);
if (irq) {
- printk(", irq %u", irq);
+ printk(KERN_CONT ", irq %u", irq);
if (dma0) {
- printk(", dma %u", dma0);
+ printk(KERN_CONT ", dma %u", dma0);
if (dma1)
- printk(" and %u", dma1);
+ printk(KERN_CONT " and %u", dma1);
}
}
- printk("\n");
+ printk(KERN_CONT "\n");
if (iobase == 0) {
- printk(" io base address required\n");
+ dev_err(dev->hw_dev, "io base address required\n");
return -EINVAL;
}
@@ -659,7 +660,7 @@ static int das1800_attach(struct comedi_device *dev,
board = das1800_probe(dev);
if (board < 0) {
- printk(" unable to determine board type\n");
+ dev_err(dev->hw_dev, "unable to determine board type\n");
return -ENODEV;
}
@@ -683,7 +684,8 @@ static int das1800_attach(struct comedi_device *dev,
if (irq) {
if (request_irq(irq, das1800_interrupt, 0,
driver_das1800.driver_name, dev)) {
- printk(" unable to allocate irq %u\n", irq);
+ dev_dbg(dev->hw_dev, "unable to allocate irq %u\n",
+ irq);
return -EINVAL;
}
}
@@ -712,7 +714,7 @@ static int das1800_attach(struct comedi_device *dev,
devpriv->irq_dma_bits |= 0x38;
break;
default:
- printk(" irq out of range\n");
+ dev_err(dev->hw_dev, "irq out of range\n");
return -EINVAL;
break;
}
@@ -813,8 +815,8 @@ static int das1800_detach(struct comedi_device *dev)
kfree(devpriv->ai_buf1);
}
- printk("comedi%d: %s: remove\n", dev->minor,
- driver_das1800.driver_name);
+ dev_dbg(dev->hw_dev, "comedi%d: %s: remove\n", dev->minor,
+ driver_das1800.driver_name);
return 0;
};
@@ -833,8 +835,8 @@ static int das1800_probe(struct comedi_device *dev)
case 0x3:
if (board == das1801st_da || board == das1802st_da ||
board == das1701st_da || board == das1702st_da) {
- printk(" Board model: %s\n",
- das1800_boards[board].name);
+ dev_dbg(dev->hw_dev, "Board model: %s\n",
+ das1800_boards[board].name);
return board;
}
printk
@@ -843,8 +845,8 @@ static int das1800_probe(struct comedi_device *dev)
break;
case 0x4:
if (board == das1802hr_da || board == das1702hr_da) {
- printk(" Board model: %s\n",
- das1800_boards[board].name);
+ dev_dbg(dev->hw_dev, "Board model: %s\n",
+ das1800_boards[board].name);
return board;
}
printk
@@ -854,8 +856,8 @@ static int das1800_probe(struct comedi_device *dev)
case 0x5:
if (board == das1801ao || board == das1802ao ||
board == das1701ao || board == das1702ao) {
- printk(" Board model: %s\n",
- das1800_boards[board].name);
+ dev_dbg(dev->hw_dev, "Board model: %s\n",
+ das1800_boards[board].name);
return board;
}
printk
@@ -864,18 +866,19 @@ static int das1800_probe(struct comedi_device *dev)
break;
case 0x6:
if (board == das1802hr || board == das1702hr) {
- printk(" Board model: %s\n",
- das1800_boards[board].name);
+ dev_dbg(dev->hw_dev, "Board model: %s\n",
+ das1800_boards[board].name);
return board;
}
- printk(" Board model (probed, not recommended): das-1802hr\n");
+ printk
+ (" Board model (probed, not recommended): das-1802hr\n");
return das1802hr;
break;
case 0x7:
if (board == das1801st || board == das1802st ||
board == das1701st || board == das1702st) {
- printk(" Board model: %s\n",
- das1800_boards[board].name);
+ dev_dbg(dev->hw_dev, "Board model: %s\n",
+ das1800_boards[board].name);
return board;
}
printk
@@ -884,8 +887,8 @@ static int das1800_probe(struct comedi_device *dev)
break;
case 0x8:
if (board == das1801hc || board == das1802hc) {
- printk(" Board model: %s\n",
- das1800_boards[board].name);
+ dev_dbg(dev->hw_dev, "Board model: %s\n",
+ das1800_boards[board].name);
return board;
}
printk
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index 6328f5280b66..f25684145e84 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -171,7 +171,7 @@ static irqreturn_t intr_handler(int irq, void *d)
struct comedi_subdevice *s = dev->subdevices;
if (!dev->attached || devpriv->das6402_ignoreirq) {
- printk("das6402: BUG: spurious interrupt\n");
+ dev_warn(dev->hw_dev, "BUG: spurious interrupt\n");
return IRQ_HANDLED;
}
#ifdef DEBUG
@@ -228,9 +228,7 @@ static int das6402_ai_cancel(struct comedi_device *dev,
*/
devpriv->das6402_ignoreirq = 1;
-#ifdef DEBUG
- printk("das6402: Stopping acquisition\n");
-#endif
+ dev_dbg(dev->hw_dev, "Stopping acquisition\n");
devpriv->das6402_ignoreirq = 1;
outb_p(0x02, dev->iobase + 10); /* disable external trigging */
outw_p(SCANL, dev->iobase + 2); /* resets the card fifo */
@@ -246,10 +244,7 @@ static int das6402_ai_mode2(struct comedi_device *dev,
struct comedi_subdevice *s, comedi_trig * it)
{
devpriv->das6402_ignoreirq = 1;
-
-#ifdef DEBUG
- printk("das6402: Starting acquisition\n");
-#endif
+ dev_dbg(dev->hw_dev, "Starting acquisition\n");
outb_p(0x03, dev->iobase + 10); /* enable external trigging */
outw_p(SCANL, dev->iobase + 2); /* resets the card fifo */
outb_p(IRQ | CONVSRC | BURSTEN | INTE, dev->iobase + 9);
@@ -329,10 +324,8 @@ static int das6402_attach(struct comedi_device *dev,
if (iobase == 0)
iobase = 0x300;
- printk("comedi%d: das6402: 0x%04lx", dev->minor, iobase);
-
if (!request_region(iobase, DAS6402_SIZE, "das6402")) {
- printk(" I/O port conflict\n");
+ dev_err(dev->hw_dev, "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
@@ -340,14 +333,12 @@ static int das6402_attach(struct comedi_device *dev,
/* should do a probe here */
irq = it->options[0];
- printk(" ( irq = %u )", irq);
+ dev_dbg(dev->hw_dev, "( irq = %u )\n", irq);
ret = request_irq(irq, intr_handler, 0, "das6402", dev);
- if (ret < 0) {
- printk("irq conflict\n");
+ if (ret < 0)
return ret;
- }
- dev->irq = irq;
+ dev->irq = irq;
ret = alloc_private(dev, sizeof(struct das6402_private));
if (ret < 0)
return ret;
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 96d41ad76956..6e347b40fe61 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -296,47 +296,47 @@ static int das800_probe(struct comedi_device *dev)
switch (id_bits) {
case 0x0:
if (board == das800) {
- printk(" Board model: DAS-800\n");
+ dev_dbg(dev->hw_dev, "Board model: DAS-800\n");
return board;
}
if (board == ciodas800) {
- printk(" Board model: CIO-DAS800\n");
+ dev_dbg(dev->hw_dev, "Board model: CIO-DAS800\n");
return board;
}
- printk(" Board model (probed): DAS-800\n");
+ dev_dbg(dev->hw_dev, "Board model (probed): DAS-800\n");
return das800;
break;
case 0x2:
if (board == das801) {
- printk(" Board model: DAS-801\n");
+ dev_dbg(dev->hw_dev, "Board model: DAS-801\n");
return board;
}
if (board == ciodas801) {
- printk(" Board model: CIO-DAS801\n");
+ dev_dbg(dev->hw_dev, "Board model: CIO-DAS801\n");
return board;
}
- printk(" Board model (probed): DAS-801\n");
+ dev_dbg(dev->hw_dev, "Board model (probed): DAS-801\n");
return das801;
break;
case 0x3:
if (board == das802) {
- printk(" Board model: DAS-802\n");
+ dev_dbg(dev->hw_dev, "Board model: DAS-802\n");
return board;
}
if (board == ciodas802) {
- printk(" Board model: CIO-DAS802\n");
+ dev_dbg(dev->hw_dev, "Board model: CIO-DAS802\n");
return board;
}
if (board == ciodas80216) {
- printk(" Board model: CIO-DAS802/16\n");
+ dev_dbg(dev->hw_dev, "Board model: CIO-DAS802/16\n");
return board;
}
- printk(" Board model (probed): DAS-802\n");
+ dev_dbg(dev->hw_dev, "Board model (probed): DAS-802\n");
return das802;
break;
default:
- printk(" Board model: probe returned 0x%x (unknown)\n",
- id_bits);
+ dev_dbg(dev->hw_dev, "Board model: probe returned 0x%x (unknown)\n",
+ id_bits);
return board;
break;
}
@@ -466,42 +466,43 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned long irq_flags;
int board;
- printk("comedi%d: das800: io 0x%lx", dev->minor, iobase);
+ dev_info(dev->hw_dev, "comedi%d: das800: io 0x%lx\n", dev->minor,
+ iobase);
if (irq)
- printk(", irq %u", irq);
- printk("\n");
+ dev_dbg(dev->hw_dev, "irq %u\n", irq);
/* allocate and initialize dev->private */
if (alloc_private(dev, sizeof(struct das800_private)) < 0)
return -ENOMEM;
if (iobase == 0) {
- printk("io base address required for das800\n");
+ dev_err(dev->hw_dev, "io base address required for das800\n");
return -EINVAL;
}
/* check if io addresses are available */
if (!request_region(iobase, DAS800_SIZE, "das800")) {
- printk("I/O port conflict\n");
+ dev_err(dev->hw_dev, "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
board = das800_probe(dev);
if (board < 0) {
- printk("unable to determine board type\n");
+ dev_dbg(dev->hw_dev, "unable to determine board type\n");
return -ENODEV;
}
dev->board_ptr = das800_boards + board;
/* grab our IRQ */
if (irq == 1 || irq > 7) {
- printk("irq out of range\n");
+ dev_err(dev->hw_dev, "irq out of range\n");
return -EINVAL;
}
if (irq) {
if (request_irq(irq, das800_interrupt, 0, "das800", dev)) {
- printk("unable to allocate irq %u\n", irq);
+ dev_err(dev->hw_dev, "unable to allocate irq %u\n",
+ irq);
return -EINVAL;
}
}
@@ -557,7 +558,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static int das800_detach(struct comedi_device *dev)
{
- printk("comedi%d: das800: remove\n", dev->minor);
+ dev_info(dev->hw_dev, "comedi%d: das800: remove\n", dev->minor);
/* only free stuff if it has been allocated by _attach */
if (dev->iobase)
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 6170f7bac46e..0a7979e52999 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -352,7 +352,8 @@ static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR)
return 0;
- printk("dt3k_send_cmd() timeout/error status=0x%04x\n", status);
+ dev_dbg(dev->hw_dev, "dt3k_send_cmd() timeout/error status=0x%04x\n",
+ status);
return -ETIME;
}
@@ -383,7 +384,7 @@ static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
dt3k_send_cmd(dev, CMD_WRITESINGLE);
}
-static int debug_n_ints = 0;
+static int debug_n_ints;
/* FIXME! Assumes shared interrupt is for this card. */
/* What's this debug_n_ints stuff? Obviously needs some work... */
@@ -429,12 +430,12 @@ static char *intr_flags[] = {
static void debug_intr_flags(unsigned int flags)
{
int i;
- printk("dt3k: intr_flags:");
+ printk(KERN_DEBUG "dt3k: intr_flags:");
for (i = 0; i < 8; i++) {
if (flags & (1 << i))
- printk(" %s", intr_flags[i]);
+ printk(KERN_CONT " %s", intr_flags[i]);
}
- printk("\n");
+ printk(KERN_CONT "\n");
}
#endif
@@ -452,7 +453,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev,
if (count < 0)
count += AI_FIFO_DEPTH;
- printk("reading %d samples\n", count);
+ dev_dbg(dev->hw_dev, "reading %d samples\n", count);
rear = devpriv->ai_rear;
@@ -640,7 +641,7 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
int ret;
unsigned int mode;
- printk("dt3k_ai_cmd:\n");
+ dev_dbg(dev->hw_dev, "dt3k_ai_cmd:\n");
for (i = 0; i < cmd->chanlist_len; i++) {
chan = CR_CHAN(cmd->chanlist[i]);
range = CR_RANGE(cmd->chanlist[i]);
@@ -651,15 +652,15 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
aref = CR_AREF(cmd->chanlist[0]);
writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
- printk("param[0]=0x%04x\n", cmd->scan_end_arg);
+ dev_dbg(dev->hw_dev, "param[0]=0x%04x\n", cmd->scan_end_arg);
if (cmd->convert_src == TRIG_TIMER) {
divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
cmd->flags & TRIG_ROUND_MASK);
writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
- printk("param[1]=0x%04x\n", divider >> 16);
+ dev_dbg(dev->hw_dev, "param[1]=0x%04x\n", divider >> 16);
writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
- printk("param[2]=0x%04x\n", divider & 0xffff);
+ dev_dbg(dev->hw_dev, "param[2]=0x%04x\n", divider & 0xffff);
} else {
/* not supported */
}
@@ -668,21 +669,21 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
cmd->flags & TRIG_ROUND_MASK);
writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
- printk("param[3]=0x%04x\n", tscandiv >> 16);
+ dev_dbg(dev->hw_dev, "param[3]=0x%04x\n", tscandiv >> 16);
writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
- printk("param[4]=0x%04x\n", tscandiv & 0xffff);
+ dev_dbg(dev->hw_dev, "param[4]=0x%04x\n", tscandiv & 0xffff);
} else {
/* not supported */
}
mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
writew(mode, devpriv->io_addr + DPR_Params(5));
- printk("param[5]=0x%04x\n", mode);
+ dev_dbg(dev->hw_dev, "param[5]=0x%04x\n", mode);
writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
- printk("param[6]=0x%04x\n", aref == AREF_DIFF);
+ dev_dbg(dev->hw_dev, "param[6]=0x%04x\n", aref == AREF_DIFF);
writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
- printk("param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
+ dev_dbg(dev->hw_dev, "param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
ret = dt3k_send_cmd(dev, CMD_CONFIG);
@@ -848,7 +849,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
int bus, slot;
int ret = 0;
- printk("dt3000:");
+ dev_dbg(dev->hw_dev, "dt3000:\n");
bus = it->options[0];
slot = it->options[1];
@@ -860,7 +861,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret < 0)
return ret;
if (ret == 0) {
- printk(" no DT board found\n");
+ dev_warn(dev->hw_dev, "no DT board found\n");
return -ENODEV;
}
@@ -868,7 +869,8 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (request_irq(devpriv->pci_dev->irq, dt3k_interrupt, IRQF_SHARED,
"dt3000", dev)) {
- printk(" unable to allocate IRQ %u\n", devpriv->pci_dev->irq);
+ dev_err(dev->hw_dev, "unable to allocate IRQ %u\n",
+ devpriv->pci_dev->irq);
return -EINVAL;
}
dev->irq = devpriv->pci_dev->irq;
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 8d98cf412709..6a79ba10630d 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -71,18 +71,12 @@ static struct comedi_driver driver_jr3_pci = {
};
static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = {
- {
- PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL_NEW,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_2_CHANNEL,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_3_CHANNEL,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_4_CHANNEL,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL_NEW) },
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_2_CHANNEL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_3_CHANNEL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_4_CHANNEL) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, jr3_pci_pci_table);
@@ -378,14 +372,14 @@ static int jr3_pci_open(struct comedi_device *dev)
int i;
struct jr3_pci_dev_private *devpriv = dev->private;
- printk("jr3_pci_open\n");
+ dev_dbg(dev->hw_dev, "jr3_pci_open\n");
for (i = 0; i < devpriv->n_channels; i++) {
struct jr3_pci_subdev_private *p;
p = dev->subdevices[i].private;
if (p) {
- printk("serial: %p %d (%d)\n", p, p->serial_no,
- p->channel_no);
+ dev_dbg(dev->hw_dev, "serial: %p %d (%d)\n", p,
+ p->serial_no, p->channel_no);
}
}
return 0;
@@ -463,8 +457,8 @@ static int jr3_download_firmware(struct comedi_device *dev, const u8 * data,
break;
more = more
&& read_idm_word(data, size, &pos, &addr);
- printk("Loading#%d %4.4x bytes at %4.4x\n", i,
- count, addr);
+ dev_dbg(dev->hw_dev, "Loading#%d %4.4x bytes at %4.4x\n",
+ i, count, addr);
while (more && count > 0) {
if (addr & 0x4000) {
/* 16 bit data, never seen in real life!! */
@@ -599,24 +593,24 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
min_full_scale =
get_min_full_scales(channel);
printk("Obtained Min. Full Scales:\n");
- printk("%i ", (min_full_scale).fx);
- printk("%i ", (min_full_scale).fy);
- printk("%i ", (min_full_scale).fz);
- printk("%i ", (min_full_scale).mx);
- printk("%i ", (min_full_scale).my);
- printk("%i ", (min_full_scale).mz);
- printk("\n");
+ printk(KERN_DEBUG "%i ", (min_full_scale).fx);
+ printk(KERN_CONT "%i ", (min_full_scale).fy);
+ printk(KERN_CONT "%i ", (min_full_scale).fz);
+ printk(KERN_CONT "%i ", (min_full_scale).mx);
+ printk(KERN_CONT "%i ", (min_full_scale).my);
+ printk(KERN_CONT "%i ", (min_full_scale).mz);
+ printk(KERN_CONT "\n");
max_full_scale =
get_max_full_scales(channel);
printk("Obtained Max. Full Scales:\n");
- printk("%i ", (max_full_scale).fx);
- printk("%i ", (max_full_scale).fy);
- printk("%i ", (max_full_scale).fz);
- printk("%i ", (max_full_scale).mx);
- printk("%i ", (max_full_scale).my);
- printk("%i ", (max_full_scale).mz);
- printk("\n");
+ printk(KERN_DEBUG "%i ", (max_full_scale).fx);
+ printk(KERN_CONT "%i ", (max_full_scale).fy);
+ printk(KERN_CONT "%i ", (max_full_scale).fz);
+ printk(KERN_CONT "%i ", (max_full_scale).mx);
+ printk(KERN_CONT "%i ", (max_full_scale).my);
+ printk(KERN_CONT "%i ", (max_full_scale).mz);
+ printk(KERN_CONT "\n");
set_full_scales(channel,
max_full_scale);
@@ -779,14 +773,12 @@ static int jr3_pci_attach(struct comedi_device *dev,
int opt_bus, opt_slot, i;
struct jr3_pci_dev_private *devpriv;
- printk("comedi%d: jr3_pci\n", dev->minor);
-
opt_bus = it->options[0];
opt_slot = it->options[1];
if (sizeof(struct jr3_channel) != 0xc00) {
- printk("sizeof(struct jr3_channel) = %x [expected %x]\n",
- (unsigned)sizeof(struct jr3_channel), 0xc00);
+ dev_err(dev->hw_dev, "sizeof(struct jr3_channel) = %x [expected %x]\n",
+ (unsigned)sizeof(struct jr3_channel), 0xc00);
return -EINVAL;
}
@@ -840,7 +832,7 @@ static int jr3_pci_attach(struct comedi_device *dev,
}
}
if (!card) {
- printk(" no jr3_pci found\n");
+ dev_err(dev->hw_dev, "no jr3_pci found\n");
return -EIO;
} else {
devpriv->pci_dev = card;
@@ -875,10 +867,10 @@ static int jr3_pci_attach(struct comedi_device *dev,
p = dev->subdevices[i].private;
p->channel = &devpriv->iobase->channel[i].data;
- printk("p->channel %p %p (%tx)\n",
- p->channel, devpriv->iobase,
- ((char *)(p->channel) -
- (char *)(devpriv->iobase)));
+ dev_dbg(dev->hw_dev, "p->channel %p %p (%tx)\n",
+ p->channel, devpriv->iobase,
+ ((char *)(p->channel) -
+ (char *)(devpriv->iobase)));
p->channel_no = i;
for (j = 0; j < 8; j++) {
int k;
@@ -916,7 +908,7 @@ static int jr3_pci_attach(struct comedi_device *dev,
devpriv->iobase->channel[0].reset = 0;
result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware);
- printk("Firmare load %d\n", result);
+ dev_dbg(dev->hw_dev, "Firmare load %d\n", result);
if (result < 0)
goto out;
@@ -934,9 +926,9 @@ static int jr3_pci_attach(struct comedi_device *dev,
*/
msleep_interruptible(25);
for (i = 0; i < 0x18; i++) {
- printk("%c",
- get_u16(&devpriv->iobase->channel[0].
- data.copyright[i]) >> 8);
+ dev_dbg(dev->hw_dev, "%c\n",
+ get_u16(&devpriv->iobase->channel[0].
+ data.copyright[i]) >> 8);
}
/* Start card timer */
@@ -963,7 +955,6 @@ static int jr3_pci_detach(struct comedi_device *dev)
int i;
struct jr3_pci_dev_private *devpriv = dev->private;
- printk("comedi%d: jr3_pci: remove\n", dev->minor);
if (devpriv) {
del_timer_sync(&devpriv->timer);
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index 286093bca3fb..4e9e9a078652 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -52,10 +52,8 @@ static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it);
static int cnt_detach(struct comedi_device *dev);
static DEFINE_PCI_DEVICE_TABLE(cnt_pci_table) = {
- {
- PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, cnt_pci_table);
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index cda4b224b30f..8b812e41c52b 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -188,12 +188,9 @@ static const struct comedi_lrange me2600_ao_range = {
};
static DEFINE_PCI_DEVICE_TABLE(me_pci_table) = {
- {
- PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0}, {
- PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, 0}, {
- 0}
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID) },
+ {0}
};
MODULE_DEVICE_TABLE(pci, me_pci_table);
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index 32e675e3f0b9..c25e44c1905e 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -731,9 +731,8 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
outw(trigger_bits, dev->iobase + TRIGGER_REG);
/* start acquisition for soft trigger */
- if (cmd->start_src == TRIG_NOW) {
+ if (cmd->start_src == TRIG_NOW)
outw(0, dev->iobase + FIFO_START_REG);
- }
#ifdef A2150_DEBUG
ni_dump_regs(dev);
#endif
@@ -860,11 +859,10 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
case TRIG_ROUND_NEAREST:
default:
/* if least upper bound is better approximation */
- if (lub - *period < *period - glb) {
+ if (lub - *period < *period - glb)
*period = lub;
- } else {
+ else
*period = glb;
- }
break;
case TRIG_ROUND_UP:
*period = lub;
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index 49b824c7bd2e..c0423a8c3e36 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -52,7 +52,7 @@ the PCMCIA interface.
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-static struct pcmcia_device *pcmcia_cur_dev = NULL;
+static struct pcmcia_device *pcmcia_cur_dev;
#define DIO24_SIZE 4 /* size of io region used by board */
@@ -133,22 +133,19 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
#endif
break;
default:
- printk("bug! couldn't determine board type\n");
+ pr_err("bug! couldn't determine board type\n");
return -EINVAL;
break;
}
- printk("comedi%d: ni_daq_dio24: %s, io 0x%lx", dev->minor,
- thisboard->name, iobase);
+ pr_debug("comedi%d: ni_daq_dio24: %s, io 0x%lx", dev->minor,
+ thisboard->name, iobase);
#ifdef incomplete
- if (irq) {
- printk(", irq %u", irq);
- }
+ if (irq)
+ pr_debug("irq %u\n", irq);
#endif
- printk("\n");
-
if (iobase == 0) {
- printk("io base address is zero!\n");
+ pr_err("io base address is zero!\n");
return -EINVAL;
}
@@ -173,7 +170,7 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static int dio24_detach(struct comedi_device *dev)
{
- printk("comedi%d: ni_daq_dio24: remove\n", dev->minor);
+ dev_info(dev->hw_dev, "comedi%d: ni_daq_dio24: remove\n", dev->minor);
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 0);
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 832a5178b638..ff3840544dd4 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -145,7 +145,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
irq = link->irq;
break;
default:
- printk("bug! couldn't determine board type\n");
+ pr_err("bug! couldn't determine board type\n");
return -EINVAL;
break;
}
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 9148abdad074..0f0d995f137c 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -1470,7 +1470,7 @@ static void m_series_stc_writew(struct comedi_device *dev, uint16_t data,
/* FIXME: DIO_Output_Register (16 bit reg) is replaced by M_Offset_Static_Digital_Output (32 bit)
and M_Offset_SCXI_Serial_Data_Out (8 bit) */
default:
- printk("%s: bug! unhandled register=0x%x in switch.\n",
+ printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
__func__, reg);
BUG();
return;
@@ -1505,7 +1505,7 @@ static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
offset = M_Offset_G01_Status;
break;
default:
- printk("%s: bug! unhandled register=0x%x in switch.\n",
+ printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
__func__, reg);
BUG();
return 0;
@@ -1547,7 +1547,7 @@ static void m_series_stc_writel(struct comedi_device *dev, uint32_t data,
offset = M_Offset_G1_Load_B;
break;
default:
- printk("%s: bug! unhandled register=0x%x in switch.\n",
+ printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
__func__, reg);
BUG();
return;
@@ -1573,7 +1573,7 @@ static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
offset = M_Offset_G1_Save;
break;
default:
- printk("%s: bug! unhandled register=0x%x in switch.\n",
+ printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
__func__, reg);
BUG();
return 0;
@@ -1632,9 +1632,8 @@ static void m_series_init_eeprom_buffer(struct comedi_device *dev)
}
devpriv->serial_number = be32_to_cpu(devpriv->serial_number);
- for (i = 0; i < M_SERIES_EEPROM_SIZE; ++i) {
+ for (i = 0; i < M_SERIES_EEPROM_SIZE; ++i)
devpriv->eeprom_buffer[i] = ni_readb(Start_Cal_EEPROM + i);
- }
writel(old_iodwbsr1_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR_1);
writel(old_iodwbsr_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR);
@@ -1665,9 +1664,9 @@ static void init_6143(struct comedi_device *dev)
static int pcimio_detach(struct comedi_device *dev)
{
mio_common_detach(dev);
- if (dev->irq) {
+ if (dev->irq)
free_irq(dev->irq, dev);
- }
+
if (dev->private) {
mite_free_ring(devpriv->ai_mite_ring);
mite_free_ring(devpriv->ao_mite_ring);
@@ -1685,7 +1684,7 @@ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
int ret;
- printk("comedi%d: ni_pcimio:", dev->minor);
+ dev_info(dev->hw_dev, "comedi%d: ni_pcimio:\n", dev->minor);
ret = ni_alloc_private(dev);
if (ret < 0)
@@ -1695,7 +1694,7 @@ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret < 0)
return ret;
- printk(" %s", boardtype.name);
+ dev_dbg(dev->hw_dev, "%s\n", boardtype.name);
dev->board_name = boardtype.name;
if (boardtype.reg_type & ni_reg_m_series_mask) {
@@ -1712,7 +1711,7 @@ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
ret = mite_setup(devpriv->mite);
if (ret < 0) {
- printk(" error setting up mite\n");
+ pr_warn("error setting up mite\n");
return ret;
}
comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
@@ -1740,13 +1739,13 @@ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->irq = mite_irq(devpriv->mite);
if (dev->irq == 0) {
- printk(" unknown irq (bad)\n");
+ pr_warn("unknown irq (bad)\n");
} else {
- printk(" ( irq = %u )", dev->irq);
+ pr_debug("( irq = %u )\n", dev->irq);
ret = request_irq(dev->irq, ni_E_interrupt, NI_E_IRQ_FLAGS,
DRV_NAME, dev);
if (ret < 0) {
- printk(" irq not available\n");
+ pr_warn("irq not available\n");
dev->irq = 0;
}
}
@@ -1787,7 +1786,7 @@ static int pcimio_find_device(struct comedi_device *dev, int bus, int slot)
}
}
}
- printk("no device found\n");
+ pr_warn("no device found\n");
mite_list_devices();
return -EIO;
}
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 0b9bee36eb5f..96cd7ec2ad53 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -155,8 +155,8 @@ static int pcl816_attach(struct comedi_device *dev,
static int pcl816_detach(struct comedi_device *dev);
#ifdef unused
-static int RTC_lock = 0; /* RTC lock */
-static int RTC_timer_lock = 0; /* RTC int lock */
+static int RTC_lock; /* RTC lock */
+static int RTC_timer_lock; /* RTC int lock */
#endif
static struct comedi_driver driver_pcl816 = {
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index b45a9bd8b489..7344a53a81c4 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -252,8 +252,8 @@ static int pcl818_attach(struct comedi_device *dev,
static int pcl818_detach(struct comedi_device *dev);
#ifdef unused
-static int RTC_lock = 0; /* RTC lock */
-static int RTC_timer_lock = 0; /* RTC int lock */
+static int RTC_lock; /* RTC lock */
+static int RTC_timer_lock; /* RTC int lock */
#endif
struct pcl818_board {
@@ -463,9 +463,8 @@ static int pcl818_ao_insn_read(struct comedi_device *dev,
int n;
int chan = CR_CHAN(insn->chanspec);
- for (n = 0; n < insn->n; n++) {
+ for (n = 0; n < insn->n; n++)
data[n] = devpriv->ao_readback[chan];
- }
return n;
}
@@ -571,9 +570,9 @@ conv_finish:
return IRQ_HANDLED;
}
devpriv->act_chanlist_pos++;
- if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+ if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
devpriv->act_chanlist_pos = 0;
- }
+
s->async->cur_chan++;
if (s->async->cur_chan >= devpriv->ai_n_chan) {
/* printk("E"); */
@@ -645,9 +644,9 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
comedi_buf_put(s->async, ptr[bufptr++] >> 4); /* get one sample */
devpriv->act_chanlist_pos++;
- if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+ if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
devpriv->act_chanlist_pos = 0;
- }
+
s->async->cur_chan++;
if (s->async->cur_chan >= devpriv->ai_n_chan) {
s->async->cur_chan = 0;
@@ -805,11 +804,10 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
return IRQ_HANDLED;
}
- if (lo & 2) {
+ if (lo & 2)
len = 512;
- } else {
+ else
len = 0;
- }
for (i = 0; i < len; i++) {
lo = inb(dev->iobase + PCL818_FI_DATALO);
@@ -827,9 +825,9 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4)); /* get one sample */
devpriv->act_chanlist_pos++;
- if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+ if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
devpriv->act_chanlist_pos = 0;
- }
+
s->async->cur_chan++;
if (s->async->cur_chan >= devpriv->ai_n_chan) {
s->async->cur_chan = 0;
@@ -1009,7 +1007,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
int divisor1 = 0, divisor2 = 0;
unsigned int seglen;
- printk("pcl818_ai_cmd_mode()\n");
+ dev_dbg(dev->hw_dev, "pcl818_ai_cmd_mode()\n");
if ((!dev->irq) && (!devpriv->dma_rtc)) {
comedi_error(dev, "IRQ not defined!");
return -EINVAL;
@@ -1112,7 +1110,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
break;
}
#endif
- printk("pcl818_ai_cmd_mode() end\n");
+ dev_dbg(dev->hw_dev, "pcl818_ai_cmd_mode() end\n");
return 0;
}
@@ -1309,11 +1307,9 @@ static void setup_channel_list(struct comedi_device *dev,
*/
static int check_single_ended(unsigned int port)
{
- if (inb(port + PCL818_STATUS) & 0x20) {
+ if (inb(port + PCL818_STATUS) & 0x20)
return 1;
- } else {
- return 0;
- }
+ return 0;
}
/*
@@ -1352,9 +1348,8 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
if (!cmd->stop_src || tmp != cmd->stop_src)
err++;
- if (err) {
+ if (err)
return 1;
- }
/* step 2: make sure trigger sources are unique and mutually compatible */
@@ -1377,9 +1372,8 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
err++;
- if (err) {
+ if (err)
return 2;
- }
/* step 3: make sure arguments are trivially compatible */
@@ -1421,9 +1415,8 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
}
}
- if (err) {
+ if (err)
return 3;
- }
/* step 4: fix up any arguments */
@@ -1438,9 +1431,8 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
err++;
}
- if (err) {
+ if (err)
return 4;
- }
/* step 5: complain about special chanlist considerations */
@@ -1461,7 +1453,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
struct comedi_cmd *cmd = &s->async->cmd;
int retval;
- printk("pcl818_ai_cmd()\n");
+ dev_dbg(dev->hw_dev, "pcl818_ai_cmd()\n");
devpriv->ai_n_chan = cmd->chanlist_len;
devpriv->ai_chanlist = cmd->chanlist;
devpriv->ai_flags = cmd->flags;
@@ -1470,17 +1462,16 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ai_timer1 = 0;
devpriv->ai_timer2 = 0;
- if (cmd->stop_src == TRIG_COUNT) {
+ if (cmd->stop_src == TRIG_COUNT)
devpriv->ai_scans = cmd->stop_arg;
- } else {
+ else
devpriv->ai_scans = 0;
- }
if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 3 */
if (cmd->convert_src == TRIG_TIMER) { /* mode 1 */
devpriv->ai_timer1 = cmd->convert_arg;
retval = pcl818_ai_cmd_mode(1, dev, s);
- printk("pcl818_ai_cmd() end\n");
+ dev_dbg(dev->hw_dev, "pcl818_ai_cmd() end\n");
return retval;
}
if (cmd->convert_src == TRIG_EXT) { /* mode 3 */
@@ -1499,7 +1490,7 @@ static int pcl818_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
if (devpriv->irq_blocked > 0) {
- printk("pcl818_ai_cancel()\n");
+ dev_dbg(dev->hw_dev, "pcl818_ai_cancel()\n");
devpriv->irq_was_now_closed = 1;
switch (devpriv->ai_mode) {
@@ -1549,7 +1540,7 @@ static int pcl818_ai_cancel(struct comedi_device *dev,
}
end:
- printk("pcl818_ai_cancel() end\n");
+ dev_dbg(dev->hw_dev, "pcl818_ai_cancel() end\n");
return 0;
}
@@ -1633,11 +1624,11 @@ static int set_rtc_irq_bit(unsigned char bit)
save_flags(flags);
cli();
val = CMOS_READ(RTC_CONTROL);
- if (bit) {
+ if (bit)
val |= RTC_PIE;
- } else {
+ else
val &= ~RTC_PIE;
- }
+
CMOS_WRITE(val, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
restore_flags(flags);
@@ -1754,22 +1745,23 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* claim our I/O space */
iobase = it->options[0];
- printk("comedi%d: pcl818: board=%s, ioport=0x%03lx",
- dev->minor, this_board->name, iobase);
+ printk
+ ("comedi%d: pcl818: board=%s, ioport=0x%03lx",
+ dev->minor, this_board->name, iobase);
devpriv->io_range = this_board->io_range;
if ((this_board->fifo) && (it->options[2] == -1)) { /* we've board with FIFO and we want to use FIFO */
devpriv->io_range = PCLx1xFIFO_RANGE;
devpriv->usefifo = 1;
}
if (!request_region(iobase, devpriv->io_range, "pcl818")) {
- printk("I/O port conflict\n");
+ comedi_error(dev, "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
if (pcl818_check(iobase)) {
- printk(", I can't detect board. FAIL!\n");
+ comedi_error(dev, "I can't detect board. FAIL!\n");
return -EIO;
}
@@ -1793,19 +1785,18 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
irq);
irq = 0; /* Can't use IRQ */
} else {
- printk(", irq=%u", irq);
+ printk(KERN_DEBUG "irq=%u", irq);
}
}
}
}
dev->irq = irq;
- if (irq) {
- devpriv->irq_free = 1;
- } /* 1=we have allocated irq */
- else {
+ if (irq)
+ devpriv->irq_free = 1; /* 1=we have allocated irq */
+ else
devpriv->irq_free = 0;
- }
+
devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */
devpriv->ai_mode = 0; /* mode of irq */
@@ -1825,7 +1816,7 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
"pcl818 DMA (RTC)", dev)) {
devpriv->dma_rtc = 1;
devpriv->rtc_irq = RTC_IRQ;
- printk(", dma_irq=%u", devpriv->rtc_irq);
+ printk(KERN_DEBUG "dma_irq=%u", devpriv->rtc_irq);
} else {
RTC_lock--;
if (RTC_lock == 0) {
@@ -1850,34 +1841,26 @@ no_rtc:
if (dma < 1)
goto no_dma; /* DMA disabled */
if (((1 << dma) & this_board->DMAbits) == 0) {
- printk(", DMA is out of allowed range, FAIL!\n");
+ printk(KERN_ERR "DMA is out of allowed range, FAIL!\n");
return -EINVAL; /* Bad DMA */
}
ret = request_dma(dma, "pcl818");
- if (ret) {
- printk(", unable to allocate DMA %u, FAIL!\n", dma);
+ if (ret)
return -EBUSY; /* DMA isn't free */
- }
devpriv->dma = dma;
- printk(", dma=%u", dma);
pages = 2; /* we need 16KB */
devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
- if (!devpriv->dmabuf[0]) {
- printk(", unable to allocate DMA buffer, FAIL!\n");
+ if (!devpriv->dmabuf[0])
/* maybe experiment with try_to_free_pages() will help .... */
return -EBUSY; /* no buffer :-( */
- }
devpriv->dmapages[0] = pages;
devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
/* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */
devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
- if (!devpriv->dmabuf[1]) {
- printk
- (", unable to allocate DMA buffer, FAIL!\n");
+ if (!devpriv->dmabuf[1])
return -EBUSY;
- }
devpriv->dmapages[1] = pages;
devpriv->hwdmaptr[1] =
virt_to_bus((void *)devpriv->dmabuf[1]);
@@ -2017,11 +2000,10 @@ no_dma:
}
/* select 1/10MHz oscilator */
- if ((it->options[3] == 0) || (it->options[3] == 10)) {
+ if ((it->options[3] == 0) || (it->options[3] == 10))
devpriv->i8253_osc_base = 100;
- } else {
+ else
devpriv->i8253_osc_base = 1000;
- }
/* max sampling speed */
devpriv->ns_min = this_board->ns_min;
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 3ad04aaa1e3c..eddac00e4e29 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -371,15 +371,15 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
iobase = it->options[0];
irq[0] = it->options[1];
- printk(KERN_INFO "comedi%d: %s: io: %lx ", dev->minor, driver.driver_name,
- iobase);
+ printk(KERN_INFO "comedi%d: %s: io: %lx attaching...\n", dev->minor,
+ driver.driver_name, iobase);
dev->iobase = iobase;
if (!iobase || !request_region(iobase,
thisboard->total_iosize,
driver.driver_name)) {
- printk(KERN_ERR "I/O port conflict\n");
+ printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor);
return -EIO;
}
@@ -394,7 +394,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* convenient macro defined in comedidev.h.
*/
if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) {
- printk(KERN_ERR "cannot allocate private data structure\n");
+ printk(KERN_ERR "comedi%d: cannot allocate private data structure\n",
+ dev->minor);
return -ENOMEM;
}
@@ -417,7 +418,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private),
GFP_KERNEL);
if (!devpriv->sprivs) {
- printk(KERN_ERR "cannot allocate subdevice private data structures\n");
+ printk(KERN_ERR "comedi%d: cannot allocate subdevice private data structures\n",
+ dev->minor);
return -ENOMEM;
}
/*
@@ -427,7 +429,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* Allocate 1 AI + 1 AO + 2 DIO subdevs (24 lines per DIO)
*/
if (alloc_subdevices(dev, n_subdevs) < 0) {
- printk(KERN_ERR "cannot allocate subdevice data structures\n");
+ printk(KERN_ERR "comedi%d: cannot allocate subdevice data structures\n",
+ dev->minor);
return -ENOMEM;
}
@@ -557,14 +560,15 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
*/
if (irq[0]) {
- printk(KERN_DEBUG "irq: %u ", irq[0]);
+ printk(KERN_DEBUG "comedi%d: irq: %u\n", dev->minor, irq[0]);
if (thisboard->dio_num_asics == 2 && irq[1])
- printk(KERN_DEBUG "second ASIC irq: %u ", irq[1]);
+ printk(KERN_DEBUG "comedi%d: second ASIC irq: %u\n",
+ dev->minor, irq[1]);
} else {
- printk(KERN_INFO "(IRQ mode disabled) ");
+ printk(KERN_INFO "comedi%d: (IRQ mode disabled)\n", dev->minor);
}
- printk(KERN_INFO "attached\n");
+ printk(KERN_INFO "comedi%d: attached\n", dev->minor);
return 1;
}
@@ -663,7 +667,7 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev,
}
#ifdef DAMMIT_ITS_BROKEN
/* DEBUG */
- printk(KERN_DEBUG "data_out_byte %02x\n", (unsigned)byte);
+ printk("data_out_byte %02x\n", (unsigned)byte);
#endif
/* save the digital input lines for this byte.. */
s->state |= ((unsigned int)byte) << offset;
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index b2c2c8971a32..661ba2e03892 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -295,15 +295,15 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
irq[0] = it->options[1];
irq[1] = it->options[2];
- printk("comedi%d: %s: io: %lx ", dev->minor, driver.driver_name,
- iobase);
+ dev_dbg(dev->hw_dev, "comedi%d: %s: io: %lx attached\n", dev->minor,
+ driver.driver_name, iobase);
dev->iobase = iobase;
if (!iobase || !request_region(iobase,
thisboard->num_asics * ASIC_IOSIZE,
driver.driver_name)) {
- printk("I/O port conflict\n");
+ dev_err(dev->hw_dev, "I/O port conflict\n");
return -EIO;
}
@@ -318,7 +318,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* convenient macro defined in comedidev.h.
*/
if (alloc_private(dev, sizeof(struct pcmuio_private)) < 0) {
- printk("cannot allocate private data structure\n");
+ dev_warn(dev->hw_dev, "cannot allocate private data structure\n");
return -ENOMEM;
}
@@ -337,7 +337,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
kcalloc(n_subdevs, sizeof(struct pcmuio_subdev_private),
GFP_KERNEL);
if (!devpriv->sprivs) {
- printk("cannot allocate subdevice private data structures\n");
+ dev_warn(dev->hw_dev, "cannot allocate subdevice private data structures\n");
return -ENOMEM;
}
/*
@@ -348,7 +348,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* 96-channel version of the board.
*/
if (alloc_subdevices(dev, n_subdevs) < 0) {
- printk("cannot allocate subdevice data structures\n");
+ dev_dbg(dev->hw_dev, "cannot allocate subdevice data structures\n");
return -ENOMEM;
}
@@ -436,14 +436,13 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
irqs.. */
if (irq[0]) {
- printk("irq: %u ", irq[0]);
+ dev_dbg(dev->hw_dev, "irq: %u\n", irq[0]);
if (irq[1] && thisboard->num_asics == 2)
- printk("second ASIC irq: %u ", irq[1]);
+ dev_dbg(dev->hw_dev, "second ASIC irq: %u\n", irq[1]);
} else {
- printk("(IRQ mode disabled) ");
+ dev_dbg(dev->hw_dev, "(IRQ mode disabled)\n");
}
- printk("attached\n");
return 1;
}
@@ -460,7 +459,8 @@ static int pcmuio_detach(struct comedi_device *dev)
{
int i;
- printk("comedi%d: %s: remove\n", dev->minor, driver.driver_name);
+ dev_dbg(dev->hw_dev, "comedi%d: %s: remove\n", dev->minor,
+ driver.driver_name);
if (dev->iobase)
release_region(dev->iobase, ASIC_IOSIZE * thisboard->num_asics);
@@ -501,7 +501,8 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev,
#ifdef DAMMIT_ITS_BROKEN
/* DEBUG */
- printk("write mask: %08x data: %08x\n", data[0], data[1]);
+ dev_dbg(dev->hw_dev, "write mask: %08x data: %08x\n", data[0],
+ data[1]);
#endif
s->state = 0;
@@ -537,7 +538,7 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev,
}
#ifdef DAMMIT_ITS_BROKEN
/* DEBUG */
- printk("data_out_byte %02x\n", (unsigned)byte);
+ dev_dbg(dev->hw_dev, "data_out_byte %02x\n", (unsigned)byte);
#endif
/* save the digital input lines for this byte.. */
s->state |= ((unsigned int)byte) << offset;
@@ -548,7 +549,8 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev,
#ifdef DAMMIT_ITS_BROKEN
/* DEBUG */
- printk("s->state %08x data_out %08x\n", s->state, data[1]);
+ dev_dbg(dev->hw_dev, "s->state %08x data_out %08x\n", s->state,
+ data[1]);
#endif
return 2;
@@ -951,14 +953,13 @@ pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
spin_lock_irqsave(&subpriv->intr.spinlock, flags);
s->async->inttrig = 0;
- if (subpriv->intr.active) {
+ if (subpriv->intr.active)
event = pcmuio_start_intr(dev, s);
- }
+
spin_unlock_irqrestore(&subpriv->intr.spinlock, flags);
- if (event) {
+ if (event)
comedi_event(dev, s);
- }
return 1;
}
@@ -1000,9 +1001,8 @@ static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
spin_unlock_irqrestore(&subpriv->intr.spinlock, flags);
- if (event) {
+ if (event)
comedi_event(dev, s);
- }
return 0;
}
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index ade2202b6231..d880c2f6fbc1 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -824,7 +824,7 @@ static int serial2002_attach(struct comedi_device *dev,
{
struct comedi_subdevice *s;
- printk("comedi%d: serial2002: ", dev->minor);
+ dev_dbg(dev->hw_dev, "comedi%d: attached\n", dev->minor);
dev->board_name = thisboard->name;
if (alloc_private(dev, sizeof(struct serial2002_private)) < 0)
return -ENOMEM;
@@ -832,7 +832,8 @@ static int serial2002_attach(struct comedi_device *dev,
dev->close = serial_2002_close;
devpriv->port = it->options[0];
devpriv->speed = it->options[1];
- printk("/dev/ttyS%d @ %d\n", devpriv->port, devpriv->speed);
+ dev_dbg(dev->hw_dev, "/dev/ttyS%d @ %d\n", devpriv->port,
+ devpriv->speed);
if (alloc_subdevices(dev, 5) < 0)
return -ENOMEM;
@@ -891,7 +892,7 @@ static int serial2002_detach(struct comedi_device *dev)
struct comedi_subdevice *s;
int i;
- printk("comedi%d: serial2002: remove\n", dev->minor);
+ dev_dbg(dev->hw_dev, "comedi%d: remove\n", dev->minor);
for (i = 0; i < 5; i++) {
s = &dev->subdevices[i];
kfree(s->maxdata_list);
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index 6144afb8cbaa..ca6bcf8b0231 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -1524,15 +1524,17 @@ static int usbdux_ao_inttrig(struct comedi_device *dev,
return -EFAULT;
down(&this_usbduxsub->sem);
+
if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
+ ret = -ENODEV;
+ goto out;
}
if (trignum != 0) {
dev_err(&this_usbduxsub->interface->dev,
"comedi%d: usbdux_ao_inttrig: invalid trignum\n",
dev->minor);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (!(this_usbduxsub->ao_cmd_running)) {
this_usbduxsub->ao_cmd_running = 1;
@@ -1542,8 +1544,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev,
"comedi%d: usbdux_ao_inttrig: submitURB: "
"err=%d\n", dev->minor, ret);
this_usbduxsub->ao_cmd_running = 0;
- up(&this_usbduxsub->sem);
- return ret;
+ goto out;
}
s->async->inttrig = NULL;
} else {
@@ -1551,8 +1552,10 @@ static int usbdux_ao_inttrig(struct comedi_device *dev,
"comedi%d: ao_inttrig but acqu is already running.\n",
dev->minor);
}
+ ret = 1;
+out:
up(&this_usbduxsub->sem);
- return 1;
+ return ret;
}
static int usbdux_ao_cmdtest(struct comedi_device *dev,
@@ -2689,6 +2692,7 @@ static int usbduxsigma_attach(struct comedi_device *dev,
if (ret < 0) {
dev_err(&udev->interface->dev,
"comedi%d: no space for subdev\n", dev->minor);
+ up(&udev->sem);
up(&start_stop_sem);
return ret;
}
diff --git a/drivers/staging/crystalhd/bc_dts_defs.h b/drivers/staging/crystalhd/bc_dts_defs.h
index fde5b0627f6b..8cd51a7aad8e 100644
--- a/drivers/staging/crystalhd/bc_dts_defs.h
+++ b/drivers/staging/crystalhd/bc_dts_defs.h
@@ -296,43 +296,79 @@ enum {
vdecColourPrimariesSMPTE240M,
vdecColourPrimariesGenericFilm,
};
-
+/**
+ * @vdecRESOLUTION_CUSTOM: custom
+ * @vdecRESOLUTION_480i: 480i
+ * @vdecRESOLUTION_1080i: 1080i (1920x1080, 60i)
+ * @vdecRESOLUTION_NTSC: NTSC (720x483, 60i)
+ * @vdecRESOLUTION_480p: 480p (720x480, 60p)
+ * @vdecRESOLUTION_720p: 720p (1280x720, 60p)
+ * @vdecRESOLUTION_PAL1: PAL_1 (720x576, 50i)
+ * @vdecRESOLUTION_1080i25: 1080i25 (1920x1080, 50i)
+ * @vdecRESOLUTION_720p50: 720p50 (1280x720, 50p)
+ * @vdecRESOLUTION_576p: 576p (720x576, 50p)
+ * @vdecRESOLUTION_1080i29_97: 1080i (1920x1080, 59.94i)
+ * @vdecRESOLUTION_720p59_94: 720p (1280x720, 59.94p)
+ * @vdecRESOLUTION_SD_DVD: SD DVD (720x483, 60i)
+ * @vdecRESOLUTION_480p656: 480p (720x480, 60p),
+ * output bus width 8 bit, clock 74.25MHz
+ * @vdecRESOLUTION_1080p23_976: 1080p23_976 (1920x1080, 23.976p)
+ * @vdecRESOLUTION_720p23_976: 720p23_976 (1280x720p, 23.976p)
+ * @vdecRESOLUTION_240p29_97: 240p (1440x240, 29.97p )
+ * @vdecRESOLUTION_240p30: 240p (1440x240, 30p)
+ * @vdecRESOLUTION_288p25: 288p (1440x288p, 25p)
+ * @vdecRESOLUTION_1080p29_97: 1080p29_97 (1920x1080, 29.97p)
+ * @vdecRESOLUTION_1080p30: 1080p30 (1920x1080, 30p)
+ * @vdecRESOLUTION_1080p24: 1080p24 (1920x1080, 24p)
+ * @vdecRESOLUTION_1080p25: 1080p25 (1920x1080, 25p)
+ * @vdecRESOLUTION_720p24: 720p24 (1280x720, 25p)
+ * @vdecRESOLUTION_720p29_97: 720p29.97 (1280x720, 29.97p)
+ * @vdecRESOLUTION_480p23_976: 480p23.976 (720*480, 23.976)
+ * @vdecRESOLUTION_480p29_97: 480p29.976 (720*480, 29.97p)
+ * @vdecRESOLUTION_576p25: 576p25 (720*576, 25p)
+ * @vdecRESOLUTION_480p0: 480p (720x480, 0p)
+ * @vdecRESOLUTION_480i0: 480i (720x480, 0i)
+ * @vdecRESOLUTION_576p0: 576p (720x576, 0p)
+ * @vdecRESOLUTION_720p0: 720p (1280x720, 0p)
+ * @vdecRESOLUTION_1080p0: 1080p (1920x1080, 0p)
+ * @vdecRESOLUTION_1080i0: 1080i (1920x1080, 0i)
+ */
enum {
- vdecRESOLUTION_CUSTOM = 0x00000000, /* custom */
- vdecRESOLUTION_480i = 0x00000001, /* 480i */
- vdecRESOLUTION_1080i = 0x00000002, /* 1080i (1920x1080, 60i) */
- vdecRESOLUTION_NTSC = 0x00000003, /* NTSC (720x483, 60i) */
- vdecRESOLUTION_480p = 0x00000004, /* 480p (720x480, 60p) */
- vdecRESOLUTION_720p = 0x00000005, /* 720p (1280x720, 60p) */
- vdecRESOLUTION_PAL1 = 0x00000006, /* PAL_1 (720x576, 50i) */
- vdecRESOLUTION_1080i25 = 0x00000007, /* 1080i25 (1920x1080, 50i) */
- vdecRESOLUTION_720p50 = 0x00000008, /* 720p50 (1280x720, 50p) */
- vdecRESOLUTION_576p = 0x00000009, /* 576p (720x576, 50p) */
- vdecRESOLUTION_1080i29_97 = 0x0000000A, /* 1080i (1920x1080, 59.94i) */
- vdecRESOLUTION_720p59_94 = 0x0000000B, /* 720p (1280x720, 59.94p) */
- vdecRESOLUTION_SD_DVD = 0x0000000C, /* SD DVD (720x483, 60i) */
- vdecRESOLUTION_480p656 = 0x0000000D, /* 480p (720x480, 60p), output bus width 8 bit, clock 74.25MHz */
- vdecRESOLUTION_1080p23_976 = 0x0000000E, /* 1080p23_976 (1920x1080, 23.976p) */
- vdecRESOLUTION_720p23_976 = 0x0000000F, /* 720p23_976 (1280x720p, 23.976p) */
- vdecRESOLUTION_240p29_97 = 0x00000010, /* 240p (1440x240, 29.97p ) */
- vdecRESOLUTION_240p30 = 0x00000011, /* 240p (1440x240, 30p) */
- vdecRESOLUTION_288p25 = 0x00000012, /* 288p (1440x288p, 25p) */
- vdecRESOLUTION_1080p29_97 = 0x00000013, /* 1080p29_97 (1920x1080, 29.97p) */
- vdecRESOLUTION_1080p30 = 0x00000014, /* 1080p30 (1920x1080, 30p) */
- vdecRESOLUTION_1080p24 = 0x00000015, /* 1080p24 (1920x1080, 24p) */
- vdecRESOLUTION_1080p25 = 0x00000016, /* 1080p25 (1920x1080, 25p) */
- vdecRESOLUTION_720p24 = 0x00000017, /* 720p24 (1280x720, 25p) */
- vdecRESOLUTION_720p29_97 = 0x00000018, /* 720p29.97 (1280x720, 29.97p) */
- vdecRESOLUTION_480p23_976 = 0x00000019, /* 480p23.976 (720*480, 23.976) */
- vdecRESOLUTION_480p29_97 = 0x0000001A, /* 480p29.976 (720*480, 29.97p) */
- vdecRESOLUTION_576p25 = 0x0000001B, /* 576p25 (720*576, 25p) */
+ vdecRESOLUTION_CUSTOM = 0x00000000,
+ vdecRESOLUTION_480i = 0x00000001,
+ vdecRESOLUTION_1080i = 0x00000002,
+ vdecRESOLUTION_NTSC = 0x00000003,
+ vdecRESOLUTION_480p = 0x00000004,
+ vdecRESOLUTION_720p = 0x00000005,
+ vdecRESOLUTION_PAL1 = 0x00000006,
+ vdecRESOLUTION_1080i25 = 0x00000007,
+ vdecRESOLUTION_720p50 = 0x00000008,
+ vdecRESOLUTION_576p = 0x00000009,
+ vdecRESOLUTION_1080i29_97 = 0x0000000A,
+ vdecRESOLUTION_720p59_94 = 0x0000000B,
+ vdecRESOLUTION_SD_DVD = 0x0000000C,
+ vdecRESOLUTION_480p656 = 0x0000000D,
+ vdecRESOLUTION_1080p23_976 = 0x0000000E,
+ vdecRESOLUTION_720p23_976 = 0x0000000F,
+ vdecRESOLUTION_240p29_97 = 0x00000010,
+ vdecRESOLUTION_240p30 = 0x00000011,
+ vdecRESOLUTION_288p25 = 0x00000012,
+ vdecRESOLUTION_1080p29_97 = 0x00000013,
+ vdecRESOLUTION_1080p30 = 0x00000014,
+ vdecRESOLUTION_1080p24 = 0x00000015,
+ vdecRESOLUTION_1080p25 = 0x00000016,
+ vdecRESOLUTION_720p24 = 0x00000017,
+ vdecRESOLUTION_720p29_97 = 0x00000018,
+ vdecRESOLUTION_480p23_976 = 0x00000019,
+ vdecRESOLUTION_480p29_97 = 0x0000001A,
+ vdecRESOLUTION_576p25 = 0x0000001B,
/* For Zero Frame Rate */
- vdecRESOLUTION_480p0 = 0x0000001C, /* 480p (720x480, 0p) */
- vdecRESOLUTION_480i0 = 0x0000001D, /* 480i (720x480, 0i) */
- vdecRESOLUTION_576p0 = 0x0000001E, /* 576p (720x576, 0p) */
- vdecRESOLUTION_720p0 = 0x0000001F, /* 720p (1280x720, 0p) */
- vdecRESOLUTION_1080p0 = 0x00000020, /* 1080p (1920x1080, 0p) */
- vdecRESOLUTION_1080i0 = 0x00000021, /* 1080i (1920x1080, 0i) */
+ vdecRESOLUTION_480p0 = 0x0000001C,
+ vdecRESOLUTION_480i0 = 0x0000001D,
+ vdecRESOLUTION_576p0 = 0x0000001E,
+ vdecRESOLUTION_720p0 = 0x0000001F,
+ vdecRESOLUTION_1080p0 = 0x00000020,
+ vdecRESOLUTION_1080i0 = 0x00000021,
};
/* Bit definitions for 'flags' field */
@@ -359,14 +395,23 @@ enum _BC_OUTPUT_FORMAT {
MODE422_YUY2 = 0x1,
MODE422_UYVY = 0x2,
};
-
+/**
+ * struct BC_PIC_INFO_BLOCK
+ * @timeStam;: Timestamp
+ * @picture_number: Ordinal display number
+ * @width: pixels
+ * @height: pixels
+ * @chroma_format: 0x420, 0x422 or 0x444
+ * @n_drop;: number of non-reference frames
+ * remaining to be dropped
+ */
struct BC_PIC_INFO_BLOCK {
/* Common fields. */
- uint64_t timeStamp; /* Timestamp */
- uint32_t picture_number; /* Ordinal display number */
- uint32_t width; /* pixels */
- uint32_t height; /* pixels */
- uint32_t chroma_format; /* 0x420, 0x422 or 0x444 */
+ uint64_t timeStamp;
+ uint32_t picture_number;
+ uint32_t width;
+ uint32_t height;
+ uint32_t chroma_format;
uint32_t pulldown;
uint32_t flags;
uint32_t frame_rate;
@@ -376,7 +421,8 @@ struct BC_PIC_INFO_BLOCK {
uint32_t sess_num;
uint32_t ycom;
uint32_t custom_aspect_ratio_width_height;
- uint32_t n_drop; /* number of non-reference frames remaining to be dropped */
+ uint32_t n_drop; /* number of non-reference frames
+ remaining to be dropped */
/* Protocol-specific extensions. */
union {
@@ -390,43 +436,71 @@ struct BC_PIC_INFO_BLOCK {
/*------------------------------------------------------*
* ProcOut Info *
*------------------------------------------------------*/
-/* Optional flags for ProcOut Interface.*/
+
+/**
+ * enum POUT_OPTIONAL_IN_FLAGS - Optional flags for ProcOut Interface.
+ * @BC_POUT_FLAGS_YV12: Copy Data in YV12 format
+ * @BC_POUT_FLAGS_STRIDE: Stride size is valid.
+ * @BC_POUT_FLAGS_SIZE: Take size information from Application
+ * @BC_POUT_FLAGS_INTERLACED: copy only half the bytes
+ * @BC_POUT_FLAGS_INTERLEAVED: interleaved frame
+ * @: * @BC_POUT_FLAGS_FMT_CHANGE: Data is not VALID when this flag is set
+ * @BC_POUT_FLAGS_PIB_VALID: PIB Information valid
+ * @BC_POUT_FLAGS_ENCRYPTED: Data is encrypted.
+ * @BC_POUT_FLAGS_FLD_BOT: Bottom Field data
+ */
enum POUT_OPTIONAL_IN_FLAGS_ {
/* Flags from App to Device */
- BC_POUT_FLAGS_YV12 = 0x01, /* Copy Data in YV12 format */
- BC_POUT_FLAGS_STRIDE = 0x02, /* Stride size is valid. */
- BC_POUT_FLAGS_SIZE = 0x04, /* Take size information from Application */
- BC_POUT_FLAGS_INTERLACED = 0x08, /* copy only half the bytes */
- BC_POUT_FLAGS_INTERLEAVED = 0x10, /* interleaved frame */
+ BC_POUT_FLAGS_YV12 = 0x01,
+ BC_POUT_FLAGS_STRIDE = 0x02,
+ BC_POUT_FLAGS_SIZE = 0x04,
+ BC_POUT_FLAGS_INTERLACED = 0x08,
+ BC_POUT_FLAGS_INTERLEAVED = 0x10,
/* Flags from Device to APP */
- BC_POUT_FLAGS_FMT_CHANGE = 0x10000, /* Data is not VALID when this flag is set */
- BC_POUT_FLAGS_PIB_VALID = 0x20000, /* PIB Information valid */
- BC_POUT_FLAGS_ENCRYPTED = 0x40000, /* Data is encrypted. */
- BC_POUT_FLAGS_FLD_BOT = 0x80000, /* Bottom Field data */
+ BC_POUT_FLAGS_FMT_CHANGE = 0x10000,
+ BC_POUT_FLAGS_PIB_VALID = 0x20000,
+ BC_POUT_FLAGS_ENCRYPTED = 0x40000,
+ BC_POUT_FLAGS_FLD_BOT = 0x80000,
};
-typedef enum BC_STATUS(*dts_pout_callback)(void *shnd, uint32_t width, uint32_t height, uint32_t stride, void *pOut);
+typedef enum BC_STATUS(*dts_pout_callback)(void *shnd, uint32_t width,
+ uint32_t height, uint32_t stride, void *pOut);
/* Line 21 Closed Caption */
/* User Data */
#define MAX_UD_SIZE 1792 /* 1920 - 128 */
+/**
+ * struct BC_DTS_PROC_OUT
+ * @Ybuff: Caller Supplied buffer for Y data
+ * @YbuffSz: Caller Supplied Y buffer size
+ * @YBuffDoneSz: Transferred Y datasize
+ * @*UVbuff: Caller Supplied buffer for UV data
+ * @UVbuffSz: Caller Supplied UV buffer size
+ * @UVBuffDoneSz: Transferred UV data size
+ * @StrideSz: Caller supplied Stride Size
+ * @PoutFlags: Call IN Flags
+ * @discCnt: Picture discontinuity count
+ * @PicInfo: Picture Information Block Data
+ * @b422Mode: Picture output Mode
+ * @bPibEnc: PIB encrypted
+ */
struct BC_DTS_PROC_OUT {
- uint8_t *Ybuff; /* Caller Supplied buffer for Y data */
- uint32_t YbuffSz; /* Caller Supplied Y buffer size */
- uint32_t YBuffDoneSz; /* Transferred Y datasize */
+ uint8_t *Ybuff;
+ uint32_t YbuffSz;
+ uint32_t YBuffDoneSz;
- uint8_t *UVbuff; /* Caller Supplied buffer for UV data */
- uint32_t UVbuffSz; /* Caller Supplied UV buffer size */
- uint32_t UVBuffDoneSz; /* Transferred UV data size */
+ uint8_t *UVbuff;
+ uint32_t UVbuffSz;
+ uint32_t UVBuffDoneSz;
- uint32_t StrideSz; /* Caller supplied Stride Size */
- uint32_t PoutFlags; /* Call IN Flags */
+ uint32_t StrideSz;
+ uint32_t PoutFlags;
- uint32_t discCnt; /* Picture discontinuity count */
+ uint32_t discCnt;
- struct BC_PIC_INFO_BLOCK PicInfo; /* Picture Information Block Data */
+ struct BC_PIC_INFO_BLOCK PicInfo;
/* Line 21 Closed Caption */
/* User Data */
@@ -436,39 +510,47 @@ struct BC_DTS_PROC_OUT {
void *hnd;
dts_pout_callback AppCallBack;
uint8_t DropFrames;
- uint8_t b422Mode; /* Picture output Mode */
- uint8_t bPibEnc; /* PIB encrypted */
+ uint8_t b422Mode;
+ uint8_t bPibEnc;
uint8_t bRevertScramble;
};
-
+/**
+ * struct BC_DTS_STATUS
+ * @ReadyListCount: Number of frames in ready list (reported by driver)
+ * @PowerStateChange: Number of active state power
+ * transitions (reported by driver)
+ * @FramesDropped: Number of frames dropped. (reported by DIL)
+ * @FramesCaptured: Number of frames captured. (reported by DIL)
+ * @FramesRepeated: Number of frames repeated. (reported by DIL)
+ * @InputCount: Times compressed video has been sent to the HW.
+ * i.e. Successful DtsProcInput() calls (reported by DIL)
+ * @InputTotalSize: Amount of compressed video that has been sent to the HW.
+ * (reported by DIL)
+ * @InputBusyCount: Times compressed video has attempted to be sent to the HW
+ * but the input FIFO was full. (reported by DIL)
+ * @PIBMissCount: Amount of times a PIB is invalid. (reported by DIL)
+ * @cpbEmptySize: supported only for H.264, specifically changed for
+ * Adobe. Report size of CPB buffer available. (reported by DIL)
+ * @NextTimeStamp: TimeStamp of the next picture that will be returned
+ * by a call to ProcOutput. Added for Adobe. Reported
+ * back from the driver
+ */
struct BC_DTS_STATUS {
- uint8_t ReadyListCount; /* Number of frames in ready list (reported by driver) */
- uint8_t FreeListCount; /* Number of frame buffers free. (reported by driver) */
- uint8_t PowerStateChange; /* Number of active state power transitions (reported by driver) */
+ uint8_t ReadyListCount;
+ uint8_t FreeListCount;
+ uint8_t PowerStateChange;
uint8_t reserved_[1];
-
- uint32_t FramesDropped; /* Number of frames dropped. (reported by DIL) */
- uint32_t FramesCaptured; /* Number of frames captured. (reported by DIL) */
- uint32_t FramesRepeated; /* Number of frames repeated. (reported by DIL) */
-
- uint32_t InputCount; /* Times compressed video has been sent to the HW.
- * i.e. Successful DtsProcInput() calls (reported by DIL) */
- uint64_t InputTotalSize; /* Amount of compressed video that has been sent to the HW.
- * (reported by DIL) */
- uint32_t InputBusyCount; /* Times compressed video has attempted to be sent to the HW
- * but the input FIFO was full. (reported by DIL) */
-
- uint32_t PIBMissCount; /* Amount of times a PIB is invalid. (reported by DIL) */
-
- uint32_t cpbEmptySize; /* supported only for H.264, specifically changed for
- * Adobe. Report size of CPB buffer available.
- * Reported by DIL */
- uint64_t NextTimeStamp; /* TimeStamp of the next picture that will be returned
- * by a call to ProcOutput. Added for Adobe. Reported
- * back from the driver */
+ uint32_t FramesDropped;
+ uint32_t FramesCaptured;
+ uint32_t FramesRepeated;
+ uint32_t InputCount;
+ uint64_t InputTotalSize;
+ uint32_t InputBusyCount;
+ uint32_t PIBMissCount;
+ uint32_t cpbEmptySize;
+ uint64_t NextTimeStamp;
uint8_t reserved__[16];
-
};
#define BC_SWAP32(_v) \
diff --git a/drivers/staging/cxt1e1/comet.h b/drivers/staging/cxt1e1/comet.h
index 5cb3afda0112..e06da4a6f6f6 100644
--- a/drivers/staging/cxt1e1/comet.h
+++ b/drivers/staging/cxt1e1/comet.h
@@ -1,7 +1,3 @@
-/*
- * $Id: comet.h,v 1.3 2005/09/28 00:10:07 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_COMET_H_
#define _INC_COMET_H_
@@ -23,27 +19,9 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.3 $
- * Last changed on $Date: 2005/09/28 00:10:07 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: comet.h,v $
- * Revision 1.3 2005/09/28 00:10:07 rickd
- * Add RCS header. Switch to structure usage.
- *
- * Revision 1.2 2005/04/28 23:43:03 rickd
- * Add RCS tracking heading.
- *
- *-----------------------------------------------------------------------------
*/
-#if defined(__FreeBSD__) || defined (__NetBSD__)
-#include <sys/types.h>
-#else
#include <linux/types.h>
-#endif
-
#define VINT32 volatile u_int32_t
diff --git a/drivers/staging/cxt1e1/comet_tables.c b/drivers/staging/cxt1e1/comet_tables.c
index db1293c71a6d..84931117da35 100644
--- a/drivers/staging/cxt1e1/comet_tables.c
+++ b/drivers/staging/cxt1e1/comet_tables.c
@@ -1,7 +1,3 @@
-/*
- * $Id: comet_tables.c,v 1.2 2005/10/17 23:55:27 rickd PMCC4_3_1B $
- */
-
/*-----------------------------------------------------------------------------
* comet_tables.c - waveform tables for the PM4351 'COMET'
*
@@ -20,28 +16,8 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.2 $
- * Last changed on $Date: 2005/10/17 23:55:27 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: comet_tables.c,v $
- * Revision 1.2 2005/10/17 23:55:27 rickd
- * Note that 75 Ohm transmit waveform is not supported on PMCC4.
- *
- * Revision 1.1 2005/09/28 00:10:05 rickd
- * Cosmetic alignment of tables for readability.
- *
- * Revision 1.0 2005/05/10 22:47:53 rickd
- * Initial revision
- *
- *-----------------------------------------------------------------------------
*/
-char SBEid_pmcc4_comet_tblc[] =
- "@(#)comet_tables.c - $Revision: 1.2 $ (c) Copyright 2004-2005 SBE, Inc.";
-
-
#include <linux/types.h>
/*****************************************************************************
diff --git a/drivers/staging/cxt1e1/comet_tables.h b/drivers/staging/cxt1e1/comet_tables.h
index 80424a26a169..3e2e5badf787 100644
--- a/drivers/staging/cxt1e1/comet_tables.h
+++ b/drivers/staging/cxt1e1/comet_tables.h
@@ -1,7 +1,3 @@
-/*
- * $Id: comet_tables.h,v 1.5 2006/01/02 22:37:31 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_COMET_TBLS_H_
#define _INC_COMET_TBLS_H_
@@ -23,26 +19,6 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.5 $
- * Last changed on $Date: 2006/01/02 22:37:31 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: comet_tables.h,v $
- * Revision 1.5 2006/01/02 22:37:31 rickd
- * Double indexed arrays need sizings to avoid CC errors under
- * gcc 4.0.0
- *
- * Revision 1.4 2005/10/17 23:55:28 rickd
- * The 75 Ohm transmit waveform is not supported on PMCC4.
- *
- * Revision 1.3 2005/09/28 00:10:08 rickd
- * Add GNU License info. Structures moved to -C- file.
- *
- * Revision 1.2 2005/04/28 23:43:04 rickd
- * Add RCS tracking heading.
- *
- *-----------------------------------------------------------------------------
*/
diff --git a/drivers/staging/cxt1e1/libsbew.h b/drivers/staging/cxt1e1/libsbew.h
index ae8f06d05bed..4254c0426db9 100644
--- a/drivers/staging/cxt1e1/libsbew.h
+++ b/drivers/staging/cxt1e1/libsbew.h
@@ -1,7 +1,3 @@
-/*
- * $Id: libsbew.h,v 2.1 2005/10/27 18:54:19 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_LIBSBEW_H_
#define _INC_LIBSBEW_H_
@@ -25,32 +21,8 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 2.1 $
- * Last changed on $Date: 2005/10/27 18:54:19 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: libsbew.h,v $
- * Revision 2.1 2005/10/27 18:54:19 rickd
- * Add E1PLAIN support.
- *
- * Revision 2.0 2005/09/28 00:10:08 rickd
- * Customized for PMCC4 comet-per-port design.
- *
- * Revision 1.15 2005/03/29 00:51:31 rickd
- * File imported from C1T3 port, Revision 1.15
- *-----------------------------------------------------------------------------
*/
-#ifndef __KERNEL__
-#include <sys/types.h>
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
/********************************/
/** set driver logging level **/
/********************************/
@@ -574,8 +546,4 @@ struct sbecom_port_param
extern int wancfg_set_tsioc (wcfg_t *, struct wanc1t3_ts_param *);
#endif
-#ifdef __cplusplus
-}
-#endif
-
#endif /*** _INC_LIBSBEW_H_ ***/
diff --git a/drivers/staging/cxt1e1/musycc.c b/drivers/staging/cxt1e1/musycc.c
index 5cc3423a6646..90c0f1e30f65 100644
--- a/drivers/staging/cxt1e1/musycc.c
+++ b/drivers/staging/cxt1e1/musycc.c
@@ -1,7 +1,3 @@
-/*
- * $Id: musycc.c,v 2.1 2007/08/15 23:32:17 rickd PMCC4_3_1B $
- */
-
unsigned int max_intcnt = 0;
unsigned int max_bh = 0;
@@ -24,53 +20,8 @@ unsigned int max_bh = 0;
* For further information, contact via email: support@onestopsystems.com
* One Stop Systems, Inc. Escondido, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 2.1 $
- * Last changed on $Date: 2007/08/15 23:32:17 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: musycc.c,v $
- * Revision 2.1 2007/08/15 23:32:17 rickd
- * Use 'if 0' instead of GNU comment delimeter to avoid line wrap induced compiler errors.
- *
- * Revision 2.0 2007/08/15 22:13:20 rickd
- * Update to printf pointer %p usage and correct some UINT to ULONG for
- * 64bit comptibility.
- *
- * Revision 1.7 2006/04/21 00:56:40 rickd
- * workqueue files now prefixed with <sbecom> prefix.
- *
- * Revision 1.6 2005/10/27 18:54:19 rickd
- * Clean out old code. Default to HDLC_FCS16, not TRANS.
- *
- * Revision 1.5 2005/10/17 23:55:28 rickd
- * Initial port of NCOMM support patches from original work found
- * in pmc_c4t1e1 as updated by NCOMM. Ref: CONFIG_SBE_PMCC4_NCOMM.
- *
- * Revision 1.4 2005/10/13 20:35:25 rickd
- * Cleanup warning for unused <flags> variable.
- *
- * Revision 1.3 2005/10/13 19:19:22 rickd
- * Disable redundant driver removal cleanup code.
- *
- * Revision 1.2 2005/10/11 18:36:16 rickd
- * Clean up warning messages caused by de-implemented some <flags> associated
- * with spin_lock() removals.
- *
- * Revision 1.1 2005/10/05 00:45:28 rickd
- * Re-enable xmit on flow-controlled and full channel to fix restart hang.
- * Add some temp spin-lock debug code (rld_spin_owner).
- *
- * Revision 1.0 2005/09/28 00:10:06 rickd
- * Initial release for C4T1E1 support. Lots of transparent
- * mode updates.
- *
- *-----------------------------------------------------------------------------
*/
-char SBEid_pmcc4_musyccc[] =
-"@(#)musycc.c - $Revision: 2.1 $ (c) Copyright 2004-2006 SBE, Inc.";
-
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/types.h>
diff --git a/drivers/staging/cxt1e1/musycc.h b/drivers/staging/cxt1e1/musycc.h
index 68f3660f4477..cf6b54e15689 100644
--- a/drivers/staging/cxt1e1/musycc.h
+++ b/drivers/staging/cxt1e1/musycc.h
@@ -1,7 +1,3 @@
-/*
- * $Id: musycc.h,v 1.3 2005/09/28 00:10:08 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_MUSYCC_H_
#define _INC_MUSYCC_H_
@@ -24,36 +20,13 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.3 $
- * Last changed on $Date: 2005/09/28 00:10:08 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: musycc.h,v $
- * Revision 1.3 2005/09/28 00:10:08 rickd
- * Add GNU license info. Add PMCC4 PCI/DevIDs. Implement new
- * musycc reg&bits namings. Use PORTMAP_0 GCD grouping.
- *
- * Revision 1.2 2005/04/28 23:43:04 rickd
- * Add RCS tracking heading.
- *
- *-----------------------------------------------------------------------------
*/
-#if defined (__FreeBSD__) || defined (__NetBSD__)
-#include <sys/types.h>
-#else
#include <linux/types.h>
-#endif
#define VINT8 volatile u_int8_t
#define VINT32 volatile u_int32_t
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
#include "pmcc4_defs.h"
@@ -448,10 +421,6 @@ extern "C"
/* This must be defined on an entire channel group (Port) basis */
#define SUERM_THRESHOLD 0x1f
-#ifdef __cplusplus
-}
-#endif
-
#undef VINT32
#undef VINT8
diff --git a/drivers/staging/cxt1e1/ossiRelease.c b/drivers/staging/cxt1e1/ossiRelease.c
index a56029866c2d..f17a902e95e3 100644
--- a/drivers/staging/cxt1e1/ossiRelease.c
+++ b/drivers/staging/cxt1e1/ossiRelease.c
@@ -1,7 +1,3 @@
-/*
- * $Id: ossiRelease.c,v 1.2 2008/05/08 20:14:03 rdobbs PMCC4_3_1B $
- */
-
/*-----------------------------------------------------------------------------
* ossiRelease.c -
*
@@ -26,14 +22,8 @@
* One Stop Systems, Inc. Escondido, California U.S.A.
*
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.2 $
- * Last changed on $Date: 2008/05/08 20:14:03 $
- * Changed by $Author: rdobbs $
- *-----------------------------------------------------------------------------
*/
-
char pmcc4_OSSI_release[] = "$Release: PMCC4_3_1B, Copyright (c) 2008 One Stop Systems$";
/*** End-of-File ***/
diff --git a/drivers/staging/cxt1e1/pmc93x6_eeprom.h b/drivers/staging/cxt1e1/pmc93x6_eeprom.h
index c3ada87efd26..96c48cb83260 100644
--- a/drivers/staging/cxt1e1/pmc93x6_eeprom.h
+++ b/drivers/staging/cxt1e1/pmc93x6_eeprom.h
@@ -1,7 +1,3 @@
-/*
- * $Id: pmc93x6_eeprom.h,v 1.1 2005/09/28 00:10:08 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_PMC93X6_EEPROM_H_
#define _INC_PMC93X6_EEPROM_H_
@@ -23,26 +19,9 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- *-----------------------------------------------------------------------------
- * $Log: pmc93x6_eeprom.h,v $
- * Revision 1.1 2005/09/28 00:10:08 rickd
- * pmc_verify_cksum return value is char.
- *
- * Revision 1.0 2005/05/04 17:20:51 rickd
- * Initial revision
- *
- * Revision 1.0 2005/04/22 23:48:48 rickd
- * Initial revision
- *
- *-----------------------------------------------------------------------------
*/
-#if defined (__FreeBSD__) || defined (__NetBSD__)
-#include <sys/types.h>
-#else
#include <linux/types.h>
-#endif
#ifdef __KERNEL__
diff --git a/drivers/staging/cxt1e1/pmcc4.h b/drivers/staging/cxt1e1/pmcc4.h
index e046b87763a2..b0ed4ad13011 100644
--- a/drivers/staging/cxt1e1/pmcc4.h
+++ b/drivers/staging/cxt1e1/pmcc4.h
@@ -1,7 +1,3 @@
-/*
- * $Id: pmcc4.h,v 1.4 2005/11/01 19:24:48 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_PMCC4_H_
#define _INC_PMCC4_H_
@@ -23,49 +19,15 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.4 $
- * Last changed on $Date: 2005/11/01 19:24:48 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: pmcc4.h,v $
- * Revision 1.4 2005/11/01 19:24:48 rickd
- * Remove de-implement function prototypes. Several <int> to
- * <status_t> changes for consistent usage of same.
- *
- * Revision 1.3 2005/09/28 00:10:08 rickd
- * Add GNU license info. Use config params from libsbew.h
- *
- * Revision 1.2 2005/04/28 23:43:03 rickd
- * Add RCS tracking heading.
- *
- *-----------------------------------------------------------------------------
*/
-
-#if defined(__FreeBSD__) || defined(__NetBSD__)
-#include <sys/types.h>
-#else
-#ifndef __KERNEL__
-#include <sys/types.h>
-#else
#include <linux/types.h>
-#endif
-#endif
-
-
typedef int status_t;
#define SBE_DRVR_FAIL 0
#define SBE_DRVR_SUCCESS 1
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-
/********************/
/* PMCC4 memory Map */
/********************/
@@ -105,10 +67,6 @@ extern "C"
#define sbeE1errSMF 0x02
#define sbeE1CRC 0x01
-#ifdef __cplusplus
-}
-#endif
-
#ifdef __KERNEL__
/*
diff --git a/drivers/staging/cxt1e1/pmcc4_cpld.h b/drivers/staging/cxt1e1/pmcc4_cpld.h
index 6d8f0337aa3e..a51209bc5274 100644
--- a/drivers/staging/cxt1e1/pmcc4_cpld.h
+++ b/drivers/staging/cxt1e1/pmcc4_cpld.h
@@ -1,7 +1,3 @@
-/*
- * $Id: pmcc4_cpld.h,v 1.0 2005/09/28 00:10:08 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_PMCC4_CPLD_H_
#define _INC_PMCC4_CPLD_H_
@@ -23,34 +19,9 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.0 $
- * Last changed on $Date: 2005/09/28 00:10:08 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: pmcc4_cpld.h,v $
- * Revision 1.0 2005/09/28 00:10:08 rickd
- * Initial revision
- *
- *-----------------------------------------------------------------------------
*/
-
-#if defined(__FreeBSD__) || defined(__NetBSD__)
-#include <sys/types.h>
-#else
-#ifndef __KERNEL__
-#include <sys/types.h>
-#else
#include <linux/types.h>
-#endif
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
/********************************/
/* iSPLD control chip registers */
@@ -117,8 +88,4 @@ extern "C"
#define PMCC4_CPLD_INTR_CMT_3 0x04
#define PMCC4_CPLD_INTR_CMT_4 0x08
-#ifdef __cplusplus
-}
-#endif
-
#endif /* _INC_PMCC4_CPLD_H_ */
diff --git a/drivers/staging/cxt1e1/pmcc4_defs.h b/drivers/staging/cxt1e1/pmcc4_defs.h
index a39505f45c29..83ceae4324b2 100644
--- a/drivers/staging/cxt1e1/pmcc4_defs.h
+++ b/drivers/staging/cxt1e1/pmcc4_defs.h
@@ -1,7 +1,3 @@
-/*
- * $Id: pmcc4_defs.h,v 1.0 2005/09/28 00:10:09 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_PMCC4_DEFS_H_
#define _INC_PMCC4_DEFS_H_
@@ -25,16 +21,6 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.0 $
- * Last changed on $Date: 2005/09/28 00:10:09 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: pmcc4_defs.h,v $
- * Revision 1.0 2005/09/28 00:10:09 rickd
- * Initial revision
- *
- *-----------------------------------------------------------------------------
*/
diff --git a/drivers/staging/cxt1e1/pmcc4_drv.c b/drivers/staging/cxt1e1/pmcc4_drv.c
index e1f07fabd22d..8a7b3a646451 100644
--- a/drivers/staging/cxt1e1/pmcc4_drv.c
+++ b/drivers/staging/cxt1e1/pmcc4_drv.c
@@ -1,8 +1,3 @@
-/*
- * $Id: pmcc4_drv.c,v 3.1 2007/08/15 23:32:17 rickd PMCC4_3_1B $
- */
-
-
/*-----------------------------------------------------------------------------
* pmcc4_drv.c -
*
@@ -22,74 +17,10 @@
* For further information, contact via email: support@onestopsystems.com
* One Stop Systems, Inc. Escondido, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 3.1 $
- * Last changed on $Date: 2007/08/15 23:32:17 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: pmcc4_drv.c,v $
- * Revision 3.1 2007/08/15 23:32:17 rickd
- * Use 'if 0' instead of GNU comment delimeter to avoid line wrap induced compiler errors.
- *
- * Revision 3.0 2007/08/15 22:19:55 rickd
- * Correct sizeof() castings and pi->regram to support 64bit compatibility.
- *
- * Revision 2.10 2006/04/21 00:56:40 rickd
- * workqueue files now prefixed with <sbecom> prefix.
- *
- * Revision 2.9 2005/11/01 19:22:49 rickd
- * Add sanity checks against max_port for ioctl functions.
- *
- * Revision 2.8 2005/10/27 18:59:25 rickd
- * Code cleanup. Default channel config to HDLC_FCS16.
- *
- * Revision 2.7 2005/10/18 18:16:30 rickd
- * Further NCOMM code repairs - (1) interrupt matrix usage inconsistent
- * for indexing into nciInterrupt[][], code missing double parameters.
- * (2) check input of ncomm interrupt registration cardID for correct
- * boundary values.
- *
- * Revision 2.6 2005/10/17 23:55:28 rickd
- * Initial port of NCOMM support patches from original work found
- * in pmc_c4t1e1 as updated by NCOMM. Ref: CONFIG_SBE_PMCC4_NCOMM.
- * Corrected NCOMMs wanpmcC4T1E1_getBaseAddress() to correctly handle
- * multiple boards.
- *
- * Revision 2.5 2005/10/13 23:01:28 rickd
- * Correct panic for illegal address reference w/in get_brdinfo on
- * first_if/last_if name acquistion under Linux 2.6
- *
- * Revision 2.4 2005/10/13 21:20:19 rickd
- * Correction of c4_cleanup() wherein next should be acquired before
- * ci_t structure is free'd.
- *
- * Revision 2.3 2005/10/13 19:20:10 rickd
- * Correct driver removal cleanup code for multiple boards.
- *
- * Revision 2.2 2005/10/11 18:34:04 rickd
- * New routine added to determine number of ports (comets) on board.
- *
- * Revision 2.1 2005/10/05 00:48:13 rickd
- * Add some RX activation trace code.
- *
- * Revision 2.0 2005/09/28 00:10:06 rickd
- * Implement 2.6 workqueue for TX/RX restart. Correction to
- * hardware register boundary checks allows expanded access of MUSYCC.
- * Implement new musycc reg&bits namings.
- *
- *-----------------------------------------------------------------------------
*/
-char OSSIid_pmcc4_drvc[] =
-"@(#)pmcc4_drv.c - $Revision: 3.1 $ (c) Copyright 2002-2007 One Stop Systems, Inc.";
-
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#if defined (__FreeBSD__) || defined (__NetBSD__)
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/errno.h>
-#else
#include <linux/types.h>
#include "pmcc4_sysdep.h"
#include <linux/errno.h>
@@ -98,7 +29,6 @@ char OSSIid_pmcc4_drvc[] =
#include <linux/timer.h> /* include for timer */
#include <linux/hdlc.h>
#include <asm/io.h>
-#endif
#include "sbecom_inline_linux.h"
#include "libsbew.h"
diff --git a/drivers/staging/cxt1e1/pmcc4_ioctls.h b/drivers/staging/cxt1e1/pmcc4_ioctls.h
index 6b8d65673c78..56a1ee39be18 100644
--- a/drivers/staging/cxt1e1/pmcc4_ioctls.h
+++ b/drivers/staging/cxt1e1/pmcc4_ioctls.h
@@ -1,6 +1,3 @@
-/* RCSid: $Header: /home/rickd/projects/pmcc4/include/pmcc4_ioctls.h,v 2.0 2005/09/28 00:10:09 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_PMCC4_IOCTLS_H_
#define _INC_PMCC4_IOCTLS_H_
@@ -22,19 +19,6 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 2.0 $
- * Last changed on $Date: 2005/09/28 00:10:09 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: pmcc4_ioctls.h,v $
- * Revision 2.0 2005/09/28 00:10:09 rickd
- * Add GNU license info. Switch Ioctls to sbe_ioc.h usage.
- *
- * Revision 1.2 2005/04/28 23:43:03 rickd
- * Add RCS tracking heading.
- *
- *-----------------------------------------------------------------------------
*/
#include "sbew_ioc.h"
diff --git a/drivers/staging/cxt1e1/sbe_bid.h b/drivers/staging/cxt1e1/sbe_bid.h
index 1f49b4061fb7..abc2e55f62fc 100644
--- a/drivers/staging/cxt1e1/sbe_bid.h
+++ b/drivers/staging/cxt1e1/sbe_bid.h
@@ -1,7 +1,3 @@
-/*
- * $Id: sbe_bid.h,v 1.0 2005/09/28 00:10:09 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_SBEBID_H_
#define _INC_SBEBID_H_
@@ -24,16 +20,6 @@
* SBE, Inc. San Ramon, California U.S.A.
*
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.0 $
- * Last changed on $Date: 2005/09/28 00:10:09 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: sbe_bid.h,v $
- * Revision 1.0 2005/09/28 00:10:09 rickd
- * Initial revision
- *
- *-----------------------------------------------------------------------------
*/
#define SBE_BID_REG 0x00000000 /* Board ID Register */
diff --git a/drivers/staging/cxt1e1/sbe_promformat.h b/drivers/staging/cxt1e1/sbe_promformat.h
index 746f81b15c73..aad411d185f5 100644
--- a/drivers/staging/cxt1e1/sbe_promformat.h
+++ b/drivers/staging/cxt1e1/sbe_promformat.h
@@ -1,7 +1,3 @@
-/*
- * $Id: sbe_promformat.h,v 2.2 2005/09/28 00:10:09 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_SBE_PROMFORMAT_H_
#define _INC_SBE_PROMFORMAT_H_
@@ -24,19 +20,6 @@
* SBE, Inc. San Ramon, California U.S.A.
*
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 2.2 $
- * Last changed on $Date: 2005/09/28 00:10:09 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: sbe_promformat.h,v $
- * Revision 2.2 2005/09/28 00:10:09 rickd
- * Add EEPROM sample from C4T1E1 board.
- *
- * Revision 2.1 2005/05/04 17:18:24 rickd
- * Initial CI.
- *
- *-----------------------------------------------------------------------------
*/
@@ -85,12 +68,6 @@
*
*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-
#define STRUCT_OFFSET(type, symbol) ((long)&(((type *)0)->symbol))
/*------------------------------------------------------------------------
@@ -150,8 +127,4 @@ extern "C"
FLD_TYPE2 fldType2;
} PROMFORMAT;
-#ifdef __cplusplus
-}
-#endif
-
#endif /*** _INC_SBE_PROMFORMAT_H_ ***/
diff --git a/drivers/staging/cxt1e1/sbecom_inline_linux.h b/drivers/staging/cxt1e1/sbecom_inline_linux.h
index 9ea2c0c2061f..68ed445ab0cb 100644
--- a/drivers/staging/cxt1e1/sbecom_inline_linux.h
+++ b/drivers/staging/cxt1e1/sbecom_inline_linux.h
@@ -1,7 +1,3 @@
-/*
- * $Id: sbecom_inline_linux.h,v 1.2 2007/08/15 22:51:35 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_SBECOM_INLNX_H_
#define _INC_SBECOM_INLNX_H_
@@ -24,22 +20,6 @@
* For further information, contact via email: support@onestopsystems.com
* One Stop Systems, Inc. Escondido, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.2 $
- * Last changed on $Date: 2007/08/15 22:51:35 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: sbecom_inline_linux.h,v $
- * Revision 1.2 2007/08/15 22:51:35 rickd
- * Remove duplicate version.h entry.
- *
- * Revision 1.1 2007/08/15 22:50:29 rickd
- * Update linux/config for 2.6.18 and later.
- *
- * Revision 1.0 2005/09/28 00:10:09 rickd
- * Initial revision
- *
- *-----------------------------------------------------------------------------
*/
diff --git a/drivers/staging/cxt1e1/sbeproc.h b/drivers/staging/cxt1e1/sbeproc.h
index 4aa53f44ec0b..e82be6afd1e8 100644
--- a/drivers/staging/cxt1e1/sbeproc.h
+++ b/drivers/staging/cxt1e1/sbeproc.h
@@ -1,7 +1,3 @@
-/*
- * $Id: sbeproc.h,v 1.2 2005/10/17 23:55:28 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_SBEPROC_H_
#define _INC_SBEPROC_H_
@@ -23,22 +19,6 @@
* For further information, contact via email: support@sbei.com
* SBE, Inc. San Ramon, California U.S.A.
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.2 $
- * Last changed on $Date: 2005/10/17 23:55:28 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: sbeproc.h,v $
- * Revision 1.2 2005/10/17 23:55:28 rickd
- * sbecom_proc_brd_init() is an declared an __init function.
- *
- * Revision 1.1 2005/09/28 00:10:09 rickd
- * Remove unneeded inclusion of c4_private.h.
- *
- * Revision 1.0 2005/05/10 22:21:46 rickd
- * Initial check-in.
- *
- *-----------------------------------------------------------------------------
*/
diff --git a/drivers/staging/cxt1e1/sbew_ioc.h b/drivers/staging/cxt1e1/sbew_ioc.h
index 14d371904d1f..ce9b15c71894 100644
--- a/drivers/staging/cxt1e1/sbew_ioc.h
+++ b/drivers/staging/cxt1e1/sbew_ioc.h
@@ -1,7 +1,3 @@
-/*
- * $Id: sbew_ioc.h,v 1.0 2005/09/28 00:10:10 rickd PMCC4_3_1B $
- */
-
#ifndef _INC_SBEWIOC_H_
#define _INC_SBEWIOC_H_
@@ -24,55 +20,9 @@
* SBE, Inc. San Ramon, California U.S.A.
*
*-----------------------------------------------------------------------------
- * RCS info:
- * RCS revision: $Revision: 1.0 $
- * Last changed on $Date: 2005/09/28 00:10:10 $
- * Changed by $Author: rickd $
- *-----------------------------------------------------------------------------
- * $Log: sbew_ioc.h,v $
- * Revision 1.0 2005/09/28 00:10:10 rickd
- * Initial revision
- *
- * Revision 1.6 2005/01/11 18:41:01 rickd
- * Add BRDADDR_GET Ioctl.
- *
- * Revision 1.5 2004/09/16 18:55:59 rickd
- * Start setting up for generic framer configuration Ioctl by switch
- * from tect3_framer_param[] to sbecom_framer_param[].
- *
- * Revision 1.4 2004/06/28 17:58:15 rickd
- * Rename IOC_TSMAP_[GS] to IOC_TSIOC_[GS] to support need for
- * multiple formats of data when setting up TimeSlots.
- *
- * Revision 1.3 2004/06/22 21:18:13 rickd
- * read_vec now() ONLY handles a single common wrt_vec array.
- *
- * Revision 1.1 2004/06/10 18:11:34 rickd
- * Add IID_GET Ioctl reference.
- *
- * Revision 1.0 2004/06/08 22:59:38 rickd
- * Initial revision
- *
- * Revision 2.0 2004/06/07 17:49:47 rickd
- * Initial library release following merge of wanc1t3/wan256 into
- * common elements for lib.
- *
- *-----------------------------------------------------------------------------
*/
-#ifndef __KERNEL__
-#include <sys/types.h>
-#endif
-#ifdef SunOS
-#include <sys/ioccom.h>
-#else
#include <linux/ioctl.h>
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
#define SBE_LOCKFILE "/tmp/.sbewan.LCK"
@@ -128,9 +78,4 @@ extern "C"
#define SBE_IOC_MAXVEC 1
-
-#ifdef __cplusplus
-}
-#endif
-
#endif /*** _INC_SBEWIOC_H_ ***/
diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
index 0c1c6ca8c379..2c4069fcd981 100644
--- a/drivers/staging/et131x/et131x.c
+++ b/drivers/staging/et131x/et131x.c
@@ -155,7 +155,6 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver "
#define fMP_ADAPTER_FAIL_SEND_MASK 0x3ff00000
/* Some offsets in PCI config space that are actually used. */
-#define ET1310_PCI_MAX_PYLD 0x4C
#define ET1310_PCI_MAC_ADDRESS 0xA4
#define ET1310_PCI_EEPROM_STATUS 0xB2
#define ET1310_PCI_ACK_NACK 0xC0
@@ -178,9 +177,7 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver "
/* RX defines */
#define USE_FBR0 1
-
#define FBR_CHUNKS 32
-
#define MAX_DESC_PER_RING_RX 1024
/* number of RFDs - default and min */
@@ -195,7 +192,6 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver "
#endif
#define NIC_MIN_NUM_RFD 64
-
#define NUM_PACKETS_HANDLED 256
#define ALCATEL_MULTICAST_PKT 0x01000000
@@ -303,8 +299,8 @@ struct fbr_lookup {
dma_addr_t ring_physaddr;
void *mem_virtaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
dma_addr_t mem_physaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
- uint64_t real_physaddr;
- uint64_t offset;
+ u64 real_physaddr;
+ u64 offset;
u32 local_full;
u32 num_entries;
u32 buffsize;
@@ -427,7 +423,6 @@ struct tx_ring {
int since_irq;
};
-/* ADAPTER defines */
/*
* Do not change these values: if changed, then change also in respective
* TXdma and Rxdma engines
@@ -576,8 +571,6 @@ struct et131x_adapter {
struct net_device_stats net_stats;
};
-/* EEPROM functions */
-
static int eeprom_wait_ready(struct pci_dev *pdev, u32 *status)
{
u32 reg;
@@ -795,7 +788,7 @@ static int eeprom_read(struct et131x_adapter *adapter, u32 addr, u8 *pdata)
return (status & LBCIF_STATUS_ACK_ERROR) ? -EIO : 0;
}
-int et131x_init_eeprom(struct et131x_adapter *adapter)
+static int et131x_init_eeprom(struct et131x_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
u8 eestatus;
@@ -868,7 +861,7 @@ int et131x_init_eeprom(struct et131x_adapter *adapter)
* et131x_rx_dma_enable - re-start of Rx_DMA on the ET1310.
* @adapter: pointer to our adapter structure
*/
-void et131x_rx_dma_enable(struct et131x_adapter *adapter)
+static void et131x_rx_dma_enable(struct et131x_adapter *adapter)
{
/* Setup the receive dma configuration register for normal operation */
u32 csr = 0x2000; /* FBR1 enable */
@@ -906,7 +899,7 @@ void et131x_rx_dma_enable(struct et131x_adapter *adapter)
* et131x_rx_dma_disable - Stop of Rx_DMA on the ET1310
* @adapter: pointer to our adapter structure
*/
-void et131x_rx_dma_disable(struct et131x_adapter *adapter)
+static void et131x_rx_dma_disable(struct et131x_adapter *adapter)
{
u32 csr;
/* Setup the receive dma configuration register */
@@ -928,7 +921,7 @@ void et131x_rx_dma_disable(struct et131x_adapter *adapter)
*
* Mainly used after a return to the D0 (full-power) state from a lower state.
*/
-void et131x_tx_dma_enable(struct et131x_adapter *adapter)
+static void et131x_tx_dma_enable(struct et131x_adapter *adapter)
{
/* Setup the transmit dma configuration register for normal
* operation
@@ -948,23 +941,10 @@ static inline void add_12bit(u32 *v, int n)
}
/**
- * nic_rx_pkts - Checks the hardware for available packets
- * @adapter: pointer to our adapter
- *
- * Returns rfd, a pointer to our MPRFD.
- *
- * Checks the hardware for available packets, using completion ring
- * If packets are available, it gets an RFD from the recv_list, attaches
- * the packet to it, puts the RFD in the RecvPendList, and also returns
- * the pointer to the RFD.
- */
-/* MAC functions */
-
-/**
* et1310_config_mac_regs1 - Initialize the first part of MAC regs
* @adapter: pointer to our adapter structure
*/
-void et1310_config_mac_regs1(struct et131x_adapter *adapter)
+static void et1310_config_mac_regs1(struct et131x_adapter *adapter)
{
struct mac_regs __iomem *macregs = &adapter->regs->mac;
u32 station1;
@@ -1024,7 +1004,7 @@ void et1310_config_mac_regs1(struct et131x_adapter *adapter)
* et1310_config_mac_regs2 - Initialize the second part of MAC regs
* @adapter: pointer to our adapter structure
*/
-void et1310_config_mac_regs2(struct et131x_adapter *adapter)
+static void et1310_config_mac_regs2(struct et131x_adapter *adapter)
{
int32_t delay = 0;
struct mac_regs __iomem *mac = &adapter->regs->mac;
@@ -1105,7 +1085,7 @@ void et1310_config_mac_regs2(struct et131x_adapter *adapter)
*
* Returns 0 if the device is not in phy coma, 1 if it is in phy coma
*/
-int et1310_in_phy_coma(struct et131x_adapter *adapter)
+static int et1310_in_phy_coma(struct et131x_adapter *adapter)
{
u32 pmcsr;
@@ -1114,15 +1094,13 @@ int et1310_in_phy_coma(struct et131x_adapter *adapter)
return ET_PM_PHY_SW_COMA & pmcsr ? 1 : 0;
}
-void et1310_setup_device_for_multicast(struct et131x_adapter *adapter)
+static void et1310_setup_device_for_multicast(struct et131x_adapter *adapter)
{
struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac;
- uint32_t nIndex;
- uint32_t result;
- uint32_t hash1 = 0;
- uint32_t hash2 = 0;
- uint32_t hash3 = 0;
- uint32_t hash4 = 0;
+ u32 hash1 = 0;
+ u32 hash2 = 0;
+ u32 hash3 = 0;
+ u32 hash4 = 0;
u32 pm_csr;
/* If ET131X_PACKET_TYPE_MULTICAST is specified, then we provision
@@ -1131,10 +1109,13 @@ void et1310_setup_device_for_multicast(struct et131x_adapter *adapter)
* driver.
*/
if (adapter->packet_filter & ET131X_PACKET_TYPE_MULTICAST) {
+ int i;
+
/* Loop through our multicast array and set up the device */
- for (nIndex = 0; nIndex < adapter->multicast_addr_count;
- nIndex++) {
- result = ether_crc(6, adapter->multicast_list[nIndex]);
+ for (i = 0; i < adapter->multicast_addr_count; i++) {
+ u32 result;
+
+ result = ether_crc(6, adapter->multicast_list[i]);
result = (result & 0x3F800000) >> 23;
@@ -1163,7 +1144,7 @@ void et1310_setup_device_for_multicast(struct et131x_adapter *adapter)
}
}
-void et1310_setup_device_for_unicast(struct et131x_adapter *adapter)
+static void et1310_setup_device_for_unicast(struct et131x_adapter *adapter)
{
struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac;
u32 uni_pf1;
@@ -1203,7 +1184,7 @@ void et1310_setup_device_for_unicast(struct et131x_adapter *adapter)
}
}
-void et1310_config_rxmac_regs(struct et131x_adapter *adapter)
+static void et1310_config_rxmac_regs(struct et131x_adapter *adapter)
{
struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac;
struct phy_device *phydev = adapter->phydev;
@@ -1334,7 +1315,7 @@ void et1310_config_rxmac_regs(struct et131x_adapter *adapter)
writel(0x9, &rxmac->ctrl);
}
-void et1310_config_txmac_regs(struct et131x_adapter *adapter)
+static void et1310_config_txmac_regs(struct et131x_adapter *adapter)
{
struct txmac_regs __iomem *txmac = &adapter->regs->txmac;
@@ -1348,7 +1329,7 @@ void et1310_config_txmac_regs(struct et131x_adapter *adapter)
writel(0x40, &txmac->cf_param);
}
-void et1310_config_macstat_regs(struct et131x_adapter *adapter)
+static void et1310_config_macstat_regs(struct et131x_adapter *adapter)
{
struct macstat_regs __iomem *macstat =
&adapter->regs->macstat;
@@ -1422,7 +1403,7 @@ void et1310_config_macstat_regs(struct et131x_adapter *adapter)
*
* Returns 0 on success, errno on failure (as defined in errno.h)
*/
-int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr,
+static int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr,
u8 reg, u16 *value)
{
struct mac_regs __iomem *mac = &adapter->regs->mac;
@@ -1478,7 +1459,7 @@ int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr,
return status;
}
-int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value)
+static int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value)
{
struct phy_device *phydev = adapter->phydev;
@@ -1498,7 +1479,7 @@ int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value)
*
* Return 0 on success, errno on failure (as defined in errno.h)
*/
-int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value)
+static int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value)
{
struct mac_regs __iomem *mac = &adapter->regs->mac;
struct phy_device *phydev = adapter->phydev;
@@ -1564,8 +1545,9 @@ int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value)
}
/* Still used from _mac for BIT_READ */
-void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, u16 action,
- u16 regnum, u16 bitnum, u8 *value)
+static void et1310_phy_access_mii_bit(struct et131x_adapter *adapter,
+ u16 action, u16 regnum, u16 bitnum,
+ u8 *value)
{
u16 reg;
u16 mask = 0x0001 << bitnum;
@@ -1591,7 +1573,7 @@ void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, u16 action,
}
}
-void et1310_config_flow_control(struct et131x_adapter *adapter)
+static void et1310_config_flow_control(struct et131x_adapter *adapter)
{
struct phy_device *phydev = adapter->phydev;
@@ -1632,7 +1614,7 @@ void et1310_config_flow_control(struct et131x_adapter *adapter)
* et1310_update_macstat_host_counters - Update the local copy of the statistics
* @adapter: pointer to the adapter structure
*/
-void et1310_update_macstat_host_counters(struct et131x_adapter *adapter)
+static void et1310_update_macstat_host_counters(struct et131x_adapter *adapter)
{
struct ce_stats *stats = &adapter->stats;
struct macstat_regs __iomem *macstat =
@@ -1664,7 +1646,7 @@ void et1310_update_macstat_host_counters(struct et131x_adapter *adapter)
* the statistics held in the adapter structure, checking the "wrap"
* bit for each counter.
*/
-void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter)
+static void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter)
{
u32 carry_reg1;
u32 carry_reg2;
@@ -1714,9 +1696,7 @@ void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter)
adapter->stats.tx_collisions += COUNTER_WRAP_12_BIT;
}
-/* PHY functions */
-
-int et131x_mdio_read(struct mii_bus *bus, int phy_addr, int reg)
+static int et131x_mdio_read(struct mii_bus *bus, int phy_addr, int reg)
{
struct net_device *netdev = bus->priv;
struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -1731,7 +1711,7 @@ int et131x_mdio_read(struct mii_bus *bus, int phy_addr, int reg)
return value;
}
-int et131x_mdio_write(struct mii_bus *bus, int phy_addr, int reg, u16 value)
+static int et131x_mdio_write(struct mii_bus *bus, int phy_addr, int reg, u16 value)
{
struct net_device *netdev = bus->priv;
struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -1739,7 +1719,7 @@ int et131x_mdio_write(struct mii_bus *bus, int phy_addr, int reg, u16 value)
return et131x_mii_write(adapter, reg, value);
}
-int et131x_mdio_reset(struct mii_bus *bus)
+static int et131x_mdio_reset(struct mii_bus *bus)
{
struct net_device *netdev = bus->priv;
struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -1759,7 +1739,7 @@ int et131x_mdio_reset(struct mii_bus *bus)
* Can't you see that this code processed
* Phy power, phy power..
*/
-void et1310_phy_power_down(struct et131x_adapter *adapter, bool down)
+static void et1310_phy_power_down(struct et131x_adapter *adapter, bool down)
{
u16 data;
@@ -1775,7 +1755,7 @@ void et1310_phy_power_down(struct et131x_adapter *adapter, bool down)
* @adapter: pointer to our private adapter structure
*
*/
-void et131x_xcvr_init(struct et131x_adapter *adapter)
+static void et131x_xcvr_init(struct et131x_adapter *adapter)
{
u16 imr;
u16 isr;
@@ -1822,7 +1802,7 @@ void et131x_xcvr_init(struct et131x_adapter *adapter)
*
* Used to configure the global registers on the JAGCore
*/
-void et131x_configure_global_regs(struct et131x_adapter *adapter)
+static void et131x_configure_global_regs(struct et131x_adapter *adapter)
{
struct global_regs __iomem *regs = &adapter->regs->global;
@@ -1863,13 +1843,11 @@ void et131x_configure_global_regs(struct et131x_adapter *adapter)
writel(0, &regs->watchdog_timer);
}
-/* PM functions */
-
/**
* et131x_config_rx_dma_regs - Start of Rx_DMA init sequence
* @adapter: pointer to our adapter structure
*/
-void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
+static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
{
struct rxdma_regs __iomem *rx_dma = &adapter->regs->rxdma;
struct rx_ring *rx_local = &adapter->rx_ring;
@@ -1987,7 +1965,7 @@ void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
* Configure the transmit engine with the ring buffers we have created
* and prepare it for use.
*/
-void et131x_config_tx_dma_regs(struct et131x_adapter *adapter)
+static void et131x_config_tx_dma_regs(struct et131x_adapter *adapter)
{
struct txdma_regs __iomem *txdma = &adapter->regs->txdma;
@@ -2017,7 +1995,7 @@ void et131x_config_tx_dma_regs(struct et131x_adapter *adapter)
*
* Returns 0 on success, errno on failure (as defined in errno.h)
*/
-void et131x_adapter_setup(struct et131x_adapter *adapter)
+static void et131x_adapter_setup(struct et131x_adapter *adapter)
{
/* Configure the JAGCore */
et131x_configure_global_regs(adapter);
@@ -2044,7 +2022,7 @@ void et131x_adapter_setup(struct et131x_adapter *adapter)
* et131x_soft_reset - Issue a soft reset to the hardware, complete for ET1310
* @adapter: pointer to our private adapter structure
*/
-void et131x_soft_reset(struct et131x_adapter *adapter)
+static void et131x_soft_reset(struct et131x_adapter *adapter)
{
/* Disable MAC Core */
writel(0xc00f0000, &adapter->regs->mac.cfg1);
@@ -2062,7 +2040,7 @@ void et131x_soft_reset(struct et131x_adapter *adapter)
* Enable the appropriate interrupts on the ET131x according to our
* configuration
*/
-void et131x_enable_interrupts(struct et131x_adapter *adapter)
+static void et131x_enable_interrupts(struct et131x_adapter *adapter)
{
u32 mask;
@@ -2082,7 +2060,7 @@ void et131x_enable_interrupts(struct et131x_adapter *adapter)
*
* Block all interrupts from the et131x device at the device itself
*/
-void et131x_disable_interrupts(struct et131x_adapter *adapter)
+static void et131x_disable_interrupts(struct et131x_adapter *adapter)
{
/* Disable all global interrupts */
writel(INT_MASK_DISABLE, &adapter->regs->global.int_mask);
@@ -2092,7 +2070,7 @@ void et131x_disable_interrupts(struct et131x_adapter *adapter)
* et131x_tx_dma_disable - Stop of Tx_DMA on the ET1310
* @adapter: pointer to our adapter structure
*/
-void et131x_tx_dma_disable(struct et131x_adapter *adapter)
+static void et131x_tx_dma_disable(struct et131x_adapter *adapter)
{
/* Setup the tramsmit dma configuration register */
writel(ET_TXDMA_CSR_HALT|ET_TXDMA_SNGL_EPKT,
@@ -2103,7 +2081,7 @@ void et131x_tx_dma_disable(struct et131x_adapter *adapter)
* et131x_enable_txrx - Enable tx/rx queues
* @netdev: device to be enabled
*/
-void et131x_enable_txrx(struct net_device *netdev)
+static void et131x_enable_txrx(struct net_device *netdev)
{
struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -2123,7 +2101,7 @@ void et131x_enable_txrx(struct net_device *netdev)
* et131x_disable_txrx - Disable tx/rx queues
* @netdev: device to be disabled
*/
-void et131x_disable_txrx(struct net_device *netdev)
+static void et131x_disable_txrx(struct net_device *netdev)
{
struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -2142,7 +2120,7 @@ void et131x_disable_txrx(struct net_device *netdev)
* et131x_init_send - Initialize send data structures
* @adapter: pointer to our private adapter structure
*/
-void et131x_init_send(struct et131x_adapter *adapter)
+static void et131x_init_send(struct et131x_adapter *adapter)
{
struct tcb *tcb;
u32 ct;
@@ -2192,7 +2170,7 @@ void et131x_init_send(struct et131x_adapter *adapter)
* indicating linkup status, call the MPDisablePhyComa routine to
* restore JAGCore and gigE PHY
*/
-void et1310_enable_phy_coma(struct et131x_adapter *adapter)
+static void et1310_enable_phy_coma(struct et131x_adapter *adapter)
{
unsigned long flags;
u32 pmcsr;
@@ -2231,7 +2209,7 @@ void et1310_enable_phy_coma(struct et131x_adapter *adapter)
* et1310_disable_phy_coma - Disable the Phy Coma Mode
* @adapter: pointer to our adapter structure
*/
-void et1310_disable_phy_coma(struct et131x_adapter *adapter)
+static void et1310_disable_phy_coma(struct et131x_adapter *adapter)
{
u32 pmcsr;
@@ -2269,8 +2247,6 @@ void et1310_disable_phy_coma(struct et131x_adapter *adapter)
et131x_enable_txrx(adapter->netdev);
}
-/* RX functions */
-
static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit)
{
u32 tmp_free_buff_ring = *free_buff_ring;
@@ -2296,16 +2272,14 @@ static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit)
* @offset: pointer to the offset variable
* @mask: correct mask
*/
-void et131x_align_allocated_memory(struct et131x_adapter *adapter,
- uint64_t *phys_addr,
- uint64_t *offset, uint64_t mask)
+static void et131x_align_allocated_memory(struct et131x_adapter *adapter,
+ u64 *phys_addr, u64 *offset,
+ u64 mask)
{
- uint64_t new_addr;
+ u64 new_addr = *phys_addr & ~mask;
*offset = 0;
- new_addr = *phys_addr & ~mask;
-
if (new_addr != *phys_addr) {
/* Move to next aligned block */
new_addr += mask + 1;
@@ -2325,7 +2299,7 @@ void et131x_align_allocated_memory(struct et131x_adapter *adapter,
* Allocates Free buffer ring 1 for sure, free buffer ring 0 if required,
* and the Packet Status Ring.
*/
-int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
+static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
{
u32 i, j;
u32 bufsize;
@@ -2454,8 +2428,8 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
rx_ring->fbr[1]->offset);
#endif
for (i = 0; i < (rx_ring->fbr[0]->num_entries / FBR_CHUNKS); i++) {
- u64 fbr1_offset;
u64 fbr1_tmp_physaddr;
+ u64 fbr1_offset;
u32 fbr1_align;
/* This code allocates an area of memory big enough for N
@@ -2520,8 +2494,8 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
#ifdef USE_FBR0
/* Same for FBR0 (if in use) */
for (i = 0; i < (rx_ring->fbr[1]->num_entries / FBR_CHUNKS); i++) {
- u64 fbr0_offset;
u64 fbr0_tmp_physaddr;
+ u64 fbr0_offset;
fbr_chunksize =
((FBR_CHUNKS + 1) * rx_ring->fbr[1]->buffsize) - 1;
@@ -2629,7 +2603,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
* et131x_rx_dma_memory_free - Free all memory allocated within this module.
* @adapter: pointer to our private adapter structure
*/
-void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
+static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
{
u32 index;
u32 bufsize;
@@ -2774,7 +2748,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
*
* Returns 0 on success and errno on failure (as defined in errno.h)
*/
-int et131x_init_recv(struct et131x_adapter *adapter)
+static int et131x_init_recv(struct et131x_adapter *adapter)
{
int status = -ENOMEM;
struct rfd *rfd = NULL;
@@ -2824,7 +2798,7 @@ int et131x_init_recv(struct et131x_adapter *adapter)
* et131x_set_rx_dma_timer - Set the heartbeat timer according to line rate.
* @adapter: pointer to our adapter structure
*/
-void et131x_set_rx_dma_timer(struct et131x_adapter *adapter)
+static void et131x_set_rx_dma_timer(struct et131x_adapter *adapter)
{
struct phy_device *phydev = adapter->phydev;
@@ -2918,6 +2892,17 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd)
WARN_ON(rx_local->num_ready_recv > rx_local->num_rfd);
}
+/**
+ * nic_rx_pkts - Checks the hardware for available packets
+ * @adapter: pointer to our adapter
+ *
+ * Returns rfd, a pointer to our MPRFD.
+ *
+ * Checks the hardware for available packets, using completion ring
+ * If packets are available, it gets an RFD from the recv_list, attaches
+ * the packet to it, puts the RFD in the RecvPendList, and also returns
+ * the pointer to the RFD.
+ */
static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter)
{
struct rx_ring *rx_local = &adapter->rx_ring;
@@ -3139,7 +3124,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter)
*
* Assumption, Rcv spinlock has been acquired.
*/
-void et131x_handle_recv_interrupt(struct et131x_adapter *adapter)
+static void et131x_handle_recv_interrupt(struct et131x_adapter *adapter)
{
struct rfd *rfd = NULL;
u32 count = 0;
@@ -3188,8 +3173,6 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *adapter)
adapter->rx_ring.unfinished_receives = false;
}
-/* TX functions */
-
/**
* et131x_tx_dma_memory_alloc
* @adapter: pointer to our private adapter structure
@@ -3202,7 +3185,7 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *adapter)
* memory. The device will update the "status" in memory each time it xmits a
* packet.
*/
-int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter)
+static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter)
{
int desc_size = 0;
struct tx_ring *tx_ring = &adapter->tx_ring;
@@ -3256,7 +3239,7 @@ int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter)
*
* Returns 0 on success and errno on failure (as defined in errno.h).
*/
-void et131x_tx_dma_memory_free(struct et131x_adapter *adapter)
+static void et131x_tx_dma_memory_free(struct et131x_adapter *adapter)
{
int desc_size = 0;
@@ -3578,7 +3561,7 @@ static int send_packet(struct sk_buff *skb, struct et131x_adapter *adapter)
*
* Return 0 in almost all cases; non-zero value in extreme hard failure only
*/
-int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev)
+static int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev)
{
int status = 0;
struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -3696,7 +3679,7 @@ static inline void free_send_packet(struct et131x_adapter *adapter,
*
* Assumption - Send spinlock has been acquired
*/
-void et131x_free_busy_send_packets(struct et131x_adapter *adapter)
+static void et131x_free_busy_send_packets(struct et131x_adapter *adapter)
{
struct tcb *tcb;
unsigned long flags;
@@ -3743,7 +3726,7 @@ void et131x_free_busy_send_packets(struct et131x_adapter *adapter)
*
* Assumption - Send spinlock has been acquired
*/
-void et131x_handle_send_interrupt(struct et131x_adapter *adapter)
+static void et131x_handle_send_interrupt(struct et131x_adapter *adapter)
{
unsigned long flags;
u32 serviced;
@@ -3798,8 +3781,6 @@ void et131x_handle_send_interrupt(struct et131x_adapter *adapter)
spin_unlock_irqrestore(&adapter->tcb_send_qlock, flags);
}
-/* ETHTOOL functions */
-
static int et131x_get_settings(struct net_device *netdev,
struct ethtool_cmd *cmd)
{
@@ -3965,18 +3946,16 @@ static struct ethtool_ops et131x_ethtool_ops = {
.get_link = ethtool_op_get_link,
};
-void et131x_set_ethtool_ops(struct net_device *netdev)
+static void et131x_set_ethtool_ops(struct net_device *netdev)
{
SET_ETHTOOL_OPS(netdev, &et131x_ethtool_ops);
}
-/* PCI functions */
-
/**
* et131x_hwaddr_init - set up the MAC Address on the ET1310
* @adapter: pointer to our private adapter structure
*/
-void et131x_hwaddr_init(struct et131x_adapter *adapter)
+static void et131x_hwaddr_init(struct et131x_adapter *adapter)
{
/* If have our default mac from init and no mac address from
* EEPROM then we need to generate the last octet and set it on the
@@ -4022,24 +4001,31 @@ void et131x_hwaddr_init(struct et131x_adapter *adapter)
static int et131x_pci_init(struct et131x_adapter *adapter,
struct pci_dev *pdev)
{
- int i;
- u8 max_payload;
- u8 read_size_reg;
+ int cap = pci_pcie_cap(pdev);
+ u16 max_payload;
+ u16 ctl;
+ int i, rc;
- if (et131x_init_eeprom(adapter) < 0)
- return -EIO;
+ rc = et131x_init_eeprom(adapter);
+ if (rc < 0)
+ goto out;
+ if (!cap) {
+ dev_err(&pdev->dev, "Missing PCIe capabilities\n");
+ goto err_out;
+ }
+
/* Let's set up the PORT LOGIC Register. First we need to know what
* the max_payload_size is
*/
- if (pci_read_config_byte(pdev, ET1310_PCI_MAX_PYLD, &max_payload)) {
+ if (pci_read_config_word(pdev, cap + PCI_EXP_DEVCAP, &max_payload)) {
dev_err(&pdev->dev,
"Could not read PCI config space for Max Payload Size\n");
- return -EIO;
+ goto err_out;
}
/* Program the Ack/Nak latency and replay timers */
- max_payload &= 0x07; /* Only the lower 3 bits are valid */
+ max_payload &= 0x07;
if (max_payload < 2) {
static const u16 acknak[2] = { 0x76, 0xD0 };
@@ -4049,13 +4035,13 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
acknak[max_payload])) {
dev_err(&pdev->dev,
"Could not write PCI config space for ACK/NAK\n");
- return -EIO;
+ goto err_out;
}
if (pci_write_config_word(pdev, ET1310_PCI_REPLAY,
replay[max_payload])) {
dev_err(&pdev->dev,
"Could not write PCI config space for Replay Timer\n");
- return -EIO;
+ goto err_out;
}
}
@@ -4065,23 +4051,22 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
if (pci_write_config_byte(pdev, ET1310_PCI_L0L1LATENCY, 0x11)) {
dev_err(&pdev->dev,
"Could not write PCI config space for Latency Timers\n");
- return -EIO;
+ goto err_out;
}
/* Change the max read size to 2k */
- if (pci_read_config_byte(pdev, 0x51, &read_size_reg)) {
+ if (pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl)) {
dev_err(&pdev->dev,
"Could not read PCI config space for Max read size\n");
- return -EIO;
+ goto err_out;
}
- read_size_reg &= 0x8f;
- read_size_reg |= 0x40;
+ ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | ( 0x04 << 12);
- if (pci_write_config_byte(pdev, 0x51, read_size_reg)) {
+ if (pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl)) {
dev_err(&pdev->dev,
"Could not write PCI config space for Max read size\n");
- return -EIO;
+ goto err_out;
}
/* Get MAC address from config space if an eeprom exists, otherwise
@@ -4096,11 +4081,15 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
if (pci_read_config_byte(pdev, ET1310_PCI_MAC_ADDRESS + i,
adapter->rom_addr + i)) {
dev_err(&pdev->dev, "Could not read PCI config space for MAC address\n");
- return -EIO;
+ goto err_out;
}
}
memcpy(adapter->addr, adapter->rom_addr, ETH_ALEN);
- return 0;
+out:
+ return rc;
+err_out:
+ rc = -EIO;
+ goto out;
}
/**
@@ -4110,7 +4099,7 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
* The routine called when the error timer expires, to track the number of
* recurring errors.
*/
-void et131x_error_timer_handler(unsigned long data)
+static void et131x_error_timer_handler(unsigned long data)
{
struct et131x_adapter *adapter = (struct et131x_adapter *) data;
struct phy_device *phydev = adapter->phydev;
@@ -4153,7 +4142,7 @@ void et131x_error_timer_handler(unsigned long data)
*
* Allocate all the memory blocks for send, receive and others.
*/
-int et131x_adapter_memory_alloc(struct et131x_adapter *adapter)
+static int et131x_adapter_memory_alloc(struct et131x_adapter *adapter)
{
int status;
@@ -4188,7 +4177,7 @@ int et131x_adapter_memory_alloc(struct et131x_adapter *adapter)
* et131x_adapter_memory_free - Free all memory allocated for use by Tx & Rx
* @adapter: pointer to our private adapter structure
*/
-void et131x_adapter_memory_free(struct et131x_adapter *adapter)
+static void et131x_adapter_memory_free(struct et131x_adapter *adapter)
{
/* Free DMA memory */
et131x_tx_dma_memory_free(adapter);
@@ -4364,10 +4353,6 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev,
adapter->pdev = pci_dev_get(pdev);
adapter->netdev = netdev;
- /* Do the same for the netdev struct */
- netdev->irq = pdev->irq;
- netdev->base_addr = pci_resource_start(pdev, 0);
-
/* Initialize spinlocks here */
spin_lock_init(&adapter->lock);
spin_lock_init(&adapter->tcb_send_qlock);
@@ -4400,6 +4385,7 @@ static void __devexit et131x_pci_remove(struct pci_dev *pdev)
struct et131x_adapter *adapter = netdev_priv(netdev);
unregister_netdev(netdev);
+ phy_disconnect(adapter->phydev);
mdiobus_unregister(adapter->mii_bus);
kfree(adapter->mii_bus->irq);
mdiobus_free(adapter->mii_bus);
@@ -4417,7 +4403,7 @@ static void __devexit et131x_pci_remove(struct pci_dev *pdev)
* et131x_up - Bring up a device for use.
* @netdev: device to be opened
*/
-void et131x_up(struct net_device *netdev)
+static void et131x_up(struct net_device *netdev)
{
struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -4429,7 +4415,7 @@ void et131x_up(struct net_device *netdev)
* et131x_down - Bring down the device
* @netdev: device to be broght down
*/
-void et131x_down(struct net_device *netdev)
+static void et131x_down(struct net_device *netdev)
{
struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -4475,8 +4461,6 @@ static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume);
#define ET131X_PM_OPS NULL
#endif
-/* ISR functions */
-
/**
* et131x_isr - The Interrupt Service Routine for the driver.
* @irq: the IRQ on which the interrupt was received.
@@ -4573,7 +4557,7 @@ out:
* scheduled to run in a deferred context by the ISR. This is where the ISR's
* work actually gets done.
*/
-void et131x_isr_handler(struct work_struct *work)
+static void et131x_isr_handler(struct work_struct *work)
{
struct et131x_adapter *adapter =
container_of(work, struct et131x_adapter, task);
@@ -4774,8 +4758,6 @@ void et131x_isr_handler(struct work_struct *work)
et131x_enable_interrupts(adapter);
}
-/* NETDEV functions */
-
/**
* et131x_stats - Return the current device statistics.
* @netdev: device whose stats are being queried
@@ -4829,10 +4811,12 @@ static struct net_device_stats *et131x_stats(struct net_device *netdev)
*
* Returns 0 on success, errno on failure (as defined in errno.h)
*/
-int et131x_open(struct net_device *netdev)
+static int et131x_open(struct net_device *netdev)
{
- int result = 0;
struct et131x_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = adapter->pdev;
+ unsigned int irq = pdev->irq;
+ int result;
/* Start the timer to track NIC errors */
init_timer(&adapter->error_timer);
@@ -4841,12 +4825,9 @@ int et131x_open(struct net_device *netdev)
adapter->error_timer.data = (unsigned long)adapter;
add_timer(&adapter->error_timer);
- /* Register our IRQ */
- result = request_irq(netdev->irq, et131x_isr, IRQF_SHARED,
- netdev->name, netdev);
+ result = request_irq(irq, et131x_isr, IRQF_SHARED, netdev->name, netdev);
if (result) {
- dev_err(&adapter->pdev->dev, "could not register IRQ %d\n",
- netdev->irq);
+ dev_err(&pdev->dev, "could not register IRQ %d\n", irq);
return result;
}
@@ -4863,14 +4844,14 @@ int et131x_open(struct net_device *netdev)
*
* Returns 0 on success, errno on failure (as defined in errno.h)
*/
-int et131x_close(struct net_device *netdev)
+static int et131x_close(struct net_device *netdev)
{
struct et131x_adapter *adapter = netdev_priv(netdev);
et131x_down(netdev);
adapter->flags &= ~fMP_ADAPTER_INTERRUPT_IN_USE;
- free_irq(netdev->irq, netdev);
+ free_irq(adapter->pdev->irq, netdev);
/* Stop the error timer */
return del_timer_sync(&adapter->error_timer);
@@ -4905,8 +4886,8 @@ static int et131x_ioctl(struct net_device *netdev, struct ifreq *reqbuf,
*/
static int et131x_set_packet_filter(struct et131x_adapter *adapter)
{
+ int filter = adapter->packet_filter;
int status = 0;
- uint32_t filter = adapter->packet_filter;
u32 ctrl;
u32 pf_ctrl;
@@ -4968,7 +4949,7 @@ static int et131x_set_packet_filter(struct et131x_adapter *adapter)
static void et131x_multicast(struct net_device *netdev)
{
struct et131x_adapter *adapter = netdev_priv(netdev);
- uint32_t packet_filter = 0;
+ int packet_filter;
unsigned long flags;
struct netdev_hw_addr *ha;
int i;
@@ -5249,40 +5230,6 @@ static const struct net_device_ops et131x_netdev_ops = {
};
/**
- * et131x_device_alloc
- *
- * Returns pointer to the allocated and initialized net_device struct for
- * this device.
- *
- * Create instances of net_device and wl_private for the new adapter and
- * register the device's entry points in the net_device structure.
- */
-struct net_device *et131x_device_alloc(void)
-{
- struct net_device *netdev;
-
- /* Alloc net_device and adapter structs */
- netdev = alloc_etherdev(sizeof(struct et131x_adapter));
-
- if (!netdev) {
- printk(KERN_ERR "et131x: Alloc of net_device struct failed\n");
- return NULL;
- }
-
- /*
- * Setup the function registration table (and other data) for a
- * net_device
- */
- netdev->watchdog_timeo = ET131X_TX_TIMEOUT;
- netdev->netdev_ops = &et131x_netdev_ops;
-
- /* Poll? */
- /* netdev->poll = &et131x_poll; */
- /* netdev->poll_controller = &et131x_poll_controller; */
- return netdev;
-}
-
-/**
* et131x_pci_setup - Perform device initialization
* @pdev: a pointer to the device's pci_dev structure
* @ent: this device's entry in the pci_device_id table
@@ -5297,24 +5244,26 @@ struct net_device *et131x_device_alloc(void)
static int __devinit et131x_pci_setup(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- int result;
struct net_device *netdev;
struct et131x_adapter *adapter;
+ int rc;
int ii;
- result = pci_enable_device(pdev);
- if (result) {
+ rc = pci_enable_device(pdev);
+ if (rc < 0) {
dev_err(&pdev->dev, "pci_enable_device() failed\n");
- goto err_out;
+ goto out;
}
/* Perform some basic PCI checks */
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
dev_err(&pdev->dev, "Can't find PCI device's base address\n");
+ rc = -ENODEV;
goto err_disable;
}
- if (pci_request_regions(pdev, DRIVER_NAME)) {
+ rc = pci_request_regions(pdev, DRIVER_NAME);
+ if (rc < 0) {
dev_err(&pdev->dev, "Can't get PCI resources\n");
goto err_disable;
}
@@ -5323,46 +5272,50 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev,
/* Check the DMA addressing support of this device */
if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
- result = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
- if (result) {
+ rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+ if (rc < 0) {
dev_err(&pdev->dev,
"Unable to obtain 64 bit DMA for consistent allocations\n");
goto err_release_res;
}
} else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
- result = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
- if (result) {
+ rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+ if (rc < 0) {
dev_err(&pdev->dev,
"Unable to obtain 32 bit DMA for consistent allocations\n");
goto err_release_res;
}
} else {
dev_err(&pdev->dev, "No usable DMA addressing method\n");
- result = -EIO;
+ rc = -EIO;
goto err_release_res;
}
/* Allocate netdev and private adapter structs */
- netdev = et131x_device_alloc();
+ netdev = alloc_etherdev(sizeof(struct et131x_adapter));
if (!netdev) {
dev_err(&pdev->dev, "Couldn't alloc netdev struct\n");
- result = -ENOMEM;
+ rc = -ENOMEM;
goto err_release_res;
}
+ netdev->watchdog_timeo = ET131X_TX_TIMEOUT;
+ netdev->netdev_ops = &et131x_netdev_ops;
+
SET_NETDEV_DEV(netdev, &pdev->dev);
et131x_set_ethtool_ops(netdev);
adapter = et131x_adapter_init(netdev, pdev);
- /* Initialise the PCI setup for the device */
- et131x_pci_init(adapter, pdev);
+ rc = et131x_pci_init(adapter, pdev);
+ if (rc < 0)
+ goto err_free_dev;
/* Map the bus-relative registers to system virtual memory */
adapter->regs = pci_ioremap_bar(pdev, 0);
if (!adapter->regs) {
dev_err(&pdev->dev, "Cannot map device registers\n");
- result = -ENOMEM;
+ rc = -ENOMEM;
goto err_free_dev;
}
@@ -5376,8 +5329,8 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev,
et131x_disable_interrupts(adapter);
/* Allocate DMA memory */
- result = et131x_adapter_memory_alloc(adapter);
- if (result) {
+ rc = et131x_adapter_memory_alloc(adapter);
+ if (rc < 0) {
dev_err(&pdev->dev, "Could not alloc adapater memory (DMA)\n");
goto err_iounmap;
}
@@ -5395,6 +5348,8 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev,
adapter->boot_coma = 0;
et1310_disable_phy_coma(adapter);
+ rc = -ENOMEM;
+
/* Setup the mii_bus struct */
adapter->mii_bus = mdiobus_alloc();
if (!adapter->mii_bus) {
@@ -5418,13 +5373,14 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev,
for (ii = 0; ii < PHY_MAX_ADDR; ii++)
adapter->mii_bus->irq[ii] = PHY_POLL;
- if (mdiobus_register(adapter->mii_bus)) {
+ rc = mdiobus_register(adapter->mii_bus);
+ if (rc < 0) {
dev_err(&pdev->dev, "failed to register MII bus\n");
- mdiobus_free(adapter->mii_bus);
goto err_mdio_free_irq;
}
- if (et131x_mii_probe(netdev)) {
+ rc = et131x_mii_probe(netdev);
+ if (rc < 0) {
dev_err(&pdev->dev, "failed to probe MII bus\n");
goto err_mdio_unregister;
}
@@ -5440,10 +5396,10 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev,
*/
/* Register the net_device struct with the Linux network layer */
- result = register_netdev(netdev);
- if (result != 0) {
+ rc = register_netdev(netdev);
+ if (rc < 0) {
dev_err(&pdev->dev, "register_netdev() failed\n");
- goto err_mdio_unregister;
+ goto err_phy_disconnect;
}
/* Register the net_device struct with the PCI subsystem. Save a copy
@@ -5451,10 +5407,11 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev,
* been initialized, just in case it needs to be quickly restored.
*/
pci_set_drvdata(pdev, netdev);
- pci_save_state(adapter->pdev);
-
- return result;
+out:
+ return rc;
+err_phy_disconnect:
+ phy_disconnect(adapter->phydev);
err_mdio_unregister:
mdiobus_unregister(adapter->mii_bus);
err_mdio_free_irq:
@@ -5472,8 +5429,7 @@ err_release_res:
pci_release_regions(pdev);
err_disable:
pci_disable_device(pdev);
-err_out:
- return result;
+ goto out;
}
static DEFINE_PCI_DEVICE_TABLE(et131x_pci_table) = {
diff --git a/drivers/staging/frontier/tranzport.c b/drivers/staging/frontier/tranzport.c
index c263284ddc0e..cf47a5d191fc 100644
--- a/drivers/staging/frontier/tranzport.c
+++ b/drivers/staging/frontier/tranzport.c
@@ -199,7 +199,7 @@ static void usb_tranzport_abort_transfers(struct usb_tranzport *dev)
struct usb_interface *intf = to_usb_interface(dev); \
struct usb_tranzport *t = usb_get_intfdata(intf); \
unsigned long temp; \
- if (strict_strtoul(buf, 10, &temp)) \
+ if (kstrtoul(buf, 10, &temp)) \
return -EINVAL; \
t->value = temp; \
return count; \
diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig
index bfe2166acda6..c7a2b3bc0a18 100644
--- a/drivers/staging/gma500/Kconfig
+++ b/drivers/staging/gma500/Kconfig
@@ -1,6 +1,6 @@
config DRM_PSB
tristate "Intel GMA5/600 KMS Framebuffer"
- depends on DRM && PCI && X86
+ depends on DRM && PCI && X86 && BROKEN
select FB_CFB_COPYAREA
select FB_CFB_FILLRECT
select FB_CFB_IMAGEBLIT
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c
index 114b99a1ce19..b8f78ebbb145 100644
--- a/drivers/staging/gma500/accel_2d.c
+++ b/drivers/staging/gma500/accel_2d.c
@@ -253,7 +253,7 @@ static void psbfb_copyarea_accel(struct fb_info *info,
return;
offset = psbfb->gtt->offset;
- stride = fb->pitch;
+ stride = fb->pitches[0];
switch (fb->depth) {
case 8:
diff --git a/drivers/staging/gma500/cdv_intel_display.c b/drivers/staging/gma500/cdv_intel_display.c
index 7b97c600eff0..c63a32776a9e 100644
--- a/drivers/staging/gma500/cdv_intel_display.c
+++ b/drivers/staging/gma500/cdv_intel_display.c
@@ -507,9 +507,9 @@ int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
if (ret < 0)
goto psb_intel_pipe_set_base_exit;
start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+ offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
- REG_WRITE(dspstride, crtc->fb->pitch);
+ REG_WRITE(dspstride, crtc->fb->pitches[0]);
dspcntr = REG_READ(dspcntr_reg);
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
index 3f39a37456fc..b00761cba144 100644
--- a/drivers/staging/gma500/framebuffer.c
+++ b/drivers/staging/gma500/framebuffer.c
@@ -32,6 +32,7 @@
#include <drm/drmP.h>
#include <drm/drm.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_fb_helper.h>
#include "psb_drv.h"
#include "psb_intel_reg.h"
@@ -273,14 +274,17 @@ static struct fb_ops psbfb_unaccel_ops = {
*/
static int psb_framebuffer_init(struct drm_device *dev,
struct psb_framebuffer *fb,
- struct drm_mode_fb_cmd *mode_cmd,
+ struct drm_mode_fb_cmd2 *mode_cmd,
struct gtt_range *gt)
{
+ u32 bpp, depth;
int ret;
- if (mode_cmd->pitch & 63)
+ drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+
+ if (mode_cmd->pitches[0] & 63)
return -EINVAL;
- switch (mode_cmd->bpp) {
+ switch (bpp) {
case 8:
case 16:
case 24:
@@ -313,7 +317,7 @@ static int psb_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *psb_framebuffer_create
(struct drm_device *dev,
- struct drm_mode_fb_cmd *mode_cmd,
+ struct drm_mode_fb_cmd2 *mode_cmd,
struct gtt_range *gt)
{
struct psb_framebuffer *fb;
@@ -387,27 +391,28 @@ static int psbfb_create(struct psb_fbdev *fbdev,
struct fb_info *info;
struct drm_framebuffer *fb;
struct psb_framebuffer *psbfb = &fbdev->pfb;
- struct drm_mode_fb_cmd mode_cmd;
+ struct drm_mode_fb_cmd2 mode_cmd;
struct device *device = &dev->pdev->dev;
int size;
int ret;
struct gtt_range *backing;
int gtt_roll = 1;
+ u32 bpp, depth;
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
- mode_cmd.bpp = sizes->surface_bpp;
+ bpp = sizes->surface_bpp;
/* No 24bit packed */
- if (mode_cmd.bpp == 24)
- mode_cmd.bpp = 32;
+ if (bpp == 24)
+ bpp = 32;
/* Acceleration via the GTT requires pitch to be 4096 byte aligned
(ie 1024 or 2048 pixels in normal use) */
- mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 4096);
- mode_cmd.depth = sizes->surface_depth;
+ mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096);
+ depth = sizes->surface_depth;
- size = mode_cmd.pitch * mode_cmd.height;
+ size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);
/* Allocate the framebuffer in the GTT with stolen page backing */
@@ -421,10 +426,10 @@ static int psbfb_create(struct psb_fbdev *fbdev,
gtt_roll = 0; /* Don't use GTT accelerated scrolling */
- mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
- mode_cmd.depth = sizes->surface_depth;
+ mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
+ depth = sizes->surface_depth;
- size = mode_cmd.pitch * mode_cmd.height;
+ size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);
/* Allocate the framebuffer in the GTT with stolen page
@@ -443,6 +448,8 @@ static int psbfb_create(struct psb_fbdev *fbdev,
}
info->par = fbdev;
+ mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
+
ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
if (ret)
goto out_unref;
@@ -504,7 +511,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
}
- drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
sizes->fb_width, sizes->fb_height);
@@ -546,7 +553,7 @@ out_err1:
*/
static struct drm_framebuffer *psb_user_framebuffer_create
(struct drm_device *dev, struct drm_file *filp,
- struct drm_mode_fb_cmd *cmd)
+ struct drm_mode_fb_cmd2 *cmd)
{
struct gtt_range *r;
struct drm_gem_object *obj;
@@ -555,7 +562,7 @@ static struct drm_framebuffer *psb_user_framebuffer_create
* Find the GEM object and thus the gtt range object that is
* to back this space
*/
- obj = drm_gem_object_lookup(dev, filp, cmd->handle);
+ obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]);
if (obj == NULL)
return ERR_PTR(-ENOENT);
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
index 8eb827ecc3d3..0b37b7b6b02a 100644
--- a/drivers/staging/gma500/mdfld_intel_display.c
+++ b/drivers/staging/gma500/mdfld_intel_display.c
@@ -390,9 +390,9 @@ int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_f
goto psb_intel_pipe_set_base_exit;
start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+ offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
- REG_WRITE(dspstride, crtc->fb->pitch);
+ REG_WRITE(dspstride, crtc->fb->pitches[0]);
dspcntr = REG_READ(dspcntr_reg);
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
index c9311a573c28..980837e37d80 100644
--- a/drivers/staging/gma500/mrst_crtc.c
+++ b/drivers/staging/gma500/mrst_crtc.c
@@ -543,9 +543,9 @@ int mrst_pipe_set_base(struct drm_crtc *crtc,
return 0;
start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+ offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
- REG_WRITE(dspstride, crtc->fb->pitch);
+ REG_WRITE(dspstride, crtc->fb->pitches[0]);
dspcntr = REG_READ(dspcntr_reg);
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
index 436fe9733b16..408257038335 100644
--- a/drivers/staging/gma500/power.c
+++ b/drivers/staging/gma500/power.c
@@ -266,7 +266,7 @@ bool gma_power_begin(struct drm_device *dev, bool force_on)
ret = gma_resume_pci(dev->pdev);
if (ret == 0) {
/* FIXME: we want to defer this for Medfield/Oaktrail */
- gma_resume_display(dev);
+ gma_resume_display(dev->pdev);
psb_irq_preinstall(dev);
psb_irq_postinstall(dev);
pm_runtime_get(&dev->pdev->dev);
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 986a04d16ba8..95816808f867 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -1151,6 +1151,17 @@ static struct vm_operations_struct psb_gem_vm_ops = {
.close = drm_gem_vm_close,
};
+static const struct file_operations gma500_driver_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = psb_unlocked_ioctl,
+ .mmap = drm_gem_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ .read = drm_read,
+};
+
static struct drm_driver driver = {
.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM ,
@@ -1179,17 +1190,7 @@ static struct drm_driver driver = {
.dumb_create = psb_gem_dumb_create,
.dumb_map_offset = psb_gem_dumb_map_gtt,
.dumb_destroy = psb_gem_dumb_destroy,
-
- .fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = psb_unlocked_ioctl,
- .mmap = drm_gem_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- .read = drm_read,
- },
+ .fops = &gma500_driver_fops,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = PSB_DRM_DRIVER_DATE,
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index caa9d86f26d8..85659613ae62 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -367,9 +367,9 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
goto psb_intel_pipe_set_base_exit;
start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+ offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
- REG_WRITE(dspstride, crtc->fb->pitch);
+ REG_WRITE(dspstride, crtc->fb->pitches[0]);
dspcntr = REG_READ(dspcntr_reg);
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig
index 072185ebe95b..60ac479a2909 100644
--- a/drivers/staging/hv/Kconfig
+++ b/drivers/staging/hv/Kconfig
@@ -3,15 +3,3 @@ config HYPERV_STORAGE
depends on HYPERV && SCSI
help
Select this option to enable the Hyper-V virtual storage driver.
-
-config HYPERV_NET
- tristate "Microsoft Hyper-V virtual network driver"
- depends on HYPERV && NET
- help
- Select this option to enable the Hyper-V virtual network driver.
-
-config HYPERV_MOUSE
- tristate "Microsoft Hyper-V mouse driver"
- depends on HYPERV && HID
- help
- Select this option to enable the Hyper-V mouse driver.
diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
index 0f55ceee919b..af95a6b7e436 100644
--- a/drivers/staging/hv/Makefile
+++ b/drivers/staging/hv/Makefile
@@ -1,6 +1,3 @@
obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o
-obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o
-obj-$(CONFIG_HYPERV_MOUSE) += hv_mouse.o
hv_storvsc-y := storvsc_drv.o
-hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO
index ed4d63619df2..dea7d92dfdc1 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -1,7 +1,5 @@
TODO:
- - audit the network driver
- audit the scsi driver
Please send patches for this code to Greg Kroah-Hartman <gregkh@suse.de>,
-Hank Janssen <hjanssen@microsoft.com>, Haiyang Zhang <haiyangz@microsoft.com>,
-K. Y. Srinivasan <kys@microsoft.com>
+Haiyang Zhang <haiyangz@microsoft.com>, and K. Y. Srinivasan <kys@microsoft.com>
diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
deleted file mode 100644
index ccd39c70c527..000000000000
--- a/drivers/staging/hv/hv_mouse.c
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright (c) 2009, Citrix Systems, Inc.
- * Copyright (c) 2010, Microsoft Corporation.
- * Copyright (c) 2011, Novell Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/input.h>
-#include <linux/hid.h>
-#include <linux/hiddev.h>
-#include <linux/hyperv.h>
-
-
-struct hv_input_dev_info {
- unsigned int size;
- unsigned short vendor;
- unsigned short product;
- unsigned short version;
- unsigned short reserved[11];
-};
-
-/* The maximum size of a synthetic input message. */
-#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
-
-/*
- * Current version
- *
- * History:
- * Beta, RC < 2008/1/22 1,0
- * RC > 2008/1/22 2,0
- */
-#define SYNTHHID_INPUT_VERSION_MAJOR 2
-#define SYNTHHID_INPUT_VERSION_MINOR 0
-#define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \
- (SYNTHHID_INPUT_VERSION_MAJOR << 16))
-
-
-#pragma pack(push, 1)
-/*
- * Message types in the synthetic input protocol
- */
-enum synthhid_msg_type {
- SYNTH_HID_PROTOCOL_REQUEST,
- SYNTH_HID_PROTOCOL_RESPONSE,
- SYNTH_HID_INITIAL_DEVICE_INFO,
- SYNTH_HID_INITIAL_DEVICE_INFO_ACK,
- SYNTH_HID_INPUT_REPORT,
- SYNTH_HID_MAX
-};
-
-/*
- * Basic message structures.
- */
-struct synthhid_msg_hdr {
- enum synthhid_msg_type type;
- u32 size;
-};
-
-struct synthhid_msg {
- struct synthhid_msg_hdr header;
- char data[1]; /* Enclosed message */
-};
-
-union synthhid_version {
- struct {
- u16 minor_version;
- u16 major_version;
- };
- u32 version;
-};
-
-/*
- * Protocol messages
- */
-struct synthhid_protocol_request {
- struct synthhid_msg_hdr header;
- union synthhid_version version_requested;
-};
-
-struct synthhid_protocol_response {
- struct synthhid_msg_hdr header;
- union synthhid_version version_requested;
- unsigned char approved;
-};
-
-struct synthhid_device_info {
- struct synthhid_msg_hdr header;
- struct hv_input_dev_info hid_dev_info;
- struct hid_descriptor hid_descriptor;
-};
-
-struct synthhid_device_info_ack {
- struct synthhid_msg_hdr header;
- unsigned char reserved;
-};
-
-struct synthhid_input_report {
- struct synthhid_msg_hdr header;
- char buffer[1];
-};
-
-#pragma pack(pop)
-
-#define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE)
-#define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE)
-
-#define NBITS(x) (((x)/BITS_PER_LONG)+1)
-
-enum pipe_prot_msg_type {
- PIPE_MESSAGE_INVALID,
- PIPE_MESSAGE_DATA,
- PIPE_MESSAGE_MAXIMUM
-};
-
-
-struct pipe_prt_msg {
- enum pipe_prot_msg_type type;
- u32 size;
- char data[1];
-};
-
-struct mousevsc_prt_msg {
- enum pipe_prot_msg_type type;
- u32 size;
- union {
- struct synthhid_protocol_request request;
- struct synthhid_protocol_response response;
- struct synthhid_device_info_ack ack;
- };
-};
-
-/*
- * Represents an mousevsc device
- */
-struct mousevsc_dev {
- struct hv_device *device;
- unsigned char init_complete;
- struct mousevsc_prt_msg protocol_req;
- struct mousevsc_prt_msg protocol_resp;
- /* Synchronize the request/response if needed */
- struct completion wait_event;
- int dev_info_status;
-
- struct hid_descriptor *hid_desc;
- unsigned char *report_desc;
- u32 report_desc_size;
- struct hv_input_dev_info hid_dev_info;
- int connected;
- struct hid_device *hid_device;
-};
-
-
-static struct mousevsc_dev *alloc_input_device(struct hv_device *device)
-{
- struct mousevsc_dev *input_dev;
-
- input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL);
-
- if (!input_dev)
- return NULL;
-
- input_dev->device = device;
- hv_set_drvdata(device, input_dev);
- init_completion(&input_dev->wait_event);
-
- return input_dev;
-}
-
-static void free_input_device(struct mousevsc_dev *device)
-{
- kfree(device->hid_desc);
- kfree(device->report_desc);
- hv_set_drvdata(device->device, NULL);
- kfree(device);
-}
-
-
-static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
- struct synthhid_device_info *device_info)
-{
- int ret = 0;
- struct hid_descriptor *desc;
- struct mousevsc_prt_msg ack;
-
- /* Assume success for now */
- input_device->dev_info_status = 0;
-
- memcpy(&input_device->hid_dev_info, &device_info->hid_dev_info,
- sizeof(struct hv_input_dev_info));
-
- desc = &device_info->hid_descriptor;
- WARN_ON(desc->bLength == 0);
-
- input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC);
-
- if (!input_device->hid_desc)
- goto cleanup;
-
- memcpy(input_device->hid_desc, desc, desc->bLength);
-
- input_device->report_desc_size = desc->desc[0].wDescriptorLength;
- if (input_device->report_desc_size == 0)
- goto cleanup;
- input_device->report_desc = kzalloc(input_device->report_desc_size,
- GFP_ATOMIC);
-
- if (!input_device->report_desc)
- goto cleanup;
-
- memcpy(input_device->report_desc,
- ((unsigned char *)desc) + desc->bLength,
- desc->desc[0].wDescriptorLength);
-
- /* Send the ack */
- memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
-
- ack.type = PIPE_MESSAGE_DATA;
- ack.size = sizeof(struct synthhid_device_info_ack);
-
- ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK;
- ack.ack.header.size = 1;
- ack.ack.reserved = 0;
-
- ret = vmbus_sendpacket(input_device->device->channel,
- &ack,
- sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
- sizeof(struct synthhid_device_info_ack),
- (unsigned long)&ack,
- VM_PKT_DATA_INBAND,
- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
- if (ret != 0)
- goto cleanup;
-
- complete(&input_device->wait_event);
-
- return;
-
-cleanup:
- kfree(input_device->hid_desc);
- input_device->hid_desc = NULL;
-
- kfree(input_device->report_desc);
- input_device->report_desc = NULL;
-
- input_device->dev_info_status = -1;
- complete(&input_device->wait_event);
-}
-
-static void mousevsc_on_receive(struct hv_device *device,
- struct vmpacket_descriptor *packet)
-{
- struct pipe_prt_msg *pipe_msg;
- struct synthhid_msg *hid_msg;
- struct mousevsc_dev *input_dev = hv_get_drvdata(device);
- struct synthhid_input_report *input_report;
-
- pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
- (packet->offset8 << 3));
-
- if (pipe_msg->type != PIPE_MESSAGE_DATA)
- return;
-
- hid_msg = (struct synthhid_msg *)&pipe_msg->data[0];
-
- switch (hid_msg->header.type) {
- case SYNTH_HID_PROTOCOL_RESPONSE:
- memcpy(&input_dev->protocol_resp, pipe_msg,
- pipe_msg->size + sizeof(struct pipe_prt_msg) -
- sizeof(unsigned char));
- complete(&input_dev->wait_event);
- break;
-
- case SYNTH_HID_INITIAL_DEVICE_INFO:
- WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info));
-
- /*
- * Parse out the device info into device attr,
- * hid desc and report desc
- */
- mousevsc_on_receive_device_info(input_dev,
- (struct synthhid_device_info *)&pipe_msg->data[0]);
- break;
- case SYNTH_HID_INPUT_REPORT:
- input_report =
- (struct synthhid_input_report *)&pipe_msg->data[0];
- if (!input_dev->init_complete)
- break;
- hid_input_report(input_dev->hid_device,
- HID_INPUT_REPORT, input_report->buffer,
- input_report->header.size, 1);
- break;
- default:
- pr_err("unsupported hid msg type - type %d len %d",
- hid_msg->header.type, hid_msg->header.size);
- break;
- }
-
-}
-
-static void mousevsc_on_channel_callback(void *context)
-{
- const int packetSize = 0x100;
- int ret = 0;
- struct hv_device *device = (struct hv_device *)context;
-
- u32 bytes_recvd;
- u64 req_id;
- unsigned char packet[0x100];
- struct vmpacket_descriptor *desc;
- unsigned char *buffer = packet;
- int bufferlen = packetSize;
-
-
- do {
- ret = vmbus_recvpacket_raw(device->channel, buffer,
- bufferlen, &bytes_recvd, &req_id);
-
- if (ret == 0) {
- if (bytes_recvd > 0) {
- desc = (struct vmpacket_descriptor *)buffer;
-
- switch (desc->type) {
- case VM_PKT_COMP:
- break;
-
- case VM_PKT_DATA_INBAND:
- mousevsc_on_receive(
- device, desc);
- break;
-
- default:
- pr_err("unhandled packet type %d, tid %llx len %d\n",
- desc->type,
- req_id,
- bytes_recvd);
- break;
- }
-
- /* reset */
- if (bufferlen > packetSize) {
- kfree(buffer);
-
- buffer = packet;
- bufferlen = packetSize;
- }
- } else {
- if (bufferlen > packetSize) {
- kfree(buffer);
-
- buffer = packet;
- bufferlen = packetSize;
- }
- break;
- }
- } else if (ret == -ENOBUFS) {
- /* Handle large packet */
- bufferlen = bytes_recvd;
- buffer = kzalloc(bytes_recvd, GFP_ATOMIC);
-
- if (buffer == NULL) {
- buffer = packet;
- bufferlen = packetSize;
- break;
- }
- }
- } while (1);
-
- return;
-}
-
-static int mousevsc_connect_to_vsp(struct hv_device *device)
-{
- int ret = 0;
- int t;
- struct mousevsc_dev *input_dev = hv_get_drvdata(device);
- struct mousevsc_prt_msg *request;
- struct mousevsc_prt_msg *response;
-
-
- request = &input_dev->protocol_req;
-
- memset(request, 0, sizeof(struct mousevsc_prt_msg));
-
- request->type = PIPE_MESSAGE_DATA;
- request->size = sizeof(struct synthhid_protocol_request);
-
- request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST;
- request->request.header.size = sizeof(unsigned int);
- request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
-
-
- ret = vmbus_sendpacket(device->channel, request,
- sizeof(struct pipe_prt_msg) -
- sizeof(unsigned char) +
- sizeof(struct synthhid_protocol_request),
- (unsigned long)request,
- VM_PKT_DATA_INBAND,
- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
- if (ret != 0)
- goto cleanup;
-
- t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
- if (t == 0) {
- ret = -ETIMEDOUT;
- goto cleanup;
- }
-
- response = &input_dev->protocol_resp;
-
- if (!response->response.approved) {
- pr_err("synthhid protocol request failed (version %d)",
- SYNTHHID_INPUT_VERSION);
- ret = -ENODEV;
- goto cleanup;
- }
-
- t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
- if (t == 0) {
- ret = -ETIMEDOUT;
- goto cleanup;
- }
-
- /*
- * We should have gotten the device attr, hid desc and report
- * desc at this point
- */
- if (input_dev->dev_info_status)
- ret = -ENOMEM;
-
-cleanup:
-
- return ret;
-}
-
-static int mousevsc_hid_open(struct hid_device *hid)
-{
- return 0;
-}
-
-static void mousevsc_hid_close(struct hid_device *hid)
-{
-}
-
-static struct hid_ll_driver mousevsc_ll_driver = {
- .open = mousevsc_hid_open,
- .close = mousevsc_hid_close,
-};
-
-static struct hid_driver mousevsc_hid_driver;
-
-static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len)
-{
- struct hid_device *hid_dev;
- struct mousevsc_dev *input_device = hv_get_drvdata(dev);
-
- hid_dev = hid_allocate_device();
- if (IS_ERR(hid_dev))
- return;
-
- hid_dev->ll_driver = &mousevsc_ll_driver;
- hid_dev->driver = &mousevsc_hid_driver;
-
- if (hid_parse_report(hid_dev, packet, len))
- return;
-
- hid_dev->bus = BUS_VIRTUAL;
- hid_dev->vendor = input_device->hid_dev_info.vendor;
- hid_dev->product = input_device->hid_dev_info.product;
- hid_dev->version = input_device->hid_dev_info.version;
-
- sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
-
- if (!hidinput_connect(hid_dev, 0)) {
- hid_dev->claimed |= HID_CLAIMED_INPUT;
-
- input_device->connected = 1;
-
- }
-
- input_device->hid_device = hid_dev;
-}
-
-static int mousevsc_on_device_add(struct hv_device *device)
-{
- int ret = 0;
- struct mousevsc_dev *input_dev;
-
- input_dev = alloc_input_device(device);
-
- if (!input_dev)
- return -ENOMEM;
-
- input_dev->init_complete = false;
-
- ret = vmbus_open(device->channel,
- INPUTVSC_SEND_RING_BUFFER_SIZE,
- INPUTVSC_RECV_RING_BUFFER_SIZE,
- NULL,
- 0,
- mousevsc_on_channel_callback,
- device
- );
-
- if (ret != 0) {
- free_input_device(input_dev);
- return ret;
- }
-
-
- ret = mousevsc_connect_to_vsp(device);
-
- if (ret != 0) {
- vmbus_close(device->channel);
- free_input_device(input_dev);
- return ret;
- }
-
-
- /* workaround SA-167 */
- if (input_dev->report_desc[14] == 0x25)
- input_dev->report_desc[14] = 0x29;
-
- reportdesc_callback(device, input_dev->report_desc,
- input_dev->report_desc_size);
-
- input_dev->init_complete = true;
-
- return ret;
-}
-
-static int mousevsc_probe(struct hv_device *dev,
- const struct hv_vmbus_device_id *dev_id)
-{
-
- return mousevsc_on_device_add(dev);
-
-}
-
-static int mousevsc_remove(struct hv_device *dev)
-{
- struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
-
- vmbus_close(dev->channel);
-
- if (input_dev->connected) {
- hidinput_disconnect(input_dev->hid_device);
- input_dev->connected = 0;
- hid_destroy_device(input_dev->hid_device);
- }
-
- free_input_device(input_dev);
-
- return 0;
-}
-
-static const struct hv_vmbus_device_id id_table[] = {
- /* Mouse guid */
- { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
- 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) },
- { },
-};
-
-MODULE_DEVICE_TABLE(vmbus, id_table);
-
-static struct hv_driver mousevsc_drv = {
- .name = "mousevsc",
- .id_table = id_table,
- .probe = mousevsc_probe,
- .remove = mousevsc_remove,
-};
-
-static int __init mousevsc_init(void)
-{
- return vmbus_driver_register(&mousevsc_drv);
-}
-
-static void __exit mousevsc_exit(void)
-{
- vmbus_driver_unregister(&mousevsc_drv);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION(HV_DRV_VERSION);
-module_init(mousevsc_init);
-module_exit(mousevsc_exit);
diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
deleted file mode 100644
index ac1ec8405124..000000000000
--- a/drivers/staging/hv/hyperv_net.h
+++ /dev/null
@@ -1,1058 +0,0 @@
-/*
- *
- * Copyright (c) 2011, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- * Haiyang Zhang <haiyangz@microsoft.com>
- * Hank Janssen <hjanssen@microsoft.com>
- * K. Y. Srinivasan <kys@microsoft.com>
- *
- */
-
-#ifndef _HYPERV_NET_H
-#define _HYPERV_NET_H
-
-#include <linux/list.h>
-#include <linux/hyperv.h>
-
-/* Fwd declaration */
-struct hv_netvsc_packet;
-
-/* Represent the xfer page packet which contains 1 or more netvsc packet */
-struct xferpage_packet {
- struct list_head list_ent;
-
- /* # of netvsc packets this xfer packet contains */
- u32 count;
-};
-
-/* The number of pages which are enough to cover jumbo frame buffer. */
-#define NETVSC_PACKET_MAXPAGE 4
-
-/*
- * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
- * within the RNDIS
- */
-struct hv_netvsc_packet {
- /* Bookkeeping stuff */
- struct list_head list_ent;
-
- struct hv_device *device;
- bool is_data_pkt;
-
- /*
- * Valid only for receives when we break a xfer page packet
- * into multiple netvsc packets
- */
- struct xferpage_packet *xfer_page_pkt;
-
- union {
- struct {
- u64 recv_completion_tid;
- void *recv_completion_ctx;
- void (*recv_completion)(void *context);
- } recv;
- struct {
- u64 send_completion_tid;
- void *send_completion_ctx;
- void (*send_completion)(void *context);
- } send;
- } completion;
-
- /* This points to the memory after page_buf */
- void *extension;
-
- u32 total_data_buflen;
- /* Points to the send/receive buffer where the ethernet frame is */
- u32 page_buf_cnt;
- struct hv_page_buffer page_buf[NETVSC_PACKET_MAXPAGE];
-};
-
-struct netvsc_device_info {
- unsigned char mac_adr[6];
- bool link_state; /* 0 - link up, 1 - link down */
- int ring_size;
-};
-
-/* Interface */
-int netvsc_device_add(struct hv_device *device, void *additional_info);
-int netvsc_device_remove(struct hv_device *device);
-int netvsc_send(struct hv_device *device,
- struct hv_netvsc_packet *packet);
-void netvsc_linkstatus_callback(struct hv_device *device_obj,
- unsigned int status);
-int netvsc_recv_callback(struct hv_device *device_obj,
- struct hv_netvsc_packet *packet);
-int rndis_filter_open(struct hv_device *dev);
-int rndis_filter_close(struct hv_device *dev);
-int rndis_filter_device_add(struct hv_device *dev,
- void *additional_info);
-void rndis_filter_device_remove(struct hv_device *dev);
-int rndis_filter_receive(struct hv_device *dev,
- struct hv_netvsc_packet *pkt);
-
-
-
-int rndis_filter_send(struct hv_device *dev,
- struct hv_netvsc_packet *pkt);
-
-#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF)
-
-#define NVSP_PROTOCOL_VERSION_1 2
-#define NVSP_MIN_PROTOCOL_VERSION NVSP_PROTOCOL_VERSION_1
-#define NVSP_MAX_PROTOCOL_VERSION NVSP_PROTOCOL_VERSION_1
-
-enum {
- NVSP_MSG_TYPE_NONE = 0,
-
- /* Init Messages */
- NVSP_MSG_TYPE_INIT = 1,
- NVSP_MSG_TYPE_INIT_COMPLETE = 2,
-
- NVSP_VERSION_MSG_START = 100,
-
- /* Version 1 Messages */
- NVSP_MSG1_TYPE_SEND_NDIS_VER = NVSP_VERSION_MSG_START,
-
- NVSP_MSG1_TYPE_SEND_RECV_BUF,
- NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE,
- NVSP_MSG1_TYPE_REVOKE_RECV_BUF,
-
- NVSP_MSG1_TYPE_SEND_SEND_BUF,
- NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE,
- NVSP_MSG1_TYPE_REVOKE_SEND_BUF,
-
- NVSP_MSG1_TYPE_SEND_RNDIS_PKT,
- NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE,
-
- /*
- * This should be set to the number of messages for the version with
- * the maximum number of messages.
- */
- NVSP_NUM_MSG_PER_VERSION = 9,
-};
-
-enum {
- NVSP_STAT_NONE = 0,
- NVSP_STAT_SUCCESS,
- NVSP_STAT_FAIL,
- NVSP_STAT_PROTOCOL_TOO_NEW,
- NVSP_STAT_PROTOCOL_TOO_OLD,
- NVSP_STAT_INVALID_RNDIS_PKT,
- NVSP_STAT_BUSY,
- NVSP_STAT_MAX,
-};
-
-struct nvsp_message_header {
- u32 msg_type;
-};
-
-/* Init Messages */
-
-/*
- * This message is used by the VSC to initialize the channel after the channels
- * has been opened. This message should never include anything other then
- * versioning (i.e. this message will be the same for ever).
- */
-struct nvsp_message_init {
- u32 min_protocol_ver;
- u32 max_protocol_ver;
-} __packed;
-
-/*
- * This message is used by the VSP to complete the initialization of the
- * channel. This message should never include anything other then versioning
- * (i.e. this message will be the same for ever).
- */
-struct nvsp_message_init_complete {
- u32 negotiated_protocol_ver;
- u32 max_mdl_chain_len;
- u32 status;
-} __packed;
-
-union nvsp_message_init_uber {
- struct nvsp_message_init init;
- struct nvsp_message_init_complete init_complete;
-} __packed;
-
-/* Version 1 Messages */
-
-/*
- * This message is used by the VSC to send the NDIS version to the VSP. The VSP
- * can use this information when handling OIDs sent by the VSC.
- */
-struct nvsp_1_message_send_ndis_version {
- u32 ndis_major_ver;
- u32 ndis_minor_ver;
-} __packed;
-
-/*
- * This message is used by the VSC to send a receive buffer to the VSP. The VSP
- * can then use the receive buffer to send data to the VSC.
- */
-struct nvsp_1_message_send_receive_buffer {
- u32 gpadl_handle;
- u16 id;
-} __packed;
-
-struct nvsp_1_receive_buffer_section {
- u32 offset;
- u32 sub_alloc_size;
- u32 num_sub_allocs;
- u32 end_offset;
-} __packed;
-
-/*
- * This message is used by the VSP to acknowledge a receive buffer send by the
- * VSC. This message must be sent by the VSP before the VSP uses the receive
- * buffer.
- */
-struct nvsp_1_message_send_receive_buffer_complete {
- u32 status;
- u32 num_sections;
-
- /*
- * The receive buffer is split into two parts, a large suballocation
- * section and a small suballocation section. These sections are then
- * suballocated by a certain size.
- */
-
- /*
- * For example, the following break up of the receive buffer has 6
- * large suballocations and 10 small suballocations.
- */
-
- /*
- * | Large Section | | Small Section |
- * ------------------------------------------------------------
- * | | | | | | | | | | | | | | | | | |
- * | |
- * LargeOffset SmallOffset
- */
-
- struct nvsp_1_receive_buffer_section sections[1];
-} __packed;
-
-/*
- * This message is sent by the VSC to revoke the receive buffer. After the VSP
- * completes this transaction, the vsp should never use the receive buffer
- * again.
- */
-struct nvsp_1_message_revoke_receive_buffer {
- u16 id;
-};
-
-/*
- * This message is used by the VSC to send a send buffer to the VSP. The VSC
- * can then use the send buffer to send data to the VSP.
- */
-struct nvsp_1_message_send_send_buffer {
- u32 gpadl_handle;
- u16 id;
-} __packed;
-
-/*
- * This message is used by the VSP to acknowledge a send buffer sent by the
- * VSC. This message must be sent by the VSP before the VSP uses the sent
- * buffer.
- */
-struct nvsp_1_message_send_send_buffer_complete {
- u32 status;
-
- /*
- * The VSC gets to choose the size of the send buffer and the VSP gets
- * to choose the sections size of the buffer. This was done to enable
- * dynamic reconfigurations when the cost of GPA-direct buffers
- * decreases.
- */
- u32 section_size;
-} __packed;
-
-/*
- * This message is sent by the VSC to revoke the send buffer. After the VSP
- * completes this transaction, the vsp should never use the send buffer again.
- */
-struct nvsp_1_message_revoke_send_buffer {
- u16 id;
-};
-
-/*
- * This message is used by both the VSP and the VSC to send a RNDIS message to
- * the opposite channel endpoint.
- */
-struct nvsp_1_message_send_rndis_packet {
- /*
- * This field is specified by RNIDS. They assume there's two different
- * channels of communication. However, the Network VSP only has one.
- * Therefore, the channel travels with the RNDIS packet.
- */
- u32 channel_type;
-
- /*
- * This field is used to send part or all of the data through a send
- * buffer. This values specifies an index into the send buffer. If the
- * index is 0xFFFFFFFF, then the send buffer is not being used and all
- * of the data was sent through other VMBus mechanisms.
- */
- u32 send_buf_section_index;
- u32 send_buf_section_size;
-} __packed;
-
-/*
- * This message is used by both the VSP and the VSC to complete a RNDIS message
- * to the opposite channel endpoint. At this point, the initiator of this
- * message cannot use any resources associated with the original RNDIS packet.
- */
-struct nvsp_1_message_send_rndis_packet_complete {
- u32 status;
-};
-
-union nvsp_1_message_uber {
- struct nvsp_1_message_send_ndis_version send_ndis_ver;
-
- struct nvsp_1_message_send_receive_buffer send_recv_buf;
- struct nvsp_1_message_send_receive_buffer_complete
- send_recv_buf_complete;
- struct nvsp_1_message_revoke_receive_buffer revoke_recv_buf;
-
- struct nvsp_1_message_send_send_buffer send_send_buf;
- struct nvsp_1_message_send_send_buffer_complete send_send_buf_complete;
- struct nvsp_1_message_revoke_send_buffer revoke_send_buf;
-
- struct nvsp_1_message_send_rndis_packet send_rndis_pkt;
- struct nvsp_1_message_send_rndis_packet_complete
- send_rndis_pkt_complete;
-} __packed;
-
-union nvsp_all_messages {
- union nvsp_message_init_uber init_msg;
- union nvsp_1_message_uber v1_msg;
-} __packed;
-
-/* ALL Messages */
-struct nvsp_message {
- struct nvsp_message_header hdr;
- union nvsp_all_messages msg;
-} __packed;
-
-
-
-
-/* #define NVSC_MIN_PROTOCOL_VERSION 1 */
-/* #define NVSC_MAX_PROTOCOL_VERSION 1 */
-
-#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024) /* 1MB */
-
-#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
-
-#define NETVSC_RECEIVE_SG_COUNT 1
-
-/* Preallocated receive packets */
-#define NETVSC_RECEIVE_PACKETLIST_COUNT 256
-
-#define NETVSC_PACKET_SIZE 2048
-
-/* Per netvsc channel-specific */
-struct netvsc_device {
- struct hv_device *dev;
-
- atomic_t num_outstanding_sends;
- bool destroy;
- /*
- * List of free preallocated hv_netvsc_packet to represent receive
- * packet
- */
- struct list_head recv_pkt_list;
- spinlock_t recv_pkt_list_lock;
-
- /* Receive buffer allocated by us but manages by NetVSP */
- void *recv_buf;
- u32 recv_buf_size;
- u32 recv_buf_gpadl_handle;
- u32 recv_section_cnt;
- struct nvsp_1_receive_buffer_section *recv_section;
-
- /* Used for NetVSP initialization protocol */
- struct completion channel_init_wait;
- struct nvsp_message channel_init_pkt;
-
- struct nvsp_message revoke_packet;
- /* unsigned char HwMacAddr[HW_MACADDR_LEN]; */
-
- struct net_device *ndev;
-
- /* Holds rndis device info */
- void *extension;
-};
-
-
-/* Status codes */
-
-
-#ifndef STATUS_SUCCESS
-#define STATUS_SUCCESS (0x00000000L)
-#endif
-
-#ifndef STATUS_UNSUCCESSFUL
-#define STATUS_UNSUCCESSFUL (0xC0000001L)
-#endif
-
-#ifndef STATUS_PENDING
-#define STATUS_PENDING (0x00000103L)
-#endif
-
-#ifndef STATUS_INSUFFICIENT_RESOURCES
-#define STATUS_INSUFFICIENT_RESOURCES (0xC000009AL)
-#endif
-
-#ifndef STATUS_BUFFER_OVERFLOW
-#define STATUS_BUFFER_OVERFLOW (0x80000005L)
-#endif
-
-#ifndef STATUS_NOT_SUPPORTED
-#define STATUS_NOT_SUPPORTED (0xC00000BBL)
-#endif
-
-#define RNDIS_STATUS_SUCCESS (STATUS_SUCCESS)
-#define RNDIS_STATUS_PENDING (STATUS_PENDING)
-#define RNDIS_STATUS_NOT_RECOGNIZED (0x00010001L)
-#define RNDIS_STATUS_NOT_COPIED (0x00010002L)
-#define RNDIS_STATUS_NOT_ACCEPTED (0x00010003L)
-#define RNDIS_STATUS_CALL_ACTIVE (0x00010007L)
-
-#define RNDIS_STATUS_ONLINE (0x40010003L)
-#define RNDIS_STATUS_RESET_START (0x40010004L)
-#define RNDIS_STATUS_RESET_END (0x40010005L)
-#define RNDIS_STATUS_RING_STATUS (0x40010006L)
-#define RNDIS_STATUS_CLOSED (0x40010007L)
-#define RNDIS_STATUS_WAN_LINE_UP (0x40010008L)
-#define RNDIS_STATUS_WAN_LINE_DOWN (0x40010009L)
-#define RNDIS_STATUS_WAN_FRAGMENT (0x4001000AL)
-#define RNDIS_STATUS_MEDIA_CONNECT (0x4001000BL)
-#define RNDIS_STATUS_MEDIA_DISCONNECT (0x4001000CL)
-#define RNDIS_STATUS_HARDWARE_LINE_UP (0x4001000DL)
-#define RNDIS_STATUS_HARDWARE_LINE_DOWN (0x4001000EL)
-#define RNDIS_STATUS_INTERFACE_UP (0x4001000FL)
-#define RNDIS_STATUS_INTERFACE_DOWN (0x40010010L)
-#define RNDIS_STATUS_MEDIA_BUSY (0x40010011L)
-#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION (0x40010012L)
-#define RNDIS_STATUS_WW_INDICATION RDIA_SPECIFIC_INDICATION
-#define RNDIS_STATUS_LINK_SPEED_CHANGE (0x40010013L)
-
-#define RNDIS_STATUS_NOT_RESETTABLE (0x80010001L)
-#define RNDIS_STATUS_SOFT_ERRORS (0x80010003L)
-#define RNDIS_STATUS_HARD_ERRORS (0x80010004L)
-#define RNDIS_STATUS_BUFFER_OVERFLOW (STATUS_BUFFER_OVERFLOW)
-
-#define RNDIS_STATUS_FAILURE (STATUS_UNSUCCESSFUL)
-#define RNDIS_STATUS_RESOURCES (STATUS_INSUFFICIENT_RESOURCES)
-#define RNDIS_STATUS_CLOSING (0xC0010002L)
-#define RNDIS_STATUS_BAD_VERSION (0xC0010004L)
-#define RNDIS_STATUS_BAD_CHARACTERISTICS (0xC0010005L)
-#define RNDIS_STATUS_ADAPTER_NOT_FOUND (0xC0010006L)
-#define RNDIS_STATUS_OPEN_FAILED (0xC0010007L)
-#define RNDIS_STATUS_DEVICE_FAILED (0xC0010008L)
-#define RNDIS_STATUS_MULTICAST_FULL (0xC0010009L)
-#define RNDIS_STATUS_MULTICAST_EXISTS (0xC001000AL)
-#define RNDIS_STATUS_MULTICAST_NOT_FOUND (0xC001000BL)
-#define RNDIS_STATUS_REQUEST_ABORTED (0xC001000CL)
-#define RNDIS_STATUS_RESET_IN_PROGRESS (0xC001000DL)
-#define RNDIS_STATUS_CLOSING_INDICATING (0xC001000EL)
-#define RNDIS_STATUS_NOT_SUPPORTED (STATUS_NOT_SUPPORTED)
-#define RNDIS_STATUS_INVALID_PACKET (0xC001000FL)
-#define RNDIS_STATUS_OPEN_LIST_FULL (0xC0010010L)
-#define RNDIS_STATUS_ADAPTER_NOT_READY (0xC0010011L)
-#define RNDIS_STATUS_ADAPTER_NOT_OPEN (0xC0010012L)
-#define RNDIS_STATUS_NOT_INDICATING (0xC0010013L)
-#define RNDIS_STATUS_INVALID_LENGTH (0xC0010014L)
-#define RNDIS_STATUS_INVALID_DATA (0xC0010015L)
-#define RNDIS_STATUS_BUFFER_TOO_SHORT (0xC0010016L)
-#define RNDIS_STATUS_INVALID_OID (0xC0010017L)
-#define RNDIS_STATUS_ADAPTER_REMOVED (0xC0010018L)
-#define RNDIS_STATUS_UNSUPPORTED_MEDIA (0xC0010019L)
-#define RNDIS_STATUS_GROUP_ADDRESS_IN_USE (0xC001001AL)
-#define RNDIS_STATUS_FILE_NOT_FOUND (0xC001001BL)
-#define RNDIS_STATUS_ERROR_READING_FILE (0xC001001CL)
-#define RNDIS_STATUS_ALREADY_MAPPED (0xC001001DL)
-#define RNDIS_STATUS_RESOURCE_CONFLICT (0xC001001EL)
-#define RNDIS_STATUS_NO_CABLE (0xC001001FL)
-
-#define RNDIS_STATUS_INVALID_SAP (0xC0010020L)
-#define RNDIS_STATUS_SAP_IN_USE (0xC0010021L)
-#define RNDIS_STATUS_INVALID_ADDRESS (0xC0010022L)
-#define RNDIS_STATUS_VC_NOT_ACTIVATED (0xC0010023L)
-#define RNDIS_STATUS_DEST_OUT_OF_ORDER (0xC0010024L)
-#define RNDIS_STATUS_VC_NOT_AVAILABLE (0xC0010025L)
-#define RNDIS_STATUS_CELLRATE_NOT_AVAILABLE (0xC0010026L)
-#define RNDIS_STATUS_INCOMPATABLE_QOS (0xC0010027L)
-#define RNDIS_STATUS_AAL_PARAMS_UNSUPPORTED (0xC0010028L)
-#define RNDIS_STATUS_NO_ROUTE_TO_DESTINATION (0xC0010029L)
-
-#define RNDIS_STATUS_TOKEN_RING_OPEN_ERROR (0xC0011000L)
-
-/* Object Identifiers used by NdisRequest Query/Set Information */
-/* General Objects */
-#define RNDIS_OID_GEN_SUPPORTED_LIST 0x00010101
-#define RNDIS_OID_GEN_HARDWARE_STATUS 0x00010102
-#define RNDIS_OID_GEN_MEDIA_SUPPORTED 0x00010103
-#define RNDIS_OID_GEN_MEDIA_IN_USE 0x00010104
-#define RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
-#define RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
-#define RNDIS_OID_GEN_LINK_SPEED 0x00010107
-#define RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
-#define RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
-#define RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
-#define RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
-#define RNDIS_OID_GEN_VENDOR_ID 0x0001010C
-#define RNDIS_OID_GEN_VENDOR_DESCRIPTION 0x0001010D
-#define RNDIS_OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
-#define RNDIS_OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
-#define RNDIS_OID_GEN_DRIVER_VERSION 0x00010110
-#define RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
-#define RNDIS_OID_GEN_PROTOCOL_OPTIONS 0x00010112
-#define RNDIS_OID_GEN_MAC_OPTIONS 0x00010113
-#define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
-#define RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
-#define RNDIS_OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
-#define RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118
-#define RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119
-#define RNDIS_OID_GEN_MACHINE_NAME 0x0001021A
-#define RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B
-
-#define RNDIS_OID_GEN_XMIT_OK 0x00020101
-#define RNDIS_OID_GEN_RCV_OK 0x00020102
-#define RNDIS_OID_GEN_XMIT_ERROR 0x00020103
-#define RNDIS_OID_GEN_RCV_ERROR 0x00020104
-#define RNDIS_OID_GEN_RCV_NO_BUFFER 0x00020105
-
-#define RNDIS_OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
-#define RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
-#define RNDIS_OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
-#define RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
-#define RNDIS_OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
-#define RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
-#define RNDIS_OID_GEN_DIRECTED_BYTES_RCV 0x00020207
-#define RNDIS_OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
-#define RNDIS_OID_GEN_MULTICAST_BYTES_RCV 0x00020209
-#define RNDIS_OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
-#define RNDIS_OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
-#define RNDIS_OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
-
-#define RNDIS_OID_GEN_RCV_CRC_ERROR 0x0002020D
-#define RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
-
-#define RNDIS_OID_GEN_GET_TIME_CAPS 0x0002020F
-#define RNDIS_OID_GEN_GET_NETCARD_TIME 0x00020210
-
-/* These are connection-oriented general OIDs. */
-/* These replace the above OIDs for connection-oriented media. */
-#define RNDIS_OID_GEN_CO_SUPPORTED_LIST 0x00010101
-#define RNDIS_OID_GEN_CO_HARDWARE_STATUS 0x00010102
-#define RNDIS_OID_GEN_CO_MEDIA_SUPPORTED 0x00010103
-#define RNDIS_OID_GEN_CO_MEDIA_IN_USE 0x00010104
-#define RNDIS_OID_GEN_CO_LINK_SPEED 0x00010105
-#define RNDIS_OID_GEN_CO_VENDOR_ID 0x00010106
-#define RNDIS_OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107
-#define RNDIS_OID_GEN_CO_DRIVER_VERSION 0x00010108
-#define RNDIS_OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109
-#define RNDIS_OID_GEN_CO_MAC_OPTIONS 0x0001010A
-#define RNDIS_OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B
-#define RNDIS_OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C
-#define RNDIS_OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D
-
-#define RNDIS_OID_GEN_CO_GET_TIME_CAPS 0x00010201
-#define RNDIS_OID_GEN_CO_GET_NETCARD_TIME 0x00010202
-
-/* These are connection-oriented statistics OIDs. */
-#define RNDIS_OID_GEN_CO_XMIT_PDUS_OK 0x00020101
-#define RNDIS_OID_GEN_CO_RCV_PDUS_OK 0x00020102
-#define RNDIS_OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103
-#define RNDIS_OID_GEN_CO_RCV_PDUS_ERROR 0x00020104
-#define RNDIS_OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105
-
-
-#define RNDIS_OID_GEN_CO_RCV_CRC_ERROR 0x00020201
-#define RNDIS_OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202
-#define RNDIS_OID_GEN_CO_BYTES_XMIT 0x00020203
-#define RNDIS_OID_GEN_CO_BYTES_RCV 0x00020204
-#define RNDIS_OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205
-#define RNDIS_OID_GEN_CO_NETCARD_LOAD 0x00020206
-
-/* These are objects for Connection-oriented media call-managers. */
-#define RNDIS_OID_CO_ADD_PVC 0xFF000001
-#define RNDIS_OID_CO_DELETE_PVC 0xFF000002
-#define RNDIS_OID_CO_GET_CALL_INFORMATION 0xFF000003
-#define RNDIS_OID_CO_ADD_ADDRESS 0xFF000004
-#define RNDIS_OID_CO_DELETE_ADDRESS 0xFF000005
-#define RNDIS_OID_CO_GET_ADDRESSES 0xFF000006
-#define RNDIS_OID_CO_ADDRESS_CHANGE 0xFF000007
-#define RNDIS_OID_CO_SIGNALING_ENABLED 0xFF000008
-#define RNDIS_OID_CO_SIGNALING_DISABLED 0xFF000009
-
-/* 802.3 Objects (Ethernet) */
-#define RNDIS_OID_802_3_PERMANENT_ADDRESS 0x01010101
-#define RNDIS_OID_802_3_CURRENT_ADDRESS 0x01010102
-#define RNDIS_OID_802_3_MULTICAST_LIST 0x01010103
-#define RNDIS_OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
-#define RNDIS_OID_802_3_MAC_OPTIONS 0x01010105
-
-#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
-
-#define RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
-#define RNDIS_OID_802_3_XMIT_ONE_COLLISION 0x01020102
-#define RNDIS_OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
-
-#define RNDIS_OID_802_3_XMIT_DEFERRED 0x01020201
-#define RNDIS_OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
-#define RNDIS_OID_802_3_RCV_OVERRUN 0x01020203
-#define RNDIS_OID_802_3_XMIT_UNDERRUN 0x01020204
-#define RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
-#define RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
-#define RNDIS_OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
-
-/* Remote NDIS message types */
-#define REMOTE_NDIS_PACKET_MSG 0x00000001
-#define REMOTE_NDIS_INITIALIZE_MSG 0x00000002
-#define REMOTE_NDIS_HALT_MSG 0x00000003
-#define REMOTE_NDIS_QUERY_MSG 0x00000004
-#define REMOTE_NDIS_SET_MSG 0x00000005
-#define REMOTE_NDIS_RESET_MSG 0x00000006
-#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007
-#define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008
-
-#define REMOTE_CONDIS_MP_CREATE_VC_MSG 0x00008001
-#define REMOTE_CONDIS_MP_DELETE_VC_MSG 0x00008002
-#define REMOTE_CONDIS_MP_ACTIVATE_VC_MSG 0x00008005
-#define REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG 0x00008006
-#define REMOTE_CONDIS_INDICATE_STATUS_MSG 0x00008007
-
-/* Remote NDIS message completion types */
-#define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002
-#define REMOTE_NDIS_QUERY_CMPLT 0x80000004
-#define REMOTE_NDIS_SET_CMPLT 0x80000005
-#define REMOTE_NDIS_RESET_CMPLT 0x80000006
-#define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008
-
-#define REMOTE_CONDIS_MP_CREATE_VC_CMPLT 0x80008001
-#define REMOTE_CONDIS_MP_DELETE_VC_CMPLT 0x80008002
-#define REMOTE_CONDIS_MP_ACTIVATE_VC_CMPLT 0x80008005
-#define REMOTE_CONDIS_MP_DEACTIVATE_VC_CMPLT 0x80008006
-
-/*
- * Reserved message type for private communication between lower-layer host
- * driver and remote device, if necessary.
- */
-#define REMOTE_NDIS_BUS_MSG 0xff000001
-
-/* Defines for DeviceFlags in struct rndis_initialize_complete */
-#define RNDIS_DF_CONNECTIONLESS 0x00000001
-#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002
-#define RNDIS_DF_RAW_DATA 0x00000004
-
-/* Remote NDIS medium types. */
-#define RNDIS_MEDIUM_802_3 0x00000000
-#define RNDIS_MEDIUM_802_5 0x00000001
-#define RNDIS_MEDIUM_FDDI 0x00000002
-#define RNDIS_MEDIUM_WAN 0x00000003
-#define RNDIS_MEDIUM_LOCAL_TALK 0x00000004
-#define RNDIS_MEDIUM_ARCNET_RAW 0x00000006
-#define RNDIS_MEDIUM_ARCNET_878_2 0x00000007
-#define RNDIS_MEDIUM_ATM 0x00000008
-#define RNDIS_MEDIUM_WIRELESS_WAN 0x00000009
-#define RNDIS_MEDIUM_IRDA 0x0000000a
-#define RNDIS_MEDIUM_CO_WAN 0x0000000b
-/* Not a real medium, defined as an upper-bound */
-#define RNDIS_MEDIUM_MAX 0x0000000d
-
-
-/* Remote NDIS medium connection states. */
-#define RNDIS_MEDIA_STATE_CONNECTED 0x00000000
-#define RNDIS_MEDIA_STATE_DISCONNECTED 0x00000001
-
-/* Remote NDIS version numbers */
-#define RNDIS_MAJOR_VERSION 0x00000001
-#define RNDIS_MINOR_VERSION 0x00000000
-
-
-/* NdisInitialize message */
-struct rndis_initialize_request {
- u32 req_id;
- u32 major_ver;
- u32 minor_ver;
- u32 max_xfer_size;
-};
-
-/* Response to NdisInitialize */
-struct rndis_initialize_complete {
- u32 req_id;
- u32 status;
- u32 major_ver;
- u32 minor_ver;
- u32 dev_flags;
- u32 medium;
- u32 max_pkt_per_msg;
- u32 max_xfer_size;
- u32 pkt_alignment_factor;
- u32 af_list_offset;
- u32 af_list_size;
-};
-
-/* Call manager devices only: Information about an address family */
-/* supported by the device is appended to the response to NdisInitialize. */
-struct rndis_co_address_family {
- u32 address_family;
- u32 major_ver;
- u32 minor_ver;
-};
-
-/* NdisHalt message */
-struct rndis_halt_request {
- u32 req_id;
-};
-
-/* NdisQueryRequest message */
-struct rndis_query_request {
- u32 req_id;
- u32 oid;
- u32 info_buflen;
- u32 info_buf_offset;
- u32 dev_vc_handle;
-};
-
-/* Response to NdisQueryRequest */
-struct rndis_query_complete {
- u32 req_id;
- u32 status;
- u32 info_buflen;
- u32 info_buf_offset;
-};
-
-/* NdisSetRequest message */
-struct rndis_set_request {
- u32 req_id;
- u32 oid;
- u32 info_buflen;
- u32 info_buf_offset;
- u32 dev_vc_handle;
-};
-
-/* Response to NdisSetRequest */
-struct rndis_set_complete {
- u32 req_id;
- u32 status;
-};
-
-/* NdisReset message */
-struct rndis_reset_request {
- u32 reserved;
-};
-
-/* Response to NdisReset */
-struct rndis_reset_complete {
- u32 status;
- u32 addressing_reset;
-};
-
-/* NdisMIndicateStatus message */
-struct rndis_indicate_status {
- u32 status;
- u32 status_buflen;
- u32 status_buf_offset;
-};
-
-/* Diagnostic information passed as the status buffer in */
-/* struct rndis_indicate_status messages signifying error conditions. */
-struct rndis_diagnostic_info {
- u32 diag_status;
- u32 error_offset;
-};
-
-/* NdisKeepAlive message */
-struct rndis_keepalive_request {
- u32 req_id;
-};
-
-/* Response to NdisKeepAlive */
-struct rndis_keepalive_complete {
- u32 req_id;
- u32 status;
-};
-
-/*
- * Data message. All Offset fields contain byte offsets from the beginning of
- * struct rndis_packet. All Length fields are in bytes. VcHandle is set
- * to 0 for connectionless data, otherwise it contains the VC handle.
- */
-struct rndis_packet {
- u32 data_offset;
- u32 data_len;
- u32 oob_data_offset;
- u32 oob_data_len;
- u32 num_oob_data_elements;
- u32 per_pkt_info_offset;
- u32 per_pkt_info_len;
- u32 vc_handle;
- u32 reserved;
-};
-
-/* Optional Out of Band data associated with a Data message. */
-struct rndis_oobd {
- u32 size;
- u32 type;
- u32 class_info_offset;
-};
-
-/* Packet extension field contents associated with a Data message. */
-struct rndis_per_packet_info {
- u32 size;
- u32 type;
- u32 per_pkt_info_offset;
-};
-
-/* Format of Information buffer passed in a SetRequest for the OID */
-/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
-struct rndis_config_parameter_info {
- u32 parameter_name_offset;
- u32 parameter_name_length;
- u32 parameter_type;
- u32 parameter_value_offset;
- u32 parameter_value_length;
-};
-
-/* Values for ParameterType in struct rndis_config_parameter_info */
-#define RNDIS_CONFIG_PARAM_TYPE_INTEGER 0
-#define RNDIS_CONFIG_PARAM_TYPE_STRING 2
-
-/* CONDIS Miniport messages for connection oriented devices */
-/* that do not implement a call manager. */
-
-/* CoNdisMiniportCreateVc message */
-struct rcondis_mp_create_vc {
- u32 req_id;
- u32 ndis_vc_handle;
-};
-
-/* Response to CoNdisMiniportCreateVc */
-struct rcondis_mp_create_vc_complete {
- u32 req_id;
- u32 dev_vc_handle;
- u32 status;
-};
-
-/* CoNdisMiniportDeleteVc message */
-struct rcondis_mp_delete_vc {
- u32 req_id;
- u32 dev_vc_handle;
-};
-
-/* Response to CoNdisMiniportDeleteVc */
-struct rcondis_mp_delete_vc_complete {
- u32 req_id;
- u32 status;
-};
-
-/* CoNdisMiniportQueryRequest message */
-struct rcondis_mp_query_request {
- u32 req_id;
- u32 request_type;
- u32 oid;
- u32 dev_vc_handle;
- u32 info_buflen;
- u32 info_buf_offset;
-};
-
-/* CoNdisMiniportSetRequest message */
-struct rcondis_mp_set_request {
- u32 req_id;
- u32 request_type;
- u32 oid;
- u32 dev_vc_handle;
- u32 info_buflen;
- u32 info_buf_offset;
-};
-
-/* CoNdisIndicateStatus message */
-struct rcondis_indicate_status {
- u32 ndis_vc_handle;
- u32 status;
- u32 status_buflen;
- u32 status_buf_offset;
-};
-
-/* CONDIS Call/VC parameters */
-struct rcondis_specific_parameters {
- u32 parameter_type;
- u32 parameter_length;
- u32 parameter_lffset;
-};
-
-struct rcondis_media_parameters {
- u32 flags;
- u32 reserved1;
- u32 reserved2;
- struct rcondis_specific_parameters media_specific;
-};
-
-struct rndis_flowspec {
- u32 token_rate;
- u32 token_bucket_size;
- u32 peak_bandwidth;
- u32 latency;
- u32 delay_variation;
- u32 service_type;
- u32 max_sdu_size;
- u32 minimum_policed_size;
-};
-
-struct rcondis_call_manager_parameters {
- struct rndis_flowspec transmit;
- struct rndis_flowspec receive;
- struct rcondis_specific_parameters call_mgr_specific;
-};
-
-/* CoNdisMiniportActivateVc message */
-struct rcondis_mp_activate_vc_request {
- u32 req_id;
- u32 flags;
- u32 dev_vc_handle;
- u32 media_params_offset;
- u32 media_params_length;
- u32 call_mgr_params_offset;
- u32 call_mgr_params_length;
-};
-
-/* Response to CoNdisMiniportActivateVc */
-struct rcondis_mp_activate_vc_complete {
- u32 req_id;
- u32 status;
-};
-
-/* CoNdisMiniportDeactivateVc message */
-struct rcondis_mp_deactivate_vc_request {
- u32 req_id;
- u32 flags;
- u32 dev_vc_handle;
-};
-
-/* Response to CoNdisMiniportDeactivateVc */
-struct rcondis_mp_deactivate_vc_complete {
- u32 req_id;
- u32 status;
-};
-
-
-/* union with all of the RNDIS messages */
-union rndis_message_container {
- struct rndis_packet pkt;
- struct rndis_initialize_request init_req;
- struct rndis_halt_request halt_req;
- struct rndis_query_request query_req;
- struct rndis_set_request set_req;
- struct rndis_reset_request reset_req;
- struct rndis_keepalive_request keep_alive_req;
- struct rndis_indicate_status indicate_status;
- struct rndis_initialize_complete init_complete;
- struct rndis_query_complete query_complete;
- struct rndis_set_complete set_complete;
- struct rndis_reset_complete reset_complete;
- struct rndis_keepalive_complete keep_alive_complete;
- struct rcondis_mp_create_vc co_miniport_create_vc;
- struct rcondis_mp_delete_vc co_miniport_delete_vc;
- struct rcondis_indicate_status co_indicate_status;
- struct rcondis_mp_activate_vc_request co_miniport_activate_vc;
- struct rcondis_mp_deactivate_vc_request co_miniport_deactivate_vc;
- struct rcondis_mp_create_vc_complete co_miniport_create_vc_complete;
- struct rcondis_mp_delete_vc_complete co_miniport_delete_vc_complete;
- struct rcondis_mp_activate_vc_complete co_miniport_activate_vc_complete;
- struct rcondis_mp_deactivate_vc_complete
- co_miniport_deactivate_vc_complete;
-};
-
-/* Remote NDIS message format */
-struct rndis_message {
- u32 ndis_msg_type;
-
- /* Total length of this message, from the beginning */
- /* of the sruct rndis_message, in bytes. */
- u32 msg_len;
-
- /* Actual message */
- union rndis_message_container msg;
-};
-
-
-struct rndis_filter_packet {
- void *completion_ctx;
- void (*completion)(void *context);
- struct rndis_message msg;
-};
-
-/* Handy macros */
-
-/* get the size of an RNDIS message. Pass in the message type, */
-/* struct rndis_set_request, struct rndis_packet for example */
-#define RNDIS_MESSAGE_SIZE(msg) \
- (sizeof(msg) + (sizeof(struct rndis_message) - \
- sizeof(union rndis_message_container)))
-
-/* get pointer to info buffer with message pointer */
-#define MESSAGE_TO_INFO_BUFFER(msg) \
- (((unsigned char *)(msg)) + msg->info_buf_offset)
-
-/* get pointer to status buffer with message pointer */
-#define MESSAGE_TO_STATUS_BUFFER(msg) \
- (((unsigned char *)(msg)) + msg->status_buf_offset)
-
-/* get pointer to OOBD buffer with message pointer */
-#define MESSAGE_TO_OOBD_BUFFER(msg) \
- (((unsigned char *)(msg)) + msg->oob_data_offset)
-
-/* get pointer to data buffer with message pointer */
-#define MESSAGE_TO_DATA_BUFFER(msg) \
- (((unsigned char *)(msg)) + msg->per_pkt_info_offset)
-
-/* get pointer to contained message from NDIS_MESSAGE pointer */
-#define RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(rndis_msg) \
- ((void *) &rndis_msg->msg)
-
-/* get pointer to contained message from NDIS_MESSAGE pointer */
-#define RNDIS_MESSAGE_RAW_PTR_TO_MESSAGE_PTR(rndis_msg) \
- ((void *) rndis_msg)
-
-
-#define __struct_bcount(x)
-
-
-
-#define RNDIS_HEADER_SIZE (sizeof(struct rndis_message) - \
- sizeof(union rndis_message_container))
-
-#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
-#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
-#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
-#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
-#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
-#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
-#define NDIS_PACKET_TYPE_SMT 0x00000040
-#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
-#define NDIS_PACKET_TYPE_GROUP 0x00000100
-#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200
-#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
-#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
-
-
-
-#endif /* _HYPERV_NET_H */
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
deleted file mode 100644
index b902579c7fe6..000000000000
--- a/drivers/staging/hv/netvsc.c
+++ /dev/null
@@ -1,944 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- * Haiyang Zhang <haiyangz@microsoft.com>
- * Hank Janssen <hjanssen@microsoft.com>
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-
-#include "hyperv_net.h"
-
-
-static struct netvsc_device *alloc_net_device(struct hv_device *device)
-{
- struct netvsc_device *net_device;
- struct net_device *ndev = hv_get_drvdata(device);
-
- net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL);
- if (!net_device)
- return NULL;
-
-
- net_device->destroy = false;
- net_device->dev = device;
- net_device->ndev = ndev;
-
- hv_set_drvdata(device, net_device);
- return net_device;
-}
-
-static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
-{
- struct netvsc_device *net_device;
-
- net_device = hv_get_drvdata(device);
- if (net_device && net_device->destroy)
- net_device = NULL;
-
- return net_device;
-}
-
-static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
-{
- struct netvsc_device *net_device;
-
- net_device = hv_get_drvdata(device);
-
- if (!net_device)
- goto get_in_err;
-
- if (net_device->destroy &&
- atomic_read(&net_device->num_outstanding_sends) == 0)
- net_device = NULL;
-
-get_in_err:
- return net_device;
-}
-
-
-static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
-{
- struct nvsp_message *revoke_packet;
- int ret = 0;
- struct net_device *ndev = net_device->ndev;
-
- /*
- * If we got a section count, it means we received a
- * SendReceiveBufferComplete msg (ie sent
- * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
- * to send a revoke msg here
- */
- if (net_device->recv_section_cnt) {
- /* Send the revoke receive buffer */
- revoke_packet = &net_device->revoke_packet;
- memset(revoke_packet, 0, sizeof(struct nvsp_message));
-
- revoke_packet->hdr.msg_type =
- NVSP_MSG1_TYPE_REVOKE_RECV_BUF;
- revoke_packet->msg.v1_msg.
- revoke_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;
-
- ret = vmbus_sendpacket(net_device->dev->channel,
- revoke_packet,
- sizeof(struct nvsp_message),
- (unsigned long)revoke_packet,
- VM_PKT_DATA_INBAND, 0);
- /*
- * If we failed here, we might as well return and
- * have a leak rather than continue and a bugchk
- */
- if (ret != 0) {
- netdev_err(ndev, "unable to send "
- "revoke receive buffer to netvsp\n");
- return ret;
- }
- }
-
- /* Teardown the gpadl on the vsp end */
- if (net_device->recv_buf_gpadl_handle) {
- ret = vmbus_teardown_gpadl(net_device->dev->channel,
- net_device->recv_buf_gpadl_handle);
-
- /* If we failed here, we might as well return and have a leak
- * rather than continue and a bugchk
- */
- if (ret != 0) {
- netdev_err(ndev,
- "unable to teardown receive buffer's gpadl\n");
- return ret;
- }
- net_device->recv_buf_gpadl_handle = 0;
- }
-
- if (net_device->recv_buf) {
- /* Free up the receive buffer */
- free_pages((unsigned long)net_device->recv_buf,
- get_order(net_device->recv_buf_size));
- net_device->recv_buf = NULL;
- }
-
- if (net_device->recv_section) {
- net_device->recv_section_cnt = 0;
- kfree(net_device->recv_section);
- net_device->recv_section = NULL;
- }
-
- return ret;
-}
-
-static int netvsc_init_recv_buf(struct hv_device *device)
-{
- int ret = 0;
- int t;
- struct netvsc_device *net_device;
- struct nvsp_message *init_packet;
- struct net_device *ndev;
-
- net_device = get_outbound_net_device(device);
- if (!net_device)
- return -ENODEV;
- ndev = net_device->ndev;
-
- net_device->recv_buf =
- (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
- get_order(net_device->recv_buf_size));
- if (!net_device->recv_buf) {
- netdev_err(ndev, "unable to allocate receive "
- "buffer of size %d\n", net_device->recv_buf_size);
- ret = -ENOMEM;
- goto cleanup;
- }
-
- /*
- * Establish the gpadl handle for this buffer on this
- * channel. Note: This call uses the vmbus connection rather
- * than the channel to establish the gpadl handle.
- */
- ret = vmbus_establish_gpadl(device->channel, net_device->recv_buf,
- net_device->recv_buf_size,
- &net_device->recv_buf_gpadl_handle);
- if (ret != 0) {
- netdev_err(ndev,
- "unable to establish receive buffer's gpadl\n");
- goto cleanup;
- }
-
-
- /* Notify the NetVsp of the gpadl handle */
- init_packet = &net_device->channel_init_pkt;
-
- memset(init_packet, 0, sizeof(struct nvsp_message));
-
- init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF;
- init_packet->msg.v1_msg.send_recv_buf.
- gpadl_handle = net_device->recv_buf_gpadl_handle;
- init_packet->msg.v1_msg.
- send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;
-
- /* Send the gpadl notification request */
- ret = vmbus_sendpacket(device->channel, init_packet,
- sizeof(struct nvsp_message),
- (unsigned long)init_packet,
- VM_PKT_DATA_INBAND,
- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
- if (ret != 0) {
- netdev_err(ndev,
- "unable to send receive buffer's gpadl to netvsp\n");
- goto cleanup;
- }
-
- t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
- BUG_ON(t == 0);
-
-
- /* Check the response */
- if (init_packet->msg.v1_msg.
- send_recv_buf_complete.status != NVSP_STAT_SUCCESS) {
- netdev_err(ndev, "Unable to complete receive buffer "
- "initialization with NetVsp - status %d\n",
- init_packet->msg.v1_msg.
- send_recv_buf_complete.status);
- ret = -EINVAL;
- goto cleanup;
- }
-
- /* Parse the response */
-
- net_device->recv_section_cnt = init_packet->msg.
- v1_msg.send_recv_buf_complete.num_sections;
-
- net_device->recv_section = kmalloc(net_device->recv_section_cnt
- * sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL);
- if (net_device->recv_section == NULL) {
- ret = -EINVAL;
- goto cleanup;
- }
-
- memcpy(net_device->recv_section,
- init_packet->msg.v1_msg.
- send_recv_buf_complete.sections,
- net_device->recv_section_cnt *
- sizeof(struct nvsp_1_receive_buffer_section));
-
- /*
- * For 1st release, there should only be 1 section that represents the
- * entire receive buffer
- */
- if (net_device->recv_section_cnt != 1 ||
- net_device->recv_section->offset != 0) {
- ret = -EINVAL;
- goto cleanup;
- }
-
- goto exit;
-
-cleanup:
- netvsc_destroy_recv_buf(net_device);
-
-exit:
- return ret;
-}
-
-
-static int netvsc_connect_vsp(struct hv_device *device)
-{
- int ret, t;
- struct netvsc_device *net_device;
- struct nvsp_message *init_packet;
- int ndis_version;
- struct net_device *ndev;
-
- net_device = get_outbound_net_device(device);
- if (!net_device)
- return -ENODEV;
- ndev = net_device->ndev;
-
- init_packet = &net_device->channel_init_pkt;
-
- memset(init_packet, 0, sizeof(struct nvsp_message));
- init_packet->hdr.msg_type = NVSP_MSG_TYPE_INIT;
- init_packet->msg.init_msg.init.min_protocol_ver =
- NVSP_MIN_PROTOCOL_VERSION;
- init_packet->msg.init_msg.init.max_protocol_ver =
- NVSP_MAX_PROTOCOL_VERSION;
-
- /* Send the init request */
- ret = vmbus_sendpacket(device->channel, init_packet,
- sizeof(struct nvsp_message),
- (unsigned long)init_packet,
- VM_PKT_DATA_INBAND,
- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
- if (ret != 0)
- goto cleanup;
-
- t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
-
- if (t == 0) {
- ret = -ETIMEDOUT;
- goto cleanup;
- }
-
- if (init_packet->msg.init_msg.init_complete.status !=
- NVSP_STAT_SUCCESS) {
- ret = -EINVAL;
- goto cleanup;
- }
-
- if (init_packet->msg.init_msg.init_complete.
- negotiated_protocol_ver != NVSP_PROTOCOL_VERSION_1) {
- ret = -EPROTO;
- goto cleanup;
- }
- /* Send the ndis version */
- memset(init_packet, 0, sizeof(struct nvsp_message));
-
- ndis_version = 0x00050000;
-
- init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER;
- init_packet->msg.v1_msg.
- send_ndis_ver.ndis_major_ver =
- (ndis_version & 0xFFFF0000) >> 16;
- init_packet->msg.v1_msg.
- send_ndis_ver.ndis_minor_ver =
- ndis_version & 0xFFFF;
-
- /* Send the init request */
- ret = vmbus_sendpacket(device->channel, init_packet,
- sizeof(struct nvsp_message),
- (unsigned long)init_packet,
- VM_PKT_DATA_INBAND, 0);
- if (ret != 0)
- goto cleanup;
-
- /* Post the big receive buffer to NetVSP */
- ret = netvsc_init_recv_buf(device);
-
-cleanup:
- return ret;
-}
-
-static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
-{
- netvsc_destroy_recv_buf(net_device);
-}
-
-/*
- * netvsc_device_remove - Callback when the root bus device is removed
- */
-int netvsc_device_remove(struct hv_device *device)
-{
- struct netvsc_device *net_device;
- struct hv_netvsc_packet *netvsc_packet, *pos;
- unsigned long flags;
-
- net_device = hv_get_drvdata(device);
- spin_lock_irqsave(&device->channel->inbound_lock, flags);
- net_device->destroy = true;
- spin_unlock_irqrestore(&device->channel->inbound_lock, flags);
-
- /* Wait for all send completions */
- while (atomic_read(&net_device->num_outstanding_sends)) {
- dev_info(&device->device,
- "waiting for %d requests to complete...\n",
- atomic_read(&net_device->num_outstanding_sends));
- udelay(100);
- }
-
- netvsc_disconnect_vsp(net_device);
-
- /*
- * Since we have already drained, we don't need to busy wait
- * as was done in final_release_stor_device()
- * Note that we cannot set the ext pointer to NULL until
- * we have drained - to drain the outgoing packets, we need to
- * allow incoming packets.
- */
-
- spin_lock_irqsave(&device->channel->inbound_lock, flags);
- hv_set_drvdata(device, NULL);
- spin_unlock_irqrestore(&device->channel->inbound_lock, flags);
-
- /*
- * At this point, no one should be accessing net_device
- * except in here
- */
- dev_notice(&device->device, "net device safe to remove\n");
-
- /* Now, we can close the channel safely */
- vmbus_close(device->channel);
-
- /* Release all resources */
- list_for_each_entry_safe(netvsc_packet, pos,
- &net_device->recv_pkt_list, list_ent) {
- list_del(&netvsc_packet->list_ent);
- kfree(netvsc_packet);
- }
-
- kfree(net_device);
- return 0;
-}
-
-static void netvsc_send_completion(struct hv_device *device,
- struct vmpacket_descriptor *packet)
-{
- struct netvsc_device *net_device;
- struct nvsp_message *nvsp_packet;
- struct hv_netvsc_packet *nvsc_packet;
- struct net_device *ndev;
-
- net_device = get_inbound_net_device(device);
- if (!net_device)
- return;
- ndev = net_device->ndev;
-
- nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
- (packet->offset8 << 3));
-
- if ((nvsp_packet->hdr.msg_type == NVSP_MSG_TYPE_INIT_COMPLETE) ||
- (nvsp_packet->hdr.msg_type ==
- NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE) ||
- (nvsp_packet->hdr.msg_type ==
- NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE)) {
- /* Copy the response back */
- memcpy(&net_device->channel_init_pkt, nvsp_packet,
- sizeof(struct nvsp_message));
- complete(&net_device->channel_init_wait);
- } else if (nvsp_packet->hdr.msg_type ==
- NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) {
- /* Get the send context */
- nvsc_packet = (struct hv_netvsc_packet *)(unsigned long)
- packet->trans_id;
-
- /* Notify the layer above us */
- nvsc_packet->completion.send.send_completion(
- nvsc_packet->completion.send.send_completion_ctx);
-
- atomic_dec(&net_device->num_outstanding_sends);
- } else {
- netdev_err(ndev, "Unknown send completion packet type- "
- "%d received!!\n", nvsp_packet->hdr.msg_type);
- }
-
-}
-
-int netvsc_send(struct hv_device *device,
- struct hv_netvsc_packet *packet)
-{
- struct netvsc_device *net_device;
- int ret = 0;
- struct nvsp_message sendMessage;
- struct net_device *ndev;
-
- net_device = get_outbound_net_device(device);
- if (!net_device)
- return -ENODEV;
- ndev = net_device->ndev;
-
- sendMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT;
- if (packet->is_data_pkt) {
- /* 0 is RMC_DATA; */
- sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 0;
- } else {
- /* 1 is RMC_CONTROL; */
- sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 1;
- }
-
- /* Not using send buffer section */
- sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_index =
- 0xFFFFFFFF;
- sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0;
-
- if (packet->page_buf_cnt) {
- ret = vmbus_sendpacket_pagebuffer(device->channel,
- packet->page_buf,
- packet->page_buf_cnt,
- &sendMessage,
- sizeof(struct nvsp_message),
- (unsigned long)packet);
- } else {
- ret = vmbus_sendpacket(device->channel, &sendMessage,
- sizeof(struct nvsp_message),
- (unsigned long)packet,
- VM_PKT_DATA_INBAND,
- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
- }
-
- if (ret != 0)
- netdev_err(ndev, "Unable to send packet %p ret %d\n",
- packet, ret);
- else
- atomic_inc(&net_device->num_outstanding_sends);
-
- return ret;
-}
-
-static void netvsc_send_recv_completion(struct hv_device *device,
- u64 transaction_id)
-{
- struct nvsp_message recvcompMessage;
- int retries = 0;
- int ret;
- struct net_device *ndev;
- struct netvsc_device *net_device = hv_get_drvdata(device);
-
- ndev = net_device->ndev;
-
- recvcompMessage.hdr.msg_type =
- NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
-
- /* FIXME: Pass in the status */
- recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status =
- NVSP_STAT_SUCCESS;
-
-retry_send_cmplt:
- /* Send the completion */
- ret = vmbus_sendpacket(device->channel, &recvcompMessage,
- sizeof(struct nvsp_message), transaction_id,
- VM_PKT_COMP, 0);
- if (ret == 0) {
- /* success */
- /* no-op */
- } else if (ret == -EAGAIN) {
- /* no more room...wait a bit and attempt to retry 3 times */
- retries++;
- netdev_err(ndev, "unable to send receive completion pkt"
- " (tid %llx)...retrying %d\n", transaction_id, retries);
-
- if (retries < 4) {
- udelay(100);
- goto retry_send_cmplt;
- } else {
- netdev_err(ndev, "unable to send receive "
- "completion pkt (tid %llx)...give up retrying\n",
- transaction_id);
- }
- } else {
- netdev_err(ndev, "unable to send receive "
- "completion pkt - %llx\n", transaction_id);
- }
-}
-
-/* Send a receive completion packet to RNDIS device (ie NetVsp) */
-static void netvsc_receive_completion(void *context)
-{
- struct hv_netvsc_packet *packet = context;
- struct hv_device *device = (struct hv_device *)packet->device;
- struct netvsc_device *net_device;
- u64 transaction_id = 0;
- bool fsend_receive_comp = false;
- unsigned long flags;
- struct net_device *ndev;
-
- /*
- * Even though it seems logical to do a GetOutboundNetDevice() here to
- * send out receive completion, we are using GetInboundNetDevice()
- * since we may have disable outbound traffic already.
- */
- net_device = get_inbound_net_device(device);
- if (!net_device)
- return;
- ndev = net_device->ndev;
-
- /* Overloading use of the lock. */
- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
-
- packet->xfer_page_pkt->count--;
-
- /*
- * Last one in the line that represent 1 xfer page packet.
- * Return the xfer page packet itself to the freelist
- */
- if (packet->xfer_page_pkt->count == 0) {
- fsend_receive_comp = true;
- transaction_id = packet->completion.recv.recv_completion_tid;
- list_add_tail(&packet->xfer_page_pkt->list_ent,
- &net_device->recv_pkt_list);
-
- }
-
- /* Put the packet back */
- list_add_tail(&packet->list_ent, &net_device->recv_pkt_list);
- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
-
- /* Send a receive completion for the xfer page packet */
- if (fsend_receive_comp)
- netvsc_send_recv_completion(device, transaction_id);
-
-}
-
-static void netvsc_receive(struct hv_device *device,
- struct vmpacket_descriptor *packet)
-{
- struct netvsc_device *net_device;
- struct vmtransfer_page_packet_header *vmxferpage_packet;
- struct nvsp_message *nvsp_packet;
- struct hv_netvsc_packet *netvsc_packet = NULL;
- unsigned long start;
- unsigned long end, end_virtual;
- /* struct netvsc_driver *netvscDriver; */
- struct xferpage_packet *xferpage_packet = NULL;
- int i, j;
- int count = 0, bytes_remain = 0;
- unsigned long flags;
- struct net_device *ndev;
-
- LIST_HEAD(listHead);
-
- net_device = get_inbound_net_device(device);
- if (!net_device)
- return;
- ndev = net_device->ndev;
-
- /*
- * All inbound packets other than send completion should be xfer page
- * packet
- */
- if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) {
- netdev_err(ndev, "Unknown packet type received - %d\n",
- packet->type);
- return;
- }
-
- nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
- (packet->offset8 << 3));
-
- /* Make sure this is a valid nvsp packet */
- if (nvsp_packet->hdr.msg_type !=
- NVSP_MSG1_TYPE_SEND_RNDIS_PKT) {
- netdev_err(ndev, "Unknown nvsp packet type received-"
- " %d\n", nvsp_packet->hdr.msg_type);
- return;
- }
-
- vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet;
-
- if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) {
- netdev_err(ndev, "Invalid xfer page set id - "
- "expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID,
- vmxferpage_packet->xfer_pageset_id);
- return;
- }
-
- /*
- * Grab free packets (range count + 1) to represent this xfer
- * page packet. +1 to represent the xfer page packet itself.
- * We grab it here so that we know exactly how many we can
- * fulfil
- */
- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
- while (!list_empty(&net_device->recv_pkt_list)) {
- list_move_tail(net_device->recv_pkt_list.next, &listHead);
- if (++count == vmxferpage_packet->range_cnt + 1)
- break;
- }
- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
-
- /*
- * We need at least 2 netvsc pkts (1 to represent the xfer
- * page and at least 1 for the range) i.e. we can handled
- * some of the xfer page packet ranges...
- */
- if (count < 2) {
- netdev_err(ndev, "Got only %d netvsc pkt...needed "
- "%d pkts. Dropping this xfer page packet completely!\n",
- count, vmxferpage_packet->range_cnt + 1);
-
- /* Return it to the freelist */
- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
- for (i = count; i != 0; i--) {
- list_move_tail(listHead.next,
- &net_device->recv_pkt_list);
- }
- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock,
- flags);
-
- netvsc_send_recv_completion(device,
- vmxferpage_packet->d.trans_id);
-
- return;
- }
-
- /* Remove the 1st packet to represent the xfer page packet itself */
- xferpage_packet = (struct xferpage_packet *)listHead.next;
- list_del(&xferpage_packet->list_ent);
-
- /* This is how much we can satisfy */
- xferpage_packet->count = count - 1;
-
- if (xferpage_packet->count != vmxferpage_packet->range_cnt) {
- netdev_err(ndev, "Needed %d netvsc pkts to satisfy "
- "this xfer page...got %d\n",
- vmxferpage_packet->range_cnt, xferpage_packet->count);
- }
-
- /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
- for (i = 0; i < (count - 1); i++) {
- netvsc_packet = (struct hv_netvsc_packet *)listHead.next;
- list_del(&netvsc_packet->list_ent);
-
- /* Initialize the netvsc packet */
- netvsc_packet->xfer_page_pkt = xferpage_packet;
- netvsc_packet->completion.recv.recv_completion =
- netvsc_receive_completion;
- netvsc_packet->completion.recv.recv_completion_ctx =
- netvsc_packet;
- netvsc_packet->device = device;
- /* Save this so that we can send it back */
- netvsc_packet->completion.recv.recv_completion_tid =
- vmxferpage_packet->d.trans_id;
-
- netvsc_packet->total_data_buflen =
- vmxferpage_packet->ranges[i].byte_count;
- netvsc_packet->page_buf_cnt = 1;
-
- netvsc_packet->page_buf[0].len =
- vmxferpage_packet->ranges[i].byte_count;
-
- start = virt_to_phys((void *)((unsigned long)net_device->
- recv_buf + vmxferpage_packet->ranges[i].byte_offset));
-
- netvsc_packet->page_buf[0].pfn = start >> PAGE_SHIFT;
- end_virtual = (unsigned long)net_device->recv_buf
- + vmxferpage_packet->ranges[i].byte_offset
- + vmxferpage_packet->ranges[i].byte_count - 1;
- end = virt_to_phys((void *)end_virtual);
-
- /* Calculate the page relative offset */
- netvsc_packet->page_buf[0].offset =
- vmxferpage_packet->ranges[i].byte_offset &
- (PAGE_SIZE - 1);
- if ((end >> PAGE_SHIFT) != (start >> PAGE_SHIFT)) {
- /* Handle frame across multiple pages: */
- netvsc_packet->page_buf[0].len =
- (netvsc_packet->page_buf[0].pfn <<
- PAGE_SHIFT)
- + PAGE_SIZE - start;
- bytes_remain = netvsc_packet->total_data_buflen -
- netvsc_packet->page_buf[0].len;
- for (j = 1; j < NETVSC_PACKET_MAXPAGE; j++) {
- netvsc_packet->page_buf[j].offset = 0;
- if (bytes_remain <= PAGE_SIZE) {
- netvsc_packet->page_buf[j].len =
- bytes_remain;
- bytes_remain = 0;
- } else {
- netvsc_packet->page_buf[j].len =
- PAGE_SIZE;
- bytes_remain -= PAGE_SIZE;
- }
- netvsc_packet->page_buf[j].pfn =
- virt_to_phys((void *)(end_virtual -
- bytes_remain)) >> PAGE_SHIFT;
- netvsc_packet->page_buf_cnt++;
- if (bytes_remain == 0)
- break;
- }
- }
-
- /* Pass it to the upper layer */
- rndis_filter_receive(device, netvsc_packet);
-
- netvsc_receive_completion(netvsc_packet->
- completion.recv.recv_completion_ctx);
- }
-
-}
-
-static void netvsc_channel_cb(void *context)
-{
- int ret;
- struct hv_device *device = context;
- struct netvsc_device *net_device;
- u32 bytes_recvd;
- u64 request_id;
- unsigned char *packet;
- struct vmpacket_descriptor *desc;
- unsigned char *buffer;
- int bufferlen = NETVSC_PACKET_SIZE;
- struct net_device *ndev;
-
- packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
- GFP_ATOMIC);
- if (!packet)
- return;
- buffer = packet;
-
- net_device = get_inbound_net_device(device);
- if (!net_device)
- goto out;
- ndev = net_device->ndev;
-
- do {
- ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen,
- &bytes_recvd, &request_id);
- if (ret == 0) {
- if (bytes_recvd > 0) {
- desc = (struct vmpacket_descriptor *)buffer;
- switch (desc->type) {
- case VM_PKT_COMP:
- netvsc_send_completion(device, desc);
- break;
-
- case VM_PKT_DATA_USING_XFER_PAGES:
- netvsc_receive(device, desc);
- break;
-
- default:
- netdev_err(ndev,
- "unhandled packet type %d, "
- "tid %llx len %d\n",
- desc->type, request_id,
- bytes_recvd);
- break;
- }
-
- /* reset */
- if (bufferlen > NETVSC_PACKET_SIZE) {
- kfree(buffer);
- buffer = packet;
- bufferlen = NETVSC_PACKET_SIZE;
- }
- } else {
- /* reset */
- if (bufferlen > NETVSC_PACKET_SIZE) {
- kfree(buffer);
- buffer = packet;
- bufferlen = NETVSC_PACKET_SIZE;
- }
-
- break;
- }
- } else if (ret == -ENOBUFS) {
- /* Handle large packet */
- buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
- if (buffer == NULL) {
- /* Try again next time around */
- netdev_err(ndev,
- "unable to allocate buffer of size "
- "(%d)!!\n", bytes_recvd);
- break;
- }
-
- bufferlen = bytes_recvd;
- }
- } while (1);
-
-out:
- kfree(buffer);
- return;
-}
-
-/*
- * netvsc_device_add - Callback when the device belonging to this
- * driver is added
- */
-int netvsc_device_add(struct hv_device *device, void *additional_info)
-{
- int ret = 0;
- int i;
- int ring_size =
- ((struct netvsc_device_info *)additional_info)->ring_size;
- struct netvsc_device *net_device;
- struct hv_netvsc_packet *packet, *pos;
- struct net_device *ndev;
-
- net_device = alloc_net_device(device);
- if (!net_device) {
- ret = -ENOMEM;
- goto cleanup;
- }
-
- /*
- * Coming into this function, struct net_device * is
- * registered as the driver private data.
- * In alloc_net_device(), we register struct netvsc_device *
- * as the driver private data and stash away struct net_device *
- * in struct netvsc_device *.
- */
- ndev = net_device->ndev;
-
- /* Initialize the NetVSC channel extension */
- net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
- spin_lock_init(&net_device->recv_pkt_list_lock);
-
- INIT_LIST_HEAD(&net_device->recv_pkt_list);
-
- for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
- packet = kzalloc(sizeof(struct hv_netvsc_packet) +
- (NETVSC_RECEIVE_SG_COUNT *
- sizeof(struct hv_page_buffer)), GFP_KERNEL);
- if (!packet)
- break;
-
- list_add_tail(&packet->list_ent,
- &net_device->recv_pkt_list);
- }
- init_completion(&net_device->channel_init_wait);
-
- /* Open the channel */
- ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
- ring_size * PAGE_SIZE, NULL, 0,
- netvsc_channel_cb, device);
-
- if (ret != 0) {
- netdev_err(ndev, "unable to open channel: %d\n", ret);
- goto cleanup;
- }
-
- /* Channel is opened */
- pr_info("hv_netvsc channel opened successfully\n");
-
- /* Connect with the NetVsp */
- ret = netvsc_connect_vsp(device);
- if (ret != 0) {
- netdev_err(ndev,
- "unable to connect to NetVSP - %d\n", ret);
- goto close;
- }
-
- return ret;
-
-close:
- /* Now, we can close the channel safely */
- vmbus_close(device->channel);
-
-cleanup:
-
- if (net_device) {
- list_for_each_entry_safe(packet, pos,
- &net_device->recv_pkt_list,
- list_ent) {
- list_del(&packet->list_ent);
- kfree(packet);
- }
-
- kfree(net_device);
- }
-
- return ret;
-}
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
deleted file mode 100644
index 93b0e91cbf98..000000000000
--- a/drivers/staging/hv/netvsc_drv.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- * Haiyang Zhang <haiyangz@microsoft.com>
- * Hank Janssen <hjanssen@microsoft.com>
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/atomic.h>
-#include <linux/module.h>
-#include <linux/highmem.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <net/arp.h>
-#include <net/route.h>
-#include <net/sock.h>
-#include <net/pkt_sched.h>
-
-#include "hyperv_net.h"
-
-struct net_device_context {
- /* point back to our device context */
- struct hv_device *device_ctx;
- atomic_t avail;
- struct delayed_work dwork;
-};
-
-
-#define PACKET_PAGES_LOWATER 8
-/* Need this many pages to handle worst case fragmented packet */
-#define PACKET_PAGES_HIWATER (MAX_SKB_FRAGS + 2)
-
-static int ring_size = 128;
-module_param(ring_size, int, S_IRUGO);
-MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
-
-/* no-op so the netdev core doesn't return -EINVAL when modifying the the
- * multicast address list in SIOCADDMULTI. hv is setup to get all multicast
- * when it calls RndisFilterOnOpen() */
-static void netvsc_set_multicast_list(struct net_device *net)
-{
-}
-
-static int netvsc_open(struct net_device *net)
-{
- struct net_device_context *net_device_ctx = netdev_priv(net);
- struct hv_device *device_obj = net_device_ctx->device_ctx;
- int ret = 0;
-
- /* Open up the device */
- ret = rndis_filter_open(device_obj);
- if (ret != 0) {
- netdev_err(net, "unable to open device (ret %d).\n", ret);
- return ret;
- }
-
- netif_start_queue(net);
-
- return ret;
-}
-
-static int netvsc_close(struct net_device *net)
-{
- struct net_device_context *net_device_ctx = netdev_priv(net);
- struct hv_device *device_obj = net_device_ctx->device_ctx;
- int ret;
-
- netif_stop_queue(net);
-
- ret = rndis_filter_close(device_obj);
- if (ret != 0)
- netdev_err(net, "unable to close device (ret %d).\n", ret);
-
- return ret;
-}
-
-static void netvsc_xmit_completion(void *context)
-{
- struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
- struct sk_buff *skb = (struct sk_buff *)
- (unsigned long)packet->completion.send.send_completion_tid;
-
- kfree(packet);
-
- if (skb) {
- struct net_device *net = skb->dev;
- struct net_device_context *net_device_ctx = netdev_priv(net);
- unsigned int num_pages = skb_shinfo(skb)->nr_frags + 2;
-
- dev_kfree_skb_any(skb);
-
- atomic_add(num_pages, &net_device_ctx->avail);
- if (atomic_read(&net_device_ctx->avail) >=
- PACKET_PAGES_HIWATER)
- netif_wake_queue(net);
- }
-}
-
-static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
-{
- struct net_device_context *net_device_ctx = netdev_priv(net);
- struct hv_netvsc_packet *packet;
- int ret;
- unsigned int i, num_pages;
-
- /* Add 1 for skb->data and additional one for RNDIS */
- num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
- if (num_pages > atomic_read(&net_device_ctx->avail))
- return NETDEV_TX_BUSY;
-
- /* Allocate a netvsc packet based on # of frags. */
- packet = kzalloc(sizeof(struct hv_netvsc_packet) +
- (num_pages * sizeof(struct hv_page_buffer)) +
- sizeof(struct rndis_filter_packet), GFP_ATOMIC);
- if (!packet) {
- /* out of memory, drop packet */
- netdev_err(net, "unable to allocate hv_netvsc_packet\n");
-
- dev_kfree_skb(skb);
- net->stats.tx_dropped++;
- return NETDEV_TX_BUSY;
- }
-
- packet->extension = (void *)(unsigned long)packet +
- sizeof(struct hv_netvsc_packet) +
- (num_pages * sizeof(struct hv_page_buffer));
-
- /* Setup the rndis header */
- packet->page_buf_cnt = num_pages;
-
- /* Initialize it from the skb */
- packet->total_data_buflen = skb->len;
-
- /* Start filling in the page buffers starting after RNDIS buffer. */
- packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
- packet->page_buf[1].offset
- = (unsigned long)skb->data & (PAGE_SIZE - 1);
- packet->page_buf[1].len = skb_headlen(skb);
-
- /* Additional fragments are after SKB data */
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- const skb_frag_t *f = &skb_shinfo(skb)->frags[i];
-
- packet->page_buf[i+2].pfn = page_to_pfn(skb_frag_page(f));
- packet->page_buf[i+2].offset = f->page_offset;
- packet->page_buf[i+2].len = skb_frag_size(f);
- }
-
- /* Set the completion routine */
- packet->completion.send.send_completion = netvsc_xmit_completion;
- packet->completion.send.send_completion_ctx = packet;
- packet->completion.send.send_completion_tid = (unsigned long)skb;
-
- ret = rndis_filter_send(net_device_ctx->device_ctx,
- packet);
- if (ret == 0) {
- net->stats.tx_bytes += skb->len;
- net->stats.tx_packets++;
-
- atomic_sub(num_pages, &net_device_ctx->avail);
- if (atomic_read(&net_device_ctx->avail) < PACKET_PAGES_LOWATER)
- netif_stop_queue(net);
- } else {
- /* we are shutting down or bus overloaded, just drop packet */
- net->stats.tx_dropped++;
- kfree(packet);
- dev_kfree_skb_any(skb);
- }
-
- return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK;
-}
-
-/*
- * netvsc_linkstatus_callback - Link up/down notification
- */
-void netvsc_linkstatus_callback(struct hv_device *device_obj,
- unsigned int status)
-{
- struct net_device *net;
- struct net_device_context *ndev_ctx;
- struct netvsc_device *net_device;
-
- net_device = hv_get_drvdata(device_obj);
- net = net_device->ndev;
-
- if (!net) {
- netdev_err(net, "got link status but net device "
- "not initialized yet\n");
- return;
- }
-
- if (status == 1) {
- netif_carrier_on(net);
- netif_wake_queue(net);
- ndev_ctx = netdev_priv(net);
- schedule_delayed_work(&ndev_ctx->dwork, 0);
- schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
- } else {
- netif_carrier_off(net);
- netif_stop_queue(net);
- }
-}
-
-/*
- * netvsc_recv_callback - Callback when we receive a packet from the
- * "wire" on the specified device.
- */
-int netvsc_recv_callback(struct hv_device *device_obj,
- struct hv_netvsc_packet *packet)
-{
- struct net_device *net = dev_get_drvdata(&device_obj->device);
- struct sk_buff *skb;
- void *data;
- int i;
- unsigned long flags;
- struct netvsc_device *net_device;
-
- net_device = hv_get_drvdata(device_obj);
- net = net_device->ndev;
-
- if (!net) {
- netdev_err(net, "got receive callback but net device"
- " not initialized yet\n");
- return 0;
- }
-
- /* Allocate a skb - TODO direct I/O to pages? */
- skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen);
- if (unlikely(!skb)) {
- ++net->stats.rx_dropped;
- return 0;
- }
-
- /* for kmap_atomic */
- local_irq_save(flags);
-
- /*
- * Copy to skb. This copy is needed here since the memory pointed by
- * hv_netvsc_packet cannot be deallocated
- */
- for (i = 0; i < packet->page_buf_cnt; i++) {
- data = kmap_atomic(pfn_to_page(packet->page_buf[i].pfn),
- KM_IRQ1);
- data = (void *)(unsigned long)data +
- packet->page_buf[i].offset;
-
- memcpy(skb_put(skb, packet->page_buf[i].len), data,
- packet->page_buf[i].len);
-
- kunmap_atomic((void *)((unsigned long)data -
- packet->page_buf[i].offset), KM_IRQ1);
- }
-
- local_irq_restore(flags);
-
- skb->protocol = eth_type_trans(skb, net);
- skb->ip_summed = CHECKSUM_NONE;
-
- net->stats.rx_packets++;
- net->stats.rx_bytes += skb->len;
-
- /*
- * Pass the skb back up. Network stack will deallocate the skb when it
- * is done.
- * TODO - use NAPI?
- */
- netif_rx(skb);
-
- return 0;
-}
-
-static void netvsc_get_drvinfo(struct net_device *net,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, "hv_netvsc");
- strcpy(info->version, HV_DRV_VERSION);
- strcpy(info->fw_version, "N/A");
-}
-
-static const struct ethtool_ops ethtool_ops = {
- .get_drvinfo = netvsc_get_drvinfo,
- .get_link = ethtool_op_get_link,
-};
-
-static const struct net_device_ops device_ops = {
- .ndo_open = netvsc_open,
- .ndo_stop = netvsc_close,
- .ndo_start_xmit = netvsc_start_xmit,
- .ndo_set_rx_mode = netvsc_set_multicast_list,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
-};
-
-/*
- * Send GARP packet to network peers after migrations.
- * After Quick Migration, the network is not immediately operational in the
- * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
- * another netif_notify_peers() into a delayed work, otherwise GARP packet
- * will not be sent after quick migration, and cause network disconnection.
- */
-static void netvsc_send_garp(struct work_struct *w)
-{
- struct net_device_context *ndev_ctx;
- struct net_device *net;
- struct netvsc_device *net_device;
-
- ndev_ctx = container_of(w, struct net_device_context, dwork.work);
- net_device = hv_get_drvdata(ndev_ctx->device_ctx);
- net = net_device->ndev;
- netif_notify_peers(net);
-}
-
-
-static int netvsc_probe(struct hv_device *dev,
- const struct hv_vmbus_device_id *dev_id)
-{
- struct net_device *net = NULL;
- struct net_device_context *net_device_ctx;
- struct netvsc_device_info device_info;
- int ret;
-
- net = alloc_etherdev(sizeof(struct net_device_context));
- if (!net)
- return -ENOMEM;
-
- /* Set initial state */
- netif_carrier_off(net);
-
- net_device_ctx = netdev_priv(net);
- net_device_ctx->device_ctx = dev;
- atomic_set(&net_device_ctx->avail, ring_size);
- hv_set_drvdata(dev, net);
- INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
-
- net->netdev_ops = &device_ops;
-
- /* TODO: Add GSO and Checksum offload */
- net->hw_features = NETIF_F_SG;
- net->features = NETIF_F_SG;
-
- SET_ETHTOOL_OPS(net, &ethtool_ops);
- SET_NETDEV_DEV(net, &dev->device);
-
- ret = register_netdev(net);
- if (ret != 0) {
- pr_err("Unable to register netdev.\n");
- free_netdev(net);
- goto out;
- }
-
- /* Notify the netvsc driver of the new device */
- device_info.ring_size = ring_size;
- ret = rndis_filter_device_add(dev, &device_info);
- if (ret != 0) {
- netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
- unregister_netdev(net);
- free_netdev(net);
- hv_set_drvdata(dev, NULL);
- return ret;
- }
- memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
-
- netif_carrier_on(net);
-
-out:
- return ret;
-}
-
-static int netvsc_remove(struct hv_device *dev)
-{
- struct net_device *net;
- struct net_device_context *ndev_ctx;
- struct netvsc_device *net_device;
-
- net_device = hv_get_drvdata(dev);
- net = net_device->ndev;
-
- if (net == NULL) {
- dev_err(&dev->device, "No net device to remove\n");
- return 0;
- }
-
- ndev_ctx = netdev_priv(net);
- cancel_delayed_work_sync(&ndev_ctx->dwork);
-
- /* Stop outbound asap */
- netif_stop_queue(net);
-
- unregister_netdev(net);
-
- /*
- * Call to the vsc driver to let it know that the device is being
- * removed
- */
- rndis_filter_device_remove(dev);
-
- free_netdev(net);
- return 0;
-}
-
-static const struct hv_vmbus_device_id id_table[] = {
- /* Network guid */
- { VMBUS_DEVICE(0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
- 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E) },
- { },
-};
-
-MODULE_DEVICE_TABLE(vmbus, id_table);
-
-/* The one and only one */
-static struct hv_driver netvsc_drv = {
- .name = "netvsc",
- .id_table = id_table,
- .probe = netvsc_probe,
- .remove = netvsc_remove,
-};
-
-static void __exit netvsc_drv_exit(void)
-{
- vmbus_driver_unregister(&netvsc_drv);
-}
-
-static int __init netvsc_drv_init(void)
-{
- return vmbus_driver_register(&netvsc_drv);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION(HV_DRV_VERSION);
-MODULE_DESCRIPTION("Microsoft Hyper-V network driver");
-
-module_init(netvsc_drv_init);
-module_exit(netvsc_drv_exit);
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c
deleted file mode 100644
index bafccb360041..000000000000
--- a/drivers/staging/hv/rndis_filter.c
+++ /dev/null
@@ -1,855 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- * Haiyang Zhang <haiyangz@microsoft.com>
- * Hank Janssen <hjanssen@microsoft.com>
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/highmem.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/if_ether.h>
-#include <linux/netdevice.h>
-
-#include "hyperv_net.h"
-
-
-enum rndis_device_state {
- RNDIS_DEV_UNINITIALIZED = 0,
- RNDIS_DEV_INITIALIZING,
- RNDIS_DEV_INITIALIZED,
- RNDIS_DEV_DATAINITIALIZED,
-};
-
-struct rndis_device {
- struct netvsc_device *net_dev;
-
- enum rndis_device_state state;
- bool link_state;
- atomic_t new_req_id;
-
- spinlock_t request_lock;
- struct list_head req_list;
-
- unsigned char hw_mac_adr[ETH_ALEN];
-};
-
-struct rndis_request {
- struct list_head list_ent;
- struct completion wait_event;
-
- /*
- * FIXME: We assumed a fixed size response here. If we do ever need to
- * handle a bigger response, we can either define a max response
- * message or add a response buffer variable above this field
- */
- struct rndis_message response_msg;
-
- /* Simplify allocation by having a netvsc packet inline */
- struct hv_netvsc_packet pkt;
- struct hv_page_buffer buf;
- /* FIXME: We assumed a fixed size request here. */
- struct rndis_message request_msg;
-};
-
-static void rndis_filter_send_completion(void *ctx);
-
-static void rndis_filter_send_request_completion(void *ctx);
-
-
-
-static struct rndis_device *get_rndis_device(void)
-{
- struct rndis_device *device;
-
- device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
- if (!device)
- return NULL;
-
- spin_lock_init(&device->request_lock);
-
- INIT_LIST_HEAD(&device->req_list);
-
- device->state = RNDIS_DEV_UNINITIALIZED;
-
- return device;
-}
-
-static struct rndis_request *get_rndis_request(struct rndis_device *dev,
- u32 msg_type,
- u32 msg_len)
-{
- struct rndis_request *request;
- struct rndis_message *rndis_msg;
- struct rndis_set_request *set;
- unsigned long flags;
-
- request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
- if (!request)
- return NULL;
-
- init_completion(&request->wait_event);
-
- rndis_msg = &request->request_msg;
- rndis_msg->ndis_msg_type = msg_type;
- rndis_msg->msg_len = msg_len;
-
- /*
- * Set the request id. This field is always after the rndis header for
- * request/response packet types so we just used the SetRequest as a
- * template
- */
- set = &rndis_msg->msg.set_req;
- set->req_id = atomic_inc_return(&dev->new_req_id);
-
- /* Add to the request list */
- spin_lock_irqsave(&dev->request_lock, flags);
- list_add_tail(&request->list_ent, &dev->req_list);
- spin_unlock_irqrestore(&dev->request_lock, flags);
-
- return request;
-}
-
-static void put_rndis_request(struct rndis_device *dev,
- struct rndis_request *req)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dev->request_lock, flags);
- list_del(&req->list_ent);
- spin_unlock_irqrestore(&dev->request_lock, flags);
-
- kfree(req);
-}
-
-static void dump_rndis_message(struct hv_device *hv_dev,
- struct rndis_message *rndis_msg)
-{
- struct net_device *netdev;
- struct netvsc_device *net_device;
-
- net_device = hv_get_drvdata(hv_dev);
- netdev = net_device->ndev;
-
- switch (rndis_msg->ndis_msg_type) {
- case REMOTE_NDIS_PACKET_MSG:
- netdev_dbg(netdev, "REMOTE_NDIS_PACKET_MSG (len %u, "
- "data offset %u data len %u, # oob %u, "
- "oob offset %u, oob len %u, pkt offset %u, "
- "pkt len %u\n",
- rndis_msg->msg_len,
- rndis_msg->msg.pkt.data_offset,
- rndis_msg->msg.pkt.data_len,
- rndis_msg->msg.pkt.num_oob_data_elements,
- rndis_msg->msg.pkt.oob_data_offset,
- rndis_msg->msg.pkt.oob_data_len,
- rndis_msg->msg.pkt.per_pkt_info_offset,
- rndis_msg->msg.pkt.per_pkt_info_len);
- break;
-
- case REMOTE_NDIS_INITIALIZE_CMPLT:
- netdev_dbg(netdev, "REMOTE_NDIS_INITIALIZE_CMPLT "
- "(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
- "device flags %d, max xfer size 0x%x, max pkts %u, "
- "pkt aligned %u)\n",
- rndis_msg->msg_len,
- rndis_msg->msg.init_complete.req_id,
- rndis_msg->msg.init_complete.status,
- rndis_msg->msg.init_complete.major_ver,
- rndis_msg->msg.init_complete.minor_ver,
- rndis_msg->msg.init_complete.dev_flags,
- rndis_msg->msg.init_complete.max_xfer_size,
- rndis_msg->msg.init_complete.
- max_pkt_per_msg,
- rndis_msg->msg.init_complete.
- pkt_alignment_factor);
- break;
-
- case REMOTE_NDIS_QUERY_CMPLT:
- netdev_dbg(netdev, "REMOTE_NDIS_QUERY_CMPLT "
- "(len %u, id 0x%x, status 0x%x, buf len %u, "
- "buf offset %u)\n",
- rndis_msg->msg_len,
- rndis_msg->msg.query_complete.req_id,
- rndis_msg->msg.query_complete.status,
- rndis_msg->msg.query_complete.
- info_buflen,
- rndis_msg->msg.query_complete.
- info_buf_offset);
- break;
-
- case REMOTE_NDIS_SET_CMPLT:
- netdev_dbg(netdev,
- "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)\n",
- rndis_msg->msg_len,
- rndis_msg->msg.set_complete.req_id,
- rndis_msg->msg.set_complete.status);
- break;
-
- case REMOTE_NDIS_INDICATE_STATUS_MSG:
- netdev_dbg(netdev, "REMOTE_NDIS_INDICATE_STATUS_MSG "
- "(len %u, status 0x%x, buf len %u, buf offset %u)\n",
- rndis_msg->msg_len,
- rndis_msg->msg.indicate_status.status,
- rndis_msg->msg.indicate_status.status_buflen,
- rndis_msg->msg.indicate_status.status_buf_offset);
- break;
-
- default:
- netdev_dbg(netdev, "0x%x (len %u)\n",
- rndis_msg->ndis_msg_type,
- rndis_msg->msg_len);
- break;
- }
-}
-
-static int rndis_filter_send_request(struct rndis_device *dev,
- struct rndis_request *req)
-{
- int ret;
- struct hv_netvsc_packet *packet;
-
- /* Setup the packet to send it */
- packet = &req->pkt;
-
- packet->is_data_pkt = false;
- packet->total_data_buflen = req->request_msg.msg_len;
- packet->page_buf_cnt = 1;
-
- packet->page_buf[0].pfn = virt_to_phys(&req->request_msg) >>
- PAGE_SHIFT;
- packet->page_buf[0].len = req->request_msg.msg_len;
- packet->page_buf[0].offset =
- (unsigned long)&req->request_msg & (PAGE_SIZE - 1);
-
- packet->completion.send.send_completion_ctx = req;/* packet; */
- packet->completion.send.send_completion =
- rndis_filter_send_request_completion;
- packet->completion.send.send_completion_tid = (unsigned long)dev;
-
- ret = netvsc_send(dev->net_dev->dev, packet);
- return ret;
-}
-
-static void rndis_filter_receive_response(struct rndis_device *dev,
- struct rndis_message *resp)
-{
- struct rndis_request *request = NULL;
- bool found = false;
- unsigned long flags;
- struct net_device *ndev;
-
- ndev = dev->net_dev->ndev;
-
- spin_lock_irqsave(&dev->request_lock, flags);
- list_for_each_entry(request, &dev->req_list, list_ent) {
- /*
- * All request/response message contains RequestId as the 1st
- * field
- */
- if (request->request_msg.msg.init_req.req_id
- == resp->msg.init_complete.req_id) {
- found = true;
- break;
- }
- }
- spin_unlock_irqrestore(&dev->request_lock, flags);
-
- if (found) {
- if (resp->msg_len <= sizeof(struct rndis_message)) {
- memcpy(&request->response_msg, resp,
- resp->msg_len);
- } else {
- netdev_err(ndev,
- "rndis response buffer overflow "
- "detected (size %u max %zu)\n",
- resp->msg_len,
- sizeof(struct rndis_filter_packet));
-
- if (resp->ndis_msg_type ==
- REMOTE_NDIS_RESET_CMPLT) {
- /* does not have a request id field */
- request->response_msg.msg.reset_complete.
- status = STATUS_BUFFER_OVERFLOW;
- } else {
- request->response_msg.msg.
- init_complete.status =
- STATUS_BUFFER_OVERFLOW;
- }
- }
-
- complete(&request->wait_event);
- } else {
- netdev_err(ndev,
- "no rndis request found for this response "
- "(id 0x%x res type 0x%x)\n",
- resp->msg.init_complete.req_id,
- resp->ndis_msg_type);
- }
-}
-
-static void rndis_filter_receive_indicate_status(struct rndis_device *dev,
- struct rndis_message *resp)
-{
- struct rndis_indicate_status *indicate =
- &resp->msg.indicate_status;
-
- if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) {
- netvsc_linkstatus_callback(
- dev->net_dev->dev, 1);
- } else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) {
- netvsc_linkstatus_callback(
- dev->net_dev->dev, 0);
- } else {
- /*
- * TODO:
- */
- }
-}
-
-static void rndis_filter_receive_data(struct rndis_device *dev,
- struct rndis_message *msg,
- struct hv_netvsc_packet *pkt)
-{
- struct rndis_packet *rndis_pkt;
- u32 data_offset;
- int i;
-
- rndis_pkt = &msg->msg.pkt;
-
- /*
- * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
- * netvsc packet (ie TotalDataBufferLength != MessageLength)
- */
-
- /* Remove the rndis header and pass it back up the stack */
- data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
-
- pkt->total_data_buflen -= data_offset;
- pkt->page_buf[0].offset += data_offset;
- pkt->page_buf[0].len -= data_offset;
-
- /* Drop the 0th page, if rndis data go beyond page boundary */
- if (pkt->page_buf[0].offset >= PAGE_SIZE) {
- pkt->page_buf[1].offset = pkt->page_buf[0].offset - PAGE_SIZE;
- pkt->page_buf[1].len -= pkt->page_buf[1].offset;
- pkt->page_buf_cnt--;
- for (i = 0; i < pkt->page_buf_cnt; i++)
- pkt->page_buf[i] = pkt->page_buf[i+1];
- }
-
- pkt->is_data_pkt = true;
-
- netvsc_recv_callback(dev->net_dev->dev, pkt);
-}
-
-int rndis_filter_receive(struct hv_device *dev,
- struct hv_netvsc_packet *pkt)
-{
- struct netvsc_device *net_dev = hv_get_drvdata(dev);
- struct rndis_device *rndis_dev;
- struct rndis_message rndis_msg;
- struct rndis_message *rndis_hdr;
- struct net_device *ndev;
-
- if (!net_dev)
- return -EINVAL;
-
- ndev = net_dev->ndev;
-
- /* Make sure the rndis device state is initialized */
- if (!net_dev->extension) {
- netdev_err(ndev, "got rndis message but no rndis device - "
- "dropping this message!\n");
- return -ENODEV;
- }
-
- rndis_dev = (struct rndis_device *)net_dev->extension;
- if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
- netdev_err(ndev, "got rndis message but rndis device "
- "uninitialized...dropping this message!\n");
- return -ENODEV;
- }
-
- rndis_hdr = (struct rndis_message *)kmap_atomic(
- pfn_to_page(pkt->page_buf[0].pfn), KM_IRQ0);
-
- rndis_hdr = (void *)((unsigned long)rndis_hdr +
- pkt->page_buf[0].offset);
-
- /* Make sure we got a valid rndis message */
- if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
- (rndis_hdr->msg_len > sizeof(struct rndis_message))) {
- netdev_err(ndev, "incoming rndis message buffer overflow "
- "detected (got %u, max %zu)..marking it an error!\n",
- rndis_hdr->msg_len,
- sizeof(struct rndis_message));
- }
-
- memcpy(&rndis_msg, rndis_hdr,
- (rndis_hdr->msg_len > sizeof(struct rndis_message)) ?
- sizeof(struct rndis_message) :
- rndis_hdr->msg_len);
-
- kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0);
-
- dump_rndis_message(dev, &rndis_msg);
-
- switch (rndis_msg.ndis_msg_type) {
- case REMOTE_NDIS_PACKET_MSG:
- /* data msg */
- rndis_filter_receive_data(rndis_dev, &rndis_msg, pkt);
- break;
-
- case REMOTE_NDIS_INITIALIZE_CMPLT:
- case REMOTE_NDIS_QUERY_CMPLT:
- case REMOTE_NDIS_SET_CMPLT:
- /* completion msgs */
- rndis_filter_receive_response(rndis_dev, &rndis_msg);
- break;
-
- case REMOTE_NDIS_INDICATE_STATUS_MSG:
- /* notification msgs */
- rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg);
- break;
- default:
- netdev_err(ndev,
- "unhandled rndis message (type %u len %u)\n",
- rndis_msg.ndis_msg_type,
- rndis_msg.msg_len);
- break;
- }
-
- return 0;
-}
-
-static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
- void *result, u32 *result_size)
-{
- struct rndis_request *request;
- u32 inresult_size = *result_size;
- struct rndis_query_request *query;
- struct rndis_query_complete *query_complete;
- int ret = 0;
- int t;
-
- if (!result)
- return -EINVAL;
-
- *result_size = 0;
- request = get_rndis_request(dev, REMOTE_NDIS_QUERY_MSG,
- RNDIS_MESSAGE_SIZE(struct rndis_query_request));
- if (!request) {
- ret = -ENOMEM;
- goto cleanup;
- }
-
- /* Setup the rndis query */
- query = &request->request_msg.msg.query_req;
- query->oid = oid;
- query->info_buf_offset = sizeof(struct rndis_query_request);
- query->info_buflen = 0;
- query->dev_vc_handle = 0;
-
- ret = rndis_filter_send_request(dev, request);
- if (ret != 0)
- goto cleanup;
-
- t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
- if (t == 0) {
- ret = -ETIMEDOUT;
- goto cleanup;
- }
-
- /* Copy the response back */
- query_complete = &request->response_msg.msg.query_complete;
-
- if (query_complete->info_buflen > inresult_size) {
- ret = -1;
- goto cleanup;
- }
-
- memcpy(result,
- (void *)((unsigned long)query_complete +
- query_complete->info_buf_offset),
- query_complete->info_buflen);
-
- *result_size = query_complete->info_buflen;
-
-cleanup:
- if (request)
- put_rndis_request(dev, request);
-
- return ret;
-}
-
-static int rndis_filter_query_device_mac(struct rndis_device *dev)
-{
- u32 size = ETH_ALEN;
-
- return rndis_filter_query_device(dev,
- RNDIS_OID_802_3_PERMANENT_ADDRESS,
- dev->hw_mac_adr, &size);
-}
-
-static int rndis_filter_query_device_link_status(struct rndis_device *dev)
-{
- u32 size = sizeof(u32);
- u32 link_status;
- int ret;
-
- ret = rndis_filter_query_device(dev,
- RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
- &link_status, &size);
- dev->link_state = (link_status != 0) ? true : false;
-
- return ret;
-}
-
-static int rndis_filter_set_packet_filter(struct rndis_device *dev,
- u32 new_filter)
-{
- struct rndis_request *request;
- struct rndis_set_request *set;
- struct rndis_set_complete *set_complete;
- u32 status;
- int ret, t;
- struct net_device *ndev;
-
- ndev = dev->net_dev->ndev;
-
- request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG,
- RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
- sizeof(u32));
- if (!request) {
- ret = -ENOMEM;
- goto cleanup;
- }
-
- /* Setup the rndis set */
- set = &request->request_msg.msg.set_req;
- set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
- set->info_buflen = sizeof(u32);
- set->info_buf_offset = sizeof(struct rndis_set_request);
-
- memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
- &new_filter, sizeof(u32));
-
- ret = rndis_filter_send_request(dev, request);
- if (ret != 0)
- goto cleanup;
-
- t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-
- if (t == 0) {
- netdev_err(ndev,
- "timeout before we got a set response...\n");
- /*
- * We can't deallocate the request since we may still receive a
- * send completion for it.
- */
- goto exit;
- } else {
- set_complete = &request->response_msg.msg.set_complete;
- status = set_complete->status;
- }
-
-cleanup:
- if (request)
- put_rndis_request(dev, request);
-exit:
- return ret;
-}
-
-
-static int rndis_filter_init_device(struct rndis_device *dev)
-{
- struct rndis_request *request;
- struct rndis_initialize_request *init;
- struct rndis_initialize_complete *init_complete;
- u32 status;
- int ret, t;
-
- request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG,
- RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
- if (!request) {
- ret = -ENOMEM;
- goto cleanup;
- }
-
- /* Setup the rndis set */
- init = &request->request_msg.msg.init_req;
- init->major_ver = RNDIS_MAJOR_VERSION;
- init->minor_ver = RNDIS_MINOR_VERSION;
- /* FIXME: Use 1536 - rounded ethernet frame size */
- init->max_xfer_size = 2048;
-
- dev->state = RNDIS_DEV_INITIALIZING;
-
- ret = rndis_filter_send_request(dev, request);
- if (ret != 0) {
- dev->state = RNDIS_DEV_UNINITIALIZED;
- goto cleanup;
- }
-
-
- t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
-
- if (t == 0) {
- ret = -ETIMEDOUT;
- goto cleanup;
- }
-
- init_complete = &request->response_msg.msg.init_complete;
- status = init_complete->status;
- if (status == RNDIS_STATUS_SUCCESS) {
- dev->state = RNDIS_DEV_INITIALIZED;
- ret = 0;
- } else {
- dev->state = RNDIS_DEV_UNINITIALIZED;
- ret = -EINVAL;
- }
-
-cleanup:
- if (request)
- put_rndis_request(dev, request);
-
- return ret;
-}
-
-static void rndis_filter_halt_device(struct rndis_device *dev)
-{
- struct rndis_request *request;
- struct rndis_halt_request *halt;
-
- /* Attempt to do a rndis device halt */
- request = get_rndis_request(dev, REMOTE_NDIS_HALT_MSG,
- RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
- if (!request)
- goto cleanup;
-
- /* Setup the rndis set */
- halt = &request->request_msg.msg.halt_req;
- halt->req_id = atomic_inc_return(&dev->new_req_id);
-
- /* Ignore return since this msg is optional. */
- rndis_filter_send_request(dev, request);
-
- dev->state = RNDIS_DEV_UNINITIALIZED;
-
-cleanup:
- if (request)
- put_rndis_request(dev, request);
- return;
-}
-
-static int rndis_filter_open_device(struct rndis_device *dev)
-{
- int ret;
-
- if (dev->state != RNDIS_DEV_INITIALIZED)
- return 0;
-
- ret = rndis_filter_set_packet_filter(dev,
- NDIS_PACKET_TYPE_BROADCAST |
- NDIS_PACKET_TYPE_ALL_MULTICAST |
- NDIS_PACKET_TYPE_DIRECTED);
- if (ret == 0)
- dev->state = RNDIS_DEV_DATAINITIALIZED;
-
- return ret;
-}
-
-static int rndis_filter_close_device(struct rndis_device *dev)
-{
- int ret;
-
- if (dev->state != RNDIS_DEV_DATAINITIALIZED)
- return 0;
-
- ret = rndis_filter_set_packet_filter(dev, 0);
- if (ret == 0)
- dev->state = RNDIS_DEV_INITIALIZED;
-
- return ret;
-}
-
-int rndis_filter_device_add(struct hv_device *dev,
- void *additional_info)
-{
- int ret;
- struct netvsc_device *net_device;
- struct rndis_device *rndis_device;
- struct netvsc_device_info *device_info = additional_info;
-
- rndis_device = get_rndis_device();
- if (!rndis_device)
- return -ENODEV;
-
- /*
- * Let the inner driver handle this first to create the netvsc channel
- * NOTE! Once the channel is created, we may get a receive callback
- * (RndisFilterOnReceive()) before this call is completed
- */
- ret = netvsc_device_add(dev, additional_info);
- if (ret != 0) {
- kfree(rndis_device);
- return ret;
- }
-
-
- /* Initialize the rndis device */
- net_device = hv_get_drvdata(dev);
-
- net_device->extension = rndis_device;
- rndis_device->net_dev = net_device;
-
- /* Send the rndis initialization message */
- ret = rndis_filter_init_device(rndis_device);
- if (ret != 0) {
- /*
- * TODO: If rndis init failed, we will need to shut down the
- * channel
- */
- }
-
- /* Get the mac address */
- ret = rndis_filter_query_device_mac(rndis_device);
- if (ret != 0) {
- /*
- * TODO: shutdown rndis device and the channel
- */
- }
-
- memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
-
- rndis_filter_query_device_link_status(rndis_device);
-
- device_info->link_state = rndis_device->link_state;
-
- dev_info(&dev->device, "Device MAC %pM link state %s\n",
- rndis_device->hw_mac_adr,
- device_info->link_state ? "down" : "up");
-
- return ret;
-}
-
-void rndis_filter_device_remove(struct hv_device *dev)
-{
- struct netvsc_device *net_dev = hv_get_drvdata(dev);
- struct rndis_device *rndis_dev = net_dev->extension;
-
- /* Halt and release the rndis device */
- rndis_filter_halt_device(rndis_dev);
-
- kfree(rndis_dev);
- net_dev->extension = NULL;
-
- netvsc_device_remove(dev);
-}
-
-
-int rndis_filter_open(struct hv_device *dev)
-{
- struct netvsc_device *net_device = hv_get_drvdata(dev);
-
- if (!net_device)
- return -EINVAL;
-
- return rndis_filter_open_device(net_device->extension);
-}
-
-int rndis_filter_close(struct hv_device *dev)
-{
- struct netvsc_device *netDevice = hv_get_drvdata(dev);
-
- if (!netDevice)
- return -EINVAL;
-
- return rndis_filter_close_device(netDevice->extension);
-}
-
-int rndis_filter_send(struct hv_device *dev,
- struct hv_netvsc_packet *pkt)
-{
- int ret;
- struct rndis_filter_packet *filterPacket;
- struct rndis_message *rndisMessage;
- struct rndis_packet *rndisPacket;
- u32 rndisMessageSize;
-
- /* Add the rndis header */
- filterPacket = (struct rndis_filter_packet *)pkt->extension;
-
- memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
-
- rndisMessage = &filterPacket->msg;
- rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
-
- rndisMessage->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
- rndisMessage->msg_len = pkt->total_data_buflen +
- rndisMessageSize;
-
- rndisPacket = &rndisMessage->msg.pkt;
- rndisPacket->data_offset = sizeof(struct rndis_packet);
- rndisPacket->data_len = pkt->total_data_buflen;
-
- pkt->is_data_pkt = true;
- pkt->page_buf[0].pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
- pkt->page_buf[0].offset =
- (unsigned long)rndisMessage & (PAGE_SIZE-1);
- pkt->page_buf[0].len = rndisMessageSize;
-
- /* Save the packet send completion and context */
- filterPacket->completion = pkt->completion.send.send_completion;
- filterPacket->completion_ctx =
- pkt->completion.send.send_completion_ctx;
-
- /* Use ours */
- pkt->completion.send.send_completion = rndis_filter_send_completion;
- pkt->completion.send.send_completion_ctx = filterPacket;
-
- ret = netvsc_send(dev, pkt);
- if (ret != 0) {
- /*
- * Reset the completion to originals to allow retries from
- * above
- */
- pkt->completion.send.send_completion =
- filterPacket->completion;
- pkt->completion.send.send_completion_ctx =
- filterPacket->completion_ctx;
- }
-
- return ret;
-}
-
-static void rndis_filter_send_completion(void *ctx)
-{
- struct rndis_filter_packet *filterPacket = ctx;
-
- /* Pass it back to the original handler */
- filterPacket->completion(filterPacket->completion_ctx);
-}
-
-
-static void rndis_filter_send_request_completion(void *ctx)
-{
- /* Noop */
-}
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index ae8c33e7849c..eb853f71089a 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/hyperv.h>
+#include <linux/mempool.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
@@ -42,6 +43,7 @@
#include <scsi/scsi_dbg.h>
+#define STORVSC_MIN_BUF_NR 64
#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE)
static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
@@ -78,7 +80,7 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
/* V1 Beta 0.1 */
/* V1 RC < 2008/1/31 1.0 */
/* V1 RC > 2008/1/31 2.0 */
-#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
+#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(4, 2)
@@ -104,7 +106,8 @@ enum vstor_packet_operation {
VSTOR_OPERATION_END_INITIALIZATION = 8,
VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9,
VSTOR_OPERATION_QUERY_PROPERTIES = 10,
- VSTOR_OPERATION_MAXIMUM = 10
+ VSTOR_OPERATION_ENUMERATE_BUS = 11,
+ VSTOR_OPERATION_MAXIMUM = 11
};
/*
@@ -234,8 +237,6 @@ struct vstor_packet {
#define STORVSC_MAX_CHANNELS 1
#define STORVSC_MAX_CMD_LEN 16
-struct hv_storvsc_request;
-
/* Matches Windows-end */
enum storvsc_request_type {
WRITE_TYPE,
@@ -284,9 +285,13 @@ struct storvsc_device {
struct hv_storvsc_request reset_request;
};
+struct stor_mem_pools {
+ struct kmem_cache *request_pool;
+ mempool_t *request_mempool;
+};
+
struct hv_host_device {
struct hv_device *dev;
- struct kmem_cache *request_pool;
unsigned int port;
unsigned char path;
unsigned char target;
@@ -302,6 +307,51 @@ struct storvsc_cmd_request {
struct hv_storvsc_request request;
};
+struct storvsc_scan_work {
+ struct work_struct work;
+ struct Scsi_Host *host;
+ uint lun;
+};
+
+static void storvsc_bus_scan(struct work_struct *work)
+{
+ struct storvsc_scan_work *wrk;
+ int id, order_id;
+
+ wrk = container_of(work, struct storvsc_scan_work, work);
+ for (id = 0; id < wrk->host->max_id; ++id) {
+ if (wrk->host->reverse_ordering)
+ order_id = wrk->host->max_id - id - 1;
+ else
+ order_id = id;
+
+ scsi_scan_target(&wrk->host->shost_gendev, 0,
+ order_id, SCAN_WILD_CARD, 1);
+ }
+ kfree(wrk);
+}
+
+static void storvsc_remove_lun(struct work_struct *work)
+{
+ struct storvsc_scan_work *wrk;
+ struct scsi_device *sdev;
+
+ wrk = container_of(work, struct storvsc_scan_work, work);
+ if (!scsi_host_get(wrk->host))
+ goto done;
+
+ sdev = scsi_device_lookup(wrk->host, 0, 0, wrk->lun);
+
+ if (sdev) {
+ scsi_remove_device(sdev);
+ scsi_device_put(sdev);
+ }
+ scsi_host_put(wrk->host);
+
+done:
+ kfree(wrk);
+}
+
static inline struct storvsc_device *get_out_stor_device(
struct hv_device *device)
{
@@ -549,11 +599,25 @@ static void storvsc_on_receive(struct hv_device *device,
struct vstor_packet *vstor_packet,
struct hv_storvsc_request *request)
{
+ struct storvsc_scan_work *work;
+ struct storvsc_device *stor_device;
+
switch (vstor_packet->operation) {
case VSTOR_OPERATION_COMPLETE_IO:
storvsc_on_io_completion(device, vstor_packet, request);
break;
+
case VSTOR_OPERATION_REMOVE_DEVICE:
+ case VSTOR_OPERATION_ENUMERATE_BUS:
+ stor_device = get_in_stor_device(device);
+ work = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC);
+ if (!work)
+ return;
+
+ INIT_WORK(&work->work, storvsc_bus_scan);
+ work->host = stor_device->host;
+ schedule_work(&work->work);
+ break;
default:
break;
@@ -729,19 +793,48 @@ static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
static int storvsc_device_alloc(struct scsi_device *sdevice)
{
- /*
- * This enables luns to be located sparsely. Otherwise, we may not
- * discovered them.
- */
- sdevice->sdev_bflags |= BLIST_SPARSELUN | BLIST_LARGELUN;
+ struct stor_mem_pools *memp;
+ int number = STORVSC_MIN_BUF_NR;
+
+ memp = kzalloc(sizeof(struct stor_mem_pools), GFP_KERNEL);
+ if (!memp)
+ return -ENOMEM;
+
+ memp->request_pool =
+ kmem_cache_create(dev_name(&sdevice->sdev_dev),
+ sizeof(struct storvsc_cmd_request), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+
+ if (!memp->request_pool)
+ goto err0;
+
+ memp->request_mempool = mempool_create(number, mempool_alloc_slab,
+ mempool_free_slab,
+ memp->request_pool);
+
+ if (!memp->request_mempool)
+ goto err1;
+
+ sdevice->hostdata = memp;
+
return 0;
+
+err1:
+ kmem_cache_destroy(memp->request_pool);
+
+err0:
+ kfree(memp);
+ return -ENOMEM;
}
-static int storvsc_merge_bvec(struct request_queue *q,
- struct bvec_merge_data *bmd, struct bio_vec *bvec)
+static void storvsc_device_destroy(struct scsi_device *sdevice)
{
- /* checking done by caller. */
- return bvec->bv_len;
+ struct stor_mem_pools *memp = sdevice->hostdata;
+
+ mempool_destroy(memp->request_mempool);
+ kmem_cache_destroy(memp->request_pool);
+ kfree(memp);
+ sdevice->hostdata = NULL;
}
static int storvsc_device_configure(struct scsi_device *sdevice)
@@ -751,8 +844,6 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
- blk_queue_merge_bvec(sdevice->request_queue, storvsc_merge_bvec);
-
blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY);
return 0;
@@ -802,12 +893,14 @@ static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
unsigned int sg_count,
- unsigned int len)
+ unsigned int len,
+ int write)
{
int i;
int num_pages;
struct scatterlist *bounce_sgl;
struct page *page_buf;
+ unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE);
num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT;
@@ -819,7 +912,7 @@ static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
page_buf = alloc_page(GFP_ATOMIC);
if (!page_buf)
goto cleanup;
- sg_set_page(&bounce_sgl[i], page_buf, 0, 0);
+ sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0);
}
return bounce_sgl;
@@ -833,7 +926,8 @@ cleanup:
/* Assume the original sgl has enough room */
static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
struct scatterlist *bounce_sgl,
- unsigned int orig_sgl_count)
+ unsigned int orig_sgl_count,
+ unsigned int bounce_sgl_count)
{
int i;
int j = 0;
@@ -874,6 +968,24 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
kunmap_atomic((void *)bounce_addr, KM_IRQ0);
j++;
+ /*
+ * It is possible that the number of elements
+ * in the bounce buffer may not be equal to
+ * the number of elements in the original
+ * scatter list. Handle this correctly.
+ */
+
+ if (j == bounce_sgl_count) {
+ /*
+ * We are done; cleanup and return.
+ */
+ kunmap_atomic((void *)(dest_addr -
+ orig_sgl[i].offset),
+ KM_IRQ0);
+ local_irq_restore(flags);
+ return total_copied;
+ }
+
/* if we need to use another bounce buffer */
if (destlen || i != orig_sgl_count - 1)
bounce_addr =
@@ -965,18 +1077,13 @@ static int storvsc_remove(struct hv_device *dev)
{
struct storvsc_device *stor_device = hv_get_drvdata(dev);
struct Scsi_Host *host = stor_device->host;
- struct hv_host_device *host_dev =
- (struct hv_host_device *)host->hostdata;
scsi_remove_host(host);
scsi_host_put(host);
storvsc_dev_remove(dev);
- if (host_dev->request_pool) {
- kmem_cache_destroy(host_dev->request_pool);
- host_dev->request_pool = NULL;
- }
+
return 0;
}
@@ -1014,7 +1121,7 @@ static int storvsc_host_reset(struct hv_device *device)
stor_device = get_out_stor_device(device);
if (!stor_device)
- return -ENODEV;
+ return FAILED;
request = &stor_device->reset_request;
vstor_packet = &request->vstor_packet;
@@ -1031,13 +1138,11 @@ static int storvsc_host_reset(struct hv_device *device)
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
if (ret != 0)
- goto cleanup;
+ return FAILED;
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
- if (t == 0) {
- ret = -ETIMEDOUT;
- goto cleanup;
- }
+ if (t == 0)
+ return TIMEOUT_ERROR;
/*
@@ -1045,8 +1150,7 @@ static int storvsc_host_reset(struct hv_device *device)
* should have been flushed out and return to us
*/
-cleanup:
- return ret;
+ return SUCCESS;
}
@@ -1055,16 +1159,10 @@ cleanup:
*/
static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
{
- int ret;
- struct hv_host_device *host_dev =
- (struct hv_host_device *)scmnd->device->host->hostdata;
+ struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
struct hv_device *dev = host_dev->dev;
- ret = storvsc_host_reset(dev);
- if (ret != 0)
- return ret;
-
- return ret;
+ return storvsc_host_reset(dev);
}
@@ -1076,21 +1174,22 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
struct storvsc_cmd_request *cmd_request =
(struct storvsc_cmd_request *)request->context;
struct scsi_cmnd *scmnd = cmd_request->cmd;
- struct hv_host_device *host_dev =
- (struct hv_host_device *)scmnd->device->host->hostdata;
+ struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
void (*scsi_done_fn)(struct scsi_cmnd *);
struct scsi_sense_hdr sense_hdr;
struct vmscsi_request *vm_srb;
+ struct storvsc_scan_work *wrk;
+ struct stor_mem_pools *memp = scmnd->device->hostdata;
vm_srb = &request->vstor_packet.vm_srb;
if (cmd_request->bounce_sgl_count) {
- if (vm_srb->data_in == READ_TYPE) {
+ if (vm_srb->data_in == READ_TYPE)
copy_from_bounce_buffer(scsi_sglist(scmnd),
cmd_request->bounce_sgl,
- scsi_sg_count(scmnd));
- destroy_bounce_buffer(cmd_request->bounce_sgl,
+ scsi_sg_count(scmnd),
+ cmd_request->bounce_sgl_count);
+ destroy_bounce_buffer(cmd_request->bounce_sgl,
cmd_request->bounce_sgl_count);
- }
}
/*
@@ -1103,6 +1202,29 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
else
scmnd->result = vm_srb->scsi_status;
+ /*
+ * If the LUN is invalid; remove the device.
+ */
+ if (vm_srb->srb_status == 0x20) {
+ struct storvsc_device *stor_dev;
+ struct hv_device *dev = host_dev->dev;
+ struct Scsi_Host *host;
+
+ stor_dev = get_in_stor_device(dev);
+ host = stor_dev->host;
+
+ wrk = kmalloc(sizeof(struct storvsc_scan_work),
+ GFP_ATOMIC);
+ if (!wrk) {
+ scmnd->result = DID_TARGET_FAILURE << 16;
+ } else {
+ wrk->host = host;
+ wrk->lun = vm_srb->lun;
+ INIT_WORK(&wrk->work, storvsc_remove_lun);
+ schedule_work(&wrk->work);
+ }
+ }
+
if (scmnd->result) {
if (scsi_normalize_sense(scmnd->sense_buffer,
SCSI_SENSE_BUFFERSIZE, &sense_hdr))
@@ -1120,7 +1242,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
scsi_done_fn(scmnd);
- kmem_cache_free(host_dev->request_pool, cmd_request);
+ mempool_free(cmd_request, memp->request_mempool);
}
static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)
@@ -1131,7 +1253,7 @@ static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)
switch (scsi_op) {
/* smartd sends this command, which will offline the device */
case SET_WINDOW:
- scmnd->result = DID_ERROR << 16;
+ scmnd->result = ILLEGAL_REQUEST << 16;
allowed = false;
break;
default:
@@ -1143,12 +1265,10 @@ static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)
/*
* storvsc_queuecommand - Initiate command processing
*/
-static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
- void (*done)(struct scsi_cmnd *))
+static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
{
int ret;
- struct hv_host_device *host_dev =
- (struct hv_host_device *)scmnd->device->host->hostdata;
+ struct hv_host_device *host_dev = shost_priv(host);
struct hv_device *dev = host_dev->dev;
struct hv_storvsc_request *request;
struct storvsc_cmd_request *cmd_request;
@@ -1157,9 +1277,10 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
struct scatterlist *sgl;
unsigned int sg_count = 0;
struct vmscsi_request *vm_srb;
+ struct stor_mem_pools *memp = scmnd->device->hostdata;
if (storvsc_check_scsi_cmd(scmnd) == false) {
- done(scmnd);
+ scmnd->scsi_done(scmnd);
return 0;
}
@@ -1172,16 +1293,14 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
goto retry_request;
}
- scmnd->scsi_done = done;
-
request_size = sizeof(struct storvsc_cmd_request);
- cmd_request = kmem_cache_zalloc(host_dev->request_pool,
+ cmd_request = mempool_alloc(memp->request_mempool,
GFP_ATOMIC);
- if (!cmd_request) {
- scmnd->scsi_done = NULL;
+ if (!cmd_request)
return SCSI_MLQUEUE_DEVICE_BUSY;
- }
+
+ memset(cmd_request, 0, sizeof(struct storvsc_cmd_request));
/* Setup the cmd request */
cmd_request->bounce_sgl_count = 0;
@@ -1231,12 +1350,12 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
cmd_request->bounce_sgl =
create_bounce_buffer(sgl, scsi_sg_count(scmnd),
- scsi_bufflen(scmnd));
+ scsi_bufflen(scmnd),
+ vm_srb->data_in);
if (!cmd_request->bounce_sgl) {
- scmnd->scsi_done = NULL;
scmnd->host_scribble = NULL;
- kmem_cache_free(host_dev->request_pool,
- cmd_request);
+ mempool_free(cmd_request,
+ memp->request_mempool);
return SCSI_MLQUEUE_HOST_BUSY;
}
@@ -1278,9 +1397,8 @@ retry_request:
destroy_bounce_buffer(cmd_request->bounce_sgl,
cmd_request->bounce_sgl_count);
- kmem_cache_free(host_dev->request_pool, cmd_request);
+ mempool_free(cmd_request, memp->request_mempool);
- scmnd->scsi_done = NULL;
scmnd->host_scribble = NULL;
ret = SCSI_MLQUEUE_DEVICE_BUSY;
@@ -1289,9 +1407,6 @@ retry_request:
return ret;
}
-static DEF_SCSI_QCMD(storvsc_queuecommand)
-
-
/* Scsi driver */
static struct scsi_host_template scsi_driver = {
.module = THIS_MODULE,
@@ -1300,6 +1415,7 @@ static struct scsi_host_template scsi_driver = {
.queuecommand = storvsc_queuecommand,
.eh_host_reset_handler = storvsc_host_reset_handler,
.slave_alloc = storvsc_device_alloc,
+ .slave_destroy = storvsc_device_destroy,
.slave_configure = storvsc_device_configure,
.cmd_per_lun = 1,
/* 64 max_queue * 1 target */
@@ -1308,14 +1424,7 @@ static struct scsi_host_template scsi_driver = {
/* no use setting to 0 since ll_blk_rw reset it to 1 */
/* currently 32 */
.sg_tablesize = MAX_MULTIPAGE_BUFFER_COUNT,
- /*
- * ENABLE_CLUSTERING allows mutiple physically contig bio_vecs to merge
- * into 1 sg element. If set, we must limit the max_segment_size to
- * PAGE_SIZE, otherwise we may get 1 sg element that represents
- * multiple
- */
- /* physically contig pfns (ie sg[x].length > PAGE_SIZE). */
- .use_clustering = ENABLE_CLUSTERING,
+ .use_clustering = DISABLE_CLUSTERING,
/* Make sure we dont get a sg segment crosses a page boundary */
.dma_boundary = PAGE_SIZE-1,
};
@@ -1360,27 +1469,17 @@ static int storvsc_probe(struct hv_device *device,
if (!host)
return -ENOMEM;
- host_dev = (struct hv_host_device *)host->hostdata;
+ host_dev = shost_priv(host);
memset(host_dev, 0, sizeof(struct hv_host_device));
host_dev->port = host->host_no;
host_dev->dev = device;
- host_dev->request_pool =
- kmem_cache_create(dev_name(&device->device),
- sizeof(struct storvsc_cmd_request), 0,
- SLAB_HWCACHE_ALIGN, NULL);
-
- if (!host_dev->request_pool) {
- scsi_host_put(host);
- return -ENOMEM;
- }
stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
if (!stor_device) {
- kmem_cache_destroy(host_dev->request_pool);
- scsi_host_put(host);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_out0;
}
stor_device->destroy = false;
@@ -1391,12 +1490,8 @@ static int storvsc_probe(struct hv_device *device,
stor_device->port_number = host->host_no;
ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size);
- if (ret) {
- kmem_cache_destroy(host_dev->request_pool);
- scsi_host_put(host);
- kfree(stor_device);
- return ret;
- }
+ if (ret)
+ goto err_out1;
if (dev_is_ide)
storvsc_get_ide_info(device, &target, &path);
@@ -1416,7 +1511,7 @@ static int storvsc_probe(struct hv_device *device,
/* Register the HBA and start the scsi bus scan */
ret = scsi_add_host(host, &device->device);
if (ret != 0)
- goto err_out;
+ goto err_out2;
if (!dev_is_ide) {
scsi_scan_host(host);
@@ -1425,21 +1520,32 @@ static int storvsc_probe(struct hv_device *device,
ret = scsi_add_device(host, 0, target, 0);
if (ret) {
scsi_remove_host(host);
- goto err_out;
+ goto err_out2;
}
return 0;
-err_out:
+err_out2:
+ /*
+ * Once we have connected with the host, we would need to
+ * to invoke storvsc_dev_remove() to rollback this state and
+ * this call also frees up the stor_device; hence the jump around
+ * err_out1 label.
+ */
storvsc_dev_remove(device);
- kmem_cache_destroy(host_dev->request_pool);
+ goto err_out0;
+
+err_out1:
+ kfree(stor_device);
+
+err_out0:
scsi_host_put(host);
- return -ENODEV;
+ return ret;
}
/* The one and only one */
static struct hv_driver storvsc_drv = {
- .name = "storvsc",
+ .name = KBUILD_MODNAME,
.id_table = id_table,
.probe = storvsc_probe,
.remove = storvsc_remove,
diff --git a/drivers/staging/iio/Documentation/generic_buffer.c b/drivers/staging/iio/Documentation/generic_buffer.c
index d58095321491..69a05b9456d6 100644
--- a/drivers/staging/iio/Documentation/generic_buffer.c
+++ b/drivers/staging/iio/Documentation/generic_buffer.c
@@ -28,6 +28,7 @@
#include <linux/types.h>
#include <string.h>
#include <poll.h>
+#include <endian.h>
#include "iio_utils.h"
/**
@@ -56,6 +57,13 @@ int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
void print2byte(int input, struct iio_channel_info *info)
{
+ /* First swap if incorrect endian */
+
+ if (info->be)
+ input = be16toh((uint_16t)input);
+ else
+ input = le16toh((uint_16t)input);
+
/* shift before conversion to avoid sign extension
of left aligned data */
input = input >> info->shift;
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index 75938b2412ff..6f3a392297ec 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -13,6 +13,7 @@
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
+#include <dirent.h>
#define IIO_MAX_NAME_LENGTH 30
@@ -73,6 +74,7 @@ struct iio_channel_info {
unsigned bits_used;
unsigned shift;
uint64_t mask;
+ unsigned be;
unsigned is_signed;
unsigned enabled;
unsigned location;
@@ -83,6 +85,7 @@ struct iio_channel_info {
* @is_signed: output whether channel is signed
* @bytes: output how many bytes the channel storage occupies
* @mask: output a bit mask for the raw data
+ * @be: big endian
* @device_dir: the iio device directory
* @name: the channel name
* @generic_name: the channel type name
@@ -92,6 +95,7 @@ inline int iioutils_get_type(unsigned *is_signed,
unsigned *bits_used,
unsigned *shift,
uint64_t *mask,
+ unsigned *be,
const char *device_dir,
const char *name,
const char *generic_name)
@@ -100,7 +104,7 @@ inline int iioutils_get_type(unsigned *is_signed,
int ret;
DIR *dp;
char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
- char signchar;
+ char signchar, endianchar;
unsigned padint;
const struct dirent *ent;
@@ -144,9 +148,18 @@ inline int iioutils_get_type(unsigned *is_signed,
ret = -errno;
goto error_free_filename;
}
- fscanf(sysfsfp,
- "%c%u/%u>>%u", &signchar, bits_used,
- &padint, shift);
+
+ ret = fscanf(sysfsfp,
+ "%ce:%c%u/%u>>%u",
+ &endianchar,
+ &signchar,
+ bits_used,
+ &padint, shift);
+ if (ret < 0) {
+ printf("failed to pass scan type description\n");
+ return ret;
+ }
+ *be = (endianchar == 'b');
*bytes = padint / 8;
if (*bits_used == 64)
*mask = ~0;
@@ -156,6 +169,10 @@ inline int iioutils_get_type(unsigned *is_signed,
*is_signed = 1;
else
*is_signed = 0;
+ fclose(sysfsfp);
+ free(filename);
+
+ filename = 0;
}
error_free_filename:
if (filename)
@@ -386,6 +403,7 @@ inline int build_channel_array(const char *device_dir,
&current->bits_used,
&current->shift,
&current->mask,
+ &current->be,
device_dir,
current->name,
current->generic_name);
diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt
index 7e99ef2b7bc0..e33807761cd7 100644
--- a/drivers/staging/iio/Documentation/ring.txt
+++ b/drivers/staging/iio/Documentation/ring.txt
@@ -23,10 +23,6 @@ The function pointers within here are used to allow the core to handle
as much buffer functionality as possible. Note almost all of these
are optional.
-mark_in_use, unmark_in_use
- Basically indicate that not changes should be made to the buffer state that
- will effect the form of the data being captures (e.g. scan elements or length)
-
store_to
If possible, push data to the buffer.
@@ -39,8 +35,6 @@ rip_first_n
The primary buffer reading function. Note that it may well not return
as much data as requested.
-mark_param_changed
- Used to indicate that something has changed. Used in conjunction with
request_update
If parameters have changed that require reinitialization or configuration of
the buffer this will trigger it.
@@ -51,7 +45,3 @@ get_bytes_per_datum, set_bytes_per_datum
get_length / set_length
Get/set the number of complete scans that may be held by the buffer.
-is_enabled
- Query if ring buffer is in use
-enable
- Start the ring buffer.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio b/drivers/staging/iio/Documentation/sysfs-bus-iio
index 0d6823d19b61..46a995d6d261 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio
@@ -276,6 +276,16 @@ Description:
If a discrete set of scale values are available, they
are listed in this attribute.
+What: /sys/.../in_accel_filter_low_pass_3db_frequency
+What: /sys/.../in_magn_filter_low_pass_3db_frequency
+What: /sys/.../in_anglvel_filter_low_pass_3db_frequency
+KernelVersion: 3.2
+Contact: linux-iio@vger.kernel.org
+Description:
+ If a known or controllable low pass filter is applied
+ to the underlying data channel, then this parameter
+ gives the 3dB frequency of the filter in Hz.
+
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index 4ec9118955f9..90162aa8b2df 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -76,7 +76,6 @@ config IIO_DUMMY_EVGEN
config IIO_SIMPLE_DUMMY
tristate "An example driver with no hardware requirements"
- select IIO_SIMPLE_DUMMY_EVGEN if IIO_SIMPLE_DUMMY_EVENTS
help
Driver intended mainly as documentation for how to write
a driver. May also be useful for testing userspace code
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index 97f747eac647..d439e45d07fa 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -17,7 +17,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "adis16201.h"
@@ -322,8 +322,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
*val = 0;
@@ -348,10 +347,10 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
break;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
*val = 25;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ACCEL:
bits = 12;
@@ -388,7 +387,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
s16 val16;
u8 addr;
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ACCEL:
bits = 12;
@@ -408,36 +407,36 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
static struct iio_chan_spec adis16201_channels[] = {
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
in_supply, ADIS16201_SCAN_SUPPLY,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
temp, ADIS16201_SCAN_TEMP,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
accel_x, ADIS16201_SCAN_ACC_X,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
accel_y, ADIS16201_SCAN_ACC_Y,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
in_aux, ADIS16201_SCAN_AUX_ADC,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
incli_x, ADIS16201_SCAN_INCLI_X,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
incli_y, ADIS16201_SCAN_INCLI_Y,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN_SOFT_TIMESTAMP(7)
@@ -554,3 +553,4 @@ module_spi_driver(adis16201_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16201 Programmable Digital Vibration Sensor driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:adis16201");
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c
index 0016ed378e3a..26c610faee3f 100644
--- a/drivers/staging/iio/accel/adis16201_ring.c
+++ b/drivers/staging/iio/accel/adis16201_ring.c
@@ -74,11 +74,11 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p)
return -ENOMEM;
}
- if (ring->scan_count)
- if (adis16201_read_ring_data(indio_dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
- data[i] = be16_to_cpup(
- (__be16 *)&(st->rx[i*2]));
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)
+ && adis16201_read_ring_data(indio_dev, st->rx) >= 0)
+ for (; i < bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength); i++)
+ data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
@@ -116,11 +116,9 @@ int adis16201_configure_ring(struct iio_dev *indio_dev)
}
indio_dev->buffer = ring;
/* Effectively select the ring buffer implementation */
- ring->bpe = 2;
ring->scan_timestamp = true;
ring->access = &ring_sw_access_funcs;
- ring->setup_ops = &adis16201_ring_setup_ops;
- ring->owner = THIS_MODULE;
+ indio_dev->setup_ops = &adis16201_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16201_trigger_handler,
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index a6d6d27f3c97..1a5140f9e3f4 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -17,7 +17,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "adis16203.h"
@@ -329,8 +329,7 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
*val = 0;
@@ -350,10 +349,10 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
*val = 25;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
bits = 14;
mutex_lock(&indio_dev->mlock);
addr = adis16203_addresses[chan->address][1];
@@ -374,26 +373,26 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
static struct iio_chan_spec adis16203_channels[] = {
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
in_supply, ADIS16203_SCAN_SUPPLY,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
in_aux, ADIS16203_SCAN_AUX_ADC,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
incli_x, ADIS16203_SCAN_INCLI_X,
IIO_ST('s', 14, 16, 0), 0),
/* Fixme: Not what it appears to be - see data sheet */
IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
incli_y, ADIS16203_SCAN_INCLI_Y,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
temp, ADIS16203_SCAN_TEMP,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN_SOFT_TIMESTAMP(5),
@@ -509,3 +508,4 @@ module_spi_driver(adis16203_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable Digital Vibration Sensor driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:adis16203");
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c
index 1fdfe6f6ac6e..064640d15e41 100644
--- a/drivers/staging/iio/accel/adis16203_ring.c
+++ b/drivers/staging/iio/accel/adis16203_ring.c
@@ -74,11 +74,11 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p)
return -ENOMEM;
}
- if (ring->scan_count)
- if (adis16203_read_ring_data(&indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
- data[i] = be16_to_cpup(
- (__be16 *)&(st->rx[i*2]));
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
+ adis16203_read_ring_data(&indio_dev->dev, st->rx) >= 0)
+ for (; i < bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength); i++)
+ data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
@@ -118,11 +118,9 @@ int adis16203_configure_ring(struct iio_dev *indio_dev)
}
indio_dev->buffer = ring;
/* Effectively select the ring buffer implementation */
- ring->bpe = 2;
ring->scan_timestamp = true;
ring->access = &ring_sw_access_funcs;
- ring->setup_ops = &adis16203_ring_setup_ops;
- ring->owner = THIS_MODULE;
+ indio_dev->setup_ops = &adis16203_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16203_trigger_handler,
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index 7ac5b4c533d8..fa89364b841e 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -20,7 +20,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "adis16204.h"
@@ -366,7 +366,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
*val = 0;
@@ -390,12 +390,12 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
break;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
*val = 25;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
- case (1 << IIO_CHAN_INFO_PEAK_SEPARATE):
- if (mask == (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE)) {
+ case IIO_CHAN_INFO_CALIBBIAS:
+ case IIO_CHAN_INFO_PEAK:
+ if (mask == IIO_CHAN_INFO_CALIBBIAS) {
bits = 12;
addrind = 1;
} else { /* PEAK_SEPARATE */
@@ -428,7 +428,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
s16 val16;
u8 addr;
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ACCEL:
bits = 12;
@@ -445,28 +445,28 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
static struct iio_chan_spec adis16204_channels[] = {
IIO_CHAN(IIO_VOLTAGE, 0, 0, 0, "supply", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
in_supply, ADIS16204_SCAN_SUPPLY,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
in_aux, ADIS16204_SCAN_AUX_ADC,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
temp, ADIS16204_SCAN_TEMP,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_PEAK_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
accel_x, ADIS16204_SCAN_ACC_X,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_PEAK_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
accel_y, ADIS16204_SCAN_ACC_Y,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN_SOFT_TIMESTAMP(5),
@@ -582,3 +582,4 @@ module_spi_driver(adis16204_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("ADIS16204 High-g Digital Impact Sensor and Recorder");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:adis16204");
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c
index 6fd3d8f51f2c..4081179dfa5c 100644
--- a/drivers/staging/iio/accel/adis16204_ring.c
+++ b/drivers/staging/iio/accel/adis16204_ring.c
@@ -71,11 +71,11 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p)
return -ENOMEM;
}
- if (ring->scan_count)
- if (adis16204_read_ring_data(&indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
- data[i] = be16_to_cpup(
- (__be16 *)&(st->rx[i*2]));
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
+ adis16204_read_ring_data(&indio_dev->dev, st->rx) >= 0)
+ for (; i < bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength); i++)
+ data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
if (ring->scan_timestamp)
@@ -114,10 +114,8 @@ int adis16204_configure_ring(struct iio_dev *indio_dev)
indio_dev->buffer = ring;
/* Effectively select the ring buffer implementation */
ring->access = &ring_sw_access_funcs;
- ring->bpe = 2;
ring->scan_timestamp = true;
- ring->setup_ops = &adis16204_ring_setup_ops;
- ring->owner = THIS_MODULE;
+ indio_dev->setup_ops = &adis16204_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16204_trigger_handler,
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index c03afbf5bbdc..a98715f6bd6d 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -18,7 +18,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "adis16209.h"
@@ -304,7 +304,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev,
s16 val16;
u8 addr;
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ACCEL:
case IIO_INCLI:
@@ -355,8 +355,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
*val = 0;
@@ -381,10 +380,10 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
break;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
*val = 25;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ACCEL:
bits = 14;
@@ -410,34 +409,34 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
static struct iio_chan_spec adis16209_channels[] = {
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
in_supply, ADIS16209_SCAN_SUPPLY,
IIO_ST('u', 14, 16, 0), 0),
IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
temp, ADIS16209_SCAN_TEMP,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
accel_x, ADIS16209_SCAN_ACC_X,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
accel_y, ADIS16209_SCAN_ACC_Y,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
in_aux, ADIS16209_SCAN_AUX_ADC,
IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
incli_x, ADIS16209_SCAN_INCLI_X,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
incli_y, ADIS16209_SCAN_INCLI_Y,
IIO_ST('s', 14, 16, 0), 0),
IIO_CHAN(IIO_ROT, 0, 1, 0, NULL, 0, IIO_MOD_X,
@@ -558,3 +557,4 @@ module_spi_driver(adis16209_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16209 Digital Vibration Sensor driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:adis16209");
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
index d17e39d95459..2a6fd334f5f1 100644
--- a/drivers/staging/iio/accel/adis16209_ring.c
+++ b/drivers/staging/iio/accel/adis16209_ring.c
@@ -72,9 +72,10 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p)
return -ENOMEM;
}
- if (ring->scan_count &&
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
adis16209_read_ring_data(&indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
+ for (; i < bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
@@ -114,10 +115,8 @@ int adis16209_configure_ring(struct iio_dev *indio_dev)
indio_dev->buffer = ring;
/* Effectively select the ring buffer implementation */
ring->access = &ring_sw_access_funcs;
- ring->bpe = 2;
ring->scan_timestamp = true;
- ring->setup_ops = &adis16209_ring_setup_ops;
- ring->owner = THIS_MODULE;
+ indio_dev->setup_ops = &adis16209_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16209_trigger_handler,
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index 73298e7849e6..51a852d45482 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -167,9 +167,9 @@ static ssize_t adis16220_write_16bit(struct device *dev,
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ u16 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
goto error_ret;
ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val);
@@ -510,17 +510,17 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
case 0:
addrind = 0;
break;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
if (chan->type == IIO_TEMP) {
*val = 25;
return IIO_VAL_INT;
}
addrind = 1;
break;
- case (1 << IIO_CHAN_INFO_PEAK_SEPARATE):
+ case IIO_CHAN_INFO_PEAK:
addrind = 2;
break;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
*val = 0;
switch (chan->type) {
case IIO_TEMP:
@@ -575,27 +575,27 @@ static const struct iio_chan_spec adis16220_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "supply",
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
}, {
.type = IIO_ACCEL,
- .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_PEAK_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
.address = accel,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = temp,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_1,
}, {
.type = IIO_VOLTAGE,
@@ -713,3 +713,4 @@ module_spi_driver(adis16220_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16220 Digital Vibration Sensor");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:adis16220");
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index 88881b9919ef..17f77fef7f2b 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -21,7 +21,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "adis16240.h"
@@ -389,8 +389,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
*val = 0;
@@ -411,14 +410,14 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
break;
- case (1 << IIO_CHAN_INFO_PEAK_SCALE_SHARED):
+ case IIO_CHAN_INFO_PEAK_SCALE:
*val = 6;
*val2 = 629295;
return IIO_VAL_INT_PLUS_MICRO;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
*val = 25;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
bits = 10;
mutex_lock(&indio_dev->mlock);
addr = adis16240_addresses[chan->address][1];
@@ -432,7 +431,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_PEAK_SEPARATE):
+ case IIO_CHAN_INFO_PEAK:
bits = 10;
mutex_lock(&indio_dev->mlock);
addr = adis16240_addresses[chan->address][2];
@@ -460,7 +459,7 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
s16 val16;
u8 addr;
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
val16 = val & ((1 << bits) - 1);
addr = adis16240_addresses[chan->address][1];
return adis16240_spi_write_reg_16(indio_dev, addr, val16);
@@ -470,7 +469,7 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
static struct iio_chan_spec adis16240_channels[] = {
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
in_supply, ADIS16240_SCAN_SUPPLY,
IIO_ST('u', 10, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
@@ -478,22 +477,22 @@ static struct iio_chan_spec adis16240_channels[] = {
in_aux, ADIS16240_SCAN_AUX_ADC,
IIO_ST('u', 10, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
accel_x, ADIS16240_SCAN_ACC_X,
IIO_ST('s', 10, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
accel_y, ADIS16240_SCAN_ACC_Y,
IIO_ST('s', 10, 16, 0), 0),
IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z,
- (1 << IIO_CHAN_INFO_SCALE_SHARED) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
accel_z, ADIS16240_SCAN_ACC_Z,
IIO_ST('s', 10, 16, 0), 0),
IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
temp, ADIS16240_SCAN_TEMP,
IIO_ST('u', 10, 16, 0), 0),
IIO_CHAN_SOFT_TIMESTAMP(6)
@@ -611,3 +610,4 @@ module_spi_driver(adis16240_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices Programmable Impact Sensor and Recorder");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:adis16240");
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
index b907ca3f4fdf..e23622d96f9f 100644
--- a/drivers/staging/iio/accel/adis16240_ring.c
+++ b/drivers/staging/iio/accel/adis16240_ring.c
@@ -69,9 +69,10 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p)
return -ENOMEM;
}
- if (ring->scan_count &&
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
adis16240_read_ring_data(&indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
+ for (; i < bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
@@ -111,10 +112,8 @@ int adis16240_configure_ring(struct iio_dev *indio_dev)
indio_dev->buffer = ring;
/* Effectively select the ring buffer implementation */
ring->access = &ring_sw_access_funcs;
- ring->bpe = 2;
ring->scan_timestamp = true;
- ring->setup_ops = &adis16240_ring_setup_ops;
- ring->owner = THIS_MODULE;
+ indio_dev->setup_ops = &adis16240_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16240_trigger_handler,
diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
index cfce21c2eddc..d13d7215ff6e 100644
--- a/drivers/staging/iio/accel/kxsd9.c
+++ b/drivers/staging/iio/accel/kxsd9.c
@@ -140,7 +140,7 @@ static int kxsd9_write_raw(struct iio_dev *indio_dev,
{
int ret = -EINVAL;
- if (mask == (1 << IIO_CHAN_INFO_SCALE_SHARED)) {
+ if (mask == IIO_CHAN_INFO_SCALE) {
/* Check no integer component */
if (val)
return -EINVAL;
@@ -164,7 +164,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev,
goto error_ret;
*val = ret;
break;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
if (ret)
goto error_ret;
@@ -181,7 +181,7 @@ error_ret:
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
- .info_mask = 1 << IIO_CHAN_INFO_SCALE_SHARED, \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = KXSD9_REG_##axis, \
}
@@ -268,8 +268,10 @@ static int __devexit kxsd9_remove(struct spi_device *spi)
}
static const struct spi_device_id kxsd9_id[] = {
- {"kxsd9", 0}
+ {"kxsd9", 0},
+ { },
};
+MODULE_DEVICE_TABLE(spi, kxsd9_id);
static struct spi_driver kxsd9_driver = {
.driver = {
diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h
index 7237a9ab61a8..2db383fc2743 100644
--- a/drivers/staging/iio/accel/lis3l02dq.h
+++ b/drivers/staging/iio/accel/lis3l02dq.h
@@ -181,11 +181,6 @@ int lis3l02dq_disable_all_events(struct iio_dev *indio_dev);
void lis3l02dq_remove_trigger(struct iio_dev *indio_dev);
int lis3l02dq_probe_trigger(struct iio_dev *indio_dev);
-ssize_t lis3l02dq_read_accel_from_buffer(struct iio_buffer *buffer,
- int index,
- int *val);
-
-
int lis3l02dq_configure_buffer(struct iio_dev *indio_dev);
void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev);
@@ -212,13 +207,6 @@ static inline int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
{
return 0;
}
-static inline ssize_t
-lis3l02dq_read_accel_from_buffer(struct iio_buffer *buffer,
- int index,
- int *val)
-{
- return 0;
-}
static int lis3l02dq_configure_buffer(struct iio_dev *indio_dev)
{
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index 6877521ec173..376da5137967 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -25,7 +25,8 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../events.h"
+#include "../buffer.h"
#include "lis3l02dq.h"
@@ -226,14 +227,14 @@ static int lis3l02dq_write_raw(struct iio_dev *indio_dev,
u8 uval;
s8 sval;
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
if (val > 255 || val < -256)
return -EINVAL;
sval = val;
reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address];
ret = lis3l02dq_spi_write_reg_8(indio_dev, reg, sval);
break;
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
if (val & ~0xFF)
return -EINVAL;
uval = val;
@@ -259,23 +260,20 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev,
case 0:
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
- if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
- ret = lis3l02dq_read_accel_from_buffer(indio_dev->
- buffer,
- chan->scan_index,
- val);
- else {
+ if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+ ret = -EBUSY;
+ } else {
reg = lis3l02dq_axis_map
[LIS3L02DQ_ACCEL][chan->address];
ret = lis3l02dq_read_reg_s16(indio_dev, reg, val);
}
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = 9580;
return IIO_VAL_INT_PLUS_MICRO;
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN][chan->address];
ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, &utemp);
if (ret)
@@ -284,7 +282,7 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev,
*val = utemp;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address];
ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, (u8 *)&stemp);
/* to match with what previous code does */
@@ -331,11 +329,11 @@ static ssize_t lis3l02dq_write_frequency(struct device *dev,
size_t len)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- long val;
+ unsigned long val;
int ret;
u8 t;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtoul(buf, 10, &val);
if (ret)
return ret;
@@ -515,9 +513,9 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
}
#define LIS3L02DQ_INFO_MASK \
- ((1 << IIO_CHAN_INFO_SCALE_SHARED) | \
- (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE))
+ (IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT)
#define LIS3L02DQ_EVENT_MASK \
(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
@@ -534,7 +532,7 @@ static struct iio_chan_spec lis3l02dq_channels[] = {
};
-static ssize_t lis3l02dq_read_event_config(struct iio_dev *indio_dev,
+static int lis3l02dq_read_event_config(struct iio_dev *indio_dev,
u64 event_code)
{
@@ -809,3 +807,4 @@ module_spi_driver(lis3l02dq_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_DESCRIPTION("ST LIS3L02DQ Accelerometer SPI driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:lis3l02dq");
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 89527af8f4c5..98c5c92d3450 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -38,38 +38,6 @@ irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private)
return IRQ_WAKE_THREAD;
}
-/**
- * lis3l02dq_read_accel_from_buffer() individual acceleration read from buffer
- **/
-ssize_t lis3l02dq_read_accel_from_buffer(struct iio_buffer *buffer,
- int index,
- int *val)
-{
- int ret;
- s16 *data;
-
- if (!iio_scan_mask_query(buffer, index))
- return -EINVAL;
-
- if (!buffer->access->read_last)
- return -EBUSY;
-
- data = kmalloc(buffer->access->get_bytes_per_datum(buffer),
- GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- ret = buffer->access->read_last(buffer, (u8 *)data);
- if (ret)
- goto error_free_data;
- *val = data[bitmap_weight(buffer->scan_mask, index)];
-error_free_data:
-
- kfree(data);
-
- return ret;
-}
-
static const u8 read_all_tx_array[] = {
LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_X_L_ADDR), 0,
LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_X_H_ADDR), 0,
@@ -87,21 +55,21 @@ static const u8 read_all_tx_array[] = {
**/
static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array)
{
- struct iio_buffer *buffer = indio_dev->buffer;
struct lis3l02dq_state *st = iio_priv(indio_dev);
struct spi_transfer *xfers;
struct spi_message msg;
int ret, i, j = 0;
- xfers = kzalloc((buffer->scan_count) * 2
- * sizeof(*xfers), GFP_KERNEL);
+ xfers = kcalloc(bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) * 2,
+ sizeof(*xfers), GFP_KERNEL);
if (!xfers)
return -ENOMEM;
mutex_lock(&st->buf_lock);
for (i = 0; i < ARRAY_SIZE(read_all_tx_array)/4; i++)
- if (test_bit(i, buffer->scan_mask)) {
+ if (test_bit(i, indio_dev->active_scan_mask)) {
/* lower byte */
xfers[j].tx_buf = st->tx + 2*j;
st->tx[2*j] = read_all_tx_array[i*4];
@@ -129,7 +97,8 @@ static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array)
* values in alternate bytes
*/
spi_message_init(&msg);
- for (j = 0; j < buffer->scan_count * 2; j++)
+ for (j = 0; j < bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) * 2; j++)
spi_message_add_tail(&xfers[j], &msg);
ret = spi_sync(st->us, &msg);
@@ -145,14 +114,16 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev,
int ret, i;
u8 *rx_array ;
s16 *data = (s16 *)buf;
+ int scan_count = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength);
- rx_array = kzalloc(4 * (indio_dev->buffer->scan_count), GFP_KERNEL);
+ rx_array = kzalloc(4 * scan_count, GFP_KERNEL);
if (rx_array == NULL)
return -ENOMEM;
ret = lis3l02dq_read_all(indio_dev, rx_array);
if (ret < 0)
return ret;
- for (i = 0; i < indio_dev->buffer->scan_count; i++)
+ for (i = 0; i < scan_count; i++)
data[i] = combine_8_to_16(rx_array[i*4+1],
rx_array[i*4+3]);
kfree(rx_array);
@@ -175,7 +146,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
return -ENOMEM;
}
- if (buffer->scan_count)
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
len = lis3l02dq_get_buffer_element(indio_dev, data);
/* Guaranteed to be aligned with 8 byte boundary */
@@ -363,17 +334,17 @@ static int lis3l02dq_buffer_postenable(struct iio_dev *indio_dev)
if (ret)
goto error_ret;
- if (iio_scan_mask_query(indio_dev->buffer, 0)) {
+ if (test_bit(0, indio_dev->active_scan_mask)) {
t |= LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE;
oneenabled = true;
} else
t &= ~LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE;
- if (iio_scan_mask_query(indio_dev->buffer, 1)) {
+ if (test_bit(1, indio_dev->active_scan_mask)) {
t |= LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE;
oneenabled = true;
} else
t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE;
- if (iio_scan_mask_query(indio_dev->buffer, 2)) {
+ if (test_bit(2, indio_dev->active_scan_mask)) {
t |= LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
oneenabled = true;
} else
@@ -437,11 +408,9 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev)
indio_dev->buffer = buffer;
/* Effectively select the buffer implementation */
indio_dev->buffer->access = &lis3l02dq_access_funcs;
- buffer->bpe = 2;
buffer->scan_timestamp = true;
- buffer->setup_ops = &lis3l02dq_buffer_setup_ops;
- buffer->owner = THIS_MODULE;
+ indio_dev->setup_ops = &lis3l02dq_buffer_setup_ops;
/* Functions are NULL as we set handler below */
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 6c359074a06d..49764fb7181c 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -20,7 +20,8 @@
#include <linux/module.h>
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../events.h"
+#include "../buffer.h"
#include "sca3000.h"
@@ -381,13 +382,17 @@ sca3000_store_measurement_mode(struct device *dev,
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
- int mask = 0x03;
- long val;
+ u8 mask = 0x03;
+ u8 val;
mutex_lock(&st->lock);
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou8(buf, 10, &val);
if (ret)
goto error_ret;
+ if (val > 3) {
+ ret = -EINVAL;
+ goto error_ret;
+ }
ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
@@ -424,7 +429,7 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0);
#define SCA3000_INFO_MASK \
- (1 << IIO_CHAN_INFO_SCALE_SHARED)
+ IIO_CHAN_INFO_SCALE_SHARED_BIT
#define SCA3000_EVENT_MASK \
(IIO_EV_BIT(IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING))
@@ -474,7 +479,7 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
(sizeof(*val)*8 - 13);
mutex_unlock(&st->lock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
*val = 0;
if (chan->type == IIO_ACCEL)
*val2 = st->info->scale;
@@ -1161,9 +1166,9 @@ static int __devinit sca3000_probe(struct spi_device *spi)
if (ret < 0)
goto error_unregister_dev;
if (indio_dev->buffer) {
- iio_scan_mask_set(indio_dev->buffer, 0);
- iio_scan_mask_set(indio_dev->buffer, 1);
- iio_scan_mask_set(indio_dev->buffer, 2);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer, 0);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer, 1);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer, 2);
}
if (spi->irq) {
@@ -1240,6 +1245,7 @@ static const struct spi_device_id sca3000_id[] = {
{"sca3000_e05", e05},
{}
};
+MODULE_DEVICE_TABLE(spi, sca3000_id);
static struct spi_driver sca3000_driver = {
.driver = {
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 4a9a01dccd0c..6b824a11f7f4 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -20,7 +20,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_hw.h"
#include "sca3000.h"
@@ -146,7 +146,6 @@ static int sca3000_ring_get_bytes_per_datum(struct iio_buffer *r)
}
static IIO_BUFFER_ENABLE_ATTR;
-static IIO_BUFFER_BYTES_PER_DATUM_ATTR;
static IIO_BUFFER_LENGTH_ATTR;
/**
@@ -158,8 +157,7 @@ static ssize_t sca3000_query_ring_int(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret, val;
- struct iio_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = iio_priv(indio_dev);
mutex_lock(&st->lock);
@@ -180,8 +178,7 @@ static ssize_t sca3000_set_ring_int(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
long val;
@@ -222,8 +219,7 @@ static ssize_t sca3000_show_buffer_scale(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_buffer *ring = dev_get_drvdata(dev);
- struct iio_dev *indio_dev = ring->indio_dev;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct sca3000_state *st = iio_priv(indio_dev);
return sprintf(buf, "0.%06d\n", 4*st->info->scale);
@@ -243,7 +239,6 @@ static IIO_DEVICE_ATTR(in_accel_scale,
*/
static struct attribute *sca3000_ring_attributes[] = {
&dev_attr_length.attr,
- &dev_attr_bytes_per_datum.attr,
&dev_attr_enable.attr,
&iio_dev_attr_50_percent.dev_attr.attr,
&iio_dev_attr_75_percent.dev_attr.attr,
@@ -269,7 +264,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev)
buf = &ring->buf;
buf->stufftoread = 0;
buf->attrs = &sca3000_ring_attr;
- iio_buffer_init(buf, indio_dev);
+ iio_buffer_init(buf);
return buf;
}
@@ -350,7 +345,7 @@ static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = {
void sca3000_register_ring_funcs(struct iio_dev *indio_dev)
{
- indio_dev->buffer->setup_ops = &sca3000_ring_setup_ops;
+ indio_dev->setup_ops = &sca3000_ring_setup_ops;
}
/**
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index 797e65cd03e8..45f4504ed927 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -19,7 +19,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_sw.h"
#include "../trigger.h"
#include "../trigger_consumer.h"
@@ -453,25 +453,6 @@ out:
return ret;
}
-static int ad7192_scan_from_ring(struct ad7192_state *st, unsigned ch, int *val)
-{
- struct iio_buffer *ring = iio_priv_to_dev(st)->buffer;
- int ret;
- s64 dat64[2];
- u32 *dat32 = (u32 *)dat64;
-
- if (!(test_bit(ch, ring->scan_mask)))
- return -EBUSY;
-
- ret = ring->access->read_last(ring, (u8 *) &dat64);
- if (ret)
- return ret;
-
- *val = *dat32;
-
- return 0;
-}
-
static int ad7192_ring_preenable(struct iio_dev *indio_dev)
{
struct ad7192_state *st = iio_priv(indio_dev);
@@ -479,12 +460,14 @@ static int ad7192_ring_preenable(struct iio_dev *indio_dev)
size_t d_size;
unsigned channel;
- if (!ring->scan_count)
+ if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
- channel = find_first_bit(ring->scan_mask, indio_dev->masklength);
+ channel = find_first_bit(indio_dev->active_scan_mask,
+ indio_dev->masklength);
- d_size = ring->scan_count *
+ d_size = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) *
indio_dev->channels[0].scan_type.storagebits / 8;
if (ring->scan_timestamp) {
@@ -544,7 +527,7 @@ static irqreturn_t ad7192_trigger_handler(int irq, void *p)
s64 dat64[2];
s32 *dat32 = (s32 *)dat64;
- if (ring->scan_count)
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
__ad7192_read_reg(st, 1, 1, AD7192_REG_DATA,
dat32,
indio_dev->channels[0].scan_type.realbits/8);
@@ -592,7 +575,7 @@ static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev)
}
/* Ring buffer functions - here trigger setup related */
- indio_dev->buffer->setup_ops = &ad7192_ring_setup_ops;
+ indio_dev->setup_ops = &ad7192_ring_setup_ops;
/* Flag that polled ring buffering is possible */
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
@@ -626,6 +609,10 @@ static irqreturn_t ad7192_data_rdy_trig_poll(int irq, void *private)
return IRQ_HANDLED;
}
+static struct iio_trigger_ops ad7192_trigger_ops = {
+ .owner = THIS_MODULE,
+};
+
static int ad7192_probe_trigger(struct iio_dev *indio_dev)
{
struct ad7192_state *st = iio_priv(indio_dev);
@@ -638,7 +625,7 @@ static int ad7192_probe_trigger(struct iio_dev *indio_dev)
ret = -ENOMEM;
goto error_ret;
}
-
+ st->trig->ops = &ad7192_trigger_ops;
ret = request_irq(st->spi->irq,
ad7192_data_rdy_trig_poll,
IRQF_TRIGGER_LOW,
@@ -650,7 +637,6 @@ static int ad7192_probe_trigger(struct iio_dev *indio_dev)
disable_irq_nosync(st->spi->irq);
st->irq_dis = true;
st->trig->dev.parent = &st->spi->dev;
- st->trig->owner = THIS_MODULE;
st->trig->private_data = indio_dev;
ret = iio_trigger_register(st->trig);
@@ -795,7 +781,7 @@ static ssize_t ad7192_set(struct device *dev,
return -EBUSY;
}
- switch (this_attr->address) {
+ switch ((u32) this_attr->address) {
case AD7192_REG_GPOCON:
if (val)
st->gpocon |= AD7192_GPOCON_BPDSW;
@@ -873,8 +859,7 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
case 0:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
- ret = ad7192_scan_from_ring(st,
- chan->scan_index, &smpl);
+ ret = -EBUSY;
else
ret = ad7192_read(st, chan->address,
chan->scan_type.realbits / 8, &smpl);
@@ -901,18 +886,20 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
}
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
- mutex_lock(&indio_dev->mlock);
- *val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0];
- *val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1];
- mutex_unlock(&indio_dev->mlock);
-
- return IIO_VAL_INT_PLUS_NANO;
-
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
- *val = 1000;
-
- return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ mutex_lock(&indio_dev->mlock);
+ *val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0];
+ *val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1];
+ mutex_unlock(&indio_dev->mlock);
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_TEMP:
+ *val = 1000;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
}
return -EINVAL;
@@ -935,7 +922,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
}
switch (mask) {
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
ret = -EINVAL;
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
if (val2 == st->scale_avail[i][1]) {
@@ -992,7 +979,7 @@ static const struct iio_info ad7192_info = {
.extend_name = _name, \
.channel = _chan, \
.channel2 = _chan2, \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('s', 24, 32, 0)}
@@ -1001,7 +988,7 @@ static const struct iio_info ad7192_info = {
{ .type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _chan, \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('s', 24, 32, 0)}
@@ -1010,7 +997,7 @@ static const struct iio_info ad7192_info = {
{ .type = IIO_TEMP, \
.indexed = 1, \
.channel = _chan, \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('s', 24, 32, 0)}
@@ -1151,6 +1138,7 @@ static const struct spi_device_id ad7192_id[] = {
{"ad7195", ID_AD7195},
{}
};
+MODULE_DEVICE_TABLE(spi, ad7192_id);
static struct spi_driver ad7192_driver = {
.driver = {
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
index dbaeae81e873..7dbd6812c240 100644
--- a/drivers/staging/iio/adc/ad7280a.c
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -18,6 +18,7 @@
#include "../iio.h"
#include "../sysfs.h"
+#include "../events.h"
#include "ad7280a.h"
@@ -455,10 +456,10 @@ static ssize_t ad7280_store_balance_timer(struct device *dev,
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- long val;
+ unsigned long val;
int ret;
- ret = strict_strtoul(buf, 10, &val);
+ ret = kstrtoul(buf, 10, &val);
if (ret)
return ret;
@@ -487,8 +488,8 @@ static int ad7280_channel_init(struct ad7280_state *st)
{
int dev, ch, cnt;
- st->channels = kzalloc(sizeof(*st->channels) *
- ((st->slave_num + 1) * 12 + 2), GFP_KERNEL);
+ st->channels = kcalloc((st->slave_num + 1) * 12 + 2,
+ sizeof(*st->channels), GFP_KERNEL);
if (st->channels == NULL)
return -ENOMEM;
@@ -507,7 +508,7 @@ static int ad7280_channel_init(struct ad7280_state *st)
}
st->channels[cnt].indexed = 1;
st->channels[cnt].info_mask =
- (1 << IIO_CHAN_INFO_SCALE_SHARED);
+ IIO_CHAN_INFO_SCALE_SHARED_BIT;
st->channels[cnt].address =
AD7280A_DEVADDR(dev) << 8 | ch;
st->channels[cnt].scan_index = cnt;
@@ -523,7 +524,7 @@ static int ad7280_channel_init(struct ad7280_state *st)
st->channels[cnt].channel2 = dev * 6;
st->channels[cnt].address = AD7280A_ALL_CELLS;
st->channels[cnt].indexed = 1;
- st->channels[cnt].info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED);
+ st->channels[cnt].info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT;
st->channels[cnt].scan_index = cnt;
st->channels[cnt].scan_type.sign = 'u';
st->channels[cnt].scan_type.realbits = 32;
@@ -600,7 +601,7 @@ static ssize_t ad7280_read_channel_config(struct device *dev,
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned val;
- switch (this_attr->address) {
+ switch ((u32) this_attr->address) {
case AD7280A_CELL_OVERVOLTAGE:
val = 1000 + (st->cell_threshhigh * 1568) / 100;
break;
@@ -636,7 +637,7 @@ static ssize_t ad7280_write_channel_config(struct device *dev,
if (ret)
return ret;
- switch (this_attr->address) {
+ switch ((u32) this_attr->address) {
case AD7280A_CELL_OVERVOLTAGE:
case AD7280A_CELL_UNDERVOLTAGE:
val = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */
@@ -652,7 +653,7 @@ static ssize_t ad7280_write_channel_config(struct device *dev,
val = clamp(val, 0L, 0xFFL);
mutex_lock(&indio_dev->mlock);
- switch (this_attr->address) {
+ switch ((u32) this_attr->address) {
case AD7280A_CELL_OVERVOLTAGE:
st->cell_threshhigh = val;
break;
@@ -682,13 +683,13 @@ static irqreturn_t ad7280_event_handler(int irq, void *private)
unsigned *channels;
int i, ret;
- channels = kzalloc(sizeof(*channels) * st->scan_cnt, GFP_KERNEL);
+ channels = kcalloc(st->scan_cnt, sizeof(*channels), GFP_KERNEL);
if (channels == NULL)
return IRQ_HANDLED;
ret = ad7280_read_all_channels(st, st->scan_cnt, channels);
if (ret < 0)
- return IRQ_HANDLED;
+ goto out;
for (i = 0; i < st->scan_cnt; i++) {
if (((channels[i] >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6) {
@@ -731,6 +732,7 @@ static irqreturn_t ad7280_event_handler(int irq, void *private)
}
}
+out:
kfree(channels);
return IRQ_HANDLED;
@@ -801,7 +803,7 @@ static int ad7280_read_raw(struct iio_dev *indio_dev,
*val = ret;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6)
scale_uv = (4000 * 1000) >> AD7280A_BITS;
else
@@ -968,11 +970,11 @@ static const struct spi_device_id ad7280_id[] = {
{"ad7280a", 0},
{}
};
+MODULE_DEVICE_TABLE(spi, ad7280_id);
static struct spi_driver ad7280_driver = {
.driver = {
.name = "ad7280",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad7280_probe,
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
index aa44a52a7adb..0a13616e3db9 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/staging/iio/adc/ad7291.c
@@ -19,6 +19,7 @@
#include "../iio.h"
#include "../sysfs.h"
+#include "../events.h"
/*
* Simplified handling
@@ -500,7 +501,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
- case (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE):
+ case IIO_CHAN_INFO_AVERAGE_RAW:
ret = i2c_smbus_read_word_data(chip->client,
AD7291_T_AVERAGE);
if (ret < 0)
@@ -509,18 +510,24 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
AD7291_VALUE_MASK) << 4) >> 4;
*val = signval;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
- scale_uv = (chip->int_vref_mv * 1000) >> AD7291_BITS;
- *val = scale_uv / 1000;
- *val2 = (scale_uv % 1000) * 1000;
- return IIO_VAL_INT_PLUS_MICRO;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
- /*
- * One LSB of the ADC corresponds to 0.25 deg C.
- * The temperature reading is in 12-bit twos complement format
- */
- *val = 250;
- return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ scale_uv = (chip->int_vref_mv * 1000) >> AD7291_BITS;
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ /*
+ * One LSB of the ADC corresponds to 0.25 deg C.
+ * The temperature reading is in 12-bit twos
+ * complement format
+ */
+ *val = 250;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
default:
return -EINVAL;
}
@@ -529,7 +536,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
#define AD7291_VOLTAGE_CHAN(_chan) \
{ \
.type = IIO_VOLTAGE, \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.indexed = 1, \
.channel = _chan, \
.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|\
@@ -547,8 +554,8 @@ static const struct iio_chan_spec ad7291_channels[] = {
AD7291_VOLTAGE_CHAN(7),
{
.type = IIO_TEMP,
- .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.indexed = 1,
.channel = 0,
.event_mask =
diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h
index 9ddf5cf0e519..a0e5dea415ef 100644
--- a/drivers/staging/iio/adc/ad7298.h
+++ b/drivers/staging/iio/adc/ad7298.h
@@ -54,14 +54,9 @@ struct ad7298_state {
};
#ifdef CONFIG_IIO_BUFFER
-int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch);
int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void ad7298_ring_cleanup(struct iio_dev *indio_dev);
#else /* CONFIG_IIO_BUFFER */
-static inline int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch)
-{
- return 0;
-}
static inline int
ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c
index a799bd1922dc..8dd6aa9cf928 100644
--- a/drivers/staging/iio/adc/ad7298_core.c
+++ b/drivers/staging/iio/adc/ad7298_core.c
@@ -18,37 +18,37 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "ad7298.h"
static struct iio_chan_spec ad7298_channels[] = {
IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
9, AD7298_CH_TEMP, IIO_ST('s', 32, 32, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
1, 1, IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 2, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
2, 2, IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 3, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
3, 3, IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 4, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
4, 4, IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 5, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
5, 5, IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 6, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
6, 6, IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 7, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
7, 7, IIO_ST('u', 12, 16, 0), 0),
IIO_CHAN_SOFT_TIMESTAMP(8),
};
@@ -69,27 +69,28 @@ static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
static int ad7298_scan_temp(struct ad7298_state *st, int *val)
{
int tmp, ret;
+ __be16 buf;
- tmp = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
+ buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
AD7298_TAVG | st->ext_ref);
- ret = spi_write(st->spi, (u8 *)&tmp, 2);
+ ret = spi_write(st->spi, (u8 *)&buf, 2);
if (ret)
return ret;
- tmp = 0;
+ buf = cpu_to_be16(0);
- ret = spi_write(st->spi, (u8 *)&tmp, 2);
+ ret = spi_write(st->spi, (u8 *)&buf, 2);
if (ret)
return ret;
usleep_range(101, 1000); /* sleep > 100us */
- ret = spi_read(st->spi, (u8 *)&tmp, 2);
+ ret = spi_read(st->spi, (u8 *)&buf, 2);
if (ret)
return ret;
- tmp = be16_to_cpu(tmp) & RES_MASK(AD7298_BITS);
+ tmp = be16_to_cpu(buf) & RES_MASK(AD7298_BITS);
/*
* One LSB of the ADC corresponds to 0.25 deg C.
@@ -122,12 +123,8 @@ static int ad7298_read_raw(struct iio_dev *indio_dev,
switch (m) {
case 0:
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_enabled(indio_dev)) {
- if (chan->address == AD7298_CH_TEMP)
- ret = -ENODEV;
- else
- ret = ad7298_scan_from_ring(indio_dev,
- chan->address);
+ if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+ ret = -EBUSY;
} else {
if (chan->address == AD7298_CH_TEMP)
ret = ad7298_scan_temp(st, val);
@@ -143,15 +140,20 @@ static int ad7298_read_raw(struct iio_dev *indio_dev,
*val = ret & RES_MASK(AD7298_BITS);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
- scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS;
- *val = scale_uv / 1000;
- *val2 = (scale_uv % 1000) * 1000;
- return IIO_VAL_INT_PLUS_MICRO;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
- *val = 1;
- *val2 = 0;
- return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS;
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ *val = 1;
+ *val2 = 0;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
}
return -EINVAL;
}
@@ -265,11 +267,11 @@ static const struct spi_device_id ad7298_id[] = {
{"ad7298", 0},
{}
};
+MODULE_DEVICE_TABLE(spi, ad7298_id);
static struct spi_driver ad7298_driver = {
.driver = {
.name = "ad7298",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad7298_probe,
@@ -281,4 +283,3 @@ module_spi_driver(ad7298_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD7298 ADC");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:ad7298");
diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c
index 47630d506a63..d1a12dd015e2 100644
--- a/drivers/staging/iio/adc/ad7298_ring.c
+++ b/drivers/staging/iio/adc/ad7298_ring.c
@@ -12,41 +12,12 @@
#include <linux/spi/spi.h>
#include "../iio.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_sw.h"
#include "../trigger_consumer.h"
#include "ad7298.h"
-int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- int ret;
- u16 *ring_data;
-
- if (!(test_bit(ch, ring->scan_mask))) {
- ret = -EBUSY;
- goto error_ret;
- }
-
- ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
- GFP_KERNEL);
- if (ring_data == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- ret = ring->access->read_last(ring, (u8 *) ring_data);
- if (ret)
- goto error_free_ring_data;
-
- ret = be16_to_cpu(ring_data[ch]);
-
-error_free_ring_data:
- kfree(ring_data);
-error_ret:
- return ret;
-}
-
/**
* ad7298_ring_preenable() setup the parameters of the ring before enabling
*
@@ -61,8 +32,9 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev)
size_t d_size;
int i, m;
unsigned short command;
-
- d_size = ring->scan_count * (AD7298_STORAGE_BITS / 8);
+ int scan_count = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength);
+ d_size = scan_count * (AD7298_STORAGE_BITS / 8);
if (ring->scan_timestamp) {
d_size += sizeof(s64);
@@ -79,7 +51,7 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev)
command = AD7298_WRITE | st->ext_ref;
for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1)
- if (test_bit(i, ring->scan_mask))
+ if (test_bit(i, indio_dev->active_scan_mask))
command |= m;
st->tx_buf[0] = cpu_to_be16(command);
@@ -96,7 +68,7 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev)
spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
- for (i = 0; i < ring->scan_count; i++) {
+ for (i = 0; i < scan_count; i++) {
st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i];
st->ring_xfer[i + 2].len = 2;
st->ring_xfer[i + 2].cs_change = 1;
@@ -134,7 +106,8 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p)
&time_ns, sizeof(time_ns));
}
- for (i = 0; i < ring->scan_count; i++)
+ for (i = 0; i < bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength); i++)
buf[i] = be16_to_cpu(st->rx_buf[i]);
indio_dev->buffer->access->store_to(ring, (u8 *)buf, time_ns);
@@ -174,7 +147,7 @@ int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
}
/* Ring buffer functions - here trigger setup related */
- indio_dev->buffer->setup_ops = &ad7298_ring_setup_ops;
+ indio_dev->setup_ops = &ad7298_ring_setup_ops;
indio_dev->buffer->scan_timestamp = true;
/* Flag that polled ring buffering is possible */
diff --git a/drivers/staging/iio/adc/ad7476.h b/drivers/staging/iio/adc/ad7476.h
index 60142926565f..27f696c75cc4 100644
--- a/drivers/staging/iio/adc/ad7476.h
+++ b/drivers/staging/iio/adc/ad7476.h
@@ -50,14 +50,9 @@ enum ad7476_supported_device_ids {
};
#ifdef CONFIG_IIO_BUFFER
-int ad7476_scan_from_ring(struct iio_dev *indio_dev);
int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void ad7476_ring_cleanup(struct iio_dev *indio_dev);
#else /* CONFIG_IIO_BUFFER */
-static inline int ad7476_scan_from_ring(struct iio_dev *indio_dev)
-{
- return 0;
-}
static inline int
ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c
index 0b5852030ab6..0c064d1c3927 100644
--- a/drivers/staging/iio/adc/ad7476_core.c
+++ b/drivers/staging/iio/adc/ad7476_core.c
@@ -17,7 +17,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "ad7476.h"
@@ -46,7 +46,7 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
case 0:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
- ret = ad7476_scan_from_ring(indio_dev);
+ ret = -EBUSY;
else
ret = ad7476_scan_direct(st);
mutex_unlock(&indio_dev->mlock);
@@ -56,7 +56,7 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
*val = (ret >> st->chip_info->channel[0].scan_type.shift) &
RES_MASK(st->chip_info->channel[0].scan_type.realbits);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
scale_uv = (st->int_vref_mv * 1000)
>> st->chip_info->channel[0].scan_type.realbits;
*val = scale_uv/1000;
@@ -69,49 +69,49 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
[ID_AD7466] = {
.channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('u', 12, 16, 0), 0),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7467] = {
.channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('u', 10, 16, 2), 0),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7468] = {
.channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1 , 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('u', 8, 16, 4), 0),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7475] = {
.channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('u', 12, 16, 0), 0),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7476] = {
.channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('u', 12, 16, 0), 0),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7477] = {
.channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('u', 10, 16, 2), 0),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7478] = {
.channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('u', 8, 16, 4), 0),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7495] = {
.channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('u', 12, 16, 0), 0),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
.int_vref_mv = 2500,
@@ -237,11 +237,11 @@ static const struct spi_device_id ad7476_id[] = {
{"ad7495", ID_AD7495},
{}
};
+MODULE_DEVICE_TABLE(spi, ad7476_id);
static struct spi_driver ad7476_driver = {
.driver = {
.name = "ad7476",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad7476_probe,
@@ -253,4 +253,3 @@ module_spi_driver(ad7476_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD7475/6/7/8(A) AD7466/7/8 ADC");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:ad7476");
diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c
index e82c1a433f4f..4e298b2a05b2 100644
--- a/drivers/staging/iio/adc/ad7476_ring.c
+++ b/drivers/staging/iio/adc/ad7476_ring.c
@@ -14,36 +14,12 @@
#include <linux/spi/spi.h>
#include "../iio.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_sw.h"
#include "../trigger_consumer.h"
#include "ad7476.h"
-int ad7476_scan_from_ring(struct iio_dev *indio_dev)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- int ret;
- u8 *ring_data;
-
- ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
- GFP_KERNEL);
- if (ring_data == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- ret = ring->access->read_last(ring, ring_data);
- if (ret)
- goto error_free_ring_data;
-
- ret = (ring_data[0] << 8) | ring_data[1];
-
-error_free_ring_data:
- kfree(ring_data);
-error_ret:
- return ret;
-}
-
/**
* ad7476_ring_preenable() setup the parameters of the ring before enabling
*
@@ -56,7 +32,8 @@ static int ad7476_ring_preenable(struct iio_dev *indio_dev)
struct ad7476_state *st = iio_priv(indio_dev);
struct iio_buffer *ring = indio_dev->buffer;
- st->d_size = ring->scan_count *
+ st->d_size = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) *
st->chip_info->channel[0].scan_type.storagebits / 8;
if (ring->scan_timestamp) {
@@ -137,7 +114,7 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
}
/* Ring buffer functions - here trigger setup related */
- indio_dev->buffer->setup_ops = &ad7476_ring_setup_ops;
+ indio_dev->setup_ops = &ad7476_ring_setup_ops;
indio_dev->buffer->scan_timestamp = true;
/* Flag that polled ring buffering is possible */
diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h
index 35018c3f518e..10f59896597f 100644
--- a/drivers/staging/iio/adc/ad7606.h
+++ b/drivers/staging/iio/adc/ad7606.h
@@ -99,7 +99,6 @@ enum ad7606_supported_device_ids {
ID_AD7606_4
};
-int ad7606_scan_from_ring(struct iio_dev *indio_dev, unsigned ch);
int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void ad7606_ring_cleanup(struct iio_dev *indio_dev);
#endif /* IIO_ADC_AD7606_H_ */
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c
index e3ecd3d2ef3a..ddb7ef92f5c1 100644
--- a/drivers/staging/iio/adc/ad7606_core.c
+++ b/drivers/staging/iio/adc/ad7606_core.c
@@ -20,7 +20,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "ad7606.h"
@@ -91,7 +91,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
case 0:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
- ret = ad7606_scan_from_ring(indio_dev, chan->address);
+ ret = -EBUSY;
else
ret = ad7606_scan_direct(indio_dev, chan->address);
mutex_unlock(&indio_dev->mlock);
@@ -100,7 +100,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
return ret;
*val = (short) ret;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
scale_uv = (st->range * 1000 * 2)
>> st->chip_info->channels[0].scan_type.realbits;
*val = scale_uv / 1000;
diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c
index 688632edd3d7..cff97568189e 100644
--- a/drivers/staging/iio/adc/ad7606_par.c
+++ b/drivers/staging/iio/adc/ad7606_par.c
@@ -189,4 +189,3 @@ module_exit(ad7606_cleanup);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:ad7606_par");
diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c
index 20927fd53728..e8f94a18a943 100644
--- a/drivers/staging/iio/adc/ad7606_ring.c
+++ b/drivers/staging/iio/adc/ad7606_ring.c
@@ -12,36 +12,12 @@
#include <linux/slab.h>
#include "../iio.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_sw.h"
#include "../trigger_consumer.h"
#include "ad7606.h"
-int ad7606_scan_from_ring(struct iio_dev *indio_dev, unsigned ch)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- int ret;
- u16 *ring_data;
-
- ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
- GFP_KERNEL);
- if (ring_data == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- ret = ring->access->read_last(ring, (u8 *) ring_data);
- if (ret)
- goto error_free_ring_data;
-
- ret = ring_data[ch];
-
-error_free_ring_data:
- kfree(ring_data);
-error_ret:
- return ret;
-}
-
/**
* ad7606_trigger_handler_th() th/bh of trigger launched polling to ring buffer
*
@@ -136,8 +112,6 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev)
/* Effectively select the ring buffer implementation */
indio_dev->buffer->access = &ring_sw_access_funcs;
- indio_dev->buffer->bpe =
- st->chip_info->channels[0].scan_type.storagebits / 8;
indio_dev->pollfunc = iio_alloc_pollfunc(&ad7606_trigger_handler_th_bh,
&ad7606_trigger_handler_th_bh,
0,
@@ -152,7 +126,7 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev)
/* Ring buffer functions - here trigger setup related */
- indio_dev->buffer->setup_ops = &ad7606_ring_setup_ops;
+ indio_dev->setup_ops = &ad7606_ring_setup_ops;
indio_dev->buffer->scan_timestamp = true ;
INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring);
diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c
index b984bd2048b6..237f1c44d296 100644
--- a/drivers/staging/iio/adc/ad7606_spi.c
+++ b/drivers/staging/iio/adc/ad7606_spi.c
@@ -97,11 +97,11 @@ static const struct spi_device_id ad7606_id[] = {
{"ad7606-4", ID_AD7606_4},
{}
};
+MODULE_DEVICE_TABLE(spi, ad7606_id);
static struct spi_driver ad7606_driver = {
.driver = {
.name = "ad7606",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = AD7606_SPI_PM_OPS,
},
@@ -114,4 +114,3 @@ module_spi_driver(ad7606_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:ad7606_spi");
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index ec90261cbc3c..a13e58c814e6 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -114,7 +114,7 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
*val *= 128;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
scale_uv = (st->int_vref_mv * 100000)
>> (channel.scan_type.realbits - 1);
*val = scale_uv / 100000;
@@ -127,12 +127,12 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
[ID_AD7780] = {
.channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('s', 24, 32, 8), 0),
},
[ID_AD7781] = {
.channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
0, 0, IIO_ST('s', 20, 32, 12), 0),
},
};
@@ -272,11 +272,11 @@ static const struct spi_device_id ad7780_id[] = {
{"ad7781", ID_AD7781},
{}
};
+MODULE_DEVICE_TABLE(spi, ad7780_id);
static struct spi_driver ad7780_driver = {
.driver = {
.name = "ad7780",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad7780_probe,
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 1c5588e88cdf..6a058b19c49a 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -20,7 +20,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_sw.h"
#include "../trigger.h"
#include "../trigger_consumer.h"
@@ -316,25 +316,6 @@ out:
return ret;
}
-static int ad7793_scan_from_ring(struct ad7793_state *st, unsigned ch, int *val)
-{
- struct iio_buffer *ring = iio_priv_to_dev(st)->buffer;
- int ret;
- s64 dat64[2];
- u32 *dat32 = (u32 *)dat64;
-
- if (!(test_bit(ch, ring->scan_mask)))
- return -EBUSY;
-
- ret = ring->access->read_last(ring, (u8 *) &dat64);
- if (ret)
- return ret;
-
- *val = *dat32;
-
- return 0;
-}
-
static int ad7793_ring_preenable(struct iio_dev *indio_dev)
{
struct ad7793_state *st = iio_priv(indio_dev);
@@ -342,14 +323,15 @@ static int ad7793_ring_preenable(struct iio_dev *indio_dev)
size_t d_size;
unsigned channel;
- if (!ring->scan_count)
+ if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
- channel = find_first_bit(ring->scan_mask,
+ channel = find_first_bit(indio_dev->active_scan_mask,
indio_dev->masklength);
- d_size = ring->scan_count *
- indio_dev->channels[0].scan_type.storagebits / 8;
+ d_size = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) *
+ indio_dev->channels[0].scan_type.storagebits / 8;
if (ring->scan_timestamp) {
d_size += sizeof(s64);
@@ -411,7 +393,7 @@ static irqreturn_t ad7793_trigger_handler(int irq, void *p)
s64 dat64[2];
s32 *dat32 = (s32 *)dat64;
- if (ring->scan_count)
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
__ad7793_read_reg(st, 1, 1, AD7793_REG_DATA,
dat32,
indio_dev->channels[0].scan_type.realbits/8);
@@ -459,7 +441,7 @@ static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev)
}
/* Ring buffer functions - here trigger setup related */
- indio_dev->buffer->setup_ops = &ad7793_ring_setup_ops;
+ indio_dev->setup_ops = &ad7793_ring_setup_ops;
/* Flag that polled ring buffering is possible */
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
@@ -493,6 +475,10 @@ static irqreturn_t ad7793_data_rdy_trig_poll(int irq, void *private)
return IRQ_HANDLED;
}
+static struct iio_trigger_ops ad7793_trigger_ops = {
+ .owner = THIS_MODULE,
+};
+
static int ad7793_probe_trigger(struct iio_dev *indio_dev)
{
struct ad7793_state *st = iio_priv(indio_dev);
@@ -505,6 +491,7 @@ static int ad7793_probe_trigger(struct iio_dev *indio_dev)
ret = -ENOMEM;
goto error_ret;
}
+ st->trig->ops = &ad7793_trigger_ops;
ret = request_irq(st->spi->irq,
ad7793_data_rdy_trig_poll,
@@ -517,7 +504,6 @@ static int ad7793_probe_trigger(struct iio_dev *indio_dev)
disable_irq_nosync(st->spi->irq);
st->irq_dis = true;
st->trig->dev.parent = &st->spi->dev;
- st->trig->owner = THIS_MODULE;
st->trig->private_data = indio_dev;
ret = iio_trigger_register(st->trig);
@@ -649,8 +635,7 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,
case 0:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
- ret = ad7793_scan_from_ring(st,
- chan->scan_index, &smpl);
+ ret = -EBUSY;
else
ret = ad7793_read(st, chan->address,
chan->scan_type.realbits / 8, &smpl);
@@ -667,19 +652,21 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
- *val = st->scale_avail[(st->conf >> 8) & 0x7][0];
- *val2 = st->scale_avail[(st->conf >> 8) & 0x7][1];
-
- return IIO_VAL_INT_PLUS_NANO;
-
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
- /* 1170mV / 2^23 * 6 */
- scale_uv = (1170ULL * 100000000ULL * 6ULL)
- >> (chan->scan_type.realbits -
- (unipolar ? 0 : 1));
+ if (chan->differential) {
+ *val = st->
+ scale_avail[(st->conf >> 8) & 0x7][0];
+ *val2 = st->
+ scale_avail[(st->conf >> 8) & 0x7][1];
+ return IIO_VAL_INT_PLUS_NANO;
+ } else {
+ /* 1170mV / 2^23 * 6 */
+ scale_uv = (1170ULL * 100000000ULL * 6ULL)
+ >> (chan->scan_type.realbits -
+ (unipolar ? 0 : 1));
+ }
break;
case IIO_TEMP:
/* Always uses unity gain and internal ref */
@@ -716,7 +703,7 @@ static int ad7793_write_raw(struct iio_dev *indio_dev,
}
switch (mask) {
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
ret = -EINVAL;
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
if (val2 == st->scale_avail[i][1]) {
@@ -775,7 +762,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 0,
.channel2 = 0,
.address = AD7793_CH_AIN1P_AIN1M,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 0,
.scan_type = IIO_ST('s', 24, 32, 0)
},
@@ -786,7 +773,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 1,
.channel2 = 1,
.address = AD7793_CH_AIN2P_AIN2M,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 1,
.scan_type = IIO_ST('s', 24, 32, 0)
},
@@ -797,7 +784,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN3P_AIN3M,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('s', 24, 32, 0)
},
@@ -809,7 +796,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN1M_AIN1M,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('s', 24, 32, 0)
},
@@ -818,7 +805,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.indexed = 1,
.channel = 0,
.address = AD7793_CH_TEMP,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 4,
.scan_type = IIO_ST('s', 24, 32, 0),
},
@@ -828,7 +815,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.indexed = 1,
.channel = 4,
.address = AD7793_CH_AVDD_MONITOR,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 5,
.scan_type = IIO_ST('s', 24, 32, 0),
},
@@ -842,7 +829,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 0,
.channel2 = 0,
.address = AD7793_CH_AIN1P_AIN1M,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 0,
.scan_type = IIO_ST('s', 16, 32, 0)
},
@@ -853,7 +840,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 1,
.channel2 = 1,
.address = AD7793_CH_AIN2P_AIN2M,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 1,
.scan_type = IIO_ST('s', 16, 32, 0)
},
@@ -864,7 +851,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN3P_AIN3M,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('s', 16, 32, 0)
},
@@ -876,7 +863,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN1M_AIN1M,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('s', 16, 32, 0)
},
@@ -885,7 +872,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.indexed = 1,
.channel = 0,
.address = AD7793_CH_TEMP,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 4,
.scan_type = IIO_ST('s', 16, 32, 0),
},
@@ -895,7 +882,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.indexed = 1,
.channel = 4,
.address = AD7793_CH_AVDD_MONITOR,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 5,
.scan_type = IIO_ST('s', 16, 32, 0),
},
@@ -1034,11 +1021,11 @@ static const struct spi_device_id ad7793_id[] = {
{"ad7793", ID_AD7793},
{}
};
+MODULE_DEVICE_TABLE(spi, ad7793_id);
static struct spi_driver ad7793_driver = {
.driver = {
.name = "ad7793",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad7793_probe,
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index acbf9363132b..52b720e2b03a 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -18,6 +18,7 @@
#include "../iio.h"
#include "../sysfs.h"
+#include "../events.h"
/*
* AD7816 config masks
@@ -459,7 +460,6 @@ MODULE_DEVICE_TABLE(spi, ad7816_id);
static struct spi_driver ad7816_driver = {
.driver = {
.name = "ad7816",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad7816_probe,
diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h
index 3452d1819077..bc53b6532121 100644
--- a/drivers/staging/iio/adc/ad7887.h
+++ b/drivers/staging/iio/adc/ad7887.h
@@ -83,14 +83,9 @@ enum ad7887_supported_device_ids {
};
#ifdef CONFIG_IIO_BUFFER
-int ad7887_scan_from_ring(struct ad7887_state *st, int channum);
int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void ad7887_ring_cleanup(struct iio_dev *indio_dev);
#else /* CONFIG_IIO_BUFFER */
-static inline int ad7887_scan_from_ring(struct ad7887_state *st, int channum)
-{
- return 0;
-}
static inline int
ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c
index 91b8fb09d92b..e9bbc3eed15d 100644
--- a/drivers/staging/iio/adc/ad7887_core.c
+++ b/drivers/staging/iio/adc/ad7887_core.c
@@ -17,7 +17,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "ad7887.h"
@@ -45,7 +45,7 @@ static int ad7887_read_raw(struct iio_dev *indio_dev,
case 0:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
- ret = ad7887_scan_from_ring(st, 1 << chan->address);
+ ret = -EBUSY;
else
ret = ad7887_scan_direct(st, chan->address);
mutex_unlock(&indio_dev->mlock);
@@ -55,7 +55,7 @@ static int ad7887_read_raw(struct iio_dev *indio_dev,
*val = (ret >> st->chip_info->channel[0].scan_type.shift) &
RES_MASK(st->chip_info->channel[0].scan_type.realbits);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
scale_uv = (st->int_vref_mv * 1000)
>> st->chip_info->channel[0].scan_type.realbits;
*val = scale_uv/1000;
@@ -75,7 +75,7 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = 1,
.scan_index = 1,
.scan_type = IIO_ST('u', 12, 16, 0),
@@ -84,7 +84,7 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = 0,
.scan_index = 0,
.scan_type = IIO_ST('u', 12, 16, 0),
@@ -246,11 +246,11 @@ static const struct spi_device_id ad7887_id[] = {
{"ad7887", ID_AD7887},
{}
};
+MODULE_DEVICE_TABLE(spi, ad7887_id);
static struct spi_driver ad7887_driver = {
.driver = {
.name = "ad7887",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad7887_probe,
@@ -262,4 +262,3 @@ module_spi_driver(ad7887_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD7887 ADC");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:ad7887");
diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c
index cb74cada5611..85076cd962e7 100644
--- a/drivers/staging/iio/adc/ad7887_ring.c
+++ b/drivers/staging/iio/adc/ad7887_ring.c
@@ -13,46 +13,12 @@
#include <linux/spi/spi.h>
#include "../iio.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_sw.h"
#include "../trigger_consumer.h"
#include "ad7887.h"
-int ad7887_scan_from_ring(struct ad7887_state *st, int channum)
-{
- struct iio_buffer *ring = iio_priv_to_dev(st)->buffer;
- int count = 0, ret;
- u16 *ring_data;
-
- if (!(test_bit(channum, ring->scan_mask))) {
- ret = -EBUSY;
- goto error_ret;
- }
-
- ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
- GFP_KERNEL);
- if (ring_data == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- ret = ring->access->read_last(ring, (u8 *) ring_data);
- if (ret)
- goto error_free_ring_data;
-
- /* for single channel scan the result is stored with zero offset */
- if ((test_bit(1, ring->scan_mask) || test_bit(0, ring->scan_mask)) &&
- (channum == 1))
- count = 1;
-
- ret = be16_to_cpu(ring_data[count]);
-
-error_free_ring_data:
- kfree(ring_data);
-error_ret:
- return ret;
-}
-
/**
* ad7887_ring_preenable() setup the parameters of the ring before enabling
*
@@ -65,7 +31,8 @@ static int ad7887_ring_preenable(struct iio_dev *indio_dev)
struct ad7887_state *st = iio_priv(indio_dev);
struct iio_buffer *ring = indio_dev->buffer;
- st->d_size = ring->scan_count *
+ st->d_size = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) *
st->chip_info->channel[0].scan_type.storagebits / 8;
if (ring->scan_timestamp) {
@@ -80,7 +47,7 @@ static int ad7887_ring_preenable(struct iio_dev *indio_dev)
set_bytes_per_datum(indio_dev->buffer, st->d_size);
/* We know this is a single long so can 'cheat' */
- switch (*ring->scan_mask) {
+ switch (*indio_dev->active_scan_mask) {
case (1 << 0):
st->ring_msg = &st->msg[AD7887_CH0];
break;
@@ -121,7 +88,8 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p)
__u8 *buf;
int b_sent;
- unsigned int bytes = ring->scan_count *
+ unsigned int bytes = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) *
st->chip_info->channel[0].scan_type.storagebits / 8;
buf = kzalloc(st->d_size, GFP_KERNEL);
@@ -176,7 +144,7 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
goto error_deallocate_sw_rb;
}
/* Ring buffer functions - here trigger setup related */
- indio_dev->buffer->setup_ops = &ad7887_ring_setup_ops;
+ indio_dev->setup_ops = &ad7887_ring_setup_ops;
/* Flag that polled ring buffering is possible */
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h
index eda01d5bab7d..356f690a76fb 100644
--- a/drivers/staging/iio/adc/ad799x.h
+++ b/drivers/staging/iio/adc/ad799x.h
@@ -124,15 +124,9 @@ struct ad799x_platform_data {
int ad7997_8_set_scan_mode(struct ad799x_state *st, unsigned mask);
#ifdef CONFIG_AD799X_RING_BUFFER
-int ad799x_single_channel_from_ring(struct iio_dev *indio_dev, int channum);
int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void ad799x_ring_cleanup(struct iio_dev *indio_dev);
#else /* CONFIG_AD799X_RING_BUFFER */
-int ad799x_single_channel_from_ring(struct iio_dev *indio_dev, int channum)
-{
- return -EINVAL;
-}
-
static inline int
ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index c0d2f886ea2c..d5b581d8bc2b 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -35,7 +35,8 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../events.h"
+#include "../buffer.h"
#include "ad799x.h"
@@ -150,8 +151,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
case 0:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
- ret = ad799x_single_channel_from_ring(indio_dev,
- chan->scan_index);
+ ret = -EBUSY;
else
ret = ad799x_scan_direct(st, chan->scan_index);
mutex_unlock(&indio_dev->mlock);
@@ -161,7 +161,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
*val = (ret >> chan->scan_type.shift) &
RES_MASK(chan->scan_type.realbits);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
scale_uv = (st->int_vref_mv * 1000) >> chan->scan_type.realbits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
@@ -934,4 +934,3 @@ module_i2c_driver(ad799x_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD799x ADC");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("i2c:ad799x");
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index e3f4698d7815..5dded9e7820a 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -17,42 +17,12 @@
#include <linux/bitops.h>
#include "../iio.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_sw.h"
#include "../trigger_consumer.h"
#include "ad799x.h"
-int ad799x_single_channel_from_ring(struct iio_dev *indio_dev, int channum)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- int count = 0, ret;
- u16 *ring_data;
-
- if (!(test_bit(channum, ring->scan_mask))) {
- ret = -EBUSY;
- goto error_ret;
- }
-
- ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
- GFP_KERNEL);
- if (ring_data == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- ret = ring->access->read_last(ring, (u8 *) ring_data);
- if (ret)
- goto error_free_ring_data;
- /* Need a count of channels prior to this one */
- count = bitmap_weight(ring->scan_mask, channum);
- ret = be16_to_cpu(ring_data[count]);
-
-error_free_ring_data:
- kfree(ring_data);
-error_ret:
- return ret;
-}
-
/**
* ad799x_ring_preenable() setup the parameters of the ring before enabling
*
@@ -71,9 +41,10 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev)
*/
if (st->id == ad7997 || st->id == ad7998)
- ad7997_8_set_scan_mode(st, *ring->scan_mask);
+ ad7997_8_set_scan_mode(st, *indio_dev->active_scan_mask);
- st->d_size = ring->scan_count * 2;
+ st->d_size = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) * 2;
if (ring->scan_timestamp) {
st->d_size += sizeof(s64);
@@ -115,12 +86,13 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
case ad7991:
case ad7995:
case ad7999:
- cmd = st->config | (*ring->scan_mask << AD799X_CHANNEL_SHIFT);
+ cmd = st->config |
+ (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT);
break;
case ad7992:
case ad7993:
case ad7994:
- cmd = (*ring->scan_mask << AD799X_CHANNEL_SHIFT) |
+ cmd = (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT) |
AD7998_CONV_RES_REG;
break;
case ad7997:
@@ -132,7 +104,8 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
}
b_sent = i2c_smbus_read_i2c_block_data(st->client,
- cmd, ring->scan_count * 2, rxbuf);
+ cmd, bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) * 2, rxbuf);
if (b_sent < 0)
goto done;
@@ -183,7 +156,7 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
}
/* Ring buffer functions - here trigger setup related */
- indio_dev->buffer->setup_ops = &ad799x_buf_setup_ops;
+ indio_dev->setup_ops = &ad799x_buf_setup_ops;
indio_dev->buffer->scan_timestamp = true;
/* Flag that polled ring buffering is possible */
diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c
index bc307f3b024e..eec2f325d549 100644
--- a/drivers/staging/iio/adc/adt7310.c
+++ b/drivers/staging/iio/adc/adt7310.c
@@ -17,7 +17,7 @@
#include "../iio.h"
#include "../sysfs.h"
-
+#include "../events.h"
/*
* ADT7310 registers definition
*/
@@ -877,7 +877,6 @@ MODULE_DEVICE_TABLE(spi, adt7310_id);
static struct spi_driver adt7310_driver = {
.driver = {
.name = "adt7310",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = adt7310_probe,
diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
index 3481cf6f7574..c62248ceb37a 100644
--- a/drivers/staging/iio/adc/adt7410.c
+++ b/drivers/staging/iio/adc/adt7410.c
@@ -17,6 +17,7 @@
#include "../iio.h"
#include "../sysfs.h"
+#include "../events.h"
/*
* ADT7410 registers definition
diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h
index cbcb08a2cb50..2cd0112067b2 100644
--- a/drivers/staging/iio/adc/max1363.h
+++ b/drivers/staging/iio/adc/max1363.h
@@ -146,22 +146,22 @@ struct max1363_state {
};
const struct max1363_mode
-*max1363_match_mode(unsigned long *mask, const struct max1363_chip_info *ci);
+*max1363_match_mode(const unsigned long *mask,
+ const struct max1363_chip_info *ci);
int max1363_set_scan_mode(struct max1363_state *st);
#ifdef CONFIG_MAX1363_RING_BUFFER
-
-int max1363_single_channel_from_ring(const long *mask,
- struct max1363_state *st);
+int max1363_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask);
int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void max1363_ring_cleanup(struct iio_dev *indio_dev);
#else /* CONFIG_MAX1363_RING_BUFFER */
-
-int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
+int max1363_update_scan_mode(struct iio_dev *indio_dev,
+ const long *scan_mask)
{
- return -EINVAL;
+ return 0;
}
static inline int
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 3f28f1ab52a2..b92cb4af18ce 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -34,7 +34,8 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../events.h"
+#include "../buffer.h"
#include "max1363.h"
@@ -147,7 +148,8 @@ static const struct max1363_mode max1363_mode_table[] = {
};
const struct max1363_mode
-*max1363_match_mode(unsigned long *mask, const struct max1363_chip_info *ci)
+*max1363_match_mode(const unsigned long *mask,
+const struct max1363_chip_info *ci)
{
int i;
if (mask)
@@ -189,7 +191,6 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
int ret = 0;
s32 data;
char rxbuf[2];
- const unsigned long *mask;
struct max1363_state *st = iio_priv(indio_dev);
struct i2c_client *client = st->client;
@@ -198,46 +199,38 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
* If monitor mode is enabled, the method for reading a single
* channel will have to be rather different and has not yet
* been implemented.
+ *
+ * Also, cannot read directly if buffered capture enabled.
*/
- if (st->monitor_on) {
+ if (st->monitor_on || iio_buffer_enabled(indio_dev)) {
ret = -EBUSY;
goto error_ret;
}
- /* If ring buffer capture is occurring, query the buffer */
- if (iio_buffer_enabled(indio_dev)) {
- mask = max1363_mode_table[chan->address].modemask;
- data = max1363_single_channel_from_ring(mask, st);
+ /* Check to see if current scan mode is correct */
+ if (st->current_mode != &max1363_mode_table[chan->address]) {
+ /* Update scan mode if needed */
+ st->current_mode = &max1363_mode_table[chan->address];
+ ret = max1363_set_scan_mode(st);
+ if (ret < 0)
+ goto error_ret;
+ }
+ if (st->chip_info->bits != 8) {
+ /* Get reading */
+ data = i2c_master_recv(client, rxbuf, 2);
if (data < 0) {
ret = data;
goto error_ret;
}
+ data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8;
} else {
- /* Check to see if current scan mode is correct */
- if (st->current_mode != &max1363_mode_table[chan->address]) {
- /* Update scan mode if needed */
- st->current_mode = &max1363_mode_table[chan->address];
- ret = max1363_set_scan_mode(st);
- if (ret < 0)
- goto error_ret;
- }
- if (st->chip_info->bits != 8) {
- /* Get reading */
- data = i2c_master_recv(client, rxbuf, 2);
- if (data < 0) {
- ret = data;
- goto error_ret;
- }
- data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8;
- } else {
- /* Get reading */
- data = i2c_master_recv(client, rxbuf, 1);
- if (data < 0) {
- ret = data;
- goto error_ret;
- }
- data = rxbuf[0];
+ /* Get reading */
+ data = i2c_master_recv(client, rxbuf, 1);
+ if (data < 0) {
+ ret = data;
+ goto error_ret;
}
+ data = rxbuf[0];
}
*val = data;
error_ret:
@@ -260,7 +253,7 @@ static int max1363_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
if ((1 << (st->chip_info->bits + 1)) >
st->chip_info->int_vref_mv) {
*val = 0;
@@ -288,7 +281,7 @@ 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 (1 << IIO_CHAN_INFO_SCALE_SHARED)
+#define MAX1363_INFO_MASK IIO_CHAN_INFO_SCALE_SHARED_BIT
#define MAX1363_CHAN_U(num, addr, si, bits, evmask) \
{ \
.type = IIO_VOLTAGE, \
@@ -296,7 +289,13 @@ static const enum max1363_modes max1363_mode_list[] = {
.channel = num, \
.address = addr, \
.info_mask = MAX1363_INFO_MASK, \
- .scan_type = IIO_ST('u', bits, (bits > 8) ? 16 : 8, 0), \
+ .datasheet_name = "AIN"#num, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = bits, \
+ .storagebits = (bits > 8) ? 16 : 8, \
+ .endianness = IIO_BE, \
+ }, \
.scan_index = si, \
.event_mask = evmask, \
}
@@ -311,7 +310,13 @@ static const enum max1363_modes max1363_mode_list[] = {
.channel2 = num2, \
.address = addr, \
.info_mask = MAX1363_INFO_MASK, \
- .scan_type = IIO_ST('u', bits, (bits > 8) ? 16 : 8, 0), \
+ .datasheet_name = "AIN"#num"-AIN"#num2, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = bits, \
+ .storagebits = (bits > 8) ? 16 : 8, \
+ .endianness = IIO_BE, \
+ }, \
.scan_index = si, \
.event_mask = evmask, \
}
@@ -833,6 +838,7 @@ static const struct iio_info max1363_info = {
.read_event_config = &max1363_read_event_config,
.write_event_config = &max1363_write_event_config,
.read_raw = &max1363_read_raw,
+ .update_scan_mode = &max1363_update_scan_mode,
.driver_module = THIS_MODULE,
.event_attrs = &max1363_event_attribute_group,
};
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index df6893e058cc..f730b3fb971a 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -15,88 +15,25 @@
#include <linux/bitops.h>
#include "../iio.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_sw.h"
#include "../trigger_consumer.h"
#include "max1363.h"
-int max1363_single_channel_from_ring(const long *mask, struct max1363_state *st)
-{
- struct iio_buffer *ring = iio_priv_to_dev(st)->buffer;
- int count = 0, ret, index;
- u8 *ring_data;
- index = find_first_bit(mask, MAX1363_MAX_CHANNELS);
-
- if (!(test_bit(index, st->current_mode->modemask))) {
- ret = -EBUSY;
- goto error_ret;
- }
-
- ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
- GFP_KERNEL);
- if (ring_data == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- ret = ring->access->read_last(ring, ring_data);
- if (ret)
- goto error_free_ring_data;
- /* Need a count of channels prior to this one */
-
- count = bitmap_weight(mask, index - 1);
- if (st->chip_info->bits != 8)
- ret = ((int)(ring_data[count*2 + 0] & 0x0F) << 8)
- + (int)(ring_data[count*2 + 1]);
- else
- ret = ring_data[count];
-
-error_free_ring_data:
- kfree(ring_data);
-error_ret:
- return ret;
-}
-
-
-/**
- * max1363_ring_preenable() - setup the parameters of the ring before enabling
- *
- * The complex nature of the setting of the nuber of bytes per datum is due
- * to this driver currently ensuring that the timestamp is stored at an 8
- * byte boundary.
- **/
-static int max1363_ring_preenable(struct iio_dev *indio_dev)
+int max1363_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
{
struct max1363_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- size_t d_size = 0;
- unsigned long numvals;
/*
* Need to figure out the current mode based upon the requested
* scan mask in iio_dev
*/
- st->current_mode = max1363_match_mode(ring->scan_mask,
- st->chip_info);
+ st->current_mode = max1363_match_mode(scan_mask, st->chip_info);
if (!st->current_mode)
return -EINVAL;
-
max1363_set_scan_mode(st);
-
- numvals = bitmap_weight(st->current_mode->modemask,
- indio_dev->masklength);
- if (ring->access->set_bytes_per_datum) {
- if (ring->scan_timestamp)
- d_size += sizeof(s64);
- if (st->chip_info->bits != 8)
- d_size += numvals*2;
- else
- d_size += numvals;
- if (ring->scan_timestamp && (d_size % 8))
- d_size += 8 - (d_size % 8);
- ring->access->set_bytes_per_datum(ring, d_size);
- }
-
return 0;
}
@@ -114,12 +51,14 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
/* Ensure the timestamp is 8 byte aligned */
if (st->chip_info->bits != 8)
- d_size = numvals*2 + sizeof(s64);
+ d_size = numvals*2;
else
- d_size = numvals + sizeof(s64);
- if (d_size % sizeof(s64))
- d_size += sizeof(s64) - (d_size % sizeof(s64));
-
+ d_size = numvals;
+ if (indio_dev->buffer->scan_timestamp) {
+ d_size += sizeof(s64);
+ if (d_size % sizeof(s64))
+ d_size += sizeof(s64) - (d_size % sizeof(s64));
+ }
/* Monitor mode prevents reading. Whilst not currently implemented
* might as well have this test in here in the meantime as it does
* no harm.
@@ -139,9 +78,10 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
time_ns = iio_get_time_ns();
- memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
+ if (indio_dev->buffer->scan_timestamp)
+ memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
+ iio_push_to_buffer(indio_dev->buffer, rxbuf, time_ns);
- indio_dev->buffer->access->store_to(indio_dev->buffer, rxbuf, time_ns);
done:
iio_trigger_notify_done(indio_dev->trig);
kfree(rxbuf);
@@ -151,7 +91,7 @@ done:
static const struct iio_buffer_setup_ops max1363_ring_setup_ops = {
.postenable = &iio_triggered_buffer_postenable,
- .preenable = &max1363_ring_preenable,
+ .preenable = &iio_sw_buffer_preenable,
.predisable = &iio_triggered_buffer_predisable,
};
@@ -179,7 +119,7 @@ int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
/* Effectively select the ring buffer implementation */
indio_dev->buffer->access = &ring_sw_access_funcs;
/* Ring buffer functions - here trigger setup related */
- indio_dev->buffer->setup_ops = &max1363_ring_setup_ops;
+ indio_dev->setup_ops = &max1363_ring_setup_ops;
/* Flag that polled ring buffering is possible */
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c
index 1e93c7b7aed9..1ea3cd06299d 100644
--- a/drivers/staging/iio/addac/adt7316-spi.c
+++ b/drivers/staging/iio/addac/adt7316-spi.c
@@ -151,7 +151,6 @@ static int adt7316_spi_resume(struct spi_device *spi_dev)
static struct spi_driver adt7316_driver = {
.driver = {
.name = "adt7316",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = adt7316_spi_probe,
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index 8df24704ff26..13c39292d3f2 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include "../iio.h"
+#include "../events.h"
#include "../sysfs.h"
#include "adt7316.h"
diff --git a/drivers/staging/iio/buffer_generic.h b/drivers/staging/iio/buffer.h
index 9e8f01009979..6fb6e64181a5 100644
--- a/drivers/staging/iio/buffer_generic.h
+++ b/drivers/staging/iio/buffer.h
@@ -11,7 +11,6 @@
#define _IIO_BUFFER_GENERIC_H_
#include <linux/sysfs.h>
#include "iio.h"
-#include "chrdev.h"
#ifdef CONFIG_IIO_BUFFER
@@ -19,22 +18,14 @@ struct iio_buffer;
/**
* struct iio_buffer_access_funcs - access functions for buffers.
- * @mark_in_use: reference counting, typically to prevent module removal
- * @unmark_in_use: reduce reference count when no longer using buffer
* @store_to: actually store stuff to the buffer
- * @read_last: get the last element stored
- * @read_first_n: try to get a specified number of elements (must exist)
- * @mark_param_change: notify buffer that some relevant parameter has changed
- * Often this means the underlying storage may need to
- * change.
+ * @read_first_n: try to get a specified number of bytes (must exist)
* @request_update: if a parameter change has been marked, update underlying
* storage.
* @get_bytes_per_datum:get current bytes per datum
* @set_bytes_per_datum:set number of bytes per datum
* @get_length: get number of datums in buffer
* @set_length: set number of datums in buffer
- * @is_enabled: query if buffer is currently being used
- * @enable: enable the buffer
*
* The purpose of this structure is to make the buffer element
* modular as event for a given driver, different usecases may require
@@ -45,85 +36,60 @@ struct iio_buffer;
* any of them not existing.
**/
struct iio_buffer_access_funcs {
- void (*mark_in_use)(struct iio_buffer *buffer);
- void (*unmark_in_use)(struct iio_buffer *buffer);
-
int (*store_to)(struct iio_buffer *buffer, u8 *data, s64 timestamp);
- int (*read_last)(struct iio_buffer *buffer, u8 *data);
int (*read_first_n)(struct iio_buffer *buffer,
size_t n,
char __user *buf);
- int (*mark_param_change)(struct iio_buffer *buffer);
int (*request_update)(struct iio_buffer *buffer);
int (*get_bytes_per_datum)(struct iio_buffer *buffer);
int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd);
int (*get_length)(struct iio_buffer *buffer);
int (*set_length)(struct iio_buffer *buffer, int length);
-
- int (*is_enabled)(struct iio_buffer *buffer);
- int (*enable)(struct iio_buffer *buffer);
-};
-
-/**
- * struct iio_buffer_setup_ops - buffer setup related callbacks
- * @preenable: [DRIVER] function to run prior to marking buffer enabled
- * @postenable: [DRIVER] function to run after marking buffer enabled
- * @predisable: [DRIVER] function to run prior to marking buffer
- * disabled
- * @postdisable: [DRIVER] function to run after marking buffer disabled
- */
-struct iio_buffer_setup_ops {
- int (*preenable)(struct iio_dev *);
- int (*postenable)(struct iio_dev *);
- int (*predisable)(struct iio_dev *);
- int (*postdisable)(struct iio_dev *);
};
/**
* struct iio_buffer - general buffer structure
- * @indio_dev: industrial I/O device structure
- * @owner: module that owns the buffer (for ref counting)
* @length: [DEVICE] number of datums in buffer
* @bytes_per_datum: [DEVICE] size of individual datum including timestamp
- * @bpe: [DEVICE] size of individual channel value
* @scan_el_attrs: [DRIVER] control of scan elements if that scan mode
* control method is used
- * @scan_count: [INTERN] the number of elements in the current scan mode
* @scan_mask: [INTERN] bitmask used in masking scan mode elements
+ * @scan_index_timestamp:[INTERN] cache of the index to the timestamp
* @scan_timestamp: [INTERN] does the scan mode include a timestamp
* @access: [DRIVER] buffer access functions associated with the
* implementation.
- * @flags: [INTERN] file ops related flags including busy flag.
+ * @scan_el_dev_attr_list:[INTERN] list of scan element related attributes.
+ * @scan_el_group: [DRIVER] attribute group for those attributes not
+ * created from the iio_chan_info array.
+ * @pollq: [INTERN] wait queue to allow for polling on the buffer.
+ * @stufftoread: [INTERN] flag to indicate new data.
+ * @demux_list: [INTERN] list of operations required to demux the scan.
+ * @demux_bounce: [INTERN] buffer for doing gather from incoming scan.
**/
struct iio_buffer {
- struct iio_dev *indio_dev;
- struct module *owner;
int length;
int bytes_per_datum;
- int bpe;
struct attribute_group *scan_el_attrs;
- int scan_count;
long *scan_mask;
bool scan_timestamp;
+ unsigned scan_index_timestamp;
const struct iio_buffer_access_funcs *access;
- const struct iio_buffer_setup_ops *setup_ops;
struct list_head scan_el_dev_attr_list;
struct attribute_group scan_el_group;
wait_queue_head_t pollq;
bool stufftoread;
- unsigned long flags;
const struct attribute_group *attrs;
+ struct list_head demux_list;
+ unsigned char *demux_bounce;
};
/**
* iio_buffer_init() - Initialize the buffer structure
* @buffer: buffer to be initialized
- * @indio_dev: the iio device the buffer is assocated with
**/
-void iio_buffer_init(struct iio_buffer *buffer,
- struct iio_dev *indio_dev);
+void iio_buffer_init(struct iio_buffer *buffer);
void iio_buffer_deinit(struct iio_buffer *buffer);
@@ -140,17 +106,27 @@ static inline void __iio_update_buffer(struct iio_buffer *buffer,
buffer->length = length;
}
-int iio_scan_mask_query(struct iio_buffer *buffer, int bit);
+int iio_scan_mask_query(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer, int bit);
/**
* iio_scan_mask_set() - set particular bit in the scan mask
* @buffer: the buffer whose scan mask we are interested in
* @bit: the bit to be set.
**/
-int iio_scan_mask_set(struct iio_buffer *buffer, int bit);
+int iio_scan_mask_set(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer, int bit);
-#define to_iio_buffer(d) \
- container_of(d, struct iio_buffer, dev)
+/**
+ * iio_push_to_buffer() - push to a registered buffer.
+ * @buffer: IIO buffer structure for device
+ * @scan: Full scan.
+ * @timestamp:
+ */
+int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
+ s64 timestamp);
+
+int iio_update_demux(struct iio_dev *indio_dev);
/**
* iio_buffer_register() - register the buffer with IIO core
@@ -180,12 +156,6 @@ ssize_t iio_buffer_write_length(struct device *dev,
const char *buf,
size_t len);
/**
- * iio_buffer_read_bytes_per_datum() - attr for number of bytes in whole datum
- **/
-ssize_t iio_buffer_read_bytes_per_datum(struct device *dev,
- struct device_attribute *attr,
- char *buf);
-/**
* iio_buffer_store_enable() - attr to turn the buffer on
**/
ssize_t iio_buffer_store_enable(struct device *dev,
@@ -201,9 +171,6 @@ ssize_t iio_buffer_show_enable(struct device *dev,
#define IIO_BUFFER_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \
iio_buffer_read_length, \
iio_buffer_write_length)
-#define IIO_BUFFER_BYTES_PER_DATUM_ATTR \
- DEVICE_ATTR(bytes_per_datum, S_IRUGO | S_IWUSR, \
- iio_buffer_read_bytes_per_datum, NULL)
#define IIO_BUFFER_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \
iio_buffer_show_enable, \
diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c
index 47181875e113..b73007dcf4b3 100644
--- a/drivers/staging/iio/cdc/ad7150.c
+++ b/drivers/staging/iio/cdc/ad7150.c
@@ -15,7 +15,7 @@
#include "../iio.h"
#include "../sysfs.h"
-
+#include "../events.h"
/*
* AD7150 registers definition
*/
@@ -111,7 +111,7 @@ static int ad7150_read_raw(struct iio_dev *indio_dev,
return ret;
*val = swab16(ret);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE):
+ case IIO_CHAN_INFO_AVERAGE_RAW:
ret = i2c_smbus_read_word_data(chip->client,
ad7150_addresses[chan->channel][1]);
if (ret < 0)
@@ -429,7 +429,7 @@ static const struct iio_chan_spec ad7150_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT,
.event_mask =
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) |
@@ -441,7 +441,7 @@ static const struct iio_chan_spec ad7150_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 1,
- .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT,
.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/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
index 152d3be6d97d..fdb83c35e6dd 100644
--- a/drivers/staging/iio/cdc/ad7152.c
+++ b/drivers/staging/iio/cdc/ad7152.c
@@ -259,7 +259,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
if (val != 1) {
ret = -EINVAL;
goto out;
@@ -276,7 +276,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev,
ret = 0;
break;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
if ((val < 0) | (val > 0xFFFF)) {
ret = -EINVAL;
goto out;
@@ -289,7 +289,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev,
ret = 0;
break;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
if (val != 0) {
ret = -EINVAL;
goto out;
@@ -372,7 +372,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT;
break;
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
ret = i2c_smbus_read_word_data(chip->client,
ad7152_addresses[chan->channel][AD7152_GAIN]);
@@ -384,7 +384,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT_PLUS_MICRO;
break;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
ret = i2c_smbus_read_word_data(chip->client,
ad7152_addresses[chan->channel][AD7152_OFFS]);
if (ret < 0)
@@ -393,7 +393,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT;
break;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
ret = i2c_smbus_read_byte_data(chip->client,
ad7152_addresses[chan->channel][AD7152_SETUP]);
if (ret < 0)
@@ -416,7 +416,7 @@ static int ad7152_write_raw_get_fmt(struct iio_dev *indio_dev,
long mask)
{
switch (mask) {
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
return IIO_VAL_INT_PLUS_NANO;
default:
return IIO_VAL_INT_PLUS_MICRO;
@@ -436,34 +436,34 @@ static const struct iio_chan_spec ad7152_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}, {
.type = IIO_CAPACITANCE,
.differential = 1,
.indexed = 1,
.channel = 0,
.channel2 = 2,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}, {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 1,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}, {
.type = IIO_CAPACITANCE,
.differential = 1,
.indexed = 1,
.channel = 1,
.channel2 = 3,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}
};
/*
diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c
index 9df590891a69..40b8512cbc32 100644
--- a/drivers/staging/iio/cdc/ad7746.c
+++ b/drivers/staging/iio/cdc/ad7746.c
@@ -123,7 +123,7 @@ static const struct iio_chan_spec ad7746_channels[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = AD7746_REG_VT_DATA_HIGH << 8 |
AD7746_VTSETUP_VTMD_EXT_VIN,
},
@@ -132,7 +132,7 @@ static const struct iio_chan_spec ad7746_channels[] = {
.indexed = 1,
.channel = 1,
.extend_name = "supply",
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = AD7746_REG_VT_DATA_HIGH << 8 |
AD7746_VTSETUP_VTMD_VDD_MON,
},
@@ -156,10 +156,10 @@ static const struct iio_chan_spec ad7746_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) |
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = AD7746_REG_CAP_DATA_HIGH << 8,
},
[CIN1_DIFF] = {
@@ -168,10 +168,10 @@ static const struct iio_chan_spec ad7746_channels[] = {
.indexed = 1,
.channel = 0,
.channel2 = 2,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) |
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = AD7746_REG_CAP_DATA_HIGH << 8 |
AD7746_CAPSETUP_CAPDIFF
},
@@ -179,10 +179,10 @@ static const struct iio_chan_spec ad7746_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 1,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) |
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = AD7746_REG_CAP_DATA_HIGH << 8 |
AD7746_CAPSETUP_CIN2,
},
@@ -192,10 +192,10 @@ static const struct iio_chan_spec ad7746_channels[] = {
.indexed = 1,
.channel = 1,
.channel2 = 3,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) |
- (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) |
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = AD7746_REG_CAP_DATA_HIGH << 8 |
AD7746_CAPSETUP_CAPDIFF | AD7746_CAPSETUP_CIN2,
}
@@ -477,7 +477,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
if (val != 1) {
ret = -EINVAL;
goto out;
@@ -503,7 +503,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev,
ret = 0;
break;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED):
+ case IIO_CHAN_INFO_CALIBBIAS:
if ((val < 0) | (val > 0xFFFF)) {
ret = -EINVAL;
goto out;
@@ -515,7 +515,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev,
ret = 0;
break;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
if ((val < 0) | (val > 43008000)) { /* 21pF */
ret = -EINVAL;
goto out;
@@ -612,7 +612,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT;
break;
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
switch (chan->type) {
case IIO_CAPACITANCE:
reg = AD7746_REG_CAP_GAINH;
@@ -634,7 +634,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT_PLUS_MICRO;
break;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED):
+ case IIO_CHAN_INFO_CALIBBIAS:
ret = i2c_smbus_read_word_data(chip->client,
AD7746_REG_CAP_OFFH);
if (ret < 0)
@@ -643,13 +643,13 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT;
break;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
*val = AD7746_CAPDAC_DACP(chip->capdac[chan->channel]
[chan->differential]) * 338646;
ret = IIO_VAL_INT;
break;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_CAPACITANCE:
/* 8.192pf / 2^24 */
diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h
deleted file mode 100644
index d8e736f60522..000000000000
--- a/drivers/staging/iio/chrdev.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* The industrial I/O core - character device related
- *
- * Copyright (c) 2008 Jonathan Cameron
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#ifndef _IIO_CHRDEV_H_
-#define _IIO_CHRDEV_H_
-
-/**
- * struct iio_event_data - The actual event being pushed to userspace
- * @id: event identifier
- * @timestamp: best estimate of time of event occurrence (often from
- * the interrupt handler)
- */
-struct iio_event_data {
- u64 id;
- s64 timestamp;
-};
-
-#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int)
-#endif
diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig
index fac8549dc8e7..13e27979df24 100644
--- a/drivers/staging/iio/dac/Kconfig
+++ b/drivers/staging/iio/dac/Kconfig
@@ -24,6 +24,29 @@ config AD5360
To compile this driver as module choose M here: the module will be called
ad5360.
+config AD5380
+ tristate "Analog Devices AD5380/81/82/83/84/90/91/92 DAC driver"
+ depends on (SPI_MASTER || I2C)
+ select REGMAP_I2C if I2C
+ select REGMAP_SPI if SPI_MASTER
+ help
+ Say yes here to build support for Analog Devices AD5380, AD5381,
+ AD5382, AD5383, AD5384, AD5390, AD5391, AD5392 multi-channel
+ Digital to Analog Converters (DAC).
+
+ To compile this driver as module choose M here: the module will be called
+ ad5380.
+
+config AD5421
+ tristate "Analog Devices AD5421 DAC driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices AD5421 loop-powered
+ digital-to-analog convertors (DAC).
+
+ To compile this driver as module choose M here: the module will be called
+ ad5421.
+
config AD5624R_SPI
tristate "Analog Devices AD5624/44/64R DAC spi driver"
depends on SPI
@@ -37,7 +60,7 @@ config AD5446
help
Say yes here to build support for Analog Devices AD5444, AD5446,
AD5512A, AD5542A, AD5543, AD5553, AD5601, AD5611, AD5620, AD5621,
- AD5640, AD5660 DACs.
+ AD5640, AD5660, AD5662 DACs.
To compile this driver as a module, choose M here: the
module will be called ad5446.
@@ -52,12 +75,22 @@ config AD5504
To compile this driver as a module, choose M here: the
module will be called ad5504.
+config AD5764
+ tristate "Analog Devices AD5764/64R/44/44R DAC driver"
+ depends on SPI_MASTER
+ help
+ Say yes here to build support for Analog Devices AD5764, AD5764R, AD5744,
+ AD5744R Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5764.
+
config AD5791
- tristate "Analog Devices AD5760/AD5780/AD5781/AD5791 DAC SPI driver"
+ tristate "Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC SPI driver"
depends on SPI
help
Say yes here to build support for Analog Devices AD5760, AD5780,
- AD5781, AD5791 High Resolution Voltage Output Digital to
+ AD5781, AD5790, AD5791 High Resolution Voltage Output Digital to
Analog Converter.
To compile this driver as a module, choose M here: the
diff --git a/drivers/staging/iio/dac/Makefile b/drivers/staging/iio/dac/Makefile
index 07b6f5ebdb52..8ab1d264aab7 100644
--- a/drivers/staging/iio/dac/Makefile
+++ b/drivers/staging/iio/dac/Makefile
@@ -3,10 +3,13 @@
#
obj-$(CONFIG_AD5360) += ad5360.o
+obj-$(CONFIG_AD5380) += ad5380.o
+obj-$(CONFIG_AD5421) += ad5421.o
obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o
obj-$(CONFIG_AD5064) += ad5064.o
obj-$(CONFIG_AD5504) += ad5504.o
obj-$(CONFIG_AD5446) += ad5446.o
+obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_MAX517) += max517.o
diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c
index 39cfe6cb02a2..049a855039c2 100644
--- a/drivers/staging/iio/dac/ad5064.c
+++ b/drivers/staging/iio/dac/ad5064.c
@@ -91,7 +91,7 @@ enum ad5064_type {
.indexed = 1, \
.output = 1, \
.channel = (chan), \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.address = AD5064_ADDR_DAC(chan), \
.scan_type = IIO_ST('u', (bits), 16, 20 - (bits)) \
}
@@ -280,14 +280,14 @@ static int ad5064_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad5064_state *st = iio_priv(indio_dev);
- unsigned long scale_uv;
unsigned int vref;
+ int scale_uv;
switch (m) {
case 0:
*val = st->dac_cache[chan->channel];
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
vref = st->chip_info->shared_vref ? 0 : chan->channel;
scale_uv = regulator_get_voltage(st->vref_reg[vref].consumer);
if (scale_uv < 0)
diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c
index bc0459e32d04..710b256affcc 100644
--- a/drivers/staging/iio/dac/ad5360.c
+++ b/drivers/staging/iio/dac/ad5360.c
@@ -103,10 +103,10 @@ enum ad5360_type {
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | \
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | \
- (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
.scan_type = IIO_ST('u', (bits), 16, 16 - (bits)) \
}
@@ -326,21 +326,21 @@ static int ad5360_write_raw(struct iio_dev *indio_dev,
return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA,
chan->address, val, chan->scan_type.shift);
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
if (val >= max_val || val < 0)
return -EINVAL;
return ad5360_write(indio_dev, AD5360_CMD_WRITE_OFFSET,
chan->address, val, chan->scan_type.shift);
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
if (val >= max_val || val < 0)
return -EINVAL;
return ad5360_write(indio_dev, AD5360_CMD_WRITE_GAIN,
chan->address, val, chan->scan_type.shift);
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
if (val <= -max_val || val > 0)
return -EINVAL;
@@ -371,8 +371,8 @@ static int ad5360_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad5360_state *st = iio_priv(indio_dev);
- unsigned long scale_uv;
unsigned int ofs_index;
+ int scale_uv;
int ret;
switch (m) {
@@ -383,7 +383,7 @@ static int ad5360_read_raw(struct iio_dev *indio_dev,
return ret;
*val = ret >> chan->scan_type.shift;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
/* vout = 4 * vref * dac_code */
scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100;
if (scale_uv < 0)
@@ -393,21 +393,21 @@ static int ad5360_read_raw(struct iio_dev *indio_dev,
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET,
chan->address);
if (ret < 0)
return ret;
*val = ret;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
ret = ad5360_read(indio_dev, AD5360_READBACK_GAIN,
chan->address);
if (ret < 0)
return ret;
*val = ret;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
ofs_index = ad5360_get_channel_vref_index(st, chan->channel);
ret = ad5360_read(indio_dev, AD5360_READBACK_SF,
AD5360_REG_SF_OFS(ofs_index));
diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/staging/iio/dac/ad5380.c
new file mode 100644
index 000000000000..eff97ae05c4b
--- /dev/null
+++ b/drivers/staging/iio/dac/ad5380.c
@@ -0,0 +1,676 @@
+/*
+ * Analog devices AD5380, AD5381, AD5382, AD5383, AD5390, AD5391, AD5392
+ * multi-channel Digital to Analog Converters driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "dac.h"
+
+
+#define AD5380_REG_DATA(x) (((x) << 2) | 3)
+#define AD5380_REG_OFFSET(x) (((x) << 2) | 2)
+#define AD5380_REG_GAIN(x) (((x) << 2) | 1)
+#define AD5380_REG_SF_PWR_DOWN (8 << 2)
+#define AD5380_REG_SF_PWR_UP (9 << 2)
+#define AD5380_REG_SF_CTRL (12 << 2)
+
+#define AD5380_CTRL_PWR_DOWN_MODE_OFFSET 13
+#define AD5380_CTRL_INT_VREF_2V5 BIT(12)
+#define AD5380_CTRL_INT_VREF_EN BIT(10)
+
+/**
+ * struct ad5380_chip_info - chip specific information
+ * @channel_template: channel specification template
+ * @num_channels: number of channels
+ * @int_vref: internal vref in uV
+*/
+
+struct ad5380_chip_info {
+ struct iio_chan_spec channel_template;
+ unsigned int num_channels;
+ unsigned int int_vref;
+};
+
+/**
+ * struct ad5380_state - driver instance specific data
+ * @regmap: regmap instance used by the device
+ * @chip_info: chip model specific constants, available modes etc
+ * @vref_reg: vref supply regulator
+ * @vref: actual reference voltage used in uA
+ * @pwr_down: whether the chip is currently in power down mode
+ */
+
+struct ad5380_state {
+ struct regmap *regmap;
+ const struct ad5380_chip_info *chip_info;
+ struct regulator *vref_reg;
+ int vref;
+ bool pwr_down;
+};
+
+enum ad5380_type {
+ ID_AD5380_3,
+ ID_AD5380_5,
+ ID_AD5381_3,
+ ID_AD5381_5,
+ ID_AD5382_3,
+ ID_AD5382_5,
+ ID_AD5383_3,
+ ID_AD5383_5,
+ ID_AD5390_3,
+ ID_AD5390_5,
+ ID_AD5391_3,
+ ID_AD5391_5,
+ ID_AD5392_3,
+ ID_AD5392_5,
+};
+
+#define AD5380_CHANNEL(_bits) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .output = 1, \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
+ .scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)) \
+}
+
+static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
+ [ID_AD5380_3] = {
+ .channel_template = AD5380_CHANNEL(14),
+ .num_channels = 40,
+ .int_vref = 1250000,
+ },
+ [ID_AD5380_5] = {
+ .channel_template = AD5380_CHANNEL(14),
+ .num_channels = 40,
+ .int_vref = 2500000,
+ },
+ [ID_AD5381_3] = {
+ .channel_template = AD5380_CHANNEL(12),
+ .num_channels = 16,
+ .int_vref = 1250000,
+ },
+ [ID_AD5381_5] = {
+ .channel_template = AD5380_CHANNEL(12),
+ .num_channels = 16,
+ .int_vref = 2500000,
+ },
+ [ID_AD5382_3] = {
+ .channel_template = AD5380_CHANNEL(14),
+ .num_channels = 32,
+ .int_vref = 1250000,
+ },
+ [ID_AD5382_5] = {
+ .channel_template = AD5380_CHANNEL(14),
+ .num_channels = 32,
+ .int_vref = 2500000,
+ },
+ [ID_AD5383_3] = {
+ .channel_template = AD5380_CHANNEL(12),
+ .num_channels = 32,
+ .int_vref = 1250000,
+ },
+ [ID_AD5383_5] = {
+ .channel_template = AD5380_CHANNEL(12),
+ .num_channels = 32,
+ .int_vref = 2500000,
+ },
+ [ID_AD5390_3] = {
+ .channel_template = AD5380_CHANNEL(14),
+ .num_channels = 16,
+ .int_vref = 1250000,
+ },
+ [ID_AD5390_5] = {
+ .channel_template = AD5380_CHANNEL(14),
+ .num_channels = 16,
+ .int_vref = 2500000,
+ },
+ [ID_AD5391_3] = {
+ .channel_template = AD5380_CHANNEL(12),
+ .num_channels = 16,
+ .int_vref = 1250000,
+ },
+ [ID_AD5391_5] = {
+ .channel_template = AD5380_CHANNEL(12),
+ .num_channels = 16,
+ .int_vref = 2500000,
+ },
+ [ID_AD5392_3] = {
+ .channel_template = AD5380_CHANNEL(14),
+ .num_channels = 8,
+ .int_vref = 1250000,
+ },
+ [ID_AD5392_5] = {
+ .channel_template = AD5380_CHANNEL(14),
+ .num_channels = 8,
+ .int_vref = 2500000,
+ },
+};
+
+static ssize_t ad5380_read_dac_powerdown(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5380_state *st = iio_priv(indio_dev);
+
+ return sprintf(buf, "%d\n", st->pwr_down);
+}
+
+static ssize_t ad5380_write_dac_powerdown(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5380_state *st = iio_priv(indio_dev);
+ bool pwr_down;
+ int ret;
+
+ ret = strtobool(buf, &pwr_down);
+ if (ret)
+ return ret;
+
+ mutex_lock(&indio_dev->mlock);
+
+ if (pwr_down)
+ ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_DOWN, 0);
+ else
+ ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_UP, 0);
+
+ st->pwr_down = pwr_down;
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret ? ret : len;
+}
+
+static IIO_DEVICE_ATTR(out_voltage_powerdown,
+ S_IRUGO | S_IWUSR,
+ ad5380_read_dac_powerdown,
+ ad5380_write_dac_powerdown, 0);
+
+static const char ad5380_powerdown_modes[][15] = {
+ [0] = "100kohm_to_gnd",
+ [1] = "three_state",
+};
+
+static ssize_t ad5380_read_powerdown_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5380_state *st = iio_priv(indio_dev);
+ unsigned int mode;
+ int ret;
+
+ ret = regmap_read(st->regmap, AD5380_REG_SF_CTRL, &mode);
+ if (ret)
+ return ret;
+
+ mode = (mode >> AD5380_CTRL_PWR_DOWN_MODE_OFFSET) & 1;
+
+ return sprintf(buf, "%s\n", ad5380_powerdown_modes[mode]);
+}
+
+static ssize_t ad5380_write_powerdown_mode(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5380_state *st = iio_priv(indio_dev);
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(ad5380_powerdown_modes); ++i) {
+ if (sysfs_streq(buf, ad5380_powerdown_modes[i]))
+ break;
+ }
+
+ if (i == ARRAY_SIZE(ad5380_powerdown_modes))
+ return -EINVAL;
+
+ ret = regmap_update_bits(st->regmap, AD5380_REG_SF_CTRL,
+ 1 << AD5380_CTRL_PWR_DOWN_MODE_OFFSET,
+ i << AD5380_CTRL_PWR_DOWN_MODE_OFFSET);
+
+ return ret ? ret : len;
+}
+
+static IIO_DEVICE_ATTR(out_voltage_powerdown_mode,
+ S_IRUGO | S_IWUSR,
+ ad5380_read_powerdown_mode,
+ ad5380_write_powerdown_mode, 0);
+
+static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
+ "100kohm_to_gnd three_state");
+
+static struct attribute *ad5380_attributes[] = {
+ &iio_dev_attr_out_voltage_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group ad5380_attribute_group = {
+ .attrs = ad5380_attributes,
+};
+
+static unsigned int ad5380_info_to_reg(struct iio_chan_spec const *chan,
+ long info)
+{
+ switch (info) {
+ case 0:
+ return AD5380_REG_DATA(chan->address);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return AD5380_REG_OFFSET(chan->address);
+ case IIO_CHAN_INFO_CALIBSCALE:
+ return AD5380_REG_GAIN(chan->address);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int ad5380_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2, long info)
+{
+ const unsigned int max_val = (1 << chan->scan_type.realbits);
+ struct ad5380_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case 0:
+ case IIO_CHAN_INFO_CALIBSCALE:
+ if (val >= max_val || val < 0)
+ return -EINVAL;
+
+ return regmap_write(st->regmap,
+ ad5380_info_to_reg(chan, info),
+ val << chan->scan_type.shift);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ val += (1 << chan->scan_type.realbits) / 2;
+ if (val >= max_val || val < 0)
+ return -EINVAL;
+
+ return regmap_write(st->regmap,
+ AD5380_REG_OFFSET(chan->address),
+ val << chan->scan_type.shift);
+ default:
+ break;
+ }
+ return -EINVAL;
+}
+
+static int ad5380_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val, int *val2, long info)
+{
+ struct ad5380_state *st = iio_priv(indio_dev);
+ unsigned long scale_uv;
+ int ret;
+
+ switch (info) {
+ case 0:
+ case IIO_CHAN_INFO_CALIBSCALE:
+ ret = regmap_read(st->regmap, ad5380_info_to_reg(chan, info),
+ val);
+ if (ret)
+ return ret;
+ *val >>= chan->scan_type.shift;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ ret = regmap_read(st->regmap, AD5380_REG_OFFSET(chan->address),
+ val);
+ if (ret)
+ return ret;
+ *val >>= chan->scan_type.shift;
+ val -= (1 << chan->scan_type.realbits) / 2;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ scale_uv = ((2 * st->vref) >> chan->scan_type.realbits) * 100;
+ *val = scale_uv / 100000;
+ *val2 = (scale_uv % 100000) * 10;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info ad5380_info = {
+ .read_raw = ad5380_read_raw,
+ .write_raw = ad5380_write_raw,
+ .attrs = &ad5380_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev)
+{
+ struct ad5380_state *st = iio_priv(indio_dev);
+ struct iio_chan_spec *channels;
+ unsigned int i;
+
+ channels = kcalloc(sizeof(struct iio_chan_spec),
+ st->chip_info->num_channels, GFP_KERNEL);
+
+ if (!channels)
+ return -ENOMEM;
+
+ for (i = 0; i < st->chip_info->num_channels; ++i) {
+ channels[i] = st->chip_info->channel_template;
+ channels[i].channel = i;
+ channels[i].address = i;
+ }
+
+ indio_dev->channels = channels;
+
+ return 0;
+}
+
+static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap,
+ enum ad5380_type type, const char *name)
+{
+ struct iio_dev *indio_dev;
+ struct ad5380_state *st;
+ unsigned int ctrl = 0;
+ int ret;
+
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
+ dev_err(dev, "Failed to allocate iio device\n");
+ ret = -ENOMEM;
+ goto error_regmap_exit;
+ }
+
+ st = iio_priv(indio_dev);
+ dev_set_drvdata(dev, indio_dev);
+
+ st->chip_info = &ad5380_chip_info_tbl[type];
+ st->regmap = regmap;
+
+ indio_dev->dev.parent = dev;
+ indio_dev->name = name;
+ indio_dev->info = &ad5380_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->num_channels = st->chip_info->num_channels;
+
+ ret = ad5380_alloc_channels(indio_dev);
+ if (ret) {
+ dev_err(dev, "Failed to allocate channel spec: %d\n", ret);
+ goto error_free;
+ }
+
+ if (st->chip_info->int_vref == 2500000)
+ ctrl |= AD5380_CTRL_INT_VREF_2V5;
+
+ st->vref_reg = regulator_get(dev, "vref");
+ if (!IS_ERR(st->vref_reg)) {
+ ret = regulator_enable(st->vref_reg);
+ if (ret) {
+ dev_err(dev, "Failed to enable vref regulators: %d\n",
+ ret);
+ goto error_free_reg;
+ }
+
+ st->vref = regulator_get_voltage(st->vref_reg);
+ } else {
+ st->vref = st->chip_info->int_vref;
+ ctrl |= AD5380_CTRL_INT_VREF_EN;
+ }
+
+ ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl);
+ if (ret) {
+ dev_err(dev, "Failed to write to device: %d\n", ret);
+ goto error_disable_reg;
+ }
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(dev, "Failed to register iio device: %d\n", ret);
+ goto error_disable_reg;
+ }
+
+ return 0;
+
+error_disable_reg:
+ if (!IS_ERR(st->vref_reg))
+ regulator_disable(st->vref_reg);
+error_free_reg:
+ if (!IS_ERR(st->vref_reg))
+ regulator_put(st->vref_reg);
+
+ kfree(indio_dev->channels);
+error_free:
+ iio_free_device(indio_dev);
+error_regmap_exit:
+ regmap_exit(regmap);
+
+ return ret;
+}
+
+static int __devexit ad5380_remove(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad5380_state *st = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+
+ kfree(indio_dev->channels);
+
+ if (!IS_ERR(st->vref_reg)) {
+ regulator_disable(st->vref_reg);
+ regulator_put(st->vref_reg);
+ }
+
+ regmap_exit(st->regmap);
+ iio_free_device(indio_dev);
+
+ return 0;
+}
+
+static bool ad5380_reg_false(struct device *dev, unsigned int reg)
+{
+ return false;
+}
+
+static const struct regmap_config ad5380_regmap_config = {
+ .reg_bits = 10,
+ .val_bits = 14,
+
+ .max_register = AD5380_REG_DATA(40),
+ .cache_type = REGCACHE_RBTREE,
+
+ .volatile_reg = ad5380_reg_false,
+ .readable_reg = ad5380_reg_false,
+};
+
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+
+static int __devinit ad5380_spi_probe(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+ struct regmap *regmap;
+
+ regmap = regmap_init_spi(spi, &ad5380_regmap_config);
+
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name);
+}
+
+static int __devexit ad5380_spi_remove(struct spi_device *spi)
+{
+ return ad5380_remove(&spi->dev);
+}
+
+static const struct spi_device_id ad5380_spi_ids[] = {
+ { "ad5380-3", ID_AD5380_3 },
+ { "ad5380-5", ID_AD5380_5 },
+ { "ad5381-3", ID_AD5381_3 },
+ { "ad5381-5", ID_AD5381_5 },
+ { "ad5382-3", ID_AD5382_3 },
+ { "ad5382-5", ID_AD5382_5 },
+ { "ad5383-3", ID_AD5383_3 },
+ { "ad5383-5", ID_AD5383_5 },
+ { "ad5384-3", ID_AD5380_3 },
+ { "ad5384-5", ID_AD5380_5 },
+ { "ad5390-3", ID_AD5390_3 },
+ { "ad5390-5", ID_AD5390_5 },
+ { "ad5391-3", ID_AD5391_3 },
+ { "ad5391-5", ID_AD5391_5 },
+ { "ad5392-3", ID_AD5392_3 },
+ { "ad5392-5", ID_AD5392_5 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad5380_spi_ids);
+
+static struct spi_driver ad5380_spi_driver = {
+ .driver = {
+ .name = "ad5380",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad5380_spi_probe,
+ .remove = __devexit_p(ad5380_spi_remove),
+ .id_table = ad5380_spi_ids,
+};
+
+static inline int ad5380_spi_register_driver(void)
+{
+ return spi_register_driver(&ad5380_spi_driver);
+}
+
+static inline void ad5380_spi_unregister_driver(void)
+{
+ spi_unregister_driver(&ad5380_spi_driver);
+}
+
+#else
+
+static inline int ad5380_spi_register_driver(void)
+{
+ return 0;
+}
+
+static inline void ad5380_spi_unregister_driver(void)
+{
+}
+
+#endif
+
+#if IS_ENABLED(CONFIG_I2C)
+
+static int __devinit ad5380_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct regmap *regmap;
+
+ regmap = regmap_init_i2c(i2c, &ad5380_regmap_config);
+
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name);
+}
+
+static int __devexit ad5380_i2c_remove(struct i2c_client *i2c)
+{
+ return ad5380_remove(&i2c->dev);
+}
+
+static const struct i2c_device_id ad5380_i2c_ids[] = {
+ { "ad5380-3", ID_AD5380_3 },
+ { "ad5380-5", ID_AD5380_5 },
+ { "ad5381-3", ID_AD5381_3 },
+ { "ad5381-5", ID_AD5381_5 },
+ { "ad5382-3", ID_AD5382_3 },
+ { "ad5382-5", ID_AD5382_5 },
+ { "ad5383-3", ID_AD5383_3 },
+ { "ad5383-5", ID_AD5383_5 },
+ { "ad5384-3", ID_AD5380_3 },
+ { "ad5384-5", ID_AD5380_5 },
+ { "ad5390-3", ID_AD5390_3 },
+ { "ad5390-5", ID_AD5390_5 },
+ { "ad5391-3", ID_AD5391_3 },
+ { "ad5391-5", ID_AD5391_5 },
+ { "ad5392-3", ID_AD5392_3 },
+ { "ad5392-5", ID_AD5392_5 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ad5380_i2c_ids);
+
+static struct i2c_driver ad5380_i2c_driver = {
+ .driver = {
+ .name = "ad5380",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad5380_i2c_probe,
+ .remove = __devexit_p(ad5380_i2c_remove),
+ .id_table = ad5380_i2c_ids,
+};
+
+static inline int ad5380_i2c_register_driver(void)
+{
+ return i2c_add_driver(&ad5380_i2c_driver);
+}
+
+static inline void ad5380_i2c_unregister_driver(void)
+{
+ i2c_del_driver(&ad5380_i2c_driver);
+}
+
+#else
+
+static inline int ad5380_i2c_register_driver(void)
+{
+ return 0;
+}
+
+static inline void ad5380_i2c_unregister_driver(void)
+{
+}
+
+#endif
+
+static int __init ad5380_spi_init(void)
+{
+ int ret;
+
+ ret = ad5380_spi_register_driver();
+ if (ret)
+ return ret;
+
+ ret = ad5380_i2c_register_driver();
+ if (ret) {
+ ad5380_spi_unregister_driver();
+ return ret;
+ }
+
+ return 0;
+}
+module_init(ad5380_spi_init);
+
+static void __exit ad5380_spi_exit(void)
+{
+ ad5380_i2c_unregister_driver();
+ ad5380_spi_unregister_driver();
+
+}
+module_exit(ad5380_spi_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices AD5380/81/82/83/84/90/91/92 DAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/dac/ad5421.c b/drivers/staging/iio/dac/ad5421.c
new file mode 100644
index 000000000000..71ee86824763
--- /dev/null
+++ b/drivers/staging/iio/dac/ad5421.c
@@ -0,0 +1,555 @@
+/*
+ * AD5421 Digital to analog converters driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../events.h"
+#include "dac.h"
+#include "ad5421.h"
+
+
+#define AD5421_REG_DAC_DATA 0x1
+#define AD5421_REG_CTRL 0x2
+#define AD5421_REG_OFFSET 0x3
+#define AD5421_REG_GAIN 0x4
+/* load dac and fault shared the same register number. Writing to it will cause
+ * a dac load command, reading from it will return the fault status register */
+#define AD5421_REG_LOAD_DAC 0x5
+#define AD5421_REG_FAULT 0x5
+#define AD5421_REG_FORCE_ALARM_CURRENT 0x6
+#define AD5421_REG_RESET 0x7
+#define AD5421_REG_START_CONVERSION 0x8
+#define AD5421_REG_NOOP 0x9
+
+#define AD5421_CTRL_WATCHDOG_DISABLE BIT(12)
+#define AD5421_CTRL_AUTO_FAULT_READBACK BIT(11)
+#define AD5421_CTRL_MIN_CURRENT BIT(9)
+#define AD5421_CTRL_ADC_SOURCE_TEMP BIT(8)
+#define AD5421_CTRL_ADC_ENABLE BIT(7)
+#define AD5421_CTRL_PWR_DOWN_INT_VREF BIT(6)
+
+#define AD5421_FAULT_SPI BIT(15)
+#define AD5421_FAULT_PEC BIT(14)
+#define AD5421_FAULT_OVER_CURRENT BIT(13)
+#define AD5421_FAULT_UNDER_CURRENT BIT(12)
+#define AD5421_FAULT_TEMP_OVER_140 BIT(11)
+#define AD5421_FAULT_TEMP_OVER_100 BIT(10)
+#define AD5421_FAULT_UNDER_VOLTAGE_6V BIT(9)
+#define AD5421_FAULT_UNDER_VOLTAGE_12V BIT(8)
+
+/* These bits will cause the fault pin to go high */
+#define AD5421_FAULT_TRIGGER_IRQ \
+ (AD5421_FAULT_SPI | AD5421_FAULT_PEC | AD5421_FAULT_OVER_CURRENT | \
+ AD5421_FAULT_UNDER_CURRENT | AD5421_FAULT_TEMP_OVER_140)
+
+/**
+ * struct ad5421_state - driver instance specific data
+ * @spi: spi_device
+ * @ctrl: control register cache
+ * @current_range: current range which the device is configured for
+ * @data: spi transfer buffers
+ * @fault_mask: software masking of events
+ */
+struct ad5421_state {
+ struct spi_device *spi;
+ unsigned int ctrl;
+ enum ad5421_current_range current_range;
+ unsigned int fault_mask;
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ union {
+ u32 d32;
+ u8 d8[4];
+ } data[2] ____cacheline_aligned;
+};
+
+static const struct iio_chan_spec ad5421_channels[] = {
+ {
+ .type = IIO_CURRENT,
+ .indexed = 1,
+ .output = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .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),
+ },
+ {
+ .type = IIO_TEMP,
+ .channel = -1,
+ .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+ },
+};
+
+static int ad5421_write_unlocked(struct iio_dev *indio_dev,
+ unsigned int reg, unsigned int val)
+{
+ struct ad5421_state *st = iio_priv(indio_dev);
+
+ st->data[0].d32 = cpu_to_be32((reg << 16) | val);
+
+ return spi_write(st->spi, &st->data[0].d8[1], 3);
+}
+
+static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg,
+ unsigned int val)
+{
+ int ret;
+
+ mutex_lock(&indio_dev->mlock);
+ ret = ad5421_write_unlocked(indio_dev, reg, val);
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg)
+{
+ struct ad5421_state *st = iio_priv(indio_dev);
+ struct spi_message m;
+ int ret;
+ struct spi_transfer t[] = {
+ {
+ .tx_buf = &st->data[0].d8[1],
+ .len = 3,
+ .cs_change = 1,
+ }, {
+ .rx_buf = &st->data[1].d8[1],
+ .len = 3,
+ },
+ };
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t[0], &m);
+ spi_message_add_tail(&t[1], &m);
+
+ mutex_lock(&indio_dev->mlock);
+
+ st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16));
+
+ ret = spi_sync(st->spi, &m);
+ if (ret >= 0)
+ ret = be32_to_cpu(st->data[1].d32) & 0xffff;
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static int ad5421_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
+ unsigned int clr)
+{
+ struct ad5421_state *st = iio_priv(indio_dev);
+ unsigned int ret;
+
+ mutex_lock(&indio_dev->mlock);
+
+ st->ctrl &= ~clr;
+ st->ctrl |= set;
+
+ ret = ad5421_write_unlocked(indio_dev, AD5421_REG_CTRL, st->ctrl);
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static irqreturn_t ad5421_fault_handler(int irq, void *data)
+{
+ struct iio_dev *indio_dev = data;
+ struct ad5421_state *st = iio_priv(indio_dev);
+ unsigned int fault;
+ unsigned int old_fault = 0;
+ unsigned int events;
+
+ fault = ad5421_read(indio_dev, AD5421_REG_FAULT);
+ if (!fault)
+ return IRQ_NONE;
+
+ /* If we had a fault, this might mean that the DAC has lost its state
+ * and has been reset. Make sure that the control register actually
+ * contains what we expect it to contain. Otherwise the watchdog might
+ * be enabled and we get watchdog timeout faults, which will render the
+ * DAC unusable. */
+ ad5421_update_ctrl(indio_dev, 0, 0);
+
+
+ /* The fault pin stays high as long as a fault condition is present and
+ * it is not possible to mask fault conditions. For certain fault
+ * conditions for example like over-temperature it takes some time
+ * until the fault condition disappears. If we would exit the interrupt
+ * handler immediately after handling the event it would be entered
+ * again instantly. Thus we fall back to polling in case we detect that
+ * a interrupt condition is still present.
+ */
+ do {
+ /* 0xffff is a invalid value for the register and will only be
+ * read if there has been a communication error */
+ if (fault == 0xffff)
+ fault = 0;
+
+ /* we are only interested in new events */
+ events = (old_fault ^ fault) & fault;
+ events &= st->fault_mask;
+
+ if (events & AD5421_FAULT_OVER_CURRENT) {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_CURRENT,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns());
+ }
+
+ if (events & AD5421_FAULT_UNDER_CURRENT) {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_CURRENT,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ iio_get_time_ns());
+ }
+
+ if (events & AD5421_FAULT_TEMP_OVER_140) {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+ 0,
+ IIO_EV_TYPE_MAG,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns());
+ }
+
+ old_fault = fault;
+ fault = ad5421_read(indio_dev, AD5421_REG_FAULT);
+
+ /* still active? go to sleep for some time */
+ if (fault & AD5421_FAULT_TRIGGER_IRQ)
+ msleep(1000);
+
+ } while (fault & AD5421_FAULT_TRIGGER_IRQ);
+
+
+ return IRQ_HANDLED;
+}
+
+static void ad5421_get_current_min_max(struct ad5421_state *st,
+ unsigned int *min, unsigned int *max)
+{
+ /* The current range is configured using external pins, which are
+ * usually hard-wired and not run-time switchable. */
+ switch (st->current_range) {
+ case AD5421_CURRENT_RANGE_4mA_20mA:
+ *min = 4000;
+ *max = 20000;
+ break;
+ case AD5421_CURRENT_RANGE_3mA8_21mA:
+ *min = 3800;
+ *max = 21000;
+ break;
+ case AD5421_CURRENT_RANGE_3mA2_24mA:
+ *min = 3200;
+ *max = 24000;
+ break;
+ default:
+ *min = 0;
+ *max = 1;
+ break;
+ }
+}
+
+static inline unsigned int ad5421_get_offset(struct ad5421_state *st)
+{
+ unsigned int min, max;
+
+ ad5421_get_current_min_max(st, &min, &max);
+ return (min * (1 << 16)) / (max - min);
+}
+
+static inline unsigned int ad5421_get_scale(struct ad5421_state *st)
+{
+ unsigned int min, max;
+
+ ad5421_get_current_min_max(st, &min, &max);
+ return ((max - min) * 1000) / (1 << 16);
+}
+
+static int ad5421_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val, int *val2, long m)
+{
+ struct ad5421_state *st = iio_priv(indio_dev);
+ int ret;
+
+ if (chan->type != IIO_CURRENT)
+ return -EINVAL;
+
+ switch (m) {
+ case 0:
+ ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = ad5421_get_scale(st);
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_OFFSET:
+ *val = ad5421_get_offset(st);
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ ret = ad5421_read(indio_dev, AD5421_REG_OFFSET);
+ if (ret < 0)
+ return ret;
+ *val = ret - 32768;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ ret = ad5421_read(indio_dev, AD5421_REG_GAIN);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static int ad5421_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+ const unsigned int max_val = 1 << 16;
+
+ switch (mask) {
+ case 0:
+ if (val >= max_val || val < 0)
+ return -EINVAL;
+
+ return ad5421_write(indio_dev, AD5421_REG_DAC_DATA, val);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ val += 32768;
+ if (val >= max_val || val < 0)
+ return -EINVAL;
+
+ return ad5421_write(indio_dev, AD5421_REG_OFFSET, val);
+ case IIO_CHAN_INFO_CALIBSCALE:
+ if (val >= max_val || val < 0)
+ return -EINVAL;
+
+ return ad5421_write(indio_dev, AD5421_REG_GAIN, val);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int ad5421_write_event_config(struct iio_dev *indio_dev,
+ u64 event_code, int state)
+{
+ struct ad5421_state *st = iio_priv(indio_dev);
+ unsigned int mask;
+
+ switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+ case IIO_CURRENT:
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
+ IIO_EV_DIR_RISING)
+ mask = AD5421_FAULT_OVER_CURRENT;
+ else
+ mask = AD5421_FAULT_UNDER_CURRENT;
+ break;
+ case IIO_TEMP:
+ mask = AD5421_FAULT_TEMP_OVER_140;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mutex_lock(&indio_dev->mlock);
+ if (state)
+ st->fault_mask |= mask;
+ else
+ st->fault_mask &= ~mask;
+ mutex_unlock(&indio_dev->mlock);
+
+ return 0;
+}
+
+static int ad5421_read_event_config(struct iio_dev *indio_dev,
+ u64 event_code)
+{
+ struct ad5421_state *st = iio_priv(indio_dev);
+ unsigned int mask;
+
+ switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+ case IIO_CURRENT:
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
+ IIO_EV_DIR_RISING)
+ mask = AD5421_FAULT_OVER_CURRENT;
+ else
+ mask = AD5421_FAULT_UNDER_CURRENT;
+ break;
+ case IIO_TEMP:
+ mask = AD5421_FAULT_TEMP_OVER_140;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return (bool)(st->fault_mask & mask);
+}
+
+static int ad5421_read_event_value(struct iio_dev *indio_dev, u64 event_code,
+ int *val)
+{
+ int ret;
+
+ switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+ case IIO_CURRENT:
+ ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ break;
+ case IIO_TEMP:
+ *val = 140000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct iio_info ad5421_info = {
+ .read_raw = ad5421_read_raw,
+ .write_raw = ad5421_write_raw,
+ .read_event_config = ad5421_read_event_config,
+ .write_event_config = ad5421_write_event_config,
+ .read_event_value = ad5421_read_event_value,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit ad5421_probe(struct spi_device *spi)
+{
+ struct ad5421_platform_data *pdata = dev_get_platdata(&spi->dev);
+ struct iio_dev *indio_dev;
+ struct ad5421_state *st;
+ int ret;
+
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
+ dev_err(&spi->dev, "Failed to allocate iio device\n");
+ return -ENOMEM;
+ }
+
+ st = iio_priv(indio_dev);
+ spi_set_drvdata(spi, indio_dev);
+
+ st->spi = spi;
+
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = "ad5421";
+ indio_dev->info = &ad5421_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = ad5421_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad5421_channels);
+
+ st->ctrl = AD5421_CTRL_WATCHDOG_DISABLE |
+ AD5421_CTRL_AUTO_FAULT_READBACK;
+
+ if (pdata) {
+ st->current_range = pdata->current_range;
+ if (pdata->external_vref)
+ st->ctrl |= AD5421_CTRL_PWR_DOWN_INT_VREF;
+ } else {
+ st->current_range = AD5421_CURRENT_RANGE_4mA_20mA;
+ }
+
+ /* write initial ctrl register value */
+ ad5421_update_ctrl(indio_dev, 0, 0);
+
+ if (spi->irq) {
+ ret = request_threaded_irq(spi->irq,
+ NULL,
+ ad5421_fault_handler,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "ad5421 fault",
+ indio_dev);
+ if (ret)
+ goto error_free;
+ }
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to register iio device: %d\n", ret);
+ goto error_free_irq;
+ }
+
+ return 0;
+
+error_free_irq:
+ if (spi->irq)
+ free_irq(spi->irq, indio_dev);
+error_free:
+ iio_free_device(indio_dev);
+
+ return ret;
+}
+
+static int __devexit ad5421_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+
+ iio_device_unregister(indio_dev);
+ if (spi->irq)
+ free_irq(spi->irq, indio_dev);
+ iio_free_device(indio_dev);
+
+ return 0;
+}
+
+static struct spi_driver ad5421_driver = {
+ .driver = {
+ .name = "ad5421",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad5421_probe,
+ .remove = __devexit_p(ad5421_remove),
+};
+
+static __init int ad5421_init(void)
+{
+ return spi_register_driver(&ad5421_driver);
+}
+module_init(ad5421_init);
+
+static __exit void ad5421_exit(void)
+{
+ spi_unregister_driver(&ad5421_driver);
+}
+module_exit(ad5421_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices AD5421 DAC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:ad5421");
diff --git a/drivers/staging/iio/dac/ad5421.h b/drivers/staging/iio/dac/ad5421.h
new file mode 100644
index 000000000000..cd2bb84ff1b0
--- /dev/null
+++ b/drivers/staging/iio/dac/ad5421.h
@@ -0,0 +1,32 @@
+#ifndef __IIO_DAC_AD5421_H__
+#define __IIO_DAC_AD5421_H__
+
+/*
+ * TODO: This file needs to go into include/linux/iio
+ */
+
+/**
+ * enum ad5421_current_range - Current range the AD5421 is configured for.
+ * @AD5421_CURRENT_RANGE_4mA_20mA: 4 mA to 20 mA (RANGE1,0 pins = 00)
+ * @AD5421_CURRENT_RANGE_3mA8_21mA: 3.8 mA to 21 mA (RANGE1,0 pins = x1)
+ * @AD5421_CURRENT_RANGE_3mA2_24mA: 3.2 mA to 24 mA (RANGE1,0 pins = 10)
+ */
+
+enum ad5421_current_range {
+ AD5421_CURRENT_RANGE_4mA_20mA,
+ AD5421_CURRENT_RANGE_3mA8_21mA,
+ AD5421_CURRENT_RANGE_3mA2_24mA,
+};
+
+/**
+ * struct ad5421_platform_data - AD5421 DAC driver platform data
+ * @external_vref: whether an external reference voltage is used or not
+ * @current_range: Current range the AD5421 is configured for
+ */
+
+struct ad5421_platform_data {
+ bool external_vref;
+ enum ad5421_current_range current_range;
+};
+
+#endif
diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c
index ec701e939b6b..693e7482524c 100644
--- a/drivers/staging/iio/dac/ad5446.c
+++ b/drivers/staging/iio/dac/ad5446.c
@@ -26,19 +26,17 @@
static void ad5446_store_sample(struct ad5446_state *st, unsigned val)
{
- st->data.d16 = cpu_to_be16(AD5446_LOAD |
- (val << st->chip_info->left_shift));
+ st->data.d16 = cpu_to_be16(AD5446_LOAD | val);
}
static void ad5542_store_sample(struct ad5446_state *st, unsigned val)
{
- st->data.d16 = cpu_to_be16(val << st->chip_info->left_shift);
+ st->data.d16 = cpu_to_be16(val);
}
static void ad5620_store_sample(struct ad5446_state *st, unsigned val)
{
- st->data.d16 = cpu_to_be16(AD5620_LOAD |
- (val << st->chip_info->left_shift));
+ st->data.d16 = cpu_to_be16(AD5620_LOAD | val);
}
static void ad5660_store_sample(struct ad5446_state *st, unsigned val)
@@ -63,50 +61,6 @@ static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode)
st->data.d24[2] = val & 0xFF;
}
-static ssize_t ad5446_write(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5446_state *st = iio_priv(indio_dev);
- int ret;
- long val;
-
- ret = strict_strtol(buf, 10, &val);
- if (ret)
- goto error_ret;
-
- if (val > RES_MASK(st->chip_info->bits)) {
- ret = -EINVAL;
- goto error_ret;
- }
-
- mutex_lock(&indio_dev->mlock);
- st->cached_val = val;
- st->chip_info->store_sample(st, val);
- ret = spi_sync(st->spi, &st->msg);
- mutex_unlock(&indio_dev->mlock);
-
-error_ret:
- return ret ? ret : len;
-}
-
-static IIO_DEV_ATTR_OUT_RAW(0, ad5446_write, 0);
-
-static ssize_t ad5446_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5446_state *st = iio_priv(indio_dev);
- /* Corresponds to Vref / 2^(bits) */
- unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
-
- return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
-}
-static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5446_show_scale, NULL, 0);
-
static ssize_t ad5446_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
@@ -189,8 +143,6 @@ static IIO_DEVICE_ATTR(out_voltage0_powerdown, S_IRUGO | S_IWUSR,
ad5446_write_dac_powerdown, 0);
static struct attribute *ad5446_attributes[] = {
- &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
- &iio_dev_attr_out_voltage_scale.dev_attr.attr,
&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
@@ -223,121 +175,148 @@ static const struct attribute_group ad5446_attribute_group = {
.is_visible = ad5446_attr_is_visible,
};
+#define AD5446_CHANNEL(bits, storage, shift) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .output = 1, \
+ .channel = 0, \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .scan_type = IIO_ST('u', (bits), (storage), (shift)) \
+}
+
static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
[ID_AD5444] = {
- .bits = 12,
- .storagebits = 16,
- .left_shift = 2,
+ .channel = AD5446_CHANNEL(12, 16, 2),
.store_sample = ad5446_store_sample,
},
[ID_AD5446] = {
- .bits = 14,
- .storagebits = 16,
- .left_shift = 0,
+ .channel = AD5446_CHANNEL(14, 16, 0),
.store_sample = ad5446_store_sample,
},
[ID_AD5541A] = {
- .bits = 16,
- .storagebits = 16,
- .left_shift = 0,
+ .channel = AD5446_CHANNEL(16, 16, 0),
.store_sample = ad5542_store_sample,
},
[ID_AD5542A] = {
- .bits = 16,
- .storagebits = 16,
- .left_shift = 0,
+ .channel = AD5446_CHANNEL(16, 16, 0),
.store_sample = ad5542_store_sample,
},
[ID_AD5543] = {
- .bits = 16,
- .storagebits = 16,
- .left_shift = 0,
+ .channel = AD5446_CHANNEL(16, 16, 0),
.store_sample = ad5542_store_sample,
},
[ID_AD5512A] = {
- .bits = 12,
- .storagebits = 16,
- .left_shift = 4,
+ .channel = AD5446_CHANNEL(12, 16, 4),
.store_sample = ad5542_store_sample,
},
[ID_AD5553] = {
- .bits = 14,
- .storagebits = 16,
- .left_shift = 0,
+ .channel = AD5446_CHANNEL(14, 16, 0),
.store_sample = ad5542_store_sample,
},
[ID_AD5601] = {
- .bits = 8,
- .storagebits = 16,
- .left_shift = 6,
+ .channel = AD5446_CHANNEL(8, 16, 6),
.store_sample = ad5542_store_sample,
.store_pwr_down = ad5620_store_pwr_down,
},
[ID_AD5611] = {
- .bits = 10,
- .storagebits = 16,
- .left_shift = 4,
+ .channel = AD5446_CHANNEL(10, 16, 4),
.store_sample = ad5542_store_sample,
.store_pwr_down = ad5620_store_pwr_down,
},
[ID_AD5621] = {
- .bits = 12,
- .storagebits = 16,
- .left_shift = 2,
+ .channel = AD5446_CHANNEL(12, 16, 2),
.store_sample = ad5542_store_sample,
.store_pwr_down = ad5620_store_pwr_down,
},
[ID_AD5620_2500] = {
- .bits = 12,
- .storagebits = 16,
- .left_shift = 2,
+ .channel = AD5446_CHANNEL(12, 16, 2),
.int_vref_mv = 2500,
.store_sample = ad5620_store_sample,
.store_pwr_down = ad5620_store_pwr_down,
},
[ID_AD5620_1250] = {
- .bits = 12,
- .storagebits = 16,
- .left_shift = 2,
+ .channel = AD5446_CHANNEL(12, 16, 2),
.int_vref_mv = 1250,
.store_sample = ad5620_store_sample,
.store_pwr_down = ad5620_store_pwr_down,
},
[ID_AD5640_2500] = {
- .bits = 14,
- .storagebits = 16,
- .left_shift = 0,
+ .channel = AD5446_CHANNEL(14, 16, 0),
.int_vref_mv = 2500,
.store_sample = ad5620_store_sample,
.store_pwr_down = ad5620_store_pwr_down,
},
[ID_AD5640_1250] = {
- .bits = 14,
- .storagebits = 16,
- .left_shift = 0,
+ .channel = AD5446_CHANNEL(14, 16, 0),
.int_vref_mv = 1250,
.store_sample = ad5620_store_sample,
.store_pwr_down = ad5620_store_pwr_down,
},
[ID_AD5660_2500] = {
- .bits = 16,
- .storagebits = 24,
- .left_shift = 0,
+ .channel = AD5446_CHANNEL(16, 16, 0),
.int_vref_mv = 2500,
.store_sample = ad5660_store_sample,
.store_pwr_down = ad5660_store_pwr_down,
},
[ID_AD5660_1250] = {
- .bits = 16,
- .storagebits = 24,
- .left_shift = 0,
+ .channel = AD5446_CHANNEL(16, 16, 0),
.int_vref_mv = 1250,
.store_sample = ad5660_store_sample,
.store_pwr_down = ad5660_store_pwr_down,
},
};
+static int ad5446_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
+{
+ struct ad5446_state *st = iio_priv(indio_dev);
+ unsigned long scale_uv;
+
+ switch (m) {
+ case IIO_CHAN_INFO_SCALE:
+ scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+
+ }
+ return -EINVAL;
+}
+
+static int ad5446_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ struct ad5446_state *st = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case 0:
+ if (val >= (1 << chan->scan_type.realbits) || val < 0)
+ return -EINVAL;
+
+ val <<= chan->scan_type.shift;
+ mutex_lock(&indio_dev->mlock);
+ st->cached_val = val;
+ st->chip_info->store_sample(st, val);
+ ret = spi_sync(st->spi, &st->msg);
+ mutex_unlock(&indio_dev->mlock);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
static const struct iio_info ad5446_info = {
+ .read_raw = ad5446_read_raw,
+ .write_raw = ad5446_write_raw,
.attrs = &ad5446_attribute_group,
.driver_module = THIS_MODULE,
};
@@ -376,11 +355,13 @@ static int __devinit ad5446_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = &ad5446_info;
indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = &st->chip_info->channel;
+ indio_dev->num_channels = 1;
/* Setup default message */
st->xfer.tx_buf = &st->data;
- st->xfer.len = st->chip_info->storagebits / 8;
+ st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8;
spi_message_init(&st->msg);
spi_message_add_tail(&st->xfer, &st->msg);
@@ -454,11 +435,11 @@ static const struct spi_device_id ad5446_id[] = {
{"ad5660-1250", ID_AD5660_1250},
{}
};
+MODULE_DEVICE_TABLE(spi, ad5446_id);
static struct spi_driver ad5446_driver = {
.driver = {
.name = "ad5446",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad5446_probe,
@@ -470,4 +451,3 @@ module_spi_driver(ad5446_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:ad5446");
diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h
index 7118d653ac3e..4ea3476fb065 100644
--- a/drivers/staging/iio/dac/ad5446.h
+++ b/drivers/staging/iio/dac/ad5446.h
@@ -25,8 +25,6 @@
#define AD5660_PWRDWN_100k (0x2 << 16) /* Power-down: 100kOhm to GND */
#define AD5660_PWRDWN_TRISTATE (0x3 << 16) /* Power-down: Three-state */
-#define RES_MASK(bits) ((1 << (bits)) - 1)
-
#define MODE_PWRDWN_1k 0x1
#define MODE_PWRDWN_100k 0x2
#define MODE_PWRDWN_TRISTATE 0x3
@@ -62,18 +60,14 @@ struct ad5446_state {
/**
* struct ad5446_chip_info - chip specific information
- * @bits: accuracy of the DAC in bits
- * @storagebits: number of bits written to the DAC
- * @left_shift: number of bits the datum must be shifted
+ * @channel: channel spec for the DAC
* @int_vref_mv: AD5620/40/60: the internal reference voltage
* @store_sample: chip specific helper function to store the datum
* @store_sample: chip specific helper function to store the powerpown cmd
*/
struct ad5446_chip_info {
- u8 bits;
- u8 storagebits;
- u8 left_shift;
+ struct iio_chan_spec channel;
u16 int_vref_mv;
void (*store_sample) (struct ad5446_state *st, unsigned val);
void (*store_pwr_down) (struct ad5446_state *st, unsigned mode);
diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c
index 57539ce8e6cf..bc17205fe722 100644
--- a/drivers/staging/iio/dac/ad5504.c
+++ b/drivers/staging/iio/dac/ad5504.c
@@ -18,9 +18,27 @@
#include "../iio.h"
#include "../sysfs.h"
+#include "../events.h"
#include "dac.h"
#include "ad5504.h"
+#define AD5504_CHANNEL(_chan) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .output = 1, \
+ .channel = (_chan), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .address = AD5504_ADDR_DAC(_chan), \
+ .scan_type = IIO_ST('u', 12, 16, 0), \
+}
+
+static const struct iio_chan_spec ad5504_channels[] = {
+ AD5504_CHANNEL(0),
+ AD5504_CHANNEL(1),
+ AD5504_CHANNEL(2),
+ AD5504_CHANNEL(3),
+};
+
static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val)
{
u16 tmp = cpu_to_be16(AD5504_CMD_WRITE |
@@ -30,13 +48,14 @@ static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val)
return spi_write(spi, (u8 *)&tmp, 2);
}
-static int ad5504_spi_read(struct spi_device *spi, u8 addr, u16 *val)
+static int ad5504_spi_read(struct spi_device *spi, u8 addr)
{
u16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr));
+ u16 val;
int ret;
struct spi_transfer t = {
.tx_buf = &tmp,
- .rx_buf = val,
+ .rx_buf = &val,
.len = 2,
};
struct spi_message m;
@@ -45,44 +64,61 @@ static int ad5504_spi_read(struct spi_device *spi, u8 addr, u16 *val)
spi_message_add_tail(&t, &m);
ret = spi_sync(spi, &m);
- *val = be16_to_cpu(*val) & AD5504_RES_MASK;
+ if (ret < 0)
+ return ret;
- return ret;
+ return be16_to_cpu(val) & AD5504_RES_MASK;
}
-static ssize_t ad5504_write_dac(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
+static int ad5504_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad5504_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- long readin;
+ unsigned long scale_uv;
int ret;
- ret = strict_strtol(buf, 10, &readin);
- if (ret)
- return ret;
+ switch (m) {
+ case 0:
+ ret = ad5504_spi_read(st->spi, chan->address);
+ if (ret < 0)
+ return ret;
- ret = ad5504_spi_write(st->spi, this_attr->address, readin);
- return ret ? ret : len;
+ *val = ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+
+ }
+ return -EINVAL;
}
-static ssize_t ad5504_read_dac(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int ad5504_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad5504_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- u16 val;
- ret = ad5504_spi_read(st->spi, this_attr->address, &val);
- if (ret)
- return ret;
+ switch (mask) {
+ case 0:
+ if (val >= (1 << chan->scan_type.realbits) || val < 0)
+ return -EINVAL;
- return sprintf(buf, "%d\n", val);
+ return ad5504_spi_write(st->spi, chan->address, val);
+ default:
+ ret = -EINVAL;
+ }
+
+ return -EINVAL;
}
static ssize_t ad5504_read_powerdown_mode(struct device *dev,
@@ -157,32 +193,6 @@ static ssize_t ad5504_write_dac_powerdown(struct device *dev,
return ret ? ret : len;
}
-static ssize_t ad5504_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5504_state *st = iio_priv(indio_dev);
- /* Corresponds to Vref / 2^(bits) */
- unsigned int scale_uv = (st->vref_mv * 1000) >> AD5505_BITS;
-
- return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
-}
-static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5504_show_scale, NULL, 0);
-
-#define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \
- IIO_DEVICE_ATTR(out_voltage##_num##_raw, \
- S_IRUGO | S_IWUSR, _show, _store, _addr)
-
-static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5504_read_dac,
- ad5504_write_dac, AD5504_ADDR_DAC0);
-static IIO_DEV_ATTR_OUT_RW_RAW(1, ad5504_read_dac,
- ad5504_write_dac, AD5504_ADDR_DAC1);
-static IIO_DEV_ATTR_OUT_RW_RAW(2, ad5504_read_dac,
- ad5504_write_dac, AD5504_ADDR_DAC2);
-static IIO_DEV_ATTR_OUT_RW_RAW(3, ad5504_read_dac,
- ad5504_write_dac, AD5504_ADDR_DAC3);
-
static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO |
S_IWUSR, ad5504_read_powerdown_mode,
ad5504_write_powerdown_mode, 0);
@@ -203,17 +213,12 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5504_read_dac_powerdown,
ad5504_write_dac_powerdown, 3);
static struct attribute *ad5504_attributes[] = {
- &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
- &iio_dev_attr_out_voltage1_raw.dev_attr.attr,
- &iio_dev_attr_out_voltage2_raw.dev_attr.attr,
- &iio_dev_attr_out_voltage3_raw.dev_attr.attr,
&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage1_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage2_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage3_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
- &iio_dev_attr_out_voltage_scale.dev_attr.attr,
NULL,
};
@@ -222,11 +227,9 @@ static const struct attribute_group ad5504_attribute_group = {
};
static struct attribute *ad5501_attributes[] = {
- &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
- &iio_dev_attr_out_voltage_scale.dev_attr.attr,
NULL,
};
@@ -261,12 +264,16 @@ static irqreturn_t ad5504_event_handler(int irq, void *private)
}
static const struct iio_info ad5504_info = {
+ .write_raw = ad5504_write_raw,
+ .read_raw = ad5504_read_raw,
.attrs = &ad5504_attribute_group,
.event_attrs = &ad5504_ev_attribute_group,
.driver_module = THIS_MODULE,
};
static const struct iio_info ad5501_info = {
+ .write_raw = ad5504_write_raw,
+ .read_raw = ad5504_read_raw,
.attrs = &ad5501_attribute_group,
.event_attrs = &ad5504_ev_attribute_group,
.driver_module = THIS_MODULE,
@@ -307,10 +314,14 @@ static int __devinit ad5504_probe(struct spi_device *spi)
st->spi = spi;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(st->spi)->name;
- if (spi_get_device_id(st->spi)->driver_data == ID_AD5501)
+ if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) {
indio_dev->info = &ad5501_info;
- else
+ indio_dev->num_channels = 1;
+ } else {
indio_dev->info = &ad5504_info;
+ indio_dev->num_channels = 4;
+ }
+ indio_dev->channels = ad5504_channels;
indio_dev->modes = INDIO_DIRECT_MODE;
if (spi->irq) {
@@ -367,6 +378,7 @@ static const struct spi_device_id ad5504_id[] = {
{"ad5501", ID_AD5501},
{}
};
+MODULE_DEVICE_TABLE(spi, ad5504_id);
static struct spi_driver ad5504_driver = {
.driver = {
diff --git a/drivers/staging/iio/dac/ad5504.h b/drivers/staging/iio/dac/ad5504.h
index 85beb1dd29b9..afe09522f53c 100644
--- a/drivers/staging/iio/dac/ad5504.h
+++ b/drivers/staging/iio/dac/ad5504.h
@@ -18,10 +18,7 @@
/* Registers */
#define AD5504_ADDR_NOOP 0
-#define AD5504_ADDR_DAC0 1
-#define AD5504_ADDR_DAC1 2
-#define AD5504_ADDR_DAC2 3
-#define AD5504_ADDR_DAC3 4
+#define AD5504_ADDR_DAC(x) ((x) + 1)
#define AD5504_ADDR_ALL_DAC 5
#define AD5504_ADDR_CTRL 7
diff --git a/drivers/staging/iio/dac/ad5624r.h b/drivers/staging/iio/dac/ad5624r.h
index b71c6a03e780..5dca3028cdfd 100644
--- a/drivers/staging/iio/dac/ad5624r.h
+++ b/drivers/staging/iio/dac/ad5624r.h
@@ -32,12 +32,12 @@
/**
* struct ad5624r_chip_info - chip specific information
- * @bits: accuracy of the DAC in bits
+ * @channels: channel spec for the DAC
* @int_vref_mv: AD5620/40/60: the internal reference voltage
*/
struct ad5624r_chip_info {
- u8 bits;
+ const struct iio_chan_spec *channels;
u16 int_vref_mv;
};
diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c
index 6e05f0dbae0b..10c7484366ef 100644
--- a/drivers/staging/iio/dac/ad5624r_spi.c
+++ b/drivers/staging/iio/dac/ad5624r_spi.c
@@ -21,29 +21,51 @@
#include "dac.h"
#include "ad5624r.h"
+#define AD5624R_CHANNEL(_chan, _bits) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .output = 1, \
+ .channel = (_chan), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .address = (_chan), \
+ .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \
+}
+
+#define DECLARE_AD5624R_CHANNELS(_name, _bits) \
+ const struct iio_chan_spec _name##_channels[] = { \
+ AD5624R_CHANNEL(0, _bits), \
+ AD5624R_CHANNEL(1, _bits), \
+ AD5624R_CHANNEL(2, _bits), \
+ AD5624R_CHANNEL(3, _bits), \
+}
+
+static DECLARE_AD5624R_CHANNELS(ad5624r, 12);
+static DECLARE_AD5624R_CHANNELS(ad5644r, 14);
+static DECLARE_AD5624R_CHANNELS(ad5664r, 16);
+
static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = {
[ID_AD5624R3] = {
- .bits = 12,
- .int_vref_mv = 1250,
- },
- [ID_AD5644R3] = {
- .bits = 14,
- .int_vref_mv = 1250,
- },
- [ID_AD5664R3] = {
- .bits = 16,
+ .channels = ad5624r_channels,
.int_vref_mv = 1250,
},
[ID_AD5624R5] = {
- .bits = 12,
+ .channels = ad5624r_channels,
.int_vref_mv = 2500,
},
+ [ID_AD5644R3] = {
+ .channels = ad5644r_channels,
+ .int_vref_mv = 1250,
+ },
[ID_AD5644R5] = {
- .bits = 14,
+ .channels = ad5644r_channels,
.int_vref_mv = 2500,
},
+ [ID_AD5664R3] = {
+ .channels = ad5664r_channels,
+ .int_vref_mv = 1250,
+ },
[ID_AD5664R5] = {
- .bits = 16,
+ .channels = ad5664r_channels,
.int_vref_mv = 2500,
},
};
@@ -70,24 +92,49 @@ static int ad5624r_spi_write(struct spi_device *spi,
return spi_write(spi, msg, 3);
}
-static ssize_t ad5624r_write_dac(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
+static int ad5624r_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
{
- long readin;
- int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad5624r_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ unsigned long scale_uv;
- ret = strict_strtol(buf, 10, &readin);
- if (ret)
- return ret;
+ switch (m) {
+ case IIO_CHAN_INFO_SCALE:
+ scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
+ *val = scale_uv / 1000;
+ *val2 = (scale_uv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
- ret = ad5624r_spi_write(st->us, AD5624R_CMD_WRITE_INPUT_N_UPDATE_N,
- this_attr->address, readin,
- st->chip_info->bits);
- return ret ? ret : len;
+ }
+ return -EINVAL;
+}
+
+static int ad5624r_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ struct ad5624r_state *st = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case 0:
+ if (val >= (1 << chan->scan_type.realbits) || val < 0)
+ return -EINVAL;
+
+ return ad5624r_spi_write(st->us,
+ AD5624R_CMD_WRITE_INPUT_N_UPDATE_N,
+ chan->address, val,
+ chan->scan_type.shift);
+ default:
+ ret = -EINVAL;
+ }
+
+ return -EINVAL;
}
static ssize_t ad5624r_read_powerdown_mode(struct device *dev,
@@ -161,24 +208,6 @@ static ssize_t ad5624r_write_dac_powerdown(struct device *dev,
return ret ? ret : len;
}
-static ssize_t ad5624r_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5624r_state *st = iio_priv(indio_dev);
- /* Corresponds to Vref / 2^(bits) */
- unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
-
- return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
-}
-static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5624r_show_scale, NULL, 0);
-
-static IIO_DEV_ATTR_OUT_RAW(0, ad5624r_write_dac, AD5624R_ADDR_DAC0);
-static IIO_DEV_ATTR_OUT_RAW(1, ad5624r_write_dac, AD5624R_ADDR_DAC1);
-static IIO_DEV_ATTR_OUT_RAW(2, ad5624r_write_dac, AD5624R_ADDR_DAC2);
-static IIO_DEV_ATTR_OUT_RAW(3, ad5624r_write_dac, AD5624R_ADDR_DAC3);
-
static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO |
S_IWUSR, ad5624r_read_powerdown_mode,
ad5624r_write_powerdown_mode, 0);
@@ -200,17 +229,12 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5624r_read_dac_powerdown,
ad5624r_write_dac_powerdown, 3);
static struct attribute *ad5624r_attributes[] = {
- &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
- &iio_dev_attr_out_voltage1_raw.dev_attr.attr,
- &iio_dev_attr_out_voltage2_raw.dev_attr.attr,
- &iio_dev_attr_out_voltage3_raw.dev_attr.attr,
&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage1_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage2_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage3_powerdown.dev_attr.attr,
&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
- &iio_dev_attr_out_voltage_scale.dev_attr.attr,
NULL,
};
@@ -219,6 +243,8 @@ static const struct attribute_group ad5624r_attribute_group = {
};
static const struct iio_info ad5624r_info = {
+ .write_raw = ad5624r_write_raw,
+ .read_raw = ad5624r_read_raw,
.attrs = &ad5624r_attribute_group,
.driver_module = THIS_MODULE,
};
@@ -259,6 +285,8 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = &ad5624r_info;
indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = st->chip_info->channels;
+ indio_dev->num_channels = AD5624R_DAC_CHANNELS;
ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0,
!!voltage_uv, 16);
@@ -307,6 +335,7 @@ static const struct spi_device_id ad5624r_id[] = {
{"ad5664r5", ID_AD5664R5},
{}
};
+MODULE_DEVICE_TABLE(spi, ad5624r_id);
static struct spi_driver ad5624r_driver = {
.driver = {
diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c
index e72db2fbfedf..ce2d6193dd89 100644
--- a/drivers/staging/iio/dac/ad5686.c
+++ b/drivers/staging/iio/dac/ad5686.c
@@ -99,7 +99,7 @@ enum ad5686_supported_device_ids {
.indexed = 1, \
.output = 1, \
.channel = chan, \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = AD5686_ADDR_DAC(chan), \
.scan_type = IIO_ST('u', bits, 16, shift) \
}
@@ -306,7 +306,7 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
*val = ret;
return IIO_VAL_INT;
break;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_mv * 100000)
>> (chan->scan_type.realbits);
*val = scale_uv / 100000;
@@ -437,6 +437,7 @@ static const struct spi_device_id ad5686_id[] = {
{"ad5686", ID_AD5686},
{}
};
+MODULE_DEVICE_TABLE(spi, ad5686_id);
static struct spi_driver ad5686_driver = {
.driver = {
diff --git a/drivers/staging/iio/dac/ad5764.c b/drivers/staging/iio/dac/ad5764.c
new file mode 100644
index 000000000000..ff91480ae65c
--- /dev/null
+++ b/drivers/staging/iio/dac/ad5764.c
@@ -0,0 +1,393 @@
+/*
+ * Analog devices AD5764, AD5764R, AD5744, AD5744R quad-channel
+ * Digital to Analog Converters driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/regulator/consumer.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "dac.h"
+
+#define AD5764_REG_SF_NOP 0x0
+#define AD5764_REG_SF_CONFIG 0x1
+#define AD5764_REG_SF_CLEAR 0x4
+#define AD5764_REG_SF_LOAD 0x5
+#define AD5764_REG_DATA(x) ((2 << 3) | (x))
+#define AD5764_REG_COARSE_GAIN(x) ((3 << 3) | (x))
+#define AD5764_REG_FINE_GAIN(x) ((4 << 3) | (x))
+#define AD5764_REG_OFFSET(x) ((5 << 3) | (x))
+
+#define AD5764_NUM_CHANNELS 4
+
+/**
+ * struct ad5764_chip_info - chip specific information
+ * @int_vref: Value of the internal reference voltage in uV - 0 if external
+ * reference voltage is used
+ * @channel channel specification
+*/
+
+struct ad5764_chip_info {
+ unsigned long int_vref;
+ const struct iio_chan_spec *channels;
+};
+
+/**
+ * struct ad5764_state - driver instance specific data
+ * @spi: spi_device
+ * @chip_info: chip info
+ * @vref_reg: vref supply regulators
+ * @data: spi transfer buffers
+ */
+
+struct ad5764_state {
+ struct spi_device *spi;
+ const struct ad5764_chip_info *chip_info;
+ struct regulator_bulk_data vref_reg[2];
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ union {
+ __be32 d32;
+ u8 d8[4];
+ } data[2] ____cacheline_aligned;
+};
+
+enum ad5764_type {
+ ID_AD5744,
+ ID_AD5744R,
+ ID_AD5764,
+ ID_AD5764R,
+};
+
+#define AD5764_CHANNEL(_chan, _bits) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .output = 1, \
+ .channel = (_chan), \
+ .address = (_chan), \
+ .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
+ .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)) \
+}
+
+#define DECLARE_AD5764_CHANNELS(_name, _bits) \
+const struct iio_chan_spec _name##_channels[] = { \
+ AD5764_CHANNEL(0, (_bits)), \
+ AD5764_CHANNEL(1, (_bits)), \
+ AD5764_CHANNEL(2, (_bits)), \
+ AD5764_CHANNEL(3, (_bits)), \
+};
+
+static DECLARE_AD5764_CHANNELS(ad5764, 16);
+static DECLARE_AD5764_CHANNELS(ad5744, 14);
+
+static const struct ad5764_chip_info ad5764_chip_infos[] = {
+ [ID_AD5744] = {
+ .int_vref = 0,
+ .channels = ad5744_channels,
+ },
+ [ID_AD5744R] = {
+ .int_vref = 5000000,
+ .channels = ad5744_channels,
+ },
+ [ID_AD5764] = {
+ .int_vref = 0,
+ .channels = ad5764_channels,
+ },
+ [ID_AD5764R] = {
+ .int_vref = 5000000,
+ .channels = ad5764_channels,
+ },
+};
+
+static int ad5764_write(struct iio_dev *indio_dev, unsigned int reg,
+ unsigned int val)
+{
+ struct ad5764_state *st = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&indio_dev->mlock);
+ st->data[0].d32 = cpu_to_be32((reg << 16) | val);
+
+ ret = spi_write(st->spi, &st->data[0].d8[1], 3);
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg,
+ unsigned int *val)
+{
+ struct ad5764_state *st = iio_priv(indio_dev);
+ struct spi_message m;
+ int ret;
+ struct spi_transfer t[] = {
+ {
+ .tx_buf = &st->data[0].d8[1],
+ .len = 3,
+ .cs_change = 1,
+ }, {
+ .rx_buf = &st->data[1].d8[1],
+ .len = 3,
+ },
+ };
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t[0], &m);
+ spi_message_add_tail(&t[1], &m);
+
+ mutex_lock(&indio_dev->mlock);
+
+ st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16));
+
+ ret = spi_sync(st->spi, &m);
+ if (ret >= 0)
+ *val = be32_to_cpu(st->data[1].d32) & 0xffff;
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static int ad5764_chan_info_to_reg(struct iio_chan_spec const *chan, long info)
+{
+ switch (info) {
+ case 0:
+ return AD5764_REG_DATA(chan->address);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return AD5764_REG_OFFSET(chan->address);
+ case IIO_CHAN_INFO_CALIBSCALE:
+ return AD5764_REG_FINE_GAIN(chan->address);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int ad5764_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2, long info)
+{
+ const int max_val = (1 << chan->scan_type.realbits);
+ unsigned int reg;
+
+ switch (info) {
+ case 0:
+ if (val >= max_val || val < 0)
+ return -EINVAL;
+ val <<= chan->scan_type.shift;
+ break;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ if (val >= 128 || val < -128)
+ return -EINVAL;
+ break;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ if (val >= 32 || val < -32)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ reg = ad5764_chan_info_to_reg(chan, info);
+ return ad5764_write(indio_dev, reg, (u16)val);
+}
+
+static int ad5764_get_channel_vref(struct ad5764_state *st,
+ unsigned int channel)
+{
+ if (st->chip_info->int_vref)
+ return st->chip_info->int_vref;
+ else
+ return regulator_get_voltage(st->vref_reg[channel / 2].consumer);
+}
+
+static int ad5764_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val, int *val2, long info)
+{
+ struct ad5764_state *st = iio_priv(indio_dev);
+ unsigned long scale_uv;
+ unsigned int reg;
+ int vref;
+ int ret;
+
+ switch (info) {
+ case 0:
+ reg = AD5764_REG_DATA(chan->address);
+ ret = ad5764_read(indio_dev, reg, val);
+ if (ret < 0)
+ return ret;
+ *val >>= chan->scan_type.shift;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ reg = AD5764_REG_OFFSET(chan->address);
+ ret = ad5764_read(indio_dev, reg, val);
+ if (ret < 0)
+ return ret;
+ *val = sign_extend32(*val, 7);
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ reg = AD5764_REG_FINE_GAIN(chan->address);
+ ret = ad5764_read(indio_dev, reg, val);
+ if (ret < 0)
+ return ret;
+ *val = sign_extend32(*val, 5);
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ /* vout = 4 * vref + ((dac_code / 65535) - 0.5) */
+ vref = ad5764_get_channel_vref(st, chan->channel);
+ if (vref < 0)
+ return vref;
+
+ scale_uv = (vref * 4 * 100) >> chan->scan_type.realbits;
+ *val = scale_uv / 100000;
+ *val2 = (scale_uv % 100000) * 10;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_OFFSET:
+ *val = -(1 << chan->scan_type.realbits) / 2;
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info ad5764_info = {
+ .read_raw = ad5764_read_raw,
+ .write_raw = ad5764_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit ad5764_probe(struct spi_device *spi)
+{
+ enum ad5764_type type = spi_get_device_id(spi)->driver_data;
+ struct iio_dev *indio_dev;
+ struct ad5764_state *st;
+ int ret;
+
+ indio_dev = iio_allocate_device(sizeof(*st));
+ if (indio_dev == NULL) {
+ dev_err(&spi->dev, "Failed to allocate iio device\n");
+ return -ENOMEM;
+ }
+
+ st = iio_priv(indio_dev);
+ spi_set_drvdata(spi, indio_dev);
+
+ st->spi = spi;
+ st->chip_info = &ad5764_chip_infos[type];
+
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->info = &ad5764_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->num_channels = AD5764_NUM_CHANNELS;
+ indio_dev->channels = st->chip_info->channels;
+
+ if (st->chip_info->int_vref == 0) {
+ st->vref_reg[0].supply = "vrefAB";
+ st->vref_reg[1].supply = "vrefCD";
+
+ ret = regulator_bulk_get(&st->spi->dev,
+ ARRAY_SIZE(st->vref_reg), st->vref_reg);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to request vref regulators: %d\n",
+ ret);
+ goto error_free;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(st->vref_reg),
+ st->vref_reg);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to enable vref regulators: %d\n",
+ ret);
+ goto error_free_reg;
+ }
+ }
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to register iio device: %d\n", ret);
+ goto error_disable_reg;
+ }
+
+ return 0;
+
+error_disable_reg:
+ if (st->chip_info->int_vref == 0)
+ regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg);
+error_free_reg:
+ if (st->chip_info->int_vref == 0)
+ regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg);
+error_free:
+ iio_free_device(indio_dev);
+
+ return ret;
+}
+
+static int __devexit ad5764_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad5764_state *st = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+
+ if (st->chip_info->int_vref == 0) {
+ regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg);
+ regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg);
+ }
+
+ iio_free_device(indio_dev);
+
+ return 0;
+}
+
+static const struct spi_device_id ad5764_ids[] = {
+ { "ad5744", ID_AD5744 },
+ { "ad5744r", ID_AD5744R },
+ { "ad5764", ID_AD5764 },
+ { "ad5764r", ID_AD5764R },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad5764_ids);
+
+static struct spi_driver ad5764_driver = {
+ .driver = {
+ .name = "ad5764",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad5764_probe,
+ .remove = __devexit_p(ad5764_remove),
+ .id_table = ad5764_ids,
+};
+
+static int __init ad5764_spi_init(void)
+{
+ return spi_register_driver(&ad5764_driver);
+}
+module_init(ad5764_spi_init);
+
+static void __exit ad5764_spi_exit(void)
+{
+ spi_unregister_driver(&ad5764_driver);
+}
+module_exit(ad5764_spi_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices AD5744/AD5744R/AD5764/AD5764R DAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c
index 4a80fd822231..ac45636a8d72 100644
--- a/drivers/staging/iio/dac/ad5791.c
+++ b/drivers/staging/iio/dac/ad5791.c
@@ -1,5 +1,6 @@
/*
- * AD5760, AD5780, AD5781, AD5791 Voltage Output Digital to Analog Converter
+ * AD5760, AD5780, AD5781, AD5790, AD5791 Voltage Output Digital to Analog
+ * Converter
*
* Copyright 2011 Analog Devices Inc.
*
@@ -77,8 +78,8 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
.indexed = 1, \
.address = AD5791_ADDR_DAC0, \
.channel = 0, \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED) | \
- (1 << IIO_CHAN_INFO_OFFSET_SHARED), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
.scan_type = IIO_ST('u', bits, 24, shift) \
}
@@ -237,11 +238,11 @@ static int ad5791_read_raw(struct iio_dev *indio_dev,
*val &= AD5791_DAC_MASK;
*val >>= chan->scan_type.shift;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits;
return IIO_VAL_INT_PLUS_MICRO;
- case (1 << IIO_CHAN_INFO_OFFSET_SHARED):
+ case IIO_CHAN_INFO_OFFSET:
val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits);
do_div(val64, st->vref_mv);
*val = -val64;
@@ -397,9 +398,11 @@ static const struct spi_device_id ad5791_id[] = {
{"ad5760", ID_AD5760},
{"ad5780", ID_AD5780},
{"ad5781", ID_AD5781},
+ {"ad5790", ID_AD5791},
{"ad5791", ID_AD5791},
{}
};
+MODULE_DEVICE_TABLE(spi, ad5791_id);
static struct spi_driver ad5791_driver = {
.driver = {
@@ -413,5 +416,5 @@ static struct spi_driver ad5791_driver = {
module_spi_driver(ad5791_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5791 DAC");
+MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c
index 4a360d044a36..9c32d1beae25 100644
--- a/drivers/staging/iio/dds/ad5930.c
+++ b/drivers/staging/iio/dds/ad5930.c
@@ -148,3 +148,4 @@ module_spi_driver(ad5930_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad5930 driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:" DRV_NAME);
diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c
index cc32fd65b8b3..2ccf25dd9289 100644
--- a/drivers/staging/iio/dds/ad9832.c
+++ b/drivers/staging/iio/dds/ad9832.c
@@ -88,7 +88,7 @@ static ssize_t ad9832_write(struct device *dev,
goto error_ret;
mutex_lock(&indio_dev->mlock);
- switch (this_attr->address) {
+ switch ((u32) this_attr->address) {
case AD9832_FREQ0HM:
case AD9832_FREQ1HM:
ret = ad9832_write_frequency(st, this_attr->address, val);
@@ -344,11 +344,11 @@ static const struct spi_device_id ad9832_id[] = {
{"ad9835", 0},
{}
};
+MODULE_DEVICE_TABLE(spi, ad9832_id);
static struct spi_driver ad9832_driver = {
.driver = {
.name = "ad9832",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad9832_probe,
@@ -360,4 +360,3 @@ module_spi_driver(ad9832_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD9832/AD9835 DDS");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:ad9832");
diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c
index 51fda6f69815..5e67104fea18 100644
--- a/drivers/staging/iio/dds/ad9834.c
+++ b/drivers/staging/iio/dds/ad9834.c
@@ -77,7 +77,7 @@ static ssize_t ad9834_write(struct device *dev,
goto error_ret;
mutex_lock(&indio_dev->mlock);
- switch (this_attr->address) {
+ switch ((u32) this_attr->address) {
case AD9834_REG_FREQ0:
case AD9834_REG_FREQ1:
ret = ad9834_write_frequency(st, this_attr->address, val);
@@ -153,7 +153,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
mutex_lock(&indio_dev->mlock);
- switch (this_attr->address) {
+ switch ((u32) this_attr->address) {
case 0:
if (sysfs_streq(buf, "sine")) {
st->control &= ~AD9834_MODE;
@@ -435,11 +435,11 @@ static const struct spi_device_id ad9834_id[] = {
{"ad9838", ID_AD9838},
{}
};
+MODULE_DEVICE_TABLE(spi, ad9834_id);
static struct spi_driver ad9834_driver = {
.driver = {
.name = "ad9834",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ad9834_probe,
@@ -451,4 +451,3 @@ module_spi_driver(ad9834_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD9833/AD9834/AD9837/AD9838 DDS");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:ad9834");
diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c
index f9c96afcb996..f4f731bb2191 100644
--- a/drivers/staging/iio/dds/ad9850.c
+++ b/drivers/staging/iio/dds/ad9850.c
@@ -134,3 +134,4 @@ module_spi_driver(ad9850_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad9850 driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:" DRV_NAME);
diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c
index 9fc73fdc9c3b..554266c615a8 100644
--- a/drivers/staging/iio/dds/ad9852.c
+++ b/drivers/staging/iio/dds/ad9852.c
@@ -285,3 +285,4 @@ module_spi_driver(ad9852_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad9852 driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:" DRV_NAME);
diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c
index 57046b03121f..3985766d6f87 100644
--- a/drivers/staging/iio/dds/ad9910.c
+++ b/drivers/staging/iio/dds/ad9910.c
@@ -418,3 +418,4 @@ module_spi_driver(ad9910_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad9910 driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:" DRV_NAME);
diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c
index d29130e9acdf..4d150048002a 100644
--- a/drivers/staging/iio/dds/ad9951.c
+++ b/drivers/staging/iio/dds/ad9951.c
@@ -229,3 +229,4 @@ module_spi_driver(ad9951_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("Analog Devices ad9951 driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:" DRV_NAME);
diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h
new file mode 100644
index 000000000000..bfb63400fa60
--- /dev/null
+++ b/drivers/staging/iio/events.h
@@ -0,0 +1,103 @@
+/* The industrial I/O - event passing to userspace
+ *
+ * Copyright (c) 2008-2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef _IIO_EVENTS_H_
+#define _IIO_EVENTS_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include "types.h"
+
+/**
+ * struct iio_event_data - The actual event being pushed to userspace
+ * @id: event identifier
+ * @timestamp: best estimate of time of event occurrence (often from
+ * the interrupt handler)
+ */
+struct iio_event_data {
+ __u64 id;
+ __s64 timestamp;
+};
+
+#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int)
+
+enum iio_event_type {
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_TYPE_MAG,
+ IIO_EV_TYPE_ROC,
+ IIO_EV_TYPE_THRESH_ADAPTIVE,
+ IIO_EV_TYPE_MAG_ADAPTIVE,
+};
+
+enum iio_event_direction {
+ IIO_EV_DIR_EITHER,
+ IIO_EV_DIR_RISING,
+ IIO_EV_DIR_FALLING,
+};
+
+/**
+ * IIO_EVENT_CODE() - create event identifier
+ * @chan_type: Type of the channel. Should be one of enum iio_chan_type.
+ * @diff: Whether the event is for an differential channel or not.
+ * @modifier: Modifier for the channel. Should be one of enum iio_modifier.
+ * @direction: Direction of the event. One of enum iio_event_direction.
+ * @type: Type of the event. Should be one enum iio_event_type.
+ * @chan: Channel number for non-differential channels.
+ * @chan1: First channel number for differential channels.
+ * @chan2: Second channel number for differential channels.
+ */
+
+#define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \
+ type, chan, chan1, chan2) \
+ (((u64)type << 56) | ((u64)diff << 55) | \
+ ((u64)direction << 48) | ((u64)modifier << 40) | \
+ ((u64)chan_type << 32) | (((u16)chan2) << 16) | ((u16)chan1) | \
+ ((u16)chan))
+
+
+#define IIO_EV_DIR_MAX 4
+#define IIO_EV_BIT(type, direction) \
+ (1 << (type*IIO_EV_DIR_MAX + direction))
+
+/**
+ * IIO_MOD_EVENT_CODE() - create event identifier for modified channels
+ * @chan_type: Type of the channel. Should be one of enum iio_chan_type.
+ * @number: Channel number.
+ * @modifier: Modifier for the channel. Should be one of enum iio_modifier.
+ * @type: Type of the event. Should be one enum iio_event_type.
+ * @direction: Direction of the event. One of enum iio_event_direction.
+ */
+
+#define IIO_MOD_EVENT_CODE(chan_type, number, modifier, \
+ type, direction) \
+ IIO_EVENT_CODE(chan_type, 0, modifier, direction, type, number, 0, 0)
+
+/**
+ * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified channels
+ * @chan_type: Type of the channel. Should be one of enum iio_chan_type.
+ * @number: Channel number.
+ * @type: Type of the event. Should be one enum iio_event_type.
+ * @direction: Direction of the event. One of enum iio_event_direction.
+ */
+
+#define IIO_UNMOD_EVENT_CODE(chan_type, number, type, direction) \
+ IIO_EVENT_CODE(chan_type, 0, 0, direction, type, number, 0, 0)
+
+#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF)
+
+#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF)
+
+#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF)
+
+/* Event code number extraction depends on which type of event we have.
+ * Perhaps review this function in the future*/
+#define IIO_EVENT_CODE_EXTRACT_NUM(mask) ((__s16)(mask & 0xFFFF))
+
+#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF)
+
+#endif
diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig
index 22aea5b4e61d..ea295b25308c 100644
--- a/drivers/staging/iio/gyro/Kconfig
+++ b/drivers/staging/iio/gyro/Kconfig
@@ -37,11 +37,11 @@ config ADIS16260
will be called adis16260.
config ADXRS450
- tristate "Analog Devices ADXRS450 Digital Output Gyroscope SPI driver"
+ tristate "Analog Devices ADXRS450/3 Digital Output Gyroscope SPI driver"
depends on SPI
help
- Say yes here to build support for Analog Devices ADXRS450 programmable
- digital output gyroscope.
+ Say yes here to build support for Analog Devices ADXRS450 and ADXRS453
+ programmable digital output gyroscope.
This driver can also be built as a module. If so, the module
will be called adxrs450.
diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
index ff1b5a82b3d6..c0ca7093e0ed 100644
--- a/drivers/staging/iio/gyro/adis16060_core.c
+++ b/drivers/staging/iio/gyro/adis16060_core.c
@@ -98,11 +98,11 @@ static int adis16060_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&indio_dev->mlock);
*val = tval;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
*val = -7;
*val2 = 461117;
return IIO_VAL_INT_PLUS_MICRO;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = 34000;
return IIO_VAL_INT_PLUS_MICRO;
@@ -136,8 +136,8 @@ static const struct iio_chan_spec adis16060_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = ADIS16060_TEMP_OUT,
}
};
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
index 9405f2d368ee..1815490db8b4 100644
--- a/drivers/staging/iio/gyro/adis16080_core.c
+++ b/drivers/staging/iio/gyro/adis16080_core.c
@@ -194,3 +194,4 @@ module_spi_driver(adis16080_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:adis16080");
diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
index c9aaca9631f4..947eb86f05d8 100644
--- a/drivers/staging/iio/gyro/adis16130_core.c
+++ b/drivers/staging/iio/gyro/adis16130_core.c
@@ -173,3 +173,4 @@ module_spi_driver(adis16130_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:adis16130");
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index 886dddf867ef..8f6af47e9559 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -20,7 +20,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "adis16260.h"
@@ -390,9 +390,9 @@ enum adis16260_channel {
#define ADIS16260_GYRO_CHANNEL_SET(axis, mod) \
struct iio_chan_spec adis16260_channels_##axis[] = { \
IIO_CHAN(IIO_ANGL_VEL, 1, 0, 0, NULL, 0, mod, \
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | \
- (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
gyro, ADIS16260_SCAN_GYRO, \
IIO_ST('s', 14, 16, 0), 0), \
IIO_CHAN(IIO_ANGL, 1, 0, 0, NULL, 0, mod, \
@@ -400,16 +400,16 @@ enum adis16260_channel {
angle, ADIS16260_SCAN_ANGL, \
IIO_ST('u', 14, 16, 0), 0), \
IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, \
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | \
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
temp, ADIS16260_SCAN_TEMP, \
IIO_ST('u', 12, 16, 0), 0), \
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, \
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
in_supply, ADIS16260_SCAN_SUPPLY, \
IIO_ST('u', 12, 16, 0), 0), \
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, \
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
in_aux, ADIS16260_SCAN_AUX_ADC, \
IIO_ST('u', 12, 16, 0), 0), \
IIO_CHAN_SOFT_TIMESTAMP(5) \
@@ -464,8 +464,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
*val = 0;
@@ -489,10 +488,10 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
break;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
*val = 25;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ANGL_VEL:
bits = 12;
@@ -512,7 +511,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
bits = 12;
@@ -544,11 +543,11 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
s16 val16;
u8 addr;
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
val16 = val & ((1 << bits) - 1);
addr = adis16260_addresses[chan->address][1];
return adis16260_spi_write_reg_16(indio_dev, addr, val16);
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
val16 = val & ((1 << bits) - 1);
addr = adis16260_addresses[chan->address][2];
return adis16260_spi_write_reg_16(indio_dev, addr, val16);
@@ -633,11 +632,16 @@ static int __devinit adis16260_probe(struct spi_device *spi)
}
if (indio_dev->buffer) {
/* Set default scan mode */
- iio_scan_mask_set(indio_dev->buffer, ADIS16260_SCAN_SUPPLY);
- iio_scan_mask_set(indio_dev->buffer, ADIS16260_SCAN_GYRO);
- iio_scan_mask_set(indio_dev->buffer, ADIS16260_SCAN_AUX_ADC);
- iio_scan_mask_set(indio_dev->buffer, ADIS16260_SCAN_TEMP);
- iio_scan_mask_set(indio_dev->buffer, ADIS16260_SCAN_ANGL);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer,
+ ADIS16260_SCAN_SUPPLY);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer,
+ ADIS16260_SCAN_GYRO);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer,
+ ADIS16260_SCAN_AUX_ADC);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer,
+ ADIS16260_SCAN_TEMP);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer,
+ ADIS16260_SCAN_ANGL);
}
if (spi->irq) {
ret = adis16260_probe_trigger(indio_dev);
@@ -701,6 +705,7 @@ static const struct spi_device_id adis16260_id[] = {
{"adis16251", 1},
{}
};
+MODULE_DEVICE_TABLE(spi, adis16260_id);
static struct spi_driver adis16260_driver = {
.driver = {
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
index 52a9e784e7c8..699a6152c409 100644
--- a/drivers/staging/iio/gyro/adis16260_ring.c
+++ b/drivers/staging/iio/gyro/adis16260_ring.c
@@ -74,9 +74,10 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p)
return -ENOMEM;
}
- if (ring->scan_count &&
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
adis16260_read_ring_data(&indio_dev->dev, st->rx) >= 0)
- for (; i < ring->scan_count; i++)
+ for (; i < bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
@@ -116,10 +117,8 @@ int adis16260_configure_ring(struct iio_dev *indio_dev)
indio_dev->buffer = ring;
/* Effectively select the ring buffer implementation */
ring->access = &ring_sw_access_funcs;
- ring->bpe = 2;
ring->scan_timestamp = true;
- ring->setup_ops = &adis16260_ring_setup_ops;
- ring->owner = THIS_MODULE;
+ indio_dev->setup_ops = &adis16260_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16260_trigger_handler,
diff --git a/drivers/staging/iio/gyro/adxrs450.h b/drivers/staging/iio/gyro/adxrs450.h
index b6b682876406..af0c870100b6 100644
--- a/drivers/staging/iio/gyro/adxrs450.h
+++ b/drivers/staging/iio/gyro/adxrs450.h
@@ -39,6 +39,11 @@
#define ADXRS450_GET_ST(a) ((a >> 26) & 0x3)
+enum {
+ ID_ADXRS450,
+ ID_ADXRS453,
+};
+
/**
* struct adxrs450_state - device instance specific data
* @us: actual spi_device
diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c
index 70fd468b6850..15e2496f70c8 100644
--- a/drivers/staging/iio/gyro/adxrs450_core.c
+++ b/drivers/staging/iio/gyro/adxrs450_core.c
@@ -1,5 +1,5 @@
/*
- * ADXRS450 Digital Output Gyroscope Driver
+ * ADXRS450/ADXRS453 Digital Output Gyroscope Driver
*
* Copyright 2011 Analog Devices Inc.
*
@@ -243,7 +243,7 @@ static int adxrs450_write_raw(struct iio_dev *indio_dev,
{
int ret;
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
ret = adxrs450_spi_write_reg_16(indio_dev,
ADXRS450_DNC1,
val & 0x3FF);
@@ -263,7 +263,7 @@ static int adxrs450_read_raw(struct iio_dev *indio_dev,
{
int ret;
s16 t;
- u16 ut;
+
switch (mask) {
case 0:
switch (chan->type) {
@@ -276,10 +276,10 @@ static int adxrs450_read_raw(struct iio_dev *indio_dev,
break;
case IIO_TEMP:
ret = adxrs450_spi_read_reg_16(indio_dev,
- ADXRS450_TEMP1, &ut);
+ ADXRS450_TEMP1, &t);
if (ret)
break;
- *val = ut;
+ *val = (t >> 6) + 225;
ret = IIO_VAL_INT;
break;
default:
@@ -287,13 +287,34 @@ static int adxrs450_read_raw(struct iio_dev *indio_dev,
break;
}
break;
- case (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *val = 0;
+ *val2 = 218166;
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_TEMP:
+ *val = 200;
+ *val2 = 0;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW:
ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t);
if (ret)
break;
*val = t;
ret = IIO_VAL_INT;
break;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t);
+ if (ret)
+ break;
+ *val = t;
+ ret = IIO_VAL_INT;
+ break;
default:
ret = -EINVAL;
break;
@@ -302,18 +323,36 @@ static int adxrs450_read_raw(struct iio_dev *indio_dev,
return ret;
}
-static const struct iio_chan_spec adxrs450_channels[] = {
- {
- .type = IIO_ANGL_VEL,
- .modified = 1,
- .channel2 = IIO_MOD_Z,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE)
- }, {
- .type = IIO_TEMP,
- .indexed = 1,
- .channel = 0,
- }
+static const struct iio_chan_spec adxrs450_channels[2][2] = {
+ [ID_ADXRS450] = {
+ {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ }
+ },
+ [ID_ADXRS453] = {
+ {
+ .type = IIO_ANGL_VEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT,
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ }
+ },
};
static const struct iio_info adxrs450_info = {
@@ -343,7 +382,8 @@ static int __devinit adxrs450_probe(struct spi_device *spi)
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adxrs450_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels = adxrs450_channels;
+ indio_dev->channels =
+ adxrs450_channels[spi_get_device_id(spi)->driver_data];
indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels);
indio_dev->name = spi->dev.driver->name;
@@ -373,6 +413,13 @@ static int adxrs450_remove(struct spi_device *spi)
return 0;
}
+static const struct spi_device_id adxrs450_id[] = {
+ {"adxrs450", ID_ADXRS450},
+ {"adxrs453", ID_ADXRS453},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, adxrs450_id);
+
static struct spi_driver adxrs450_driver = {
.driver = {
.name = "adxrs450",
@@ -380,9 +427,10 @@ static struct spi_driver adxrs450_driver = {
},
.probe = adxrs450_probe,
.remove = __devexit_p(adxrs450_remove),
+ .id_table = adxrs450_id,
};
module_spi_driver(adxrs450_driver);
MODULE_AUTHOR("Cliff Cai <cliff.cai@xxxxxxxxxx>");
-MODULE_DESCRIPTION("Analog Devices ADXRS450 Gyroscope SPI driver");
+MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index f3d88cd7e8a0..be6ced31f65e 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -7,13 +7,12 @@
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
-
#ifndef _INDUSTRIAL_IO_H_
#define _INDUSTRIAL_IO_H_
#include <linux/device.h>
#include <linux/cdev.h>
-
+#include "types.h"
/* IIO TODO LIST */
/*
* Provide means of adjusting timer accuracy.
@@ -25,62 +24,64 @@ enum iio_data_type {
IIO_PROCESSED,
};
-enum iio_chan_type {
- /* real channel types */
- IIO_VOLTAGE,
- IIO_CURRENT,
- IIO_POWER,
- IIO_ACCEL,
- IIO_ANGL_VEL,
- IIO_MAGN,
- IIO_LIGHT,
- IIO_INTENSITY,
- IIO_PROXIMITY,
- IIO_TEMP,
- IIO_INCLI,
- IIO_ROT,
- IIO_ANGL,
- IIO_TIMESTAMP,
- IIO_CAPACITANCE,
-};
-
-enum iio_modifier {
- IIO_NO_MOD,
- IIO_MOD_X,
- IIO_MOD_Y,
- IIO_MOD_Z,
- IIO_MOD_X_AND_Y,
- IIO_MOD_X_ANX_Z,
- IIO_MOD_Y_AND_Z,
- IIO_MOD_X_AND_Y_AND_Z,
- IIO_MOD_X_OR_Y,
- IIO_MOD_X_OR_Z,
- IIO_MOD_Y_OR_Z,
- IIO_MOD_X_OR_Y_OR_Z,
- IIO_MOD_LIGHT_BOTH,
- IIO_MOD_LIGHT_IR,
-};
-
/* Could add the raw attributes as well - allowing buffer only devices */
enum iio_chan_info_enum {
- IIO_CHAN_INFO_SCALE_SHARED,
- IIO_CHAN_INFO_SCALE_SEPARATE,
- IIO_CHAN_INFO_OFFSET_SHARED,
- IIO_CHAN_INFO_OFFSET_SEPARATE,
- IIO_CHAN_INFO_CALIBSCALE_SHARED,
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE,
- IIO_CHAN_INFO_CALIBBIAS_SHARED,
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE,
- IIO_CHAN_INFO_PEAK_SHARED,
- IIO_CHAN_INFO_PEAK_SEPARATE,
- IIO_CHAN_INFO_PEAK_SCALE_SHARED,
- IIO_CHAN_INFO_PEAK_SCALE_SEPARATE,
- IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED,
- IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE,
- IIO_CHAN_INFO_AVERAGE_RAW_SHARED,
- IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE,
+ /* 0 is reserverd for raw attributes */
+ IIO_CHAN_INFO_SCALE = 1,
+ IIO_CHAN_INFO_OFFSET,
+ IIO_CHAN_INFO_CALIBSCALE,
+ IIO_CHAN_INFO_CALIBBIAS,
+ IIO_CHAN_INFO_PEAK,
+ IIO_CHAN_INFO_PEAK_SCALE,
+ IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW,
+ IIO_CHAN_INFO_AVERAGE_RAW,
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY,
};
+#define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2)
+#define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1)
+
+#define IIO_CHAN_INFO_SCALE_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SCALE)
+#define IIO_CHAN_INFO_SCALE_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SCALE)
+#define IIO_CHAN_INFO_OFFSET_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_OFFSET)
+#define IIO_CHAN_INFO_OFFSET_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_OFFSET)
+#define IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBSCALE)
+#define IIO_CHAN_INFO_CALIBSCALE_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBSCALE)
+#define IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBBIAS)
+#define IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBBIAS)
+#define IIO_CHAN_INFO_PEAK_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAK)
+#define IIO_CHAN_INFO_PEAK_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAK)
+#define IIO_CHAN_INFO_PEAKSCALE_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAKSCALE)
+#define IIO_CHAN_INFO_PEAKSCALE_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAKSCALE)
+#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT( \
+ IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW)
+#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT( \
+ IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW)
+#define IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_AVERAGE_RAW)
+#define IIO_CHAN_INFO_AVERAGE_RAW_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_AVERAGE_RAW)
+#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT( \
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY)
+#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT( \
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY)
+
enum iio_endian {
IIO_CPU,
IIO_BE,
@@ -109,6 +110,10 @@ enum iio_endian {
* @extend_name: Allows labeling of channel attributes with an
* informative name. Note this has no effect codes etc,
* unlike modifiers.
+ * @datasheet_name: A name used in in kernel mapping of channels. It should
+ * corrspond to the first name that the channel is referred
+ * to by in the datasheet (e.g. IND), or the nearest
+ * possible compound name (e.g. IND-INC).
* @processed_val: Flag to specify the data access attribute should be
* *_input rather than *_raw.
* @modified: Does a modifier apply to this channel. What these are
@@ -137,6 +142,7 @@ struct iio_chan_spec {
long info_mask;
long event_mask;
char *extend_name;
+ const char *datasheet_name;
unsigned processed_val:1;
unsigned modified:1;
unsigned indexed:1;
@@ -261,7 +267,23 @@ struct iio_info {
int val);
int (*validate_trigger)(struct iio_dev *indio_dev,
struct iio_trigger *trig);
+ int (*update_scan_mode)(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask);
+};
+/**
+ * struct iio_buffer_setup_ops - buffer setup related callbacks
+ * @preenable: [DRIVER] function to run prior to marking buffer enabled
+ * @postenable: [DRIVER] function to run after marking buffer enabled
+ * @predisable: [DRIVER] function to run prior to marking buffer
+ * disabled
+ * @postdisable: [DRIVER] function to run after marking buffer disabled
+ */
+struct iio_buffer_setup_ops {
+ int (*preenable)(struct iio_dev *);
+ int (*postenable)(struct iio_dev *);
+ int (*predisable)(struct iio_dev *);
+ int (*postdisable)(struct iio_dev *);
};
/**
@@ -278,6 +300,7 @@ struct iio_info {
* @available_scan_masks: [DRIVER] optional array of allowed bitmasks
* @masklength: [INTERN] the length of the mask established from
* channels
+ * @active_scan_mask: [INTERN] union of all scan masks requested by buffers
* @trig: [INTERN] current device trigger (buffer modes)
* @pollfunc: [DRIVER] function run on trigger being received
* @channels: [DRIVER] channel specification structure table
@@ -290,6 +313,7 @@ struct iio_info {
* @chrdev: [INTERN] associated character device
* @groups: [INTERN] attribute groups
* @groupcounter: [INTERN] index of next attribute group
+ * @flags: [INTERN] file ops related flags including busy flag.
**/
struct iio_dev {
int id;
@@ -305,6 +329,7 @@ struct iio_dev {
unsigned long *available_scan_masks;
unsigned masklength;
+ unsigned long *active_scan_mask;
struct iio_trigger *trig;
struct iio_poll_func *pollfunc;
@@ -315,13 +340,24 @@ struct iio_dev {
struct attribute_group chan_attr_group;
const char *name;
const struct iio_info *info;
+ const struct iio_buffer_setup_ops *setup_ops;
struct cdev chrdev;
#define IIO_MAX_GROUPS 6
const struct attribute_group *groups[IIO_MAX_GROUPS + 1];
int groupcounter;
+
+ unsigned long flags;
};
/**
+ * iio_find_channel_from_si() - get channel from its scan index
+ * @indio_dev: device
+ * @si: scan index to match
+ */
+const struct iio_chan_spec
+*iio_find_channel_from_si(struct iio_dev *indio_dev, int si);
+
+/**
* iio_device_register() - register a device with the IIO subsystem
* @indio_dev: Device structure filled by the device driver
**/
diff --git a/drivers/staging/iio/iio_core.h b/drivers/staging/iio/iio_core.h
index 36159e0dbfc3..107cfb1cbb01 100644
--- a/drivers/staging/iio/iio_core.h
+++ b/drivers/staging/iio/iio_core.h
@@ -33,9 +33,6 @@ int __iio_add_chan_devattr(const char *postfix,
#ifdef CONFIG_IIO_BUFFER
struct poll_table_struct;
-int iio_chrdev_buffer_open(struct iio_dev *indio_dev);
-void iio_chrdev_buffer_release(struct iio_dev *indio_dev);
-
unsigned int iio_buffer_poll(struct file *filp,
struct poll_table_struct *wait);
ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
@@ -47,14 +44,6 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
#else
-static inline int iio_chrdev_buffer_open(struct iio_dev *indio_dev)
-{
- return -EINVAL;
-}
-
-static inline void iio_chrdev_buffer_release(struct iio_dev *indio_dev)
-{}
-
#define iio_buffer_poll_addr NULL
#define iio_buffer_read_first_n_outer_addr NULL
diff --git a/drivers/staging/iio/iio_core_trigger.h b/drivers/staging/iio/iio_core_trigger.h
index 523c288b776b..6f7c56fcbe78 100644
--- a/drivers/staging/iio/iio_core_trigger.h
+++ b/drivers/staging/iio/iio_core_trigger.h
@@ -13,8 +13,7 @@
* iio_device_register_trigger_consumer() - set up an iio_dev to use triggers
* @indio_dev: iio_dev associated with the device that will consume the trigger
**/
-
-int iio_device_register_trigger_consumer(struct iio_dev *indio_dev);
+void iio_device_register_trigger_consumer(struct iio_dev *indio_dev);
/**
* iio_device_unregister_trigger_consumer() - reverse the registration process
diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c
index da657d10471d..cdbf289bfe2d 100644
--- a/drivers/staging/iio/iio_dummy_evgen.c
+++ b/drivers/staging/iio/iio_dummy_evgen.c
@@ -102,6 +102,10 @@ static int iio_dummy_evgen_create(void)
int iio_dummy_evgen_get_irq(void)
{
int i, ret = 0;
+
+ if (iio_evgen == NULL)
+ return -ENODEV;
+
mutex_lock(&iio_evgen->lock);
for (i = 0; i < IIO_EVENTGEN_NO; i++)
if (iio_evgen->inuse[i] == false) {
diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c
index af0c99236d4f..e3a94572bb40 100644
--- a/drivers/staging/iio/iio_simple_dummy.c
+++ b/drivers/staging/iio/iio_simple_dummy.c
@@ -21,7 +21,8 @@
#include "iio.h"
#include "sysfs.h"
-#include "buffer_generic.h"
+#include "events.h"
+#include "buffer.h"
#include "iio_simple_dummy.h"
/*
@@ -76,13 +77,13 @@ static struct iio_chan_spec iio_dummy_channels[] = {
* Offset for userspace to apply prior to scale
* when converting to standard units (microvolts)
*/
- (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
/*
* in_voltage0_scale
* Multipler for userspace to apply post offset
* when converting to standard units (microvolts)
*/
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
/* The ordering of elements in the buffer via an enum */
.scan_index = voltage0,
.scan_type = { /* Description of storage in buffer */
@@ -117,7 +118,7 @@ static struct iio_chan_spec iio_dummy_channels[] = {
* Shared version of scale - shared by differential
* input channels of type IIO_VOLTAGE.
*/
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = diffvoltage1m2,
.scan_type = { /* Description of storage in buffer */
.sign = 's', /* signed */
@@ -134,7 +135,7 @@ static struct iio_chan_spec iio_dummy_channels[] = {
.channel = 3,
.channel2 = 4,
.info_mask =
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = diffvoltage3m4,
.scan_type = {
.sign = 's',
@@ -159,7 +160,7 @@ static struct iio_chan_spec iio_dummy_channels[] = {
* seeing the readings. Typically part of hardware
* calibration.
*/
- (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE),
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
.scan_index = accelx,
.scan_type = { /* Description of storage in buffer */
.sign = 's', /* signed */
@@ -228,29 +229,32 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev,
break;
}
break;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
/* only single ended adc -> 7 */
*val = 7;
ret = IIO_VAL_INT;
break;
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
- /* only single ended adc -> 0.001333 */
- *val = 0;
- *val2 = 1333;
- ret = IIO_VAL_INT_PLUS_MICRO;
- break;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
- /* all differential adc channels -> 0.000001344 */
- *val = 0;
- *val2 = 1344;
- ret = IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->differential) {
+ case 0:
+ /* only single ended adc -> 0.001333 */
+ *val = 0;
+ *val2 = 1333;
+ ret = IIO_VAL_INT_PLUS_MICRO;
+ break;
+ case 1:
+ /* all differential adc channels -> 0.000001344 */
+ *val = 0;
+ *val2 = 1344;
+ ret = IIO_VAL_INT_PLUS_NANO;
+ }
break;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
/* only the acceleration axis - read from cache */
*val = st->accel_calibbias;
ret = IIO_VAL_INT;
break;
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
*val = st->accel_calibscale->val;
*val2 = st->accel_calibscale->val2;
ret = IIO_VAL_INT_PLUS_MICRO;
@@ -295,7 +299,7 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev,
st->dac_val = val;
mutex_unlock(&st->lock);
return 0;
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
mutex_lock(&st->lock);
/* Compare against table - hard matching here */
for (i = 0; i < ARRAY_SIZE(dummy_scales); i++)
@@ -514,7 +518,8 @@ static __init int iio_dummy_init(void)
return -EINVAL;
}
/* Fake a bus */
- iio_dummy_devs = kzalloc(sizeof(*iio_dummy_devs)*instances, GFP_KERNEL);
+ iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs),
+ GFP_KERNEL);
/* Here we have no actual device so call probe */
for (i = 0; i < instances; i++) {
ret = iio_dummy_probe(i);
diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c
index edad0e7b4f4d..d6a1c0e82a5b 100644
--- a/drivers/staging/iio/iio_simple_dummy_buffer.c
+++ b/drivers/staging/iio/iio_simple_dummy_buffer.c
@@ -57,7 +57,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
if (data == NULL)
return -ENOMEM;
- if (buffer->scan_count) {
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) {
/*
* Three common options here:
* hardware scans: certain combinations of channels make
@@ -75,7 +75,10 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
* in the constant table fakedata.
*/
int i, j;
- for (i = 0, j = 0; i < buffer->scan_count; i++) {
+ for (i = 0, j = 0;
+ i < bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength);
+ i++) {
j = find_next_bit(buffer->scan_mask,
indio_dev->masklength, j + 1);
/* random access read form the 'device' */
@@ -142,8 +145,6 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
/* Tell the core how to access the buffer */
buffer->access = &kfifo_access_funcs;
- /* Number of bytes per element */
- buffer->bpe = 2;
/* Enable timestamps by default */
buffer->scan_timestamp = true;
@@ -151,8 +152,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
* Tell the core what device type specific functions should
* be run on either side of buffer capture enable / disable.
*/
- buffer->setup_ops = &iio_simple_dummy_buffer_setup_ops;
- buffer->owner = THIS_MODULE;
+ indio_dev->setup_ops = &iio_simple_dummy_buffer_setup_ops;
/*
* Configure a polling function.
diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c
index 9f00cff7ddd5..449c7a5ece80 100644
--- a/drivers/staging/iio/iio_simple_dummy_events.c
+++ b/drivers/staging/iio/iio_simple_dummy_events.c
@@ -14,6 +14,7 @@
#include "iio.h"
#include "sysfs.h"
+#include "events.h"
#include "iio_simple_dummy.h"
/* Evgen 'fakes' interrupt events for this example */
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 454d131455de..9a2ca55625f4 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -21,7 +21,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "../ring_sw.h"
#include "ad5933.h"
@@ -113,10 +113,10 @@ static struct iio_chan_spec ad5933_channels[] = {
0, AD5933_REG_TEMP_DATA, IIO_ST('s', 14, 16, 0), 0),
/* Ring Channels */
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "real_raw", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
AD5933_REG_REAL_DATA, 0, IIO_ST('s', 16, 16, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "imag_raw", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
AD5933_REG_IMAG_DATA, 1, IIO_ST('s', 16, 16, 0), 0),
};
@@ -329,7 +329,7 @@ static ssize_t ad5933_show(struct device *dev,
int ret = 0, len = 0;
mutex_lock(&indio_dev->mlock);
- switch (this_attr->address) {
+ switch ((u32) this_attr->address) {
case AD5933_OUT_RANGE:
len = sprintf(buf, "%d\n",
st->range_avail[(st->ctrl_hb >> 1) & 0x3]);
@@ -380,7 +380,7 @@ static ssize_t ad5933_store(struct device *dev,
}
mutex_lock(&indio_dev->mlock);
- switch (this_attr->address) {
+ switch ((u32) this_attr->address) {
case AD5933_OUT_RANGE:
for (i = 0; i < 4; i++)
if (val == st->range_avail[i]) {
@@ -537,14 +537,14 @@ static const struct iio_info ad5933_info = {
static int ad5933_ring_preenable(struct iio_dev *indio_dev)
{
struct ad5933_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
size_t d_size;
int ret;
- if (!ring->scan_count)
+ if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
- d_size = ring->scan_count *
+ d_size = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength) *
ad5933_channels[1].scan_type.storagebits / 8;
if (indio_dev->buffer->access->set_bytes_per_datum)
@@ -611,7 +611,7 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->buffer->access = &ring_sw_access_funcs;
/* Ring buffer functions - here trigger setup related */
- indio_dev->buffer->setup_ops = &ad5933_ring_setup_ops;
+ indio_dev->setup_ops = &ad5933_ring_setup_ops;
indio_dev->modes |= INDIO_BUFFER_HARDWARE;
@@ -640,12 +640,14 @@ static void ad5933_work(struct work_struct *work)
ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status);
if (status & AD5933_STAT_DATA_VALID) {
+ int scan_count = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength);
ad5933_i2c_read(st->client,
- test_bit(1, ring->scan_mask) ?
+ test_bit(1, indio_dev->active_scan_mask) ?
AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
- ring->scan_count * 2, (u8 *)buf);
+ scan_count * 2, (u8 *)buf);
- if (ring->scan_count == 2) {
+ if (scan_count == 2) {
buf[0] = be16_to_cpu(buf[0]);
buf[1] = be16_to_cpu(buf[1]);
} else {
@@ -734,8 +736,8 @@ static int __devinit ad5933_probe(struct i2c_client *client,
goto error_unreg_ring;
/* enable both REAL and IMAG channels by default */
- iio_scan_mask_set(indio_dev->buffer, 0);
- iio_scan_mask_set(indio_dev->buffer, 1);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer, 0);
+ iio_scan_mask_set(indio_dev, indio_dev->buffer, 1);
ret = ad5933_setup(st);
if (ret)
diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
index f3546ee910a2..83d133efaac6 100644
--- a/drivers/staging/iio/imu/adis16400.h
+++ b/drivers/staging/iio/imu/adis16400.h
@@ -148,12 +148,14 @@ struct adis16400_chip_info {
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
+ * @filt_int: integer part of requested filter frequency
**/
struct adis16400_state {
struct spi_device *us;
struct iio_trigger *trig;
struct mutex buf_lock;
struct adis16400_chip_info *variant;
+ int filt_int;
u8 tx[ADIS16400_MAX_TX] ____cacheline_aligned;
u8 rx[ADIS16400_MAX_RX] ____cacheline_aligned;
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index efc0f6529008..e73ad7818d85 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -28,7 +28,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "adis16400.h"
enum adis16400_chip_variant {
@@ -161,25 +161,65 @@ error_ret:
return ret;
}
+static int adis16400_get_freq(struct iio_dev *indio_dev)
+{
+ u16 t;
+ int sps, ret;
+
+ ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t);
+ if (ret < 0)
+ return ret;
+ sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 53 : 1638;
+ sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1;
+
+ return sps;
+}
+
static ssize_t adis16400_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
int ret, len = 0;
- u16 t;
- int sps;
- ret = adis16400_spi_read_reg_16(indio_dev,
- ADIS16400_SMPL_PRD,
- &t);
- if (ret)
+ ret = adis16400_get_freq(indio_dev);
+ if (ret < 0)
return ret;
- sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 53 : 1638;
- sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1;
- len = sprintf(buf, "%d SPS\n", sps);
+ len = sprintf(buf, "%d SPS\n", ret);
return len;
}
+static const unsigned adis16400_3db_divisors[] = {
+ [0] = 2, /* Special case */
+ [1] = 5,
+ [2] = 10,
+ [3] = 50,
+ [4] = 200,
+};
+
+static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
+{
+ int i, ret;
+ u16 val16;
+ for (i = ARRAY_SIZE(adis16400_3db_divisors) - 1; i >= 0; i--)
+ if (sps/adis16400_3db_divisors[i] > val)
+ break;
+ if (i == -1)
+ ret = -EINVAL;
+ else {
+ ret = adis16400_spi_read_reg_16(indio_dev,
+ ADIS16400_SENS_AVG,
+ &val16);
+ if (ret < 0)
+ goto error_ret;
+
+ ret = adis16400_spi_write_reg_16(indio_dev,
+ ADIS16400_SENS_AVG,
+ (val16 & ~0x03) | i);
+ }
+error_ret:
+ return ret;
+}
+
static ssize_t adis16400_write_frequency(struct device *dev,
struct device_attribute *attr,
const char *buf,
@@ -210,6 +250,7 @@ static ssize_t adis16400_write_frequency(struct device *dev,
ADIS16400_SMPL_PRD,
t);
+ /* Also update the filter */
mutex_unlock(&indio_dev->mlock);
return ret ? ret : len;
@@ -455,22 +496,39 @@ static u8 adis16400_addresses[17][2] = {
[incli_y] = { ADIS16300_ROLL_OUT }
};
+
static int adis16400_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long mask)
{
- int ret;
+ struct adis16400_state *st = iio_priv(indio_dev);
+ int ret, sps;
switch (mask) {
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
mutex_lock(&indio_dev->mlock);
ret = adis16400_spi_write_reg_16(indio_dev,
adis16400_addresses[chan->address][1],
val);
mutex_unlock(&indio_dev->mlock);
return ret;
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ /* Need to cache values so we can update if the frequency
+ changes */
+ mutex_lock(&indio_dev->mlock);
+ st->filt_int = val;
+ /* Work out update to current value */
+ sps = adis16400_get_freq(indio_dev);
+ if (sps < 0) {
+ mutex_unlock(&indio_dev->mlock);
+ return sps;
+ }
+
+ ret = adis16400_set_filter(indio_dev, sps, val);
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
default:
return -EINVAL;
}
@@ -504,8 +562,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
*val = val16;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
*val = 0;
@@ -533,7 +590,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
- case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
+ case IIO_CHAN_INFO_CALIBBIAS:
mutex_lock(&indio_dev->mlock);
ret = adis16400_spi_read_reg_16(indio_dev,
adis16400_addresses[chan->address][1],
@@ -544,11 +601,29 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
val16 = ((val16 & 0xFFF) << 4) >> 4;
*val = val16;
return IIO_VAL_INT;
- case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE):
+ case IIO_CHAN_INFO_OFFSET:
/* currently only temperature */
*val = 198;
*val2 = 160000;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ mutex_lock(&indio_dev->mlock);
+ /* Need both the number of taps and the sampling frequency */
+ ret = adis16400_spi_read_reg_16(indio_dev,
+ ADIS16400_SENS_AVG,
+ &val16);
+ if (ret < 0) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ ret = adis16400_get_freq(indio_dev);
+ if (ret > 0)
+ *val = ret/adis16400_3db_divisors[val16 & 0x03];
+ *val2 = 0;
+ mutex_unlock(&indio_dev->mlock);
+ if (ret < 0)
+ return ret;
+ return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
@@ -560,7 +635,7 @@ static struct iio_chan_spec adis16400_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "supply",
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16400_SCAN_SUPPLY,
.scan_type = IIO_ST('u', 14, 16, 0)
@@ -568,8 +643,9 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
.scan_index = ADIS16400_SCAN_GYRO_X,
.scan_type = IIO_ST('s', 14, 16, 0)
@@ -577,8 +653,9 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_y,
.scan_index = ADIS16400_SCAN_GYRO_Y,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -586,8 +663,9 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_z,
.scan_index = ADIS16400_SCAN_GYRO_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -595,8 +673,9 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_x,
.scan_index = ADIS16400_SCAN_ACC_X,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -604,8 +683,9 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_y,
.scan_index = ADIS16400_SCAN_ACC_Y,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -613,8 +693,9 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_z,
.scan_index = ADIS16400_SCAN_ACC_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -622,7 +703,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_MAGN,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = magn_x,
.scan_index = ADIS16400_SCAN_MAGN_X,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -630,7 +712,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_MAGN,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = magn_y,
.scan_index = ADIS16400_SCAN_MAGN_Y,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -638,7 +721,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_MAGN,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = magn_z,
.scan_index = ADIS16400_SCAN_MAGN_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -646,8 +730,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = temp,
.scan_index = ADIS16400_SCAN_TEMP,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -655,7 +739,7 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in1,
.scan_index = ADIS16400_SCAN_ADC_0,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -669,7 +753,7 @@ static struct iio_chan_spec adis16350_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "supply",
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16400_SCAN_SUPPLY,
.scan_type = IIO_ST('u', 12, 16, 0)
@@ -677,8 +761,9 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
.scan_index = ADIS16400_SCAN_GYRO_X,
.scan_type = IIO_ST('s', 14, 16, 0)
@@ -686,8 +771,9 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_y,
.scan_index = ADIS16400_SCAN_GYRO_Y,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -695,8 +781,9 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_z,
.scan_index = ADIS16400_SCAN_GYRO_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -704,8 +791,9 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_x,
.scan_index = ADIS16400_SCAN_ACC_X,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -713,8 +801,9 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_y,
.scan_index = ADIS16400_SCAN_ACC_Y,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -722,8 +811,9 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_z,
.scan_index = ADIS16400_SCAN_ACC_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -732,8 +822,9 @@ static struct iio_chan_spec adis16350_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "x",
- .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = temp0,
.scan_index = ADIS16350_SCAN_TEMP_X,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -742,8 +833,9 @@ static struct iio_chan_spec adis16350_channels[] = {
.indexed = 1,
.channel = 1,
.extend_name = "y",
- .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = temp1,
.scan_index = ADIS16350_SCAN_TEMP_Y,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -752,8 +844,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.indexed = 1,
.channel = 2,
.extend_name = "z",
- .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = temp2,
.scan_index = ADIS16350_SCAN_TEMP_Z,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -761,7 +853,7 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in1,
.scan_index = ADIS16350_SCAN_ADC_0,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -775,7 +867,7 @@ static struct iio_chan_spec adis16300_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "supply",
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16400_SCAN_SUPPLY,
.scan_type = IIO_ST('u', 12, 16, 0)
@@ -783,8 +875,9 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
.scan_index = ADIS16400_SCAN_GYRO_X,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -792,8 +885,9 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_x,
.scan_index = ADIS16400_SCAN_ACC_X,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -801,8 +895,9 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_y,
.scan_index = ADIS16400_SCAN_ACC_Y,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -810,8 +905,9 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_z,
.scan_index = ADIS16400_SCAN_ACC_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -819,8 +915,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = temp,
.scan_index = ADIS16400_SCAN_TEMP,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -828,7 +924,7 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in1,
.scan_index = ADIS16350_SCAN_ADC_0,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -836,7 +932,7 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_INCLI,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = incli_x,
.scan_index = ADIS16300_SCAN_INCLI_X,
.scan_type = IIO_ST('s', 13, 16, 0),
@@ -844,7 +940,7 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_INCLI,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = incli_y,
.scan_index = ADIS16300_SCAN_INCLI_Y,
.scan_type = IIO_ST('s', 13, 16, 0),
@@ -857,8 +953,9 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
.scan_index = ADIS16400_SCAN_GYRO_X,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -866,8 +963,9 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_y,
.scan_index = ADIS16400_SCAN_GYRO_Y,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -875,8 +973,9 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_z,
.scan_index = ADIS16400_SCAN_GYRO_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -884,8 +983,9 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_x,
.scan_index = ADIS16400_SCAN_ACC_X,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -893,8 +993,9 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_y,
.scan_index = ADIS16400_SCAN_ACC_Y,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -902,8 +1003,9 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_z,
.scan_index = ADIS16400_SCAN_ACC_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -911,8 +1013,8 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = accel_z,
.scan_index = ADIS16400_SCAN_ACC_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
@@ -1118,6 +1220,7 @@ static const struct spi_device_id adis16400_id[] = {
{"adis16405", ADIS16400},
{}
};
+MODULE_DEVICE_TABLE(spi, adis16400_id);
static struct spi_driver adis16400_driver = {
.driver = {
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
index fd886bf51a6d..ac22de573f3e 100644
--- a/drivers/staging/iio/imu/adis16400_ring.c
+++ b/drivers/staging/iio/imu/adis16400_ring.c
@@ -79,14 +79,16 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx)
struct spi_message msg;
int i, j = 0, ret;
struct spi_transfer *xfers;
+ int scan_count = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength);
- xfers = kzalloc(sizeof(*xfers)*indio_dev->buffer->scan_count + 1,
+ xfers = kzalloc(sizeof(*xfers)*(scan_count + 1),
GFP_KERNEL);
if (xfers == NULL)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(read_all_tx_array); i++)
- if (test_bit(i, indio_dev->buffer->scan_mask)) {
+ if (test_bit(i, indio_dev->active_scan_mask)) {
xfers[j].tx_buf = &read_all_tx_array[i];
xfers[j].bits_per_word = 16;
xfers[j].len = 2;
@@ -97,7 +99,7 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx)
xfers[j].len = 2;
spi_message_init(&msg);
- for (j = 0; j < indio_dev->buffer->scan_count + 1; j++)
+ for (j = 0; j < scan_count + 1; j++)
spi_message_add_tail(&xfers[j], &msg);
ret = spi_sync(st->us, &msg);
@@ -119,26 +121,27 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
s16 *data;
size_t datasize = ring->access->get_bytes_per_datum(ring);
/* Asumption that long is enough for maximum channels */
- unsigned long mask = *ring->scan_mask;
-
+ unsigned long mask = *indio_dev->active_scan_mask;
+ int scan_count = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength);
data = kmalloc(datasize , GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
return -ENOMEM;
}
- if (ring->scan_count) {
+ if (scan_count) {
if (st->variant->flags & ADIS16400_NO_BURST) {
ret = adis16350_spi_read_all(&indio_dev->dev, st->rx);
if (ret < 0)
goto err;
- for (; i < ring->scan_count; i++)
+ for (; i < scan_count; i++)
data[i] = *(s16 *)(st->rx + i*2);
} else {
ret = adis16400_spi_read_burst(&indio_dev->dev, st->rx);
if (ret < 0)
goto err;
- for (; i < indio_dev->buffer->scan_count; i++) {
+ for (; i < scan_count; i++) {
j = __ffs(mask);
mask &= ~(1 << j);
data[i] = be16_to_cpup(
@@ -186,10 +189,8 @@ int adis16400_configure_ring(struct iio_dev *indio_dev)
indio_dev->buffer = ring;
/* Effectively select the ring buffer implementation */
ring->access = &ring_sw_access_funcs;
- ring->bpe = 2;
ring->scan_timestamp = true;
- ring->setup_ops = &adis16400_ring_setup_ops;
- ring->owner = THIS_MODULE;
+ indio_dev->setup_ops = &adis16400_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&adis16400_trigger_handler,
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
index 9df0ce81dade..d7b1e9e435ae 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/staging/iio/industrialio-buffer.c
@@ -24,7 +24,7 @@
#include "iio.h"
#include "iio_core.h"
#include "sysfs.h"
-#include "buffer_generic.h"
+#include "buffer.h"
static const char * const iio_endian_prefix[] = {
[IIO_BE] = "be",
@@ -43,7 +43,7 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
struct iio_dev *indio_dev = filp->private_data;
struct iio_buffer *rb = indio_dev->buffer;
- if (!rb->access->read_first_n)
+ if (!rb || !rb->access->read_first_n)
return -EINVAL;
return rb->access->read_first_n(rb, n, buf);
}
@@ -64,28 +64,9 @@ unsigned int iio_buffer_poll(struct file *filp,
return 0;
}
-int iio_chrdev_buffer_open(struct iio_dev *indio_dev)
+void iio_buffer_init(struct iio_buffer *buffer)
{
- struct iio_buffer *rb = indio_dev->buffer;
- if (!rb)
- return -EINVAL;
- if (rb->access->mark_in_use)
- rb->access->mark_in_use(rb);
- return 0;
-}
-
-void iio_chrdev_buffer_release(struct iio_dev *indio_dev)
-{
- struct iio_buffer *rb = indio_dev->buffer;
-
- clear_bit(IIO_BUSY_BIT_POS, &rb->flags);
- if (rb->access->unmark_in_use)
- rb->access->unmark_in_use(rb);
-}
-
-void iio_buffer_init(struct iio_buffer *buffer, struct iio_dev *indio_dev)
-{
- buffer->indio_dev = indio_dev;
+ INIT_LIST_HEAD(&buffer->demux_list);
init_waitqueue_head(&buffer->pollq);
}
EXPORT_SYMBOL(iio_buffer_init);
@@ -126,17 +107,15 @@ static ssize_t iio_scan_el_show(struct device *dev,
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ret = iio_scan_mask_query(indio_dev->buffer,
- to_iio_dev_attr(attr)->address);
- if (ret < 0)
- return ret;
+ ret = test_bit(to_iio_dev_attr(attr)->address,
+ indio_dev->buffer->scan_mask);
+
return sprintf(buf, "%d\n", ret);
}
static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit)
{
clear_bit(bit, buffer->scan_mask);
- buffer->scan_count--;
return 0;
}
@@ -153,11 +132,11 @@ static ssize_t iio_scan_el_store(struct device *dev,
state = !(buf[0] == '0');
mutex_lock(&indio_dev->mlock);
- if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+ if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY;
goto error_ret;
}
- ret = iio_scan_mask_query(buffer, this_attr->address);
+ ret = iio_scan_mask_query(indio_dev, buffer, this_attr->address);
if (ret < 0)
goto error_ret;
if (!state && ret) {
@@ -165,7 +144,7 @@ static ssize_t iio_scan_el_store(struct device *dev,
if (ret)
goto error_ret;
} else if (state && !ret) {
- ret = iio_scan_mask_set(buffer, this_attr->address);
+ ret = iio_scan_mask_set(indio_dev, buffer, this_attr->address);
if (ret)
goto error_ret;
}
@@ -173,7 +152,7 @@ static ssize_t iio_scan_el_store(struct device *dev,
error_ret:
mutex_unlock(&indio_dev->mlock);
- return ret ? ret : len;
+ return ret < 0 ? ret : len;
}
@@ -196,7 +175,7 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
state = !(buf[0] == '0');
mutex_lock(&indio_dev->mlock);
- if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+ if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY;
goto error_ret;
}
@@ -311,12 +290,14 @@ int iio_buffer_register(struct iio_dev *indio_dev,
if (ret < 0)
goto error_cleanup_dynamic;
attrcount += ret;
+ if (channels[i].type == IIO_TIMESTAMP)
+ buffer->scan_index_timestamp =
+ channels[i].scan_index;
}
if (indio_dev->masklength && buffer->scan_mask == NULL) {
- buffer->scan_mask
- = kzalloc(sizeof(*buffer->scan_mask)*
- BITS_TO_LONGS(indio_dev->masklength),
- GFP_KERNEL);
+ buffer->scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
+ sizeof(*buffer->scan_mask),
+ GFP_KERNEL);
if (buffer->scan_mask == NULL) {
ret = -ENOMEM;
goto error_cleanup_dynamic;
@@ -326,10 +307,9 @@ int iio_buffer_register(struct iio_dev *indio_dev,
buffer->scan_el_group.name = iio_scan_elements_group_name;
- buffer->scan_el_group.attrs
- = kzalloc(sizeof(buffer->scan_el_group.attrs[0])*
- (attrcount + 1),
- GFP_KERNEL);
+ buffer->scan_el_group.attrs = kcalloc(attrcount + 1,
+ sizeof(buffer->scan_el_group.attrs[0]),
+ GFP_KERNEL);
if (buffer->scan_el_group.attrs == NULL) {
ret = -ENOMEM;
goto error_free_scan_mask;
@@ -395,31 +375,20 @@ ssize_t iio_buffer_write_length(struct device *dev,
if (val == buffer->access->get_length(buffer))
return len;
- if (buffer->access->set_length) {
- buffer->access->set_length(buffer, val);
- if (buffer->access->mark_param_change)
- buffer->access->mark_param_change(buffer);
+ mutex_lock(&indio_dev->mlock);
+ if (iio_buffer_enabled(indio_dev)) {
+ ret = -EBUSY;
+ } else {
+ if (buffer->access->set_length)
+ buffer->access->set_length(buffer, val);
+ ret = 0;
}
+ mutex_unlock(&indio_dev->mlock);
- return len;
+ return ret ? ret : len;
}
EXPORT_SYMBOL(iio_buffer_write_length);
-ssize_t iio_buffer_read_bytes_per_datum(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
-
- if (buffer->access->get_bytes_per_datum)
- return sprintf(buf, "%d\n",
- buffer->access->get_bytes_per_datum(buffer));
-
- return 0;
-}
-EXPORT_SYMBOL(iio_buffer_read_bytes_per_datum);
-
ssize_t iio_buffer_store_enable(struct device *dev,
struct device_attribute *attr,
const char *buf,
@@ -434,14 +403,14 @@ ssize_t iio_buffer_store_enable(struct device *dev,
mutex_lock(&indio_dev->mlock);
previous_mode = indio_dev->currentmode;
requested_state = !(buf[0] == '0');
- current_state = !!(previous_mode & INDIO_ALL_BUFFER_MODES);
+ current_state = iio_buffer_enabled(indio_dev);
if (current_state == requested_state) {
printk(KERN_INFO "iio-buffer, current state requested again\n");
goto done;
}
if (requested_state) {
- if (buffer->setup_ops->preenable) {
- ret = buffer->setup_ops->preenable(indio_dev);
+ if (indio_dev->setup_ops->preenable) {
+ ret = indio_dev->setup_ops->preenable(indio_dev);
if (ret) {
printk(KERN_ERR
"Buffer not started:"
@@ -458,16 +427,12 @@ ssize_t iio_buffer_store_enable(struct device *dev,
goto error_ret;
}
}
- if (buffer->access->mark_in_use)
- buffer->access->mark_in_use(buffer);
/* Definitely possible for devices to support both of these.*/
if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
if (!indio_dev->trig) {
printk(KERN_INFO
"Buffer not started: no trigger\n");
ret = -EINVAL;
- if (buffer->access->unmark_in_use)
- buffer->access->unmark_in_use(buffer);
goto error_ret;
}
indio_dev->currentmode = INDIO_BUFFER_TRIGGERED;
@@ -478,32 +443,28 @@ ssize_t iio_buffer_store_enable(struct device *dev,
goto error_ret;
}
- if (buffer->setup_ops->postenable) {
- ret = buffer->setup_ops->postenable(indio_dev);
+ if (indio_dev->setup_ops->postenable) {
+ ret = indio_dev->setup_ops->postenable(indio_dev);
if (ret) {
printk(KERN_INFO
"Buffer not started:"
"postenable failed\n");
- if (buffer->access->unmark_in_use)
- buffer->access->unmark_in_use(buffer);
indio_dev->currentmode = previous_mode;
- if (buffer->setup_ops->postdisable)
- buffer->setup_ops->
+ if (indio_dev->setup_ops->postdisable)
+ indio_dev->setup_ops->
postdisable(indio_dev);
goto error_ret;
}
}
} else {
- if (buffer->setup_ops->predisable) {
- ret = buffer->setup_ops->predisable(indio_dev);
+ if (indio_dev->setup_ops->predisable) {
+ ret = indio_dev->setup_ops->predisable(indio_dev);
if (ret)
goto error_ret;
}
- if (buffer->access->unmark_in_use)
- buffer->access->unmark_in_use(buffer);
indio_dev->currentmode = INDIO_DIRECT_MODE;
- if (buffer->setup_ops->postdisable) {
- ret = buffer->setup_ops->postdisable(indio_dev);
+ if (indio_dev->setup_ops->postdisable) {
+ ret = indio_dev->setup_ops->postdisable(indio_dev);
if (ret)
goto error_ret;
}
@@ -523,37 +484,10 @@ ssize_t iio_buffer_show_enable(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", !!(indio_dev->currentmode
- & INDIO_ALL_BUFFER_MODES));
+ return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev));
}
EXPORT_SYMBOL(iio_buffer_show_enable);
-int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
-{
- struct iio_buffer *buffer = indio_dev->buffer;
- size_t size;
- dev_dbg(&indio_dev->dev, "%s\n", __func__);
- /* Check if there are any scan elements enabled, if not fail*/
- if (!(buffer->scan_count || buffer->scan_timestamp))
- return -EINVAL;
- if (buffer->scan_timestamp)
- if (buffer->scan_count)
- /* Timestamp (aligned to s64) and data */
- size = (((buffer->scan_count * buffer->bpe)
- + sizeof(s64) - 1)
- & ~(sizeof(s64) - 1))
- + sizeof(s64);
- else /* Timestamp only */
- size = sizeof(s64);
- else /* Data only */
- size = buffer->scan_count * buffer->bpe;
- buffer->access->set_bytes_per_datum(buffer, size);
-
- return 0;
-}
-EXPORT_SYMBOL(iio_sw_buffer_preenable);
-
-
/* note NULL used as error indicator as it doesn't make sense. */
static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
unsigned int masklength,
@@ -569,14 +503,57 @@ static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
return NULL;
}
+int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct iio_buffer *buffer = indio_dev->buffer;
+ const struct iio_chan_spec *ch;
+ unsigned bytes = 0;
+ int length, i;
+ dev_dbg(&indio_dev->dev, "%s\n", __func__);
+
+ /* How much space will the demuxed element take? */
+ for_each_set_bit(i, buffer->scan_mask,
+ indio_dev->masklength) {
+ ch = iio_find_channel_from_si(indio_dev, i);
+ length = ch->scan_type.storagebits/8;
+ bytes = ALIGN(bytes, length);
+ bytes += length;
+ }
+ if (buffer->scan_timestamp) {
+ ch = iio_find_channel_from_si(indio_dev,
+ buffer->scan_index_timestamp);
+ length = ch->scan_type.storagebits/8;
+ bytes = ALIGN(bytes, length);
+ bytes += length;
+ }
+ buffer->access->set_bytes_per_datum(buffer, bytes);
+
+ /* What scan mask do we actually have ?*/
+ if (indio_dev->available_scan_masks)
+ indio_dev->active_scan_mask =
+ iio_scan_mask_match(indio_dev->available_scan_masks,
+ indio_dev->masklength,
+ buffer->scan_mask);
+ else
+ indio_dev->active_scan_mask = buffer->scan_mask;
+ iio_update_demux(indio_dev);
+
+ if (indio_dev->info->update_scan_mode)
+ return indio_dev->info
+ ->update_scan_mode(indio_dev,
+ indio_dev->active_scan_mask);
+ return 0;
+}
+EXPORT_SYMBOL(iio_sw_buffer_preenable);
+
/**
* iio_scan_mask_set() - set particular bit in the scan mask
* @buffer: the buffer whose scan mask we are interested in
* @bit: the bit to be set.
**/
-int iio_scan_mask_set(struct iio_buffer *buffer, int bit)
+int iio_scan_mask_set(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer, int bit)
{
- struct iio_dev *indio_dev = buffer->indio_dev;
unsigned long *mask;
unsigned long *trialmask;
@@ -604,7 +581,6 @@ int iio_scan_mask_set(struct iio_buffer *buffer, int bit)
}
}
bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength);
- buffer->scan_count++;
kfree(trialmask);
@@ -612,25 +588,147 @@ int iio_scan_mask_set(struct iio_buffer *buffer, int bit)
};
EXPORT_SYMBOL_GPL(iio_scan_mask_set);
-int iio_scan_mask_query(struct iio_buffer *buffer, int bit)
+int iio_scan_mask_query(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer, int bit)
{
- struct iio_dev *indio_dev = buffer->indio_dev;
- long *mask;
-
if (bit > indio_dev->masklength)
return -EINVAL;
if (!buffer->scan_mask)
return 0;
- if (indio_dev->available_scan_masks)
- mask = iio_scan_mask_match(indio_dev->available_scan_masks,
- indio_dev->masklength,
- buffer->scan_mask);
- else
- mask = buffer->scan_mask;
- if (!mask)
- return 0;
- return test_bit(bit, mask);
+ return test_bit(bit, buffer->scan_mask);
};
EXPORT_SYMBOL_GPL(iio_scan_mask_query);
+
+/**
+ * struct iio_demux_table() - table describing demux memcpy ops
+ * @from: index to copy from
+ * @to: index to copy to
+ * @length: how many bytes to copy
+ * @l: list head used for management
+ */
+struct iio_demux_table {
+ unsigned from;
+ unsigned to;
+ unsigned length;
+ struct list_head l;
+};
+
+static unsigned char *iio_demux(struct iio_buffer *buffer,
+ unsigned char *datain)
+{
+ struct iio_demux_table *t;
+
+ if (list_empty(&buffer->demux_list))
+ return datain;
+ list_for_each_entry(t, &buffer->demux_list, l)
+ memcpy(buffer->demux_bounce + t->to,
+ datain + t->from, t->length);
+
+ return buffer->demux_bounce;
+}
+
+int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
+ s64 timestamp)
+{
+ unsigned char *dataout = iio_demux(buffer, data);
+
+ return buffer->access->store_to(buffer, dataout, timestamp);
+}
+EXPORT_SYMBOL_GPL(iio_push_to_buffer);
+
+int iio_update_demux(struct iio_dev *indio_dev)
+{
+ const struct iio_chan_spec *ch;
+ struct iio_buffer *buffer = indio_dev->buffer;
+ int ret, in_ind = -1, out_ind, length;
+ unsigned in_loc = 0, out_loc = 0;
+ struct iio_demux_table *p, *q;
+
+ /* Clear out any old demux */
+ list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
+ list_del(&p->l);
+ kfree(p);
+ }
+ kfree(buffer->demux_bounce);
+ buffer->demux_bounce = NULL;
+
+ /* First work out which scan mode we will actually have */
+ if (bitmap_equal(indio_dev->active_scan_mask,
+ buffer->scan_mask,
+ indio_dev->masklength))
+ return 0;
+
+ /* Now we have the two masks, work from least sig and build up sizes */
+ for_each_set_bit(out_ind,
+ indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ in_ind = find_next_bit(indio_dev->active_scan_mask,
+ indio_dev->masklength,
+ in_ind + 1);
+ while (in_ind != out_ind) {
+ in_ind = find_next_bit(indio_dev->active_scan_mask,
+ indio_dev->masklength,
+ in_ind + 1);
+ ch = iio_find_channel_from_si(indio_dev, in_ind);
+ length = ch->scan_type.storagebits/8;
+ /* Make sure we are aligned */
+ in_loc += length;
+ if (in_loc % length)
+ in_loc += length - in_loc % length;
+ }
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL) {
+ ret = -ENOMEM;
+ goto error_clear_mux_table;
+ }
+ ch = iio_find_channel_from_si(indio_dev, in_ind);
+ length = ch->scan_type.storagebits/8;
+ if (out_loc % length)
+ out_loc += length - out_loc % length;
+ if (in_loc % length)
+ in_loc += length - in_loc % length;
+ p->from = in_loc;
+ p->to = out_loc;
+ p->length = length;
+ list_add_tail(&p->l, &buffer->demux_list);
+ out_loc += length;
+ in_loc += length;
+ }
+ /* Relies on scan_timestamp being last */
+ if (buffer->scan_timestamp) {
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL) {
+ ret = -ENOMEM;
+ goto error_clear_mux_table;
+ }
+ ch = iio_find_channel_from_si(indio_dev,
+ buffer->scan_index_timestamp);
+ length = ch->scan_type.storagebits/8;
+ if (out_loc % length)
+ out_loc += length - out_loc % length;
+ if (in_loc % length)
+ in_loc += length - in_loc % length;
+ p->from = in_loc;
+ p->to = out_loc;
+ p->length = length;
+ list_add_tail(&p->l, &buffer->demux_list);
+ out_loc += length;
+ in_loc += length;
+ }
+ buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
+ if (buffer->demux_bounce == NULL) {
+ ret = -ENOMEM;
+ goto error_clear_mux_table;
+ }
+ return 0;
+
+error_clear_mux_table:
+ list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
+ list_del(&p->l);
+ kfree(p);
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iio_update_demux);
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index aec9311b108c..19f897f3c85e 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -25,8 +25,8 @@
#include "iio.h"
#include "iio_core.h"
#include "iio_core_trigger.h"
-#include "chrdev.h"
#include "sysfs.h"
+#include "events.h"
/* IDA to assign each registered device a unique id*/
static DEFINE_IDA(iio_ida);
@@ -77,17 +77,29 @@ static const char * const iio_modifier_names[] = {
/* relies on pairs of these shared then separate */
static const char * const iio_chan_info_postfix[] = {
- [IIO_CHAN_INFO_SCALE_SHARED/2] = "scale",
- [IIO_CHAN_INFO_OFFSET_SHARED/2] = "offset",
- [IIO_CHAN_INFO_CALIBSCALE_SHARED/2] = "calibscale",
- [IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias",
- [IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw",
- [IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale",
- [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED/2]
- = "quadrature_correction_raw",
- [IIO_CHAN_INFO_AVERAGE_RAW_SHARED/2] = "mean_raw",
+ [IIO_CHAN_INFO_SCALE] = "scale",
+ [IIO_CHAN_INFO_OFFSET] = "offset",
+ [IIO_CHAN_INFO_CALIBSCALE] = "calibscale",
+ [IIO_CHAN_INFO_CALIBBIAS] = "calibbias",
+ [IIO_CHAN_INFO_PEAK] = "peak_raw",
+ [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale",
+ [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw",
+ [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw",
+ [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY]
+ = "filter_low_pass_3db_frequency",
};
+const struct iio_chan_spec
+*iio_find_channel_from_si(struct iio_dev *indio_dev, int si)
+{
+ int i;
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ if (indio_dev->channels[i].scan_index == si)
+ return &indio_dev->channels[i];
+ return NULL;
+}
+
/**
* struct iio_detected_event_list - list element for events that have occurred
* @list: linked list header
@@ -169,8 +181,11 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
{
struct iio_event_interface *ev_int = filep->private_data;
struct iio_detected_event_list *el;
+ size_t len = sizeof(el->ev);
int ret;
- size_t len;
+
+ if (count < len)
+ return -EINVAL;
mutex_lock(&ev_int->event_list_lock);
if (list_empty(&ev_int->det_events)) {
@@ -192,7 +207,6 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
el = list_first_entry(&ev_int->det_events,
struct iio_detected_event_list,
list);
- len = sizeof el->ev;
if (copy_to_user(buf, &(el->ev), len)) {
ret = -EFAULT;
goto error_mutex_unlock;
@@ -415,7 +429,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
sysfs_attr_init(&dev_attr->attr);
/* Build up postfix of <extend_name>_<modifier>_postfix */
- if (chan->modified) {
+ if (chan->modified && !generic) {
if (chan->extend_name)
full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_modifier_names[chan
@@ -600,7 +614,7 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
chan,
&iio_read_channel_info,
&iio_write_channel_info,
- (1 << i),
+ i/2,
!(i%2),
&indio_dev->dev,
&indio_dev->channel_attr_list);
@@ -665,10 +679,9 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
if (indio_dev->name)
attrcount++;
- indio_dev->chan_attr_group.attrs
- = kzalloc(sizeof(indio_dev->chan_attr_group.attrs[0])*
- (attrcount + 1),
- GFP_KERNEL);
+ indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1,
+ sizeof(indio_dev->chan_attr_group.attrs[0]),
+ GFP_KERNEL);
if (indio_dev->chan_attr_group.attrs == NULL) {
ret = -ENOMEM;
goto error_clear_attrs;
@@ -788,6 +801,9 @@ static ssize_t iio_ev_value_store(struct device *dev,
unsigned long val;
int ret;
+ if (!indio_dev->info->write_event_value)
+ return -EINVAL;
+
ret = strict_strtoul(buf, 10, &val);
if (ret)
return ret;
@@ -958,10 +974,9 @@ static int iio_device_register_eventset(struct iio_dev *indio_dev)
}
indio_dev->event_interface->group.name = iio_event_group_name;
- indio_dev->event_interface->group.attrs =
- kzalloc(sizeof(indio_dev->event_interface->group.attrs[0])
- *(attrcount + 1),
- GFP_KERNEL);
+ indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1,
+ sizeof(indio_dev->event_interface->group.attrs[0]),
+ GFP_KERNEL);
if (indio_dev->event_interface->group.attrs == NULL) {
ret = -ENOMEM;
goto error_free_setup_event_lines;
@@ -1068,9 +1083,13 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
{
struct iio_dev *indio_dev = container_of(inode->i_cdev,
struct iio_dev, chrdev);
+
+ if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags))
+ return -EBUSY;
+
filp->private_data = indio_dev;
- return iio_chrdev_buffer_open(indio_dev);
+ return 0;
}
/**
@@ -1078,8 +1097,9 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
**/
static int iio_chrdev_release(struct inode *inode, struct file *filp)
{
- iio_chrdev_buffer_release(container_of(inode->i_cdev,
- struct iio_dev, chrdev));
+ struct iio_dev *indio_dev = container_of(inode->i_cdev,
+ struct iio_dev, chrdev);
+ clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
return 0;
}
diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c
index 68a4d4e8c635..47ecadd4818d 100644
--- a/drivers/staging/iio/industrialio-trigger.c
+++ b/drivers/staging/iio/industrialio-trigger.c
@@ -159,13 +159,12 @@ EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll);
void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time)
{
int i;
- if (!trig->use_count) {
+ if (!trig->use_count)
for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
if (trig->subirqs[i].enabled) {
trig->use_count++;
handle_nested_irq(trig->subirq_base + i);
}
- }
}
EXPORT_SYMBOL(iio_trigger_poll_chained);
@@ -173,10 +172,9 @@ void iio_trigger_notify_done(struct iio_trigger *trig)
{
trig->use_count--;
if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable)
- if (trig->ops->try_reenable(trig)) {
+ if (trig->ops->try_reenable(trig))
/* Missed and interrupt so launch new poll now */
iio_trigger_poll(trig, 0);
- }
}
EXPORT_SYMBOL(iio_trigger_notify_done);
@@ -222,8 +220,16 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
pf->type, pf->name,
pf);
- if (trig->ops && trig->ops->set_trigger_state && notinuse)
+ if (ret < 0) {
+ module_put(pf->indio_dev->info->driver_module);
+ return ret;
+ }
+
+ if (trig->ops && trig->ops->set_trigger_state && notinuse) {
ret = trig->ops->set_trigger_state(trig, true);
+ if (ret < 0)
+ module_put(pf->indio_dev->info->driver_module);
+ }
return ret;
}
@@ -336,6 +342,8 @@ static ssize_t iio_trigger_write_current(struct device *dev,
mutex_unlock(&indio_dev->mlock);
trig = iio_trigger_find_by_name(buf, len);
+ if (oldtrig == trig)
+ return len;
if (trig && indio_dev->info->validate_trigger) {
ret = indio_dev->info->validate_trigger(indio_dev, trig);
@@ -473,12 +481,10 @@ void iio_free_trigger(struct iio_trigger *trig)
}
EXPORT_SYMBOL(iio_free_trigger);
-int iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
+void iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
{
indio_dev->groups[indio_dev->groupcounter++] =
&iio_trigger_consumer_attr_group;
-
- return 0;
}
void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
@@ -490,18 +496,14 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
int iio_triggered_buffer_postenable(struct iio_dev *indio_dev)
{
- return indio_dev->trig
- ? iio_trigger_attach_poll_func(indio_dev->trig,
- indio_dev->pollfunc)
- : 0;
+ return iio_trigger_attach_poll_func(indio_dev->trig,
+ indio_dev->pollfunc);
}
EXPORT_SYMBOL(iio_triggered_buffer_postenable);
int iio_triggered_buffer_predisable(struct iio_dev *indio_dev)
{
- return indio_dev->trig
- ? iio_trigger_dettach_poll_func(indio_dev->trig,
- indio_dev->pollfunc)
- : 0;
+ return iio_trigger_dettach_poll_func(indio_dev->trig,
+ indio_dev->pollfunc);
}
EXPORT_SYMBOL(iio_triggered_buffer_predisable);
diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c
index e8c234bb18f0..e1e9c06cde4a 100644
--- a/drivers/staging/iio/kfifo_buf.c
+++ b/drivers/staging/iio/kfifo_buf.c
@@ -11,9 +11,7 @@
struct iio_kfifo {
struct iio_buffer buffer;
struct kfifo kf;
- int use_count;
int update_needed;
- struct mutex use_lock;
};
#define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer)
@@ -33,54 +31,25 @@ static int iio_request_update_kfifo(struct iio_buffer *r)
int ret = 0;
struct iio_kfifo *buf = iio_to_kfifo(r);
- mutex_lock(&buf->use_lock);
if (!buf->update_needed)
goto error_ret;
- if (buf->use_count) {
- ret = -EAGAIN;
- goto error_ret;
- }
kfifo_free(&buf->kf);
ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
buf->buffer.length);
error_ret:
- mutex_unlock(&buf->use_lock);
return ret;
}
-static void iio_mark_kfifo_in_use(struct iio_buffer *r)
-{
- struct iio_kfifo *buf = iio_to_kfifo(r);
- mutex_lock(&buf->use_lock);
- buf->use_count++;
- mutex_unlock(&buf->use_lock);
-}
-
-static void iio_unmark_kfifo_in_use(struct iio_buffer *r)
-{
- struct iio_kfifo *buf = iio_to_kfifo(r);
- mutex_lock(&buf->use_lock);
- buf->use_count--;
- mutex_unlock(&buf->use_lock);
-}
-
static int iio_get_length_kfifo(struct iio_buffer *r)
{
return r->length;
}
-static inline void __iio_init_kfifo(struct iio_kfifo *kf)
-{
- mutex_init(&kf->use_lock);
-}
-
static IIO_BUFFER_ENABLE_ATTR;
-static IIO_BUFFER_BYTES_PER_DATUM_ATTR;
static IIO_BUFFER_LENGTH_ATTR;
static struct attribute *iio_kfifo_attributes[] = {
&dev_attr_length.attr,
- &dev_attr_bytes_per_datum.attr,
&dev_attr_enable.attr,
NULL,
};
@@ -98,9 +67,8 @@ struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
if (!kf)
return NULL;
kf->update_needed = true;
- iio_buffer_init(&kf->buffer, indio_dev);
+ iio_buffer_init(&kf->buffer);
kf->buffer.attrs = &iio_kfifo_attribute_group;
- __iio_init_kfifo(kf);
return &kf->buffer;
}
@@ -111,20 +79,19 @@ static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r)
return r->bytes_per_datum;
}
-static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd)
+static int iio_mark_update_needed_kfifo(struct iio_buffer *r)
{
- if (r->bytes_per_datum != bpd) {
- r->bytes_per_datum = bpd;
- if (r->access->mark_param_change)
- r->access->mark_param_change(r);
- }
+ struct iio_kfifo *kf = iio_to_kfifo(r);
+ kf->update_needed = true;
return 0;
}
-static int iio_mark_update_needed_kfifo(struct iio_buffer *r)
+static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd)
{
- struct iio_kfifo *kf = iio_to_kfifo(r);
- kf->update_needed = true;
+ if (r->bytes_per_datum != bpd) {
+ r->bytes_per_datum = bpd;
+ iio_mark_update_needed_kfifo(r);
+ }
return 0;
}
@@ -132,8 +99,7 @@ static int iio_set_length_kfifo(struct iio_buffer *r, int length)
{
if (r->length != length) {
r->length = length;
- if (r->access->mark_param_change)
- r->access->mark_param_change(r);
+ iio_mark_update_needed_kfifo(r);
}
return 0;
}
@@ -150,16 +116,9 @@ static int iio_store_to_kfifo(struct iio_buffer *r,
{
int ret;
struct iio_kfifo *kf = iio_to_kfifo(r);
- u8 *datal = kmalloc(r->bytes_per_datum, GFP_KERNEL);
- memcpy(datal, data, r->bytes_per_datum - sizeof(timestamp));
- memcpy(datal + r->bytes_per_datum - sizeof(timestamp),
- &timestamp, sizeof(timestamp));
ret = kfifo_in(&kf->kf, data, r->bytes_per_datum);
- if (ret != r->bytes_per_datum) {
- kfree(datal);
+ if (ret != r->bytes_per_datum)
return -EBUSY;
- }
- kfree(datal);
return 0;
}
@@ -169,17 +128,18 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r,
int ret, copied;
struct iio_kfifo *kf = iio_to_kfifo(r);
- ret = kfifo_to_user(&kf->kf, buf, r->bytes_per_datum*n, &copied);
+ if (n < r->bytes_per_datum)
+ return -EINVAL;
+
+ n = rounddown(n, r->bytes_per_datum);
+ ret = kfifo_to_user(&kf->kf, buf, n, &copied);
return copied;
}
const struct iio_buffer_access_funcs kfifo_access_funcs = {
- .mark_in_use = &iio_mark_kfifo_in_use,
- .unmark_in_use = &iio_unmark_kfifo_in_use,
.store_to = &iio_store_to_kfifo,
.read_first_n = &iio_read_first_n_kfifo,
- .mark_param_change = &iio_mark_update_needed_kfifo,
.request_update = &iio_request_update_kfifo,
.get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo,
.set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo,
diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h
index a15598bb9fdb..cc2bd9a1ccfe 100644
--- a/drivers/staging/iio/kfifo_buf.h
+++ b/drivers/staging/iio/kfifo_buf.h
@@ -1,7 +1,7 @@
#include <linux/kfifo.h>
#include "iio.h"
-#include "buffer_generic.h"
+#include "buffer.h"
extern const struct iio_buffer_access_funcs kfifo_access_funcs;
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index 47638362224b..849d6a564afa 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -362,8 +362,7 @@ static int isl29018_write_raw(struct iio_dev *indio_dev,
int ret = -EINVAL;
mutex_lock(&chip->lock);
- if (mask == (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) &&
- chan->type == IIO_LIGHT) {
+ if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) {
chip->lux_scale = val;
ret = 0;
}
@@ -402,7 +401,7 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
if (!ret)
ret = IIO_VAL_INT;
break;
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
if (chan->type == IIO_LIGHT) {
*val = chip->lux_scale;
ret = IIO_VAL_INT;
@@ -421,7 +420,7 @@ static const struct iio_chan_spec isl29018_channels[] = {
.indexed = 1,
.channel = 0,
.processed_val = IIO_PROCESSED,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
}, {
.type = IIO_INTENSITY,
.modified = 1,
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 1942db13b03b..ffca85e81ef5 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -37,6 +37,7 @@
#include "../iio.h"
#include "../sysfs.h"
+#include "../events.h"
#include "tsl2563.h"
/* Use this many bits for fraction part. */
@@ -226,6 +227,8 @@ static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id)
if (ret < 0)
return ret;
+ *id = ret;
+
return 0;
}
@@ -510,7 +513,7 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev,
}
break;
- case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+ case IIO_CHAN_INFO_CALIBSCALE:
if (chan->channel == 0)
*val = calib_to_sysfs(chip->calib0);
else
@@ -536,7 +539,7 @@ static const struct iio_chan_spec tsl2563_channels[] = {
.type = IIO_INTENSITY,
.modified = 1,
.channel2 = IIO_MOD_LIGHT_BOTH,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE),
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH,
@@ -544,8 +547,8 @@ static const struct iio_chan_spec tsl2563_channels[] = {
}, {
.type = IIO_INTENSITY,
.modified = 1,
- .channel2 = IIO_MOD_LIGHT_BOTH,
- .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE),
+ .channel2 = IIO_MOD_LIGHT_IR,
+ .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
}
};
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
index 3836f73a5296..5b6455a238d8 100644
--- a/drivers/staging/iio/light/tsl2583.c
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -194,6 +194,7 @@ static int taos_get_lux(struct iio_dev *indio_dev)
{
u16 ch0, ch1; /* separated ch0/ch1 data from device */
u32 lux; /* raw lux calculated from device data */
+ u64 lux64;
u32 ratio;
u8 buf[5];
struct taos_lux *p;
@@ -297,9 +298,19 @@ static int taos_get_lux(struct iio_dev *indio_dev)
lux = (lux + (chip->als_time_scale >> 1)) /
chip->als_time_scale;
- /* adjust for active gain scale */
- lux >>= 13; /* tables have factor of 8192 builtin for accuracy */
- lux = (lux * chip->taos_settings.als_gain_trim + 500) / 1000;
+ /* Adjust for active gain scale.
+ * The taos_device_lux tables above have a factor of 8192 built in,
+ * so we need to shift right.
+ * User-specified gain provides a multiplier.
+ * Apply user-specified gain before shifting right to retain precision.
+ * Use 64 bits to avoid overflow on multiplication.
+ * Then go back to 32 bits before division to avoid using div_u64().
+ */
+ lux64 = lux;
+ lux64 = lux64 * chip->taos_settings.als_gain_trim;
+ lux64 >>= 13;
+ lux = lux64;
+ lux = (lux + 500) / 1000;
if (lux > TSL258X_LUX_CALC_OVER_FLOW) { /* check for overflow */
return_max:
lux = TSL258X_LUX_CALC_OVER_FLOW;
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
index db31d6d0e5b6..3158f12cb051 100644
--- a/drivers/staging/iio/magnetometer/ak8975.c
+++ b/drivers/staging/iio/magnetometer/ak8975.c
@@ -431,7 +431,7 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case 0:
return ak8975_read_axis(indio_dev, chan->address, val);
- case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+ case IIO_CHAN_INFO_SCALE:
*val = data->raw_to_gauss[chan->address];
return IIO_VAL_INT;
}
@@ -443,7 +443,7 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
.type = IIO_MAGN, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.address = index, \
}
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index 7bb1bc605136..f2e85a9cf196 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -463,7 +463,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
return hmc5843_read_measurement(indio_dev,
chan->address,
val);
- case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+ case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = hmc5843_regval_to_nanoscale[data->range];
return IIO_VAL_INT_PLUS_NANO;
@@ -476,7 +476,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
.type = IIO_MAGN, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
- .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \
+ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = add \
}
@@ -605,6 +605,7 @@ static const struct i2c_device_id hmc5843_id[] = {
{ "hmc5843", 0 },
{ }
};
+MODULE_DEVICE_TABLE(i2c, hmc5843_id);
static struct i2c_driver hmc5843_driver = {
.driver = {
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 4c7b0cbf49fa..57baac6c0d40 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -582,3 +582,4 @@ module_spi_driver(ade7753_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADE7753/6 Single-Phase Multifunction Meter");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:ade7753");
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 15c98cde76d1..8d81c92007e9 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -605,3 +605,4 @@ module_spi_driver(ade7754_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADE7754 Polyphase Multifunction Energy Metering IC Driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:ad7754");
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index 39338bcb1872..dcb20294dfe8 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -20,7 +20,7 @@
#include "../iio.h"
#include "../sysfs.h"
-#include "../buffer_generic.h"
+#include "../buffer.h"
#include "meter.h"
#include "ade7758.h"
@@ -663,63 +663,63 @@ static const struct attribute_group ade7758_attribute_group = {
static struct iio_chan_spec ade7758_channels[] = {
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE),
0, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT),
1, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR),
2, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR),
3, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR),
4, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE),
5, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT),
6, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR),
7, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR),
8, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR),
9, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 2, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE),
10, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 2, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT),
11, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 2, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR),
12, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 2, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR),
13, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 2, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR),
14, IIO_ST('s', 24, 32, 0), 0),
IIO_CHAN_SOFT_TIMESTAMP(15),
@@ -746,12 +746,12 @@ static int __devinit ade7758_probe(struct spi_device *spi)
spi_set_drvdata(spi, indio_dev);
/* Allocate the comms buffers */
- st->rx = kzalloc(sizeof(*st->rx)*ADE7758_MAX_RX, GFP_KERNEL);
+ st->rx = kcalloc(ADE7758_MAX_RX, sizeof(*st->rx), GFP_KERNEL);
if (st->rx == NULL) {
ret = -ENOMEM;
goto error_free_dev;
}
- st->tx = kzalloc(sizeof(*st->tx)*ADE7758_MAX_TX, GFP_KERNEL);
+ st->tx = kcalloc(ADE7758_MAX_TX, sizeof(*st->tx), GFP_KERNEL);
if (st->tx == NULL) {
ret = -ENOMEM;
goto error_free_rx;
@@ -843,6 +843,7 @@ static const struct spi_device_id ade7758_id[] = {
{"ade7758", 0},
{}
};
+MODULE_DEVICE_TABLE(spi, ade7758_id);
static struct spi_driver ade7758_driver = {
.driver = {
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index 00fa2ac5c459..f29f2b278fe4 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -67,7 +67,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
s64 dat64[2];
u32 *dat32 = (u32 *)dat64;
- if (ring->scan_count)
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
if (ade7758_spi_read_burst(&indio_dev->dev) >= 0)
*dat32 = get_unaligned_be32(&st->rx_buf[5]) & 0xFFFFFF;
@@ -96,10 +96,11 @@ static int ade7758_ring_preenable(struct iio_dev *indio_dev)
size_t d_size;
unsigned channel;
- if (!ring->scan_count)
+ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
- channel = find_first_bit(ring->scan_mask, indio_dev->masklength);
+ channel = find_first_bit(indio_dev->active_scan_mask,
+ indio_dev->masklength);
d_size = st->ade7758_ring_channels[channel].scan_type.storagebits / 8;
@@ -145,8 +146,7 @@ int ade7758_configure_ring(struct iio_dev *indio_dev)
/* Effectively select the ring buffer implementation */
indio_dev->buffer->access = &ring_sw_access_funcs;
- indio_dev->buffer->setup_ops = &ade7758_ring_setup_ops;
- indio_dev->buffer->owner = THIS_MODULE;
+ indio_dev->setup_ops = &ade7758_ring_setup_ops;
indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&ade7758_trigger_handler,
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index cfa2a5eff122..0beab478dcd9 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -526,3 +526,4 @@ module_spi_driver(ade7759_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADE7759 Active Energy Metering IC Driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:ad7759");
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index c485a79aeec3..81121862c1bd 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -343,6 +343,7 @@ static const struct spi_device_id ade7854_id[] = {
{ "ade7878", 0 },
{ }
};
+MODULE_DEVICE_TABLE(spi, ade7854_id);
static struct spi_driver ade7854_driver = {
.driver = {
diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
index 1c6a02bfd45d..d8ce854c1897 100644
--- a/drivers/staging/iio/resolver/ad2s1200.c
+++ b/drivers/staging/iio/resolver/ad2s1200.c
@@ -160,6 +160,7 @@ static const struct spi_device_id ad2s1200_id[] = {
{ "ad2s1205" },
{}
};
+MODULE_DEVICE_TABLE(spi, ad2s1200_id);
static struct spi_driver ad2s1200_driver = {
.driver = {
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index ff1b3316d016..c439fcf72be7 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -749,6 +749,7 @@ static const struct spi_device_id ad2s1210_id[] = {
{ "ad2s1210" },
{}
};
+MODULE_DEVICE_TABLE(spi, ad2s1210_id);
static struct spi_driver ad2s1210_driver = {
.driver = {
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index 6d0794389e74..2a86f582ddf1 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -109,6 +109,7 @@ static const struct spi_device_id ad2s90_id[] = {
{ "ad2s90" },
{}
};
+MODULE_DEVICE_TABLE(spi, ad2s90_id);
static struct spi_driver ad2s90_driver = {
.driver = {
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index 66a34addb75f..3e24ec455854 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -23,11 +23,8 @@
* @data: the ring buffer memory
* @read_p: read pointer (oldest available)
* @write_p: write pointer
- * @last_written_p: read pointer (newest available)
* @half_p: half buffer length behind write_p (event generation)
- * @use_count: reference count to prevent resizing when in use
* @update_needed: flag to indicated change in size requested
- * @use_lock: lock to prevent change in size when in use
*
* Note that the first element of all ring buffers must be a
* struct iio_buffer.
@@ -37,12 +34,9 @@ struct iio_sw_ring_buffer {
unsigned char *data;
unsigned char *read_p;
unsigned char *write_p;
- unsigned char *last_written_p;
/* used to act as a point at which to signal an event */
unsigned char *half_p;
- int use_count;
int update_needed;
- spinlock_t use_lock;
};
#define iio_to_sw_ring(r) container_of(r, struct iio_sw_ring_buffer, buf)
@@ -56,38 +50,15 @@ static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring,
ring->data = kmalloc(length*ring->buf.bytes_per_datum, GFP_ATOMIC);
ring->read_p = NULL;
ring->write_p = NULL;
- ring->last_written_p = NULL;
ring->half_p = NULL;
return ring->data ? 0 : -ENOMEM;
}
-static inline void __iio_init_sw_ring_buffer(struct iio_sw_ring_buffer *ring)
-{
- spin_lock_init(&ring->use_lock);
-}
-
static inline void __iio_free_sw_ring_buffer(struct iio_sw_ring_buffer *ring)
{
kfree(ring->data);
}
-static void iio_mark_sw_rb_in_use(struct iio_buffer *r)
-{
- struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
- spin_lock(&ring->use_lock);
- ring->use_count++;
- spin_unlock(&ring->use_lock);
-}
-
-static void iio_unmark_sw_rb_in_use(struct iio_buffer *r)
-{
- struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
- spin_lock(&ring->use_lock);
- ring->use_count--;
- spin_unlock(&ring->use_lock);
-}
-
-
/* Ring buffer related functionality */
/* Store to ring is typically called in the bh of a data ready interrupt handler
* in the device driver */
@@ -115,7 +86,6 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring,
* Always valid as either points to latest or second latest value.
* Before this runs it is null and read attempts fail with -EAGAIN.
*/
- ring->last_written_p = ring->write_p;
barrier();
/* temp_ptr used to ensure we never have an invalid pointer
* it may be slightly lagging, but never invalid
@@ -174,6 +144,7 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r,
u8 *initial_read_p, *initial_write_p, *current_read_p, *end_read_p;
u8 *data;
int ret, max_copied, bytes_to_rip, dead_offset;
+ size_t data_available, buffer_size;
/* A userspace program has probably made an error if it tries to
* read something that is not a whole number of bpds.
@@ -186,9 +157,11 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r,
n, ring->buf.bytes_per_datum);
goto error_ret;
}
+
+ buffer_size = ring->buf.bytes_per_datum*ring->buf.length;
+
/* Limit size to whole of ring buffer */
- bytes_to_rip = min((size_t)(ring->buf.bytes_per_datum*ring->buf.length),
- n);
+ bytes_to_rip = min_t(size_t, buffer_size, n);
data = kmalloc(bytes_to_rip, GFP_KERNEL);
if (data == NULL) {
@@ -217,38 +190,24 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r,
goto error_free_data_cpy;
}
- if (initial_write_p >= initial_read_p + bytes_to_rip) {
- /* write_p is greater than necessary, all is easy */
- max_copied = bytes_to_rip;
- memcpy(data, initial_read_p, max_copied);
- end_read_p = initial_read_p + max_copied;
- } else if (initial_write_p > initial_read_p) {
- /*not enough data to cpy */
- max_copied = initial_write_p - initial_read_p;
+ if (initial_write_p >= initial_read_p)
+ data_available = initial_write_p - initial_read_p;
+ else
+ data_available = buffer_size - (initial_read_p - initial_write_p);
+
+ if (data_available < bytes_to_rip)
+ bytes_to_rip = data_available;
+
+ if (initial_read_p + bytes_to_rip >= ring->data + buffer_size) {
+ max_copied = ring->data + buffer_size - initial_read_p;
memcpy(data, initial_read_p, max_copied);
- end_read_p = initial_write_p;
+ memcpy(data + max_copied, ring->data, bytes_to_rip - max_copied);
+ end_read_p = ring->data + bytes_to_rip - max_copied;
} else {
- /* going through 'end' of ring buffer */
- max_copied = ring->data
- + ring->buf.length*ring->buf.bytes_per_datum - initial_read_p;
- memcpy(data, initial_read_p, max_copied);
- /* possible we are done if we align precisely with end */
- if (max_copied == bytes_to_rip)
- end_read_p = ring->data;
- else if (initial_write_p
- > ring->data + bytes_to_rip - max_copied) {
- /* enough data to finish */
- memcpy(data + max_copied, ring->data,
- bytes_to_rip - max_copied);
- max_copied = bytes_to_rip;
- end_read_p = ring->data + (bytes_to_rip - max_copied);
- } else { /* not enough data */
- memcpy(data + max_copied, ring->data,
- initial_write_p - ring->data);
- max_copied += initial_write_p - ring->data;
- end_read_p = initial_write_p;
- }
+ memcpy(data, initial_read_p, bytes_to_rip);
+ end_read_p = initial_read_p + bytes_to_rip;
}
+
/* Now to verify which section was cleanly copied - i.e. how far
* read pointer has been pushed */
current_read_p = ring->read_p;
@@ -256,15 +215,14 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r,
if (initial_read_p <= current_read_p)
dead_offset = current_read_p - initial_read_p;
else
- dead_offset = ring->buf.length*ring->buf.bytes_per_datum
- - (initial_read_p - current_read_p);
+ dead_offset = buffer_size - (initial_read_p - current_read_p);
/* possible issue if the initial write has been lapped or indeed
* the point we were reading to has been passed */
/* No valid data read.
* In this case the read pointer is already correct having been
* pushed further than we would look. */
- if (max_copied - dead_offset < 0) {
+ if (bytes_to_rip - dead_offset < 0) {
ret = 0;
goto error_free_data_cpy;
}
@@ -280,7 +238,7 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r,
while (ring->read_p != end_read_p)
ring->read_p = end_read_p;
- ret = max_copied - dead_offset;
+ ret = bytes_to_rip - dead_offset;
if (copy_to_user(buf, data + dead_offset, ret)) {
ret = -EFAULT;
@@ -305,52 +263,18 @@ static int iio_store_to_sw_rb(struct iio_buffer *r,
return iio_store_to_sw_ring(ring, data, timestamp);
}
-static int iio_read_last_from_sw_ring(struct iio_sw_ring_buffer *ring,
- unsigned char *data)
-{
- unsigned char *last_written_p_copy;
-
- iio_mark_sw_rb_in_use(&ring->buf);
-again:
- barrier();
- last_written_p_copy = ring->last_written_p;
- barrier(); /*unnessecary? */
- /* Check there is anything here */
- if (last_written_p_copy == NULL)
- return -EAGAIN;
- memcpy(data, last_written_p_copy, ring->buf.bytes_per_datum);
-
- if (unlikely(ring->last_written_p != last_written_p_copy))
- goto again;
-
- iio_unmark_sw_rb_in_use(&ring->buf);
- return 0;
-}
-
-static int iio_read_last_from_sw_rb(struct iio_buffer *r,
- unsigned char *data)
-{
- return iio_read_last_from_sw_ring(iio_to_sw_ring(r), data);
-}
-
static int iio_request_update_sw_rb(struct iio_buffer *r)
{
int ret = 0;
struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
r->stufftoread = false;
- spin_lock(&ring->use_lock);
if (!ring->update_needed)
goto error_ret;
- if (ring->use_count) {
- ret = -EAGAIN;
- goto error_ret;
- }
__iio_free_sw_ring_buffer(ring);
ret = __iio_allocate_sw_ring_buffer(ring, ring->buf.bytes_per_datum,
ring->buf.length);
error_ret:
- spin_unlock(&ring->use_lock);
return ret;
}
@@ -360,12 +284,18 @@ static int iio_get_bytes_per_datum_sw_rb(struct iio_buffer *r)
return ring->buf.bytes_per_datum;
}
+static int iio_mark_update_needed_sw_rb(struct iio_buffer *r)
+{
+ struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
+ ring->update_needed = true;
+ return 0;
+}
+
static int iio_set_bytes_per_datum_sw_rb(struct iio_buffer *r, size_t bpd)
{
if (r->bytes_per_datum != bpd) {
r->bytes_per_datum = bpd;
- if (r->access->mark_param_change)
- r->access->mark_param_change(r);
+ iio_mark_update_needed_sw_rb(r);
}
return 0;
}
@@ -379,27 +309,17 @@ static int iio_set_length_sw_rb(struct iio_buffer *r, int length)
{
if (r->length != length) {
r->length = length;
- if (r->access->mark_param_change)
- r->access->mark_param_change(r);
+ iio_mark_update_needed_sw_rb(r);
}
return 0;
}
-static int iio_mark_update_needed_sw_rb(struct iio_buffer *r)
-{
- struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
- ring->update_needed = true;
- return 0;
-}
-
static IIO_BUFFER_ENABLE_ATTR;
-static IIO_BUFFER_BYTES_PER_DATUM_ATTR;
static IIO_BUFFER_LENGTH_ATTR;
/* Standard set of ring buffer attributes */
static struct attribute *iio_ring_attributes[] = {
&dev_attr_length.attr,
- &dev_attr_bytes_per_datum.attr,
&dev_attr_enable.attr,
NULL,
};
@@ -419,8 +339,7 @@ struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev)
return NULL;
ring->update_needed = true;
buf = &ring->buf;
- iio_buffer_init(buf, indio_dev);
- __iio_init_sw_ring_buffer(ring);
+ iio_buffer_init(buf);
buf->attrs = &iio_ring_attribute_group;
return buf;
@@ -434,12 +353,8 @@ void iio_sw_rb_free(struct iio_buffer *r)
EXPORT_SYMBOL(iio_sw_rb_free);
const struct iio_buffer_access_funcs ring_sw_access_funcs = {
- .mark_in_use = &iio_mark_sw_rb_in_use,
- .unmark_in_use = &iio_unmark_sw_rb_in_use,
.store_to = &iio_store_to_sw_rb,
- .read_last = &iio_read_last_from_sw_rb,
.read_first_n = &iio_read_first_n_sw_rb,
- .mark_param_change = &iio_mark_update_needed_sw_rb,
.request_update = &iio_request_update_sw_rb,
.get_bytes_per_datum = &iio_get_bytes_per_datum_sw_rb,
.set_bytes_per_datum = &iio_set_bytes_per_datum_sw_rb,
diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h
index a3e15784c225..e6a6e2c40960 100644
--- a/drivers/staging/iio/ring_sw.h
+++ b/drivers/staging/iio/ring_sw.h
@@ -23,7 +23,7 @@
#ifndef _IIO_RING_SW_H_
#define _IIO_RING_SW_H_
-#include "buffer_generic.h"
+#include "buffer.h"
/**
* ring_sw_access_funcs - access functions for a software ring buffer
diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h
index 868952b5ba63..bfedb73b850e 100644
--- a/drivers/staging/iio/sysfs.h
+++ b/drivers/staging/iio/sysfs.h
@@ -114,47 +114,4 @@ struct iio_const_attr {
#define IIO_CONST_ATTR_TEMP_SCALE(_string) \
IIO_CONST_ATTR(in_temp_scale, _string)
-enum iio_event_type {
- IIO_EV_TYPE_THRESH,
- IIO_EV_TYPE_MAG,
- IIO_EV_TYPE_ROC,
- IIO_EV_TYPE_THRESH_ADAPTIVE,
- IIO_EV_TYPE_MAG_ADAPTIVE,
-};
-
-enum iio_event_direction {
- IIO_EV_DIR_EITHER,
- IIO_EV_DIR_RISING,
- IIO_EV_DIR_FALLING,
-};
-
-#define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \
- type, chan, chan1, chan2) \
- (((u64)type << 56) | ((u64)diff << 55) | \
- ((u64)direction << 48) | ((u64)modifier << 40) | \
- ((u64)chan_type << 32) | (chan2 << 16) | chan1 | chan)
-
-#define IIO_EV_DIR_MAX 4
-#define IIO_EV_BIT(type, direction) \
- (1 << (type*IIO_EV_DIR_MAX + direction))
-
-#define IIO_MOD_EVENT_CODE(channelclass, number, modifier, \
- type, direction) \
- IIO_EVENT_CODE(channelclass, 0, modifier, direction, type, number, 0, 0)
-
-#define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction) \
- IIO_EVENT_CODE(channelclass, 0, 0, direction, type, number, 0, 0)
-
-#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF)
-
-#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF)
-
-#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF)
-
-/* Event code number extraction depends on which type of event we have.
- * Perhaps review this function in the future*/
-#define IIO_EVENT_CODE_EXTRACT_NUM(mask) (mask & 0xFFFF)
-
-#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF)
-
#endif /* _INDUSTRIAL_IO_SYSFS_H_ */
diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h
index 5cc42a655c88..1cfca231db8f 100644
--- a/drivers/staging/iio/trigger.h
+++ b/drivers/staging/iio/trigger.h
@@ -46,7 +46,6 @@ struct iio_trigger_ops {
* @private_data: [DRIVER] device specific data
* @list: [INTERN] used in maintenance of global trigger list
* @alloc_list: [DRIVER] used for driver specific trigger list
- * @owner: [DRIVER] used to monitor usage count of the trigger.
* @use_count: use count for the trigger
* @subirq_chip: [INTERN] associate 'virtual' irq chip.
* @subirq_base: [INTERN] base number for irqs provided by trigger.
@@ -63,7 +62,6 @@ struct iio_trigger {
void *private_data;
struct list_head list;
struct list_head alloc_list;
- struct module *owner;
int use_count;
struct irq_chip subirq_chip;
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index d35d085da949..bd7416b2c561 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -125,7 +125,6 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
goto error_put_trigger_and_remove_from_list;
}
trig->private_data = trig_info;
- trig->owner = THIS_MODULE;
trig->ops = &iio_prtc_trigger_ops;
/* RTC access */
trig_info->rtc
diff --git a/drivers/staging/iio/types.h b/drivers/staging/iio/types.h
new file mode 100644
index 000000000000..b7d26474ad06
--- /dev/null
+++ b/drivers/staging/iio/types.h
@@ -0,0 +1,49 @@
+/* industrial I/O data types needed both in and out of kernel
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _IIO_TYPES_H_
+#define _IIO_TYPES_H_
+
+enum iio_chan_type {
+ /* real channel types */
+ IIO_VOLTAGE,
+ IIO_CURRENT,
+ IIO_POWER,
+ IIO_ACCEL,
+ IIO_ANGL_VEL,
+ IIO_MAGN,
+ IIO_LIGHT,
+ IIO_INTENSITY,
+ IIO_PROXIMITY,
+ IIO_TEMP,
+ IIO_INCLI,
+ IIO_ROT,
+ IIO_ANGL,
+ IIO_TIMESTAMP,
+ IIO_CAPACITANCE,
+};
+
+enum iio_modifier {
+ IIO_NO_MOD,
+ IIO_MOD_X,
+ IIO_MOD_Y,
+ IIO_MOD_Z,
+ IIO_MOD_X_AND_Y,
+ IIO_MOD_X_AND_Z,
+ IIO_MOD_Y_AND_Z,
+ IIO_MOD_X_AND_Y_AND_Z,
+ IIO_MOD_X_OR_Y,
+ IIO_MOD_X_OR_Z,
+ IIO_MOD_Y_OR_Z,
+ IIO_MOD_X_OR_Y_OR_Z,
+ IIO_MOD_LIGHT_BOTH,
+ IIO_MOD_LIGHT_IR,
+};
+
+#endif /* _IIO_TYPES_H_ */
diff --git a/drivers/staging/intel_sst/Kconfig b/drivers/staging/intel_sst/Kconfig
deleted file mode 100644
index 82391077b384..000000000000
--- a/drivers/staging/intel_sst/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-config SND_INTEL_SST
- tristate "Intel SST (LPE) Driver"
- depends on X86 && INTEL_SCU_IPC
- default n
- help
- Say Y here to include support for the Intel(R) MID SST DSP driver
- On other PC platforms if you are unsure answer 'N'
-
-config SND_INTELMID
- tristate "Intel MID sound card driver"
- depends on SOUND && SND
- select SND_PCM
- select SND_SEQUENCER
- select SND_JACK
- depends on SND_INTEL_SST
- default n
- help
- Say Y here to include support for the Intel(R) MID sound card driver
- On other PC platforms if you are unsure answer 'N'
diff --git a/drivers/staging/intel_sst/Makefile b/drivers/staging/intel_sst/Makefile
deleted file mode 100644
index 9eb7c158bb65..000000000000
--- a/drivers/staging/intel_sst/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for Intel MID Audio drivers
-#
-snd-intel-sst-y := intel_sst.o intel_sst_ipc.o intel_sst_stream.o intel_sst_drv_interface.o intel_sst_dsp.o intel_sst_pvt.o intel_sst_stream_encoded.o intel_sst_app_interface.o
-snd-intelmid-y := intelmid.o intelmid_msic_control.o intelmid_ctrl.o intelmid_pvt.o intelmid_v0_control.o intelmid_v1_control.o intelmid_v2_control.o
-obj-$(CONFIG_SND_INTEL_SST) += snd-intel-sst.o
-obj-$(CONFIG_SND_INTELMID) += snd-intelmid.o
diff --git a/drivers/staging/intel_sst/TODO b/drivers/staging/intel_sst/TODO
deleted file mode 100644
index c733d7011091..000000000000
--- a/drivers/staging/intel_sst/TODO
+++ /dev/null
@@ -1,13 +0,0 @@
-TODO
-----
-
-Get the memrar driver cleaned up and upstream (dependency blocking SST)
-Replace long/short press with two virtual buttons
-Review the printks and kill off any left over ST_ERR: messages
-Review the misc device ioctls for 32/64bit safety and sanity
-Review the misc device ioctls for size safety depending on config and decide
- if space/unused areas should be left
-What the sound folks turn up on full review
-Using the ALSA frameworks properly
-
-
diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c
deleted file mode 100644
index ff9aaec0557f..000000000000
--- a/drivers/staging/intel_sst/intel_sst.c
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * intel_sst.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This driver exposes the audio engine functionalities to the ALSA
- * and middleware.
- *
- * This file contains all init functions
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/firmware.h>
-#include <linux/miscdevice.h>
-#include <linux/pm_runtime.h>
-#include <linux/module.h>
-#include <asm/mrst.h>
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intel_sst_fw_ipc.h"
-#include "intel_sst_common.h"
-
-
-MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
-MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
-MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>");
-MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>");
-MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine Driver");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(SST_DRIVER_VERSION);
-
-struct intel_sst_drv *sst_drv_ctx;
-static struct mutex drv_ctx_lock;
-struct class *sst_class;
-
-/* fops Routines */
-static const struct file_operations intel_sst_fops = {
- .owner = THIS_MODULE,
- .open = intel_sst_open,
- .release = intel_sst_release,
- .read = intel_sst_read,
- .write = intel_sst_write,
- .unlocked_ioctl = intel_sst_ioctl,
- .mmap = intel_sst_mmap,
- .aio_read = intel_sst_aio_read,
- .aio_write = intel_sst_aio_write,
-};
-static const struct file_operations intel_sst_fops_cntrl = {
- .owner = THIS_MODULE,
- .open = intel_sst_open_cntrl,
- .release = intel_sst_release_cntrl,
- .unlocked_ioctl = intel_sst_ioctl,
-};
-
-static struct miscdevice lpe_dev = {
- .minor = MISC_DYNAMIC_MINOR,/* dynamic allocation */
- .name = "intel_sst",/* /dev/intel_sst */
- .fops = &intel_sst_fops
-};
-
-
-static struct miscdevice lpe_ctrl = {
- .minor = MISC_DYNAMIC_MINOR,/* dynamic allocation */
- .name = "intel_sst_ctrl",/* /dev/intel_sst_ctrl */
- .fops = &intel_sst_fops_cntrl
-};
-
-/**
-* intel_sst_interrupt - Interrupt service routine for SST
-*
-* @irq: irq number of interrupt
-* @context: pointer to device structre
-*
-* This function is called by OS when SST device raises
-* an interrupt. This will be result of write in IPC register
-* Source can be busy or done interrupt
-*/
-static irqreturn_t intel_sst_interrupt(int irq, void *context)
-{
- union interrupt_reg isr;
- union ipc_header header;
- union interrupt_reg imr;
- struct intel_sst_drv *drv = (struct intel_sst_drv *) context;
- unsigned int size = 0, str_id;
- struct stream_info *stream ;
-
- /* Do not handle interrupt in suspended state */
- if (drv->sst_state == SST_SUSPENDED)
- return IRQ_NONE;
- /* Interrupt arrived, check src */
- isr.full = sst_shim_read(drv->shim, SST_ISRX);
-
- if (isr.part.busy_interrupt) {
- header.full = sst_shim_read(drv->shim, SST_IPCD);
- if (header.part.msg_id == IPC_SST_PERIOD_ELAPSED) {
- sst_clear_interrupt();
- str_id = header.part.str_id;
- stream = &sst_drv_ctx->streams[str_id];
- if (stream->period_elapsed)
- stream->period_elapsed(stream->pcm_substream);
- return IRQ_HANDLED;
- }
- if (header.part.large)
- size = header.part.data;
- if (header.part.msg_id & REPLY_MSG) {
- sst_drv_ctx->ipc_process_msg.header = header;
- memcpy_fromio(sst_drv_ctx->ipc_process_msg.mailbox,
- drv->mailbox + SST_MAILBOX_RCV, size);
- queue_work(sst_drv_ctx->process_msg_wq,
- &sst_drv_ctx->ipc_process_msg.wq);
- } else {
- sst_drv_ctx->ipc_process_reply.header = header;
- memcpy_fromio(sst_drv_ctx->ipc_process_reply.mailbox,
- drv->mailbox + SST_MAILBOX_RCV, size);
- queue_work(sst_drv_ctx->process_reply_wq,
- &sst_drv_ctx->ipc_process_reply.wq);
- }
- /* mask busy inetrrupt */
- imr.full = sst_shim_read(drv->shim, SST_IMRX);
- imr.part.busy_interrupt = 1;
- sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
- return IRQ_HANDLED;
- } else if (isr.part.done_interrupt) {
- /* Clear done bit */
- header.full = sst_shim_read(drv->shim, SST_IPCX);
- header.part.done = 0;
- sst_shim_write(sst_drv_ctx->shim, SST_IPCX, header.full);
- /* write 1 to clear status register */;
- isr.part.done_interrupt = 1;
- /* dummy register for shim workaround */
- sst_shim_write(sst_drv_ctx->shim, SST_ISRX, isr.full);
- queue_work(sst_drv_ctx->post_msg_wq,
- &sst_drv_ctx->ipc_post_msg.wq);
- return IRQ_HANDLED;
- } else
- return IRQ_NONE;
-
-}
-
-
-/*
-* intel_sst_probe - PCI probe function
-*
-* @pci: PCI device structure
-* @pci_id: PCI device ID structure
-*
-* This function is called by OS when a device is found
-* This enables the device, interrupt etc
-*/
-static int __devinit intel_sst_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
-{
- int i, ret = 0;
-
- pr_debug("Probe for DID %x\n", pci->device);
- mutex_lock(&drv_ctx_lock);
- if (sst_drv_ctx) {
- pr_err("Only one sst handle is supported\n");
- mutex_unlock(&drv_ctx_lock);
- return -EBUSY;
- }
-
- sst_drv_ctx = kzalloc(sizeof(*sst_drv_ctx), GFP_KERNEL);
- if (!sst_drv_ctx) {
- pr_err("malloc fail\n");
- mutex_unlock(&drv_ctx_lock);
- return -ENOMEM;
- }
- mutex_unlock(&drv_ctx_lock);
-
- sst_drv_ctx->pci_id = pci->device;
-
- mutex_init(&sst_drv_ctx->stream_lock);
- mutex_init(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->pmic_state = SND_MAD_UN_INIT;
-
- sst_drv_ctx->stream_cnt = 0;
- sst_drv_ctx->encoded_cnt = 0;
- sst_drv_ctx->am_cnt = 0;
- sst_drv_ctx->pb_streams = 0;
- sst_drv_ctx->cp_streams = 0;
- sst_drv_ctx->unique_id = 0;
- sst_drv_ctx->pmic_port_instance = SST_DEFAULT_PMIC_PORT;
-
- INIT_LIST_HEAD(&sst_drv_ctx->ipc_dispatch_list);
- INIT_WORK(&sst_drv_ctx->ipc_post_msg.wq, sst_post_message);
- INIT_WORK(&sst_drv_ctx->ipc_process_msg.wq, sst_process_message);
- INIT_WORK(&sst_drv_ctx->ipc_process_reply.wq, sst_process_reply);
- INIT_WORK(&sst_drv_ctx->mad_ops.wq, sst_process_mad_ops);
- init_waitqueue_head(&sst_drv_ctx->wait_queue);
-
- sst_drv_ctx->mad_wq = create_workqueue("sst_mad_wq");
- if (!sst_drv_ctx->mad_wq)
- goto do_free_drv_ctx;
- sst_drv_ctx->post_msg_wq = create_workqueue("sst_post_msg_wq");
- if (!sst_drv_ctx->post_msg_wq)
- goto free_mad_wq;
- sst_drv_ctx->process_msg_wq = create_workqueue("sst_process_msg_wqq");
- if (!sst_drv_ctx->process_msg_wq)
- goto free_post_msg_wq;
- sst_drv_ctx->process_reply_wq = create_workqueue("sst_proces_reply_wq");
- if (!sst_drv_ctx->process_reply_wq)
- goto free_process_msg_wq;
-
- for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
- sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
- sst_drv_ctx->alloc_block[i].ops_block.condition = false;
- }
- spin_lock_init(&sst_drv_ctx->list_spin_lock);
-
- sst_drv_ctx->max_streams = pci_id->driver_data;
- pr_debug("Got drv data max stream %d\n",
- sst_drv_ctx->max_streams);
- for (i = 1; i <= sst_drv_ctx->max_streams; i++) {
- struct stream_info *stream = &sst_drv_ctx->streams[i];
- INIT_LIST_HEAD(&stream->bufs);
- mutex_init(&stream->lock);
- spin_lock_init(&stream->pcm_lock);
- }
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
- sst_drv_ctx->mmap_mem = NULL;
- sst_drv_ctx->mmap_len = SST_MMAP_PAGES * PAGE_SIZE;
- while (sst_drv_ctx->mmap_len > 0) {
- sst_drv_ctx->mmap_mem =
- kzalloc(sst_drv_ctx->mmap_len, GFP_KERNEL);
- if (sst_drv_ctx->mmap_mem) {
- pr_debug("Got memory %p size 0x%x\n",
- sst_drv_ctx->mmap_mem,
- sst_drv_ctx->mmap_len);
- break;
- }
- if (sst_drv_ctx->mmap_len < (SST_MMAP_STEP*PAGE_SIZE)) {
- pr_err("mem alloc fail...abort!!\n");
- ret = -ENOMEM;
- goto free_process_reply_wq;
- }
- sst_drv_ctx->mmap_len -= (SST_MMAP_STEP * PAGE_SIZE);
- pr_debug("mem alloc failed...trying %d\n",
- sst_drv_ctx->mmap_len);
- }
- }
-
- /* Init the device */
- ret = pci_enable_device(pci);
- if (ret) {
- pr_err("device can't be enabled\n");
- goto do_free_mem;
- }
- sst_drv_ctx->pci = pci_dev_get(pci);
- ret = pci_request_regions(pci, SST_DRV_NAME);
- if (ret)
- goto do_disable_device;
- /* map registers */
- /* SST Shim */
- sst_drv_ctx->shim_phy_add = pci_resource_start(pci, 1);
- sst_drv_ctx->shim = pci_ioremap_bar(pci, 1);
- if (!sst_drv_ctx->shim)
- goto do_release_regions;
- pr_debug("SST Shim Ptr %p\n", sst_drv_ctx->shim);
-
- /* Shared SRAM */
- sst_drv_ctx->mailbox = pci_ioremap_bar(pci, 2);
- if (!sst_drv_ctx->mailbox)
- goto do_unmap_shim;
- pr_debug("SRAM Ptr %p\n", sst_drv_ctx->mailbox);
-
- /* IRAM */
- sst_drv_ctx->iram = pci_ioremap_bar(pci, 3);
- if (!sst_drv_ctx->iram)
- goto do_unmap_sram;
- pr_debug("IRAM Ptr %p\n", sst_drv_ctx->iram);
-
- /* DRAM */
- sst_drv_ctx->dram = pci_ioremap_bar(pci, 4);
- if (!sst_drv_ctx->dram)
- goto do_unmap_iram;
- pr_debug("DRAM Ptr %p\n", sst_drv_ctx->dram);
-
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_UN_INIT;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- /* Register the ISR */
- ret = request_irq(pci->irq, intel_sst_interrupt,
- IRQF_SHARED, SST_DRV_NAME, sst_drv_ctx);
- if (ret)
- goto do_unmap_dram;
- pr_debug("Registered IRQ 0x%x\n", pci->irq);
-
- /*Register LPE Control as misc driver*/
- ret = misc_register(&lpe_ctrl);
- if (ret) {
- pr_err("couldn't register control device\n");
- goto do_free_irq;
- }
-
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
- ret = misc_register(&lpe_dev);
- if (ret) {
- pr_err("couldn't register LPE device\n");
- goto do_free_misc;
- }
- } else if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID) {
- u32 csr;
-
- /*allocate mem for fw context save during suspend*/
- sst_drv_ctx->fw_cntx = kzalloc(FW_CONTEXT_MEM, GFP_KERNEL);
- if (!sst_drv_ctx->fw_cntx) {
- ret = -ENOMEM;
- goto do_free_misc;
- }
- /*setting zero as that is valid mem to restore*/
- sst_drv_ctx->fw_cntx_size = 0;
-
- /*set lpe start clock and ram size*/
- csr = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr |= 0x30060; /*remove the clock ratio after fw fix*/
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr);
- }
- sst_drv_ctx->lpe_stalled = 0;
- pci_set_drvdata(pci, sst_drv_ctx);
- pm_runtime_allow(&pci->dev);
- pm_runtime_put_noidle(&pci->dev);
- pr_debug("...successfully done!!!\n");
- return ret;
-
-do_free_misc:
- misc_deregister(&lpe_ctrl);
-do_free_irq:
- free_irq(pci->irq, sst_drv_ctx);
-do_unmap_dram:
- iounmap(sst_drv_ctx->dram);
-do_unmap_iram:
- iounmap(sst_drv_ctx->iram);
-do_unmap_sram:
- iounmap(sst_drv_ctx->mailbox);
-do_unmap_shim:
- iounmap(sst_drv_ctx->shim);
-do_release_regions:
- pci_release_regions(pci);
-do_disable_device:
- pci_disable_device(pci);
-do_free_mem:
- kfree(sst_drv_ctx->mmap_mem);
-free_process_reply_wq:
- destroy_workqueue(sst_drv_ctx->process_reply_wq);
-free_process_msg_wq:
- destroy_workqueue(sst_drv_ctx->process_msg_wq);
-free_post_msg_wq:
- destroy_workqueue(sst_drv_ctx->post_msg_wq);
-free_mad_wq:
- destroy_workqueue(sst_drv_ctx->mad_wq);
-do_free_drv_ctx:
- kfree(sst_drv_ctx);
- sst_drv_ctx = NULL;
- pr_err("Probe failed with %d\n", ret);
- return ret;
-}
-
-/**
-* intel_sst_remove - PCI remove function
-*
-* @pci: PCI device structure
-*
-* This function is called by OS when a device is unloaded
-* This frees the interrupt etc
-*/
-static void __devexit intel_sst_remove(struct pci_dev *pci)
-{
- pm_runtime_get_noresume(&pci->dev);
- pm_runtime_forbid(&pci->dev);
- pci_dev_put(sst_drv_ctx->pci);
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_UN_INIT;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- misc_deregister(&lpe_ctrl);
- free_irq(pci->irq, sst_drv_ctx);
- iounmap(sst_drv_ctx->dram);
- iounmap(sst_drv_ctx->iram);
- iounmap(sst_drv_ctx->mailbox);
- iounmap(sst_drv_ctx->shim);
- sst_drv_ctx->pmic_state = SND_MAD_UN_INIT;
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
- misc_deregister(&lpe_dev);
- kfree(sst_drv_ctx->mmap_mem);
- } else
- kfree(sst_drv_ctx->fw_cntx);
- flush_scheduled_work();
- destroy_workqueue(sst_drv_ctx->process_reply_wq);
- destroy_workqueue(sst_drv_ctx->process_msg_wq);
- destroy_workqueue(sst_drv_ctx->post_msg_wq);
- destroy_workqueue(sst_drv_ctx->mad_wq);
- kfree(pci_get_drvdata(pci));
- sst_drv_ctx = NULL;
- pci_release_regions(pci);
- pci_disable_device(pci);
- pci_set_drvdata(pci, NULL);
-}
-
-void sst_save_dsp_context(void)
-{
- struct snd_sst_ctxt_params fw_context;
- unsigned int pvt_id, i;
- struct ipc_post *msg = NULL;
-
- /*check cpu type*/
- if (sst_drv_ctx->pci_id != SST_MFLD_PCI_ID)
- return;
- /*not supported for rest*/
- if (sst_drv_ctx->sst_state != SST_FW_RUNNING) {
- pr_debug("fw not running no context save ...\n");
- return;
- }
-
- /*send msg to fw*/
- if (sst_create_large_msg(&msg))
- return;
- pvt_id = sst_assign_pvt_id(sst_drv_ctx);
- i = sst_get_block_stream(sst_drv_ctx);
- sst_drv_ctx->alloc_block[i].sst_id = pvt_id;
- sst_fill_header(&msg->header, IPC_IA_GET_FW_CTXT, 1, pvt_id);
- msg->header.part.data = sizeof(fw_context) + sizeof(u32);
- fw_context.address = virt_to_phys((void *)sst_drv_ctx->fw_cntx);
- fw_context.size = FW_CONTEXT_MEM;
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32),
- &fw_context, sizeof(fw_context));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- /*wait for reply*/
- if (sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]))
- pr_debug("err fw context save timeout ...\n");
- sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
- pr_debug("fw context saved ...\n");
- return;
-}
-
-/* Power Management */
-/*
-* intel_sst_suspend - PCI suspend function
-*
-* @pci: PCI device structure
-* @state: PM message
-*
-* This function is called by OS when a power event occurs
-*/
-int intel_sst_suspend(struct pci_dev *pci, pm_message_t state)
-{
- union config_status_reg csr;
-
- pr_debug("intel_sst_suspend called\n");
-
- if (sst_drv_ctx->stream_cnt) {
- pr_err("active streams,not able to suspend\n");
- return -EBUSY;
- }
- /*save fw context*/
- sst_save_dsp_context();
- /*Assert RESET on LPE Processor*/
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.full = csr.full | 0x2;
- /* Move the SST state to Suspended */
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_SUSPENDED;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
- mutex_unlock(&sst_drv_ctx->sst_lock);
- pci_set_drvdata(pci, sst_drv_ctx);
- pci_save_state(pci);
- pci_disable_device(pci);
- pci_set_power_state(pci, PCI_D3hot);
- return 0;
-}
-
-/**
-* intel_sst_resume - PCI resume function
-*
-* @pci: PCI device structure
-*
-* This function is called by OS when a power event occurs
-*/
-int intel_sst_resume(struct pci_dev *pci)
-{
- int ret = 0;
-
- pr_debug("intel_sst_resume called\n");
- if (sst_drv_ctx->sst_state != SST_SUSPENDED) {
- pr_err("SST is not in suspended state\n");
- return 0;
- }
- sst_drv_ctx = pci_get_drvdata(pci);
- pci_set_power_state(pci, PCI_D0);
- pci_restore_state(pci);
- ret = pci_enable_device(pci);
- if (ret)
- pr_err("device can't be enabled\n");
-
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_UN_INIT;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- return 0;
-}
-
-/* The runtime_suspend/resume is pretty much similar to the legacy
- * suspend/resume with the noted exception below:
- * The PCI core takes care of taking the system through D3hot and
- * restoring it back to D0 and so there is no need to duplicate
- * that here.
- */
-static int intel_sst_runtime_suspend(struct device *dev)
-{
- union config_status_reg csr;
-
- pr_debug("intel_sst_runtime_suspend called\n");
- if (sst_drv_ctx->stream_cnt) {
- pr_err("active streams,not able to suspend\n");
- return -EBUSY;
- }
- /*save fw context*/
- sst_save_dsp_context();
- /*Assert RESET on LPE Processor*/
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.full = csr.full | 0x2;
- /* Move the SST state to Suspended */
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_SUSPENDED;
-
- /* Only needed by Medfield */
- if (sst_drv_ctx->pci_id != SST_MRST_PCI_ID)
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
- mutex_unlock(&sst_drv_ctx->sst_lock);
- return 0;
-}
-
-static int intel_sst_runtime_resume(struct device *dev)
-{
-
- pr_debug("intel_sst_runtime_resume called\n");
- if (sst_drv_ctx->sst_state != SST_SUSPENDED) {
- pr_err("SST is not in suspended state\n");
- return 0;
- }
-
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_UN_INIT;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- return 0;
-}
-
-static int intel_sst_runtime_idle(struct device *dev)
-{
- pr_debug("runtime_idle called\n");
- if (sst_drv_ctx->stream_cnt == 0 && sst_drv_ctx->am_cnt == 0)
- pm_schedule_suspend(dev, SST_SUSPEND_DELAY);
- return -EBUSY;
-}
-
-static const struct dev_pm_ops intel_sst_pm = {
- .runtime_suspend = intel_sst_runtime_suspend,
- .runtime_resume = intel_sst_runtime_resume,
- .runtime_idle = intel_sst_runtime_idle,
-};
-
-/* PCI Routines */
-static struct pci_device_id intel_sst_ids[] = {
- { PCI_VDEVICE(INTEL, SST_MRST_PCI_ID), 3},
- { PCI_VDEVICE(INTEL, SST_MFLD_PCI_ID), 6},
- { 0, }
-};
-MODULE_DEVICE_TABLE(pci, intel_sst_ids);
-
-static struct pci_driver driver = {
- .name = SST_DRV_NAME,
- .id_table = intel_sst_ids,
- .probe = intel_sst_probe,
- .remove = __devexit_p(intel_sst_remove),
-#ifdef CONFIG_PM
- .suspend = intel_sst_suspend,
- .resume = intel_sst_resume,
- .driver = {
- .pm = &intel_sst_pm,
- },
-#endif
-};
-
-/**
-* intel_sst_init - Module init function
-*
-* Registers with PCI
-* Registers with /dev
-* Init all data strutures
-*/
-static int __init intel_sst_init(void)
-{
- /* Init all variables, data structure etc....*/
- int ret = 0;
- pr_debug("INFO: ******** SST DRIVER loading.. Ver: %s\n",
- SST_DRIVER_VERSION);
-
- mutex_init(&drv_ctx_lock);
- /* Register with PCI */
- ret = pci_register_driver(&driver);
- if (ret)
- pr_err("PCI register failed\n");
- return ret;
-}
-
-/**
-* intel_sst_exit - Module exit function
-*
-* Unregisters with PCI
-* Unregisters with /dev
-* Frees all data strutures
-*/
-static void __exit intel_sst_exit(void)
-{
- pci_unregister_driver(&driver);
-
- pr_debug("driver unloaded\n");
- sst_drv_ctx = NULL;
- return;
-}
-
-module_init(intel_sst_init);
-module_exit(intel_sst_exit);
diff --git a/drivers/staging/intel_sst/intel_sst.h b/drivers/staging/intel_sst/intel_sst.h
deleted file mode 100644
index 4ad2829105a7..000000000000
--- a/drivers/staging/intel_sst/intel_sst.h
+++ /dev/null
@@ -1,162 +0,0 @@
-#ifndef __INTEL_SST_H__
-#define __INTEL_SST_H__
-/*
- * intel_sst.h - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corporation
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This driver exposes the audio engine functionalities to the ALSA
- * and middleware.
- * This file is shared between the SST and MAD drivers
- */
-#include "intel_sst_ioctl.h"
-#include <sound/jack.h>
-
-#define SST_CARD_NAMES "intel_mid_card"
-
-#define MFLD_MAX_HW_CH 4
-/* control list Pmic & Lpe */
-/* Input controls */
-enum port_status {
- ACTIVATE = 1,
- DEACTIVATE,
-};
-
-/* Card states */
-enum sst_card_states {
- SND_CARD_UN_INIT = 0,
- SND_CARD_INIT_DONE,
-};
-
-enum sst_controls {
- SST_SND_ALLOC = 0x1000,
- SST_SND_PAUSE = 0x1001,
- SST_SND_RESUME = 0x1002,
- SST_SND_DROP = 0x1003,
- SST_SND_FREE = 0x1004,
- SST_SND_BUFFER_POINTER = 0x1005,
- SST_SND_STREAM_INIT = 0x1006,
- SST_SND_START = 0x1007,
- SST_SND_STREAM_PROCESS = 0x1008,
- SST_MAX_CONTROLS = 0x1008,
- SST_CONTROL_BASE = 0x1000,
- SST_ENABLE_RX_TIME_SLOT = 0x1009,
-};
-
-enum SND_CARDS {
- SND_FS = 0,
- SND_MX,
- SND_NC,
- SND_MSIC
-};
-
-struct pcm_stream_info {
- int str_id;
- void *mad_substream;
- void (*period_elapsed) (void *mad_substream);
- unsigned long long buffer_ptr;
- int sfreq;
-};
-
-struct snd_pmic_ops {
- int card_status;
- int master_mute;
- int num_channel;
- int input_dev_id;
- int mute_status;
- struct mutex lock;
- int pb_on, pbhs_on;
- int cap_on;
- int output_dev_id;
- int lineout_dev_id, line_out_names_cnt;
- int prev_lineout_dev_id;
- bool jack_interrupt_status;
- int (*set_input_dev) (u8 value);
- int (*set_output_dev) (u8 value);
- int (*set_lineout_dev) (u8 value);
- int (*set_mute) (int dev_id, u8 value);
- int (*get_mute) (int dev_id, u8 *value);
-
- int (*set_vol) (int dev_id, int value);
- int (*get_vol) (int dev_id, int *value);
-
- int (*init_card) (void);
- int (*set_pcm_audio_params)
- (int sfreq, int word_size , int num_channel);
- int (*set_pcm_voice_params) (void);
- int (*set_voice_port) (int status);
- int (*set_audio_port) (int status);
-
- int (*power_up_pmic_pb) (unsigned int port);
- int (*power_up_pmic_cp) (unsigned int port);
- int (*power_down_pmic_pb) (unsigned int device);
- int (*power_down_pmic_cp) (unsigned int device);
- int (*power_down_pmic) (void);
- void (*pmic_irq_cb) (void *cb_data, u8 value);
- void (*pmic_irq_enable)(void *data);
- int (*pmic_jack_enable) (void);
- int (*pmic_get_mic_bias)(void *intelmaddata);
- int (*pmic_set_headset_state)(int state);
-
- unsigned int hw_dmic_map[MFLD_MAX_HW_CH];
- unsigned int available_dmics;
- int (*set_hw_dmic_route) (u8 index);
-
- int gpio_amp;
-};
-
-extern void sst_mad_send_jack_report(struct snd_jack *jack,
- int buttonpressevent,
- int status);
-
-
-int intemad_set_headset_state(int state);
-int intelmad_get_mic_bias(void);
-
-struct intel_sst_pcm_control {
- int (*open) (struct snd_sst_params *str_param);
- int (*device_control) (int cmd, void *arg);
- int (*close) (unsigned int str_id);
-};
-struct intel_sst_card_ops {
- char *module_name;
- unsigned int vendor_id;
- struct intel_sst_pcm_control *pcm_control;
- struct snd_pmic_ops *scard_ops;
-};
-
-/* modified for generic access */
-struct sc_reg_access {
- u16 reg_addr;
- u8 value;
- u8 mask;
-};
-enum sc_reg_access_type {
- PMIC_READ = 0,
- PMIC_WRITE,
- PMIC_READ_MODIFY,
-};
-
-int register_sst_card(struct intel_sst_card_ops *card);
-void unregister_sst_card(struct intel_sst_card_ops *card);
-#endif /* __INTEL_SST_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_app_interface.c b/drivers/staging/intel_sst/intel_sst_app_interface.c
deleted file mode 100644
index 93b41a284d83..000000000000
--- a/drivers/staging/intel_sst/intel_sst_app_interface.c
+++ /dev/null
@@ -1,1460 +0,0 @@
-/*
- * intel_sst_interface.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * Jeeja KP <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This driver exposes the audio engine functionalities to the ALSA
- * and middleware.
- * Upper layer interfaces (MAD driver, MMF) to SST driver
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/uio.h>
-#include <linux/aio.h>
-#include <linux/uaccess.h>
-#include <linux/firmware.h>
-#include <linux/pm_runtime.h>
-#include <linux/ioctl.h>
-#ifdef CONFIG_MRST_RAR_HANDLER
-#include <linux/rar_register.h>
-#include "../../../drivers/staging/memrar/memrar.h"
-#endif
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intel_sst_fw_ipc.h"
-#include "intel_sst_common.h"
-
-#define AM_MODULE 1
-#define STREAM_MODULE 0
-
-
-/**
-* intel_sst_check_device - checks SST device
-*
-* This utility function checks the state of SST device and downlaods FW if
-* not done, or resumes the device if suspended
-*/
-
-static int intel_sst_check_device(void)
-{
- int retval = 0;
- if (sst_drv_ctx->pmic_state != SND_MAD_INIT_DONE) {
- pr_warn("Sound card not available\n");
- return -EIO;
- }
- if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
- pr_debug("Resuming from Suspended state\n");
- retval = intel_sst_resume(sst_drv_ctx->pci);
- if (retval) {
- pr_debug("Resume Failed= %#x,abort\n", retval);
- return retval;
- }
- }
-
- if (sst_drv_ctx->sst_state == SST_UN_INIT) {
- /* FW is not downloaded */
- retval = sst_download_fw();
- if (retval)
- return -ENODEV;
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
- retval = sst_drv_ctx->rx_time_slot_status;
- if (retval != RX_TIMESLOT_UNINIT
- && sst_drv_ctx->pmic_vendor != SND_NC)
- sst_enable_rx_timeslot(retval);
- }
- }
- return 0;
-}
-
-/**
- * intel_sst_open - opens a handle to driver
- *
- * @i_node: inode structure
- * @file_ptr:pointer to file
- *
- * This function is called by OS when a user space component
- * tries to get a driver handle. Only one handle at a time
- * will be allowed
- */
-int intel_sst_open(struct inode *i_node, struct file *file_ptr)
-{
- unsigned int retval;
-
- mutex_lock(&sst_drv_ctx->stream_lock);
- pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
- retval = intel_sst_check_device();
- if (retval) {
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- return retval;
- }
-
- if (sst_drv_ctx->encoded_cnt < MAX_ENC_STREAM) {
- struct ioctl_pvt_data *data =
- kzalloc(sizeof(struct ioctl_pvt_data), GFP_KERNEL);
- if (!data) {
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- return -ENOMEM;
- }
-
- sst_drv_ctx->encoded_cnt++;
- mutex_unlock(&sst_drv_ctx->stream_lock);
- data->pvt_id = sst_assign_pvt_id(sst_drv_ctx);
- data->str_id = 0;
- file_ptr->private_data = (void *)data;
- pr_debug("pvt_id handle = %d!\n", data->pvt_id);
- } else {
- retval = -EUSERS;
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- }
- return retval;
-}
-
-/**
- * intel_sst_open_cntrl - opens a handle to driver
- *
- * @i_node: inode structure
- * @file_ptr:pointer to file
- *
- * This function is called by OS when a user space component
- * tries to get a driver handle to /dev/intel_sst_control.
- * Only one handle at a time will be allowed
- * This is for control operations only
- */
-int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
-{
- unsigned int retval;
-
- /* audio manager open */
- mutex_lock(&sst_drv_ctx->stream_lock);
- pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
- retval = intel_sst_check_device();
- if (retval) {
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- return retval;
- }
-
- if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) {
- sst_drv_ctx->am_cnt++;
- pr_debug("AM handle opened...\n");
- file_ptr->private_data = NULL;
- } else {
- retval = -EACCES;
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- }
-
- mutex_unlock(&sst_drv_ctx->stream_lock);
- return retval;
-}
-
-/**
- * intel_sst_release - releases a handle to driver
- *
- * @i_node: inode structure
- * @file_ptr: pointer to file
- *
- * This function is called by OS when a user space component
- * tries to release a driver handle.
- */
-int intel_sst_release(struct inode *i_node, struct file *file_ptr)
-{
- struct ioctl_pvt_data *data = file_ptr->private_data;
-
- pr_debug("Release called, closing app handle\n");
- mutex_lock(&sst_drv_ctx->stream_lock);
- sst_drv_ctx->encoded_cnt--;
- sst_drv_ctx->stream_cnt--;
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- free_stream_context(data->str_id);
- kfree(data);
- return 0;
-}
-
-int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr)
-{
- /* audio manager close */
- mutex_lock(&sst_drv_ctx->stream_lock);
- sst_drv_ctx->am_cnt--;
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- pr_debug("AM handle closed\n");
- return 0;
-}
-
-/**
-* intel_sst_mmap - mmaps a kernel buffer to user space for copying data
-*
-* @vma: vm area structure instance
-* @file_ptr: pointer to file
-*
-* This function is called by OS when a user space component
-* tries to get mmap memory from driver
-*/
-int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma)
-{
- int retval, length;
- struct ioctl_pvt_data *data =
- (struct ioctl_pvt_data *)file_ptr->private_data;
- int str_id = data->str_id;
- void *mem_area;
-
- retval = sst_validate_strid(str_id);
- if (retval)
- return -EINVAL;
-
- length = vma->vm_end - vma->vm_start;
- pr_debug("called for stream %d length 0x%x\n", str_id, length);
-
- if (length > sst_drv_ctx->mmap_len)
- return -ENOMEM;
- if (!sst_drv_ctx->mmap_mem)
- return -EIO;
-
- /* round it up to the page boundary */
- /*mem_area = (void *)((((unsigned long)sst_drv_ctx->mmap_mem)
- + PAGE_SIZE - 1) & PAGE_MASK);*/
- mem_area = (void *) PAGE_ALIGN((unsigned int) sst_drv_ctx->mmap_mem);
-
- /* map the whole physically contiguous area in one piece */
- retval = remap_pfn_range(vma,
- vma->vm_start,
- virt_to_phys((void *)mem_area) >> PAGE_SHIFT,
- length,
- vma->vm_page_prot);
- if (retval)
- sst_drv_ctx->streams[str_id].mmapped = false;
- else
- sst_drv_ctx->streams[str_id].mmapped = true;
-
- pr_debug("mmap ret 0x%x\n", retval);
- return retval;
-}
-
-/* sets mmap data buffers to play/capture*/
-static int intel_sst_mmap_play_capture(u32 str_id,
- struct snd_sst_mmap_buffs *mmap_buf)
-{
- struct sst_stream_bufs *bufs;
- int retval, i;
- struct stream_info *stream;
- struct snd_sst_mmap_buff_entry *buf_entry;
- struct snd_sst_mmap_buff_entry *tmp_buf;
-
- pr_debug("called for str_id %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return -EINVAL;
-
- stream = &sst_drv_ctx->streams[str_id];
- if (stream->mmapped != true)
- return -EIO;
-
- if (stream->status == STREAM_UN_INIT ||
- stream->status == STREAM_DECODE) {
- return -EBADRQC;
- }
- stream->curr_bytes = 0;
- stream->cumm_bytes = 0;
-
- tmp_buf = kcalloc(mmap_buf->entries, sizeof(*tmp_buf), GFP_KERNEL);
- if (!tmp_buf)
- return -ENOMEM;
- if (copy_from_user(tmp_buf, (void __user *)mmap_buf->buff,
- mmap_buf->entries * sizeof(*tmp_buf))) {
- retval = -EFAULT;
- goto out_free;
- }
-
- pr_debug("new buffers count %d status %d\n",
- mmap_buf->entries, stream->status);
- buf_entry = tmp_buf;
- for (i = 0; i < mmap_buf->entries; i++) {
- bufs = kzalloc(sizeof(*bufs), GFP_KERNEL);
- if (!bufs) {
- retval = -ENOMEM;
- goto out_free;
- }
- bufs->size = buf_entry->size;
- bufs->offset = buf_entry->offset;
- bufs->addr = sst_drv_ctx->mmap_mem;
- bufs->in_use = false;
- buf_entry++;
- /* locking here */
- mutex_lock(&stream->lock);
- list_add_tail(&bufs->node, &stream->bufs);
- mutex_unlock(&stream->lock);
- }
-
- mutex_lock(&stream->lock);
- stream->data_blk.condition = false;
- stream->data_blk.ret_code = 0;
- if (stream->status == STREAM_INIT &&
- stream->prev != STREAM_UN_INIT &&
- stream->need_draining != true) {
- stream->prev = stream->status;
- stream->status = STREAM_RUNNING;
- if (stream->ops == STREAM_OPS_PLAYBACK) {
- if (sst_play_frame(str_id) < 0) {
- pr_warn("play frames fail\n");
- mutex_unlock(&stream->lock);
- retval = -EIO;
- goto out_free;
- }
- } else if (stream->ops == STREAM_OPS_CAPTURE) {
- if (sst_capture_frame(str_id) < 0) {
- pr_warn("capture frame fail\n");
- mutex_unlock(&stream->lock);
- retval = -EIO;
- goto out_free;
- }
- }
- }
- mutex_unlock(&stream->lock);
- /* Block the call for reply */
- if (!list_empty(&stream->bufs)) {
- stream->data_blk.on = true;
- retval = sst_wait_interruptible(sst_drv_ctx,
- &stream->data_blk);
- }
-
- if (retval >= 0)
- retval = stream->cumm_bytes;
- pr_debug("end of play/rec ioctl bytes = %d!!\n", retval);
-
-out_free:
- kfree(tmp_buf);
- return retval;
-}
-
-/*sets user data buffers to play/capture*/
-static int intel_sst_play_capture(struct stream_info *stream, int str_id)
-{
- int retval;
-
- stream->data_blk.ret_code = 0;
- stream->data_blk.on = true;
- stream->data_blk.condition = false;
-
- mutex_lock(&stream->lock);
- if (stream->status == STREAM_INIT && stream->prev != STREAM_UN_INIT) {
- /* stream is started */
- stream->prev = stream->status;
- stream->status = STREAM_RUNNING;
- }
-
- if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) {
- /* stream is not started yet */
- pr_debug("Stream isn't in started state %d, prev %d\n",
- stream->status, stream->prev);
- } else if ((stream->status == STREAM_RUNNING ||
- stream->status == STREAM_PAUSED) &&
- stream->need_draining != true) {
- /* stream is started */
- if (stream->ops == STREAM_OPS_PLAYBACK ||
- stream->ops == STREAM_OPS_PLAYBACK_DRM) {
- if (sst_play_frame(str_id) < 0) {
- pr_warn("play frames failed\n");
- mutex_unlock(&stream->lock);
- return -EIO;
- }
- } else if (stream->ops == STREAM_OPS_CAPTURE) {
- if (sst_capture_frame(str_id) < 0) {
- pr_warn("capture frames failed\n");
- mutex_unlock(&stream->lock);
- return -EIO;
- }
- }
- } else {
- mutex_unlock(&stream->lock);
- return -EIO;
- }
- mutex_unlock(&stream->lock);
- /* Block the call for reply */
-
- retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk);
- if (retval) {
- stream->status = STREAM_INIT;
- pr_debug("wait returned error...\n");
- }
- return retval;
-}
-
-/* fills kernel list with buffer addresses for SST DSP driver to process*/
-static int snd_sst_fill_kernel_list(struct stream_info *stream,
- const struct iovec *iovec, unsigned long nr_segs,
- struct list_head *copy_to_list)
-{
- struct sst_stream_bufs *stream_bufs;
- unsigned long index, mmap_len;
- unsigned char __user *bufp;
- unsigned long size, copied_size;
- int retval = 0, add_to_list = 0;
- static int sent_offset;
- static unsigned long sent_index;
-
-#ifdef CONFIG_MRST_RAR_HANDLER
- if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
- for (index = stream->sg_index; index < nr_segs; index++) {
- __u32 rar_handle;
- struct sst_stream_bufs *stream_bufs =
- kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
-
- stream->sg_index = index;
- if (!stream_bufs)
- return -ENOMEM;
- if (copy_from_user((void *) &rar_handle,
- iovec[index].iov_base,
- sizeof(__u32))) {
- kfree(stream_bufs);
- return -EFAULT;
- }
- stream_bufs->addr = (char *)rar_handle;
- stream_bufs->in_use = false;
- stream_bufs->size = iovec[0].iov_len;
- /* locking here */
- mutex_lock(&stream->lock);
- list_add_tail(&stream_bufs->node, &stream->bufs);
- mutex_unlock(&stream->lock);
- }
- stream->sg_index = index;
- return retval;
- }
-#endif
- stream_bufs = kzalloc(sizeof(*stream_bufs), GFP_KERNEL);
- if (!stream_bufs)
- return -ENOMEM;
- stream_bufs->addr = sst_drv_ctx->mmap_mem;
- mmap_len = sst_drv_ctx->mmap_len;
- stream_bufs->addr = sst_drv_ctx->mmap_mem;
- bufp = stream->cur_ptr;
-
- copied_size = 0;
-
- if (!stream->sg_index)
- sent_index = sent_offset = 0;
-
- for (index = stream->sg_index; index < nr_segs; index++) {
- stream->sg_index = index;
- if (!stream->cur_ptr)
- bufp = iovec[index].iov_base;
-
- size = ((unsigned long)iovec[index].iov_base
- + iovec[index].iov_len) - (unsigned long) bufp;
-
- if ((copied_size + size) > mmap_len)
- size = mmap_len - copied_size;
-
-
- if (stream->ops == STREAM_OPS_PLAYBACK) {
- if (copy_from_user((void *)
- (stream_bufs->addr + copied_size),
- bufp, size)) {
- /* Clean up the list and return error code */
- retval = -EFAULT;
- break;
- }
- } else if (stream->ops == STREAM_OPS_CAPTURE) {
- struct snd_sst_user_cap_list *entry =
- kzalloc(sizeof(*entry), GFP_KERNEL);
-
- if (!entry) {
- kfree(stream_bufs);
- return -ENOMEM;
- }
- entry->iov_index = index;
- entry->iov_offset = (unsigned long) bufp -
- (unsigned long)iovec[index].iov_base;
- entry->offset = copied_size;
- entry->size = size;
- list_add_tail(&entry->node, copy_to_list);
- }
-
- stream->cur_ptr = bufp + size;
-
- if (((unsigned long)iovec[index].iov_base
- + iovec[index].iov_len) <
- ((unsigned long)iovec[index].iov_base)) {
- pr_debug("Buffer overflows\n");
- kfree(stream_bufs);
- return -EINVAL;
- }
-
- if (((unsigned long)iovec[index].iov_base
- + iovec[index].iov_len) ==
- (unsigned long)stream->cur_ptr) {
- stream->cur_ptr = NULL;
- stream->sg_index++;
- }
-
- copied_size += size;
- pr_debug("copied_size - %lx\n", copied_size);
- if ((copied_size >= mmap_len) ||
- (stream->sg_index == nr_segs)) {
- add_to_list = 1;
- }
-
- if (add_to_list) {
- stream_bufs->in_use = false;
- stream_bufs->size = copied_size;
- /* locking here */
- mutex_lock(&stream->lock);
- list_add_tail(&stream_bufs->node, &stream->bufs);
- mutex_unlock(&stream->lock);
- break;
- }
- }
- return retval;
-}
-
-/* This function copies the captured data returned from SST DSP engine
- * to the user buffers*/
-static int snd_sst_copy_userbuf_capture(struct stream_info *stream,
- const struct iovec *iovec,
- struct list_head *copy_to_list)
-{
- struct snd_sst_user_cap_list *entry, *_entry;
- struct sst_stream_bufs *kbufs = NULL, *_kbufs;
- int retval = 0;
-
- /* copy sent buffers */
- pr_debug("capture stream copying to user now...\n");
- list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
- if (kbufs->in_use == true) {
- /* copy to user */
- list_for_each_entry_safe(entry, _entry,
- copy_to_list, node) {
- if (copy_to_user(iovec[entry->iov_index].iov_base + entry->iov_offset,
- kbufs->addr + entry->offset,
- entry->size)) {
- /* Clean up the list and return error */
- retval = -EFAULT;
- break;
- }
- list_del(&entry->node);
- kfree(entry);
- }
- }
- }
- pr_debug("end of cap copy\n");
- return retval;
-}
-
-/*
- * snd_sst_userbufs_play_cap - constructs the list from user buffers
- *
- * @iovec:pointer to iovec structure
- * @nr_segs:number entries in the iovec structure
- * @str_id:stream id
- * @stream:pointer to stream_info structure
- *
- * This function will traverse the user list and copy the data to the kernel
- * space buffers.
- */
-static int snd_sst_userbufs_play_cap(const struct iovec *iovec,
- unsigned long nr_segs, unsigned int str_id,
- struct stream_info *stream)
-{
- int retval;
- LIST_HEAD(copy_to_list);
-
-
- retval = snd_sst_fill_kernel_list(stream, iovec, nr_segs,
- &copy_to_list);
-
- retval = intel_sst_play_capture(stream, str_id);
- if (retval < 0)
- return retval;
-
- if (stream->ops == STREAM_OPS_CAPTURE) {
- retval = snd_sst_copy_userbuf_capture(stream, iovec,
- &copy_to_list);
- }
- return retval;
-}
-
-/* This function is common function across read/write
- for user buffers called from system calls*/
-static int intel_sst_read_write(unsigned int str_id, char __user *buf,
- size_t count)
-{
- int retval;
- struct stream_info *stream;
- struct iovec iovec;
- unsigned long nr_segs;
-
- retval = sst_validate_strid(str_id);
- if (retval)
- return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
- if (stream->mmapped == true) {
- pr_warn("user write and stream is mapped\n");
- return -EIO;
- }
- if (!count)
- return -EINVAL;
- stream->curr_bytes = 0;
- stream->cumm_bytes = 0;
- /* copy user buf details */
- pr_debug("new buffers %p, copy size %d, status %d\n" ,
- buf, (int) count, (int) stream->status);
-
- stream->buf_type = SST_BUF_USER_STATIC;
- iovec.iov_base = buf;
- iovec.iov_len = count;
- nr_segs = 1;
-
- do {
- retval = snd_sst_userbufs_play_cap(
- &iovec, nr_segs, str_id, stream);
- if (retval < 0)
- break;
-
- } while (stream->sg_index < nr_segs);
-
- stream->sg_index = 0;
- stream->cur_ptr = NULL;
- if (retval >= 0)
- retval = stream->cumm_bytes;
- pr_debug("end of play/rec bytes = %d!!\n", retval);
- return retval;
-}
-
-/***
- * intel_sst_write - This function is called when user tries to play out data
- *
- * @file_ptr:pointer to file
- * @buf:user buffer to be played out
- * @count:size of tthe buffer
- * @offset:offset to start from
- *
- * writes the encoded data into DSP
- */
-int intel_sst_write(struct file *file_ptr, const char __user *buf,
- size_t count, loff_t *offset)
-{
- struct ioctl_pvt_data *data = file_ptr->private_data;
- int str_id = data->str_id;
- struct stream_info *stream = &sst_drv_ctx->streams[str_id];
-
- pr_debug("called for %d\n", str_id);
- if (stream->status == STREAM_UN_INIT ||
- stream->status == STREAM_DECODE) {
- return -EBADRQC;
- }
- return intel_sst_read_write(str_id, (char __user *)buf, count);
-}
-
-/*
- * intel_sst_aio_write - write buffers
- *
- * @kiocb:pointer to a structure containing file pointer
- * @iov:list of user buffer to be played out
- * @nr_segs:number of entries
- * @offset:offset to start from
- *
- * This function is called when user tries to play out multiple data buffers
- */
-ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t offset)
-{
- int retval;
- struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
- int str_id = data->str_id;
- struct stream_info *stream;
-
- pr_debug("entry - %ld\n", nr_segs);
-
- if (is_sync_kiocb(kiocb) == false)
- return -EINVAL;
-
- pr_debug("called for str_id %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
- if (stream->mmapped == true)
- return -EIO;
- if (stream->status == STREAM_UN_INIT ||
- stream->status == STREAM_DECODE) {
- return -EBADRQC;
- }
- stream->curr_bytes = 0;
- stream->cumm_bytes = 0;
- pr_debug("new segs %ld, offset %d, status %d\n" ,
- nr_segs, (int) offset, (int) stream->status);
- stream->buf_type = SST_BUF_USER_STATIC;
- do {
- retval = snd_sst_userbufs_play_cap(iov, nr_segs,
- str_id, stream);
- if (retval < 0)
- break;
-
- } while (stream->sg_index < nr_segs);
-
- stream->sg_index = 0;
- stream->cur_ptr = NULL;
- if (retval >= 0)
- retval = stream->cumm_bytes;
- pr_debug("end of play/rec bytes = %d!!\n", retval);
- return retval;
-}
-
-/*
- * intel_sst_read - read the encoded data
- *
- * @file_ptr: pointer to file
- * @buf: user buffer to be filled with captured data
- * @count: size of tthe buffer
- * @offset: offset to start from
- *
- * This function is called when user tries to capture data
- */
-int intel_sst_read(struct file *file_ptr, char __user *buf,
- size_t count, loff_t *offset)
-{
- struct ioctl_pvt_data *data = file_ptr->private_data;
- int str_id = data->str_id;
- struct stream_info *stream = &sst_drv_ctx->streams[str_id];
-
- pr_debug("called for %d\n", str_id);
- if (stream->status == STREAM_UN_INIT ||
- stream->status == STREAM_DECODE)
- return -EBADRQC;
- return intel_sst_read_write(str_id, buf, count);
-}
-
-/*
- * intel_sst_aio_read - aio read
- *
- * @kiocb: pointer to a structure containing file pointer
- * @iov: list of user buffer to be filled with captured
- * @nr_segs: number of entries
- * @offset: offset to start from
- *
- * This function is called when user tries to capture out multiple data buffers
- */
-ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t offset)
-{
- int retval;
- struct ioctl_pvt_data *data = kiocb->ki_filp->private_data;
- int str_id = data->str_id;
- struct stream_info *stream;
-
- pr_debug("entry - %ld\n", nr_segs);
-
- if (is_sync_kiocb(kiocb) == false) {
- pr_debug("aio_read from user space is not allowed\n");
- return -EINVAL;
- }
-
- pr_debug("called for str_id %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
- if (stream->mmapped == true)
- return -EIO;
- if (stream->status == STREAM_UN_INIT ||
- stream->status == STREAM_DECODE)
- return -EBADRQC;
- stream->curr_bytes = 0;
- stream->cumm_bytes = 0;
-
- pr_debug("new segs %ld, offset %d, status %d\n" ,
- nr_segs, (int) offset, (int) stream->status);
- stream->buf_type = SST_BUF_USER_STATIC;
- do {
- retval = snd_sst_userbufs_play_cap(iov, nr_segs,
- str_id, stream);
- if (retval < 0)
- break;
-
- } while (stream->sg_index < nr_segs);
-
- stream->sg_index = 0;
- stream->cur_ptr = NULL;
- if (retval >= 0)
- retval = stream->cumm_bytes;
- pr_debug("end of play/rec bytes = %d!!\n", retval);
- return retval;
-}
-
-/* sst_print_stream_params - prints the stream parameters (debug fn)*/
-static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm)
-{
- pr_debug("codec params:result = %d\n",
- get_prm->codec_params.result);
- pr_debug("codec params:stream = %d\n",
- get_prm->codec_params.stream_id);
- pr_debug("codec params:codec = %d\n",
- get_prm->codec_params.codec);
- pr_debug("codec params:ops = %d\n",
- get_prm->codec_params.ops);
- pr_debug("codec params:stream_type = %d\n",
- get_prm->codec_params.stream_type);
- pr_debug("pcmparams:sfreq = %d\n",
- get_prm->pcm_params.sfreq);
- pr_debug("pcmparams:num_chan = %d\n",
- get_prm->pcm_params.num_chan);
- pr_debug("pcmparams:pcm_wd_sz = %d\n",
- get_prm->pcm_params.pcm_wd_sz);
- return;
-}
-
-/**
- * sst_create_algo_ipc - create ipc msg for algorithm parameters
- *
- * @algo_params: Algorithm parameters
- * @msg: post msg pointer
- *
- * This function is called to create ipc msg
- */
-int sst_create_algo_ipc(struct snd_ppp_params *algo_params,
- struct ipc_post **msg)
-{
- if (sst_create_large_msg(msg))
- return -ENOMEM;
- sst_fill_header(&(*msg)->header,
- IPC_IA_ALG_PARAMS, 1, algo_params->str_id);
- (*msg)->header.part.data = sizeof(u32) +
- sizeof(*algo_params) + algo_params->size;
- memcpy((*msg)->mailbox_data, &(*msg)->header, sizeof(u32));
- memcpy((*msg)->mailbox_data + sizeof(u32),
- algo_params, sizeof(*algo_params));
- return 0;
-}
-
-/**
- * sst_send_algo_ipc - send ipc msg for algorithm parameters
- *
- * @msg: post msg pointer
- *
- * This function is called to send ipc msg
- */
-int sst_send_algo_ipc(struct ipc_post **msg)
-{
- sst_drv_ctx->ppp_params_blk.condition = false;
- sst_drv_ctx->ppp_params_blk.ret_code = 0;
- sst_drv_ctx->ppp_params_blk.on = true;
- sst_drv_ctx->ppp_params_blk.data = NULL;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&(*msg)->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- return sst_wait_interruptible_timeout(sst_drv_ctx,
- &sst_drv_ctx->ppp_params_blk, SST_BLOCK_TIMEOUT);
-}
-
-/**
- * intel_sst_ioctl_dsp - receives the device ioctl's
- *
- * @cmd:Ioctl cmd
- * @arg:data
- *
- * This function is called when a user space component
- * sends a DSP Ioctl to SST driver
- */
-long intel_sst_ioctl_dsp(unsigned int cmd, unsigned long arg)
-{
- int retval = 0;
- struct snd_ppp_params algo_params;
- struct snd_ppp_params *algo_params_copied;
- struct ipc_post *msg;
-
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(SNDRV_SST_SET_ALGO):
- if (copy_from_user(&algo_params, (void __user *)arg,
- sizeof(algo_params)))
- return -EFAULT;
- if (algo_params.size > SST_MAILBOX_SIZE)
- return -EMSGSIZE;
-
- pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
- algo_params.algo_id, algo_params.str_id,
- algo_params.enable, algo_params.size);
- retval = sst_create_algo_ipc(&algo_params, &msg);
- if (retval)
- break;
- algo_params.reserved = 0;
- if (copy_from_user(msg->mailbox_data + sizeof(algo_params),
- algo_params.params, algo_params.size))
- return -EFAULT;
-
- retval = sst_send_algo_ipc(&msg);
- if (retval) {
- pr_debug("Error in sst_set_algo = %d\n", retval);
- retval = -EIO;
- }
- break;
-
- case _IOC_NR(SNDRV_SST_GET_ALGO):
- if (copy_from_user(&algo_params, (void __user *)arg,
- sizeof(algo_params)))
- return -EFAULT;
- pr_debug("Algo ID %d Str id %d Enable %d Size %d\n",
- algo_params.algo_id, algo_params.str_id,
- algo_params.enable, algo_params.size);
- retval = sst_create_algo_ipc(&algo_params, &msg);
- if (retval)
- break;
- algo_params.reserved = 1;
- retval = sst_send_algo_ipc(&msg);
- if (retval) {
- pr_debug("Error in sst_get_algo = %d\n", retval);
- retval = -EIO;
- break;
- }
- algo_params_copied = (struct snd_ppp_params *)
- sst_drv_ctx->ppp_params_blk.data;
- if (algo_params_copied->size > algo_params.size) {
- pr_debug("mem insufficient to copy\n");
- retval = -EMSGSIZE;
- goto free_mem;
- } else {
- char __user *tmp;
-
- if (copy_to_user(algo_params.params,
- algo_params_copied->params,
- algo_params_copied->size)) {
- retval = -EFAULT;
- goto free_mem;
- }
- tmp = (char __user *)arg + offsetof(
- struct snd_ppp_params, size);
- if (copy_to_user(tmp, &algo_params_copied->size,
- sizeof(__u32))) {
- retval = -EFAULT;
- goto free_mem;
- }
-
- }
-free_mem:
- kfree(algo_params_copied->params);
- kfree(algo_params_copied);
- break;
- }
- return retval;
-}
-
-
-int sst_ioctl_tuning_params(unsigned long arg)
-{
- struct snd_sst_tuning_params params;
- struct ipc_post *msg;
-
- if (copy_from_user(&params, (void __user *)arg, sizeof(params)))
- return -EFAULT;
- if (params.size > SST_MAILBOX_SIZE)
- return -ENOMEM;
- pr_debug("Parameter %d, Stream %d, Size %d\n", params.type,
- params.str_id, params.size);
- if (sst_create_large_msg(&msg))
- return -ENOMEM;
-
- sst_fill_header(&msg->header, IPC_IA_TUNING_PARAMS, 1, params.str_id);
- msg->header.part.data = sizeof(u32) + sizeof(params) + params.size;
- memcpy(msg->mailbox_data, &msg->header.full, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), &params, sizeof(params));
- if (copy_from_user(msg->mailbox_data + sizeof(params),
- (void __user *)(unsigned long)params.addr,
- params.size)) {
- kfree(msg->mailbox_data);
- kfree(msg);
- return -EFAULT;
- }
- return sst_send_algo_ipc(&msg);
-}
-/**
- * intel_sst_ioctl - receives the device ioctl's
- * @file_ptr:pointer to file
- * @cmd:Ioctl cmd
- * @arg:data
- *
- * This function is called by OS when a user space component
- * sends an Ioctl to SST driver
- */
-long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
-{
- int retval = 0;
- struct ioctl_pvt_data *data = NULL;
- int str_id = 0, minor = 0;
-
- data = file_ptr->private_data;
- if (data) {
- minor = 0;
- str_id = data->str_id;
- } else
- minor = 1;
-
- if (sst_drv_ctx->sst_state != SST_FW_RUNNING)
- return -EBUSY;
-
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(SNDRV_SST_STREAM_PAUSE):
- pr_debug("IOCTL_PAUSE received for %d!\n", str_id);
- if (minor != STREAM_MODULE) {
- retval = -EBADRQC;
- break;
- }
- retval = sst_pause_stream(str_id);
- break;
-
- case _IOC_NR(SNDRV_SST_STREAM_RESUME):
- pr_debug("SNDRV_SST_IOCTL_RESUME received!\n");
- if (minor != STREAM_MODULE) {
- retval = -EBADRQC;
- break;
- }
- retval = sst_resume_stream(str_id);
- break;
-
- case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): {
- struct snd_sst_params str_param;
-
- pr_debug("IOCTL_SET_PARAMS received!\n");
- if (minor != STREAM_MODULE) {
- retval = -EBADRQC;
- break;
- }
-
- if (copy_from_user(&str_param, (void __user *)arg,
- sizeof(str_param))) {
- retval = -EFAULT;
- break;
- }
-
- if (!str_id) {
-
- retval = sst_get_stream(&str_param);
- if (retval > 0) {
- struct stream_info *str_info;
- char __user *dest;
-
- sst_drv_ctx->stream_cnt++;
- data->str_id = retval;
- str_info = &sst_drv_ctx->streams[retval];
- str_info->src = SST_DRV;
- dest = (char __user *)arg + offsetof(struct snd_sst_params, stream_id);
- retval = copy_to_user(dest, &retval, sizeof(__u32));
- if (retval)
- retval = -EFAULT;
- } else {
- if (retval == -SST_ERR_INVALID_PARAMS)
- retval = -EINVAL;
- }
- } else {
- pr_debug("SET_STREAM_PARAMS received!\n");
- /* allocated set params only */
- retval = sst_set_stream_param(str_id, &str_param);
- /* Block the call for reply */
- if (!retval) {
- int sfreq = 0, word_size = 0, num_channel = 0;
- sfreq = str_param.sparams.uc.pcm_params.sfreq;
- word_size = str_param.sparams.uc.pcm_params.pcm_wd_sz;
- num_channel = str_param.sparams.uc.pcm_params.num_chan;
- if (str_param.ops == STREAM_OPS_CAPTURE) {
- sst_drv_ctx->scard_ops->\
- set_pcm_audio_params(sfreq,
- word_size, num_channel);
- }
- }
- }
- break;
- }
- case _IOC_NR(SNDRV_SST_SET_VOL): {
- struct snd_sst_vol set_vol;
-
- if (copy_from_user(&set_vol, (void __user *)arg,
- sizeof(set_vol))) {
- pr_debug("copy failed\n");
- retval = -EFAULT;
- break;
- }
- pr_debug("SET_VOLUME received for %d!\n",
- set_vol.stream_id);
- if (minor == STREAM_MODULE && set_vol.stream_id == 0) {
- pr_debug("invalid operation!\n");
- retval = -EPERM;
- break;
- }
- retval = sst_set_vol(&set_vol);
- break;
- }
- case _IOC_NR(SNDRV_SST_GET_VOL): {
- struct snd_sst_vol get_vol;
-
- if (copy_from_user(&get_vol, (void __user *)arg,
- sizeof(get_vol))) {
- retval = -EFAULT;
- break;
- }
- pr_debug("IOCTL_GET_VOLUME received for stream = %d!\n",
- get_vol.stream_id);
- if (minor == STREAM_MODULE && get_vol.stream_id == 0) {
- pr_debug("invalid operation!\n");
- retval = -EPERM;
- break;
- }
- retval = sst_get_vol(&get_vol);
- if (retval) {
- retval = -EIO;
- break;
- }
- pr_debug("id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n",
- get_vol.stream_id, get_vol.volume,
- get_vol.ramp_duration, get_vol.ramp_type);
- if (copy_to_user((struct snd_sst_vol __user *)arg,
- &get_vol, sizeof(get_vol))) {
- retval = -EFAULT;
- break;
- }
- /*sst_print_get_vol_info(str_id, &get_vol);*/
- break;
- }
-
- case _IOC_NR(SNDRV_SST_MUTE): {
- struct snd_sst_mute set_mute;
-
- if (copy_from_user(&set_mute, (void __user *)arg,
- sizeof(set_mute))) {
- retval = -EFAULT;
- break;
- }
- pr_debug("SNDRV_SST_SET_VOLUME received for %d!\n",
- set_mute.stream_id);
- if (minor == STREAM_MODULE && set_mute.stream_id == 0) {
- retval = -EPERM;
- break;
- }
- retval = sst_set_mute(&set_mute);
- break;
- }
- case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): {
- struct snd_sst_get_stream_params get_params;
-
- pr_debug("IOCTL_GET_PARAMS received!\n");
- if (minor != 0) {
- retval = -EBADRQC;
- break;
- }
-
- retval = sst_get_stream_params(str_id, &get_params);
- if (retval) {
- retval = -EIO;
- break;
- }
- if (copy_to_user((struct snd_sst_get_stream_params __user *)arg,
- &get_params, sizeof(get_params))) {
- retval = -EFAULT;
- break;
- }
- sst_print_stream_params(&get_params);
- break;
- }
-
- case _IOC_NR(SNDRV_SST_MMAP_PLAY):
- case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): {
- struct snd_sst_mmap_buffs mmap_buf;
-
- pr_debug("SNDRV_SST_MMAP_PLAY/CAPTURE received!\n");
- if (minor != STREAM_MODULE) {
- retval = -EBADRQC;
- break;
- }
- if (copy_from_user(&mmap_buf, (void __user *)arg,
- sizeof(mmap_buf))) {
- retval = -EFAULT;
- break;
- }
- retval = intel_sst_mmap_play_capture(str_id, &mmap_buf);
- break;
- }
- case _IOC_NR(SNDRV_SST_STREAM_DROP):
- pr_debug("SNDRV_SST_IOCTL_DROP received!\n");
- if (minor != STREAM_MODULE) {
- retval = -EINVAL;
- break;
- }
- retval = sst_drop_stream(str_id);
- break;
-
- case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): {
- struct snd_sst_tstamp tstamp = {0};
- unsigned long long time, freq, mod;
-
- pr_debug("SNDRV_SST_STREAM_GET_TSTAMP received!\n");
- if (minor != STREAM_MODULE) {
- retval = -EBADRQC;
- break;
- }
- memcpy_fromio(&tstamp,
- sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
- sizeof(tstamp));
- time = tstamp.samples_rendered;
- freq = (unsigned long long) tstamp.sampling_frequency;
- time = time * 1000; /* converting it to ms */
- mod = do_div(time, freq);
- if (copy_to_user((void __user *)arg, &time,
- sizeof(unsigned long long)))
- retval = -EFAULT;
- break;
- }
-
- case _IOC_NR(SNDRV_SST_STREAM_START):{
- struct stream_info *stream;
-
- pr_debug("SNDRV_SST_STREAM_START received!\n");
- if (minor != STREAM_MODULE) {
- retval = -EINVAL;
- break;
- }
- retval = sst_validate_strid(str_id);
- if (retval)
- break;
- stream = &sst_drv_ctx->streams[str_id];
- mutex_lock(&stream->lock);
- if (stream->status == STREAM_INIT &&
- stream->need_draining != true) {
- stream->prev = stream->status;
- stream->status = STREAM_RUNNING;
- if (stream->ops == STREAM_OPS_PLAYBACK ||
- stream->ops == STREAM_OPS_PLAYBACK_DRM) {
- retval = sst_play_frame(str_id);
- } else if (stream->ops == STREAM_OPS_CAPTURE)
- retval = sst_capture_frame(str_id);
- else {
- retval = -EINVAL;
- mutex_unlock(&stream->lock);
- break;
- }
- if (retval < 0) {
- stream->status = STREAM_INIT;
- mutex_unlock(&stream->lock);
- break;
- }
- } else {
- retval = -EINVAL;
- }
- mutex_unlock(&stream->lock);
- break;
- }
-
- case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): {
- struct snd_sst_target_device target_device;
-
- pr_debug("SET_TARGET_DEVICE received!\n");
- if (copy_from_user(&target_device, (void __user *)arg,
- sizeof(target_device))) {
- retval = -EFAULT;
- break;
- }
- if (minor != AM_MODULE) {
- retval = -EBADRQC;
- break;
- }
- retval = sst_target_device_select(&target_device);
- break;
- }
-
- case _IOC_NR(SNDRV_SST_DRIVER_INFO): {
- struct snd_sst_driver_info info;
-
- pr_debug("SNDRV_SST_DRIVER_INFO received\n");
- info.version = SST_VERSION_NUM;
- /* hard coding, shud get sumhow later */
- info.active_pcm_streams = sst_drv_ctx->stream_cnt -
- sst_drv_ctx->encoded_cnt;
- info.active_enc_streams = sst_drv_ctx->encoded_cnt;
- info.max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM;
- info.max_enc_streams = MAX_ENC_STREAM;
- info.buf_per_stream = sst_drv_ctx->mmap_len;
- if (copy_to_user((void __user *)arg, &info,
- sizeof(info)))
- retval = -EFAULT;
- break;
- }
-
- case _IOC_NR(SNDRV_SST_STREAM_DECODE): {
- struct snd_sst_dbufs param;
- struct snd_sst_dbufs dbufs_local;
- struct snd_sst_buffs ibufs, obufs;
- struct snd_sst_buff_entry *ibuf_tmp, *obuf_tmp;
- char __user *dest;
-
- pr_debug("SNDRV_SST_STREAM_DECODE received\n");
- if (minor != STREAM_MODULE) {
- retval = -EBADRQC;
- break;
- }
- if (copy_from_user(&param, (void __user *)arg,
- sizeof(param))) {
- retval = -EFAULT;
- break;
- }
-
- dbufs_local.input_bytes_consumed = param.input_bytes_consumed;
- dbufs_local.output_bytes_produced =
- param.output_bytes_produced;
-
- if (copy_from_user(&ibufs, (void __user *)param.ibufs, sizeof(ibufs))) {
- retval = -EFAULT;
- break;
- }
- if (copy_from_user(&obufs, (void __user *)param.obufs, sizeof(obufs))) {
- retval = -EFAULT;
- break;
- }
-
- ibuf_tmp = kcalloc(ibufs.entries, sizeof(*ibuf_tmp), GFP_KERNEL);
- obuf_tmp = kcalloc(obufs.entries, sizeof(*obuf_tmp), GFP_KERNEL);
- if (!ibuf_tmp || !obuf_tmp) {
- retval = -ENOMEM;
- goto free_iobufs;
- }
-
- if (copy_from_user(ibuf_tmp, (void __user *)ibufs.buff_entry,
- ibufs.entries * sizeof(*ibuf_tmp))) {
- retval = -EFAULT;
- goto free_iobufs;
- }
- ibufs.buff_entry = ibuf_tmp;
- dbufs_local.ibufs = &ibufs;
-
- if (copy_from_user(obuf_tmp, (void __user *)obufs.buff_entry,
- obufs.entries * sizeof(*obuf_tmp))) {
- retval = -EFAULT;
- goto free_iobufs;
- }
- obufs.buff_entry = obuf_tmp;
- dbufs_local.obufs = &obufs;
-
- retval = sst_decode(str_id, &dbufs_local);
- if (retval) {
- retval = -EAGAIN;
- goto free_iobufs;
- }
-
- dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
- if (copy_to_user(dest,
- &dbufs_local.input_bytes_consumed,
- sizeof(unsigned long long))) {
- retval = -EFAULT;
- goto free_iobufs;
- }
-
- dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed);
- if (copy_to_user(dest,
- &dbufs_local.output_bytes_produced,
- sizeof(unsigned long long))) {
- retval = -EFAULT;
- goto free_iobufs;
- }
-free_iobufs:
- kfree(ibuf_tmp);
- kfree(obuf_tmp);
- break;
- }
-
- case _IOC_NR(SNDRV_SST_STREAM_DRAIN):
- pr_debug("SNDRV_SST_STREAM_DRAIN received\n");
- if (minor != STREAM_MODULE) {
- retval = -EINVAL;
- break;
- }
- retval = sst_drain_stream(str_id);
- break;
-
- case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): {
- unsigned long long __user *bytes = (unsigned long long __user *)arg;
- struct snd_sst_tstamp tstamp = {0};
-
- pr_debug("STREAM_BYTES_DECODED received!\n");
- if (minor != STREAM_MODULE) {
- retval = -EINVAL;
- break;
- }
- memcpy_fromio(&tstamp,
- sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp),
- sizeof(tstamp));
- if (copy_to_user(bytes, &tstamp.bytes_processed,
- sizeof(*bytes)))
- retval = -EFAULT;
- break;
- }
- case _IOC_NR(SNDRV_SST_FW_INFO): {
- struct snd_sst_fw_info *fw_info;
-
- pr_debug("SNDRV_SST_FW_INFO received\n");
-
- fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC);
- if (!fw_info) {
- retval = -ENOMEM;
- break;
- }
- retval = sst_get_fw_info(fw_info);
- if (retval) {
- retval = -EIO;
- kfree(fw_info);
- break;
- }
- if (copy_to_user((struct snd_sst_dbufs __user *)arg,
- fw_info, sizeof(*fw_info))) {
- kfree(fw_info);
- retval = -EFAULT;
- break;
- }
- /*sst_print_fw_info(fw_info);*/
- kfree(fw_info);
- break;
- }
- case _IOC_NR(SNDRV_SST_GET_ALGO):
- case _IOC_NR(SNDRV_SST_SET_ALGO):
- if (minor != AM_MODULE) {
- retval = -EBADRQC;
- break;
- }
- retval = intel_sst_ioctl_dsp(cmd, arg);
- break;
-
- case _IOC_NR(SNDRV_SST_TUNING_PARAMS):
- if (minor != AM_MODULE) {
- retval = -EBADRQC;
- break;
- }
- retval = sst_ioctl_tuning_params(arg);
- break;
-
- default:
- retval = -EINVAL;
- }
- pr_debug("intel_sst_ioctl:complete ret code = %d\n", retval);
- return retval;
-}
-
diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h
deleted file mode 100644
index 870981ba3c97..000000000000
--- a/drivers/staging/intel_sst/intel_sst_common.h
+++ /dev/null
@@ -1,623 +0,0 @@
-#ifndef __INTEL_SST_COMMON_H__
-#define __INTEL_SST_COMMON_H__
-/*
- * intel_sst_common.h - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corporation
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * Common private declarations for SST
- */
-
-#define SST_DRIVER_VERSION "1.2.17"
-#define SST_VERSION_NUM 0x1217
-
-/* driver names */
-#define SST_DRV_NAME "intel_sst_driver"
-#define SST_MRST_PCI_ID 0x080A
-#define SST_MFLD_PCI_ID 0x082F
-#define PCI_ID_LENGTH 4
-#define SST_SUSPEND_DELAY 2000
-#define FW_CONTEXT_MEM (64*1024)
-
-enum sst_states {
- SST_FW_LOADED = 1,
- SST_FW_RUNNING,
- SST_UN_INIT,
- SST_ERROR,
- SST_SUSPENDED
-};
-
-#define MAX_ACTIVE_STREAM 3
-#define MAX_ENC_STREAM 1
-#define MAX_AM_HANDLES 1
-#define ALLOC_TIMEOUT 5000
-/* SST numbers */
-#define SST_BLOCK_TIMEOUT 5000
-#define TARGET_DEV_BLOCK_TIMEOUT 5000
-
-#define BLOCK_UNINIT -1
-#define RX_TIMESLOT_UNINIT -1
-
-/* SST register map */
-#define SST_CSR 0x00
-#define SST_PISR 0x08
-#define SST_PIMR 0x10
-#define SST_ISRX 0x18
-#define SST_IMRX 0x28
-#define SST_IPCX 0x38 /* IPC IA-SST */
-#define SST_IPCD 0x40 /* IPC SST-IA */
-#define SST_ISRD 0x20 /* dummy register for shim workaround */
-#define SST_SHIM_SIZE 0X44
-
-#define SPI_MODE_ENABLE_BASE_ADDR 0xffae4000
-#define FW_SIGNATURE_SIZE 4
-
-/* PMIC and SST hardware states */
-enum sst_mad_states {
- SND_MAD_UN_INIT = 0,
- SND_MAD_INIT_DONE,
-};
-
-/* stream states */
-enum sst_stream_states {
- STREAM_UN_INIT = 0, /* Freed/Not used stream */
- STREAM_RUNNING = 1, /* Running */
- STREAM_PAUSED = 2, /* Paused stream */
- STREAM_DECODE = 3, /* stream is in decoding only state */
- STREAM_INIT = 4, /* stream init, waiting for data */
-};
-
-
-enum sst_ram_type {
- SST_IRAM = 1,
- SST_DRAM = 2,
-};
-/* SST shim registers to structure mapping */
-union config_status_reg {
- struct {
- u32 mfld_strb:1;
- u32 sst_reset:1;
- u32 hw_rsvd:3;
- u32 sst_clk:2;
- u32 bypass:3;
- u32 run_stall:1;
- u32 rsvd1:2;
- u32 strb_cntr_rst:1;
- u32 rsvd:18;
- } part;
- u32 full;
-};
-
-union interrupt_reg {
- struct {
- u32 done_interrupt:1;
- u32 busy_interrupt:1;
- u32 rsvd:30;
- } part;
- u32 full;
-};
-
-union sst_pisr_reg {
- struct {
- u32 pssp0:1;
- u32 pssp1:1;
- u32 rsvd0:3;
- u32 dmac:1;
- u32 rsvd1:26;
- } part;
- u32 full;
-};
-
-union sst_pimr_reg {
- struct {
- u32 ssp0:1;
- u32 ssp1:1;
- u32 rsvd0:3;
- u32 dmac:1;
- u32 rsvd1:10;
- u32 ssp0_sc:1;
- u32 ssp1_sc:1;
- u32 rsvd2:3;
- u32 dmac_sc:1;
- u32 rsvd3:10;
- } part;
- u32 full;
-};
-
-
-struct sst_stream_bufs {
- struct list_head node;
- u32 size;
- const char *addr;
- u32 data_copied;
- bool in_use;
- u32 offset;
-};
-
-struct snd_sst_user_cap_list {
- unsigned int iov_index; /* index of iov */
- unsigned long iov_offset; /* offset in iov */
- unsigned long offset; /* offset in kmem */
- unsigned long size; /* size copied */
- struct list_head node;
-};
-/*
-This structure is used to block a user/fw data call to another
-fw/user call
-*/
-struct sst_block {
- bool condition; /* condition for blocking check */
- int ret_code; /* ret code when block is released */
- void *data; /* data to be appsed for block if any */
- bool on;
-};
-
-enum snd_sst_buf_type {
- SST_BUF_USER_STATIC = 1,
- SST_BUF_USER_DYNAMIC,
- SST_BUF_MMAP_STATIC,
- SST_BUF_MMAP_DYNAMIC,
-};
-
-enum snd_src {
- SST_DRV = 1,
- MAD_DRV = 2
-};
-
-/**
- * struct stream_info - structure that holds the stream information
- *
- * @status : stream current state
- * @prev : stream prev state
- * @codec : stream codec
- * @sst_id : stream id
- * @ops : stream operation pb/cp/drm...
- * @bufs: stream buffer list
- * @lock : stream mutex for protecting state
- * @pcm_lock : spinlock for pcm path only
- * @mmapped : is stream mmapped
- * @sg_index : current stream user buffer index
- * @cur_ptr : stream user buffer pointer
- * @buf_entry : current user buffer
- * @data_blk : stream block for data operations
- * @ctrl_blk : stream block for ctrl operations
- * @buf_type : stream user buffer type
- * @pcm_substream : PCM substream
- * @period_elapsed : PCM period elapsed callback
- * @sfreq : stream sampling freq
- * @decode_ibuf : Decoded i/p buffers pointer
- * @decode_obuf : Decoded o/p buffers pointer
- * @decode_isize : Decoded i/p buffers size
- * @decode_osize : Decoded o/p buffers size
- * @decode_ibuf_type : Decoded i/p buffer type
- * @decode_obuf_type : Decoded o/p buffer type
- * @idecode_alloc : Decode alloc index
- * @need_draining : stream set for drain
- * @str_type : stream type
- * @curr_bytes : current bytes decoded
- * @cumm_bytes : cummulative bytes decoded
- * @str_type : stream type
- * @src : stream source
- * @device : output device type (medfield only)
- * @pcm_slot : pcm slot value
- */
-struct stream_info {
- unsigned int status;
- unsigned int prev;
- u8 codec;
- unsigned int sst_id;
- unsigned int ops;
- struct list_head bufs;
- struct mutex lock; /* mutex */
- spinlock_t pcm_lock;
- bool mmapped;
- unsigned int sg_index; /* current buf Index */
- unsigned char __user *cur_ptr; /* Current static bufs */
- struct snd_sst_buf_entry __user *buf_entry;
- struct sst_block data_blk; /* stream ops block */
- struct sst_block ctrl_blk; /* stream control cmd block */
- enum snd_sst_buf_type buf_type;
- void *pcm_substream;
- void (*period_elapsed) (void *pcm_substream);
- unsigned int sfreq;
- void *decode_ibuf, *decode_obuf;
- unsigned int decode_isize, decode_osize;
- u8 decode_ibuf_type, decode_obuf_type;
- unsigned int idecode_alloc;
- unsigned int need_draining;
- unsigned int str_type;
- u32 curr_bytes;
- u32 cumm_bytes;
- u32 src;
- enum snd_sst_audio_device_type device;
- u8 pcm_slot;
-};
-
-/*
- * struct stream_alloc_bloc - this structure is used for blocking the user's
- * alloc calls to fw's response to alloc calls
- *
- * @sst_id : session id of blocked stream
- * @ops_block : ops block struture
- */
-struct stream_alloc_block {
- int sst_id; /* session id of blocked stream */
- struct sst_block ops_block; /* ops block struture */
-};
-
-#define SST_FW_SIGN "$SST"
-#define SST_FW_LIB_SIGN "$LIB"
-
-/*
- * struct fw_header - FW file headers
- *
- * @signature : FW signature
- * @modules : # of modules
- * @file_format : version of header format
- * @reserved : reserved fields
- */
-struct fw_header {
- unsigned char signature[FW_SIGNATURE_SIZE]; /* FW signature */
- u32 file_size; /* size of fw minus this header */
- u32 modules; /* # of modules */
- u32 file_format; /* version of header format */
- u32 reserved[4];
-};
-
-struct fw_module_header {
- unsigned char signature[FW_SIGNATURE_SIZE]; /* module signature */
- u32 mod_size; /* size of module */
- u32 blocks; /* # of blocks */
- u32 type; /* codec type, pp lib */
- u32 entry_point;
-};
-
-struct dma_block_info {
- enum sst_ram_type type; /* IRAM/DRAM */
- u32 size; /* Bytes */
- u32 ram_offset; /* Offset in I/DRAM */
- u32 rsvd; /* Reserved field */
-};
-
-struct ioctl_pvt_data {
- int str_id;
- int pvt_id;
-};
-
-struct sst_ipc_msg_wq {
- union ipc_header header;
- char mailbox[SST_MAILBOX_SIZE];
- struct work_struct wq;
-};
-
-struct mad_ops_wq {
- int stream_id;
- enum sst_controls control_op;
- struct work_struct wq;
-
-};
-
-#define SST_MMAP_PAGES (640*1024 / PAGE_SIZE)
-#define SST_MMAP_STEP (40*1024 / PAGE_SIZE)
-
-/***
- * struct intel_sst_drv - driver ops
- *
- * @pmic_state : pmic state
- * @pmic_vendor : pmic vendor detected
- * @sst_state : current sst device state
- * @pci_id : PCI device id loaded
- * @shim : SST shim pointer
- * @mailbox : SST mailbox pointer
- * @iram : SST IRAM pointer
- * @dram : SST DRAM pointer
- * @shim_phy_add : SST shim phy addr
- * @ipc_dispatch_list : ipc messages dispatched
- * @ipc_post_msg_wq : wq to post IPC messages context
- * @ipc_process_msg : wq to process msgs from FW context
- * @ipc_process_reply : wq to process reply from FW context
- * @ipc_post_msg : wq to post reply from FW context
- * @mad_ops : MAD driver operations registered
- * @mad_wq : MAD driver wq
- * @post_msg_wq : wq to post IPC messages
- * @process_msg_wq : wq to process msgs from FW
- * @process_reply_wq : wq to process reply from FW
- * @streams : sst stream contexts
- * @alloc_block : block structure for alloc
- * @tgt_dev_blk : block structure for target device
- * @fw_info_blk : block structure for fw info block
- * @vol_info_blk : block structure for vol info block
- * @mute_info_blk : block structure for mute info block
- * @hs_info_blk : block structure for hs info block
- * @list_lock : sst driver list lock (deprecated)
- * @list_spin_lock : sst driver spin lock block
- * @scard_ops : sst card ops
- * @pci : sst pci device struture
- * @active_streams : sst active streams
- * @sst_lock : sst device lock
- * @stream_lock : sst stream lock
- * @unique_id : sst unique id
- * @stream_cnt : total sst active stream count
- * @pb_streams : total active pb streams
- * @cp_streams : total active cp streams
- * @lpe_stalled : lpe stall status
- * @pmic_port_instance : active pmic port instance
- * @rx_time_slot_status : active rx slot
- * @lpaudio_start : lpaudio status
- * @audio_start : audio status
- * @devt_d : pointer to /dev/lpe node
- * @devt_c : pointer to /dev/lpe_ctrl node
- * @max_streams : max streams allowed
- */
-struct intel_sst_drv {
- bool pmic_state;
- int pmic_vendor;
- int sst_state;
- unsigned int pci_id;
- void __iomem *shim;
- void __iomem *mailbox;
- void __iomem *iram;
- void __iomem *dram;
- unsigned int shim_phy_add;
- struct list_head ipc_dispatch_list;
- struct work_struct ipc_post_msg_wq;
- struct sst_ipc_msg_wq ipc_process_msg;
- struct sst_ipc_msg_wq ipc_process_reply;
- struct sst_ipc_msg_wq ipc_post_msg;
- struct mad_ops_wq mad_ops;
- wait_queue_head_t wait_queue;
- struct workqueue_struct *mad_wq;
- struct workqueue_struct *post_msg_wq;
- struct workqueue_struct *process_msg_wq;
- struct workqueue_struct *process_reply_wq;
-
- struct stream_info streams[MAX_NUM_STREAMS];
- struct stream_alloc_block alloc_block[MAX_ACTIVE_STREAM];
- struct sst_block tgt_dev_blk, fw_info_blk, ppp_params_blk,
- vol_info_blk, mute_info_blk, hs_info_blk;
- struct mutex list_lock;/* mutex for IPC list locking */
- spinlock_t list_spin_lock; /* mutex for IPC list locking */
- struct snd_pmic_ops *scard_ops;
- struct pci_dev *pci;
- int active_streams[MAX_NUM_STREAMS];
- void *mmap_mem;
- struct mutex sst_lock;
- struct mutex stream_lock;
- unsigned int mmap_len;
- unsigned int unique_id;
- unsigned int stream_cnt; /* total streams */
- unsigned int encoded_cnt; /* enocded streams only */
- unsigned int am_cnt;
- unsigned int pb_streams; /* pb streams active */
- unsigned int cp_streams; /* cp streams active */
- unsigned int lpe_stalled; /* LPE is stalled or not */
- unsigned int pmic_port_instance; /*pmic port instance*/
- int rx_time_slot_status;
- unsigned int lpaudio_start;
- /* 1 - LPA stream(MP3 pb) in progress*/
- unsigned int audio_start;
- dev_t devt_d, devt_c;
- unsigned int max_streams;
- unsigned int *fw_cntx;
- unsigned int fw_cntx_size;
-
- unsigned int fw_downloaded;
-};
-
-extern struct intel_sst_drv *sst_drv_ctx;
-
-#define CHIP_REV_REG 0xff108000
-#define CHIP_REV_ADDR 0x78
-
-/* misc definitions */
-#define FW_DWNL_ID 0xFF
-#define LOOP1 0x11111111
-#define LOOP2 0x22222222
-#define LOOP3 0x33333333
-#define LOOP4 0x44444444
-
-#define SST_DEFAULT_PMIC_PORT 1 /*audio port*/
-/* NOTE: status will have +ve for good cases and -ve for error ones */
-#define MAX_STREAM_FIELD 255
-
-int sst_alloc_stream(char *params, unsigned int stream_ops, u8 codec,
- unsigned int session_id);
-int sst_alloc_stream_response(unsigned int str_id,
- struct snd_sst_alloc_response *response);
-int sst_stalled(void);
-int sst_pause_stream(int id);
-int sst_resume_stream(int id);
-int sst_enable_rx_timeslot(int status);
-int sst_drop_stream(int id);
-int sst_free_stream(int id);
-int sst_start_stream(int streamID);
-int sst_play_frame(int streamID);
-int sst_pcm_play_frame(int str_id, struct sst_stream_bufs *sst_buf);
-int sst_capture_frame(int streamID);
-int sst_set_stream_param(int streamID, struct snd_sst_params *str_param);
-int sst_target_device_select(struct snd_sst_target_device *target_device);
-int sst_decode(int str_id, struct snd_sst_dbufs *dbufs);
-int sst_get_decoded_bytes(int str_id, unsigned long long *bytes);
-int sst_get_fw_info(struct snd_sst_fw_info *info);
-int sst_get_stream_params(int str_id,
- struct snd_sst_get_stream_params *get_params);
-int sst_get_stream(struct snd_sst_params *str_param);
-int sst_get_stream_allocated(struct snd_sst_params *str_param,
- struct snd_sst_lib_download **lib_dnld);
-int sst_drain_stream(int str_id);
-int sst_get_vol(struct snd_sst_vol *set_vol);
-int sst_set_vol(struct snd_sst_vol *set_vol);
-int sst_set_mute(struct snd_sst_mute *set_mute);
-
-
-void sst_post_message(struct work_struct *work);
-void sst_process_message(struct work_struct *work);
-void sst_process_reply(struct work_struct *work);
-void sst_process_mad_ops(struct work_struct *work);
-void sst_process_mad_jack_detection(struct work_struct *work);
-
-long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd,
- unsigned long arg);
-int intel_sst_open(struct inode *i_node, struct file *file_ptr);
-int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr);
-int intel_sst_release(struct inode *i_node, struct file *file_ptr);
-int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr);
-int intel_sst_read(struct file *file_ptr, char __user *buf,
- size_t count, loff_t *ppos);
-int intel_sst_write(struct file *file_ptr, const char __user *buf,
- size_t count, loff_t *ppos);
-int intel_sst_mmap(struct file *fp, struct vm_area_struct *vma);
-ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t offset);
-ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t offset);
-
-int sst_load_fw(const struct firmware *fw, void *context);
-int sst_load_library(struct snd_sst_lib_download *lib, u8 ops);
-int sst_spi_mode_enable(void);
-int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx);
-
-int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
- struct sst_block *block);
-int sst_wait_interruptible_timeout(struct intel_sst_drv *sst_drv_ctx,
- struct sst_block *block, int timeout);
-int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx,
- struct stream_alloc_block *block);
-int sst_create_large_msg(struct ipc_post **arg);
-int sst_create_short_msg(struct ipc_post **arg);
-void sst_wake_up_alloc_block(struct intel_sst_drv *sst_drv_ctx,
- u8 sst_id, int status, void *data);
-void sst_clear_interrupt(void);
-int intel_sst_resume(struct pci_dev *pci);
-int sst_download_fw(void);
-void free_stream_context(unsigned int str_id);
-void sst_clean_stream(struct stream_info *stream);
-
-/*
- * sst_fill_header - inline to fill sst header
- *
- * @header : ipc header
- * @msg : IPC message to be sent
- * @large : is ipc large msg
- * @str_id : stream id
- *
- * this function is an inline function that sets the headers before
- * sending a message
- */
-static inline void sst_fill_header(union ipc_header *header,
- int msg, int large, int str_id)
-{
- header->part.msg_id = msg;
- header->part.str_id = str_id;
- header->part.large = large;
- header->part.done = 0;
- header->part.busy = 1;
- header->part.data = 0;
-}
-
-/*
- * sst_assign_pvt_id - assign a pvt id for stream
- *
- * @sst_drv_ctx : driver context
- *
- * this inline function assigns a private id for calls that dont have stream
- * context yet, should be called with lock held
- */
-static inline unsigned int sst_assign_pvt_id(struct intel_sst_drv *sst_drv_ctx)
-{
- sst_drv_ctx->unique_id++;
- if (sst_drv_ctx->unique_id >= MAX_NUM_STREAMS)
- sst_drv_ctx->unique_id = 1;
- return sst_drv_ctx->unique_id;
-}
-
-/*
- * sst_init_stream - this function initialzes stream context
- *
- * @stream : stream struture
- * @codec : codec for stream
- * @sst_id : stream id
- * @ops : stream operation
- * @slot : stream pcm slot
- * @device : device type
- *
- * this inline function initialzes stream context for allocated stream
- */
-static inline void sst_init_stream(struct stream_info *stream,
- int codec, int sst_id, int ops, u8 slot,
- enum snd_sst_audio_device_type device)
-{
- stream->status = STREAM_INIT;
- stream->prev = STREAM_UN_INIT;
- stream->codec = codec;
- stream->sst_id = sst_id;
- stream->str_type = 0;
- stream->ops = ops;
- stream->data_blk.on = false;
- stream->data_blk.condition = false;
- stream->data_blk.ret_code = 0;
- stream->data_blk.data = NULL;
- stream->ctrl_blk.on = false;
- stream->ctrl_blk.condition = false;
- stream->ctrl_blk.ret_code = 0;
- stream->ctrl_blk.data = NULL;
- stream->need_draining = false;
- stream->decode_ibuf = NULL;
- stream->decode_isize = 0;
- stream->mmapped = false;
- stream->pcm_slot = slot;
- stream->device = device;
-}
-
-
-/*
- * sst_validate_strid - this function validates the stream id
- *
- * @str_id : stream id to be validated
- *
- * returns 0 if valid stream
- */
-static inline int sst_validate_strid(int str_id)
-{
- if (str_id <= 0 || str_id > sst_drv_ctx->max_streams) {
- pr_err("SST ERR: invalid stream id : %d MAX_STREAMS:%d\n",
- str_id, sst_drv_ctx->max_streams);
- return -EINVAL;
- } else
- return 0;
-}
-
-static inline int sst_shim_write(void __iomem *addr, int offset, int value)
-{
-
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
- writel(value, addr + SST_ISRD); /*dummy*/
- writel(value, addr + offset);
- return 0;
-}
-
-static inline int sst_shim_read(void __iomem *addr, int offset)
-{
- return readl(addr + offset);
-}
-#endif /* __INTEL_SST_COMMON_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c
deleted file mode 100644
index 22bd29c0c439..000000000000
--- a/drivers/staging/intel_sst/intel_sst_drv_interface.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * intel_sst_interface.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com)
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This driver exposes the audio engine functionalities to the ALSA
- * and middleware.
- * Upper layer interfaces (MAD driver, MMF) to SST driver
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/firmware.h>
-#include <linux/pm_runtime.h>
-#include <linux/export.h>
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intel_sst_fw_ipc.h"
-#include "intel_sst_common.h"
-
-
-/*
- * sst_download_fw - download the audio firmware to DSP
- *
- * This function is called when the FW needs to be downloaded to SST DSP engine
- */
-int sst_download_fw(void)
-{
- int retval;
- const struct firmware *fw_sst;
- char name[20];
-
- if (sst_drv_ctx->sst_state != SST_UN_INIT)
- return -EPERM;
-
- /* Reload firmware is not needed for MRST */
- if ( (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) && sst_drv_ctx->fw_downloaded) {
- pr_debug("FW already downloaded, skip for MRST platform\n");
- sst_drv_ctx->sst_state = SST_FW_RUNNING;
- return 0;
- }
-
- snprintf(name, sizeof(name), "%s%04x%s", "fw_sst_",
- sst_drv_ctx->pci_id, ".bin");
-
- pr_debug("Downloading %s FW now...\n", name);
- retval = request_firmware(&fw_sst, name, &sst_drv_ctx->pci->dev);
- if (retval) {
- pr_err("request fw failed %d\n", retval);
- return retval;
- }
- sst_drv_ctx->alloc_block[0].sst_id = FW_DWNL_ID;
- sst_drv_ctx->alloc_block[0].ops_block.condition = false;
- retval = sst_load_fw(fw_sst, NULL);
- if (retval)
- goto end_restore;
-
- retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[0]);
- if (retval)
- pr_err("fw download failed %d\n" , retval);
- else
- sst_drv_ctx->fw_downloaded = 1;
-
-end_restore:
- release_firmware(fw_sst);
- sst_drv_ctx->alloc_block[0].sst_id = BLOCK_UNINIT;
- return retval;
-}
-
-
-/*
- * sst_stalled - this function checks if the lpe is in stalled state
- */
-int sst_stalled(void)
-{
- int retry = 1000;
- int retval = -1;
-
- while (retry) {
- if (!sst_drv_ctx->lpe_stalled)
- return 0;
- /*wait for time and re-check*/
- msleep(1);
-
- retry--;
- }
- pr_debug("in Stalled State\n");
- return retval;
-}
-
-void free_stream_context(unsigned int str_id)
-{
- struct stream_info *stream;
-
- if (!sst_validate_strid(str_id)) {
- /* str_id is valid, so stream is alloacted */
- stream = &sst_drv_ctx->streams[str_id];
- if (sst_free_stream(str_id))
- sst_clean_stream(&sst_drv_ctx->streams[str_id]);
- if (stream->ops == STREAM_OPS_PLAYBACK ||
- stream->ops == STREAM_OPS_PLAYBACK_DRM) {
- sst_drv_ctx->pb_streams--;
- if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID)
- sst_drv_ctx->scard_ops->power_down_pmic_pb(
- stream->device);
- else {
- if (sst_drv_ctx->pb_streams == 0)
- sst_drv_ctx->scard_ops->
- power_down_pmic_pb(stream->device);
- }
- } else if (stream->ops == STREAM_OPS_CAPTURE) {
- sst_drv_ctx->cp_streams--;
- if (sst_drv_ctx->cp_streams == 0)
- sst_drv_ctx->scard_ops->power_down_pmic_cp(
- stream->device);
- }
- if (sst_drv_ctx->pb_streams == 0
- && sst_drv_ctx->cp_streams == 0)
- sst_drv_ctx->scard_ops->power_down_pmic();
- }
-}
-
-/*
- * sst_get_stream_allocated - this function gets a stream allocated with
- * the given params
- *
- * @str_param : stream params
- * @lib_dnld : pointer to pointer of lib downlaod struct
- *
- * This creates new stream id for a stream, in case lib is to be downloaded to
- * DSP, it downloads that
- */
-int sst_get_stream_allocated(struct snd_sst_params *str_param,
- struct snd_sst_lib_download **lib_dnld)
-{
- int retval, str_id;
- struct stream_info *str_info;
-
- retval = sst_alloc_stream((char *) &str_param->sparams, str_param->ops,
- str_param->codec, str_param->device_type);
- if (retval < 0) {
- pr_err("sst_alloc_stream failed %d\n", retval);
- return retval;
- }
- pr_debug("Stream allocated %d\n", retval);
- str_id = retval;
- str_info = &sst_drv_ctx->streams[str_id];
- /* Block the call for reply */
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
- if ((retval != 0) || (str_info->ctrl_blk.ret_code != 0)) {
- pr_debug("FW alloc failed retval %d, ret_code %d\n",
- retval, str_info->ctrl_blk.ret_code);
- str_id = -str_info->ctrl_blk.ret_code; /*return error*/
- *lib_dnld = str_info->ctrl_blk.data;
- sst_clean_stream(str_info);
- } else
- pr_debug("FW Stream allocated success\n");
- return str_id; /*will ret either error (in above if) or correct str id*/
-}
-
-/*
- * sst_get_sfreq - this function returns the frequency of the stream
- *
- * @str_param : stream params
- */
-static int sst_get_sfreq(struct snd_sst_params *str_param)
-{
- switch (str_param->codec) {
- case SST_CODEC_TYPE_PCM:
- return 48000; /*str_param->sparams.uc.pcm_params.sfreq;*/
- case SST_CODEC_TYPE_MP3:
- return str_param->sparams.uc.mp3_params.sfreq;
- case SST_CODEC_TYPE_AAC:
- return str_param->sparams.uc.aac_params.sfreq;
- case SST_CODEC_TYPE_WMA9:
- return str_param->sparams.uc.wma_params.sfreq;
- default:
- return 0;
- }
-}
-
-/*
- * sst_get_stream - this function prepares for stream allocation
- *
- * @str_param : stream param
- */
-int sst_get_stream(struct snd_sst_params *str_param)
-{
- int i, retval;
- struct stream_info *str_info;
- struct snd_sst_lib_download *lib_dnld;
-
- /* stream is not allocated, we are allocating */
- retval = sst_get_stream_allocated(str_param, &lib_dnld);
- if (retval == -(SST_LIB_ERR_LIB_DNLD_REQUIRED)) {
- /* codec download is required */
- struct snd_sst_alloc_response *response;
-
- pr_debug("Codec is required.... trying that\n");
- if (lib_dnld == NULL) {
- pr_err("lib download null!!! abort\n");
- return -EIO;
- }
- i = sst_get_block_stream(sst_drv_ctx);
- response = sst_drv_ctx->alloc_block[i].ops_block.data;
- pr_debug("alloc block allocated = %d\n", i);
- if (i < 0) {
- kfree(lib_dnld);
- return -ENOMEM;
- }
- retval = sst_load_library(lib_dnld, str_param->ops);
- kfree(lib_dnld);
-
- sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
- if (!retval) {
- pr_debug("codec was downloaded successfully\n");
-
- retval = sst_get_stream_allocated(str_param, &lib_dnld);
- if (retval <= 0)
- goto err;
-
- pr_debug("Alloc done stream id %d\n", retval);
- } else {
- pr_debug("codec download failed\n");
- retval = -EIO;
- goto err;
- }
- } else if (retval <= 0)
- goto err;
- /*else
- set_port_params(str_param, str_param->ops);*/
-
- /* store sampling freq */
- str_info = &sst_drv_ctx->streams[retval];
- str_info->sfreq = sst_get_sfreq(str_param);
-
- /* power on the analog, if reqd */
- if (str_param->ops == STREAM_OPS_PLAYBACK ||
- str_param->ops == STREAM_OPS_PLAYBACK_DRM) {
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
- sst_drv_ctx->scard_ops->power_up_pmic_pb(
- sst_drv_ctx->pmic_port_instance);
- else
- sst_drv_ctx->scard_ops->power_up_pmic_pb(
- str_info->device);
- /*Only if the playback is MP3 - Send a message*/
- sst_drv_ctx->pb_streams++;
- } else if (str_param->ops == STREAM_OPS_CAPTURE) {
-
- sst_drv_ctx->scard_ops->power_up_pmic_cp(
- sst_drv_ctx->pmic_port_instance);
- /*Send a messageif not sent already*/
- sst_drv_ctx->cp_streams++;
- }
-
-err:
- return retval;
-}
-
-void sst_process_mad_ops(struct work_struct *work)
-{
-
- struct mad_ops_wq *mad_ops =
- container_of(work, struct mad_ops_wq, wq);
- int retval = 0;
-
- switch (mad_ops->control_op) {
- case SST_SND_PAUSE:
- retval = sst_pause_stream(mad_ops->stream_id);
- break;
- case SST_SND_RESUME:
- retval = sst_resume_stream(mad_ops->stream_id);
- break;
- case SST_SND_DROP:
- retval = sst_drop_stream(mad_ops->stream_id);
- break;
- case SST_SND_START:
- pr_debug("SST Debug: start stream\n");
- retval = sst_start_stream(mad_ops->stream_id);
- break;
- case SST_SND_STREAM_PROCESS:
- pr_debug("play/capt frames...\n");
- break;
- default:
- pr_err(" wrong control_ops reported\n");
- }
- return;
-}
-
-void send_intial_rx_timeslot(void)
-{
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID &&
- sst_drv_ctx->rx_time_slot_status != RX_TIMESLOT_UNINIT
- && sst_drv_ctx->pmic_vendor != SND_NC)
- sst_enable_rx_timeslot(sst_drv_ctx->rx_time_slot_status);
-}
-
-/*
- * sst_open_pcm_stream - Open PCM interface
- *
- * @str_param: parameters of pcm stream
- *
- * This function is called by MID sound card driver to open
- * a new pcm interface
- */
-int sst_open_pcm_stream(struct snd_sst_params *str_param)
-{
- struct stream_info *str_info;
- int retval;
-
- pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
-
- if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
- /* LPE is suspended, resume it before proceeding*/
- pr_debug("Resuming from Suspended state\n");
- retval = intel_sst_resume(sst_drv_ctx->pci);
- if (retval) {
- pr_err("Resume Failed = %#x, abort\n", retval);
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- return retval;
- }
- }
- if (sst_drv_ctx->sst_state == SST_UN_INIT) {
- /* FW is not downloaded */
- pr_debug("DSP Downloading FW now...\n");
- retval = sst_download_fw();
- if (retval) {
- pr_err("FW download fail %x, abort\n", retval);
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- return retval;
- }
- send_intial_rx_timeslot();
- }
-
- if (!str_param) {
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- return -EINVAL;
- }
-
- retval = sst_get_stream(str_param);
- if (retval > 0) {
- sst_drv_ctx->stream_cnt++;
- str_info = &sst_drv_ctx->streams[retval];
- str_info->src = MAD_DRV;
- } else
- pm_runtime_put(&sst_drv_ctx->pci->dev);
-
- return retval;
-}
-
-/*
- * sst_close_pcm_stream - Close PCM interface
- *
- * @str_id: stream id to be closed
- *
- * This function is called by MID sound card driver to close
- * an existing pcm interface
- */
-int sst_close_pcm_stream(unsigned int str_id)
-{
- struct stream_info *stream;
-
- pr_debug("sst: stream free called\n");
- if (sst_validate_strid(str_id))
- return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
- free_stream_context(str_id);
- stream->pcm_substream = NULL;
- stream->status = STREAM_UN_INIT;
- stream->period_elapsed = NULL;
- sst_drv_ctx->stream_cnt--;
- pr_debug("sst: will call runtime put now\n");
- pm_runtime_put(&sst_drv_ctx->pci->dev);
- return 0;
-}
-
-/*
- * sst_device_control - Set Control params
- *
- * @cmd: control cmd to be set
- * @arg: command argument
- *
- * This function is called by MID sound card driver to set
- * SST/Sound card controls for an opened stream.
- * This is registered with MID driver
- */
-int sst_device_control(int cmd, void *arg)
-{
- int retval = 0, str_id = 0;
-
- switch (cmd) {
- case SST_SND_PAUSE:
- case SST_SND_RESUME:
- case SST_SND_DROP:
- case SST_SND_START:
- sst_drv_ctx->mad_ops.control_op = cmd;
- sst_drv_ctx->mad_ops.stream_id = *(int *)arg;
- queue_work(sst_drv_ctx->mad_wq, &sst_drv_ctx->mad_ops.wq);
- break;
-
- case SST_SND_STREAM_INIT: {
- struct pcm_stream_info *str_info;
- struct stream_info *stream;
-
- pr_debug("stream init called\n");
- str_info = (struct pcm_stream_info *)arg;
- str_id = str_info->str_id;
- retval = sst_validate_strid(str_id);
- if (retval)
- break;
-
- stream = &sst_drv_ctx->streams[str_id];
- pr_debug("setting the period ptrs\n");
- stream->pcm_substream = str_info->mad_substream;
- stream->period_elapsed = str_info->period_elapsed;
- stream->sfreq = str_info->sfreq;
- stream->prev = stream->status;
- stream->status = STREAM_INIT;
- break;
- }
-
- case SST_SND_BUFFER_POINTER: {
- struct pcm_stream_info *stream_info;
- struct snd_sst_tstamp fw_tstamp = {0,};
- struct stream_info *stream;
-
-
- stream_info = (struct pcm_stream_info *)arg;
- str_id = stream_info->str_id;
- retval = sst_validate_strid(str_id);
- if (retval)
- break;
- stream = &sst_drv_ctx->streams[str_id];
-
- if (!stream->pcm_substream)
- break;
- memcpy_fromio(&fw_tstamp,
- ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP)
- +(str_id * sizeof(fw_tstamp))),
- sizeof(fw_tstamp));
-
- pr_debug("Pointer Query on strid = %d ops %d\n",
- str_id, stream->ops);
-
- if (stream->ops == STREAM_OPS_PLAYBACK)
- stream_info->buffer_ptr = fw_tstamp.samples_rendered;
- else
- stream_info->buffer_ptr = fw_tstamp.samples_processed;
- pr_debug("Samples rendered = %llu, buffer ptr %llu\n",
- fw_tstamp.samples_rendered, stream_info->buffer_ptr);
- break;
- }
- case SST_ENABLE_RX_TIME_SLOT: {
- int status = *(int *)arg;
- sst_drv_ctx->rx_time_slot_status = status ;
- sst_enable_rx_timeslot(status);
- break;
- }
- default:
- /* Illegal case */
- pr_warn("illegal req\n");
- return -EINVAL;
- }
-
- return retval;
-}
-
-
-struct intel_sst_pcm_control pcm_ops = {
- .open = sst_open_pcm_stream,
- .device_control = sst_device_control,
- .close = sst_close_pcm_stream,
-};
-
-struct intel_sst_card_ops sst_pmic_ops = {
- .pcm_control = &pcm_ops,
-};
-
-/*
- * register_sst_card - function for sound card to register
- *
- * @card: pointer to structure of operations
- *
- * This function is called card driver loads and is ready for registration
- */
-int register_sst_card(struct intel_sst_card_ops *card)
-{
- if (!sst_drv_ctx) {
- pr_err("No SST driver register card reject\n");
- return -ENODEV;
- }
-
- if (!card || !card->module_name) {
- pr_err("Null Pointer Passed\n");
- return -EINVAL;
- }
- if (sst_drv_ctx->pmic_state == SND_MAD_UN_INIT) {
- /* register this driver */
- if ((strncmp(SST_CARD_NAMES, card->module_name,
- strlen(SST_CARD_NAMES))) == 0) {
- sst_drv_ctx->pmic_vendor = card->vendor_id;
- sst_drv_ctx->scard_ops = card->scard_ops;
- sst_pmic_ops.module_name = card->module_name;
- sst_drv_ctx->pmic_state = SND_MAD_INIT_DONE;
- sst_drv_ctx->rx_time_slot_status = 0; /*default AMIC*/
- card->pcm_control = sst_pmic_ops.pcm_control;
- return 0;
- } else {
- pr_err("strcmp fail %s\n", card->module_name);
- return -EINVAL;
- }
-
- } else {
- /* already registered a driver */
- pr_err("Repeat for registration..denied\n");
- return -EBADRQC;
- }
- /* The ASoC code doesn't set scard_ops */
- if (sst_drv_ctx->scard_ops)
- sst_drv_ctx->scard_ops->card_status = SND_CARD_UN_INIT;
- return 0;
-}
-EXPORT_SYMBOL_GPL(register_sst_card);
-
-/*
- * unregister_sst_card- function for sound card to un-register
- *
- * @card: pointer to structure of operations
- *
- * This function is called when card driver unloads
- */
-void unregister_sst_card(struct intel_sst_card_ops *card)
-{
- if (sst_pmic_ops.pcm_control == card->pcm_control) {
- /* unreg */
- sst_pmic_ops.module_name = "";
- sst_drv_ctx->pmic_state = SND_MAD_UN_INIT;
- pr_debug("Unregistered %s\n", card->module_name);
- }
- return;
-}
-EXPORT_SYMBOL_GPL(unregister_sst_card);
diff --git a/drivers/staging/intel_sst/intel_sst_dsp.c b/drivers/staging/intel_sst/intel_sst_dsp.c
deleted file mode 100644
index 426d2b92073a..000000000000
--- a/drivers/staging/intel_sst/intel_sst_dsp.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * intel_sst_dsp.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This driver exposes the audio engine functionalities to the ALSA
- * and middleware.
- *
- * This file contains all dsp controlling functions like firmware download,
- * setting/resetting dsp cores, etc
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/firmware.h>
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intel_sst_fw_ipc.h"
-#include "intel_sst_common.h"
-
-
-/**
- * intel_sst_reset_dsp_mrst - Resetting SST DSP
- *
- * This resets DSP in case of MRST platfroms
- */
-static int intel_sst_reset_dsp_mrst(void)
-{
- union config_status_reg csr;
-
- pr_debug("Resetting the DSP in mrst\n");
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.full |= 0x382;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.part.strb_cntr_rst = 0;
- csr.part.run_stall = 0x1;
- csr.part.bypass = 0x7;
- csr.part.sst_reset = 0x1;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
- return 0;
-}
-
-/**
- * intel_sst_reset_dsp_medfield - Resetting SST DSP
- *
- * This resets DSP in case of Medfield platfroms
- */
-static int intel_sst_reset_dsp_medfield(void)
-{
- union config_status_reg csr;
-
- pr_debug("Resetting the DSP in medfield\n");
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.full |= 0x382;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
-
- return 0;
-}
-
-/**
- * sst_start_mrst - Start the SST DSP processor
- *
- * This starts the DSP in MRST platfroms
- */
-static int sst_start_mrst(void)
-{
- union config_status_reg csr;
-
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.part.bypass = 0;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
- csr.part.run_stall = 0;
- csr.part.sst_reset = 0;
- csr.part.strb_cntr_rst = 1;
- pr_debug("Setting SST to execute_mrst 0x%x\n", csr.full);
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
-
- return 0;
-}
-
-/**
- * sst_start_medfield - Start the SST DSP processor
- *
- * This starts the DSP in Medfield platfroms
- */
-static int sst_start_medfield(void)
-{
- union config_status_reg csr;
-
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.part.bypass = 0;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.part.mfld_strb = 1;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.part.run_stall = 0;
- csr.part.sst_reset = 0;
- pr_debug("Starting the DSP_medfld %x\n", csr.full);
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
- pr_debug("Starting the DSP_medfld\n");
-
- return 0;
-}
-
-/**
- * sst_parse_module - Parse audio FW modules
- *
- * @module: FW module header
- *
- * Parses modules that need to be placed in SST IRAM and DRAM
- * returns error or 0 if module sizes are proper
- */
-static int sst_parse_module(struct fw_module_header *module)
-{
- struct dma_block_info *block;
- u32 count;
- void __iomem *ram;
-
- pr_debug("module sign %s size %x blocks %x type %x\n",
- module->signature, module->mod_size,
- module->blocks, module->type);
- pr_debug("module entrypoint 0x%x\n", module->entry_point);
-
- block = (void *)module + sizeof(*module);
-
- for (count = 0; count < module->blocks; count++) {
- if (block->size <= 0) {
- pr_err("block size invalid\n");
- return -EINVAL;
- }
- switch (block->type) {
- case SST_IRAM:
- ram = sst_drv_ctx->iram;
- break;
- case SST_DRAM:
- ram = sst_drv_ctx->dram;
- break;
- default:
- pr_err("wrong ram type0x%x in block0x%x\n",
- block->type, count);
- return -EINVAL;
- }
- memcpy_toio(ram + block->ram_offset,
- (void *)block + sizeof(*block), block->size);
- block = (void *)block + sizeof(*block) + block->size;
- }
- return 0;
-}
-
-/**
- * sst_parse_fw_image - parse and load FW
- *
- * @sst_fw: pointer to audio fw
- *
- * This function is called to parse and download the FW image
- */
-static int sst_parse_fw_image(const struct firmware *sst_fw)
-{
- struct fw_header *header;
- u32 count;
- int ret_val;
- struct fw_module_header *module;
-
- BUG_ON(!sst_fw);
-
- /* Read the header information from the data pointer */
- header = (struct fw_header *)sst_fw->data;
-
- /* verify FW */
- if ((strncmp(header->signature, SST_FW_SIGN, 4) != 0) ||
- (sst_fw->size != header->file_size + sizeof(*header))) {
- /* Invalid FW signature */
- pr_err("Invalid FW sign/filesize mismatch\n");
- return -EINVAL;
- }
- pr_debug("header sign=%s size=%x modules=%x fmt=%x size=%x\n",
- header->signature, header->file_size, header->modules,
- header->file_format, sizeof(*header));
- module = (void *)sst_fw->data + sizeof(*header);
- for (count = 0; count < header->modules; count++) {
- /* module */
- ret_val = sst_parse_module(module);
- if (ret_val)
- return ret_val;
- module = (void *)module + sizeof(*module) + module->mod_size ;
- }
-
- return 0;
-}
-
-/**
- * sst_load_fw - function to load FW into DSP
- *
- * @fw: Pointer to driver loaded FW
- * @context: driver context
- *
- * This function is called by OS when the FW is loaded into kernel
- */
-int sst_load_fw(const struct firmware *fw, void *context)
-{
- int ret_val;
-
- pr_debug("load_fw called\n");
- BUG_ON(!fw);
-
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
- ret_val = intel_sst_reset_dsp_mrst();
- else if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID)
- ret_val = intel_sst_reset_dsp_medfield();
- if (ret_val)
- return ret_val;
-
- ret_val = sst_parse_fw_image(fw);
- if (ret_val)
- return ret_val;
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_FW_LOADED;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- /* 7. ask scu to reset the bypass bits */
- /* 8.bring sst out of reset */
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
- ret_val = sst_start_mrst();
- else if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID)
- ret_val = sst_start_medfield();
- if (ret_val)
- return ret_val;
-
- pr_debug("fw loaded successful!!!\n");
- return ret_val;
-}
-
-/*This function is called when any codec/post processing library
- needs to be downloaded*/
-static int sst_download_library(const struct firmware *fw_lib,
- struct snd_sst_lib_download_info *lib)
-{
- /* send IPC message and wait */
- int i;
- u8 pvt_id;
- struct ipc_post *msg = NULL;
- union config_status_reg csr;
- struct snd_sst_str_type str_type = {0};
- int retval = 0;
-
- if (sst_create_large_msg(&msg))
- return -ENOMEM;
-
- pvt_id = sst_assign_pvt_id(sst_drv_ctx);
- i = sst_get_block_stream(sst_drv_ctx);
- pr_debug("alloc block allocated = %d, pvt_id %d\n", i, pvt_id);
- if (i < 0) {
- kfree(msg);
- return -ENOMEM;
- }
- sst_drv_ctx->alloc_block[i].sst_id = pvt_id;
- sst_fill_header(&msg->header, IPC_IA_PREP_LIB_DNLD, 1, pvt_id);
- msg->header.part.data = sizeof(u32) + sizeof(str_type);
- str_type.codec_type = lib->dload_lib.lib_info.lib_type;
- /*str_type.pvt_id = pvt_id;*/
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), &str_type, sizeof(str_type));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]);
- if (retval) {
- /* error */
- sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
- pr_err("Prep codec downloaded failed %d\n",
- retval);
- return -EIO;
- }
- pr_debug("FW responded, ready for download now...\n");
- /* downloading on success */
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_FW_LOADED;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- csr.full = readl(sst_drv_ctx->shim + SST_CSR);
- csr.part.run_stall = 1;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
-
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.part.bypass = 0x7;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
-
- sst_parse_fw_image(fw_lib);
-
- /* set the FW to running again */
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.part.bypass = 0x0;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
-
- csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
- csr.part.run_stall = 0;
- sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
-
- /* send download complete and wait */
- if (sst_create_large_msg(&msg)) {
- sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
- return -ENOMEM;
- }
-
- sst_fill_header(&msg->header, IPC_IA_LIB_DNLD_CMPLT, 1, pvt_id);
- sst_drv_ctx->alloc_block[i].sst_id = pvt_id;
- msg->header.part.data = sizeof(u32) + sizeof(*lib);
- lib->pvt_id = pvt_id;
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), lib, sizeof(*lib));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- pr_debug("Waiting for FW response Download complete\n");
- sst_drv_ctx->alloc_block[i].ops_block.condition = false;
- retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]);
- if (retval) {
- /* error */
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_UN_INIT;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
- return -EIO;
- }
-
- pr_debug("FW success on Download complete\n");
- sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_FW_RUNNING;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- return 0;
-
-}
-
-/* This function is called before downloading the codec/postprocessing
-library is set for download to SST DSP*/
-static int sst_validate_library(const struct firmware *fw_lib,
- struct lib_slot_info *slot,
- u32 *entry_point)
-{
- struct fw_header *header;
- struct fw_module_header *module;
- struct dma_block_info *block;
- unsigned int n_blk, isize = 0, dsize = 0;
- int err = 0;
-
- header = (struct fw_header *)fw_lib->data;
- if (header->modules != 1) {
- pr_err("Module no mismatch found\n");
- err = -EINVAL;
- goto exit;
- }
- module = (void *)fw_lib->data + sizeof(*header);
- *entry_point = module->entry_point;
- pr_debug("Module entry point 0x%x\n", *entry_point);
- pr_debug("Module Sign %s, Size 0x%x, Blocks 0x%x Type 0x%x\n",
- module->signature, module->mod_size,
- module->blocks, module->type);
-
- block = (void *)module + sizeof(*module);
- for (n_blk = 0; n_blk < module->blocks; n_blk++) {
- switch (block->type) {
- case SST_IRAM:
- isize += block->size;
- break;
- case SST_DRAM:
- dsize += block->size;
- break;
- default:
- pr_err("Invalid block type for 0x%x\n", n_blk);
- err = -EINVAL;
- goto exit;
- }
- block = (void *)block + sizeof(*block) + block->size;
- }
- if (isize > slot->iram_size || dsize > slot->dram_size) {
- pr_err("library exceeds size allocated\n");
- err = -EINVAL;
- goto exit;
- } else
- pr_debug("Library is safe for download...\n");
-
- pr_debug("iram 0x%x, dram 0x%x, iram 0x%x, dram 0x%x\n",
- isize, dsize, slot->iram_size, slot->dram_size);
-exit:
- return err;
-
-}
-
-/* This function is called when FW requests for a particular library download
-This function prepares the library to download*/
-int sst_load_library(struct snd_sst_lib_download *lib, u8 ops)
-{
- char buf[20];
- const char *type, *dir;
- int len = 0, error = 0;
- u32 entry_point;
- const struct firmware *fw_lib;
- struct snd_sst_lib_download_info dload_info = {{{0},},};
-
- memset(buf, 0, sizeof(buf));
-
- pr_debug("Lib Type 0x%x, Slot 0x%x, ops 0x%x\n",
- lib->lib_info.lib_type, lib->slot_info.slot_num, ops);
- pr_debug("Version 0x%x, name %s, caps 0x%x media type 0x%x\n",
- lib->lib_info.lib_version, lib->lib_info.lib_name,
- lib->lib_info.lib_caps, lib->lib_info.media_type);
-
- pr_debug("IRAM Size 0x%x, offset 0x%x\n",
- lib->slot_info.iram_size, lib->slot_info.iram_offset);
- pr_debug("DRAM Size 0x%x, offset 0x%x\n",
- lib->slot_info.dram_size, lib->slot_info.dram_offset);
-
- switch (lib->lib_info.lib_type) {
- case SST_CODEC_TYPE_MP3:
- type = "mp3_";
- break;
- case SST_CODEC_TYPE_AAC:
- type = "aac_";
- break;
- case SST_CODEC_TYPE_AACP:
- type = "aac_v1_";
- break;
- case SST_CODEC_TYPE_eAACP:
- type = "aac_v2_";
- break;
- case SST_CODEC_TYPE_WMA9:
- type = "wma9_";
- break;
- default:
- pr_err("Invalid codec type\n");
- error = -EINVAL;
- goto wake;
- }
-
- if (ops == STREAM_OPS_CAPTURE)
- dir = "enc_";
- else
- dir = "dec_";
- len = strlen(type) + strlen(dir);
- strncpy(buf, type, sizeof(buf)-1);
- strncpy(buf + strlen(type), dir, sizeof(buf)-strlen(type)-1);
- len += snprintf(buf + len, sizeof(buf) - len, "%d",
- lib->slot_info.slot_num);
- len += snprintf(buf + len, sizeof(buf) - len, ".bin");
-
- pr_debug("Requesting %s\n", buf);
-
- error = request_firmware(&fw_lib, buf, &sst_drv_ctx->pci->dev);
- if (error) {
- pr_err("library load failed %d\n", error);
- goto wake;
- }
- error = sst_validate_library(fw_lib, &lib->slot_info, &entry_point);
- if (error)
- goto wake_free;
-
- lib->mod_entry_pt = entry_point;
- memcpy(&dload_info.dload_lib, lib, sizeof(*lib));
- error = sst_download_library(fw_lib, &dload_info);
- if (error)
- goto wake_free;
-
- /* lib is downloaded and init send alloc again */
- pr_debug("Library is downloaded now...\n");
-wake_free:
- /* sst_wake_up_alloc_block(sst_drv_ctx, pvt_id, error, NULL); */
- release_firmware(fw_lib);
-wake:
- return error;
-}
-
diff --git a/drivers/staging/intel_sst/intel_sst_fw_ipc.h b/drivers/staging/intel_sst/intel_sst_fw_ipc.h
deleted file mode 100644
index 5d0cc56aaef9..000000000000
--- a/drivers/staging/intel_sst/intel_sst_fw_ipc.h
+++ /dev/null
@@ -1,416 +0,0 @@
-#ifndef __INTEL_SST_FW_IPC_H__
-#define __INTEL_SST_FW_IPC_H__
-/*
-* intel_sst_fw_ipc.h - Intel SST Driver for audio engine
-*
-* Copyright (C) 2008-10 Intel Corporation
-* Author: Vinod Koul <vinod.koul@intel.com>
-* Harsha Priya <priya.harsha@intel.com>
-* Dharageswari R <dharageswari.r@intel.com>
-* KP Jeeja <jeeja.kp@intel.com>
-* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; version 2 of the License.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License along
-* with this program; if not, write to the Free Software Foundation, Inc.,
-* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-*
-* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-*
-* This driver exposes the audio engine functionalities to the ALSA
-* and middleware.
-* This file has definitions shared between the firmware and driver
-*/
-
-#define MAX_NUM_STREAMS_MRST 3
-#define MAX_NUM_STREAMS_MFLD 6
-#define MAX_NUM_STREAMS 6
-#define MAX_DBG_RW_BYTES 80
-#define MAX_NUM_SCATTER_BUFFERS 8
-#define MAX_LOOP_BACK_DWORDS 8
-/* IPC base address and mailbox, timestamp offsets */
-#define SST_MAILBOX_SIZE 0x0400
-#define SST_MAILBOX_SEND 0x0000
-#define SST_MAILBOX_RCV 0x0804
-#define SST_TIME_STAMP 0x1800
-#define SST_RESERVED_OFFSET 0x1A00
-#define SST_CHEKPOINT_OFFSET 0x1C00
-#define REPLY_MSG 0x80
-
-/* Message ID's for IPC messages */
-/* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */
-
-/* I2L Firmware/Codec Download msgs */
-#define IPC_IA_PREP_LIB_DNLD 0x01
-#define IPC_IA_LIB_DNLD_CMPLT 0x02
-
-#define IPC_IA_SET_PMIC_TYPE 0x03
-#define IPC_IA_GET_FW_VERSION 0x04
-#define IPC_IA_GET_FW_BUILD_INF 0x05
-#define IPC_IA_GET_FW_INFO 0x06
-#define IPC_IA_GET_FW_CTXT 0x07
-#define IPC_IA_SET_FW_CTXT 0x08
-
-/* I2L Codec Config/control msgs */
-#define IPC_IA_SET_CODEC_PARAMS 0x10
-#define IPC_IA_GET_CODEC_PARAMS 0x11
-#define IPC_IA_SET_PPP_PARAMS 0x12
-#define IPC_IA_GET_PPP_PARAMS 0x13
-#define IPC_IA_PLAY_FRAMES 0x14
-#define IPC_IA_CAPT_FRAMES 0x15
-#define IPC_IA_PLAY_VOICE 0x16
-#define IPC_IA_CAPT_VOICE 0x17
-#define IPC_IA_DECODE_FRAMES 0x18
-
-#define IPC_IA_ALG_PARAMS 0x1A
-#define IPC_IA_TUNING_PARAMS 0x1B
-
-/* I2L Stream config/control msgs */
-#define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */
-#define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */
-#define IPC_IA_SET_STREAM_PARAMS 0x22
-#define IPC_IA_GET_STREAM_PARAMS 0x23
-#define IPC_IA_PAUSE_STREAM 0x24
-#define IPC_IA_RESUME_STREAM 0x25
-#define IPC_IA_DROP_STREAM 0x26
-#define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */
-#define IPC_IA_TARGET_DEV_SELECT 0x28
-#define IPC_IA_CONTROL_ROUTING 0x29
-
-#define IPC_IA_SET_STREAM_VOL 0x2A /*Vol for stream, pre mixer */
-#define IPC_IA_GET_STREAM_VOL 0x2B
-#define IPC_IA_SET_STREAM_MUTE 0x2C
-#define IPC_IA_GET_STREAM_MUTE 0x2D
-#define IPC_IA_ENABLE_RX_TIME_SLOT 0x2E /* Enable Rx time slot 0 or 1 */
-
-#define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */
-
-/* Debug msgs */
-#define IPC_IA_DBG_MEM_READ 0x40
-#define IPC_IA_DBG_MEM_WRITE 0x41
-#define IPC_IA_DBG_LOOP_BACK 0x42
-
-/* L2I Firmware/Codec Download msgs */
-#define IPC_IA_FW_INIT_CMPLT 0x81
-#define IPC_IA_LPE_GETTING_STALLED 0x82
-#define IPC_IA_LPE_UNSTALLED 0x83
-
-/* L2I Codec Config/control msgs */
-#define IPC_SST_GET_PLAY_FRAMES 0x90 /* Request IA more data */
-#define IPC_SST_GET_CAPT_FRAMES 0x91 /* Request IA more data */
-#define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */
-#define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */
-#define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */
-#define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */
-#define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */
-#define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */
-#define IPC_IA_TARGET_DEV_CHNGD 0x98 /* error in processing a stream */
-
-#define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */
-/* L2S messages */
-#define IPC_SC_DDR_LINK_UP 0xC0
-#define IPC_SC_DDR_LINK_DOWN 0xC1
-#define IPC_SC_SET_LPECLK_REQ 0xC2
-#define IPC_SC_SSP_BIT_BANG 0xC3
-
-/* L2I Error reporting msgs */
-#define IPC_IA_MEM_ALLOC_FAIL 0xE0
-#define IPC_IA_PROC_ERR 0xE1 /* error in processing a
- stream can be used by playback and
- capture modules */
-
-/* L2I Debug msgs */
-#define IPC_IA_PRINT_STRING 0xF0
-
-
-
-/* Command Response or Acknowledge message to any IPC message will have
- * same message ID and stream ID information which is sent.
- * There is no specific Ack message ID. The data field is used as response
- * meaning.
- */
-enum ackData {
- IPC_ACK_SUCCESS = 0,
- IPC_ACK_FAILURE
-};
-
-
-enum sst_error_codes {
- /* Error code,response to msgId: Description */
- /* Common error codes */
- SST_SUCCESS = 0, /* Success */
- SST_ERR_INVALID_STREAM_ID = 1,
- SST_ERR_INVALID_MSG_ID = 2,
- SST_ERR_INVALID_STREAM_OP = 3,
- SST_ERR_INVALID_PARAMS = 4,
- SST_ERR_INVALID_CODEC = 5,
- SST_ERR_INVALID_MEDIA_TYPE = 6,
- SST_ERR_STREAM_ERR = 7,
-
- /* IPC specific error codes */
- SST_IPC_ERR_CALL_BACK_NOT_REGD = 8,
- SST_IPC_ERR_STREAM_NOT_ALLOCATED = 9,
- SST_IPC_ERR_STREAM_ALLOC_FAILED = 10,
- SST_IPC_ERR_GET_STREAM_FAILED = 11,
- SST_ERR_MOD_NOT_AVAIL = 12,
- SST_ERR_MOD_DNLD_RQD = 13,
- SST_ERR_STREAM_STOPPED = 14,
- SST_ERR_STREAM_IN_USE = 15,
-
- /* Capture specific error codes */
- SST_CAP_ERR_INCMPLTE_CAPTURE_MSG = 16,
- SST_CAP_ERR_CAPTURE_FAIL = 17,
- SST_CAP_ERR_GET_DDR_NEW_SGLIST = 18,
- SST_CAP_ERR_UNDER_RUN = 19,
- SST_CAP_ERR_OVERFLOW = 20,
-
- /* Playback specific error codes*/
- SST_PB_ERR_INCMPLTE_PLAY_MSG = 21,
- SST_PB_ERR_PLAY_FAIL = 22,
- SST_PB_ERR_GET_DDR_NEW_SGLIST = 23,
-
- /* Codec manager specific error codes */
- SST_LIB_ERR_LIB_DNLD_REQUIRED = 24,
- SST_LIB_ERR_LIB_NOT_SUPPORTED = 25,
-
- /* Library manager specific error codes */
- SST_SCC_ERR_PREP_DNLD_FAILED = 26,
- SST_SCC_ERR_LIB_DNLD_RES_FAILED = 27,
- /* Scheduler specific error codes */
- SST_SCH_ERR_FAIL = 28,
-
- /* DMA specific error codes */
- SST_DMA_ERR_NO_CHNL_AVAILABLE = 29,
- SST_DMA_ERR_INVALID_INPUT_PARAMS = 30,
- SST_DMA_ERR_CHNL_ALREADY_SUSPENDED = 31,
- SST_DMA_ERR_CHNL_ALREADY_STARTED = 32,
- SST_DMA_ERR_CHNL_NOT_ENABLED = 33,
- SST_DMA_ERR_TRANSFER_FAILED = 34,
-
- SST_SSP_ERR_ALREADY_ENABLED = 35,
- SST_SSP_ERR_ALREADY_DISABLED = 36,
- SST_SSP_ERR_NOT_INITIALIZED = 37,
- SST_SSP_ERR_SRAM_NO_DMA_DATA = 38,
-
- /* Other error codes */
- SST_ERR_MOD_INIT_FAIL = 39,
-
- /* FW init error codes */
- SST_RDR_ERR_IO_DEV_SEL_NOT_ALLOWED = 40,
- SST_RDR_ERR_ROUTE_ALREADY_STARTED = 41,
- SST_RDR_ERR_IO_DEV_SEL_FAILED = 42,
- SST_RDR_PREP_CODEC_DNLD_FAILED = 43,
-
- /* Memory debug error codes */
- SST_ERR_DBG_MEM_READ_FAIL = 44,
- SST_ERR_DBG_MEM_WRITE_FAIL = 45,
- SST_ERR_INSUFFICIENT_INPUT_SG_LIST = 46,
- SST_ERR_INSUFFICIENT_OUTPUT_SG_LIST = 47,
-
- SST_ERR_BUFFER_NOT_AVAILABLE = 48,
- SST_ERR_BUFFER_NOT_ALLOCATED = 49,
- SST_ERR_INVALID_REGION_TYPE = 50,
- SST_ERR_NULL_PTR = 51,
- SST_ERR_INVALID_BUFFER_SIZE = 52,
- SST_ERR_INVALID_BUFFER_INDEX = 53,
-
- /*IIPC specific error codes */
- SST_IIPC_QUEUE_FULL = 54,
- SST_IIPC_ERR_MSG_SND_FAILED = 55,
- SST_PB_ERR_UNDERRUN_OCCURED = 56,
- SST_RDR_INSUFFICIENT_MIXER_BUFFER = 57,
- SST_INVALID_TIME_SLOTS = 58,
-};
-
-enum dbg_mem_data_type {
- /* Data type of debug read/write */
- DATA_TYPE_U32,
- DATA_TYPE_U16,
- DATA_TYPE_U8,
-};
-
-/* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/
-
-/* IPC Header */
-union ipc_header {
- struct {
- u32 msg_id:8; /* Message ID - Max 256 Message Types */
- u32 str_id:5;
- u32 large:1; /* Large Message if large = 1 */
- u32 reserved:2; /* Reserved for future use */
- u32 data:14; /* Ack/Info for msg, size of msg in Mailbox */
- u32 done:1; /* bit 30 */
- u32 busy:1; /* bit 31 */
- } part;
- u32 full;
-} __attribute__ ((packed));
-
-/* Firmware build info */
-struct sst_fw_build_info {
- unsigned char date[16]; /* Firmware build date */
- unsigned char time[16]; /* Firmware build time */
-} __attribute__ ((packed));
-
-struct ipc_header_fw_init {
- struct snd_sst_fw_version fw_version;/* Firmware version details */
- struct sst_fw_build_info build_info;
- u16 result; /* Fw init result */
- u8 module_id; /* Module ID in case of error */
- u8 debug_info; /* Debug info from Module ID in case of fail */
-} __attribute__ ((packed));
-
-/* Address and size info of a frame buffer in DDR */
-struct sst_address_info {
- u32 addr; /* Address at IA */
- u32 size; /* Size of the buffer */
-} __attribute__ ((packed));
-
-/* Time stamp */
-struct snd_sst_tstamp {
- u64 samples_processed;/* capture - data in DDR */
- u64 samples_rendered;/* playback - data rendered */
- u64 bytes_processed;/* bytes decoded or encoded */
- u32 sampling_frequency;/* eg: 48000, 44100 */
- u32 dma_base_address;/* DMA base address */
- u16 dma_channel_no;/* DMA Channel used for the data transfer*/
- u16 reserved;/* 32 bit alignment */
-};
-
-/* Frame info to play or capture */
-struct sst_frame_info {
- u16 num_entries; /* number of entries to follow */
- u16 rsrvd;
- struct sst_address_info addr[MAX_NUM_SCATTER_BUFFERS];
-} __attribute__ ((packed));
-
-/* Frames info for decode */
-struct snd_sst_decode_info {
- unsigned long long input_bytes_consumed;
- unsigned long long output_bytes_produced;
- struct sst_frame_info frames_in;
- struct sst_frame_info frames_out;
-} __attribute__ ((packed));
-
-/* SST to IA print debug message*/
-struct ipc_sst_ia_print_params {
- u32 string_size;/* Max value is 160 */
- u8 prt_string[160];/* Null terminated Char string */
-} __attribute__ ((packed));
-
-/* Voice data message */
-struct snd_sst_voice_data {
- u16 num_bytes;/* Number of valid voice data bytes */
- u8 pcm_wd_size;/* 0=8 bit, 1=16 bit 2=32 bit */
- u8 reserved;/* Reserved */
- u8 voice_data_buf[0];/* Voice data buffer in bytes, little endian */
-} __attribute__ ((packed));
-
-/* SST to IA memory read debug message */
-struct ipc_sst_ia_dbg_mem_rw {
- u16 num_bytes;/* Maximum of MAX_DBG_RW_BYTES */
- u16 data_type;/* enum: dbg_mem_data_type */
- u32 address; /* Memory address of data memory of data_type */
- u8 rw_bytes[MAX_DBG_RW_BYTES];/* Maximum of 64 bytes can be RW */
-} __attribute__ ((packed));
-
-struct ipc_sst_ia_dbg_loop_back {
- u16 num_dwords; /* Maximum of MAX_DBG_RW_BYTES */
- u16 increment_val;/* Increments dwords by this value, 0- no increment */
- u32 lpbk_dwords[MAX_LOOP_BACK_DWORDS];/* Maximum of 8 dwords loopback */
-} __attribute__ ((packed));
-
-/* Stream type params struture for Alloc stream */
-struct snd_sst_str_type {
- u8 codec_type; /* Codec type */
- u8 str_type; /* 1 = voice 2 = music */
- u8 operation; /* Playback or Capture */
- u8 protected_str; /* 0=Non DRM, 1=DRM */
- u8 time_slots;
- u8 reserved; /* Reserved */
- u16 result; /* Result used for acknowledgment */
-} __attribute__ ((packed));
-
-/* Library info structure */
-struct module_info {
- u32 lib_version;
- u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/
- u32 media_type;
- u8 lib_name[12];
- u32 lib_caps;
- unsigned char b_date[16]; /* Lib build date */
- unsigned char b_time[16]; /* Lib build time */
-} __attribute__ ((packed));
-
-/* Library slot info */
-struct lib_slot_info {
- u8 slot_num; /* 1 or 2 */
- u8 reserved1;
- u16 reserved2;
- u32 iram_size; /* slot size in IRAM */
- u32 dram_size; /* slot size in DRAM */
- u32 iram_offset; /* starting offset of slot in IRAM */
- u32 dram_offset; /* starting offset of slot in DRAM */
-} __attribute__ ((packed));
-
-struct snd_sst_lib_download {
- struct module_info lib_info; /* library info type, capabilities etc */
- struct lib_slot_info slot_info; /* slot info to be downloaded */
- u32 mod_entry_pt;
-};
-
-struct snd_sst_lib_download_info {
- struct snd_sst_lib_download dload_lib;
- u16 result; /* Result used for acknowledgment */
- u8 pvt_id; /* Private ID */
- u8 reserved; /* for alignment */
-};
-
-/* Alloc stream params structure */
-struct snd_sst_alloc_params {
- struct snd_sst_str_type str_type;
- struct snd_sst_stream_params stream_params;
-};
-
-struct snd_sst_fw_get_stream_params {
- struct snd_sst_stream_params codec_params;
- struct snd_sst_pmic_config pcm_params;
-};
-
-/* Alloc stream response message */
-struct snd_sst_alloc_response {
- struct snd_sst_str_type str_type; /* Stream type for allocation */
- struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */
-};
-
-/* Drop response */
-struct snd_sst_drop_response {
- u32 result;
- u32 bytes;
-};
-
-/* CSV Voice call routing structure */
-struct snd_sst_control_routing {
- u8 control; /* 0=start, 1=Stop */
- u8 reserved[3]; /* Reserved- for 32 bit alignment */
-};
-
-
-struct ipc_post {
- struct list_head node;
- union ipc_header header; /* driver specific */
- char *mailbox_data;
-};
-
-struct snd_sst_ctxt_params {
- u32 address; /* Physical Address in DDR where the context is stored */
- u32 size; /* size of the context */
-};
-#endif /* __INTEL_SST_FW_IPC_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_ioctl.h b/drivers/staging/intel_sst/intel_sst_ioctl.h
deleted file mode 100644
index 5da5ee092c69..000000000000
--- a/drivers/staging/intel_sst/intel_sst_ioctl.h
+++ /dev/null
@@ -1,440 +0,0 @@
-#ifndef __INTEL_SST_IOCTL_H__
-#define __INTEL_SST_IOCTL_H__
-/*
- * intel_sst_ioctl.h - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corporation
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This file defines all sst ioctls
- */
-
-/* codec and post/pre processing related info */
-
-#include <linux/types.h>
-
-enum sst_codec_types {
-/* AUDIO/MUSIC CODEC Type Definitions */
- SST_CODEC_TYPE_UNKNOWN = 0,
- SST_CODEC_TYPE_PCM, /* Pass through Audio codec */
- SST_CODEC_TYPE_MP3,
- SST_CODEC_TYPE_MP24,
- SST_CODEC_TYPE_AAC,
- SST_CODEC_TYPE_AACP,
- SST_CODEC_TYPE_eAACP,
- SST_CODEC_TYPE_WMA9,
- SST_CODEC_TYPE_WMA10,
- SST_CODEC_TYPE_WMA10P,
- SST_CODEC_TYPE_RA,
- SST_CODEC_TYPE_DDAC3,
- SST_CODEC_TYPE_STEREO_TRUE_HD,
- SST_CODEC_TYPE_STEREO_HD_PLUS,
-
- /* VOICE CODEC Type Definitions */
- SST_CODEC_TYPE_VOICE_PCM = 0x21, /* Pass through voice codec */
-};
-
-enum sst_algo_types {
- SST_CODEC_SRC = 0x64,
- SST_CODEC_MIXER = 0x65,
- SST_CODEC_DOWN_MIXER = 0x66,
- SST_CODEC_VOLUME_CONTROL = 0x67,
- SST_CODEC_OEM1 = 0xC8,
- SST_CODEC_OEM2 = 0xC9,
-};
-
-enum snd_sst_stream_ops {
- STREAM_OPS_PLAYBACK = 0, /* Decode */
- STREAM_OPS_CAPTURE, /* Encode */
- STREAM_OPS_PLAYBACK_DRM, /* Play Audio/Voice */
- STREAM_OPS_PLAYBACK_ALERT, /* Play Audio/Voice */
- STREAM_OPS_CAPTURE_VOICE_CALL, /* CSV Voice recording */
-};
-
-enum stream_mode {
- SST_STREAM_MODE_NONE = 0,
- SST_STREAM_MODE_DNR = 1,
- SST_STREAM_MODE_FNF = 2,
- SST_STREAM_MODE_CAPTURE = 3
-};
-
-enum stream_type {
- SST_STREAM_TYPE_NONE = 0,
- SST_STREAM_TYPE_MUSIC = 1,
- SST_STREAM_TYPE_NORMAL = 2,
- SST_STREAM_TYPE_LONG_PB = 3,
- SST_STREAM_TYPE_LOW_LATENCY = 4,
-};
-
-enum snd_sst_audio_device_type {
- SND_SST_DEVICE_HEADSET = 1,
- SND_SST_DEVICE_IHF,
- SND_SST_DEVICE_VIBRA,
- SND_SST_DEVICE_HAPTIC,
- SND_SST_DEVICE_CAPTURE,
-};
-
-/* Firmware Version info */
-struct snd_sst_fw_version {
- __u8 build; /* build number*/
- __u8 minor; /* minor number*/
- __u8 major; /* major number*/
- __u8 type; /* build type */
-};
-
-/* Port info structure */
-struct snd_sst_port_info {
- __u16 port_type;
- __u16 reserved;
-};
-
-/* Mixer info structure */
-struct snd_sst_mix_info {
- __u16 max_streams;
- __u16 reserved;
-};
-
-/* PCM Parameters */
-struct snd_pcm_params {
- __u16 codec; /* codec type */
- __u8 num_chan; /* 1=Mono, 2=Stereo */
- __u8 pcm_wd_sz; /* 16/24 - bit*/
- __u32 reserved; /* Bitrate in bits per second */
- __u32 sfreq; /* Sampling rate in Hz */
- __u32 ring_buffer_size;
- __u32 period_count; /* period elapsed in samples*/
- __u32 ring_buffer_addr;
-};
-
-/* MP3 Music Parameters Message */
-struct snd_mp3_params {
- __u16 codec;
- __u8 num_chan; /* 1=Mono, 2=Stereo */
- __u8 pcm_wd_sz; /* 16/24 - bit*/
- __u32 brate; /* Use the hard coded value. */
- __u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */
- __u8 crc_check; /* crc_check - disable (0) or enable (1) */
- __u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB*/
- __u16 reserved; /* Unused */
-};
-
-#define AAC_BIT_STREAM_ADTS 0
-#define AAC_BIT_STREAM_ADIF 1
-#define AAC_BIT_STREAM_RAW 2
-
-/* AAC Music Parameters Message */
-struct snd_aac_params {
- __u16 codec;
- __u8 num_chan; /* 1=Mono, 2=Stereo*/
- __u8 pcm_wd_sz; /* 16/24 - bit*/
- __u32 brate;
- __u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */
- __u32 aac_srate; /* Plain AAC decoder operating sample rate */
- __u8 mpg_id; /* 0=MPEG-2, 1=MPEG-4 */
- __u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */
- __u8 aac_profile; /* 0=Main Profile, 1=LC profile, 3=SSR profile */
- __u8 ext_chl; /* No.of external channels */
- __u8 aot; /* Audio object type. 1=Main , 2=LC , 3=SSR, 4=SBR*/
- __u8 op_align; /* output alignment 0=16 bit , 1=MSB, 2= LSB align */
- __u8 brate_type; /* 0=CBR, 1=VBR */
- __u8 crc_check; /* crc check 0= disable, 1=enable */
- __s8 bit_stream_format[8]; /* input bit stream format adts/adif/raw */
- __u8 jstereo; /* Joint stereo Flag */
- __u8 sbr_present; /* 1 = SBR Present, 0 = SBR absent, for RAW */
- __u8 downsample; /* 1 = Downsampling ON, 0 = Downsampling OFF */
- __u8 num_syntc_elems; /* 1- Mono/stereo, 0 - Dual Mono, 0 - for raw */
- __s8 syntc_id[2]; /* 0 for ID_SCE(Dula Mono), -1 for raw */
- __s8 syntc_tag[2]; /* raw - -1 and 0 -16 for rest of the streams */
- __u8 pce_present; /* Flag. 1- present 0 - not present, for RAW */
- __u8 sbr_type; /* sbr_type: 0-plain aac, 1-aac-v1, 2-aac-v2 */
- __u8 outchmode; /*0- mono, 1-stereo, 2-dual mono 3-Parametric stereo */
- __u8 ps_present;
-};
-
-/* WMA Music Parameters Message */
-struct snd_wma_params {
- __u16 codec;
- __u8 num_chan; /* 1=Mono, 2=Stereo */
- __u8 pcm_wd_sz; /* 16/24 - bit*/
- __u32 brate; /* Use the hard coded value. */
- __u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */
- __u32 channel_mask; /* Channel Mask */
- __u16 format_tag; /* Format Tag */
- __u16 block_align; /* packet size */
- __u16 wma_encode_opt;/* Encoder option */
- __u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */
- __u8 pcm_src; /* input pcm bit width */
-};
-
-/* Pre processing param structure */
-struct snd_prp_params {
- __u32 reserved; /* No pre-processing defined yet */
-};
-
-/* Pre and post processing params structure */
-struct snd_ppp_params {
- __u8 algo_id;/* Post/Pre processing algorithm ID */
- __u8 str_id; /*Only 5 bits used 0 - 31 are valid*/
- __u8 enable; /* 0= disable, 1= enable*/
- __u8 reserved;
- __u32 size; /*Size of parameters for all blocks*/
- void *params;
-} __attribute__ ((packed));
-
-struct snd_sst_postproc_info {
- __u32 src_min; /* Supported SRC Min sampling freq */
- __u32 src_max; /* Supported SRC Max sampling freq */
- __u8 src; /* 0=Not supported, 1=Supported */
- __u8 bass_boost; /* 0=Not Supported, 1=Supported */
- __u8 stereo_widening; /* 0=Not Supported, 1=Supported */
- __u8 volume_control; /* 0=Not Supported, 1=Supported */
- __s16 min_vol; /* Minimum value of Volume in dB */
- __s16 max_vol; /* Maximum value of Volume in dB */
- __u8 mute_control; /* 0=No Mute, 1=Mute */
- __u8 reserved1;
- __u16 reserved2;
-};
-
-/* pre processing Capability info structure */
-struct snd_sst_prp_info {
- __s16 min_vol; /* Minimum value of Volume in dB */
- __s16 max_vol; /* Maximum value of Volume in dB */
- __u8 volume_control; /* 0=Not Supported, 1=Supported */
- __u8 reserved1; /* for 32 bit alignment */
- __u16 reserved2; /* for 32 bit alignment */
-} __attribute__ ((packed));
-
-/*Pre / Post processing algorithms support*/
-struct snd_sst_ppp_info {
- __u32 src:1; /* 0=Not supported, 1=Supported */
- __u32 mixer:1; /* 0=Not supported, 1=Supported */
- __u32 volume_control:1; /* 0=Not Supported, 1=Supported */
- __u32 mute_control:1; /* 0=Not Supported, 1=Supported */
- __u32 anc:1; /* 0=Not Supported, 1=Supported */
- __u32 side_tone:1; /* 0=Not Supported, 1=Supported */
- __u32 dc_removal:1; /* 0=Not Supported, 1=Supported */
- __u32 equalizer:1; /* 0=Not Supported, 1=Supported */
- __u32 spkr_prot:1; /* 0=Not Supported, 1=Supported */
- __u32 bass_boost:1; /* 0=Not Supported, 1=Supported */
- __u32 stereo_widening:1;/* 0=Not Supported, 1=Supported */
- __u32 rsvd1:21;
- __u32 rsvd2;
-};
-
-/* Firmware capabilities info */
-struct snd_sst_fw_info {
- struct snd_sst_fw_version fw_version; /* Firmware version */
- __u8 audio_codecs_supported[8]; /* Codecs supported by FW */
- __u32 recommend_min_duration; /* Min duration for Lowpower Playback */
- __u8 max_pcm_streams_supported; /* Max num of PCM streams supported */
- __u8 max_enc_streams_supported; /* Max number of Encoded streams */
- __u16 reserved; /* 32 bit alignment*/
- struct snd_sst_ppp_info ppp_info; /* pre_processing mod cap info */
- struct snd_sst_postproc_info pop_info; /* Post processing cap info*/
- struct snd_sst_port_info port_info[3]; /* Port info */
- struct snd_sst_mix_info mix_info;/* Mixer info */
- __u32 min_input_buf; /* minmum i/p buffer for decode */
-};
-
-/* Codec params struture */
-union snd_sst_codec_params {
- struct snd_pcm_params pcm_params;
- struct snd_mp3_params mp3_params;
- struct snd_aac_params aac_params;
- struct snd_wma_params wma_params;
-};
-
-
-struct snd_sst_stream_params {
- union snd_sst_codec_params uc;
-} __attribute__ ((packed));
-
-struct snd_sst_params {
- __u32 result;
- __u32 stream_id;
- __u8 codec;
- __u8 ops;
- __u8 stream_type;
- __u8 device_type;
- struct snd_sst_stream_params sparams;
-};
-
-struct snd_sst_vol {
- __u32 stream_id;
- __s32 volume;
- __u32 ramp_duration;
- __u32 ramp_type; /* Ramp type, default=0 */
-};
-
-struct snd_sst_mute {
- __u32 stream_id;
- __u32 mute;
-};
-
-/* ioctl related stuff here */
-struct snd_sst_pmic_config {
- __u32 sfreq; /* Sampling rate in Hz */
- __u16 num_chan; /* Mono =1 or Stereo =2 */
- __u16 pcm_wd_sz; /* Number of bits per sample */
-} __attribute__ ((packed));
-
-struct snd_sst_get_stream_params {
- struct snd_sst_params codec_params;
- struct snd_sst_pmic_config pcm_params;
-};
-
-enum snd_sst_target_type {
- SND_SST_TARGET_PMIC = 1,
- SND_SST_TARGET_LPE,
- SND_SST_TARGET_MODEM,
- SND_SST_TARGET_BT,
- SND_SST_TARGET_FM,
- SND_SST_TARGET_NONE,
-};
-
-enum snd_sst_device_type {
- SND_SST_DEVICE_SSP = 1,
- SND_SST_DEVICE_PCM,
- SND_SST_DEVICE_OTHER,
-};
-
-enum snd_sst_device_mode {
-
- SND_SST_DEV_MODE_PCM_MODE1 = 1, /*(16-bit word, bit-length frame sync)*/
- SND_SST_DEV_MODE_PCM_MODE2,
- SND_SST_DEV_MODE_PCM_MODE3,
- SND_SST_DEV_MODE_PCM_MODE4_RIGHT_JUSTIFIED,
- SND_SST_DEV_MODE_PCM_MODE4_LEFT_JUSTIFIED,
- SND_SST_DEV_MODE_PCM_MODE4_I2S, /*(I2S mode, 16-bit words)*/
- SND_SST_DEV_MODE_PCM_MODE5,
- SND_SST_DEV_MODE_PCM_MODE6,
-};
-
-enum snd_sst_port_action {
- SND_SST_PORT_PREPARE = 1,
- SND_SST_PORT_ACTIVATE,
-};
-
-/* Target selection per device structure */
-struct snd_sst_slot_info {
- __u8 mix_enable; /* Mixer enable or disable */
- __u8 device_type;
- __u8 device_instance; /* 0, 1, 2 */
- __u8 target_device;
- __u16 target_sink;
- __u8 slot[2];
- __u8 master;
- __u8 action;
- __u8 device_mode;
- __u8 reserved;
- struct snd_sst_pmic_config pcm_params;
-} __attribute__ ((packed));
-
-#define SST_MAX_TARGET_DEVICES 3
-/* Target device list structure */
-struct snd_sst_target_device {
- __u32 device_route;
- struct snd_sst_slot_info devices[SST_MAX_TARGET_DEVICES];
-} __attribute__ ((packed));
-
-struct snd_sst_driver_info {
- __u32 version; /* Version of the driver */
- __u32 active_pcm_streams;
- __u32 active_enc_streams;
- __u32 max_pcm_streams;
- __u32 max_enc_streams;
- __u32 buf_per_stream;
-};
-
-enum snd_sst_buff_type {
- SST_BUF_USER = 1,
- SST_BUF_MMAP,
- SST_BUF_RAR,
-};
-
-struct snd_sst_mmap_buff_entry {
- unsigned int offset;
- unsigned int size;
-};
-
-struct snd_sst_mmap_buffs {
- unsigned int entries;
- enum snd_sst_buff_type type;
- struct snd_sst_mmap_buff_entry *buff;
-};
-
-struct snd_sst_buff_entry {
- void *buffer;
- unsigned int size;
-};
-
-struct snd_sst_buffs {
- unsigned int entries;
- __u8 type;
- struct snd_sst_buff_entry *buff_entry;
-};
-
-struct snd_sst_dbufs {
- unsigned long long input_bytes_consumed;
- unsigned long long output_bytes_produced;
- struct snd_sst_buffs *ibufs;
- struct snd_sst_buffs *obufs;
-};
-
-struct snd_sst_tuning_params {
- __u8 type;
- __u8 str_id;
- __u8 size;
- __u8 rsvd;
- __aligned_u64 addr;
-} __attribute__ ((packed));
-/*IOCTL defined here */
-/*SST MMF IOCTLS only */
-#define SNDRV_SST_STREAM_SET_PARAMS _IOR('L', 0x00, \
- struct snd_sst_stream_params *)
-#define SNDRV_SST_STREAM_GET_PARAMS _IOWR('L', 0x01, \
- struct snd_sst_get_stream_params *)
-#define SNDRV_SST_STREAM_GET_TSTAMP _IOWR('L', 0x02, __u64 *)
-#define SNDRV_SST_STREAM_DECODE _IOWR('L', 0x03, struct snd_sst_dbufs *)
-#define SNDRV_SST_STREAM_BYTES_DECODED _IOWR('L', 0x04, __u64 *)
-#define SNDRV_SST_STREAM_START _IO('A', 0x42)
-#define SNDRV_SST_STREAM_DROP _IO('A', 0x43)
-#define SNDRV_SST_STREAM_DRAIN _IO('A', 0x44)
-#define SNDRV_SST_STREAM_PAUSE _IOW('A', 0x45, int)
-#define SNDRV_SST_STREAM_RESUME _IO('A', 0x47)
-#define SNDRV_SST_MMAP_PLAY _IOW('L', 0x05, struct snd_sst_mmap_buffs *)
-#define SNDRV_SST_MMAP_CAPTURE _IOW('L', 0x06, struct snd_sst_mmap_buffs *)
-/*SST common ioctls */
-#define SNDRV_SST_DRIVER_INFO _IOR('L', 0x10, struct snd_sst_driver_info *)
-#define SNDRV_SST_SET_VOL _IOW('L', 0x11, struct snd_sst_vol *)
-#define SNDRV_SST_GET_VOL _IOW('L', 0x12, struct snd_sst_vol *)
-#define SNDRV_SST_MUTE _IOW('L', 0x13, struct snd_sst_mute *)
-/*AM Ioctly only */
-#define SNDRV_SST_FW_INFO _IOR('L', 0x20, struct snd_sst_fw_info *)
-#define SNDRV_SST_SET_TARGET_DEVICE _IOW('L', 0x21, \
- struct snd_sst_target_device *)
-/*DSP Ioctls on /dev/intel_sst_ctrl only*/
-#define SNDRV_SST_SET_ALGO _IOW('L', 0x30, struct snd_ppp_params *)
-#define SNDRV_SST_GET_ALGO _IOWR('L', 0x31, struct snd_ppp_params *)
-#define SNDRV_SST_TUNING_PARAMS _IOW('L', 0x32, struct snd_sst_tuning_params *)
-
-#endif /* __INTEL_SST_IOCTL_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_ipc.c b/drivers/staging/intel_sst/intel_sst_ipc.c
deleted file mode 100644
index 5c3444f6ab41..000000000000
--- a/drivers/staging/intel_sst/intel_sst_ipc.c
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * intel_sst_ipc.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corporation
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This file defines all ipc functions
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <linux/sched.h>
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intel_sst_fw_ipc.h"
-#include "intel_sst_common.h"
-
-/*
- * sst_send_sound_card_type - send sound card type
- *
- * this function sends the sound card type to sst dsp engine
- */
-static void sst_send_sound_card_type(void)
-{
- struct ipc_post *msg = NULL;
-
- if (sst_create_short_msg(&msg))
- return;
-
- sst_fill_header(&msg->header, IPC_IA_SET_PMIC_TYPE, 0, 0);
- msg->header.part.data = sst_drv_ctx->pmic_vendor;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- return;
-}
-
-/**
-* sst_post_message - Posts message to SST
-*
-* @work: Pointer to work structure
-*
-* This function is called by any component in driver which
-* wants to send an IPC message. This will post message only if
-* busy bit is free
-*/
-void sst_post_message(struct work_struct *work)
-{
- struct ipc_post *msg;
- union ipc_header header;
- union interrupt_reg imr;
- int retval = 0;
- imr.full = 0;
-
- /*To check if LPE is in stalled state.*/
- retval = sst_stalled();
- if (retval < 0) {
- pr_err("in stalled state\n");
- return;
- }
- pr_debug("post message called\n");
- spin_lock(&sst_drv_ctx->list_spin_lock);
-
- /* check list */
- if (list_empty(&sst_drv_ctx->ipc_dispatch_list)) {
- /* list is empty, mask imr */
- pr_debug("Empty msg queue... masking\n");
- imr.full = readl(sst_drv_ctx->shim + SST_IMRX);
- imr.part.done_interrupt = 1;
- /* dummy register for shim workaround */
- sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- return;
- }
-
- /* check busy bit */
- header.full = sst_shim_read(sst_drv_ctx->shim, SST_IPCX);
- if (header.part.busy) {
- /* busy, unmask */
- pr_debug("Busy not free... unmasking\n");
- imr.full = readl(sst_drv_ctx->shim + SST_IMRX);
- imr.part.done_interrupt = 0;
- /* dummy register for shim workaround */
- sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- return;
- }
- /* copy msg from list */
- msg = list_entry(sst_drv_ctx->ipc_dispatch_list.next,
- struct ipc_post, node);
- list_del(&msg->node);
- pr_debug("Post message: header = %x\n", msg->header.full);
- pr_debug("size: = %x\n", msg->header.part.data);
- if (msg->header.part.large)
- memcpy_toio(sst_drv_ctx->mailbox + SST_MAILBOX_SEND,
- msg->mailbox_data, msg->header.part.data);
- /* dummy register for shim workaround */
-
- sst_shim_write(sst_drv_ctx->shim, SST_IPCX, msg->header.full);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
-
- kfree(msg->mailbox_data);
- kfree(msg);
- return;
-}
-
-/*
- * sst_clear_interrupt - clear the SST FW interrupt
- *
- * This function clears the interrupt register after the interrupt
- * bottom half is complete allowing next interrupt to arrive
- */
-void sst_clear_interrupt(void)
-{
- union interrupt_reg isr;
- union interrupt_reg imr;
- union ipc_header clear_ipc;
-
- imr.full = sst_shim_read(sst_drv_ctx->shim, SST_IMRX);
- isr.full = sst_shim_read(sst_drv_ctx->shim, SST_ISRX);
- /* write 1 to clear */;
- isr.part.busy_interrupt = 1;
- sst_shim_write(sst_drv_ctx->shim, SST_ISRX, isr.full);
- /* Set IA done bit */
- clear_ipc.full = sst_shim_read(sst_drv_ctx->shim, SST_IPCD);
- clear_ipc.part.busy = 0;
- clear_ipc.part.done = 1;
- clear_ipc.part.data = IPC_ACK_SUCCESS;
- sst_shim_write(sst_drv_ctx->shim, SST_IPCD, clear_ipc.full);
- /* un mask busy interrupt */
- imr.part.busy_interrupt = 0;
- sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
-}
-
-void sst_restore_fw_context(void)
-{
- struct snd_sst_ctxt_params fw_context;
- struct ipc_post *msg = NULL;
-
- pr_debug("restore_fw_context\n");
- /*check cpu type*/
- if (sst_drv_ctx->pci_id != SST_MFLD_PCI_ID)
- return;
- /*not supported for rest*/
- if (!sst_drv_ctx->fw_cntx_size)
- return;
- /*nothing to restore*/
- pr_debug("restoring context......\n");
- /*send msg to fw*/
- if (sst_create_large_msg(&msg))
- return;
-
- sst_fill_header(&msg->header, IPC_IA_SET_FW_CTXT, 1, 0);
- msg->header.part.data = sizeof(fw_context) + sizeof(u32);
- fw_context.address = virt_to_phys((void *)sst_drv_ctx->fw_cntx);
- fw_context.size = sst_drv_ctx->fw_cntx_size;
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32),
- &fw_context, sizeof(fw_context));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- return;
-}
-/*
- * process_fw_init - process the FW init msg
- *
- * @msg: IPC message from FW
- *
- * This function processes the FW init msg from FW
- * marks FW state and prints debug info of loaded FW
- */
-int process_fw_init(struct sst_ipc_msg_wq *msg)
-{
- struct ipc_header_fw_init *init =
- (struct ipc_header_fw_init *)msg->mailbox;
- int retval = 0;
-
- pr_debug("*** FW Init msg came***\n");
- if (init->result) {
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_ERROR;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- pr_debug("FW Init failed, Error %x\n", init->result);
- pr_err("FW Init failed, Error %x\n", init->result);
- retval = -init->result;
- return retval;
- }
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
- sst_send_sound_card_type();
- mutex_lock(&sst_drv_ctx->sst_lock);
- sst_drv_ctx->sst_state = SST_FW_RUNNING;
- sst_drv_ctx->lpe_stalled = 0;
- mutex_unlock(&sst_drv_ctx->sst_lock);
- pr_debug("FW Version %02x.%02x.%02x\n", init->fw_version.major,
- init->fw_version.minor, init->fw_version.build);
- pr_debug("Build Type %x\n", init->fw_version.type);
- pr_debug(" Build date %s Time %s\n",
- init->build_info.date, init->build_info.time);
- sst_wake_up_alloc_block(sst_drv_ctx, FW_DWNL_ID, retval, NULL);
- sst_restore_fw_context();
- return retval;
-}
-/**
-* sst_process_message - Processes message from SST
-*
-* @work: Pointer to work structure
-*
-* This function is scheduled by ISR
-* It take a msg from process_queue and does action based on msg
-*/
-void sst_process_message(struct work_struct *work)
-{
- struct sst_ipc_msg_wq *msg =
- container_of(work, struct sst_ipc_msg_wq, wq);
- int str_id = msg->header.part.str_id;
-
- pr_debug("IPC process for %x\n", msg->header.full);
-
- /* based on msg in list call respective handler */
- switch (msg->header.part.msg_id) {
- case IPC_SST_BUF_UNDER_RUN:
- case IPC_SST_BUF_OVER_RUN:
- if (sst_validate_strid(str_id)) {
- pr_err("stream id %d invalid\n", str_id);
- break;
- }
- pr_err("Buffer under/overrun for %d\n",
- msg->header.part.str_id);
- pr_err("Got Underrun & not to send data...ignore\n");
- break;
-
- case IPC_SST_GET_PLAY_FRAMES:
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
- struct stream_info *stream ;
-
- if (sst_validate_strid(str_id)) {
- pr_err("strid %d invalid\n", str_id);
- break;
- }
- /* call sst_play_frame */
- stream = &sst_drv_ctx->streams[str_id];
- pr_debug("sst_play_frames for %d\n",
- msg->header.part.str_id);
- mutex_lock(&sst_drv_ctx->streams[str_id].lock);
- sst_play_frame(msg->header.part.str_id);
- mutex_unlock(&sst_drv_ctx->streams[str_id].lock);
- break;
- } else
- pr_err("sst_play_frames for Penwell!!\n");
-
- case IPC_SST_GET_CAPT_FRAMES:
- if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
- struct stream_info *stream;
- /* call sst_capture_frame */
- if (sst_validate_strid(str_id)) {
- pr_err("str id %d invalid\n", str_id);
- break;
- }
- stream = &sst_drv_ctx->streams[str_id];
- pr_debug("sst_capture_frames for %d\n",
- msg->header.part.str_id);
- mutex_lock(&stream->lock);
- if (stream->mmapped == false &&
- stream->src == SST_DRV) {
- pr_debug("waking up block for copy.\n");
- stream->data_blk.ret_code = 0;
- stream->data_blk.condition = true;
- stream->data_blk.on = false;
- wake_up(&sst_drv_ctx->wait_queue);
- } else
- sst_capture_frame(msg->header.part.str_id);
- mutex_unlock(&stream->lock);
- } else
- pr_err("sst_play_frames for Penwell!!\n");
- break;
-
- case IPC_IA_PRINT_STRING:
- pr_debug("been asked to print something by fw\n");
- /* TBD */
- break;
-
- case IPC_IA_FW_INIT_CMPLT: {
- /* send next data to FW */
- process_fw_init(msg);
- break;
- }
-
- case IPC_SST_STREAM_PROCESS_FATAL_ERR:
- if (sst_validate_strid(str_id)) {
- pr_err("stream id %d invalid\n", str_id);
- break;
- }
- pr_err("codec fatal error %x stream %d...\n",
- msg->header.full, msg->header.part.str_id);
- pr_err("Dropping the stream\n");
- sst_drop_stream(msg->header.part.str_id);
- break;
- case IPC_IA_LPE_GETTING_STALLED:
- sst_drv_ctx->lpe_stalled = 1;
- break;
- case IPC_IA_LPE_UNSTALLED:
- sst_drv_ctx->lpe_stalled = 0;
- break;
- default:
- /* Illegal case */
- pr_err("Unhandled msg %x header %x\n",
- msg->header.part.msg_id, msg->header.full);
- }
- sst_clear_interrupt();
- return;
-}
-
-/**
-* sst_process_reply - Processes reply message from SST
-*
-* @work: Pointer to work structure
-*
-* This function is scheduled by ISR
-* It take a reply msg from response_queue and
-* does action based on msg
-*/
-void sst_process_reply(struct work_struct *work)
-{
- struct sst_ipc_msg_wq *msg =
- container_of(work, struct sst_ipc_msg_wq, wq);
-
- int str_id = msg->header.part.str_id;
- struct stream_info *str_info;
-
- switch (msg->header.part.msg_id) {
- case IPC_IA_TARGET_DEV_SELECT:
- if (!msg->header.part.data) {
- sst_drv_ctx->tgt_dev_blk.ret_code = 0;
- } else {
- pr_err(" Msg %x reply error %x\n",
- msg->header.part.msg_id, msg->header.part.data);
- sst_drv_ctx->tgt_dev_blk.ret_code =
- -msg->header.part.data;
- }
-
- if (sst_drv_ctx->tgt_dev_blk.on == true) {
- sst_drv_ctx->tgt_dev_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- case IPC_IA_ALG_PARAMS: {
- pr_debug("sst:IPC_ALG_PARAMS response %x\n", msg->header.full);
- pr_debug("sst: data value %x\n", msg->header.part.data);
- pr_debug("sst: large value %x\n", msg->header.part.large);
-
- if (!msg->header.part.large) {
- if (!msg->header.part.data) {
- pr_debug("sst: alg set success\n");
- sst_drv_ctx->ppp_params_blk.ret_code = 0;
- } else {
- pr_debug("sst: alg set failed\n");
- sst_drv_ctx->ppp_params_blk.ret_code =
- -msg->header.part.data;
- }
-
- } else if (msg->header.part.data) {
- struct snd_ppp_params *mailbox_params, *get_params;
- char *params;
-
- pr_debug("sst: alg get success\n");
- mailbox_params = (struct snd_ppp_params *)msg->mailbox;
- get_params = kzalloc(sizeof(*get_params), GFP_KERNEL);
- if (get_params == NULL) {
- pr_err("sst: out of memory for ALG PARAMS");
- break;
- }
- memcpy_fromio(get_params, mailbox_params,
- sizeof(*get_params));
- get_params->params = kzalloc(mailbox_params->size,
- GFP_KERNEL);
- if (get_params->params == NULL) {
- kfree(get_params);
- pr_err("sst: out of memory for ALG PARAMS block");
- break;
- }
- params = msg->mailbox;
- params = params + sizeof(*mailbox_params) - sizeof(u32);
- memcpy_fromio(get_params->params, params,
- get_params->size);
- sst_drv_ctx->ppp_params_blk.ret_code = 0;
- sst_drv_ctx->ppp_params_blk.data = get_params;
- }
-
- if (sst_drv_ctx->ppp_params_blk.on == true) {
- sst_drv_ctx->ppp_params_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- }
-
- case IPC_IA_TUNING_PARAMS: {
- pr_debug("sst:IPC_TUNING_PARAMS resp: %x\n", msg->header.full);
- pr_debug("data value %x\n", msg->header.part.data);
- if (msg->header.part.large) {
- pr_debug("alg set failed\n");
- sst_drv_ctx->ppp_params_blk.ret_code =
- -msg->header.part.data;
- } else {
- pr_debug("alg set success\n");
- sst_drv_ctx->ppp_params_blk.ret_code = 0;
- }
- if (sst_drv_ctx->ppp_params_blk.on == true) {
- sst_drv_ctx->ppp_params_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- }
-
- case IPC_IA_GET_FW_INFO: {
- struct snd_sst_fw_info *fw_info =
- (struct snd_sst_fw_info *)msg->mailbox;
- if (msg->header.part.large) {
- int major = fw_info->fw_version.major;
- int minor = fw_info->fw_version.minor;
- int build = fw_info->fw_version.build;
- pr_debug("Msg succeeded %x\n",
- msg->header.part.msg_id);
- pr_debug("INFO: ***FW*** = %02d.%02d.%02d\n",
- major, minor, build);
- memcpy_fromio(sst_drv_ctx->fw_info_blk.data,
- ((struct snd_sst_fw_info *)(msg->mailbox)),
- sizeof(struct snd_sst_fw_info));
- sst_drv_ctx->fw_info_blk.ret_code = 0;
- } else {
- pr_err(" Msg %x reply error %x\n",
- msg->header.part.msg_id, msg->header.part.data);
- sst_drv_ctx->fw_info_blk.ret_code =
- -msg->header.part.data;
- }
- if (sst_drv_ctx->fw_info_blk.on == true) {
- pr_debug("Memcopy succeeded\n");
- sst_drv_ctx->fw_info_blk.on = false;
- sst_drv_ctx->fw_info_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- }
- case IPC_IA_SET_STREAM_MUTE:
- if (!msg->header.part.data) {
- pr_debug("Msg succeeded %x\n",
- msg->header.part.msg_id);
- sst_drv_ctx->mute_info_blk.ret_code = 0;
- } else {
- pr_err(" Msg %x reply error %x\n",
- msg->header.part.msg_id, msg->header.part.data);
- sst_drv_ctx->mute_info_blk.ret_code =
- -msg->header.part.data;
-
- }
- if (sst_drv_ctx->mute_info_blk.on == true) {
- sst_drv_ctx->mute_info_blk.on = false;
- sst_drv_ctx->mute_info_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- case IPC_IA_SET_STREAM_VOL:
- if (!msg->header.part.data) {
- pr_debug("Msg succeeded %x\n",
- msg->header.part.msg_id);
- sst_drv_ctx->vol_info_blk.ret_code = 0;
- } else {
- pr_err(" Msg %x reply error %x\n",
- msg->header.part.msg_id,
- msg->header.part.data);
- sst_drv_ctx->vol_info_blk.ret_code =
- -msg->header.part.data;
-
- }
-
- if (sst_drv_ctx->vol_info_blk.on == true) {
- sst_drv_ctx->vol_info_blk.on = false;
- sst_drv_ctx->vol_info_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- case IPC_IA_GET_STREAM_VOL:
- if (msg->header.part.large) {
- pr_debug("Large Msg Received Successfully\n");
- pr_debug("Msg succeeded %x\n",
- msg->header.part.msg_id);
- memcpy_fromio(sst_drv_ctx->vol_info_blk.data,
- (void *) msg->mailbox,
- sizeof(struct snd_sst_vol));
- sst_drv_ctx->vol_info_blk.ret_code = 0;
- } else {
- pr_err("Msg %x reply error %x\n",
- msg->header.part.msg_id, msg->header.part.data);
- sst_drv_ctx->vol_info_blk.ret_code =
- -msg->header.part.data;
- }
- if (sst_drv_ctx->vol_info_blk.on == true) {
- sst_drv_ctx->vol_info_blk.on = false;
- sst_drv_ctx->vol_info_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
-
- case IPC_IA_GET_STREAM_PARAMS:
- if (sst_validate_strid(str_id)) {
- pr_err("stream id %d invalid\n", str_id);
- break;
- }
- str_info = &sst_drv_ctx->streams[str_id];
- if (msg->header.part.large) {
- pr_debug("Get stream large success\n");
- memcpy_fromio(str_info->ctrl_blk.data,
- ((void *)(msg->mailbox)),
- sizeof(struct snd_sst_fw_get_stream_params));
- str_info->ctrl_blk.ret_code = 0;
- } else {
- pr_err("Msg %x reply error %x\n",
- msg->header.part.msg_id, msg->header.part.data);
- str_info->ctrl_blk.ret_code = -msg->header.part.data;
- }
- if (str_info->ctrl_blk.on == true) {
- str_info->ctrl_blk.on = false;
- str_info->ctrl_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- case IPC_IA_DECODE_FRAMES:
- if (sst_validate_strid(str_id)) {
- pr_err("stream id %d invalid\n", str_id);
- break;
- }
- str_info = &sst_drv_ctx->streams[str_id];
- if (msg->header.part.large) {
- pr_debug("Msg succeeded %x\n",
- msg->header.part.msg_id);
- memcpy_fromio(str_info->data_blk.data,
- ((void *)(msg->mailbox)),
- sizeof(struct snd_sst_decode_info));
- str_info->data_blk.ret_code = 0;
- } else {
- pr_err("Msg %x reply error %x\n",
- msg->header.part.msg_id, msg->header.part.data);
- str_info->data_blk.ret_code = -msg->header.part.data;
- }
- if (str_info->data_blk.on == true) {
- str_info->data_blk.on = false;
- str_info->data_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- case IPC_IA_DRAIN_STREAM:
- if (sst_validate_strid(str_id)) {
- pr_err("stream id %d invalid\n", str_id);
- break;
- }
- str_info = &sst_drv_ctx->streams[str_id];
- if (!msg->header.part.data) {
- pr_debug("Msg succeeded %x\n",
- msg->header.part.msg_id);
- str_info->ctrl_blk.ret_code = 0;
-
- } else {
- pr_err(" Msg %x reply error %x\n",
- msg->header.part.msg_id, msg->header.part.data);
- str_info->ctrl_blk.ret_code = -msg->header.part.data;
-
- }
- str_info = &sst_drv_ctx->streams[str_id];
- if (str_info->data_blk.on == true) {
- str_info->data_blk.on = false;
- str_info->data_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
-
- case IPC_IA_DROP_STREAM:
- if (sst_validate_strid(str_id)) {
- pr_err("str id %d invalid\n", str_id);
- break;
- }
- str_info = &sst_drv_ctx->streams[str_id];
- if (msg->header.part.large) {
- struct snd_sst_drop_response *drop_resp =
- (struct snd_sst_drop_response *)msg->mailbox;
-
- pr_debug("Drop ret bytes %x\n", drop_resp->bytes);
-
- str_info->curr_bytes = drop_resp->bytes;
- str_info->ctrl_blk.ret_code = 0;
- } else {
- pr_err(" Msg %x reply error %x\n",
- msg->header.part.msg_id, msg->header.part.data);
- str_info->ctrl_blk.ret_code = -msg->header.part.data;
- }
- if (str_info->ctrl_blk.on == true) {
- str_info->ctrl_blk.on = false;
- str_info->ctrl_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- case IPC_IA_ENABLE_RX_TIME_SLOT:
- if (!msg->header.part.data) {
- pr_debug("RX_TIME_SLOT success\n");
- sst_drv_ctx->hs_info_blk.ret_code = 0;
- } else {
- pr_err(" Msg %x reply error %x\n",
- msg->header.part.msg_id,
- msg->header.part.data);
- sst_drv_ctx->hs_info_blk.ret_code =
- -msg->header.part.data;
- }
- if (sst_drv_ctx->hs_info_blk.on == true) {
- sst_drv_ctx->hs_info_blk.on = false;
- sst_drv_ctx->hs_info_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- case IPC_IA_PAUSE_STREAM:
- case IPC_IA_RESUME_STREAM:
- case IPC_IA_SET_STREAM_PARAMS:
- str_info = &sst_drv_ctx->streams[str_id];
- if (!msg->header.part.data) {
- pr_debug("Msg succeeded %x\n",
- msg->header.part.msg_id);
- str_info->ctrl_blk.ret_code = 0;
- } else {
- pr_err(" Msg %x reply error %x\n",
- msg->header.part.msg_id,
- msg->header.part.data);
- str_info->ctrl_blk.ret_code = -msg->header.part.data;
- }
- if (sst_validate_strid(str_id)) {
- pr_err(" stream id %d invalid\n", str_id);
- break;
- }
-
- if (str_info->ctrl_blk.on == true) {
- str_info->ctrl_blk.on = false;
- str_info->ctrl_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
-
- case IPC_IA_FREE_STREAM:
- str_info = &sst_drv_ctx->streams[str_id];
- if (!msg->header.part.data) {
- pr_debug("Stream %d freed\n", str_id);
- } else {
- pr_err("Free for %d ret error %x\n",
- str_id, msg->header.part.data);
- }
- if (str_info->ctrl_blk.on == true) {
- str_info->ctrl_blk.on = false;
- str_info->ctrl_blk.condition = true;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- break;
- case IPC_IA_ALLOC_STREAM: {
- /* map to stream, call play */
- struct snd_sst_alloc_response *resp =
- (struct snd_sst_alloc_response *)msg->mailbox;
- if (resp->str_type.result)
- pr_err("error alloc stream = %x\n",
- resp->str_type.result);
- sst_alloc_stream_response(str_id, resp);
- break;
- }
-
- case IPC_IA_PLAY_FRAMES:
- case IPC_IA_CAPT_FRAMES:
- if (sst_validate_strid(str_id)) {
- pr_err("stream id %d invalid\n", str_id);
- break;
- }
- pr_debug("Ack for play/capt frames received\n");
- break;
-
- case IPC_IA_PREP_LIB_DNLD: {
- struct snd_sst_str_type *str_type =
- (struct snd_sst_str_type *)msg->mailbox;
- pr_debug("Prep Lib download %x\n",
- msg->header.part.msg_id);
- if (str_type->result)
- pr_err("Prep lib download %x\n", str_type->result);
- else
- pr_debug("Can download codec now...\n");
- sst_wake_up_alloc_block(sst_drv_ctx, str_id,
- str_type->result, NULL);
- break;
- }
-
- case IPC_IA_LIB_DNLD_CMPLT: {
- struct snd_sst_lib_download_info *resp =
- (struct snd_sst_lib_download_info *)msg->mailbox;
- int retval = resp->result;
-
- pr_debug("Lib downloaded %x\n", msg->header.part.msg_id);
- if (resp->result) {
- pr_err("err in lib dload %x\n", resp->result);
- } else {
- pr_debug("Codec download complete...\n");
- pr_debug("codec Type %d Ver %d Built %s: %s\n",
- resp->dload_lib.lib_info.lib_type,
- resp->dload_lib.lib_info.lib_version,
- resp->dload_lib.lib_info.b_date,
- resp->dload_lib.lib_info.b_time);
- }
- sst_wake_up_alloc_block(sst_drv_ctx, str_id,
- retval, NULL);
- break;
- }
-
- case IPC_IA_GET_FW_VERSION: {
- struct ipc_header_fw_init *version =
- (struct ipc_header_fw_init *)msg->mailbox;
- int major = version->fw_version.major;
- int minor = version->fw_version.minor;
- int build = version->fw_version.build;
- dev_info(&sst_drv_ctx->pci->dev,
- "INFO: ***LOADED SST FW VERSION*** = %02d.%02d.%02d\n",
- major, minor, build);
- break;
- }
- case IPC_IA_GET_FW_BUILD_INF: {
- struct sst_fw_build_info *build =
- (struct sst_fw_build_info *)msg->mailbox;
- pr_debug("Build date:%sTime:%s", build->date, build->time);
- break;
- }
- case IPC_IA_SET_PMIC_TYPE:
- break;
- case IPC_IA_START_STREAM:
- pr_debug("reply for START STREAM %x\n", msg->header.full);
- break;
-
- case IPC_IA_GET_FW_CTXT:
- pr_debug("reply for get fw ctxt %x\n", msg->header.full);
- if (msg->header.part.data)
- sst_drv_ctx->fw_cntx_size = 0;
- else
- sst_drv_ctx->fw_cntx_size = *sst_drv_ctx->fw_cntx;
- pr_debug("fw copied data %x\n", sst_drv_ctx->fw_cntx_size);
- sst_wake_up_alloc_block(
- sst_drv_ctx, str_id, msg->header.part.data, NULL);
- break;
- default:
- /* Illegal case */
- pr_err("process reply:default = %x\n", msg->header.full);
- }
- sst_clear_interrupt();
- return;
-}
diff --git a/drivers/staging/intel_sst/intel_sst_pvt.c b/drivers/staging/intel_sst/intel_sst_pvt.c
deleted file mode 100644
index e034bea56f14..000000000000
--- a/drivers/staging/intel_sst/intel_sst_pvt.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * intel_sst_pvt.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This driver exposes the audio engine functionalities to the ALSA
- * and middleware.
- *
- * This file contains all private functions
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/firmware.h>
-#include <linux/sched.h>
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intel_sst_fw_ipc.h"
-#include "intel_sst_common.h"
-
-/*
- * sst_get_block_stream - get a new block stream
- *
- * @sst_drv_ctx: Driver context structure
- *
- * This function assigns a block for the calls that dont have stream context yet
- * the blocks are used for waiting on Firmware's response for any operation
- * Should be called with stream lock held
- */
-int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx)
-{
- int i;
-
- for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
- if (sst_drv_ctx->alloc_block[i].sst_id == BLOCK_UNINIT) {
- sst_drv_ctx->alloc_block[i].ops_block.condition = false;
- sst_drv_ctx->alloc_block[i].ops_block.ret_code = 0;
- sst_drv_ctx->alloc_block[i].sst_id = 0;
- break;
- }
- }
- if (i == MAX_ACTIVE_STREAM) {
- pr_err("max alloc_stream reached\n");
- i = -EBUSY; /* active stream limit reached */
- }
- return i;
-}
-
-/*
- * sst_wait_interruptible - wait on event
- *
- * @sst_drv_ctx: Driver context
- * @block: Driver block to wait on
- *
- * This function waits without a timeout (and is interruptable) for a
- * given block event
- */
-int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
- struct sst_block *block)
-{
- int retval = 0;
-
- if (!wait_event_interruptible(sst_drv_ctx->wait_queue,
- block->condition)) {
- /* event wake */
- if (block->ret_code < 0) {
- pr_err("stream failed %d\n", block->ret_code);
- retval = -EBUSY;
- } else {
- pr_debug("event up\n");
- retval = 0;
- }
- } else {
- pr_err("signal interrupted\n");
- retval = -EINTR;
- }
- return retval;
-
-}
-
-
-/*
- * sst_wait_interruptible_timeout - wait on event interruptable
- *
- * @sst_drv_ctx: Driver context
- * @block: Driver block to wait on
- * @timeout: time for wait on
- *
- * This function waits with a timeout value (and is interruptible) on a
- * given block event
- */
-int sst_wait_interruptible_timeout(
- struct intel_sst_drv *sst_drv_ctx,
- struct sst_block *block, int timeout)
-{
- int retval = 0;
-
- pr_debug("sst_wait_interruptible_timeout - waiting....\n");
- if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue,
- block->condition,
- msecs_to_jiffies(timeout))) {
- if (block->ret_code < 0)
- pr_err("stream failed %d\n", block->ret_code);
- else
- pr_debug("event up\n");
- retval = block->ret_code;
- } else {
- block->on = false;
- pr_err("timeout occurred...\n");
- /*setting firmware state as uninit so that the
- firmware will get re-downloaded on next request
- this is because firmare not responding for 5 sec
- is equalant to some unrecoverable error of FW
- sst_drv_ctx->sst_state = SST_UN_INIT;*/
- retval = -EBUSY;
- }
- return retval;
-
-}
-
-
-/*
- * sst_wait_timeout - wait on event for timeout
- *
- * @sst_drv_ctx: Driver context
- * @block: Driver block to wait on
- *
- * This function waits with a timeout value (and is not interruptible) on a
- * given block event
- */
-int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx,
- struct stream_alloc_block *block)
-{
- int retval = 0;
-
- /* NOTE:
- Observed that FW processes the alloc msg and replies even
- before the alloc thread has finished execution */
- pr_debug("waiting for %x, condition %x\n",
- block->sst_id, block->ops_block.condition);
- if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue,
- block->ops_block.condition,
- msecs_to_jiffies(SST_BLOCK_TIMEOUT))) {
- /* event wake */
- pr_debug("Event wake %x\n", block->ops_block.condition);
- pr_debug("message ret: %d\n", block->ops_block.ret_code);
- retval = block->ops_block.ret_code;
- } else {
- block->ops_block.on = false;
- pr_err("Wait timed-out %x\n", block->ops_block.condition);
- /* settign firmware state as uninit so that the
- firmware will get redownloaded on next request
- this is because firmare not responding for 5 sec
- is equalant to some unrecoverable error of FW
- sst_drv_ctx->sst_state = SST_UN_INIT;*/
- retval = -EBUSY;
- }
- return retval;
-
-}
-
-/*
- * sst_create_large_msg - create a large IPC message
- *
- * @arg: ipc message
- *
- * this function allocates structures to send a large message to the firmware
- */
-int sst_create_large_msg(struct ipc_post **arg)
-{
- struct ipc_post *msg;
-
- msg = kzalloc(sizeof(struct ipc_post), GFP_ATOMIC);
- if (!msg) {
- pr_err("kzalloc msg failed\n");
- return -ENOMEM;
- }
-
- msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC);
- if (!msg->mailbox_data) {
- kfree(msg);
- pr_err("kzalloc mailbox_data failed");
- return -ENOMEM;
- }
- *arg = msg;
- return 0;
-}
-
-/*
- * sst_create_short_msg - create a short IPC message
- *
- * @arg: ipc message
- *
- * this function allocates structures to send a short message to the firmware
- */
-int sst_create_short_msg(struct ipc_post **arg)
-{
- struct ipc_post *msg;
-
- msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
- if (!msg) {
- pr_err("kzalloc msg failed\n");
- return -ENOMEM;
- }
- msg->mailbox_data = NULL;
- *arg = msg;
- return 0;
-}
-
-/*
- * sst_clean_stream - clean the stream context
- *
- * @stream: stream structure
- *
- * this function resets the stream contexts
- * should be called in free
- */
-void sst_clean_stream(struct stream_info *stream)
-{
- struct sst_stream_bufs *bufs = NULL, *_bufs;
- stream->status = STREAM_UN_INIT;
- stream->prev = STREAM_UN_INIT;
- mutex_lock(&stream->lock);
- list_for_each_entry_safe(bufs, _bufs, &stream->bufs, node) {
- list_del(&bufs->node);
- kfree(bufs);
- }
- mutex_unlock(&stream->lock);
-
- if (stream->ops != STREAM_OPS_PLAYBACK_DRM)
- kfree(stream->decode_ibuf);
-}
-
-/*
- * sst_wake_up_alloc_block - wake up waiting block
- *
- * @sst_drv_ctx: Driver context
- * @sst_id: stream id
- * @status: status of wakeup
- * @data: data pointer of wakeup
- *
- * This function wakes up a sleeping block event based on the response
- */
-void sst_wake_up_alloc_block(struct intel_sst_drv *sst_drv_ctx,
- u8 sst_id, int status, void *data)
-{
- int i;
-
- /* Unblock with retval code */
- for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
- if (sst_id == sst_drv_ctx->alloc_block[i].sst_id) {
- sst_drv_ctx->alloc_block[i].ops_block.condition = true;
- sst_drv_ctx->alloc_block[i].ops_block.ret_code = status;
- sst_drv_ctx->alloc_block[i].ops_block.data = data;
- wake_up(&sst_drv_ctx->wait_queue);
- break;
- }
- }
-}
-
-/*
- * sst_enable_rx_timeslot - Send msg to query for stream parameters
- * @status: rx timeslot to be enabled
- *
- * This function is called when the RX timeslot is required to be enabled
- */
-int sst_enable_rx_timeslot(int status)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
-
- if (sst_create_short_msg(&msg)) {
- pr_err("mem allocation failed\n");
- return -ENOMEM;
- }
- pr_debug("ipc message sending: ENABLE_RX_TIME_SLOT\n");
- sst_fill_header(&msg->header, IPC_IA_ENABLE_RX_TIME_SLOT, 0, 0);
- msg->header.part.data = status;
- sst_drv_ctx->hs_info_blk.condition = false;
- sst_drv_ctx->hs_info_blk.ret_code = 0;
- sst_drv_ctx->hs_info_blk.on = true;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node,
- &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &sst_drv_ctx->hs_info_blk, SST_BLOCK_TIMEOUT);
- return retval;
-}
-
diff --git a/drivers/staging/intel_sst/intel_sst_stream.c b/drivers/staging/intel_sst/intel_sst_stream.c
deleted file mode 100644
index be4565e74f8c..000000000000
--- a/drivers/staging/intel_sst/intel_sst_stream.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- * intel_sst_stream.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This file contains the stream operations of SST driver
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include "intel_sst_ioctl.h"
-#include "intel_sst.h"
-#include "intel_sst_fw_ipc.h"
-#include "intel_sst_common.h"
-
-/*
- * sst_check_device_type - Check the medfield device type
- *
- * @device: Device to be checked
- * @num_ch: Number of channels queried
- * @pcm_slot: slot to be enabled for this device
- *
- * This checks the deivce against the map and calculates pcm_slot value
- */
-int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot)
-{
- if (device >= MAX_NUM_STREAMS_MFLD) {
- pr_debug("device type invalid %d\n", device);
- return -EINVAL;
- }
- if (sst_drv_ctx->streams[device].status == STREAM_UN_INIT) {
- if (device == SND_SST_DEVICE_VIBRA && num_chan == 1)
- *pcm_slot = 0x10;
- else if (device == SND_SST_DEVICE_HAPTIC && num_chan == 1)
- *pcm_slot = 0x20;
- else if (device == SND_SST_DEVICE_IHF && num_chan == 1)
- *pcm_slot = 0x04;
- else if (device == SND_SST_DEVICE_IHF && num_chan == 2)
- *pcm_slot = 0x0C;
- else if (device == SND_SST_DEVICE_HEADSET && num_chan == 1)
- *pcm_slot = 0x01;
- else if (device == SND_SST_DEVICE_HEADSET && num_chan == 2)
- *pcm_slot = 0x03;
- else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 1)
- *pcm_slot = 0x01;
- else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 2)
- *pcm_slot = 0x03;
- else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 3)
- *pcm_slot = 0x07;
- else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 4)
- *pcm_slot = 0x0F;
- else if (device == SND_SST_DEVICE_CAPTURE && num_chan > 4)
- *pcm_slot = 0x1F;
- else {
- pr_debug("No condition satisfied.. ret err\n");
- return -EINVAL;
- }
- } else {
- pr_debug("this stream state is not uni-init, is %d\n",
- sst_drv_ctx->streams[device].status);
- return -EBADRQC;
- }
- pr_debug("returning slot %x\n", *pcm_slot);
- return 0;
-}
-/**
- * get_mrst_stream_id - gets a new stream id for use
- *
- * This functions searches the current streams and allocated an empty stream
- * lock stream_lock required to be held before calling this
- */
-static unsigned int get_mrst_stream_id(void)
-{
- int i;
-
- for (i = 1; i <= MAX_NUM_STREAMS_MRST; i++) {
- if (sst_drv_ctx->streams[i].status == STREAM_UN_INIT)
- return i;
- }
- pr_debug("Didn't find empty stream for mrst\n");
- return -EBUSY;
-}
-
-/**
- * sst_alloc_stream - Send msg for a new stream ID
- *
- * @params: stream params
- * @stream_ops: operation of stream PB/capture
- * @codec: codec for stream
- * @device: device stream to be allocated for
- *
- * This function is called by any function which wants to start
- * a new stream. This also check if a stream exists which is idle
- * it initializes idle stream id to this request
- */
-int sst_alloc_stream(char *params, unsigned int stream_ops,
- u8 codec, unsigned int device)
-{
- struct ipc_post *msg = NULL;
- struct snd_sst_alloc_params alloc_param;
- unsigned int pcm_slot = 0, num_ch;
- int str_id;
- struct snd_sst_stream_params *sparams;
- struct stream_info *str_info;
-
- pr_debug("SST DBG:entering sst_alloc_stream\n");
- pr_debug("SST DBG:%d %d %d\n", stream_ops, codec, device);
-
- BUG_ON(!params);
- sparams = (struct snd_sst_stream_params *)params;
- num_ch = sparams->uc.pcm_params.num_chan;
- /*check the device type*/
- if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID) {
- if (sst_check_device_type(device, num_ch, &pcm_slot))
- return -EINVAL;
- mutex_lock(&sst_drv_ctx->stream_lock);
- str_id = device;
- mutex_unlock(&sst_drv_ctx->stream_lock);
- pr_debug("SST_DBG: slot %x\n", pcm_slot);
- } else {
- mutex_lock(&sst_drv_ctx->stream_lock);
- str_id = get_mrst_stream_id();
- mutex_unlock(&sst_drv_ctx->stream_lock);
- if (str_id <= 0)
- return -EBUSY;
- }
- /*allocate device type context*/
- sst_init_stream(&sst_drv_ctx->streams[str_id], codec,
- str_id, stream_ops, pcm_slot, device);
- /* send msg to FW to allocate a stream */
- if (sst_create_large_msg(&msg))
- return -ENOMEM;
-
- sst_fill_header(&msg->header, IPC_IA_ALLOC_STREAM, 1, str_id);
- msg->header.part.data = sizeof(alloc_param) + sizeof(u32);
- alloc_param.str_type.codec_type = codec;
- alloc_param.str_type.str_type = SST_STREAM_TYPE_MUSIC;
- alloc_param.str_type.operation = stream_ops;
- alloc_param.str_type.protected_str = 0; /* non drm */
- alloc_param.str_type.time_slots = pcm_slot;
- alloc_param.str_type.result = alloc_param.str_type.reserved = 0;
- memcpy(&alloc_param.stream_params, params,
- sizeof(struct snd_sst_stream_params));
-
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), &alloc_param,
- sizeof(alloc_param));
- str_info = &sst_drv_ctx->streams[str_id];
- str_info->ctrl_blk.condition = false;
- str_info->ctrl_blk.ret_code = 0;
- str_info->ctrl_blk.on = true;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- pr_debug("SST DBG:alloc stream done\n");
- return str_id;
-}
-
-
-/*
- * sst_alloc_stream_response - process alloc reply
- *
- * @str_id: stream id for which the stream has been allocated
- * @resp the stream response from firware
- *
- * This function is called by firmware as a response to stream allcoation
- * request
- */
-int sst_alloc_stream_response(unsigned int str_id,
- struct snd_sst_alloc_response *resp)
-{
- int retval = 0;
- struct stream_info *str_info;
- struct snd_sst_lib_download *lib_dnld;
-
- pr_debug("SST DEBUG: stream number given = %d\n", str_id);
- str_info = &sst_drv_ctx->streams[str_id];
- if (resp->str_type.result == SST_LIB_ERR_LIB_DNLD_REQUIRED) {
- lib_dnld = kzalloc(sizeof(*lib_dnld), GFP_KERNEL);
- memcpy(lib_dnld, &resp->lib_dnld, sizeof(*lib_dnld));
- } else
- lib_dnld = NULL;
- if (str_info->ctrl_blk.on == true) {
- str_info->ctrl_blk.on = false;
- str_info->ctrl_blk.data = lib_dnld;
- str_info->ctrl_blk.condition = true;
- str_info->ctrl_blk.ret_code = resp->str_type.result;
- pr_debug("SST DEBUG: sst_alloc_stream_response: waking up.\n");
- wake_up(&sst_drv_ctx->wait_queue);
- }
- return retval;
-}
-
-
-/**
-* sst_get_fw_info - Send msg to query for firmware configurations
-* @info: out param that holds the firmare configurations
-*
-* This function is called when the firmware configurations are queiried for
-*/
-int sst_get_fw_info(struct snd_sst_fw_info *info)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
-
- pr_debug("SST DBG:sst_get_fw_info called\n");
-
- if (sst_create_short_msg(&msg)) {
- pr_err("SST ERR: message creation failed\n");
- return -ENOMEM;
- }
-
- sst_fill_header(&msg->header, IPC_IA_GET_FW_INFO, 0, 0);
- sst_drv_ctx->fw_info_blk.condition = false;
- sst_drv_ctx->fw_info_blk.ret_code = 0;
- sst_drv_ctx->fw_info_blk.on = true;
- sst_drv_ctx->fw_info_blk.data = info;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &sst_drv_ctx->fw_info_blk, SST_BLOCK_TIMEOUT);
- if (retval) {
- pr_err("SST ERR: error in fw_info = %d\n", retval);
- retval = -EIO;
- }
- return retval;
-}
-
-
-/**
-* sst_pause_stream - Send msg for a pausing stream
-* @str_id: stream ID
-*
-* This function is called by any function which wants to pause
-* an already running stream.
-*/
-int sst_start_stream(int str_id)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
- struct stream_info *str_info;
-
- pr_debug("sst_start_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
- if (str_info->status != STREAM_INIT)
- return -EBADRQC;
- if (sst_create_short_msg(&msg))
- return -ENOMEM;
-
- sst_fill_header(&msg->header, IPC_IA_START_STREAM, 0, str_id);
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- return retval;
-}
-
-/*
- * sst_pause_stream - Send msg for a pausing stream
- * @str_id: stream ID
- *
- * This function is called by any function which wants to pause
- * an already running stream.
- */
-int sst_pause_stream(int str_id)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
- struct stream_info *str_info;
-
- pr_debug("SST DBG:sst_pause_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
- if (str_info->status == STREAM_PAUSED)
- return 0;
- if (str_info->status == STREAM_RUNNING ||
- str_info->status == STREAM_INIT) {
- if (str_info->prev == STREAM_UN_INIT)
- return -EBADRQC;
- if (str_info->ctrl_blk.on == true) {
- pr_err("SST ERR: control path is in use\n");
- return -EINVAL;
- }
- if (sst_create_short_msg(&msg))
- return -ENOMEM;
-
- sst_fill_header(&msg->header, IPC_IA_PAUSE_STREAM, 0, str_id);
- str_info->ctrl_blk.condition = false;
- str_info->ctrl_blk.ret_code = 0;
- str_info->ctrl_blk.on = true;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node,
- &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
- if (retval == 0) {
- str_info->prev = str_info->status;
- str_info->status = STREAM_PAUSED;
- } else if (retval == SST_ERR_INVALID_STREAM_ID) {
- retval = -EINVAL;
- mutex_lock(&sst_drv_ctx->stream_lock);
- sst_clean_stream(str_info);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- }
- } else {
- retval = -EBADRQC;
- pr_err("SST ERR: BADQRC for stream\n");
- }
-
- return retval;
-}
-
-/**
- * sst_resume_stream - Send msg for resuming stream
- * @str_id: stream ID
- *
- * This function is called by any function which wants to resume
- * an already paused stream.
- */
-int sst_resume_stream(int str_id)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
- struct stream_info *str_info;
-
- pr_debug("SST DBG:sst_resume_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
- if (str_info->status == STREAM_RUNNING)
- return 0;
- if (str_info->status == STREAM_PAUSED) {
- if (str_info->ctrl_blk.on == true) {
- pr_err("SST ERR: control path in use\n");
- return -EINVAL;
- }
- if (sst_create_short_msg(&msg)) {
- pr_err("SST ERR: mem allocation failed\n");
- return -ENOMEM;
- }
- sst_fill_header(&msg->header, IPC_IA_RESUME_STREAM, 0, str_id);
- str_info->ctrl_blk.condition = false;
- str_info->ctrl_blk.ret_code = 0;
- str_info->ctrl_blk.on = true;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node,
- &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
- if (!retval) {
- if (str_info->prev == STREAM_RUNNING)
- str_info->status = STREAM_RUNNING;
- else
- str_info->status = STREAM_INIT;
- str_info->prev = STREAM_PAUSED;
- } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
- retval = -EINVAL;
- mutex_lock(&sst_drv_ctx->stream_lock);
- sst_clean_stream(str_info);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- }
- } else {
- retval = -EBADRQC;
- pr_err("SST ERR: BADQRC for stream\n");
- }
-
- return retval;
-}
-
-
-/**
- * sst_drop_stream - Send msg for stopping stream
- * @str_id: stream ID
- *
- * This function is called by any function which wants to stop
- * a stream.
- */
-int sst_drop_stream(int str_id)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
- struct sst_stream_bufs *bufs = NULL, *_bufs;
- struct stream_info *str_info;
-
- pr_debug("SST DBG:sst_drop_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
-
- if (str_info->status != STREAM_UN_INIT &&
- str_info->status != STREAM_DECODE) {
- if (str_info->ctrl_blk.on == true) {
- pr_err("SST ERR: control path in use\n");
- return -EINVAL;
- }
- if (sst_create_short_msg(&msg)) {
- pr_err("SST ERR: mem allocation failed\n");
- return -ENOMEM;
- }
- sst_fill_header(&msg->header, IPC_IA_DROP_STREAM, 0, str_id);
- str_info->ctrl_blk.condition = false;
- str_info->ctrl_blk.ret_code = 0;
- str_info->ctrl_blk.on = true;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node,
- &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
- if (!retval) {
- pr_debug("SST DBG:drop success\n");
- str_info->prev = STREAM_UN_INIT;
- str_info->status = STREAM_INIT;
- if (str_info->src != MAD_DRV) {
- mutex_lock(&str_info->lock);
- list_for_each_entry_safe(bufs, _bufs,
- &str_info->bufs, node) {
- list_del(&bufs->node);
- kfree(bufs);
- }
- mutex_unlock(&str_info->lock);
- }
- str_info->cumm_bytes += str_info->curr_bytes;
- } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
- retval = -EINVAL;
- mutex_lock(&sst_drv_ctx->stream_lock);
- sst_clean_stream(str_info);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- }
- if (str_info->data_blk.on == true) {
- str_info->data_blk.condition = true;
- str_info->data_blk.ret_code = retval;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- } else {
- retval = -EBADRQC;
- pr_err("SST ERR: BADQRC for stream\n");
- }
- return retval;
-}
-
-/**
-* sst_drain_stream - Send msg for draining stream
-* @str_id: stream ID
-*
-* This function is called by any function which wants to drain
-* a stream.
-*/
-int sst_drain_stream(int str_id)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
- struct stream_info *str_info;
-
- pr_debug("SST DBG:sst_drain_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
-
- if (str_info->status != STREAM_RUNNING &&
- str_info->status != STREAM_INIT &&
- str_info->status != STREAM_PAUSED) {
- pr_err("SST ERR: BADQRC for stream = %d\n",
- str_info->status);
- return -EBADRQC;
- }
-
- if (str_info->status == STREAM_INIT) {
- if (sst_create_short_msg(&msg)) {
- pr_err("SST ERR: mem allocation failed\n");
- return -ENOMEM;
- }
- sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM, 0, str_id);
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- } else
- str_info->need_draining = true;
- str_info->data_blk.condition = false;
- str_info->data_blk.ret_code = 0;
- str_info->data_blk.on = true;
- retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk);
- str_info->need_draining = false;
- return retval;
-}
-
-/**
- * sst_free_stream - Frees a stream
- * @str_id: stream ID
- *
- * This function is called by any function which wants to free
- * a stream.
- */
-int sst_free_stream(int str_id)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
- struct stream_info *str_info;
-
- pr_debug("SST DBG:sst_free_stream for %d\n", str_id);
-
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
-
- if (str_info->status != STREAM_UN_INIT) {
- if (sst_create_short_msg(&msg)) {
- pr_err("SST ERR: mem allocation failed\n");
- return -ENOMEM;
- }
- sst_fill_header(&msg->header, IPC_IA_FREE_STREAM, 0, str_id);
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- str_info->prev = str_info->status;
- str_info->status = STREAM_UN_INIT;
- if (str_info->data_blk.on == true) {
- str_info->data_blk.condition = true;
- str_info->data_blk.ret_code = 0;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- str_info->data_blk.on = true;
- str_info->data_blk.condition = false;
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
- pr_debug("wait for free returned %d\n", retval);
- msleep(100);
- mutex_lock(&sst_drv_ctx->stream_lock);
- sst_clean_stream(str_info);
- mutex_unlock(&sst_drv_ctx->stream_lock);
- pr_debug("SST DBG:Stream freed\n");
- } else {
- retval = -EBADRQC;
- pr_debug("SST DBG:BADQRC for stream\n");
- }
-
- return retval;
-}
-
-
diff --git a/drivers/staging/intel_sst/intel_sst_stream_encoded.c b/drivers/staging/intel_sst/intel_sst_stream_encoded.c
deleted file mode 100644
index 2be58c5cba02..000000000000
--- a/drivers/staging/intel_sst/intel_sst_stream_encoded.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-/*
- * intel_sst_stream.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This file contains the stream operations of SST driver
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/syscalls.h>
-#include <linux/firmware.h>
-#include <linux/sched.h>
-#ifdef CONFIG_MRST_RAR_HANDLER
-#include <linux/rar_register.h>
-#include "../memrar/memrar.h"
-#endif
-#include "intel_sst_ioctl.h"
-#include "intel_sst.h"
-#include "intel_sst_fw_ipc.h"
-#include "intel_sst_common.h"
-/**
-* sst_get_stream_params - Send msg to query for stream parameters
-* @str_id: stream id for which the parameters are queried for
-* @get_params: out parameters to which the parameters are copied to
-*
-* This function is called when the stream parameters are queiried for
-*/
-int sst_get_stream_params(int str_id,
- struct snd_sst_get_stream_params *get_params)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
- struct stream_info *str_info;
- struct snd_sst_fw_get_stream_params *fw_params;
-
- pr_debug("get_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
-
- str_info = &sst_drv_ctx->streams[str_id];
- if (str_info->status != STREAM_UN_INIT) {
- if (str_info->ctrl_blk.on == true) {
- pr_err("control path in use\n");
- return -EINVAL;
- }
- if (sst_create_short_msg(&msg)) {
- pr_err("message creation failed\n");
- return -ENOMEM;
- }
- fw_params = kzalloc(sizeof(*fw_params), GFP_ATOMIC);
- if (!fw_params) {
- pr_err("mem allocation failed\n");
- kfree(msg);
- return -ENOMEM;
- }
-
- sst_fill_header(&msg->header, IPC_IA_GET_STREAM_PARAMS,
- 0, str_id);
- str_info->ctrl_blk.condition = false;
- str_info->ctrl_blk.ret_code = 0;
- str_info->ctrl_blk.on = true;
- str_info->ctrl_blk.data = (void *) fw_params;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
- if (retval) {
- get_params->codec_params.result = retval;
- kfree(fw_params);
- return -EIO;
- }
- memcpy(&get_params->pcm_params, &fw_params->pcm_params,
- sizeof(fw_params->pcm_params));
- memcpy(&get_params->codec_params.sparams,
- &fw_params->codec_params,
- sizeof(fw_params->codec_params));
- get_params->codec_params.result = 0;
- get_params->codec_params.stream_id = str_id;
- get_params->codec_params.codec = str_info->codec;
- get_params->codec_params.ops = str_info->ops;
- get_params->codec_params.stream_type = str_info->str_type;
- kfree(fw_params);
- } else {
- pr_debug("Stream is not in the init state\n");
- }
- return retval;
-}
-
-/**
- * sst_set_stream_param - Send msg for setting stream parameters
- *
- * @str_id: stream id
- * @str_param: stream params
- *
- * This function sets stream params during runtime
- */
-int sst_set_stream_param(int str_id, struct snd_sst_params *str_param)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
- struct stream_info *str_info;
-
- BUG_ON(!str_param);
- if (sst_drv_ctx->streams[str_id].ops != str_param->ops) {
- pr_err("Invalid operation\n");
- return -EINVAL;
- }
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- pr_debug("set_stream for %d\n", str_id);
- str_info = &sst_drv_ctx->streams[str_id];
- if (sst_drv_ctx->streams[str_id].status == STREAM_INIT) {
- if (str_info->ctrl_blk.on == true) {
- pr_err("control path in use\n");
- return -EAGAIN;
- }
- if (sst_create_large_msg(&msg))
- return -ENOMEM;
-
- sst_fill_header(&msg->header,
- IPC_IA_SET_STREAM_PARAMS, 1, str_id);
- str_info->ctrl_blk.condition = false;
- str_info->ctrl_blk.ret_code = 0;
- str_info->ctrl_blk.on = true;
- msg->header.part.data = sizeof(u32) +
- sizeof(str_param->sparams);
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), &str_param->sparams,
- sizeof(str_param->sparams));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
- if (retval < 0) {
- retval = -EIO;
- sst_clean_stream(str_info);
- }
- } else {
- retval = -EBADRQC;
- pr_err("BADQRC for stream\n");
- }
- return retval;
-}
-
-/**
-* sst_get_vol - This function allows to get the premix gain or gain of a stream
-*
-* @get_vol: this is an output param through which the volume
-* structure is passed back to user
-*
-* This function is called when the premix gain or stream gain is queried for
-*/
-int sst_get_vol(struct snd_sst_vol *get_vol)
-{
- int retval = 0;
- struct ipc_post *msg = NULL;
- struct snd_sst_vol *fw_get_vol;
- int str_id = get_vol->stream_id;
-
- pr_debug("get vol called\n");
-
- if (sst_create_short_msg(&msg))
- return -ENOMEM;
-
- sst_fill_header(&msg->header,
- IPC_IA_GET_STREAM_VOL, 0, str_id);
- sst_drv_ctx->vol_info_blk.condition = false;
- sst_drv_ctx->vol_info_blk.ret_code = 0;
- sst_drv_ctx->vol_info_blk.on = true;
- fw_get_vol = kzalloc(sizeof(*fw_get_vol), GFP_ATOMIC);
- if (!fw_get_vol) {
- pr_err("mem allocation failed\n");
- kfree(msg);
- return -ENOMEM;
- }
- sst_drv_ctx->vol_info_blk.data = (void *)fw_get_vol;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &sst_drv_ctx->vol_info_blk, SST_BLOCK_TIMEOUT);
- if (retval)
- retval = -EIO;
- else {
- pr_debug("stream id %d\n", fw_get_vol->stream_id);
- pr_debug("volume %d\n", fw_get_vol->volume);
- pr_debug("ramp duration %d\n", fw_get_vol->ramp_duration);
- pr_debug("ramp_type %d\n", fw_get_vol->ramp_type);
- memcpy(get_vol, fw_get_vol, sizeof(*fw_get_vol));
- }
- return retval;
-}
-
-/**
-* sst_set_vol - This function allows to set the premix gain or gain of a stream
-*
-* @set_vol: this holds the volume structure that needs to be set
-*
-* This function is called when premix gain or stream gain is requested to be set
-*/
-int sst_set_vol(struct snd_sst_vol *set_vol)
-{
-
- int retval = 0;
- struct ipc_post *msg = NULL;
-
- pr_debug("set vol called\n");
-
- if (sst_create_large_msg(&msg)) {
- pr_err("message creation failed\n");
- return -ENOMEM;
- }
- sst_fill_header(&msg->header, IPC_IA_SET_STREAM_VOL, 1,
- set_vol->stream_id);
-
- msg->header.part.data = sizeof(u32) + sizeof(*set_vol);
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), set_vol, sizeof(*set_vol));
- sst_drv_ctx->vol_info_blk.condition = false;
- sst_drv_ctx->vol_info_blk.ret_code = 0;
- sst_drv_ctx->vol_info_blk.on = true;
- sst_drv_ctx->vol_info_blk.data = set_vol;
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &sst_drv_ctx->vol_info_blk, SST_BLOCK_TIMEOUT);
- if (retval) {
- pr_err("error in set_vol = %d\n", retval);
- retval = -EIO;
- }
- return retval;
-}
-
-/**
-* sst_set_mute - This function sets premix mute or soft mute of a stream
-*
-* @set_mute: this holds the mute structure that needs to be set
-*
-* This function is called when premix mute or stream mute requested to be set
-*/
-int sst_set_mute(struct snd_sst_mute *set_mute)
-{
-
- int retval = 0;
- struct ipc_post *msg = NULL;
-
- pr_debug("set mute called\n");
-
- if (sst_create_large_msg(&msg)) {
- pr_err("message creation failed\n");
- return -ENOMEM;
- }
- sst_fill_header(&msg->header, IPC_IA_SET_STREAM_MUTE, 1,
- set_mute->stream_id);
- sst_drv_ctx->mute_info_blk.condition = false;
- sst_drv_ctx->mute_info_blk.ret_code = 0;
- sst_drv_ctx->mute_info_blk.on = true;
- sst_drv_ctx->mute_info_blk.data = set_mute;
-
- msg->header.part.data = sizeof(u32) + sizeof(*set_mute);
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), set_mute,
- sizeof(*set_mute));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &sst_drv_ctx->mute_info_blk, SST_BLOCK_TIMEOUT);
- if (retval) {
- pr_err("error in set_mute = %d\n", retval);
- retval = -EIO;
- }
- return retval;
-}
-
-int sst_prepare_target(struct snd_sst_slot_info *slot)
-{
- if (slot->target_device == SND_SST_TARGET_PMIC
- && slot->device_instance == 1) {
- /*music mode*/
- if (sst_drv_ctx->pmic_port_instance == 0)
- sst_drv_ctx->scard_ops->set_voice_port(
- DEACTIVATE);
- } else if ((slot->target_device == SND_SST_TARGET_PMIC ||
- slot->target_device == SND_SST_TARGET_MODEM) &&
- slot->device_instance == 0) {
- /*voip mode where pcm0 is active*/
- if (sst_drv_ctx->pmic_port_instance == 1)
- sst_drv_ctx->scard_ops->set_audio_port(
- DEACTIVATE);
- }
- return 0;
-}
-
-int sst_activate_target(struct snd_sst_slot_info *slot)
-{
- if (slot->target_device == SND_SST_TARGET_PMIC &&
- slot->device_instance == 1) {
- /*music mode*/
- sst_drv_ctx->pmic_port_instance = 1;
- sst_drv_ctx->scard_ops->set_audio_port(ACTIVATE);
- sst_drv_ctx->scard_ops->set_pcm_audio_params(
- slot->pcm_params.sfreq,
- slot->pcm_params.pcm_wd_sz,
- slot->pcm_params.num_chan);
- if (sst_drv_ctx->pb_streams)
- sst_drv_ctx->scard_ops->power_up_pmic_pb(1);
- if (sst_drv_ctx->cp_streams)
- sst_drv_ctx->scard_ops->power_up_pmic_cp(1);
- } else if ((slot->target_device == SND_SST_TARGET_PMIC ||
- slot->target_device == SND_SST_TARGET_MODEM) &&
- slot->device_instance == 0) {
- /*voip mode where pcm0 is active*/
- sst_drv_ctx->pmic_port_instance = 0;
- sst_drv_ctx->scard_ops->set_voice_port(
- ACTIVATE);
- sst_drv_ctx->scard_ops->power_up_pmic_pb(0);
- /*sst_drv_ctx->scard_ops->power_up_pmic_cp(0);*/
- }
- return 0;
-}
-
-int sst_parse_target(struct snd_sst_slot_info *slot)
-{
- int retval = 0;
-
- if (slot->action == SND_SST_PORT_ACTIVATE &&
- slot->device_type == SND_SST_DEVICE_PCM) {
- retval = sst_activate_target(slot);
- if (retval)
- pr_err("SST_Activate_target_fail\n");
- else
- pr_err("SST_Activate_target_pass\n");
- } else if (slot->action == SND_SST_PORT_PREPARE &&
- slot->device_type == SND_SST_DEVICE_PCM) {
- retval = sst_prepare_target(slot);
- if (retval)
- pr_err("SST_prepare_target_fail\n");
- else
- pr_err("SST_prepare_target_pass\n");
- } else {
- pr_err("slot_action : %d, device_type: %d\n",
- slot->action, slot->device_type);
- }
- return retval;
-}
-
-int sst_send_target(struct snd_sst_target_device *target)
-{
- int retval;
- struct ipc_post *msg;
-
- if (sst_create_large_msg(&msg)) {
- pr_err("message creation failed\n");
- return -ENOMEM;
- }
- sst_fill_header(&msg->header, IPC_IA_TARGET_DEV_SELECT, 1, 0);
- sst_drv_ctx->tgt_dev_blk.condition = false;
- sst_drv_ctx->tgt_dev_blk.ret_code = 0;
- sst_drv_ctx->tgt_dev_blk.on = true;
-
- msg->header.part.data = sizeof(u32) + sizeof(*target);
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), target,
- sizeof(*target));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- pr_debug("message sent- waiting\n");
- retval = sst_wait_interruptible_timeout(sst_drv_ctx,
- &sst_drv_ctx->tgt_dev_blk, TARGET_DEV_BLOCK_TIMEOUT);
- if (retval)
- pr_err("target device ipc failed = 0x%x\n", retval);
- return retval;
-
-}
-
-int sst_target_device_validate(struct snd_sst_target_device *target)
-{
- int retval = 0;
- int i;
-
- for (i = 0; i < SST_MAX_TARGET_DEVICES; i++) {
- if (target->devices[i].device_type == SND_SST_DEVICE_PCM) {
- /*pcm device, check params*/
- if (target->devices[i].device_instance == 1) {
- if ((target->devices[i].device_mode !=
- SND_SST_DEV_MODE_PCM_MODE4_I2S) &&
- (target->devices[i].device_mode !=
- SND_SST_DEV_MODE_PCM_MODE4_RIGHT_JUSTIFIED)
- && (target->devices[i].device_mode !=
- SND_SST_DEV_MODE_PCM_MODE1))
- goto err;
- } else if (target->devices[i].device_instance == 0) {
- if ((target->devices[i].device_mode !=
- SND_SST_DEV_MODE_PCM_MODE2)
- && (target->devices[i].device_mode !=
- SND_SST_DEV_MODE_PCM_MODE4_I2S)
- && (target->devices[i].device_mode !=
- SND_SST_DEV_MODE_PCM_MODE1))
- goto err;
- if (target->devices[i].pcm_params.sfreq != 8000
- || target->devices[i].pcm_params.num_chan != 1
- || target->devices[i].pcm_params.pcm_wd_sz !=
- 16)
- goto err;
- } else {
-err:
- pr_err("i/p params incorrect\n");
- return -EINVAL;
- }
- }
- }
- return retval;
-}
-
-/**
- * sst_target_device_select - This function sets the target device configurations
- *
- * @target: this parameter holds the configurations to be set
- *
- * This function is called when the user layer wants to change the target
- * device's configurations
- */
-
-int sst_target_device_select(struct snd_sst_target_device *target)
-{
- int retval, i, prepare_count = 0;
-
- pr_debug("Target Device Select\n");
-
- if (target->device_route < 0 || target->device_route > 2) {
- pr_err("device route is invalid\n");
- return -EINVAL;
- }
-
- if (target->device_route != 0) {
- pr_err("Unsupported config\n");
- return -EIO;
- }
- retval = sst_target_device_validate(target);
- if (retval)
- return retval;
-
- retval = sst_send_target(target);
- if (retval)
- return retval;
- for (i = 0; i < SST_MAX_TARGET_DEVICES; i++) {
- if (target->devices[i].action == SND_SST_PORT_ACTIVATE) {
- pr_debug("activate called in %d\n", i);
- retval = sst_parse_target(&target->devices[i]);
- if (retval)
- return retval;
- } else if (target->devices[i].action == SND_SST_PORT_PREPARE) {
- pr_debug("PREPARE in %d, Forwarding\n", i);
- retval = sst_parse_target(&target->devices[i]);
- if (retval) {
- pr_err("Parse Target fail %d\n", retval);
- return retval;
- }
- pr_debug("Parse Target successful %d\n", retval);
- if (target->devices[i].device_type ==
- SND_SST_DEVICE_PCM)
- prepare_count++;
- }
- }
- if (target->devices[0].action == SND_SST_PORT_PREPARE &&
- prepare_count == 0)
- sst_drv_ctx->scard_ops->power_down_pmic();
-
- return retval;
-}
-#ifdef CONFIG_MRST_RAR_HANDLER
-/*This function gets the physical address of the secure memory from the handle*/
-static inline int sst_get_RAR(struct RAR_buffer *buffers, int count)
-{
- int retval = 0, rar_status = 0;
-
- rar_status = rar_handle_to_bus(buffers, count);
-
- if (count != rar_status) {
- pr_err("The rar CALL Failed");
- retval = -EIO;
- }
- if (buffers->info.type != RAR_TYPE_AUDIO) {
- pr_err("Invalid RAR type\n");
- return -EINVAL;
- }
- return retval;
-}
-
-#endif
-
-/* This function creates the scatter gather list to be sent to firmware to
-capture/playback data*/
-static int sst_create_sg_list(struct stream_info *stream,
- struct sst_frame_info *sg_list)
-{
- struct sst_stream_bufs *kbufs = NULL;
-#ifdef CONFIG_MRST_RAR_HANDLER
- struct RAR_buffer rar_buffers;
- int retval = 0;
-#endif
- int i = 0;
- list_for_each_entry(kbufs, &stream->bufs, node) {
- if (kbufs->in_use == false) {
-#ifdef CONFIG_MRST_RAR_HANDLER
- if (stream->ops == STREAM_OPS_PLAYBACK_DRM) {
- pr_debug("DRM playback handling\n");
- rar_buffers.info.handle = (__u32)kbufs->addr;
- rar_buffers.info.size = kbufs->size;
- pr_debug("rar handle 0x%x size=0x%x\n",
- rar_buffers.info.handle,
- rar_buffers.info.size);
- retval = sst_get_RAR(&rar_buffers, 1);
-
- if (retval)
- return retval;
- sg_list->addr[i].addr = rar_buffers.bus_address;
- /* rar_buffers.info.size; */
- sg_list->addr[i].size = (__u32)kbufs->size;
- pr_debug("phyaddr[%d] 0x%x Size:0x%x\n"
- , i, sg_list->addr[i].addr,
- sg_list->addr[i].size);
- }
-#endif
- if (stream->ops != STREAM_OPS_PLAYBACK_DRM) {
- sg_list->addr[i].addr =
- virt_to_phys((void *)
- kbufs->addr + kbufs->offset);
- sg_list->addr[i].size = kbufs->size;
- pr_debug("phyaddr[%d]:0x%x Size:0x%x\n"
- , i , sg_list->addr[i].addr, kbufs->size);
- }
- stream->curr_bytes += sg_list->addr[i].size;
- kbufs->in_use = true;
- i++;
- }
- if (i >= MAX_NUM_SCATTER_BUFFERS)
- break;
- }
-
- sg_list->num_entries = i;
- pr_debug("sg list entries = %d\n", sg_list->num_entries);
- return i;
-}
-
-
-/**
- * sst_play_frame - Send msg for sending stream frames
- *
- * @str_id: ID of stream
- *
- * This function is called to send data to be played out
- * to the firmware
- */
-int sst_play_frame(int str_id)
-{
- int i = 0, retval = 0;
- struct ipc_post *msg = NULL;
- struct sst_frame_info sg_list = {0};
- struct sst_stream_bufs *kbufs = NULL, *_kbufs;
- struct stream_info *stream;
-
- pr_debug("play frame for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
-
- stream = &sst_drv_ctx->streams[str_id];
- /* clear prev sent buffers */
- list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
- if (kbufs->in_use == true) {
- spin_lock(&stream->pcm_lock);
- list_del(&kbufs->node);
- spin_unlock(&stream->pcm_lock);
- kfree(kbufs);
- }
- }
- /* update bytes sent */
- stream->cumm_bytes += stream->curr_bytes;
- stream->curr_bytes = 0;
- if (list_empty(&stream->bufs)) {
- /* no user buffer available */
- pr_debug("Null buffer stream status %d\n", stream->status);
- stream->prev = stream->status;
- stream->status = STREAM_INIT;
- pr_debug("new stream status = %d\n", stream->status);
- if (stream->need_draining == true) {
- pr_debug("draining stream\n");
- if (sst_create_short_msg(&msg)) {
- pr_err("mem allocation failed\n");
- return -ENOMEM;
- }
- sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM,
- 0, str_id);
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node,
- &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- } else if (stream->data_blk.on == true) {
- pr_debug("user list empty.. wake\n");
- /* unblock */
- stream->data_blk.ret_code = 0;
- stream->data_blk.condition = true;
- stream->data_blk.on = false;
- wake_up(&sst_drv_ctx->wait_queue);
- }
- return 0;
- }
-
- /* create list */
- i = sst_create_sg_list(stream, &sg_list);
-
- /* post msg */
- if (sst_create_large_msg(&msg))
- return -ENOMEM;
-
- sst_fill_header(&msg->header, IPC_IA_PLAY_FRAMES, 1, str_id);
- msg->header.part.data = sizeof(u32) + sizeof(sg_list);
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), &sg_list, sizeof(sg_list));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- return 0;
-
-}
-
-/**
- * sst_capture_frame - Send msg for sending stream frames
- *
- * @str_id: ID of stream
- *
- * This function is called to capture data from the firmware
- */
-int sst_capture_frame(int str_id)
-{
- int i = 0, retval = 0;
- struct ipc_post *msg = NULL;
- struct sst_frame_info sg_list = {0};
- struct sst_stream_bufs *kbufs = NULL, *_kbufs;
- struct stream_info *stream;
-
-
- pr_debug("capture frame for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- stream = &sst_drv_ctx->streams[str_id];
- /* clear prev sent buffers */
- list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
- if (kbufs->in_use == true) {
- list_del(&kbufs->node);
- kfree(kbufs);
- pr_debug("del node\n");
- }
- }
- if (list_empty(&stream->bufs)) {
- /* no user buffer available */
- pr_debug("Null buffer!!!!stream status %d\n",
- stream->status);
- stream->prev = stream->status;
- stream->status = STREAM_INIT;
- pr_debug("new stream status = %d\n",
- stream->status);
- if (stream->data_blk.on == true) {
- pr_debug("user list empty.. wake\n");
- /* unblock */
- stream->data_blk.ret_code = 0;
- stream->data_blk.condition = true;
- stream->data_blk.on = false;
- wake_up(&sst_drv_ctx->wait_queue);
-
- }
- return 0;
- }
- /* create new sg list */
- i = sst_create_sg_list(stream, &sg_list);
-
- /* post msg */
- if (sst_create_large_msg(&msg))
- return -ENOMEM;
-
- sst_fill_header(&msg->header, IPC_IA_CAPT_FRAMES, 1, str_id);
- msg->header.part.data = sizeof(u32) + sizeof(sg_list);
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), &sg_list, sizeof(sg_list));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-
-
- /*update bytes recevied*/
- stream->cumm_bytes += stream->curr_bytes;
- stream->curr_bytes = 0;
-
- pr_debug("Cum bytes = %d\n", stream->cumm_bytes);
- return 0;
-}
-
-/*This function is used to calculate the minimum size of input buffers given*/
-static unsigned int calculate_min_size(struct snd_sst_buffs *bufs)
-{
- int i, min_val = bufs->buff_entry[0].size;
- for (i = 1 ; i < bufs->entries; i++) {
- if (bufs->buff_entry[i].size < min_val)
- min_val = bufs->buff_entry[i].size;
- }
- pr_debug("min_val = %d\n", min_val);
- return min_val;
-}
-
-static unsigned int calculate_max_size(struct snd_sst_buffs *bufs)
-{
- int i, max_val = bufs->buff_entry[0].size;
- for (i = 1 ; i < bufs->entries; i++) {
- if (bufs->buff_entry[i].size > max_val)
- max_val = bufs->buff_entry[i].size;
- }
- pr_debug("max_val = %d\n", max_val);
- return max_val;
-}
-
-/*This function is used to allocate input and output buffers to be sent to
-the firmware that will take encoded data and return decoded data*/
-static int sst_allocate_decode_buf(struct stream_info *str_info,
- struct snd_sst_dbufs *dbufs,
- unsigned int cum_input_given,
- unsigned int cum_output_given)
-{
-#ifdef CONFIG_MRST_RAR_HANDLER
- if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
-
- if (dbufs->ibufs->type == SST_BUF_RAR &&
- dbufs->obufs->type == SST_BUF_RAR) {
- if (dbufs->ibufs->entries == dbufs->obufs->entries)
- return 0;
- else {
- pr_err("RAR entries dont match\n");
- return -EINVAL;
- }
- } else
- str_info->decode_osize = cum_output_given;
- return 0;
-
- }
-#endif
- if (!str_info->decode_ibuf) {
- pr_debug("no i/p buffers, trying full size\n");
- str_info->decode_isize = cum_input_given;
- str_info->decode_ibuf = kzalloc(str_info->decode_isize,
- GFP_KERNEL);
- str_info->idecode_alloc = str_info->decode_isize;
- }
- if (!str_info->decode_ibuf) {
- pr_debug("buff alloc failed, try max size\n");
- str_info->decode_isize = calculate_max_size(dbufs->ibufs);
- str_info->decode_ibuf = kzalloc(
- str_info->decode_isize, GFP_KERNEL);
- str_info->idecode_alloc = str_info->decode_isize;
- }
- if (!str_info->decode_ibuf) {
- pr_debug("buff alloc failed, try min size\n");
- str_info->decode_isize = calculate_min_size(dbufs->ibufs);
- str_info->decode_ibuf = kzalloc(str_info->decode_isize,
- GFP_KERNEL);
- if (!str_info->decode_ibuf) {
- pr_err("mem allocation failed\n");
- return -ENOMEM;
- }
- str_info->idecode_alloc = str_info->decode_isize;
- }
- str_info->decode_osize = cum_output_given;
- if (str_info->decode_osize > sst_drv_ctx->mmap_len)
- str_info->decode_osize = sst_drv_ctx->mmap_len;
- return 0;
-}
-
-/*This function is used to send the message to firmware to decode the data*/
-static int sst_send_decode_mess(int str_id, struct stream_info *str_info,
- struct snd_sst_decode_info *dec_info)
-{
- struct ipc_post *msg = NULL;
- int retval = 0;
-
- pr_debug("SST DBG:sst_set_mute:called\n");
-
- if (str_info->decode_ibuf_type == SST_BUF_RAR) {
-#ifdef CONFIG_MRST_RAR_HANDLER
- dec_info->frames_in.addr[0].addr =
- (unsigned long)str_info->decode_ibuf;
- dec_info->frames_in.addr[0].size =
- str_info->decode_isize;
-#endif
-
- } else {
- dec_info->frames_in.addr[0].addr = virt_to_phys((void *)
- str_info->decode_ibuf);
- dec_info->frames_in.addr[0].size = str_info->decode_isize;
- }
-
-
- if (str_info->decode_obuf_type == SST_BUF_RAR) {
-#ifdef CONFIG_MRST_RAR_HANDLER
- dec_info->frames_out.addr[0].addr =
- (unsigned long)str_info->decode_obuf;
- dec_info->frames_out.addr[0].size = str_info->decode_osize;
-#endif
-
- } else {
- dec_info->frames_out.addr[0].addr = virt_to_phys((void *)
- str_info->decode_obuf) ;
- dec_info->frames_out.addr[0].size = str_info->decode_osize;
- }
-
- dec_info->frames_in.num_entries = 1;
- dec_info->frames_out.num_entries = 1;
- dec_info->frames_in.rsrvd = 0;
- dec_info->frames_out.rsrvd = 0;
- dec_info->input_bytes_consumed = 0;
- dec_info->output_bytes_produced = 0;
- if (sst_create_large_msg(&msg)) {
- pr_err("message creation failed\n");
- return -ENOMEM;
- }
-
- sst_fill_header(&msg->header, IPC_IA_DECODE_FRAMES, 1, str_id);
- msg->header.part.data = sizeof(u32) + sizeof(*dec_info);
- memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
- memcpy(msg->mailbox_data + sizeof(u32), dec_info,
- sizeof(*dec_info));
- spin_lock(&sst_drv_ctx->list_spin_lock);
- list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
- spin_unlock(&sst_drv_ctx->list_spin_lock);
- str_info->data_blk.condition = false;
- str_info->data_blk.ret_code = 0;
- str_info->data_blk.on = true;
- str_info->data_blk.data = dec_info;
- sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk);
- return retval;
-}
-
-#ifdef CONFIG_MRST_RAR_HANDLER
-static int sst_prepare_input_buffers_rar(struct stream_info *str_info,
- struct snd_sst_dbufs *dbufs,
- int *input_index, int *in_copied,
- int *input_index_valid_size, int *new_entry_flag)
-{
- int retval = 0, i;
-
- if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
- struct RAR_buffer rar_buffers;
- __u32 info;
- retval = copy_from_user((void *) &info,
- dbufs->ibufs->buff_entry[i].buffer,
- sizeof(__u32));
- if (retval) {
- pr_err("cpy from user fail\n");
- return -EAGAIN;
- }
- rar_buffers.info.type = dbufs->ibufs->type;
- rar_buffers.info.size = dbufs->ibufs->buff_entry[i].size;
- rar_buffers.info.handle = info;
- pr_debug("rar in DnR(input buffer function)=0x%x size=0x%x",
- rar_buffers.info.handle,
- rar_buffers.info.size);
- retval = sst_get_RAR(&rar_buffers, 1);
- if (retval) {
- pr_debug("SST ERR: RAR API failed\n");
- return retval;
- }
- str_info->decode_ibuf =
- (void *) ((unsigned long) rar_buffers.bus_address);
- pr_debug("RAR buf addr in DnR (input buffer function)0x%lu",
- (unsigned long) str_info->decode_ibuf);
- pr_debug("rar in DnR decode function/output b_add rar =0x%lu",
- (unsigned long) rar_buffers.bus_address);
- *input_index = i + 1;
- str_info->decode_isize = dbufs->ibufs->buff_entry[i].size;
- str_info->decode_ibuf_type = dbufs->ibufs->type;
- *in_copied = str_info->decode_isize;
- }
- return retval;
-}
-#endif
-/*This function is used to prepare the kernel input buffers with contents
-before sending for decode*/
-static int sst_prepare_input_buffers(struct stream_info *str_info,
- struct snd_sst_dbufs *dbufs,
- int *input_index, int *in_copied,
- int *input_index_valid_size, int *new_entry_flag)
-{
- int i, cpy_size, retval = 0;
-
- pr_debug("input_index = %d, input entries = %d\n",
- *input_index, dbufs->ibufs->entries);
- for (i = *input_index; i < dbufs->ibufs->entries; i++) {
-#ifdef CONFIG_MRST_RAR_HANDLER
- retval = sst_prepare_input_buffers_rar(str_info,
- dbufs, input_index, in_copied,
- input_index_valid_size, new_entry_flag);
- if (retval) {
- pr_err("In prepare input buffers for RAR\n");
- return -EIO;
- }
-#endif
- *input_index = i;
- if (*input_index_valid_size == 0)
- *input_index_valid_size =
- dbufs->ibufs->buff_entry[i].size;
- pr_debug("inout addr = %p, size = %d\n",
- dbufs->ibufs->buff_entry[i].buffer,
- *input_index_valid_size);
- pr_debug("decode_isize = %d, in_copied %d\n",
- str_info->decode_isize, *in_copied);
- if (*input_index_valid_size <=
- (str_info->decode_isize - *in_copied))
- cpy_size = *input_index_valid_size;
- else
- cpy_size = str_info->decode_isize - *in_copied;
-
- pr_debug("cpy size = %d\n", cpy_size);
- if (!dbufs->ibufs->buff_entry[i].buffer) {
- pr_err("i/p buffer is null\n");
- return -EINVAL;
- }
- pr_debug("Try copy To %p, From %p, size %d\n",
- str_info->decode_ibuf + *in_copied,
- dbufs->ibufs->buff_entry[i].buffer, cpy_size);
-
- retval =
- copy_from_user((void *)(str_info->decode_ibuf + *in_copied),
- (void *) dbufs->ibufs->buff_entry[i].buffer,
- cpy_size);
- if (retval) {
- pr_err("copy from user failed\n");
- return -EIO;
- }
- *in_copied += cpy_size;
- *input_index_valid_size -= cpy_size;
- pr_debug("in buff size = %d, in_copied = %d\n",
- *input_index_valid_size, *in_copied);
- if (*input_index_valid_size != 0) {
- pr_debug("more input buffers left\n");
- dbufs->ibufs->buff_entry[i].buffer += cpy_size;
- break;
- }
- if (*in_copied == str_info->decode_isize &&
- *input_index_valid_size == 0 &&
- (i+1) <= dbufs->ibufs->entries) {
- pr_debug("all input buffers copied\n");
- *new_entry_flag = true;
- *input_index = i + 1;
- break;
- }
- }
- return retval;
-}
-
-/* This function is used to copy the decoded data from kernel buffers to
-the user output buffers with contents after decode*/
-static int sst_prepare_output_buffers(struct stream_info *str_info,
- struct snd_sst_dbufs *dbufs,
- int *output_index, int output_size,
- int *out_copied)
-
-{
- int i, cpy_size, retval = 0;
- pr_debug("output_index = %d, output entries = %d\n",
- *output_index,
- dbufs->obufs->entries);
- for (i = *output_index; i < dbufs->obufs->entries; i++) {
- *output_index = i;
- pr_debug("output addr = %p, size = %d\n",
- dbufs->obufs->buff_entry[i].buffer,
- dbufs->obufs->buff_entry[i].size);
- pr_debug("output_size = %d, out_copied = %d\n",
- output_size, *out_copied);
- if (dbufs->obufs->buff_entry[i].size <
- (output_size - *out_copied))
- cpy_size = dbufs->obufs->buff_entry[i].size;
- else
- cpy_size = output_size - *out_copied;
- pr_debug("cpy size = %d\n", cpy_size);
- pr_debug("Try copy To: %p, From %p, size %d\n",
- dbufs->obufs->buff_entry[i].buffer,
- sst_drv_ctx->mmap_mem + *out_copied,
- cpy_size);
- retval = copy_to_user(dbufs->obufs->buff_entry[i].buffer,
- sst_drv_ctx->mmap_mem + *out_copied,
- cpy_size);
- if (retval) {
- pr_err("copy to user failed\n");
- return -EIO;
- } else
- pr_debug("copy to user passed\n");
- *out_copied += cpy_size;
- dbufs->obufs->buff_entry[i].size -= cpy_size;
- pr_debug("o/p buff size %d, out_copied %d\n",
- dbufs->obufs->buff_entry[i].size, *out_copied);
- if (dbufs->obufs->buff_entry[i].size != 0) {
- *output_index = i;
- dbufs->obufs->buff_entry[i].buffer += cpy_size;
- break;
- } else if (*out_copied == output_size) {
- *output_index = i + 1;
- break;
- }
- }
- return retval;
-}
-
-/**
- * sst_decode - Send msg for decoding frames
- *
- * @str_id: ID of stream
- * @dbufs: param that holds the user input and output buffers and size
- *
- * This function is called to decode data from the firmware
- */
-int sst_decode(int str_id, struct snd_sst_dbufs *dbufs)
-{
- int retval = 0, i;
- unsigned long long total_input = 0 , total_output = 0;
- unsigned int cum_input_given = 0 , cum_output_given = 0;
- int copy_in_done = false, copy_out_done = false;
- int input_index = 0, output_index = 0;
- int input_index_valid_size = 0;
- int in_copied, out_copied;
- int new_entry_flag;
- u64 output_size;
- struct stream_info *str_info;
- struct snd_sst_decode_info dec_info;
- unsigned long long input_bytes, output_bytes;
-
- sst_drv_ctx->scard_ops->power_down_pmic();
- pr_debug("Powering_down_PMIC...\n");
-
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
-
- str_info = &sst_drv_ctx->streams[str_id];
- if (str_info->status != STREAM_INIT) {
- pr_err("invalid stream state = %d\n",
- str_info->status);
- return -EINVAL;
- }
-
- str_info->prev = str_info->status;
- str_info->status = STREAM_DECODE;
-
- for (i = 0; i < dbufs->ibufs->entries; i++)
- cum_input_given += dbufs->ibufs->buff_entry[i].size;
- for (i = 0; i < dbufs->obufs->entries; i++)
- cum_output_given += dbufs->obufs->buff_entry[i].size;
-
- /* input and output buffer allocation */
- retval = sst_allocate_decode_buf(str_info, dbufs,
- cum_input_given, cum_output_given);
- if (retval) {
- pr_err("mem allocation failed, abort!!!\n");
- retval = -ENOMEM;
- goto finish;
- }
-
- str_info->decode_isize = str_info->idecode_alloc;
- str_info->decode_ibuf_type = dbufs->ibufs->type;
- str_info->decode_obuf_type = dbufs->obufs->type;
-
- while ((copy_out_done == false) && (copy_in_done == false)) {
- in_copied = 0;
- new_entry_flag = false;
- retval = sst_prepare_input_buffers(str_info,\
- dbufs, &input_index, &in_copied,
- &input_index_valid_size, &new_entry_flag);
- if (retval) {
- pr_err("prepare in buffers failed\n");
- goto finish;
- }
-
- if (str_info->ops != STREAM_OPS_PLAYBACK_DRM)
- str_info->decode_obuf = sst_drv_ctx->mmap_mem;
-
-#ifdef CONFIG_MRST_RAR_HANDLER
- else {
- if (dbufs->obufs->type == SST_BUF_RAR) {
- struct RAR_buffer rar_buffers;
- __u32 info;
-
- pr_debug("DRM");
- retval = copy_from_user((void *) &info,
- dbufs->obufs->
- buff_entry[output_index].buffer,
- sizeof(__u32));
-
- rar_buffers.info.size = dbufs->obufs->
- buff_entry[output_index].size;
- rar_buffers.info.handle = info;
- retval = sst_get_RAR(&rar_buffers, 1);
- if (retval)
- return retval;
-
- str_info->decode_obuf = (void *)((unsigned long)
- rar_buffers.bus_address);
- str_info->decode_osize = dbufs->obufs->
- buff_entry[output_index].size;
- str_info->decode_obuf_type = dbufs->obufs->type;
- pr_debug("DRM handling\n");
- pr_debug("o/p_add=0x%lu Size=0x%x\n",
- (unsigned long) str_info->decode_obuf,
- str_info->decode_osize);
- } else {
- str_info->decode_obuf = sst_drv_ctx->mmap_mem;
- str_info->decode_osize = dbufs->obufs->
- buff_entry[output_index].size;
-
- }
- }
-#endif
- if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) {
- if (str_info->decode_isize > in_copied) {
- str_info->decode_isize = in_copied;
- pr_debug("i/p size = %d\n",
- str_info->decode_isize);
- }
- }
-
-
- retval = sst_send_decode_mess(str_id, str_info, &dec_info);
- if (retval || dec_info.input_bytes_consumed == 0) {
- pr_err("SST ERR: mess failed or no input consumed\n");
- goto finish;
- }
- input_bytes = dec_info.input_bytes_consumed;
- output_bytes = dec_info.output_bytes_produced;
-
- pr_debug("in_copied=%d, con=%lld, prod=%lld\n",
- in_copied, input_bytes, output_bytes);
- if (dbufs->obufs->type == SST_BUF_RAR) {
- output_index += 1;
- if (output_index == dbufs->obufs->entries) {
- copy_in_done = true;
- pr_debug("all i/p cpy done\n");
- }
- total_output += output_bytes;
- } else {
- out_copied = 0;
- output_size = output_bytes;
- retval = sst_prepare_output_buffers(str_info, dbufs,
- &output_index, output_size, &out_copied);
- if (retval) {
- pr_err("prep out buff fail\n");
- goto finish;
- }
- if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) {
- if (in_copied != input_bytes) {
- int bytes_left = in_copied -
- input_bytes;
- pr_debug("bytes %d\n",
- bytes_left);
- if (new_entry_flag == true)
- input_index--;
- while (bytes_left) {
- struct snd_sst_buffs *ibufs;
- struct snd_sst_buff_entry
- *buff_entry;
- unsigned int size_sent;
-
- ibufs = dbufs->ibufs;
- buff_entry =
- &ibufs->buff_entry[input_index];
- size_sent = buff_entry->size -\
- input_index_valid_size;
- if (bytes_left == size_sent) {
- bytes_left = 0;
- } else if (bytes_left <
- size_sent) {
- buff_entry->buffer +=
- (size_sent -
- bytes_left);
- buff_entry->size -=
- (size_sent -
- bytes_left);
- bytes_left = 0;
- } else {
- bytes_left -= size_sent;
- input_index--;
- input_index_valid_size =
- 0;
- }
- }
-
- }
- }
-
- total_output += out_copied;
- if (str_info->decode_osize != out_copied) {
- str_info->decode_osize -= out_copied;
- pr_debug("output size modified = %d\n",
- str_info->decode_osize);
- }
- }
- total_input += input_bytes;
-
- if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
- if (total_input == cum_input_given)
- copy_in_done = true;
- copy_out_done = true;
-
- } else {
- if (total_output == cum_output_given) {
- copy_out_done = true;
- pr_debug("all o/p cpy done\n");
- }
-
- if (total_input == cum_input_given) {
- copy_in_done = true;
- pr_debug("all i/p cpy done\n");
- }
- }
-
- pr_debug("copy_out = %d, copy_in = %d\n",
- copy_out_done, copy_in_done);
- }
-
-finish:
- dbufs->input_bytes_consumed = total_input;
- dbufs->output_bytes_produced = total_output;
- str_info->status = str_info->prev;
- str_info->prev = STREAM_DECODE;
- kfree(str_info->decode_ibuf);
- str_info->decode_ibuf = NULL;
- return retval;
-}
diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c
deleted file mode 100644
index 492b660246b4..000000000000
--- a/drivers/staging/intel_sst/intelmid.c
+++ /dev/null
@@ -1,1022 +0,0 @@
-/*
- * intelmid.c - Intel Sound card driver for MID
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Harsha Priya <priya.harsha@intel.com>
- * Vinod Koul <vinod.koul@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * ALSA driver for Intel MID sound card chipset
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/firmware.h>
-#include <linux/input.h>
-#include <sound/control.h>
-#include <asm/mrst.h>
-#include <sound/pcm.h>
-#include <sound/jack.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <linux/gpio.h>
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intel_sst_fw_ipc.h"
-#include "intel_sst_common.h"
-#include "intelmid_snd_control.h"
-#include "intelmid_adc_control.h"
-#include "intelmid.h"
-
-MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
-MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
-MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>");
-MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>");
-MODULE_DESCRIPTION("Intel MAD Sound card driver");
-MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("{Intel,Intel_MAD}");
-
-
-static int card_index = SNDRV_DEFAULT_IDX1;/* Index 0-MAX */
-static char *card_id = SNDRV_DEFAULT_STR1; /* ID for this card */
-
-module_param(card_index, int, 0444);
-MODULE_PARM_DESC(card_index, "Index value for INTELMAD soundcard.");
-module_param(card_id, charp, 0444);
-MODULE_PARM_DESC(card_id, "ID string for INTELMAD soundcard.");
-
-int sst_card_vendor_id;
-int intelmid_audio_interrupt_enable;/*checkpatch fix*/
-struct snd_intelmad *intelmad_drv;
-
-#define INFO(_cpu_id, _irq_cache, _size) \
- ((kernel_ulong_t)&(struct snd_intelmad_probe_info) { \
- .cpu_id = (_cpu_id), \
- .irq_cache = (_irq_cache), \
- .size = (_size), \
- })
-/* Data path functionalities */
-static struct snd_pcm_hardware snd_intelmad_stream = {
- .info = (SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_DOUBLE |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_MMAP|
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_SYNC_START),
- .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
- SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
- SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
- .rates = (SNDRV_PCM_RATE_8000|
- SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000),
- .rate_min = MIN_RATE,
-
- .rate_max = MAX_RATE,
- .channels_min = MIN_CHANNEL,
- .channels_max = MAX_CHANNEL_AMIC,
- .buffer_bytes_max = MAX_BUFFER,
- .period_bytes_min = MIN_PERIOD_BYTES,
- .period_bytes_max = MAX_PERIOD_BYTES,
- .periods_min = MIN_PERIODS,
- .periods_max = MAX_PERIODS,
- .fifo_size = FIFO_SIZE,
-};
-
-
-/**
- * snd_intelmad_pcm_trigger - stream activities are handled here
- *
- * @substream:substream for which the stream function is called
- * @cmd:the stream commamd that requested from upper layer
- *
- * This function is called whenever an a stream activity is invoked
- */
-static int snd_intelmad_pcm_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- int ret_val = 0, str_id;
- struct snd_intelmad *intelmaddata;
- struct mad_stream_pvt *stream;
- struct intel_sst_pcm_control *sst_ops;
-
- WARN_ON(!substream);
-
- intelmaddata = snd_pcm_substream_chip(substream);
- stream = substream->runtime->private_data;
-
- WARN_ON(!intelmaddata->sstdrv_ops);
- WARN_ON(!intelmaddata->sstdrv_ops->scard_ops);
- sst_ops = intelmaddata->sstdrv_ops->pcm_control;
- str_id = stream->stream_info.str_id;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- pr_debug("Trigger Start\n");
- ret_val = sst_ops->device_control(SST_SND_START, &str_id);
- if (ret_val)
- return ret_val;
- stream->stream_status = RUNNING;
- stream->substream = substream;
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- pr_debug("in stop\n");
- ret_val = sst_ops->device_control(SST_SND_DROP, &str_id);
- if (ret_val)
- return ret_val;
- stream->stream_status = DROPPED;
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- pr_debug("in pause\n");
- ret_val = sst_ops->device_control(SST_SND_PAUSE, &str_id);
- if (ret_val)
- return ret_val;
- stream->stream_status = PAUSED;
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- pr_debug("in pause release\n");
- ret_val = sst_ops->device_control(SST_SND_RESUME, &str_id);
- if (ret_val)
- return ret_val;
- stream->stream_status = RUNNING;
- break;
- default:
- return -EINVAL;
- }
- return ret_val;
-}
-
-/**
-* snd_intelmad_pcm_prepare- internal preparation before starting a stream
-*
-* @substream: substream for which the function is called
-*
-* This function is called when a stream is started for internal preparation.
-*/
-static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct mad_stream_pvt *stream;
- int ret_val = 0;
- struct snd_intelmad *intelmaddata;
-
- pr_debug("pcm_prepare called\n");
-
- WARN_ON(!substream);
- stream = substream->runtime->private_data;
- intelmaddata = snd_pcm_substream_chip(substream);
- pr_debug("pb cnt = %d cap cnt = %d\n",\
- intelmaddata->playback_cnt,
- intelmaddata->capture_cnt);
-
- if (stream->stream_info.str_id) {
- pr_debug("Prepare called for already set stream\n");
- ret_val = intelmaddata->sstdrv_ops->pcm_control->device_control(
- SST_SND_DROP, &stream->stream_info.str_id);
- return ret_val;
- }
-
- ret_val = snd_intelmad_alloc_stream(substream);
- if (ret_val < 0)
- return ret_val;
- stream->dbg_cum_bytes = 0;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- intelmaddata->playback_cnt++;
- else
- intelmaddata->capture_cnt++;
- /* return back the stream id */
- snprintf(substream->pcm->id, sizeof(substream->pcm->id),
- "%d", stream->stream_info.str_id);
- pr_debug("stream id to user = %s\n",
- substream->pcm->id);
-
- ret_val = snd_intelmad_init_stream(substream);
- if (ret_val)
- return ret_val;
- substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
- return ret_val;
-}
-
-static int snd_intelmad_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- int ret_val;
-
- pr_debug("snd_intelmad_hw_params called\n");
- ret_val = snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
- memset(substream->runtime->dma_area, 0,
- params_buffer_bytes(hw_params));
-
- return ret_val;
-}
-
-static int snd_intelmad_hw_free(struct snd_pcm_substream *substream)
-{
- pr_debug("snd_intelmad_hw_free called\n");
- return snd_pcm_lib_free_pages(substream);
-}
-
-/**
- * snd_intelmad_pcm_pointer- to send the current buffer pointer processed by hw
- *
- * @substream: substream for which the function is called
- *
- * This function is called by ALSA framework to get the current hw buffer ptr
- * when a period is elapsed
- */
-static snd_pcm_uframes_t snd_intelmad_pcm_pointer
- (struct snd_pcm_substream *substream)
-{
- /* struct snd_pcm_runtime *runtime = substream->runtime; */
- struct mad_stream_pvt *stream;
- struct snd_intelmad *intelmaddata;
- int ret_val;
-
- WARN_ON(!substream);
-
- intelmaddata = snd_pcm_substream_chip(substream);
- stream = substream->runtime->private_data;
- if (stream->stream_status == INIT)
- return 0;
-
- ret_val = intelmaddata->sstdrv_ops->pcm_control->device_control(
- SST_SND_BUFFER_POINTER, &stream->stream_info);
- if (ret_val) {
- pr_err("error code = 0x%x\n", ret_val);
- return ret_val;
- }
- pr_debug("samples reported out 0x%llx\n",
- stream->stream_info.buffer_ptr);
- pr_debug("Frame bits:: %d period_count :: %d\n",
- (int)substream->runtime->frame_bits,
- (int)substream->runtime->period_size);
-
- return stream->stream_info.buffer_ptr;
-
-}
-
-/**
- * snd_intelmad_close- to free parameteres when stream is stopped
- *
- * @substream: substream for which the function is called
- *
- * This function is called by ALSA framework when stream is stopped
- */
-static int snd_intelmad_close(struct snd_pcm_substream *substream)
-{
- struct snd_intelmad *intelmaddata;
- struct mad_stream_pvt *stream;
- int ret_val = 0, str_id;
-
- WARN_ON(!substream);
-
- stream = substream->runtime->private_data;
- str_id = stream->stream_info.str_id;
-
- pr_debug("sst: snd_intelmad_close called for %d\n", str_id);
- intelmaddata = snd_pcm_substream_chip(substream);
-
- pr_debug("str id = %d\n", stream->stream_info.str_id);
- if (stream->stream_info.str_id) {
- /* SST API to actually stop/free the stream */
- ret_val = intelmaddata->sstdrv_ops->pcm_control->close(str_id);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- intelmaddata->playback_cnt--;
- else
- intelmaddata->capture_cnt--;
- }
- pr_debug("snd_intelmad_close : pb cnt = %d cap cnt = %d\n",
- intelmaddata->playback_cnt, intelmaddata->capture_cnt);
- kfree(substream->runtime->private_data);
- return ret_val;
-}
-
-/**
- * snd_intelmad_open- to set runtime parameters during stream start
- *
- * @substream: substream for which the function is called
- * @type: audio device type
- *
- * This function is called by ALSA framework when stream is started
- */
-static int snd_intelmad_open(struct snd_pcm_substream *substream,
- enum snd_sst_audio_device_type type)
-{
- struct snd_intelmad *intelmaddata;
- struct snd_pcm_runtime *runtime;
- struct mad_stream_pvt *stream;
-
- WARN_ON(!substream);
-
- pr_debug("snd_intelmad_open called\n");
-
- intelmaddata = snd_pcm_substream_chip(substream);
- runtime = substream->runtime;
- /* set the runtime hw parameter with local snd_pcm_hardware struct */
- runtime->hw = snd_intelmad_stream;
- if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) {
- /*
- * MRST firmware currently denies stereo recording requests.
- */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- runtime->hw.formats = (SNDRV_PCM_FMTBIT_S16 |
- SNDRV_PCM_FMTBIT_U16);
- runtime->hw.channels_max = 1;
- }
- }
- if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
- runtime->hw = snd_intelmad_stream;
- runtime->hw.rates = SNDRV_PCM_RATE_48000;
- runtime->hw.rate_min = MAX_RATE;
- runtime->hw.formats = (SNDRV_PCM_FMTBIT_S24 |
- SNDRV_PCM_FMTBIT_U24);
- if (intelmaddata->sstdrv_ops->scard_ops->input_dev_id == AMIC)
- runtime->hw.channels_max = MAX_CHANNEL_AMIC;
- else
- runtime->hw.channels_max = MAX_CHANNEL_DMIC;
-
- }
- /* setup the internal datastruture stream pointers based on it being
- playback or capture stream */
- stream = kzalloc(sizeof(*stream), GFP_KERNEL);
- if (!stream)
- return -ENOMEM;
- stream->stream_info.str_id = 0;
- stream->device = type;
- stream->stream_status = INIT;
- runtime->private_data = stream;
- return snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
-}
-
-static int snd_intelmad_headset_open(struct snd_pcm_substream *substream)
-{
- return snd_intelmad_open(substream, SND_SST_DEVICE_HEADSET);
-}
-
-static int snd_intelmad_ihf_open(struct snd_pcm_substream *substream)
-{
- return snd_intelmad_open(substream, SND_SST_DEVICE_IHF);
-}
-
-static int snd_intelmad_vibra_open(struct snd_pcm_substream *substream)
-{
- return snd_intelmad_open(substream, SND_SST_DEVICE_VIBRA);
-}
-
-static int snd_intelmad_haptic_open(struct snd_pcm_substream *substream)
-{
- return snd_intelmad_open(substream, SND_SST_DEVICE_HAPTIC);
-}
-
-static struct snd_pcm_ops snd_intelmad_headset_ops = {
- .open = snd_intelmad_headset_open,
- .close = snd_intelmad_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_intelmad_hw_params,
- .hw_free = snd_intelmad_hw_free,
- .prepare = snd_intelmad_pcm_prepare,
- .trigger = snd_intelmad_pcm_trigger,
- .pointer = snd_intelmad_pcm_pointer,
-};
-
-static struct snd_pcm_ops snd_intelmad_ihf_ops = {
- .open = snd_intelmad_ihf_open,
- .close = snd_intelmad_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_intelmad_hw_params,
- .hw_free = snd_intelmad_hw_free,
- .prepare = snd_intelmad_pcm_prepare,
- .trigger = snd_intelmad_pcm_trigger,
- .pointer = snd_intelmad_pcm_pointer,
-};
-
-static struct snd_pcm_ops snd_intelmad_vibra_ops = {
- .open = snd_intelmad_vibra_open,
- .close = snd_intelmad_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_intelmad_hw_params,
- .hw_free = snd_intelmad_hw_free,
- .prepare = snd_intelmad_pcm_prepare,
- .trigger = snd_intelmad_pcm_trigger,
- .pointer = snd_intelmad_pcm_pointer,
-};
-
-static struct snd_pcm_ops snd_intelmad_haptic_ops = {
- .open = snd_intelmad_haptic_open,
- .close = snd_intelmad_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_intelmad_hw_params,
- .hw_free = snd_intelmad_hw_free,
- .prepare = snd_intelmad_pcm_prepare,
- .trigger = snd_intelmad_pcm_trigger,
- .pointer = snd_intelmad_pcm_pointer,
-};
-
-static struct snd_pcm_ops snd_intelmad_capture_ops = {
- .open = snd_intelmad_headset_open,
- .close = snd_intelmad_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_intelmad_hw_params,
- .hw_free = snd_intelmad_hw_free,
- .prepare = snd_intelmad_pcm_prepare,
- .trigger = snd_intelmad_pcm_trigger,
- .pointer = snd_intelmad_pcm_pointer,
-};
-
-int intelmad_get_mic_bias(void)
-{
- struct snd_pmic_ops *pmic_ops;
-
- if (!intelmad_drv || !intelmad_drv->sstdrv_ops)
- return -ENODEV;
- pmic_ops = intelmad_drv->sstdrv_ops->scard_ops;
- if (pmic_ops && pmic_ops->pmic_get_mic_bias)
- return pmic_ops->pmic_get_mic_bias(intelmad_drv);
- else
- return -ENODEV;
-}
-EXPORT_SYMBOL_GPL(intelmad_get_mic_bias);
-
-int intelmad_set_headset_state(int state)
-{
- struct snd_pmic_ops *pmic_ops;
-
- if (!intelmad_drv || !intelmad_drv->sstdrv_ops)
- return -ENODEV;
- pmic_ops = intelmad_drv->sstdrv_ops->scard_ops;
- if (pmic_ops && pmic_ops->pmic_set_headset_state)
- return pmic_ops->pmic_set_headset_state(state);
- else
- return -ENODEV;
-}
-EXPORT_SYMBOL_GPL(intelmad_set_headset_state);
-
-void sst_process_mad_jack_detection(struct work_struct *work)
-{
- u8 interrupt_status;
- struct mad_jack_msg_wq *mad_jack_detect =
- container_of(work, struct mad_jack_msg_wq, wq);
-
- struct snd_intelmad *intelmaddata =
- mad_jack_detect->intelmaddata;
-
- if (!intelmaddata)
- return;
-
- interrupt_status = mad_jack_detect->intsts;
- if (intelmaddata->sstdrv_ops && intelmaddata->sstdrv_ops->scard_ops
- && intelmaddata->sstdrv_ops->scard_ops->pmic_irq_cb) {
- intelmaddata->sstdrv_ops->scard_ops->pmic_irq_cb(
- (void *)intelmaddata, interrupt_status);
- intelmaddata->sstdrv_ops->scard_ops->pmic_jack_enable();
- }
- kfree(mad_jack_detect);
-}
-/**
- * snd_intelmad_intr_handler- interrupt handler
- *
- * @irq : irq number of the interrupt received
- * @dev: device context
- *
- * This function is called when an interrupt is raised at the sound card
- */
-static irqreturn_t snd_intelmad_intr_handler(int irq, void *dev)
-{
- struct snd_intelmad *intelmaddata =
- (struct snd_intelmad *)dev;
- u8 interrupt_status;
- struct mad_jack_msg_wq *mad_jack_msg;
- memcpy_fromio(&interrupt_status,
- ((void *)(intelmaddata->int_base)),
- sizeof(u8));
-
- mad_jack_msg = kzalloc(sizeof(*mad_jack_msg), GFP_ATOMIC);
- mad_jack_msg->intsts = interrupt_status;
- mad_jack_msg->intelmaddata = intelmaddata;
- INIT_WORK(&mad_jack_msg->wq, sst_process_mad_jack_detection);
- queue_work(intelmaddata->mad_jack_wq, &mad_jack_msg->wq);
-
- return IRQ_HANDLED;
-}
-
-void sst_mad_send_jack_report(struct snd_jack *jack,
- int buttonpressevent , int status)
-{
-
- if (!jack) {
- pr_debug("MAD error jack empty\n");
-
- } else {
- snd_jack_report(jack, status);
- /* button pressed and released */
- if (buttonpressevent)
- snd_jack_report(jack, 0);
- pr_debug("MAD sending jack report Done !!!\n");
- }
-}
-
-static int __devinit snd_intelmad_register_irq(
- struct snd_intelmad *intelmaddata, unsigned int regbase,
- unsigned int regsize)
-{
- int ret_val;
- char *drv_name;
-
- pr_debug("irq reg regbase 0x%x, regsize 0x%x\n",
- regbase, regsize);
- intelmaddata->int_base = ioremap_nocache(regbase, regsize);
- if (!intelmaddata->int_base)
- pr_err("Mapping of cache failed\n");
- pr_debug("irq = 0x%x\n", intelmaddata->irq);
- if (intelmaddata->cpu_id == CPU_CHIP_PENWELL)
- drv_name = DRIVER_NAME_MFLD;
- else
- drv_name = DRIVER_NAME_MRST;
- ret_val = request_irq(intelmaddata->irq,
- snd_intelmad_intr_handler,
- IRQF_SHARED, drv_name,
- intelmaddata);
- if (ret_val)
- pr_err("cannot register IRQ\n");
- return ret_val;
-}
-
-static int __devinit snd_intelmad_sst_register(
- struct snd_intelmad *intelmaddata)
-{
- int ret_val = 0;
- struct snd_pmic_ops *intelmad_vendor_ops[MAX_VENDORS] = {
- &snd_pmic_ops_fs,
- &snd_pmic_ops_mx,
- &snd_pmic_ops_nc,
- &snd_msic_ops
- };
-
- struct sc_reg_access vendor_addr = {0x00, 0x00, 0x00};
-
- if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) {
- ret_val = sst_sc_reg_access(&vendor_addr, PMIC_READ, 1);
- if (ret_val)
- return ret_val;
- sst_card_vendor_id = (vendor_addr.value & (MASK2|MASK1|MASK0));
- pr_debug("original n extrated vendor id = 0x%x %d\n",
- vendor_addr.value, sst_card_vendor_id);
- if (sst_card_vendor_id < 0 || sst_card_vendor_id > 2) {
- pr_err("vendor card not supported!!\n");
- return -EIO;
- }
- } else
- sst_card_vendor_id = 0x3;
-
- intelmaddata->sstdrv_ops->module_name = SST_CARD_NAMES;
- intelmaddata->sstdrv_ops->vendor_id = sst_card_vendor_id;
- BUG_ON(!intelmad_vendor_ops[sst_card_vendor_id]);
- intelmaddata->sstdrv_ops->scard_ops =
- intelmad_vendor_ops[sst_card_vendor_id];
-
- if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
- intelmaddata->sstdrv_ops->scard_ops->pb_on = 0;
- intelmaddata->sstdrv_ops->scard_ops->cap_on = 0;
- intelmaddata->sstdrv_ops->scard_ops->input_dev_id = DMIC;
- intelmaddata->sstdrv_ops->scard_ops->output_dev_id =
- STEREO_HEADPHONE;
- intelmaddata->sstdrv_ops->scard_ops->lineout_dev_id = NONE;
- }
-
- /* registering with SST driver to get access to SST APIs to use */
- ret_val = register_sst_card(intelmaddata->sstdrv_ops);
- if (ret_val) {
- pr_err("sst card registration failed\n");
- return ret_val;
- }
- sst_card_vendor_id = intelmaddata->sstdrv_ops->vendor_id;
- intelmaddata->pmic_status = PMIC_UNINIT;
- return ret_val;
-}
-
-static void snd_intelmad_page_free(struct snd_pcm *pcm)
-{
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-/* Driver Init/exit functionalities */
-/**
- * snd_intelmad_pcm_new - to setup pcm for the card
- *
- * @card: pointer to the sound card structure
- * @intelmaddata: pointer to internal context
- * @pb: playback count for this card
- * @cap: capture count for this card
- * @index: device index
- *
- * This function is called from probe function to set up pcm params
- * and functions
- */
-static int __devinit snd_intelmad_pcm_new(struct snd_card *card,
- struct snd_intelmad *intelmaddata,
- unsigned int pb, unsigned int cap, unsigned int index)
-{
- int ret_val = 0;
- struct snd_pcm *pcm;
- char name[32] = INTEL_MAD;
- struct snd_pcm_ops *pb_ops = NULL, *cap_ops = NULL;
-
- pr_debug("called for pb %d, cp %d, idx %d\n", pb, cap, index);
- ret_val = snd_pcm_new(card, name, index, pb, cap, &pcm);
- if (ret_val)
- return ret_val;
- /* setup the ops for playback and capture streams */
- switch (index) {
- case 0:
- pb_ops = &snd_intelmad_headset_ops;
- cap_ops = &snd_intelmad_capture_ops;
- break;
- case 1:
- pb_ops = &snd_intelmad_ihf_ops;
- cap_ops = &snd_intelmad_capture_ops;
- break;
- case 2:
- pb_ops = &snd_intelmad_vibra_ops;
- cap_ops = &snd_intelmad_capture_ops;
- break;
- case 3:
- pb_ops = &snd_intelmad_haptic_ops;
- cap_ops = &snd_intelmad_capture_ops;
- break;
- }
- if (pb)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, pb_ops);
- if (cap)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, cap_ops);
- /* setup private data which can be retrieved when required */
- pcm->private_data = intelmaddata;
- pcm->private_free = snd_intelmad_page_free;
- pcm->info_flags = 0;
- strncpy(pcm->name, card->shortname, strlen(card->shortname));
- /* allocate dma pages for ALSA stream operations */
- snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL),
- MIN_BUFFER, MAX_BUFFER);
- return ret_val;
-}
-
-static int __devinit snd_intelmad_pcm(struct snd_card *card,
- struct snd_intelmad *intelmaddata)
-{
- int ret_val = 0;
-
- WARN_ON(!card);
- WARN_ON(!intelmaddata);
- pr_debug("snd_intelmad_pcm called\n");
- ret_val = snd_intelmad_pcm_new(card, intelmaddata, 1, 1, 0);
- if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT)
- return ret_val;
- ret_val = snd_intelmad_pcm_new(card, intelmaddata, 1, 0, 1);
- if (ret_val)
- return ret_val;
- ret_val = snd_intelmad_pcm_new(card, intelmaddata, 1, 0, 2);
- if (ret_val)
- return ret_val;
- return snd_intelmad_pcm_new(card, intelmaddata, 1, 0, 3);
-}
-
-/**
- * snd_intelmad_jack- to setup jack settings of the card
- *
- * @intelmaddata: pointer to internal context
- *
- * This function is called send jack events
- */
-static int snd_intelmad_jack(struct snd_intelmad *intelmaddata)
-{
- struct snd_jack *jack;
- int retval;
-
- pr_debug("snd_intelmad_jack called\n");
- jack = &intelmaddata->jack[0].jack;
- snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PHONE);
- retval = snd_jack_new(intelmaddata->card, "Intel(R) MID Audio Jack",
- SND_JACK_HEADPHONE | SND_JACK_HEADSET |
- SW_JACK_PHYSICAL_INSERT | SND_JACK_BTN_0
- | SND_JACK_BTN_1, &jack);
- pr_debug("snd_intelmad_jack called\n");
- if (retval < 0)
- return retval;
- snd_jack_report(jack, 0);
-
- jack->private_data = jack;
- intelmaddata->jack[0].jack = *jack;
-
- return retval;
-}
-
-/**
- * snd_intelmad_mixer- to setup mixer settings of the card
- *
- * @intelmaddata: pointer to internal context
- *
- * This function is called from probe function to set up mixer controls
- */
-static int __devinit snd_intelmad_mixer(struct snd_intelmad *intelmaddata)
-{
- struct snd_card *card;
- unsigned int idx;
- int ret_val = 0, max_controls = 0;
- char *mixername = "IntelMAD Controls";
- struct snd_kcontrol_new *controls;
-
- WARN_ON(!intelmaddata);
-
- card = intelmaddata->card;
- strncpy(card->mixername, mixername, sizeof(card->mixername)-1);
- /* add all widget controls and expose the same */
- if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
- max_controls = MAX_CTRL_MFLD;
- controls = snd_intelmad_controls_mfld;
- } else {
- max_controls = MAX_CTRL_MRST;
- controls = snd_intelmad_controls_mrst;
- }
- for (idx = 0; idx < max_controls; idx++) {
- ret_val = snd_ctl_add(card,
- snd_ctl_new1(&controls[idx],
- intelmaddata));
- pr_debug("mixer[idx]=%d added\n", idx);
- if (ret_val) {
- pr_err("in adding of control index = %d\n", idx);
- break;
- }
- }
- return ret_val;
-}
-
-static int snd_intelmad_dev_free(struct snd_device *device)
-{
- struct snd_intelmad *intelmaddata;
-
- WARN_ON(!device);
-
- intelmaddata = device->device_data;
-
- pr_debug("snd_intelmad_dev_free called\n");
- unregister_sst_card(intelmaddata->sstdrv_ops);
-
- /* free allocated memory for internal context */
- destroy_workqueue(intelmaddata->mad_jack_wq);
- device->device_data = NULL;
- kfree(intelmaddata->sstdrv_ops);
- kfree(intelmaddata);
-
- return 0;
-}
-
-static int __devinit snd_intelmad_create(
- struct snd_intelmad *intelmaddata,
- struct snd_card *card)
-{
- int ret_val;
- static struct snd_device_ops ops = {
- .dev_free = snd_intelmad_dev_free,
- };
-
- WARN_ON(!intelmaddata);
- WARN_ON(!card);
- /* ALSA api to register for the device */
- ret_val = snd_device_new(card, SNDRV_DEV_LOWLEVEL, intelmaddata, &ops);
- return ret_val;
-}
-
-/**
-* snd_intelmad_probe- function registred for init
-* @pdev : pointer to the device struture
-* This function is called when the device is initialized
-*/
-int __devinit snd_intelmad_probe(struct platform_device *pdev)
-{
- struct snd_card *card;
- int ret_val;
- struct snd_intelmad *intelmaddata;
- const struct platform_device_id *id = platform_get_device_id(pdev);
- struct snd_intelmad_probe_info *info = (void *)id->driver_data;
-
- pr_debug("probe for %s cpu_id %d\n", pdev->name, info->cpu_id);
- pr_debug("rq_chache %x of size %x\n", info->irq_cache, info->size);
- if (!strcmp(pdev->name, DRIVER_NAME_MRST))
- pr_debug("detected MRST\n");
- else if (!strcmp(pdev->name, DRIVER_NAME_MFLD))
- pr_debug("detected MFLD\n");
- else {
- pr_err("detected unknown device abort!!\n");
- return -EIO;
- }
- if ((info->cpu_id < CPU_CHIP_LINCROFT) ||
- (info->cpu_id > CPU_CHIP_PENWELL)) {
- pr_err("detected unknown cpu_id abort!!\n");
- return -EIO;
- }
- /* allocate memory for saving internal context and working */
- intelmaddata = kzalloc(sizeof(*intelmaddata), GFP_KERNEL);
- if (!intelmaddata) {
- pr_debug("mem alloctn fail\n");
- return -ENOMEM;
- }
- intelmad_drv = intelmaddata;
-
- /* allocate memory for LPE API set */
- intelmaddata->sstdrv_ops = kzalloc(sizeof(struct intel_sst_card_ops),
- GFP_KERNEL);
- if (!intelmaddata->sstdrv_ops) {
- pr_err("mem allocation for ops fail\n");
- kfree(intelmaddata);
- return -ENOMEM;
- }
-
- intelmaddata->cpu_id = info->cpu_id;
- /* create a card instance with ALSA framework */
- ret_val = snd_card_create(card_index, card_id, THIS_MODULE, 0, &card);
- if (ret_val) {
- pr_err("snd_card_create fail\n");
- goto free_allocs;
- }
-
- intelmaddata->pdev = pdev;
- intelmaddata->irq = platform_get_irq(pdev, 0);
- platform_set_drvdata(pdev, intelmaddata);
- intelmaddata->card = card;
- intelmaddata->card_id = card_id;
- intelmaddata->card_index = card_index;
- intelmaddata->master_mute = UNMUTE;
- intelmaddata->playback_cnt = intelmaddata->capture_cnt = 0;
- strncpy(card->driver, INTEL_MAD, strlen(INTEL_MAD));
- strncpy(card->shortname, INTEL_MAD, strlen(INTEL_MAD));
-
- intelmaddata->sstdrv_ops->module_name = SST_CARD_NAMES;
- /* registering with LPE driver to get access to SST APIs to use */
- ret_val = snd_intelmad_sst_register(intelmaddata);
- if (ret_val) {
- pr_err("snd_intelmad_sst_register failed\n");
- goto set_null_data;
- }
-
- intelmaddata->pmic_status = PMIC_INIT;
-
- ret_val = snd_intelmad_pcm(card, intelmaddata);
- if (ret_val) {
- pr_err("snd_intelmad_pcm failed\n");
- goto free_sst;
- }
-
- ret_val = snd_intelmad_mixer(intelmaddata);
- if (ret_val) {
- pr_err("snd_intelmad_mixer failed\n");
- goto free_card;
- }
-
- ret_val = snd_intelmad_jack(intelmaddata);
- if (ret_val) {
- pr_err("snd_intelmad_jack failed\n");
- goto free_card;
- }
- intelmaddata->adc_address = mid_initialize_adc();
-
- /*create work queue for jack interrupt*/
- INIT_WORK(&intelmaddata->mad_jack_msg.wq,
- sst_process_mad_jack_detection);
-
- intelmaddata->mad_jack_wq = create_workqueue("sst_mad_jack_wq");
- if (!intelmaddata->mad_jack_wq)
- goto free_card;
-
- ret_val = snd_intelmad_register_irq(intelmaddata,
- info->irq_cache, info->size);
- if (ret_val) {
- pr_err("snd_intelmad_register_irq fail\n");
- goto free_mad_jack_wq;
- }
-
- /* internal function call to register device with ALSA */
- ret_val = snd_intelmad_create(intelmaddata, card);
- if (ret_val) {
- pr_err("snd_intelmad_create failed\n");
- goto set_pvt_data;
- }
- card->private_data = &intelmaddata;
- snd_card_set_dev(card, &pdev->dev);
- ret_val = snd_card_register(card);
- if (ret_val) {
- pr_err("snd_card_register failed\n");
- goto set_pvt_data;
- }
- if (pdev->dev.platform_data) {
- int gpio_amp = *(int *)pdev->dev.platform_data;
- if (gpio_request_one(gpio_amp, GPIOF_OUT_INIT_LOW, "amp power"))
- gpio_amp = 0;
- intelmaddata->sstdrv_ops->scard_ops->gpio_amp = gpio_amp;
- }
-
- pr_debug("snd_intelmad_probe complete\n");
- return ret_val;
-
-set_pvt_data:
- card->private_data = NULL;
-free_mad_jack_wq:
- destroy_workqueue(intelmaddata->mad_jack_wq);
-free_card:
- snd_card_free(intelmaddata->card);
-free_sst:
- unregister_sst_card(intelmaddata->sstdrv_ops);
-set_null_data:
- platform_set_drvdata(pdev, NULL);
-free_allocs:
- pr_err("probe failed\n");
- snd_card_free(card);
- kfree(intelmaddata->sstdrv_ops);
- kfree(intelmaddata);
- return ret_val;
-}
-
-
-static int snd_intelmad_remove(struct platform_device *pdev)
-{
- struct snd_intelmad *intelmaddata = platform_get_drvdata(pdev);
-
- if (intelmaddata) {
- if (intelmaddata->sstdrv_ops->scard_ops->gpio_amp)
- gpio_free(intelmaddata->sstdrv_ops->scard_ops->gpio_amp);
- free_irq(intelmaddata->irq, intelmaddata);
- snd_card_free(intelmaddata->card);
- }
- intelmad_drv = NULL;
- platform_set_drvdata(pdev, NULL);
- return 0;
-}
-
-/*********************************************************************
- * Driver initialization and exit
- *********************************************************************/
-static const struct platform_device_id snd_intelmad_ids[] = {
- {DRIVER_NAME_MRST, INFO(CPU_CHIP_LINCROFT, AUDINT_BASE, 1)},
- {DRIVER_NAME_MFLD, INFO(CPU_CHIP_PENWELL, 0xFFFF7FCD, 1)},
- {"", 0},
-
-};
-
-static struct platform_driver snd_intelmad_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "intel_mid_sound_card",
- },
- .id_table = snd_intelmad_ids,
- .probe = snd_intelmad_probe,
- .remove = __devexit_p(snd_intelmad_remove),
-};
-
-/*
- * alsa_card_intelmad_init- driver init function
- *
- * This function is called when driver module is inserted
- */
-static int __init alsa_card_intelmad_init(void)
-{
- pr_debug("mad_init called\n");
- return platform_driver_register(&snd_intelmad_driver);
-}
-
-/**
- * alsa_card_intelmad_exit- driver exit function
- *
- * This function is called when driver module is removed
- */
-static void __exit alsa_card_intelmad_exit(void)
-{
- pr_debug("mad_exit called\n");
- return platform_driver_unregister(&snd_intelmad_driver);
-}
-
-module_init(alsa_card_intelmad_init)
-module_exit(alsa_card_intelmad_exit)
-
diff --git a/drivers/staging/intel_sst/intelmid.h b/drivers/staging/intel_sst/intelmid.h
deleted file mode 100644
index 14a7ba078b7c..000000000000
--- a/drivers/staging/intel_sst/intelmid.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * intelmid.h - Intel Sound card driver for MID
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Harsha Priya <priya.harsha@intel.com>
- * Vinod Koul <vinod.koul@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * ALSA driver header for Intel MAD chipset
- */
-#ifndef __INTELMID_H
-#define __INTELMID_H
-
-#include <linux/time.h>
-#include <sound/jack.h>
-
-#define DRIVER_NAME_MFLD "msic_audio"
-#define DRIVER_NAME_MRST "pmic_audio"
-#define DRIVER_NAME "intelmid_audio"
-#define PMIC_SOUND_IRQ_TYPE_MASK (1 << 15)
-#define AUDINT_BASE (0xFFFFEFF8 + (6 * sizeof(u8)))
-#define REG_IRQ
-/* values #defined */
-/* will differ for different hw - to be taken from config */
-#define MAX_DEVICES 1
-#define MIN_RATE 8000
-#define MAX_RATE 48000
-#define MAX_BUFFER (800*1024) /* for PCM */
-#define MIN_BUFFER (800*1024)
-#define MAX_PERIODS (1024*2)
-#define MIN_PERIODS 2
-#define MAX_PERIOD_BYTES MAX_BUFFER
-#define MIN_PERIOD_BYTES 32
-/*#define MIN_PERIOD_BYTES 160*/
-#define MAX_MUTE 1
-#define MIN_MUTE 0
-#define MONO_CNTL 1
-#define STEREO_CNTL 2
-#define MIN_CHANNEL 1
-#define MAX_CHANNEL_AMIC 2
-#define MAX_CHANNEL_DMIC 5
-#define FIFO_SIZE 0 /* fifo not being used */
-#define INTEL_MAD "Intel MAD"
-#define MAX_CTRL_MRST 8
-#define MAX_CTRL_MFLD 7
-#define MAX_CTRL 8
-#define MAX_VENDORS 4
-/* TODO +6 db */
-#define MAX_VOL 64
-/* TODO -57 db */
-#define MIN_VOL 0
-#define PLAYBACK_COUNT 1
-#define CAPTURE_COUNT 1
-#define ADC_ONE_LSB_MULTIPLIER 2346
-
-#define MID_JACK_HS_LONG_PRESS SND_JACK_BTN_0
-#define MID_JACK_HS_SHORT_PRESS SND_JACK_BTN_1
-
-extern int sst_card_vendor_id;
-
-struct mad_jack {
- struct snd_jack jack;
- int jack_status;
- int jack_dev_state;
- struct timeval buttonpressed;
- struct timeval buttonreleased;
-};
-
-struct mad_jack_msg_wq {
- u8 intsts;
- struct snd_intelmad *intelmaddata;
- struct work_struct wq;
-
-};
-
-struct snd_intelmad_probe_info {
- unsigned int cpu_id;
- unsigned int irq_cache;
- unsigned int size;
-};
-
-/**
- * struct snd_intelmad - intelmad driver structure
- *
- * @card: ptr to the card details
- * @card_index: sound card index
- * @card_id: sound card id detected
- * @sstdrv_ops: ptr to sst driver ops
- * @pdev: ptr to platform device
- * @irq: interrupt number detected
- * @pmic_status: Device status of sound card
- * @int_base: ptr to MMIO interrupt region
- * @output_sel: device selected as o/p
- * @input_sel: device selected as i/p
- * @master_mute: master mute status
- * @jack: jack status
- * @playback_cnt: active pb streams
- * @capture_cnt: active cp streams
- * @mad_jack_msg: wq struct for jack interrupt processing
- * @mad_jack_wq: wq for jack interrupt processing
- * @jack_prev_state: Previos state of jack detected
- * @cpu_id: current cpu id loaded for
- */
-struct snd_intelmad {
- struct snd_card *card; /* ptr to the card details */
- int card_index;/* card index */
- char *card_id; /* card id */
- struct intel_sst_card_ops *sstdrv_ops;/* ptr to sst driver ops */
- struct platform_device *pdev;
- int irq;
- int pmic_status;
- void __iomem *int_base;
- int output_sel;
- int input_sel;
- int lineout_sel;
- int master_mute;
- struct mad_jack jack[4];
- int playback_cnt;
- int capture_cnt;
- u16 adc_address;
- struct mad_jack_msg_wq mad_jack_msg;
- struct workqueue_struct *mad_jack_wq;
- u8 jack_prev_state;
- unsigned int cpu_id;
-};
-
-struct snd_control_val {
- int playback_vol_max;
- int playback_vol_min;
- int capture_vol_max;
- int capture_vol_min;
- int master_vol_max;
- int master_vol_min;
-};
-
-struct mad_stream_pvt {
- int stream_status;
- int stream_ops;
- struct snd_pcm_substream *substream;
- struct pcm_stream_info stream_info;
- ssize_t dbg_cum_bytes;
- enum snd_sst_device_type device;
-};
-
-enum mad_drv_status {
- INIT = 1,
- STARTED,
- RUNNING,
- PAUSED,
- DROPPED,
-};
-
-enum mad_pmic_status {
- PMIC_UNINIT = 1,
- PMIC_INIT,
-};
-enum _widget_ctrl {
- OUTPUT_SEL = 1,
- INPUT_SEL,
- PLAYBACK_VOL,
- PLAYBACK_MUTE,
- CAPTURE_VOL,
- CAPTURE_MUTE,
- MASTER_VOL,
- MASTER_MUTE
-};
-enum _widget_ctrl_mfld {
- LINEOUT_SEL_MFLD = 3,
-};
-enum hw_chs {
- HW_CH0 = 0,
- HW_CH1,
- HW_CH2,
- HW_CH3
-};
-
-void period_elapsed(void *mad_substream);
-int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream);
-int snd_intelmad_init_stream(struct snd_pcm_substream *substream);
-
-int sst_sc_reg_access(struct sc_reg_access *sc_access,
- int type, int num_val);
-#define CPU_CHIP_LINCROFT 1 /* System running lincroft */
-#define CPU_CHIP_PENWELL 2 /* System running penwell */
-
-extern struct snd_control_val intelmad_ctrl_val[];
-extern struct snd_kcontrol_new snd_intelmad_controls_mrst[];
-extern struct snd_kcontrol_new snd_intelmad_controls_mfld[];
-extern struct snd_pmic_ops *intelmad_vendor_ops[];
-void sst_mad_send_jack_report(struct snd_jack *jack,
- int buttonpressevent , int status);
-
-#endif /* __INTELMID_H */
diff --git a/drivers/staging/intel_sst/intelmid_adc_control.h b/drivers/staging/intel_sst/intelmid_adc_control.h
deleted file mode 100644
index 65d5c3988762..000000000000
--- a/drivers/staging/intel_sst/intelmid_adc_control.h
+++ /dev/null
@@ -1,193 +0,0 @@
-#ifndef __INTELMID_ADC_CONTROL_H__
-#define __INTELMID_ADC_CONTROL_H_
-/*
- * intelmid_adc_control.h - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corporation
- * Authors: R Durgadadoss <r.durgadoss@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * Common private ADC declarations for SST
- */
-
-
-#define MSIC_ADC1CNTL1 0x1C0
-#define MSIC_ADC_ENBL 0x10
-#define MSIC_ADC_START 0x08
-
-#define MSIC_ADC1CNTL3 0x1C2
-#define MSIC_ADCTHERM_ENBL 0x04
-#define MSIC_ADCRRDATA_ENBL 0x05
-
-#define MSIC_STOPBIT_MASK 16
-#define MSIC_ADCTHERM_MASK 4
-
-#define ADC_CHANLS_MAX 15 /* Number of ADC channels */
-#define ADC_LOOP_MAX (ADC_CHANLS_MAX - 1)
-
-/* ADC channel code values */
-#define AUDIO_DETECT_CODE 0x06
-
-/* ADC base addresses */
-#define ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */
-#define ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */
-
-
-/**
- * configure_adc - enables/disables the ADC for conversion
- * @val: zero: disables the ADC non-zero:enables the ADC
- *
- * Enable/Disable the ADC depending on the argument
- *
- * Can sleep
- */
-static inline int configure_adc(int val)
-{
- int ret;
- struct sc_reg_access sc_access = {0,};
-
-
- sc_access.reg_addr = MSIC_ADC1CNTL1;
- ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
- if (ret)
- return ret;
-
- if (val)
- /* Enable and start the ADC */
- sc_access.value |= (MSIC_ADC_ENBL | MSIC_ADC_START);
- else
- /* Just stop the ADC */
- sc_access.value &= (~MSIC_ADC_START);
- sc_access.reg_addr = MSIC_ADC1CNTL1;
- return sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
-}
-
-/**
- * reset_stopbit - sets the stop bit to 0 on the given channel
- * @addr: address of the channel
- *
- * Can sleep
- */
-static inline int reset_stopbit(uint16_t addr)
-{
- int ret;
- struct sc_reg_access sc_access = {0,};
- sc_access.reg_addr = addr;
- ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
- if (ret)
- return ret;
- /* Set the stop bit to zero */
- sc_access.reg_addr = addr;
- sc_access.value = (sc_access.value) & 0xEF;
- return sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
-}
-
-/**
- * find_free_channel - finds an empty channel for conversion
- *
- * If the ADC is not enabled then start using 0th channel
- * itself. Otherwise find an empty channel by looking for a
- * channel in which the stopbit is set to 1. returns the index
- * of the first free channel if succeeds or an error code.
- *
- * Context: can sleep
- *
- */
-static inline int find_free_channel(void)
-{
- int ret;
- int i;
-
- struct sc_reg_access sc_access = {0,};
-
- /* check whether ADC is enabled */
- sc_access.reg_addr = MSIC_ADC1CNTL1;
- ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
- if (ret)
- return ret;
-
- if ((sc_access.value & MSIC_ADC_ENBL) == 0)
- return 0;
-
- /* ADC is already enabled; Looking for an empty channel */
- for (i = 0; i < ADC_CHANLS_MAX; i++) {
-
- sc_access.reg_addr = ADC_CHNL_START_ADDR + i;
- ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
- if (ret)
- return ret;
-
- if (sc_access.value & MSIC_STOPBIT_MASK) {
- ret = i;
- break;
- }
- }
- return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
-}
-
-/**
- * mid_initialize_adc - initializing the ADC
- * @dev: our device structure
- *
- * Initialize the ADC for reading thermistor values. Can sleep.
- */
-static inline int mid_initialize_adc(void)
-{
- int base_addr, chnl_addr;
- int ret;
- static int channel_index;
- struct sc_reg_access sc_access = {0,};
-
- /* Index of the first channel in which the stop bit is set */
- channel_index = find_free_channel();
- if (channel_index < 0) {
- pr_err("No free ADC channels");
- return channel_index;
- }
-
- base_addr = ADC_CHNL_START_ADDR + channel_index;
-
- if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
- /* Reset stop bit for channels other than 0 and 12 */
- ret = reset_stopbit(base_addr);
- if (ret)
- return ret;
-
- /* Index of the first free channel */
- base_addr++;
- channel_index++;
- }
-
- /* Since this is the last channel, set the stop bit
- to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
- sc_access.reg_addr = base_addr;
- sc_access.value = AUDIO_DETECT_CODE | 0x10;
- ret = sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
- if (ret) {
- pr_err("unable to enable ADC");
- return ret;
- }
-
- chnl_addr = ADC_DATA_START_ADDR + 2 * channel_index;
- pr_debug("mid_initialize : %x", chnl_addr);
- configure_adc(1);
- return chnl_addr;
-}
-#endif
-
diff --git a/drivers/staging/intel_sst/intelmid_ctrl.c b/drivers/staging/intel_sst/intelmid_ctrl.c
deleted file mode 100644
index 19ec474b362a..000000000000
--- a/drivers/staging/intel_sst/intelmid_ctrl.c
+++ /dev/null
@@ -1,921 +0,0 @@
-/*
- * intelmid_ctrl.c - Intel Sound card driver for MID
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Harsha Priya <priya.harsha@intel.com>
- * Vinod Koul <vinod.koul@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * ALSA driver handling mixer controls for Intel MAD chipset
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <sound/core.h>
-#include <sound/control.h>
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intelmid_snd_control.h"
-#include "intelmid.h"
-
-#define HW_CH_BASE 4
-
-
-#define HW_CH_0 "Hw1"
-#define HW_CH_1 "Hw2"
-#define HW_CH_2 "Hw3"
-#define HW_CH_3 "Hw4"
-
-static char *router_dmics[] = { "DMIC1",
- "DMIC2",
- "DMIC3",
- "DMIC4",
- "DMIC5",
- "DMIC6"
- };
-
-static char *out_names_mrst[] = {"Headphones",
- "Internal speakers"};
-static char *in_names_mrst[] = {"AMIC",
- "DMIC",
- "HS_MIC"};
-static char *line_out_names_mfld[] = {"Headset",
- "IHF ",
- "Vibra1 ",
- "Vibra2 ",
- "NONE "};
-static char *out_names_mfld[] = {"Headset ",
- "EarPiece "};
-static char *in_names_mfld[] = {"AMIC",
- "DMIC"};
-
-struct snd_control_val intelmad_ctrl_val[MAX_VENDORS] = {
- {
- .playback_vol_max = 63,
- .playback_vol_min = 0,
- .capture_vol_max = 63,
- .capture_vol_min = 0,
- },
- {
- .playback_vol_max = 0,
- .playback_vol_min = -31,
- .capture_vol_max = 0,
- .capture_vol_min = -20,
- },
- {
- .playback_vol_max = 0,
- .playback_vol_min = -31,
- .capture_vol_max = 0,
- .capture_vol_min = -31,
- .master_vol_max = 0,
- .master_vol_min = -126,
- },
-};
-
-/* control path functionalities */
-
-static inline int snd_intelmad_volume_info(struct snd_ctl_elem_info *uinfo,
- int control_type, int max, int min)
-{
- WARN_ON(!uinfo);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = control_type;
- uinfo->value.integer.min = min;
- uinfo->value.integer.max = max;
- return 0;
-}
-
-/**
-* snd_intelmad_mute_info - provides information about the mute controls
-*
-* @kcontrol: pointer to the control
-* @uinfo: pointer to the structure where the control's info need
-* to be filled
-*
-* This function is called when a mixer application requests for control's info
-*/
-static int snd_intelmad_mute_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- WARN_ON(!uinfo);
- WARN_ON(!kcontrol);
-
- /* set up the mute as a boolean mono control with min-max values */
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = MONO_CNTL;
- uinfo->value.integer.min = MIN_MUTE;
- uinfo->value.integer.max = MAX_MUTE;
- return 0;
-}
-
-/**
-* snd_intelmad_capture_volume_info - provides info about the volume control
-*
-* @kcontrol: pointer to the control
-* @uinfo: pointer to the structure where the control's info need
-* to be filled
-*
-* This function is called when a mixer application requests for control's info
-*/
-static int snd_intelmad_capture_volume_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- snd_intelmad_volume_info(uinfo, MONO_CNTL,
- intelmad_ctrl_val[sst_card_vendor_id].capture_vol_max,
- intelmad_ctrl_val[sst_card_vendor_id].capture_vol_min);
- return 0;
-}
-
-/**
-* snd_intelmad_playback_volume_info - provides info about the volume control
-*
-* @kcontrol: pointer to the control
-* @uinfo: pointer to the structure where the control's info need
-* to be filled
-*
-* This function is called when a mixer application requests for control's info
-*/
-static int snd_intelmad_playback_volume_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- snd_intelmad_volume_info(uinfo, STEREO_CNTL,
- intelmad_ctrl_val[sst_card_vendor_id].playback_vol_max,
- intelmad_ctrl_val[sst_card_vendor_id].playback_vol_min);
- return 0;
-}
-
-static int snd_intelmad_master_volume_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- snd_intelmad_volume_info(uinfo, STEREO_CNTL,
- intelmad_ctrl_val[sst_card_vendor_id].master_vol_max,
- intelmad_ctrl_val[sst_card_vendor_id].master_vol_min);
- return 0;
-}
-
-/**
-* snd_intelmad_device_info_mrst - provides information about the devices available
-*
-* @kcontrol: pointer to the control
-* @uinfo: pointer to the structure where the devices's info need
-* to be filled
-*
-* This function is called when a mixer application requests for device's info
-*/
-static int snd_intelmad_device_info_mrst(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
-
- WARN_ON(!kcontrol);
- WARN_ON(!uinfo);
-
- /* setup device select as drop down controls with different values */
- if (kcontrol->id.numid == OUTPUT_SEL)
- uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mrst);
- else
- uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mrst);
- uinfo->count = MONO_CNTL;
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = 1;
- if (kcontrol->id.numid == OUTPUT_SEL)
- strncpy(uinfo->value.enumerated.name,
- out_names_mrst[uinfo->value.enumerated.item],
- sizeof(uinfo->value.enumerated.name)-1);
- else
- strncpy(uinfo->value.enumerated.name,
- in_names_mrst[uinfo->value.enumerated.item],
- sizeof(uinfo->value.enumerated.name)-1);
- return 0;
-}
-
-static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct snd_pmic_ops *scard_ops;
- struct snd_intelmad *intelmaddata;
-
- WARN_ON(!kcontrol);
- WARN_ON(!uinfo);
-
- intelmaddata = kcontrol->private_data;
-
- WARN_ON(!intelmaddata->sstdrv_ops);
-
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
- /* setup device select as drop down controls with different values */
- if (kcontrol->id.numid == OUTPUT_SEL)
- uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mfld);
- else if (kcontrol->id.numid == INPUT_SEL)
- uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mfld);
- else if (kcontrol->id.numid == LINEOUT_SEL_MFLD) {
- uinfo->value.enumerated.items = ARRAY_SIZE(line_out_names_mfld);
- scard_ops->line_out_names_cnt = uinfo->value.enumerated.items;
- } else
- return -EINVAL;
- uinfo->count = MONO_CNTL;
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = 1;
- if (kcontrol->id.numid == OUTPUT_SEL)
- strncpy(uinfo->value.enumerated.name,
- out_names_mfld[uinfo->value.enumerated.item],
- sizeof(uinfo->value.enumerated.name)-1);
- else if (kcontrol->id.numid == INPUT_SEL)
- strncpy(uinfo->value.enumerated.name,
- in_names_mfld[uinfo->value.enumerated.item],
- sizeof(uinfo->value.enumerated.name)-1);
- else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
- strncpy(uinfo->value.enumerated.name,
- line_out_names_mfld[uinfo->value.enumerated.item],
- sizeof(uinfo->value.enumerated.name)-1);
- else
- return -EINVAL;
- return 0;
-}
-
-/**
-* snd_intelmad_volume_get - gets the current volume for the control
-*
-* @kcontrol: pointer to the control
-* @uval: pointer to the structure where the control's info need
-* to be filled
-*
-* This function is called when .get function of a control is invoked from app
-*/
-static int snd_intelmad_volume_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uval)
-{
- int ret_val = 0, cntl_list[2] = {0,};
- int value = 0;
- struct snd_intelmad *intelmaddata;
- struct snd_pmic_ops *scard_ops;
-
- pr_debug("snd_intelmad_volume_get called\n");
-
- WARN_ON(!uval);
- WARN_ON(!kcontrol);
-
- intelmaddata = kcontrol->private_data;
-
- WARN_ON(!intelmaddata->sstdrv_ops);
-
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-
- WARN_ON(!scard_ops);
-
- switch (kcontrol->id.numid) {
- case PLAYBACK_VOL:
- cntl_list[0] = PMIC_SND_RIGHT_PB_VOL;
- cntl_list[1] = PMIC_SND_LEFT_PB_VOL;
- break;
-
- case CAPTURE_VOL:
- cntl_list[0] = PMIC_SND_CAPTURE_VOL;
- break;
-
- case MASTER_VOL:
- cntl_list[0] = PMIC_SND_RIGHT_MASTER_VOL;
- cntl_list[1] = PMIC_SND_LEFT_MASTER_VOL;
- break;
- default:
- return -EINVAL;
- }
-
- ret_val = scard_ops->get_vol(cntl_list[0], &value);
- uval->value.integer.value[0] = value;
-
- if (ret_val)
- return ret_val;
-
- if (kcontrol->id.numid == PLAYBACK_VOL ||
- kcontrol->id.numid == MASTER_VOL) {
- ret_val = scard_ops->get_vol(cntl_list[1], &value);
- uval->value.integer.value[1] = value;
- }
- return ret_val;
-}
-
-/**
-* snd_intelmad_mute_get - gets the current mute status for the control
-*
-* @kcontrol: pointer to the control
-* @uval: pointer to the structure where the control's info need
-* to be filled
-*
-* This function is called when .get function of a control is invoked from app
-*/
-static int snd_intelmad_mute_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uval)
-{
-
- int cntl_list = 0, ret_val = 0;
- u8 value = 0;
- struct snd_intelmad *intelmaddata;
- struct snd_pmic_ops *scard_ops;
-
- pr_debug("Mute_get called\n");
-
- WARN_ON(!uval);
- WARN_ON(!kcontrol);
-
- intelmaddata = kcontrol->private_data;
-
- WARN_ON(!intelmaddata->sstdrv_ops);
-
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-
- WARN_ON(!scard_ops);
-
- switch (kcontrol->id.numid) {
- case PLAYBACK_MUTE:
- if (intelmaddata->output_sel == STEREO_HEADPHONE)
- cntl_list = PMIC_SND_LEFT_HP_MUTE;
- else if ((intelmaddata->output_sel == INTERNAL_SPKR) ||
- (intelmaddata->output_sel == MONO_EARPIECE))
- cntl_list = PMIC_SND_LEFT_SPEAKER_MUTE;
- break;
-
- case CAPTURE_MUTE:
- if (intelmaddata->input_sel == DMIC)
- cntl_list = PMIC_SND_DMIC_MUTE;
- else if (intelmaddata->input_sel == AMIC)
- cntl_list = PMIC_SND_AMIC_MUTE;
- else if (intelmaddata->input_sel == HS_MIC)
- cntl_list = PMIC_SND_HP_MIC_MUTE;
- break;
- case MASTER_MUTE:
- uval->value.integer.value[0] = intelmaddata->master_mute;
- return 0;
- default:
- return -EINVAL;
- }
-
- ret_val = scard_ops->get_mute(cntl_list, &value);
- uval->value.integer.value[0] = value;
- return ret_val;
-}
-
-/**
-* snd_intelmad_volume_set - sets the volume control's info
-*
-* @kcontrol: pointer to the control
-* @uval: pointer to the structure where the control's info is
-* available to be set
-*
-* This function is called when .set function of a control is invoked from app
-*/
-static int snd_intelmad_volume_set(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uval)
-{
-
- int ret_val, cntl_list[2] = {0,};
- struct snd_intelmad *intelmaddata;
- struct snd_pmic_ops *scard_ops;
-
- pr_debug("volume set called:%ld %ld\n",
- uval->value.integer.value[0],
- uval->value.integer.value[1]);
-
- WARN_ON(!uval);
- WARN_ON(!kcontrol);
-
- intelmaddata = kcontrol->private_data;
-
- WARN_ON(!intelmaddata->sstdrv_ops);
-
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-
- WARN_ON(!scard_ops);
-
- switch (kcontrol->id.numid) {
- case PLAYBACK_VOL:
- cntl_list[0] = PMIC_SND_LEFT_PB_VOL;
- cntl_list[1] = PMIC_SND_RIGHT_PB_VOL;
- break;
-
- case CAPTURE_VOL:
- cntl_list[0] = PMIC_SND_CAPTURE_VOL;
- break;
-
- case MASTER_VOL:
- cntl_list[0] = PMIC_SND_LEFT_MASTER_VOL;
- cntl_list[1] = PMIC_SND_RIGHT_MASTER_VOL;
- break;
-
- default:
- return -EINVAL;
- }
-
- ret_val = scard_ops->set_vol(cntl_list[0],
- uval->value.integer.value[0]);
- if (ret_val)
- return ret_val;
-
- if (kcontrol->id.numid == PLAYBACK_VOL ||
- kcontrol->id.numid == MASTER_VOL)
- ret_val = scard_ops->set_vol(cntl_list[1],
- uval->value.integer.value[1]);
- return ret_val;
-}
-
-/**
-* snd_intelmad_mute_set - sets the mute control's info
-*
-* @kcontrol: pointer to the control
-* @uval: pointer to the structure where the control's info is
-* available to be set
-*
-* This function is called when .set function of a control is invoked from app
-*/
-static int snd_intelmad_mute_set(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uval)
-{
- int cntl_list[2] = {0,}, ret_val;
- struct snd_intelmad *intelmaddata;
- struct snd_pmic_ops *scard_ops;
-
- pr_debug("snd_intelmad_mute_set called\n");
-
- WARN_ON(!uval);
- WARN_ON(!kcontrol);
-
- intelmaddata = kcontrol->private_data;
-
- WARN_ON(!intelmaddata->sstdrv_ops);
-
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-
- WARN_ON(!scard_ops);
-
- kcontrol->private_value = uval->value.integer.value[0];
-
- switch (kcontrol->id.numid) {
- case PLAYBACK_MUTE:
- if (intelmaddata->output_sel == STEREO_HEADPHONE) {
- cntl_list[0] = PMIC_SND_LEFT_HP_MUTE;
- cntl_list[1] = PMIC_SND_RIGHT_HP_MUTE;
- } else if ((intelmaddata->output_sel == INTERNAL_SPKR) ||
- (intelmaddata->output_sel == MONO_EARPIECE)) {
- cntl_list[0] = PMIC_SND_LEFT_SPEAKER_MUTE;
- cntl_list[1] = PMIC_SND_RIGHT_SPEAKER_MUTE;
- }
- break;
-
- case CAPTURE_MUTE:/*based on sel device mute the i/p dev*/
- if (intelmaddata->input_sel == DMIC)
- cntl_list[0] = PMIC_SND_DMIC_MUTE;
- else if (intelmaddata->input_sel == AMIC)
- cntl_list[0] = PMIC_SND_AMIC_MUTE;
- else if (intelmaddata->input_sel == HS_MIC)
- cntl_list[0] = PMIC_SND_HP_MIC_MUTE;
- break;
- case MASTER_MUTE:
- cntl_list[0] = PMIC_SND_MUTE_ALL;
- intelmaddata->master_mute = uval->value.integer.value[0];
- break;
- default:
- return -EINVAL;
- }
-
- ret_val = scard_ops->set_mute(cntl_list[0],
- uval->value.integer.value[0]);
- if (ret_val)
- return ret_val;
-
- if (kcontrol->id.numid == PLAYBACK_MUTE)
- ret_val = scard_ops->set_mute(cntl_list[1],
- uval->value.integer.value[0]);
- return ret_val;
-}
-
-/**
-* snd_intelmad_device_get - get the device select control's info
-*
-* @kcontrol: pointer to the control
-* @uval: pointer to the structure where the control's info is
-* to be filled
-*
-* This function is called when .get function of a control is invoked from app
-*/
-static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uval)
-{
- struct snd_intelmad *intelmaddata;
- struct snd_pmic_ops *scard_ops;
- pr_debug("device_get called\n");
-
- WARN_ON(!uval);
- WARN_ON(!kcontrol);
-
- intelmaddata = kcontrol->private_data;
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
- if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
- if (kcontrol->id.numid == OUTPUT_SEL)
- uval->value.enumerated.item[0] =
- scard_ops->output_dev_id;
- else if (kcontrol->id.numid == INPUT_SEL)
- uval->value.enumerated.item[0] =
- scard_ops->input_dev_id;
- else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
- uval->value.enumerated.item[0] =
- scard_ops->lineout_dev_id;
- else
- return -EINVAL;
- } else if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) {
- if (kcontrol->id.numid == OUTPUT_SEL)
- /* There is a mismatch here.
- * ALSA expects 1 for internal speaker.
- * But internally, we may give 2 for internal speaker.
- */
- if (scard_ops->output_dev_id == MONO_EARPIECE ||
- scard_ops->output_dev_id == INTERNAL_SPKR)
- uval->value.enumerated.item[0] = MONO_EARPIECE;
- else if (scard_ops->output_dev_id == STEREO_HEADPHONE)
- uval->value.enumerated.item[0] =
- STEREO_HEADPHONE;
- else
- return -EINVAL;
- else if (kcontrol->id.numid == INPUT_SEL)
- uval->value.enumerated.item[0] =
- scard_ops->input_dev_id;
- else
- return -EINVAL;
- } else
- uval->value.enumerated.item[0] = kcontrol->private_value;
- return 0;
-}
-
-/**
-* snd_intelmad_device_set - set the device select control's info
-*
-* @kcontrol: pointer to the control
-* @uval: pointer to the structure where the control's info is
-* available to be set
-*
-* This function is called when .set function of a control is invoked from app
-*/
-static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uval)
-{
- struct snd_intelmad *intelmaddata;
- struct snd_pmic_ops *scard_ops;
- int ret_val = 0, vendor, status;
- struct intel_sst_pcm_control *pcm_control;
-
- pr_debug("snd_intelmad_device_set called\n");
-
- WARN_ON(!uval);
- WARN_ON(!kcontrol);
- status = -1;
-
- intelmaddata = kcontrol->private_data;
-
- WARN_ON(!intelmaddata->sstdrv_ops);
-
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-
- WARN_ON(!scard_ops);
-
- /* store value with driver */
- kcontrol->private_value = uval->value.enumerated.item[0];
-
- switch (kcontrol->id.numid) {
- case OUTPUT_SEL:
- ret_val = scard_ops->set_output_dev(
- uval->value.enumerated.item[0]);
- intelmaddata->output_sel = uval->value.enumerated.item[0];
- break;
- case INPUT_SEL:
- vendor = intelmaddata->sstdrv_ops->vendor_id;
- if ((vendor == SND_MX) || (vendor == SND_FS)) {
- pcm_control = intelmaddata->sstdrv_ops->pcm_control;
- if (uval->value.enumerated.item[0] == HS_MIC)
- status = 1;
- else
- status = 0;
- pcm_control->device_control(
- SST_ENABLE_RX_TIME_SLOT, &status);
- }
- ret_val = scard_ops->set_input_dev(
- uval->value.enumerated.item[0]);
- intelmaddata->input_sel = uval->value.enumerated.item[0];
- break;
- case LINEOUT_SEL_MFLD:
- ret_val = scard_ops->set_lineout_dev(
- uval->value.enumerated.item[0]);
- intelmaddata->lineout_sel = uval->value.enumerated.item[0];
- break;
- default:
- return -EINVAL;
- }
- kcontrol->private_value = uval->value.enumerated.item[0];
- return ret_val;
-}
-
-static int snd_intelmad_device_dmic_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uval)
-{
- struct snd_intelmad *intelmaddata;
- struct snd_pmic_ops *scard_ops;
-
- WARN_ON(!uval);
- WARN_ON(!kcontrol);
-
- intelmaddata = kcontrol->private_data;
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-
- if (scard_ops->input_dev_id != DMIC) {
- pr_debug("input dev = 0x%x\n", scard_ops->input_dev_id);
- return 0;
- }
-
- if (intelmaddata->cpu_id == CPU_CHIP_PENWELL)
- uval->value.enumerated.item[0] = kcontrol->private_value;
- else
- pr_debug(" CPU id = 0x%xis invalid.\n",
- intelmaddata->cpu_id);
- return 0;
-}
-
-void msic_set_bit(u8 index, unsigned int *available_dmics)
-{
- *available_dmics |= (1 << index);
-}
-
-void msic_clear_bit(u8 index, unsigned int *available_dmics)
-{
- *available_dmics &= ~(1 << index);
-}
-
-int msic_is_set_bit(u8 index, unsigned int *available_dmics)
-{
- int ret_val;
-
- ret_val = (*available_dmics & (1 << index));
- return ret_val;
-}
-
-static int snd_intelmad_device_dmic_set(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uval)
-{
- struct snd_intelmad *intelmaddata;
- struct snd_pmic_ops *scard_ops;
- int i, dmic_index;
- unsigned int available_dmics;
- int jump_count;
- int max_dmics = ARRAY_SIZE(router_dmics);
-
- WARN_ON(!uval);
- WARN_ON(!kcontrol);
-
- intelmaddata = kcontrol->private_data;
- WARN_ON(!intelmaddata->sstdrv_ops);
-
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
- WARN_ON(!scard_ops);
-
- if (scard_ops->input_dev_id != DMIC) {
- pr_debug("input dev = 0x%x\n", scard_ops->input_dev_id);
- return 0;
- }
-
- available_dmics = scard_ops->available_dmics;
-
- if (kcontrol->private_value > uval->value.enumerated.item[0]) {
- pr_debug("jump count -1.\n");
- jump_count = -1;
- } else {
- pr_debug("jump count 1.\n");
- jump_count = 1;
- }
-
- dmic_index = uval->value.enumerated.item[0];
- pr_debug("set function. dmic_index = %d, avl_dmic = 0x%x\n",
- dmic_index, available_dmics);
- for (i = 0; i < max_dmics; i++) {
- pr_debug("set function. loop index = 0x%x. dmic_index = 0x%x\n",
- i, dmic_index);
- if (!msic_is_set_bit(dmic_index, &available_dmics)) {
- msic_clear_bit(kcontrol->private_value,
- &available_dmics);
- msic_set_bit(dmic_index, &available_dmics);
- kcontrol->private_value = dmic_index;
- scard_ops->available_dmics = available_dmics;
- scard_ops->hw_dmic_map[kcontrol->id.numid-HW_CH_BASE] =
- kcontrol->private_value;
- scard_ops->set_hw_dmic_route
- (kcontrol->id.numid-HW_CH_BASE);
- return 0;
- }
-
- dmic_index += jump_count;
-
- if (dmic_index > (max_dmics - 1) && jump_count == 1) {
- pr_debug("Resettingthe dmic index to 0.\n");
- dmic_index = 0;
- } else if (dmic_index == -1 && jump_count == -1) {
- pr_debug("Resetting the dmic index to 5.\n");
- dmic_index = max_dmics - 1;
- }
- }
-
- return -EINVAL;
-}
-
-static int snd_intelmad_device_dmic_info_mfld(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct snd_intelmad *intelmaddata;
- struct snd_pmic_ops *scard_ops;
-
- uinfo->count = MONO_CNTL;
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->value.enumerated.items = ARRAY_SIZE(router_dmics);
-
- intelmaddata = kcontrol->private_data;
- WARN_ON(!intelmaddata->sstdrv_ops);
-
- scard_ops = intelmaddata->sstdrv_ops->scard_ops;
- WARN_ON(!scard_ops);
-
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item =
- uinfo->value.enumerated.items - 1;
-
- strncpy(uinfo->value.enumerated.name,
- router_dmics[uinfo->value.enumerated.item],
- sizeof(uinfo->value.enumerated.name)-1);
-
-
- msic_set_bit(kcontrol->private_value, &scard_ops->available_dmics);
- pr_debug("info function. avl_dmic = 0x%x",
- scard_ops->available_dmics);
-
- scard_ops->hw_dmic_map[kcontrol->id.numid-HW_CH_BASE] =
- kcontrol->private_value;
-
- return 0;
-}
-
-struct snd_kcontrol_new snd_intelmad_controls_mrst[MAX_CTRL] __devinitdata = {
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Source",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_device_info_mrst,
- .get = snd_intelmad_device_get,
- .put = snd_intelmad_device_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Capture Source",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_device_info_mrst,
- .get = snd_intelmad_device_get,
- .put = snd_intelmad_device_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Volume",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_playback_volume_info,
- .get = snd_intelmad_volume_get,
- .put = snd_intelmad_volume_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Switch",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_mute_info,
- .get = snd_intelmad_mute_get,
- .put = snd_intelmad_mute_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Capture Volume",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_capture_volume_info,
- .get = snd_intelmad_volume_get,
- .put = snd_intelmad_volume_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Capture Switch",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_mute_info,
- .get = snd_intelmad_mute_get,
- .put = snd_intelmad_mute_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_master_volume_info,
- .get = snd_intelmad_volume_get,
- .put = snd_intelmad_volume_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_mute_info,
- .get = snd_intelmad_mute_get,
- .put = snd_intelmad_mute_set,
- .private_value = 0,
-},
-};
-
-struct snd_kcontrol_new
-snd_intelmad_controls_mfld[MAX_CTRL_MFLD] __devinitdata = {
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Source",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_device_info_mfld,
- .get = snd_intelmad_device_get,
- .put = snd_intelmad_device_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Capture Source",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_device_info_mfld,
- .get = snd_intelmad_device_get,
- .put = snd_intelmad_device_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Line out",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_device_info_mfld,
- .get = snd_intelmad_device_get,
- .put = snd_intelmad_device_set,
- .private_value = 0,
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = HW_CH_0,
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_device_dmic_info_mfld,
- .get = snd_intelmad_device_dmic_get,
- .put = snd_intelmad_device_dmic_set,
- .private_value = 0
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = HW_CH_1,
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_device_dmic_info_mfld,
- .get = snd_intelmad_device_dmic_get,
- .put = snd_intelmad_device_dmic_set,
- .private_value = 1
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = HW_CH_2,
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_device_dmic_info_mfld,
- .get = snd_intelmad_device_dmic_get,
- .put = snd_intelmad_device_dmic_set,
- .private_value = 2
-},
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = HW_CH_3,
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_intelmad_device_dmic_info_mfld,
- .get = snd_intelmad_device_dmic_get,
- .put = snd_intelmad_device_dmic_set,
- .private_value = 3
-}
-};
-
diff --git a/drivers/staging/intel_sst/intelmid_msic_control.c b/drivers/staging/intel_sst/intelmid_msic_control.c
deleted file mode 100644
index 70cdb1697815..000000000000
--- a/drivers/staging/intel_sst/intelmid_msic_control.c
+++ /dev/null
@@ -1,1047 +0,0 @@
-/*
- * intelmid_vm_control.c - Intel Sound card driver for MID
- *
- * Copyright (C) 2010 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This file contains the control operations of msic vendors
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/file.h>
-#include <linux/delay.h>
-#include <sound/control.h>
-#include "intel_sst.h"
-#include <linux/input.h>
-#include "intelmid_snd_control.h"
-#include "intelmid.h"
-
-#define AUDIOMUX12 0x24c
-#define AUDIOMUX34 0x24d
-
-static int msic_init_card(void)
-{
- struct sc_reg_access sc_access[] = {
- /* dmic configuration */
- {0x241, 0x85, 0},
- {0x242, 0x02, 0},
- /* audio paths config */
- {0x24C, 0x10, 0},
- {0x24D, 0x32, 0},
- /* PCM2 interface slots */
- /* preconfigured slots for 0-5 both tx, rx */
- {0x272, 0x10, 0},
- {0x273, 0x32, 0},
- {0x274, 0xFF, 0},
- {0x275, 0x10, 0},
- {0x276, 0x32, 0},
- {0x277, 0x54, 0},
- /*Sinc5 decimator*/
- {0x24E, 0x28, 0},
- /*TI vibra w/a settings*/
- {0x384, 0x80, 0},
- {0x385, 0x80, 0},
- {0x267, 0x00, 0},
- {0x261, 0x00, 0},
- /* pcm port setting */
- {0x278, 0x00, 0},
- {0x27B, 0x01, 0},
- {0x27C, 0x0a, 0},
- /* Set vol HSLRVOLCTRL, IHFVOL */
- {0x259, 0x08, 0},
- {0x25A, 0x08, 0},
- {0x25B, 0x08, 0},
- {0x25C, 0x08, 0},
- /* HSEPRXCTRL Enable the headset left and right FIR filters */
- {0x250, 0x30, 0},
- /* HSMIXER */
- {0x256, 0x11, 0},
- /* amic configuration */
- {0x249, 0x01, 0x0},
- {0x24A, 0x01, 0x0},
- /* unmask ocaudio/accdet interrupts */
- {0x1d, 0x00, 0x00},
- {0x1e, 0x00, 0x00},
- };
- snd_msic_ops.card_status = SND_CARD_INIT_DONE;
- sst_sc_reg_access(sc_access, PMIC_WRITE, 28);
- snd_msic_ops.pb_on = 0;
- snd_msic_ops.pbhs_on = 0;
- snd_msic_ops.cap_on = 0;
- snd_msic_ops.input_dev_id = DMIC; /*def dev*/
- snd_msic_ops.output_dev_id = STEREO_HEADPHONE;
- snd_msic_ops.jack_interrupt_status = false;
- pr_debug("msic init complete!!\n");
- return 0;
-}
-static int msic_line_out_restore(u8 value)
-{
- struct sc_reg_access hs_drv_en[] = {
- {0x25d, 0x03, 0x03},
- };
- struct sc_reg_access ep_drv_en[] = {
- {0x25d, 0x40, 0x40},
- };
- struct sc_reg_access ihf_drv_en[] = {
- {0x25d, 0x0c, 0x0c},
- };
- struct sc_reg_access vib1_drv_en[] = {
- {0x25d, 0x10, 0x10},
- };
- struct sc_reg_access vib2_drv_en[] = {
- {0x25d, 0x20, 0x20},
- };
- struct sc_reg_access pmode_enable[] = {
- {0x381, 0x10, 0x10},
- };
- int retval = 0;
-
- pr_debug("msic_lineout_restore_lineout_dev:%d\n", value);
-
- switch (value) {
- case HEADSET:
- pr_debug("Selecting Lineout-HEADSET-restore\n");
- if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE)
- retval = sst_sc_reg_access(hs_drv_en,
- PMIC_READ_MODIFY, 1);
- else
- retval = sst_sc_reg_access(ep_drv_en,
- PMIC_READ_MODIFY, 1);
- break;
- case IHF:
- pr_debug("Selecting Lineout-IHF-restore\n");
- retval = sst_sc_reg_access(ihf_drv_en, PMIC_READ_MODIFY, 1);
- if (retval)
- return retval;
- retval = sst_sc_reg_access(pmode_enable, PMIC_READ_MODIFY, 1);
- break;
- case VIBRA1:
- pr_debug("Selecting Lineout-Vibra1-restore\n");
- retval = sst_sc_reg_access(vib1_drv_en, PMIC_READ_MODIFY, 1);
- break;
- case VIBRA2:
- pr_debug("Selecting Lineout-VIBRA2-restore\n");
- retval = sst_sc_reg_access(vib2_drv_en, PMIC_READ_MODIFY, 1);
- break;
- case NONE:
- pr_debug("Selecting Lineout-NONE-restore\n");
- break;
- default:
- return -EINVAL;
- }
- return retval;
-}
-static int msic_get_lineout_prvstate(void)
-{
- struct sc_reg_access hs_ihf_drv[2] = {
- {0x257, 0x0, 0x0},
- {0x25d, 0x0, 0x0},
- };
- struct sc_reg_access vib1drv[2] = {
- {0x264, 0x0, 0x0},
- {0x25D, 0x0, 0x0},
- };
- struct sc_reg_access vib2drv[2] = {
- {0x26A, 0x0, 0x0},
- {0x25D, 0x0, 0x0},
- };
- int retval = 0, drv_en, dac_en, dev_id, mask;
- for (dev_id = 0; dev_id < snd_msic_ops.line_out_names_cnt; dev_id++) {
- switch (dev_id) {
- case HEADSET:
- pr_debug("msic_get_lineout_prvs_state: HEADSET\n");
- sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2);
-
- mask = (MASK0|MASK1);
- dac_en = (hs_ihf_drv[0].value) & mask;
-
- mask = ((MASK0|MASK1)|MASK6);
- drv_en = (hs_ihf_drv[1].value) & mask;
-
- if (dac_en && (!drv_en)) {
- snd_msic_ops.prev_lineout_dev_id = HEADSET;
- return retval;
- }
- break;
- case IHF:
- pr_debug("msic_get_lineout_prvstate: IHF\n");
- sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2);
-
- mask = (MASK2 | MASK3);
- dac_en = (hs_ihf_drv[0].value) & mask;
-
- mask = (MASK2 | MASK3);
- drv_en = (hs_ihf_drv[1].value) & mask;
-
- if (dac_en && (!drv_en)) {
- snd_msic_ops.prev_lineout_dev_id = IHF;
- return retval;
- }
- break;
- case VIBRA1:
- pr_debug("msic_get_lineout_prvstate: vibra1\n");
- sst_sc_reg_access(vib1drv, PMIC_READ, 2);
-
- mask = MASK1;
- dac_en = (vib1drv[0].value) & mask;
-
- mask = MASK4;
- drv_en = (vib1drv[1].value) & mask;
-
- if (dac_en && (!drv_en)) {
- snd_msic_ops.prev_lineout_dev_id = VIBRA1;
- return retval;
- }
- break;
- case VIBRA2:
- pr_debug("msic_get_lineout_prvstate: vibra2\n");
- sst_sc_reg_access(vib2drv, PMIC_READ, 2);
-
- mask = MASK1;
- dac_en = (vib2drv[0].value) & mask;
-
- mask = MASK5;
- drv_en = ((vib2drv[1].value) & mask);
-
- if (dac_en && (!drv_en)) {
- snd_msic_ops.prev_lineout_dev_id = VIBRA2;
- return retval;
- }
- break;
- case NONE:
- pr_debug("msic_get_lineout_prvstate: NONE\n");
- snd_msic_ops.prev_lineout_dev_id = NONE;
- return retval;
- default:
- pr_debug("Invalid device id\n");
- snd_msic_ops.prev_lineout_dev_id = NONE;
- return -EINVAL;
- }
- }
- return retval;
-}
-static int msic_set_selected_lineout_dev(u8 value)
-{
- struct sc_reg_access lout_hs[] = {
- {0x25e, 0x33, 0xFF},
- {0x25d, 0x0, 0x43},
- };
- struct sc_reg_access lout_ihf[] = {
- {0x25e, 0x55, 0xff},
- {0x25d, 0x0, 0x0c},
- };
- struct sc_reg_access lout_vibra1[] = {
-
- {0x25e, 0x61, 0xff},
- {0x25d, 0x0, 0x10},
- };
- struct sc_reg_access lout_vibra2[] = {
-
- {0x25e, 0x16, 0xff},
- {0x25d, 0x0, 0x20},
- };
- struct sc_reg_access lout_def[] = {
- {0x25e, 0x66, 0x0},
- };
- struct sc_reg_access pmode_disable[] = {
- {0x381, 0x00, 0x10},
- };
- struct sc_reg_access pmode_enable[] = {
- {0x381, 0x10, 0x10},
- };
- int retval = 0;
-
- pr_debug("msic_set_selected_lineout_dev:%d\n", value);
- msic_get_lineout_prvstate();
- msic_line_out_restore(snd_msic_ops.prev_lineout_dev_id);
- snd_msic_ops.lineout_dev_id = value;
-
- switch (value) {
- case HEADSET:
- pr_debug("Selecting Lineout-HEADSET\n");
- if (snd_msic_ops.pb_on)
- retval = sst_sc_reg_access(lout_hs,
- PMIC_READ_MODIFY, 2);
- if (retval)
- return retval;
- retval = sst_sc_reg_access(pmode_disable,
- PMIC_READ_MODIFY, 1);
- break;
- case IHF:
- pr_debug("Selecting Lineout-IHF\n");
- if (snd_msic_ops.pb_on)
- retval = sst_sc_reg_access(lout_ihf,
- PMIC_READ_MODIFY, 2);
- if (retval)
- return retval;
- retval = sst_sc_reg_access(pmode_enable,
- PMIC_READ_MODIFY, 1);
- break;
- case VIBRA1:
- pr_debug("Selecting Lineout-Vibra1\n");
- if (snd_msic_ops.pb_on)
- retval = sst_sc_reg_access(lout_vibra1,
- PMIC_READ_MODIFY, 2);
- if (retval)
- return retval;
- retval = sst_sc_reg_access(pmode_disable,
- PMIC_READ_MODIFY, 1);
- break;
- case VIBRA2:
- pr_debug("Selecting Lineout-VIBRA2\n");
- if (snd_msic_ops.pb_on)
- retval = sst_sc_reg_access(lout_vibra2,
- PMIC_READ_MODIFY, 2);
- if (retval)
- return retval;
- retval = sst_sc_reg_access(pmode_disable,
- PMIC_READ_MODIFY, 1);
- break;
- case NONE:
- pr_debug("Selecting Lineout-NONE\n");
- retval = sst_sc_reg_access(lout_def,
- PMIC_WRITE, 1);
- if (retval)
- return retval;
- retval = sst_sc_reg_access(pmode_disable,
- PMIC_READ_MODIFY, 1);
- break;
- default:
- return -EINVAL;
- }
- return retval;
-}
-
-
-static int msic_power_up_pb(unsigned int device)
-{
- struct sc_reg_access vaud[] = {
- /* turn on the audio power supplies */
- {0x0DB, 0x07, 0},
- };
- struct sc_reg_access pll[] = {
- /* turn on PLL */
- {0x240, 0x20, 0},
- };
- struct sc_reg_access vhs[] = {
- /* VHSP */
- {0x0DC, 0x3D, 0},
- /* VHSN */
- {0x0DD, 0x3F, 0},
- };
- struct sc_reg_access hsdac[] = {
- {0x382, 0x40, 0x40},
- /* disable driver */
- {0x25D, 0x0, 0x43},
- /* DAC CONFIG ; both HP, LP on */
- {0x257, 0x03, 0x03},
- };
- struct sc_reg_access hs_filter[] = {
- /* HSEPRXCTRL Enable the headset left and right FIR filters */
- {0x250, 0x30, 0},
- /* HSMIXER */
- {0x256, 0x11, 0},
- };
- struct sc_reg_access hs_enable[] = {
- /* enable driver */
- {0x25D, 0x3, 0x3},
- {0x26C, 0x0, 0x2},
- /* unmute the headset */
- { 0x259, 0x80, 0x80},
- { 0x25A, 0x80, 0x80},
- };
- struct sc_reg_access vihf[] = {
- /* VIHF ON */
- {0x0C9, 0x27, 0x00},
- };
- struct sc_reg_access ihf_filter[] = {
- /* disable driver */
- {0x25D, 0x00, 0x0C},
- /*Filer DAC enable*/
- {0x251, 0x03, 0x03},
- {0x257, 0x0C, 0x0C},
- };
- struct sc_reg_access ihf_en[] = {
- /*enable drv*/
- {0x25D, 0x0C, 0x0c},
- };
- struct sc_reg_access ihf_unmute[] = {
- /*unmute headset*/
- {0x25B, 0x80, 0x80},
- {0x25C, 0x80, 0x80},
- };
- struct sc_reg_access epdac[] = {
- /* disable driver */
- {0x25D, 0x0, 0x43},
- /* DAC CONFIG ; both HP, LP on */
- {0x257, 0x03, 0x03},
- };
- struct sc_reg_access ep_enable[] = {
- /* enable driver */
- {0x25D, 0x40, 0x40},
- /* unmute the headset */
- { 0x259, 0x80, 0x80},
- { 0x25A, 0x80, 0x80},
- };
- struct sc_reg_access vib1_en[] = {
- /* enable driver, ADC */
- {0x25D, 0x10, 0x10},
- {0x264, 0x02, 0x82},
- };
- struct sc_reg_access vib2_en[] = {
- /* enable driver, ADC */
- {0x25D, 0x20, 0x20},
- {0x26A, 0x02, 0x82},
- };
- struct sc_reg_access pcm2_en[] = {
- /* enable pcm 2 */
- {0x27C, 0x1, 0x1},
- };
- int retval = 0;
-
- if (snd_msic_ops.card_status == SND_CARD_UN_INIT) {
- retval = msic_init_card();
- if (retval)
- return retval;
- }
-
- pr_debug("powering up pb.... Device %d\n", device);
- sst_sc_reg_access(vaud, PMIC_WRITE, 1);
- msleep(1);
- sst_sc_reg_access(pll, PMIC_WRITE, 1);
- msleep(1);
- switch (device) {
- case SND_SST_DEVICE_HEADSET:
- snd_msic_ops.pb_on = 1;
- snd_msic_ops.pbhs_on = 1;
- if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE) {
- sst_sc_reg_access(vhs, PMIC_WRITE, 2);
- sst_sc_reg_access(hsdac, PMIC_READ_MODIFY, 3);
- sst_sc_reg_access(hs_filter, PMIC_WRITE, 2);
- sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 4);
- } else {
- sst_sc_reg_access(epdac, PMIC_READ_MODIFY, 2);
- sst_sc_reg_access(hs_filter, PMIC_WRITE, 2);
- sst_sc_reg_access(ep_enable, PMIC_READ_MODIFY, 3);
- }
- if (snd_msic_ops.lineout_dev_id == HEADSET)
- msic_set_selected_lineout_dev(HEADSET);
- break;
- case SND_SST_DEVICE_IHF:
- snd_msic_ops.pb_on = 1;
- sst_sc_reg_access(vihf, PMIC_WRITE, 1);
- sst_sc_reg_access(ihf_filter, PMIC_READ_MODIFY, 3);
- sst_sc_reg_access(ihf_en, PMIC_READ_MODIFY, 1);
- sst_sc_reg_access(ihf_unmute, PMIC_READ_MODIFY, 2);
- if (snd_msic_ops.lineout_dev_id == IHF)
- msic_set_selected_lineout_dev(IHF);
- break;
-
- case SND_SST_DEVICE_VIBRA:
- snd_msic_ops.pb_on = 1;
- sst_sc_reg_access(vib1_en, PMIC_READ_MODIFY, 2);
- if (snd_msic_ops.lineout_dev_id == VIBRA1)
- msic_set_selected_lineout_dev(VIBRA1);
- break;
-
- case SND_SST_DEVICE_HAPTIC:
- snd_msic_ops.pb_on = 1;
- sst_sc_reg_access(vib2_en, PMIC_READ_MODIFY, 2);
- if (snd_msic_ops.lineout_dev_id == VIBRA2)
- msic_set_selected_lineout_dev(VIBRA2);
- break;
-
- default:
- pr_warn("Wrong Device %d, selected %d\n",
- device, snd_msic_ops.output_dev_id);
- }
- return sst_sc_reg_access(pcm2_en, PMIC_READ_MODIFY, 1);
-}
-
-static int msic_power_up_cp(unsigned int device)
-{
- struct sc_reg_access vaud[] = {
- /* turn on the audio power supplies */
- {0x0DB, 0x07, 0},
- };
- struct sc_reg_access pll[] = {
- /* turn on PLL */
- {0x240, 0x20, 0},
- };
- struct sc_reg_access dmic_bias[] = {
- /* Turn on AMIC supply */
- {0x247, 0xA0, 0xA0},
- };
- struct sc_reg_access dmic[] = {
- /* mic demux enable */
- {0x245, 0x3F, 0x3F},
- {0x246, 0x07, 0x07},
-
- };
- struct sc_reg_access amic_bias[] = {
- /* Turn on AMIC supply */
- {0x247, 0xFC, 0xFC},
- };
- struct sc_reg_access amic[] = {
- /*MIC EN*/
- {0x249, 0x01, 0x01},
- {0x24A, 0x01, 0x01},
- /*ADC EN*/
- {0x248, 0x05, 0x0F},
-
- };
- struct sc_reg_access pcm2[] = {
- /* enable pcm 2 */
- {0x27C, 0x1, 0x1},
- };
- struct sc_reg_access tx_on[] = {
- /*wait for mic to stabalize before turning on audio channels*/
- {0x24F, 0x3C, 0x0},
- };
- int retval = 0;
-
- if (snd_msic_ops.card_status == SND_CARD_UN_INIT) {
- retval = msic_init_card();
- if (retval)
- return retval;
- }
-
- pr_debug("powering up cp....%d\n", snd_msic_ops.input_dev_id);
- sst_sc_reg_access(vaud, PMIC_WRITE, 1);
- msleep(500);/*FIXME need optimzed value here*/
- sst_sc_reg_access(pll, PMIC_WRITE, 1);
- msleep(1);
- snd_msic_ops.cap_on = 1;
- if (snd_msic_ops.input_dev_id == AMIC) {
- sst_sc_reg_access(amic_bias, PMIC_READ_MODIFY, 1);
- msleep(1);
- sst_sc_reg_access(amic, PMIC_READ_MODIFY, 3);
- } else {
- sst_sc_reg_access(dmic_bias, PMIC_READ_MODIFY, 1);
- msleep(1);
- sst_sc_reg_access(dmic, PMIC_READ_MODIFY, 2);
- }
- msleep(1);
- sst_sc_reg_access(tx_on, PMIC_WRITE, 1);
- return sst_sc_reg_access(pcm2, PMIC_READ_MODIFY, 1);
-}
-
-static int msic_power_down(void)
-{
- struct sc_reg_access power_dn[] = {
- /* VHSP */
- {0x0DC, 0xC4, 0},
- /* VHSN */
- {0x0DD, 0x04, 0},
- /* VIHF */
- {0x0C9, 0x24, 0},
- };
- struct sc_reg_access pll[] = {
- /* turn off PLL*/
- {0x240, 0x00, 0x0},
- };
- struct sc_reg_access vaud[] = {
- /* turn off VAUD*/
- {0x0DB, 0x04, 0},
- };
-
- pr_debug("powering dn msic\n");
- snd_msic_ops.pbhs_on = 0;
- snd_msic_ops.pb_on = 0;
- snd_msic_ops.cap_on = 0;
- sst_sc_reg_access(power_dn, PMIC_WRITE, 3);
- msleep(1);
- sst_sc_reg_access(pll, PMIC_WRITE, 1);
- msleep(1);
- sst_sc_reg_access(vaud, PMIC_WRITE, 1);
- return 0;
-}
-
-static int msic_power_down_pb(unsigned int device)
-{
- struct sc_reg_access drv_enable[] = {
- {0x25D, 0x00, 0x00},
- };
- struct sc_reg_access hs_mute[] = {
- {0x259, 0x80, 0x80},
- {0x25A, 0x80, 0x80},
- {0x26C, 0x02, 0x02},
- };
- struct sc_reg_access hs_off[] = {
- {0x257, 0x00, 0x03},
- {0x250, 0x00, 0x30},
- {0x382, 0x00, 0x40},
- };
- struct sc_reg_access ihf_mute[] = {
- {0x25B, 0x80, 0x80},
- {0x25C, 0x80, 0x80},
- };
- struct sc_reg_access ihf_off[] = {
- {0x257, 0x00, 0x0C},
- {0x251, 0x00, 0x03},
- };
- struct sc_reg_access vib1_off[] = {
- {0x264, 0x00, 0x82},
- };
- struct sc_reg_access vib2_off[] = {
- {0x26A, 0x00, 0x82},
- };
- struct sc_reg_access lout_off[] = {
- {0x25e, 0x66, 0x00},
- };
- struct sc_reg_access pmode_disable[] = {
- {0x381, 0x00, 0x10},
- };
-
-
-
- pr_debug("powering dn pb for device %d\n", device);
- switch (device) {
- case SND_SST_DEVICE_HEADSET:
- snd_msic_ops.pbhs_on = 0;
- sst_sc_reg_access(hs_mute, PMIC_READ_MODIFY, 3);
- drv_enable[0].mask = 0x43;
- sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
- sst_sc_reg_access(hs_off, PMIC_READ_MODIFY, 3);
- if (snd_msic_ops.lineout_dev_id == HEADSET)
- sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
- break;
-
- case SND_SST_DEVICE_IHF:
- sst_sc_reg_access(ihf_mute, PMIC_READ_MODIFY, 2);
- drv_enable[0].mask = 0x0C;
- sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
- sst_sc_reg_access(ihf_off, PMIC_READ_MODIFY, 2);
- if (snd_msic_ops.lineout_dev_id == IHF) {
- sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
- sst_sc_reg_access(pmode_disable, PMIC_READ_MODIFY, 1);
- }
- break;
-
- case SND_SST_DEVICE_VIBRA:
- sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 1);
- drv_enable[0].mask = 0x10;
- sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
- if (snd_msic_ops.lineout_dev_id == VIBRA1)
- sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
- break;
-
- case SND_SST_DEVICE_HAPTIC:
- sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 1);
- drv_enable[0].mask = 0x20;
- sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
- if (snd_msic_ops.lineout_dev_id == VIBRA2)
- sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
- break;
- }
- return 0;
-}
-
-static int msic_power_down_cp(unsigned int device)
-{
- struct sc_reg_access dmic[] = {
- {0x247, 0x00, 0xA0},
- {0x245, 0x00, 0x38},
- {0x246, 0x00, 0x07},
- };
- struct sc_reg_access amic[] = {
- {0x248, 0x00, 0x05},
- {0x249, 0x00, 0x01},
- {0x24A, 0x00, 0x01},
- {0x247, 0x00, 0xA3},
- };
- struct sc_reg_access tx_off[] = {
- {0x24F, 0x00, 0x3C},
- };
-
- pr_debug("powering dn cp....\n");
- snd_msic_ops.cap_on = 0;
- sst_sc_reg_access(tx_off, PMIC_READ_MODIFY, 1);
- if (snd_msic_ops.input_dev_id == DMIC)
- sst_sc_reg_access(dmic, PMIC_READ_MODIFY, 3);
- else
- sst_sc_reg_access(amic, PMIC_READ_MODIFY, 4);
- return 0;
-}
-
-static int msic_set_selected_output_dev(u8 value)
-{
- int retval = 0;
-
- pr_debug("msic set selected output:%d\n", value);
- snd_msic_ops.output_dev_id = value;
- if (snd_msic_ops.pbhs_on)
- msic_power_up_pb(SND_SST_DEVICE_HEADSET);
- return retval;
-}
-
-static int msic_set_selected_input_dev(u8 value)
-{
-
- struct sc_reg_access sc_access_dmic[] = {
- {0x24C, 0x10, 0x0},
- };
- struct sc_reg_access sc_access_amic[] = {
- {0x24C, 0x76, 0x0},
-
- };
- int retval = 0;
-
- pr_debug("msic_set_selected_input_dev:%d\n", value);
- snd_msic_ops.input_dev_id = value;
- switch (value) {
- case AMIC:
- pr_debug("Selecting AMIC1\n");
- retval = sst_sc_reg_access(sc_access_amic, PMIC_WRITE, 1);
- break;
- case DMIC:
- pr_debug("Selecting DMIC1\n");
- retval = sst_sc_reg_access(sc_access_dmic, PMIC_WRITE, 1);
- break;
- default:
- return -EINVAL;
-
- }
- if (snd_msic_ops.cap_on)
- retval = msic_power_up_cp(SND_SST_DEVICE_CAPTURE);
- return retval;
-}
-
-static int msic_set_hw_dmic_route(u8 hw_ch_index)
-{
- struct sc_reg_access sc_access_router;
- int retval = -EINVAL;
-
- switch (hw_ch_index) {
- case HW_CH0:
- sc_access_router.reg_addr = AUDIOMUX12;
- sc_access_router.value = snd_msic_ops.hw_dmic_map[0];
- sc_access_router.mask = (MASK2 | MASK1 | MASK0);
- pr_debug("hw_ch0. value = 0x%x\n",
- sc_access_router.value);
- retval = sst_sc_reg_access(&sc_access_router,
- PMIC_READ_MODIFY, 1);
- break;
-
- case HW_CH1:
- sc_access_router.reg_addr = AUDIOMUX12;
- sc_access_router.value = (snd_msic_ops.hw_dmic_map[1]) << 4;
- sc_access_router.mask = (MASK6 | MASK5 | MASK4);
- pr_debug("### hw_ch1. value = 0x%x\n",
- sc_access_router.value);
- retval = sst_sc_reg_access(&sc_access_router,
- PMIC_READ_MODIFY, 1);
- break;
-
- case HW_CH2:
- sc_access_router.reg_addr = AUDIOMUX34;
- sc_access_router.value = snd_msic_ops.hw_dmic_map[2];
- sc_access_router.mask = (MASK2 | MASK1 | MASK0);
- pr_debug("hw_ch2. value = 0x%x\n",
- sc_access_router.value);
- retval = sst_sc_reg_access(&sc_access_router,
- PMIC_READ_MODIFY, 1);
- break;
-
- case HW_CH3:
- sc_access_router.reg_addr = AUDIOMUX34;
- sc_access_router.value = (snd_msic_ops.hw_dmic_map[3]) << 4;
- sc_access_router.mask = (MASK6 | MASK5 | MASK4);
- pr_debug("hw_ch3. value = 0x%x\n",
- sc_access_router.value);
- retval = sst_sc_reg_access(&sc_access_router,
- PMIC_READ_MODIFY, 1);
- break;
- }
-
- return retval;
-}
-
-
-static int msic_set_pcm_voice_params(void)
-{
- return 0;
-}
-
-static int msic_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
-{
- return 0;
-}
-
-static int msic_set_audio_port(int status)
-{
- return 0;
-}
-
-static int msic_set_voice_port(int status)
-{
- return 0;
-}
-
-static int msic_set_mute(int dev_id, u8 value)
-{
- return 0;
-}
-
-static int msic_set_vol(int dev_id, int value)
-{
- return 0;
-}
-
-static int msic_get_mute(int dev_id, u8 *value)
-{
- return 0;
-}
-
-static int msic_get_vol(int dev_id, int *value)
-{
- return 0;
-}
-
-static int msic_set_headset_state(int state)
-{
- struct sc_reg_access hs_enable[] = {
- {0x25D, 0x03, 0x03},
- };
-
- if (state)
- /*enable*/
- sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 1);
- else {
- hs_enable[0].value = 0;
- sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 1);
- }
- return 0;
-}
-
-static int msic_enable_mic_bias(void)
-{
- struct sc_reg_access jack_interrupt_reg[] = {
- {0x0DB, 0x07, 0x00},
-
- };
- struct sc_reg_access jack_bias_reg[] = {
- {0x247, 0x0C, 0x0C},
- };
-
- sst_sc_reg_access(jack_interrupt_reg, PMIC_WRITE, 1);
- sst_sc_reg_access(jack_bias_reg, PMIC_READ_MODIFY, 1);
- return 0;
-}
-
-static int msic_disable_mic_bias(void)
-{
- if (snd_msic_ops.jack_interrupt_status == true)
- return 0;
- if (!(snd_msic_ops.pb_on || snd_msic_ops.cap_on))
- msic_power_down();
- return 0;
-}
-
-static int msic_disable_jack_btn(void)
-{
- struct sc_reg_access btn_disable[] = {
- {0x26C, 0x00, 0x01}
- };
-
- if (!(snd_msic_ops.pb_on || snd_msic_ops.cap_on))
- msic_power_down();
- snd_msic_ops.jack_interrupt_status = false;
- return sst_sc_reg_access(btn_disable, PMIC_READ_MODIFY, 1);
-}
-
-static int msic_enable_jack_btn(void)
-{
- struct sc_reg_access btn_enable[] = {
- {0x26b, 0x77, 0x00},
- {0x26C, 0x01, 0x00},
- };
- return sst_sc_reg_access(btn_enable, PMIC_WRITE, 2);
-}
-static int msic_convert_adc_to_mvolt(unsigned int mic_bias)
-{
- return (ADC_ONE_LSB_MULTIPLIER * mic_bias) / 1000;
-}
-int msic_get_headset_state(int mic_bias)
-{
- struct sc_reg_access msic_hs_toggle[] = {
- {0x070, 0x00, 0x01},
- };
- if (mic_bias >= 0 && mic_bias < 400) {
-
- pr_debug("Detected Headphone!!!\n");
- sst_sc_reg_access(msic_hs_toggle, PMIC_READ_MODIFY, 1);
-
- } else if (mic_bias > 400 && mic_bias < 650) {
-
- pr_debug("Detected American headset\n");
- msic_hs_toggle[0].value = 0x01;
- sst_sc_reg_access(msic_hs_toggle, PMIC_READ_MODIFY, 1);
-
- } else if (mic_bias >= 650 && mic_bias < 2000) {
-
- pr_debug("Detected Headset!!!\n");
- sst_sc_reg_access(msic_hs_toggle, PMIC_READ_MODIFY, 1);
- /*power on jack and btn*/
- snd_msic_ops.jack_interrupt_status = true;
- msic_enable_jack_btn();
- msic_enable_mic_bias();
- return SND_JACK_HEADSET;
-
- } else
- pr_debug("Detected Open Cable!!!\n");
-
- return SND_JACK_HEADPHONE;
-}
-
-static int msic_get_mic_bias(void *arg)
-{
- struct snd_intelmad *intelmad_drv = (struct snd_intelmad *)arg;
- u16 adc_adr = intelmad_drv->adc_address;
- u16 adc_val;
- int ret;
- struct sc_reg_access adc_ctrl3[2] = {
- {0x1C2, 0x05, 0x0},
- };
-
- struct sc_reg_access audio_adc_reg1 = {0,};
- struct sc_reg_access audio_adc_reg2 = {0,};
-
- msic_enable_mic_bias();
- /* Enable the msic for conversion before reading */
- ret = sst_sc_reg_access(adc_ctrl3, PMIC_WRITE, 1);
- if (ret)
- return ret;
- adc_ctrl3[0].value = 0x04;
- /* Re-toggle the RRDATARD bit */
- ret = sst_sc_reg_access(adc_ctrl3, PMIC_WRITE, 1);
- if (ret)
- return ret;
-
- audio_adc_reg1.reg_addr = adc_adr;
- /* Read the higher bits of data */
- msleep(1000);
- ret = sst_sc_reg_access(&audio_adc_reg1, PMIC_READ, 1);
- if (ret)
- return ret;
- pr_debug("adc read value %x", audio_adc_reg1.value);
-
- /* Shift bits to accomodate the lower two data bits */
- adc_val = (audio_adc_reg1.value << 2);
- adc_adr++;
- audio_adc_reg2. reg_addr = adc_adr;
- ret = sst_sc_reg_access(&audio_adc_reg2, PMIC_READ, 1);
- if (ret)
- return ret;
- pr_debug("adc read value %x", audio_adc_reg2.value);
-
- /* Adding lower two bits to the higher bits */
- audio_adc_reg2.value &= 03;
- adc_val += audio_adc_reg2.value;
-
- pr_debug("ADC value 0x%x", adc_val);
- msic_disable_mic_bias();
- return adc_val;
-}
-
-static void msic_pmic_irq_cb(void *cb_data, u8 intsts)
-{
- struct mad_jack *mjack = NULL;
- unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
- struct snd_intelmad *intelmaddata = cb_data;
- int retval = 0;
-
- pr_debug("value returned = 0x%x\n", intsts);
-
- if (snd_msic_ops.card_status == SND_CARD_UN_INIT) {
- retval = msic_init_card();
- if (retval)
- return;
- }
-
- mjack = &intelmaddata->jack[0];
- if (intsts & 0x1) {
- pr_debug("MAD short_push detected\n");
- present = SND_JACK_BTN_0;
- jack_event_flag = buttonpressflag = 1;
- mjack->jack.type = SND_JACK_BTN_0;
- mjack->jack.key[0] = BTN_0 ;
- }
-
- if (intsts & 0x2) {
- pr_debug(":MAD long_push detected\n");
- jack_event_flag = buttonpressflag = 1;
- mjack->jack.type = present = SND_JACK_BTN_1;
- mjack->jack.key[1] = BTN_1;
- }
-
- if (intsts & 0x4) {
- unsigned int mic_bias;
- jack_event_flag = 1;
- buttonpressflag = 0;
- mic_bias = msic_get_mic_bias(intelmaddata);
- pr_debug("mic_bias = %d\n", mic_bias);
- mic_bias = msic_convert_adc_to_mvolt(mic_bias);
- pr_debug("mic_bias after conversion = %d mV\n", mic_bias);
- mjack->jack_dev_state = msic_get_headset_state(mic_bias);
- mjack->jack.type = present = mjack->jack_dev_state;
- }
-
- if (intsts & 0x8) {
- mjack->jack.type = mjack->jack_dev_state;
- present = 0;
- jack_event_flag = 1;
- buttonpressflag = 0;
- msic_disable_jack_btn();
- msic_disable_mic_bias();
- }
- if (jack_event_flag)
- sst_mad_send_jack_report(&mjack->jack,
- buttonpressflag, present);
-}
-
-
-
-struct snd_pmic_ops snd_msic_ops = {
- .set_input_dev = msic_set_selected_input_dev,
- .set_output_dev = msic_set_selected_output_dev,
- .set_lineout_dev = msic_set_selected_lineout_dev,
- .set_hw_dmic_route = msic_set_hw_dmic_route,
- .set_mute = msic_set_mute,
- .get_mute = msic_get_mute,
- .set_vol = msic_set_vol,
- .get_vol = msic_get_vol,
- .init_card = msic_init_card,
- .set_pcm_audio_params = msic_set_pcm_audio_params,
- .set_pcm_voice_params = msic_set_pcm_voice_params,
- .set_voice_port = msic_set_voice_port,
- .set_audio_port = msic_set_audio_port,
- .power_up_pmic_pb = msic_power_up_pb,
- .power_up_pmic_cp = msic_power_up_cp,
- .power_down_pmic_pb = msic_power_down_pb,
- .power_down_pmic_cp = msic_power_down_cp,
- .power_down_pmic = msic_power_down,
- .pmic_irq_cb = msic_pmic_irq_cb,
- .pmic_jack_enable = msic_enable_mic_bias,
- .pmic_get_mic_bias = msic_get_mic_bias,
- .pmic_set_headset_state = msic_set_headset_state,
-};
diff --git a/drivers/staging/intel_sst/intelmid_pvt.c b/drivers/staging/intel_sst/intelmid_pvt.c
deleted file mode 100644
index 90e0e64c0ab0..000000000000
--- a/drivers/staging/intel_sst/intelmid_pvt.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * intelmid_pvt.h - Intel Sound card driver for MID
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Harsha Priya <priya.harsha@intel.com>
- * Vinod Koul <vinod.koul@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * ALSA driver for Intel MID sound card chipset - holding private functions
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/io.h>
-#include <asm/intel_scu_ipc.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/pcm.h>
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intelmid_snd_control.h"
-#include "intelmid.h"
-
-
-void period_elapsed(void *mad_substream)
-{
- struct snd_pcm_substream *substream = mad_substream;
- struct mad_stream_pvt *stream;
-
-
-
- if (!substream || !substream->runtime)
- return;
- stream = substream->runtime->private_data;
- if (!stream)
- return;
-
- if (stream->stream_status != RUNNING)
- return;
- pr_debug("calling period elapsed\n");
- snd_pcm_period_elapsed(substream);
- return;
-}
-
-
-int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream)
-{
- struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
- struct mad_stream_pvt *stream = substream->runtime->private_data;
- struct snd_sst_stream_params param = {{{0,},},};
- struct snd_sst_params str_params = {0};
- int ret_val;
-
- /* set codec params and inform SST driver the same */
-
- param.uc.pcm_params.codec = SST_CODEC_TYPE_PCM;
- param.uc.pcm_params.num_chan = (u8) substream->runtime->channels;
- param.uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
- param.uc.pcm_params.reserved = 0;
- param.uc.pcm_params.sfreq = substream->runtime->rate;
- param.uc.pcm_params.ring_buffer_size =
- snd_pcm_lib_buffer_bytes(substream);
- param.uc.pcm_params.period_count = substream->runtime->period_size;
- param.uc.pcm_params.ring_buffer_addr =
- virt_to_phys(substream->runtime->dma_area);
- pr_debug("period_cnt = %d\n", param.uc.pcm_params.period_count);
- pr_debug("sfreq= %d, wd_sz = %d\n",
- param.uc.pcm_params.sfreq, param.uc.pcm_params.pcm_wd_sz);
-
- str_params.sparams = param;
- str_params.codec = SST_CODEC_TYPE_PCM;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- str_params.ops = STREAM_OPS_PLAYBACK;
- pr_debug("Playbck stream,Device %d\n", stream->device);
- } else {
- str_params.ops = STREAM_OPS_CAPTURE;
- stream->device = SND_SST_DEVICE_CAPTURE;
- pr_debug("Capture stream,Device %d\n", stream->device);
- }
- str_params.device_type = stream->device;
- ret_val = intelmaddata->sstdrv_ops->pcm_control->open(&str_params);
- pr_debug("sst: SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
- if (ret_val < 0)
- return ret_val;
-
- stream->stream_info.str_id = ret_val;
- stream->stream_status = INIT;
- stream->stream_info.buffer_ptr = 0;
- pr_debug("str id : %d\n", stream->stream_info.str_id);
-
- return ret_val;
-}
-
-int snd_intelmad_init_stream(struct snd_pcm_substream *substream)
-{
- struct mad_stream_pvt *stream = substream->runtime->private_data;
- struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
- int ret_val;
-
- pr_debug("setting buffer ptr param\n");
- stream->stream_info.period_elapsed = period_elapsed;
- stream->stream_info.mad_substream = substream;
- stream->stream_info.buffer_ptr = 0;
- stream->stream_info.sfreq = substream->runtime->rate;
- ret_val = intelmaddata->sstdrv_ops->pcm_control->device_control(
- SST_SND_STREAM_INIT, &stream->stream_info);
- if (ret_val)
- pr_err("control_set ret error %d\n", ret_val);
- return ret_val;
-
-}
-
-
-/**
- * sst_sc_reg_access - IPC read/write wrapper
- *
- * @sc_access: array of data, addresses and mask
- * @type: operation type
- * @num_val: number of reg to opertae on
- *
- * Reads/writes/read-modify operations on registers accessed through SCU (sound
- * card and few SST DSP regsisters that are not accissible to IA)
- */
-int sst_sc_reg_access(struct sc_reg_access *sc_access,
- int type, int num_val)
-{
- int i, retval = 0;
- if (type == PMIC_WRITE) {
- for (i = 0; i < num_val; i++) {
- retval = intel_scu_ipc_iowrite8(sc_access[i].reg_addr,
- sc_access[i].value);
- if (retval)
- goto err;
- }
- } else if (type == PMIC_READ) {
- for (i = 0; i < num_val; i++) {
- retval = intel_scu_ipc_ioread8(sc_access[i].reg_addr,
- &(sc_access[i].value));
- if (retval)
- goto err;
- }
- } else {
- for (i = 0; i < num_val; i++) {
- retval = intel_scu_ipc_update_register(
- sc_access[i].reg_addr, sc_access[i].value,
- sc_access[i].mask);
- if (retval)
- goto err;
- }
- }
- return 0;
-err:
- pr_err("IPC failed for cmd %d, %d\n", retval, type);
- pr_err("reg:0x%2x addr:0x%2x\n",
- sc_access[i].reg_addr, sc_access[i].value);
- return retval;
-}
diff --git a/drivers/staging/intel_sst/intelmid_snd_control.h b/drivers/staging/intel_sst/intelmid_snd_control.h
deleted file mode 100644
index 06ad3a10099c..000000000000
--- a/drivers/staging/intel_sst/intelmid_snd_control.h
+++ /dev/null
@@ -1,123 +0,0 @@
-#ifndef __INTELMID_SND_CTRL_H__
-#define __INTELMID_SND_CTRL_H__
-/*
- * intelmid_snd_control.h - Intel Sound card driver for MID
- *
- * Copyright (C) 2008-10 Intel Corporation
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This file defines all snd control functions
- */
-
-/*
-Mask bits
-*/
-#define MASK0 0x01 /* 0000 0001 */
-#define MASK1 0x02 /* 0000 0010 */
-#define MASK2 0x04 /* 0000 0100 */
-#define MASK3 0x08 /* 0000 1000 */
-#define MASK4 0x10 /* 0001 0000 */
-#define MASK5 0x20 /* 0010 0000 */
-#define MASK6 0x40 /* 0100 0000 */
-#define MASK7 0x80 /* 1000 0000 */
-/*
-value bits
-*/
-#define VALUE0 0x01 /* 0000 0001 */
-#define VALUE1 0x02 /* 0000 0010 */
-#define VALUE2 0x04 /* 0000 0100 */
-#define VALUE3 0x08 /* 0000 1000 */
-#define VALUE4 0x10 /* 0001 0000 */
-#define VALUE5 0x20 /* 0010 0000 */
-#define VALUE6 0x40 /* 0100 0000 */
-#define VALUE7 0x80 /* 1000 0000 */
-
-#define MUTE 0 /* ALSA Passes 0 for mute */
-#define UNMUTE 1 /* ALSA Passes 1 for unmute */
-
-#define MAX_VOL_PMIC_VENDOR0 0x3f /* max vol in dB for stereo & voice DAC */
-#define MIN_VOL_PMIC_VENDOR0 0 /* min vol in dB for stereo & voice DAC */
-/* Head phone volume control */
-#define MAX_HP_VOL_PMIC_VENDOR1 6 /* max volume in dB for HP */
-#define MIN_HP_VOL_PMIC_VENDOR1 (-84) /* min volume in dB for HP */
-#define MAX_HP_VOL_INDX_PMIC_VENDOR1 40 /* Number of HP volume control values */
-
-/* Mono Earpiece Volume control */
-#define MAX_EP_VOL_PMIC_VENDOR1 0 /* max volume in dB for EP */
-#define MIN_EP_VOL_PMIC_VENDOR1 (-75) /* min volume in dB for EP */
-#define MAX_EP_VOL_INDX_PMIC_VENDOR1 32 /* Number of EP volume control values */
-
-int sst_sc_reg_access(struct sc_reg_access *sc_access,
- int type, int num_val);
-extern struct snd_pmic_ops snd_pmic_ops_fs;
-extern struct snd_pmic_ops snd_pmic_ops_mx;
-extern struct snd_pmic_ops snd_pmic_ops_nc;
-extern struct snd_pmic_ops snd_msic_ops;
-
-/* device */
-enum SND_INPUT_DEVICE {
- AMIC,
- DMIC,
- HS_MIC,
- IN_UNDEFINED
-};
-enum SND_LINE_OUT_DEVICE {
- HEADSET,
- IHF,
- VIBRA1,
- VIBRA2,
- NONE,
-};
-
-enum SND_OUTPUT_DEVICE {
- STEREO_HEADPHONE,
- MONO_EARPIECE,
-
- INTERNAL_SPKR,
- RECEIVER,
- OUT_UNDEFINED
-};
-
-enum pmic_controls {
- PMIC_SND_HP_MIC_MUTE = 0x0001,
- PMIC_SND_AMIC_MUTE = 0x0002,
- PMIC_SND_DMIC_MUTE = 0x0003,
- PMIC_SND_CAPTURE_VOL = 0x0004,
-/* Output controls */
- PMIC_SND_LEFT_PB_VOL = 0x0010,
- PMIC_SND_RIGHT_PB_VOL = 0x0011,
- PMIC_SND_LEFT_HP_MUTE = 0x0012,
- PMIC_SND_RIGHT_HP_MUTE = 0x0013,
- PMIC_SND_LEFT_SPEAKER_MUTE = 0x0014,
- PMIC_SND_RIGHT_SPEAKER_MUTE = 0x0015,
- PMIC_SND_RECEIVER_VOL = 0x0016,
- PMIC_SND_RECEIVER_MUTE = 0x0017,
- PMIC_SND_LEFT_MASTER_VOL = 0x0018,
- PMIC_SND_RIGHT_MASTER_VOL = 0x0019,
-/* Other controls */
- PMIC_SND_MUTE_ALL = 0x0020,
- PMIC_MAX_CONTROLS = 0x0020,
-};
-
-#endif /* __INTELMID_SND_CTRL_H__ */
-
-
diff --git a/drivers/staging/intel_sst/intelmid_v0_control.c b/drivers/staging/intel_sst/intelmid_v0_control.c
deleted file mode 100644
index b8dfdb9bc1aa..000000000000
--- a/drivers/staging/intel_sst/intelmid_v0_control.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * intel_sst_v0_control.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corporation
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This file contains the control operations of vendor 1
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/file.h>
-#include <sound/control.h>
-#include "intel_sst.h"
-#include "intelmid_snd_control.h"
-#include "intelmid.h"
-
-enum _reg_v1 {
- VOICEPORT1 = 0x180,
- VOICEPORT2 = 0x181,
- AUDIOPORT1 = 0x182,
- AUDIOPORT2 = 0x183,
- MISCVOICECTRL = 0x184,
- MISCAUDCTRL = 0x185,
- DMICCTRL1 = 0x186,
- AUDIOBIAS = 0x187,
- MICCTRL = 0x188,
- MICLICTRL1 = 0x189,
- MICLICTRL2 = 0x18A,
- MICLICTRL3 = 0x18B,
- VOICEDACCTRL1 = 0x18C,
- STEREOADCCTRL = 0x18D,
- AUD15 = 0x18E,
- AUD16 = 0x18F,
- AUD17 = 0x190,
- AUD18 = 0x191,
- RMIXOUTSEL = 0x192,
- ANALOGLBR = 0x193,
- ANALOGLBL = 0x194,
- POWERCTRL1 = 0x195,
- POWERCTRL2 = 0x196,
- HEADSETDETECTINT = 0x197,
- HEADSETDETECTINTMASK = 0x198,
- TRIMENABLE = 0x199,
-};
-
-int rev_id = 0x20;
-static bool jack_det_enabled;
-
-/****
- * fs_init_card - initialize the sound card
- *
- * This initializes the audio paths to know values in case of this sound card
- */
-static int fs_init_card(void)
-{
- struct sc_reg_access sc_access[] = {
- {0x180, 0x00, 0x0},
- {0x181, 0x00, 0x0},
- {0x182, 0xF8, 0x0},
- {0x183, 0x08, 0x0},
- {0x184, 0x00, 0x0},
- {0x185, 0x40, 0x0},
- {0x186, 0x06, 0x0},
- {0x187, 0x80, 0x0},
- {0x188, 0x40, 0x0},
- {0x189, 0x39, 0x0},
- {0x18a, 0x39, 0x0},
- {0x18b, 0x1F, 0x0},
- {0x18c, 0x00, 0x0},
- {0x18d, 0x00, 0x0},
- {0x18e, 0x39, 0x0},
- {0x18f, 0x39, 0x0},
- {0x190, 0x39, 0x0},
- {0x191, 0x11, 0x0},
- {0x192, 0x0E, 0x0},
- {0x193, 0x00, 0x0},
- {0x194, 0x00, 0x0},
- {0x195, 0x00, 0x0},
- {0x196, 0x7C, 0x0},
- {0x197, 0x00, 0x0},
- {0x198, 0x0B, 0x0},
- {0x199, 0x00, 0x0},
- {0x037, 0x3F, 0x0},
- };
-
- snd_pmic_ops_fs.card_status = SND_CARD_INIT_DONE;
- snd_pmic_ops_fs.master_mute = UNMUTE;
- snd_pmic_ops_fs.mute_status = UNMUTE;
- snd_pmic_ops_fs.num_channel = 2;
- return sst_sc_reg_access(sc_access, PMIC_WRITE, 27);
-}
-
-static int fs_enable_audiodac(int value)
-{
- struct sc_reg_access sc_access[3];
- sc_access[0].reg_addr = AUD16;
- sc_access[1].reg_addr = AUD17;
- sc_access[2].reg_addr = AUD15;
- sc_access[0].mask = sc_access[1].mask = sc_access[2].mask = MASK7;
-
- if (snd_pmic_ops_fs.mute_status == MUTE)
- return 0;
- if (value == MUTE) {
- sc_access[0].value = sc_access[1].value =
- sc_access[2].value = 0x80;
-
- } else {
- sc_access[0].value = sc_access[1].value =
- sc_access[2].value = 0x0;
- }
- if (snd_pmic_ops_fs.num_channel == 1)
- sc_access[1].value = sc_access[2].value = 0x80;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
-
-}
-
-static int fs_power_up_pb(unsigned int port)
-{
- struct sc_reg_access sc_access[] = {
- {AUDIOBIAS, 0x00, MASK7},
- {POWERCTRL1, 0xC6, 0xC6},
- {POWERCTRL2, 0x30, 0x30},
-
- };
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
- retval = fs_enable_audiodac(MUTE);
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
-
- if (retval)
- return retval;
-
- pr_debug("in fs power up pb\n");
- return fs_enable_audiodac(UNMUTE);
-}
-
-static int fs_power_down_pb(unsigned int device)
-{
- struct sc_reg_access sc_access[] = {
- {POWERCTRL1, 0x00, 0xC6},
- {POWERCTRL2, 0x00, 0x30},
- };
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
- retval = fs_enable_audiodac(MUTE);
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-
- if (retval)
- return retval;
-
- pr_debug("in fsl power down pb\n");
- return fs_enable_audiodac(UNMUTE);
-}
-
-static int fs_power_up_cp(unsigned int port)
-{
- struct sc_reg_access sc_access[] = {
- {POWERCTRL2, 0x32, 0x32}, /*NOTE power up A ADC only as*/
- {AUDIOBIAS, 0x00, MASK7},
- /*as turning on V ADC causes noise*/
- };
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-}
-
-static int fs_power_down_cp(unsigned int device)
-{
- struct sc_reg_access sc_access[] = {
- {POWERCTRL2, 0x00, 0x03},
- };
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
-}
-
-static int fs_power_down(void)
-{
- int retval = 0;
- struct sc_reg_access sc_access[] = {
- {AUDIOBIAS, MASK7, MASK7},
- };
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
-}
-
-static int fs_set_pcm_voice_params(void)
-{
- struct sc_reg_access sc_access[] = {
- {0x180, 0xA0, 0},
- {0x181, 0x04, 0},
- {0x182, 0x0, 0},
- {0x183, 0x0, 0},
- {0x184, 0x18, 0},
- {0x185, 0x40, 0},
- {0x186, 0x06, 0},
- {0x187, 0x0, 0},
- {0x188, 0x10, 0},
- {0x189, 0x39, 0},
- {0x18a, 0x39, 0},
- {0x18b, 0x02, 0},
- {0x18c, 0x0, 0},
- {0x18d, 0x0, 0},
- {0x18e, 0x39, 0},
- {0x18f, 0x0, 0},
- {0x190, 0x0, 0},
- {0x191, 0x20, 0},
- {0x192, 0x20, 0},
- {0x193, 0x0, 0},
- {0x194, 0x0, 0},
- {0x195, 0x06, 0},
- {0x196, 0x25, 0},
- {0x197, 0x0, 0},
- {0x198, 0xF, 0},
- {0x199, 0x0, 0},
- };
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
- return sst_sc_reg_access(sc_access, PMIC_WRITE, 26);
-}
-
-static int fs_set_audio_port(int status)
-{
- struct sc_reg_access sc_access[2];
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
- if (status == DEACTIVATE) {
- /* Deactivate audio port-tristate and power */
- sc_access[0].value = 0x00;
- sc_access[0].mask = MASK6|MASK7;
- sc_access[0].reg_addr = AUDIOPORT1;
- sc_access[1].value = 0x00;
- sc_access[1].mask = MASK4|MASK5;
- sc_access[1].reg_addr = POWERCTRL2;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
- } else if (status == ACTIVATE) {
- /* activate audio port */
- sc_access[0].value = 0xC0;
- sc_access[0].mask = MASK6|MASK7;
- sc_access[0].reg_addr = AUDIOPORT1;
- sc_access[1].value = 0x30;
- sc_access[1].mask = MASK4|MASK5;
- sc_access[1].reg_addr = POWERCTRL2;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
- } else
- return -EINVAL;
-}
-
-static int fs_set_voice_port(int status)
-{
- struct sc_reg_access sc_access[2];
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
- if (status == DEACTIVATE) {
- /* Deactivate audio port-tristate and power */
- sc_access[0].value = 0x00;
- sc_access[0].mask = MASK6|MASK7;
- sc_access[0].reg_addr = VOICEPORT1;
- sc_access[1].value = 0x00;
- sc_access[1].mask = MASK0|MASK1;
- sc_access[1].reg_addr = POWERCTRL2;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
- } else if (status == ACTIVATE) {
- /* activate audio port */
- sc_access[0].value = 0xC0;
- sc_access[0].mask = MASK6|MASK7;
- sc_access[0].reg_addr = VOICEPORT1;
- sc_access[1].value = 0x03;
- sc_access[1].mask = MASK0|MASK1;
- sc_access[1].reg_addr = POWERCTRL2;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
- } else
- return -EINVAL;
-}
-
-static int fs_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
-{
- u8 config1 = 0;
- struct sc_reg_access sc_access[4];
- int retval = 0, num_value = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
- switch (sfreq) {
- case 8000:
- config1 = 0x00;
- break;
- case 11025:
- config1 = 0x01;
- break;
- case 12000:
- config1 = 0x02;
- break;
- case 16000:
- config1 = 0x03;
- break;
- case 22050:
- config1 = 0x04;
- break;
- case 24000:
- config1 = 0x05;
- break;
- case 26000:
- config1 = 0x06;
- break;
- case 32000:
- config1 = 0x07;
- break;
- case 44100:
- config1 = 0x08;
- break;
- case 48000:
- config1 = 0x09;
- break;
- }
- snd_pmic_ops_fs.num_channel = num_channel;
- if (snd_pmic_ops_fs.num_channel == 1) {
- sc_access[0].reg_addr = AUD17;
- sc_access[1].reg_addr = AUD15;
- sc_access[0].mask = sc_access[1].mask = MASK7;
- sc_access[0].value = sc_access[1].value = 0x80;
- sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-
- } else {
- sc_access[0].reg_addr = AUD17;
- sc_access[1].reg_addr = AUD15;
- sc_access[0].mask = sc_access[1].mask = MASK7;
- sc_access[0].value = sc_access[1].value = 0x00;
- sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-
- }
- pr_debug("sfreq:%d,Register value = %x\n", sfreq, config1);
-
- if (word_size == 24) {
- sc_access[0].reg_addr = AUDIOPORT1;
- sc_access[0].mask = MASK0|MASK1|MASK2|MASK3;
- sc_access[0].value = 0xFB;
-
-
- sc_access[1].reg_addr = AUDIOPORT2;
- sc_access[1].value = config1 | 0x10;
- sc_access[1].mask = MASK0 | MASK1 | MASK2 | MASK3
- | MASK4 | MASK5 | MASK6;
-
- sc_access[2].reg_addr = MISCAUDCTRL;
- sc_access[2].value = 0x02;
- sc_access[2].mask = 0x02;
-
- num_value = 3 ;
-
- } else {
-
- sc_access[0].reg_addr = AUDIOPORT2;
- sc_access[0].value = config1;
- sc_access[0].mask = MASK0|MASK1|MASK2|MASK3;
-
- sc_access[1].reg_addr = MISCAUDCTRL;
- sc_access[1].value = 0x00;
- sc_access[1].mask = 0x02;
- num_value = 2;
- }
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_value);
-
-}
-
-static int fs_set_selected_input_dev(u8 value)
-{
- struct sc_reg_access sc_access_dmic[] = {
- {MICCTRL, 0x81, 0xf7},
- {MICLICTRL3, 0x00, 0xE0},
- };
- struct sc_reg_access sc_access_mic[] = {
- {MICCTRL, 0x40, MASK2|MASK4|MASK5|MASK6|MASK7},
- {MICLICTRL3, 0x00, 0xE0},
- };
- struct sc_reg_access sc_access_hsmic[] = {
- {MICCTRL, 0x10, MASK2|MASK4|MASK5|MASK6|MASK7},
- {MICLICTRL3, 0x00, 0xE0},
- };
-
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
-
- switch (value) {
- case AMIC:
- pr_debug("Selecting amic not supported in mono cfg\n");
- return sst_sc_reg_access(sc_access_mic, PMIC_READ_MODIFY, 2);
- break;
-
- case HS_MIC:
- pr_debug("Selecting hsmic\n");
- return sst_sc_reg_access(sc_access_hsmic,
- PMIC_READ_MODIFY, 2);
- break;
-
- case DMIC:
- pr_debug("Selecting dmic\n");
- return sst_sc_reg_access(sc_access_dmic, PMIC_READ_MODIFY, 2);
- break;
-
- default:
- return -EINVAL;
-
- }
-}
-
-static int fs_set_selected_output_dev(u8 value)
-{
- struct sc_reg_access sc_access_hp[] = {
- {0x191, 0x11, 0x0},
- {0x192, 0x0E, 0x0},
- };
- struct sc_reg_access sc_access_is[] = {
- {0x191, 0x17, 0xFF},
- {0x192, 0x08, 0xFF},
- };
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
-
- switch (value) {
- case STEREO_HEADPHONE:
- pr_debug("SST DBG:Selecting headphone\n");
- return sst_sc_reg_access(sc_access_hp, PMIC_WRITE, 2);
- break;
- case MONO_EARPIECE:
- case INTERNAL_SPKR:
- pr_debug("SST DBG:Selecting internal spkr\n");
- return sst_sc_reg_access(sc_access_is, PMIC_READ_MODIFY, 2);
- break;
-
- default:
- return -EINVAL;
-
- }
-}
-
-static int fs_set_mute(int dev_id, u8 value)
-{
- struct sc_reg_access sc_access[6] = {{0,},};
- int reg_num = 0;
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
-
-
- pr_debug("dev_id:0x%x value:0x%x\n", dev_id, value);
- switch (dev_id) {
- case PMIC_SND_DMIC_MUTE:
- sc_access[0].reg_addr = MICCTRL;
- sc_access[1].reg_addr = MICLICTRL1;
- sc_access[2].reg_addr = MICLICTRL2;
- sc_access[0].mask = MASK5;
- sc_access[1].mask = sc_access[2].mask = MASK6;
- if (value == MUTE) {
- sc_access[0].value = 0x20;
- sc_access[2].value = sc_access[1].value = 0x40;
- } else
- sc_access[0].value = sc_access[1].value
- = sc_access[2].value = 0x0;
- reg_num = 3;
- break;
- case PMIC_SND_HP_MIC_MUTE:
- case PMIC_SND_AMIC_MUTE:
- sc_access[0].reg_addr = MICLICTRL1;
- sc_access[1].reg_addr = MICLICTRL2;
- sc_access[0].mask = sc_access[1].mask = MASK6;
- if (value == MUTE)
- sc_access[0].value = sc_access[1].value = 0x40;
- else
- sc_access[0].value = sc_access[1].value = 0x0;
- reg_num = 2;
- break;
- case PMIC_SND_LEFT_SPEAKER_MUTE:
- case PMIC_SND_LEFT_HP_MUTE:
- sc_access[0].reg_addr = AUD16;
- sc_access[1].reg_addr = AUD15;
-
- sc_access[0].mask = sc_access[1].mask = MASK7;
- if (value == MUTE)
- sc_access[0].value = sc_access[1].value = 0x80;
- else
- sc_access[0].value = sc_access[1].value = 0x0;
- reg_num = 2;
- snd_pmic_ops_fs.mute_status = value;
- break;
- case PMIC_SND_RIGHT_HP_MUTE:
- case PMIC_SND_RIGHT_SPEAKER_MUTE:
- sc_access[0].reg_addr = AUD17;
- sc_access[1].reg_addr = AUD15;
- sc_access[0].mask = sc_access[1].mask = MASK7;
- if (value == MUTE)
- sc_access[0].value = sc_access[1].value = 0x80;
- else
- sc_access[0].value = sc_access[1].value = 0x0;
- snd_pmic_ops_fs.mute_status = value;
- if (snd_pmic_ops_fs.num_channel == 1)
- sc_access[0].value = sc_access[1].value = 0x80;
- reg_num = 2;
- break;
- case PMIC_SND_MUTE_ALL:
- sc_access[0].reg_addr = AUD16;
- sc_access[1].reg_addr = AUD17;
- sc_access[2].reg_addr = AUD15;
- sc_access[3].reg_addr = MICCTRL;
- sc_access[4].reg_addr = MICLICTRL1;
- sc_access[5].reg_addr = MICLICTRL2;
- sc_access[0].mask = sc_access[1].mask =
- sc_access[2].mask = MASK7;
- sc_access[3].mask = MASK5;
- sc_access[4].mask = sc_access[5].mask = MASK6;
-
- if (value == MUTE) {
- sc_access[0].value =
- sc_access[1].value = sc_access[2].value = 0x80;
- sc_access[3].value = 0x20;
- sc_access[4].value = sc_access[5].value = 0x40;
-
- } else {
- sc_access[0].value = sc_access[1].value =
- sc_access[2].value = sc_access[3].value =
- sc_access[4].value = sc_access[5].value = 0x0;
- }
- if (snd_pmic_ops_fs.num_channel == 1)
- sc_access[1].value = sc_access[2].value = 0x80;
- reg_num = 6;
- snd_pmic_ops_fs.mute_status = value;
- snd_pmic_ops_fs.master_mute = value;
- break;
-
- }
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, reg_num);
-}
-
-static int fs_set_vol(int dev_id, int value)
-{
- struct sc_reg_access sc_acces, sc_access[4] = {{0},};
- int reg_num = 0;
- int retval = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
-
- switch (dev_id) {
- case PMIC_SND_LEFT_PB_VOL:
- pr_debug("PMIC_SND_LEFT_PB_VOL:%d\n", value);
- sc_access[0].value = sc_access[1].value = value;
- sc_access[0].reg_addr = AUD16;
- sc_access[1].reg_addr = AUD15;
- sc_access[0].mask = sc_access[1].mask =
- (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
- reg_num = 2;
- break;
-
- case PMIC_SND_RIGHT_PB_VOL:
- pr_debug("PMIC_SND_RIGHT_PB_VOL:%d\n", value);
- sc_access[0].value = sc_access[1].value = value;
- sc_access[0].reg_addr = AUD17;
- sc_access[1].reg_addr = AUD15;
- sc_access[0].mask = sc_access[1].mask =
- (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
- if (snd_pmic_ops_fs.num_channel == 1) {
- sc_access[0].value = sc_access[1].value = 0x80;
- sc_access[0].mask = sc_access[1].mask = MASK7;
- }
- reg_num = 2;
- break;
- case PMIC_SND_CAPTURE_VOL:
- pr_debug("PMIC_SND_CAPTURE_VOL:%d\n", value);
- sc_access[0].reg_addr = MICLICTRL1;
- sc_access[1].reg_addr = MICLICTRL2;
- sc_access[2].reg_addr = DMICCTRL1;
- sc_access[2].value = value;
- sc_access[0].value = sc_access[1].value = value;
- sc_acces.reg_addr = MICLICTRL3;
- sc_acces.value = value;
- sc_acces.mask = (MASK0|MASK1|MASK2|MASK3|MASK5|MASK6|MASK7);
- retval = sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
- sc_access[0].mask = sc_access[1].mask =
- sc_access[2].mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
- reg_num = 3;
- break;
-
- default:
- return -EINVAL;
- }
-
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, reg_num);
-}
-
-static int fs_get_mute(int dev_id, u8 *value)
-{
- struct sc_reg_access sc_access[6] = {{0,},};
-
- int retval = 0, temp_value = 0, mask = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
-
- switch (dev_id) {
-
- case PMIC_SND_AMIC_MUTE:
- case PMIC_SND_HP_MIC_MUTE:
- sc_access[0].reg_addr = MICLICTRL1;
- mask = MASK6;
- retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
- if (sc_access[0].value & mask)
- *value = MUTE;
- else
- *value = UNMUTE;
- break;
- case PMIC_SND_DMIC_MUTE:
- sc_access[0].reg_addr = MICCTRL;
- mask = MASK5;
- retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
- temp_value = (sc_access[0].value & mask);
- if (temp_value == 0)
- *value = UNMUTE;
- else
- *value = MUTE;
- break;
-
- case PMIC_SND_LEFT_HP_MUTE:
- case PMIC_SND_LEFT_SPEAKER_MUTE:
- sc_access[0].reg_addr = AUD16;
- mask = MASK7;
- retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
- temp_value = sc_access[0].value & mask;
- if (temp_value == 0)
- *value = UNMUTE;
- else
- *value = MUTE;
- break;
- case PMIC_SND_RIGHT_HP_MUTE:
- case PMIC_SND_RIGHT_SPEAKER_MUTE:
- sc_access[0].reg_addr = AUD17;
- mask = MASK7;
- retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
- temp_value = sc_access[0].value & mask;
- if (temp_value == 0)
- *value = UNMUTE;
- else
- *value = MUTE;
- break;
- default:
- return -EINVAL;
- }
-
- return retval;
-}
-
-static int fs_get_vol(int dev_id, int *value)
-{
- struct sc_reg_access sc_access = {0,};
- int retval = 0, mask = 0;
-
- if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
- retval = fs_init_card();
- if (retval)
- return retval;
-
- switch (dev_id) {
- case PMIC_SND_CAPTURE_VOL:
- pr_debug("PMIC_SND_CAPTURE_VOL\n");
- sc_access.reg_addr = MICLICTRL1;
- mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
- break;
- case PMIC_SND_LEFT_PB_VOL:
- pr_debug("PMIC_SND_LEFT_PB_VOL\n");
- sc_access.reg_addr = AUD16;
- mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
- break;
- case PMIC_SND_RIGHT_PB_VOL:
- pr_debug("PMIC_SND_RT_PB_VOL\n");
- sc_access.reg_addr = AUD17;
- mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
- break;
- default:
- return -EINVAL;
- }
-
- retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
- pr_debug("value read = 0x%x\n", sc_access.value);
- *value = (int) (sc_access.value & mask);
- pr_debug("value returned = 0x%x\n", *value);
- return retval;
-}
-
-static void fs_pmic_irq_enable(void *data)
-{
- struct snd_intelmad *intelmaddata = data;
- struct sc_reg_access sc_access[] = {
- {0x187, 0x00, MASK7},
- {0x188, 0x10, MASK4},
- {0x18b, 0x10, MASK4},
- };
-
- struct sc_reg_access sc_access_write[] = {
- {0x198, 0x00, 0x0},
- };
- pr_debug("Audio interrupt enable\n");
- sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
- sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1);
-
- intelmaddata->jack[0].jack_status = 0;
- /*intelmaddata->jack[1].jack_status = 0;*/
-
- jack_det_enabled = true;
- return;
-}
-
-static void fs_pmic_irq_cb(void *cb_data, u8 value)
-{
- struct mad_jack *mjack = NULL;
- struct snd_intelmad *intelmaddata = cb_data;
- unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
-
- mjack = &intelmaddata->jack[0];
-
- if (value & 0x4) {
- if (!jack_det_enabled)
- fs_pmic_irq_enable(intelmaddata);
-
- /* send headphone detect */
- pr_debug(":MAD headphone %d\n", value & 0x4);
- present = !(mjack->jack_status);
- mjack->jack_status = present;
- jack_event_flag = 1;
- mjack->jack.type = SND_JACK_HEADPHONE;
- }
-
- if (value & 0x2) {
- /* send short push */
- pr_debug(":MAD short push %d\n", value & 0x2);
- present = 1;
- jack_event_flag = 1;
- buttonpressflag = 1;
- mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
- }
-
- if (value & 0x1) {
- /* send long push */
- pr_debug(":MAD long push %d\n", value & 0x1);
- present = 1;
- jack_event_flag = 1;
- buttonpressflag = 1;
- mjack->jack.type = MID_JACK_HS_LONG_PRESS;
- }
-
- if (value & 0x8) {
- if (!jack_det_enabled)
- fs_pmic_irq_enable(intelmaddata);
- /* send headset detect */
- pr_debug(":MAD headset = %d\n", value & 0x8);
- present = !(mjack->jack_status);
- mjack->jack_status = present;
- jack_event_flag = 1;
- mjack->jack.type = SND_JACK_HEADSET;
- }
-
-
- if (jack_event_flag)
- sst_mad_send_jack_report(&mjack->jack,
- buttonpressflag, present);
-
- return;
-}
-static int fs_jack_enable(void)
-{
- return 0;
-}
-
-struct snd_pmic_ops snd_pmic_ops_fs = {
- .set_input_dev = fs_set_selected_input_dev,
- .set_output_dev = fs_set_selected_output_dev,
- .set_mute = fs_set_mute,
- .get_mute = fs_get_mute,
- .set_vol = fs_set_vol,
- .get_vol = fs_get_vol,
- .init_card = fs_init_card,
- .set_pcm_audio_params = fs_set_pcm_audio_params,
- .set_pcm_voice_params = fs_set_pcm_voice_params,
- .set_voice_port = fs_set_voice_port,
- .set_audio_port = fs_set_audio_port,
- .power_up_pmic_pb = fs_power_up_pb,
- .power_up_pmic_cp = fs_power_up_cp,
- .power_down_pmic_pb = fs_power_down_pb,
- .power_down_pmic_cp = fs_power_down_cp,
- .power_down_pmic = fs_power_down,
- .pmic_irq_cb = fs_pmic_irq_cb,
- /*
- * Jack detection enabling
- * need be delayed till first IRQ happen.
- */
- .pmic_irq_enable = NULL,
- .pmic_jack_enable = fs_jack_enable,
-};
diff --git a/drivers/staging/intel_sst/intelmid_v1_control.c b/drivers/staging/intel_sst/intelmid_v1_control.c
deleted file mode 100644
index 9d00728d8deb..000000000000
--- a/drivers/staging/intel_sst/intelmid_v1_control.c
+++ /dev/null
@@ -1,978 +0,0 @@
-/* intel_sst_v1_control.c - Intel SST Driver for audio engine
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This file contains the control operations of vendor 2
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/file.h>
-#include <asm/mrst.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/control.h>
-#include <sound/initval.h>
-#include "intel_sst.h"
-#include "intel_sst_ioctl.h"
-#include "intelmid.h"
-#include "intelmid_snd_control.h"
-
-#include <linux/gpio.h>
-#define KOSKI_VOICE_CODEC_ENABLE 46
-
-enum _reg_v2 {
-
- MASTER_CLOCK_PRESCALAR = 0x205,
- SET_MASTER_AND_LR_CLK1 = 0x20b,
- SET_MASTER_AND_LR_CLK2 = 0x20c,
- MASTER_MODE_AND_DATA_DELAY = 0x20d,
- DIGITAL_INTERFACE_TO_DAI2 = 0x20e,
- CLK_AND_FS1 = 0x208,
- CLK_AND_FS2 = 0x209,
- DAI2_TO_DAC_HP = 0x210,
- HP_OP_SINGLE_ENDED = 0x224,
- ENABLE_OPDEV_CTRL = 0x226,
- ENABLE_DEV_AND_USE_XTAL = 0x227,
-
- /* Max audio subsystem (PQ49) MAX 8921 */
- AS_IP_MODE_CTL = 0xF9,
- AS_LEFT_SPKR_VOL_CTL = 0xFA, /* Mono Earpiece volume control */
- AS_RIGHT_SPKR_VOL_CTL = 0xFB,
- AS_LEFT_HP_VOL_CTL = 0xFC,
- AS_RIGHT_HP_VOL_CTL = 0xFD,
- AS_OP_MIX_CTL = 0xFE,
- AS_CONFIG = 0xFF,
-
- /* Headphone volume control & mute registers */
- VOL_CTRL_LT = 0x21c,
- VOL_CTRL_RT = 0x21d,
-
-};
-/**
- * mx_init_card - initialize the sound card
- *
- * This initializes the audio paths to know values in case of this sound card
- */
-static int mx_init_card(void)
-{
- struct sc_reg_access sc_access[] = {
- {0x200, 0x80, 0x00},
- {0x201, 0xC0, 0x00},
- {0x202, 0x00, 0x00},
- {0x203, 0x00, 0x00},
- {0x204, 0x02, 0x00},
- {0x205, 0x10, 0x00},
- {0x206, 0x60, 0x00},
- {0x207, 0x00, 0x00},
- {0x208, 0x90, 0x00},
- {0x209, 0x51, 0x00},
- {0x20a, 0x00, 0x00},
- {0x20b, 0x10, 0x00},
- {0x20c, 0x00, 0x00},
- {0x20d, 0x00, 0x00},
- {0x20e, 0x21, 0x00},
- {0x20f, 0x00, 0x00},
- {0x210, 0x84, 0x00},
- {0x211, 0xB3, 0x00},
- {0x212, 0x00, 0x00},
- {0x213, 0x00, 0x00},
- {0x214, 0x41, 0x00},
- {0x215, 0x00, 0x00},
- {0x216, 0x00, 0x00},
- {0x217, 0x00, 0x00},
- {0x218, 0x03, 0x00},
- {0x219, 0x03, 0x00},
- {0x21a, 0x00, 0x00},
- {0x21b, 0x00, 0x00},
- {0x21c, 0x00, 0x00},
- {0x21d, 0x00, 0x00},
- {0x21e, 0x00, 0x00},
- {0x21f, 0x00, 0x00},
- {0x220, 0x20, 0x00},
- {0x221, 0x20, 0x00},
- {0x222, 0x51, 0x00},
- {0x223, 0x20, 0x00},
- {0x224, 0x04, 0x00},
- {0x225, 0x80, 0x00},
- {0x226, 0x0F, 0x00},
- {0x227, 0x08, 0x00},
- {0xf9, 0x40, 0x00},
- {0xfa, 0x1f, 0x00},
- {0xfb, 0x1f, 0x00},
- {0xfc, 0x1f, 0x00},
- {0xfd, 0x1f, 0x00},
- {0xfe, 0x00, 0x00},
- {0xff, 0x0c, 0x00},
- };
- snd_pmic_ops_mx.card_status = SND_CARD_INIT_DONE;
- snd_pmic_ops_mx.num_channel = 2;
- snd_pmic_ops_mx.master_mute = UNMUTE;
- snd_pmic_ops_mx.mute_status = UNMUTE;
- return sst_sc_reg_access(sc_access, PMIC_WRITE, 47);
-}
-
-static int mx_enable_audiodac(int value)
-{
- struct sc_reg_access sc_access[3];
- int mute_val = 0;
- int mute_val1 = 0;
- int retval = 0;
-
- sc_access[0].reg_addr = AS_LEFT_HP_VOL_CTL;
- sc_access[1].reg_addr = AS_RIGHT_HP_VOL_CTL;
-
- if (value == UNMUTE) {
- mute_val = 0x1F;
- mute_val1 = 0x00;
- } else {
- mute_val = 0x00;
- mute_val1 = 0x40;
- }
- sc_access[0].mask = sc_access[1].mask = MASK0|MASK1|MASK2|MASK3|MASK4;
- sc_access[0].value = sc_access[1].value = (u8)mute_val;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
- if (retval)
- return retval;
- pr_debug("mute status = %d\n", snd_pmic_ops_mx.mute_status);
- if (snd_pmic_ops_mx.mute_status == MUTE ||
- snd_pmic_ops_mx.master_mute == MUTE)
- return retval;
-
- sc_access[0].reg_addr = VOL_CTRL_LT;
- sc_access[1].reg_addr = VOL_CTRL_RT;
- sc_access[0].mask = sc_access[1].mask = MASK6;
- sc_access[0].value = sc_access[1].value = mute_val1;
- if (snd_pmic_ops_mx.num_channel == 1)
- sc_access[1].value = 0x40;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-}
-
-static int mx_power_up_pb(unsigned int port)
-{
-
- int retval = 0;
- struct sc_reg_access sc_access[3];
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
- retval = mx_enable_audiodac(MUTE);
- if (retval)
- return retval;
-
- msleep(10);
-
- sc_access[0].reg_addr = AS_CONFIG;
- sc_access[0].mask = MASK7;
- sc_access[0].value = 0x80;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- if (retval)
- return retval;
-
- sc_access[0].reg_addr = ENABLE_OPDEV_CTRL;
- sc_access[0].mask = 0xff;
- sc_access[0].value = 0x3C;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- if (retval)
- return retval;
-
- sc_access[0].reg_addr = ENABLE_DEV_AND_USE_XTAL;
- sc_access[0].mask = 0x80;
- sc_access[0].value = 0x80;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- if (retval)
- return retval;
-
- return mx_enable_audiodac(UNMUTE);
-}
-
-static int mx_power_down_pb(unsigned int device)
-{
- struct sc_reg_access sc_access[3];
- int retval = 0;
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
-
- retval = mx_enable_audiodac(MUTE);
- if (retval)
- return retval;
-
- sc_access[0].reg_addr = ENABLE_OPDEV_CTRL;
- sc_access[0].mask = MASK3|MASK2;
- sc_access[0].value = 0x00;
-
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- if (retval)
- return retval;
-
- return mx_enable_audiodac(UNMUTE);
-}
-
-static int mx_power_up_cp(unsigned int port)
-{
- int retval = 0;
- struct sc_reg_access sc_access[] = {
- {ENABLE_DEV_AND_USE_XTAL, 0x80, MASK7},
- {ENABLE_OPDEV_CTRL, 0x3, 0x3},
- };
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
-
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-}
-
-static int mx_power_down_cp(unsigned int device)
-{
- struct sc_reg_access sc_access[] = {
- {ENABLE_OPDEV_CTRL, 0x00, MASK1|MASK0},
- };
- int retval = 0;
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
-
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
-}
-
-static int mx_power_down(void)
-{
- int retval = 0;
- struct sc_reg_access sc_access[3];
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
-
- retval = mx_enable_audiodac(MUTE);
- if (retval)
- return retval;
-
- sc_access[0].reg_addr = AS_CONFIG;
- sc_access[0].mask = MASK7;
- sc_access[0].value = 0x00;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- if (retval)
- return retval;
-
- sc_access[0].reg_addr = ENABLE_DEV_AND_USE_XTAL;
- sc_access[0].mask = MASK7;
- sc_access[0].value = 0x00;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- if (retval)
- return retval;
-
- sc_access[0].reg_addr = ENABLE_OPDEV_CTRL;
- sc_access[0].mask = MASK3|MASK2;
- sc_access[0].value = 0x00;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- if (retval)
- return retval;
-
- return mx_enable_audiodac(UNMUTE);
-}
-
-static int mx_set_pcm_voice_params(void)
-{
- int retval = 0;
- struct sc_reg_access sc_access[] = {
- {0x200, 0x80, 0x00},
- {0x201, 0xC0, 0x00},
- {0x202, 0x00, 0x00},
- {0x203, 0x00, 0x00},
- {0x204, 0x0e, 0x00},
- {0x205, 0x20, 0x00},
- {0x206, 0x8f, 0x00},
- {0x207, 0x21, 0x00},
- {0x208, 0x18, 0x00},
- {0x209, 0x32, 0x00},
- {0x20a, 0x00, 0x00},
- {0x20b, 0x5A, 0x00},
- {0x20c, 0xBE, 0x00},/* 0x00 -> 0xBE Koski */
- {0x20d, 0x00, 0x00}, /* DAI2 'off' */
- {0x20e, 0x40, 0x00},
- {0x20f, 0x00, 0x00},
- {0x210, 0x84, 0x00},
- {0x211, 0x33, 0x00}, /* Voice filter */
- {0x212, 0x00, 0x00},
- {0x213, 0x00, 0x00},
- {0x214, 0x41, 0x00},
- {0x215, 0x00, 0x00},
- {0x216, 0x00, 0x00},
- {0x217, 0x20, 0x00},
- {0x218, 0x00, 0x00},
- {0x219, 0x00, 0x00},
- {0x21a, 0x40, 0x00},
- {0x21b, 0x40, 0x00},
- {0x21c, 0x09, 0x00},
- {0x21d, 0x09, 0x00},
- {0x21e, 0x00, 0x00},
- {0x21f, 0x00, 0x00},
- {0x220, 0x00, 0x00}, /* Microphone configurations */
- {0x221, 0x00, 0x00}, /* Microphone configurations */
- {0x222, 0x50, 0x00}, /* Microphone configurations */
- {0x223, 0x21, 0x00}, /* Microphone configurations */
- {0x224, 0x00, 0x00},
- {0x225, 0x80, 0x00},
- {0xf9, 0x40, 0x00},
- {0xfa, 0x19, 0x00},
- {0xfb, 0x19, 0x00},
- {0xfc, 0x12, 0x00},
- {0xfd, 0x12, 0x00},
- {0xfe, 0x00, 0x00},
- };
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
- pr_debug("SST DBG:mx_set_pcm_voice_params called\n");
- return sst_sc_reg_access(sc_access, PMIC_WRITE, 44);
-}
-
-static int mx_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
-{
- int retval = 0;
-
- int config1 = 0, config2 = 0, filter = 0xB3;
- struct sc_reg_access sc_access[5];
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
-
- switch (sfreq) {
- case 8000:
- config1 = 0x10;
- config2 = 0x00;
- filter = 0x33;
- break;
- case 11025:
- config1 = 0x16;
- config2 = 0x0d;
- break;
- case 12000:
- config1 = 0x18;
- config2 = 0x00;
- break;
- case 16000:
- config1 = 0x20;
- config2 = 0x00;
- break;
- case 22050:
- config1 = 0x2c;
- config2 = 0x1a;
- break;
- case 24000:
- config1 = 0x30;
- config2 = 0x00;
- break;
- case 32000:
- config1 = 0x40;
- config2 = 0x00;
- break;
- case 44100:
- config1 = 0x58;
- config2 = 0x33;
- break;
- case 48000:
- config1 = 0x60;
- config2 = 0x00;
- break;
- }
- snd_pmic_ops_mx.num_channel = num_channel;
- /*mute the right channel if MONO*/
- if (snd_pmic_ops_mx.num_channel == 1) {
- sc_access[0].reg_addr = VOL_CTRL_RT;
- sc_access[0].value = 0x40;
- sc_access[0].mask = MASK6;
-
- sc_access[1].reg_addr = 0x224;
- sc_access[1].value = 0x05;
- sc_access[1].mask = MASK0|MASK1|MASK2;
-
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
- if (retval)
- return retval;
- } else {
- sc_access[0].reg_addr = VOL_CTRL_RT;
- sc_access[0].value = 0x00;
- sc_access[0].mask = MASK6;
-
- sc_access[1].reg_addr = 0x224;
- sc_access[1].value = 0x04;
- sc_access[1].mask = MASK0|MASK1|MASK2;
-
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
- if (retval)
- return retval;
- }
- sc_access[0].reg_addr = 0x206;
- sc_access[0].value = config1;
- sc_access[1].reg_addr = 0x207;
- sc_access[1].value = config2;
-
- if (word_size == 16) {
- sc_access[2].value = 0x51;
- sc_access[3].value = 0x31;
- } else if (word_size == 24) {
- sc_access[2].value = 0x52;
- sc_access[3].value = 0x92;
- }
-
- sc_access[2].reg_addr = 0x209;
- sc_access[3].reg_addr = 0x20e;
-
- sc_access[4].reg_addr = 0x211;
- sc_access[4].value = filter;
-
- return sst_sc_reg_access(sc_access, PMIC_WRITE, 5);
-}
-
-static int mx_set_selected_output_dev(u8 dev_id)
-{
- struct sc_reg_access sc_access[2];
- int num_reg = 0;
- int retval = 0;
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
-
- pr_debug("mx_set_selected_output_dev dev_id:0x%x\n", dev_id);
- snd_pmic_ops_mx.output_dev_id = dev_id;
- switch (dev_id) {
- case STEREO_HEADPHONE:
- sc_access[0].reg_addr = 0xFF;
- sc_access[0].value = 0x8C;
- sc_access[0].mask =
- MASK2|MASK3|MASK5|MASK6|MASK4;
-
- num_reg = 1;
- break;
- case MONO_EARPIECE:
- case INTERNAL_SPKR:
- sc_access[0].reg_addr = 0xFF;
- sc_access[0].value = 0xb0;
- sc_access[0].mask = MASK2|MASK3|MASK5|MASK6|MASK4;
-
- num_reg = 1;
- break;
- case RECEIVER:
- pr_debug("RECEIVER Koski selected\n");
-
- /* configuration - AS enable, receiver enable */
- sc_access[0].reg_addr = 0xFF;
- sc_access[0].value = 0x81;
- sc_access[0].mask = 0xff;
-
- num_reg = 1;
- break;
- default:
- pr_err("Not a valid output dev\n");
- return 0;
- }
- return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg);
-}
-
-
-static int mx_set_voice_port(int status)
-{
- int retval = 0;
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
- if (status == ACTIVATE)
- retval = mx_set_pcm_voice_params();
-
- return retval;
-}
-
-static int mx_set_audio_port(int status)
-{
- return 0;
-}
-
-static int mx_set_selected_input_dev(u8 dev_id)
-{
- struct sc_reg_access sc_access[2];
- int num_reg = 0;
- int retval = 0;
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
- snd_pmic_ops_mx.input_dev_id = dev_id;
- pr_debug("mx_set_selected_input_dev dev_id:0x%x\n", dev_id);
-
- switch (dev_id) {
- case AMIC:
- sc_access[0].reg_addr = 0x223;
- sc_access[0].value = 0x00;
- sc_access[0].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
- sc_access[1].reg_addr = 0x222;
- sc_access[1].value = 0x50;
- sc_access[1].mask = MASK7|MASK6|MASK5|MASK4;
- num_reg = 2;
- break;
-
- case HS_MIC:
- sc_access[0].reg_addr = 0x223;
- sc_access[0].value = 0x20;
- sc_access[0].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
- sc_access[1].reg_addr = 0x222;
- sc_access[1].value = 0x51;
- sc_access[1].mask = MASK7|MASK6|MASK5|MASK4;
- num_reg = 2;
- break;
- case DMIC:
- sc_access[1].reg_addr = 0x222;
- sc_access[1].value = 0x00;
- sc_access[1].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
- sc_access[0].reg_addr = 0x223;
- sc_access[0].value = 0x20;
- sc_access[0].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
- num_reg = 2;
- break;
- }
- return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg);
-}
-
-static int mx_set_mute(int dev_id, u8 value)
-{
- struct sc_reg_access sc_access[5];
- int num_reg = 0;
- int retval = 0;
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
-
-
- pr_debug("set_mute dev_id:0x%x , value:%d\n", dev_id, value);
-
- switch (dev_id) {
- case PMIC_SND_DMIC_MUTE:
- case PMIC_SND_AMIC_MUTE:
- case PMIC_SND_HP_MIC_MUTE:
- sc_access[0].reg_addr = 0x220;
- sc_access[1].reg_addr = 0x221;
- sc_access[2].reg_addr = 0x223;
- if (value == MUTE) {
- sc_access[0].value = 0x00;
- sc_access[1].value = 0x00;
- if (snd_pmic_ops_mx.input_dev_id == DMIC)
- sc_access[2].value = 0x00;
- else
- sc_access[2].value = 0x20;
- } else {
- sc_access[0].value = 0x20;
- sc_access[1].value = 0x20;
- if (snd_pmic_ops_mx.input_dev_id == DMIC)
- sc_access[2].value = 0x20;
- else
- sc_access[2].value = 0x00;
- }
- sc_access[0].mask = MASK5|MASK6;
- sc_access[1].mask = MASK5|MASK6;
- sc_access[2].mask = MASK5|MASK6;
- num_reg = 3;
- break;
- case PMIC_SND_LEFT_SPEAKER_MUTE:
- case PMIC_SND_LEFT_HP_MUTE:
- sc_access[0].reg_addr = VOL_CTRL_LT;
- if (value == MUTE)
- sc_access[0].value = 0x40;
- else
- sc_access[0].value = 0x00;
- sc_access[0].mask = MASK6;
- num_reg = 1;
- snd_pmic_ops_mx.mute_status = value;
- break;
- case PMIC_SND_RIGHT_SPEAKER_MUTE:
- case PMIC_SND_RIGHT_HP_MUTE:
- sc_access[0].reg_addr = VOL_CTRL_RT;
- if (snd_pmic_ops_mx.num_channel == 1)
- value = MUTE;
- if (value == MUTE)
- sc_access[0].value = 0x40;
- else
- sc_access[0].value = 0x00;
- sc_access[0].mask = MASK6;
- num_reg = 1;
- snd_pmic_ops_mx.mute_status = value;
- break;
- case PMIC_SND_MUTE_ALL:
- sc_access[0].reg_addr = VOL_CTRL_RT;
- sc_access[1].reg_addr = VOL_CTRL_LT;
- sc_access[2].reg_addr = 0x220;
- sc_access[3].reg_addr = 0x221;
- sc_access[4].reg_addr = 0x223;
- snd_pmic_ops_mx.master_mute = value;
- if (value == MUTE) {
- sc_access[0].value = sc_access[1].value = 0x40;
- sc_access[2].value = 0x00;
- sc_access[3].value = 0x00;
- if (snd_pmic_ops_mx.input_dev_id == DMIC)
- sc_access[4].value = 0x00;
- else
- sc_access[4].value = 0x20;
-
- } else {
- sc_access[0].value = sc_access[1].value = 0x00;
- sc_access[2].value = sc_access[3].value = 0x20;
- sc_access[4].value = 0x20;
- if (snd_pmic_ops_mx.input_dev_id == DMIC)
- sc_access[4].value = 0x20;
- else
- sc_access[4].value = 0x00;
-
-
- }
- if (snd_pmic_ops_mx.num_channel == 1)
- sc_access[0].value = 0x40;
- sc_access[0].mask = sc_access[1].mask = MASK6;
- sc_access[2].mask = MASK5|MASK6;
- sc_access[3].mask = MASK5|MASK6|MASK2|MASK4;
- sc_access[4].mask = MASK5|MASK6|MASK4;
-
- num_reg = 5;
- break;
- case PMIC_SND_RECEIVER_MUTE:
- sc_access[0].reg_addr = VOL_CTRL_RT;
- if (value == MUTE)
- sc_access[0].value = 0x40;
- else
- sc_access[0].value = 0x00;
- sc_access[0].mask = MASK6;
- num_reg = 1;
- break;
- }
-
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
-}
-
-static int mx_set_vol(int dev_id, int value)
-{
- struct sc_reg_access sc_access[2] = {{0},};
- int num_reg = 0;
- int retval = 0;
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
- pr_debug("set_vol dev_id:0x%x ,value:%d\n", dev_id, value);
- switch (dev_id) {
- case PMIC_SND_RECEIVER_VOL:
- return 0;
- break;
- case PMIC_SND_CAPTURE_VOL:
- sc_access[0].reg_addr = 0x220;
- sc_access[1].reg_addr = 0x221;
- sc_access[0].value = sc_access[1].value = -value;
- sc_access[0].mask = sc_access[1].mask =
- (MASK0|MASK1|MASK2|MASK3|MASK4);
- num_reg = 2;
- break;
- case PMIC_SND_LEFT_PB_VOL:
- sc_access[0].value = -value;
- sc_access[0].reg_addr = VOL_CTRL_LT;
- sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
- num_reg = 1;
- break;
- case PMIC_SND_RIGHT_PB_VOL:
- sc_access[0].value = -value;
- sc_access[0].reg_addr = VOL_CTRL_RT;
- sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
- if (snd_pmic_ops_mx.num_channel == 1) {
- sc_access[0].value = 0x40;
- sc_access[0].mask = MASK6;
- sc_access[0].reg_addr = VOL_CTRL_RT;
- }
- num_reg = 1;
- break;
- }
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
-}
-
-static int mx_get_mute(int dev_id, u8 *value)
-{
- struct sc_reg_access sc_access[4] = {{0},};
- int retval = 0, num_reg = 0, mask = 0;
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
- switch (dev_id) {
- case PMIC_SND_DMIC_MUTE:
- case PMIC_SND_AMIC_MUTE:
- case PMIC_SND_HP_MIC_MUTE:
- sc_access[0].reg_addr = 0x220;
- mask = MASK5|MASK6;
- num_reg = 1;
- retval = sst_sc_reg_access(sc_access, PMIC_READ, num_reg);
- if (retval)
- return retval;
- *value = sc_access[0].value & mask;
- if (*value)
- *value = UNMUTE;
- else
- *value = MUTE;
- return retval;
- case PMIC_SND_LEFT_HP_MUTE:
- case PMIC_SND_LEFT_SPEAKER_MUTE:
- sc_access[0].reg_addr = VOL_CTRL_LT;
- num_reg = 1;
- mask = MASK6;
- break;
- case PMIC_SND_RIGHT_HP_MUTE:
- case PMIC_SND_RIGHT_SPEAKER_MUTE:
- sc_access[0].reg_addr = VOL_CTRL_RT;
- num_reg = 1;
- mask = MASK6;
- break;
- }
- retval = sst_sc_reg_access(sc_access, PMIC_READ, num_reg);
- if (retval)
- return retval;
- *value = sc_access[0].value & mask;
- if (*value)
- *value = MUTE;
- else
- *value = UNMUTE;
- return retval;
-}
-
-static int mx_get_vol(int dev_id, int *value)
-{
- struct sc_reg_access sc_access = {0,};
- int retval = 0, mask = 0, num_reg = 0;
-
- if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT) {
- retval = mx_init_card();
- if (retval)
- return retval;
- }
- switch (dev_id) {
- case PMIC_SND_CAPTURE_VOL:
- sc_access.reg_addr = 0x220;
- mask = MASK0|MASK1|MASK2|MASK3|MASK4;
- num_reg = 1;
- break;
- case PMIC_SND_LEFT_PB_VOL:
- sc_access.reg_addr = VOL_CTRL_LT;
- mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5;
- num_reg = 1;
- break;
- case PMIC_SND_RIGHT_PB_VOL:
- sc_access.reg_addr = VOL_CTRL_RT;
- mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5;
- num_reg = 1;
- break;
- }
- retval = sst_sc_reg_access(&sc_access, PMIC_READ, num_reg);
- if (retval)
- return retval;
- *value = -(sc_access.value & mask);
- pr_debug("get volume value extracted %d\n", *value);
- return retval;
-}
-
-static u8 mx_get_jack_status(void)
-{
- struct sc_reg_access sc_access_read = {0,};
-
- sc_access_read.reg_addr = 0x201;
- sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
- pr_debug("value returned = 0x%x\n", sc_access_read.value);
- return sc_access_read.value;
-}
-
-static void mx_pmic_irq_enable(void *data)
-{
- struct snd_intelmad *intelmaddata = data;
-
- intelmaddata->jack_prev_state = 0xc0;
- return;
-}
-
-static void mx_pmic_irq_cb(void *cb_data, u8 intsts)
-{
- u8 jack_cur_status, jack_prev_state = 0;
- struct mad_jack *mjack = NULL;
- unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
- time_t timediff;
- struct snd_intelmad *intelmaddata = cb_data;
-
- mjack = &intelmaddata->jack[0];
- if (intsts & 0x2) {
- jack_cur_status = mx_get_jack_status();
- jack_prev_state = intelmaddata->jack_prev_state;
- if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x40)) {
- /*headset insert detected. */
- pr_debug("MAD headset inserted\n");
- present = 1;
- jack_event_flag = 1;
- mjack->jack_status = 1;
- mjack->jack.type = SND_JACK_HEADSET;
- }
-
- if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x00)) {
- /* headphone insert detected. */
- pr_debug("MAD headphone inserted\n");
- present = 1;
- jack_event_flag = 1;
- mjack->jack.type = SND_JACK_HEADPHONE;
- }
-
- if ((jack_prev_state == 0x40) && (jack_cur_status == 0xc0)) {
- /* headset remove detected. */
- pr_debug("MAD headset removed\n");
-
- present = 0;
- jack_event_flag = 1;
- mjack->jack_status = 0;
- mjack->jack.type = SND_JACK_HEADSET;
- }
-
- if ((jack_prev_state == 0x00) && (jack_cur_status == 0xc0)) {
- /* headphone remove detected. */
- pr_debug("MAD headphone removed\n");
- present = 0;
- jack_event_flag = 1;
- mjack->jack.type = SND_JACK_HEADPHONE;
- }
-
- if ((jack_prev_state == 0x40) && (jack_cur_status == 0x00)) {
- /* button pressed */
- do_gettimeofday(&mjack->buttonpressed);
- pr_debug("MAD button press detected\n");
- }
-
- if ((jack_prev_state == 0x00) && (jack_cur_status == 0x40)) {
- if (mjack->jack_status) {
- /*button pressed */
- do_gettimeofday(
- &mjack->buttonreleased);
- /*button pressed */
- pr_debug("MAD Button Released detected\n");
- timediff = mjack->buttonreleased.tv_sec -
- mjack->buttonpressed.tv_sec;
- buttonpressflag = 1;
-
- if (timediff > 1) {
- pr_debug("MAD long press dtd\n");
- /* send headphone detect/undetect */
- present = 1;
- jack_event_flag = 1;
- mjack->jack.type =
- MID_JACK_HS_LONG_PRESS;
- } else {
- pr_debug("MAD short press dtd\n");
- /* send headphone detect/undetect */
- present = 1;
- jack_event_flag = 1;
- mjack->jack.type =
- MID_JACK_HS_SHORT_PRESS;
- }
- } else {
- /***workaround for maxim
- hw issue,0x00 t 0x40 is not
- a valid transiton for Headset insertion */
- /*headset insert detected. */
- pr_debug("MAD headset inserted\n");
- present = 1;
- jack_event_flag = 1;
- mjack->jack_status = 1;
- mjack->jack.type = SND_JACK_HEADSET;
- }
- }
- intelmaddata->jack_prev_state = jack_cur_status;
- pr_debug("mx_pmic_irq_cb prv_state= 0x%x\n",
- intelmaddata->jack_prev_state);
- }
-
- if (jack_event_flag)
- sst_mad_send_jack_report(&mjack->jack,
- buttonpressflag, present);
-}
-static int mx_jack_enable(void)
-{
- return 0;
-}
-
-struct snd_pmic_ops snd_pmic_ops_mx = {
- .set_input_dev = mx_set_selected_input_dev,
- .set_output_dev = mx_set_selected_output_dev,
- .set_mute = mx_set_mute,
- .get_mute = mx_get_mute,
- .set_vol = mx_set_vol,
- .get_vol = mx_get_vol,
- .init_card = mx_init_card,
- .set_pcm_audio_params = mx_set_pcm_audio_params,
- .set_pcm_voice_params = mx_set_pcm_voice_params,
- .set_voice_port = mx_set_voice_port,
- .set_audio_port = mx_set_audio_port,
- .power_up_pmic_pb = mx_power_up_pb,
- .power_up_pmic_cp = mx_power_up_cp,
- .power_down_pmic_pb = mx_power_down_pb,
- .power_down_pmic_cp = mx_power_down_cp,
- .power_down_pmic = mx_power_down,
- .pmic_irq_cb = mx_pmic_irq_cb,
- .pmic_irq_enable = mx_pmic_irq_enable,
- .pmic_jack_enable = mx_jack_enable,
-};
-
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
deleted file mode 100644
index 46ab55eb8097..000000000000
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
- * intelmid_v2_control.c - Intel Sound card driver for MID
- *
- * Copyright (C) 2008-10 Intel Corp
- * Authors: Vinod Koul <vinod.koul@intel.com>
- * Harsha Priya <priya.harsha@intel.com>
- * KP Jeeja <jeeja.kp@intel.com>
- * Dharageswari R <dharageswari.r@intel.com>
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This file contains the control operations of vendor 3
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/gpio.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/file.h>
-#include <sound/control.h>
-#include "intel_sst.h"
-#include "intelmid_snd_control.h"
-#include "intelmid.h"
-
-enum reg_v3 {
- VAUDIOCNT = 0x51,
- VOICEPORT1 = 0x100,
- VOICEPORT2 = 0x101,
- AUDIOPORT1 = 0x102,
- AUDIOPORT2 = 0x103,
- ADCSAMPLERATE = 0x104,
- DMICCTRL1 = 0x105,
- DMICCTRL2 = 0x106,
- MICCTRL = 0x107,
- MICSELVOL = 0x108,
- LILSEL = 0x109,
- LIRSEL = 0x10a,
- VOICEVOL = 0x10b,
- AUDIOLVOL = 0x10c,
- AUDIORVOL = 0x10d,
- LMUTE = 0x10e,
- RMUTE = 0x10f,
- POWERCTRL1 = 0x110,
- POWERCTRL2 = 0x111,
- DRVPOWERCTRL = 0x112,
- VREFPLL = 0x113,
- PCMBUFCTRL = 0x114,
- SOFTMUTE = 0x115,
- DTMFPATH = 0x116,
- DTMFVOL = 0x117,
- DTMFFREQ = 0x118,
- DTMFHFREQ = 0x119,
- DTMFLFREQ = 0x11a,
- DTMFCTRL = 0x11b,
- DTMFASON = 0x11c,
- DTMFASOFF = 0x11d,
- DTMFASINUM = 0x11e,
- CLASSDVOL = 0x11f,
- VOICEDACAVOL = 0x120,
- AUDDACAVOL = 0x121,
- LOMUTEVOL = 0x122,
- HPLVOL = 0x123,
- HPRVOL = 0x124,
- MONOVOL = 0x125,
- LINEOUTMIXVOL = 0x126,
- EPMIXVOL = 0x127,
- LINEOUTLSEL = 0x128,
- LINEOUTRSEL = 0x129,
- EPMIXOUTSEL = 0x12a,
- HPLMIXSEL = 0x12b,
- HPRMIXSEL = 0x12c,
- LOANTIPOP = 0x12d,
- AUXDBNC = 0x12f,
-};
-
-static void nc_set_amp_power(int power)
-{
- if (snd_pmic_ops_nc.gpio_amp)
- gpio_set_value(snd_pmic_ops_nc.gpio_amp, power);
-}
-
-/****
- * nc_init_card - initialize the sound card
- *
- * This initializes the audio paths to know values in case of this sound card
- */
-static int nc_init_card(void)
-{
- struct sc_reg_access sc_access[] = {
- {VAUDIOCNT, 0x25, 0},
- {VOICEPORT1, 0x00, 0},
- {VOICEPORT2, 0x00, 0},
- {AUDIOPORT1, 0x98, 0},
- {AUDIOPORT2, 0x09, 0},
- {AUDIOLVOL, 0x00, 0},
- {AUDIORVOL, 0x00, 0},
- {LMUTE, 0x03, 0},
- {RMUTE, 0x03, 0},
- {POWERCTRL1, 0x00, 0},
- {POWERCTRL2, 0x00, 0},
- {DRVPOWERCTRL, 0x00, 0},
- {VREFPLL, 0x10, 0},
- {HPLMIXSEL, 0xee, 0},
- {HPRMIXSEL, 0xf6, 0},
- {PCMBUFCTRL, 0x0, 0},
- {VOICEVOL, 0x0e, 0},
- {HPLVOL, 0x06, 0},
- {HPRVOL, 0x06, 0},
- {MICCTRL, 0x51, 0x00},
- {ADCSAMPLERATE, 0x8B, 0x00},
- {MICSELVOL, 0x5B, 0x00},
- {LILSEL, 0x06, 0},
- {LIRSEL, 0x46, 0},
- {LOANTIPOP, 0x00, 0},
- {DMICCTRL1, 0x40, 0},
- {AUXDBNC, 0xff, 0},
- };
- snd_pmic_ops_nc.card_status = SND_CARD_INIT_DONE;
- snd_pmic_ops_nc.master_mute = UNMUTE;
- snd_pmic_ops_nc.mute_status = UNMUTE;
- sst_sc_reg_access(sc_access, PMIC_WRITE, 27);
- mutex_init(&snd_pmic_ops_nc.lock);
- pr_debug("init complete!!\n");
- return 0;
-}
-
-static int nc_enable_audiodac(int value)
-{
- struct sc_reg_access sc_access[3];
- int mute_val = 0;
-
- if (snd_pmic_ops_nc.mute_status == MUTE)
- return 0;
-
- if (((snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE) ||
- (snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)) &&
- (value == UNMUTE))
- return 0;
- if (value == UNMUTE) {
- /* unmute the system, set the 7th bit to zero */
- mute_val = 0x00;
- } else {
- /* MUTE:Set the seventh bit */
- mute_val = 0x04;
-
- }
- sc_access[0].reg_addr = LMUTE;
- sc_access[1].reg_addr = RMUTE;
- sc_access[0].mask = sc_access[1].mask = MASK2;
- sc_access[0].value = sc_access[1].value = mute_val;
-
- if (snd_pmic_ops_nc.num_channel == 1)
- sc_access[1].value = 0x04;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-
-}
-
-static int nc_power_up_pb(unsigned int port)
-{
- struct sc_reg_access sc_access[7];
- int retval = 0;
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
- if (port == 0xFF)
- return 0;
- mutex_lock(&snd_pmic_ops_nc.lock);
- nc_enable_audiodac(MUTE);
- msleep(30);
-
- pr_debug("powering up pb....\n");
-
- sc_access[0].reg_addr = VAUDIOCNT;
- sc_access[0].value = 0x27;
- sc_access[0].mask = 0x27;
- sc_access[1].reg_addr = VREFPLL;
- if (port == 0) {
- sc_access[1].value = 0x3A;
- sc_access[1].mask = 0x3A;
- } else if (port == 1) {
- sc_access[1].value = 0x35;
- sc_access[1].mask = 0x35;
- }
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-
-
-
- sc_access[0].reg_addr = POWERCTRL1;
- if (port == 0) {
- sc_access[0].value = 0x40;
- sc_access[0].mask = 0x40;
- } else if (port == 1) {
- sc_access[0].value = 0x01;
- sc_access[0].mask = 0x01;
- }
- sc_access[1].reg_addr = POWERCTRL2;
- sc_access[1].value = 0x0C;
- sc_access[1].mask = 0x0C;
-
- sc_access[2].reg_addr = DRVPOWERCTRL;
- sc_access[2].value = 0x86;
- sc_access[2].mask = 0x86;
-
- sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
-
- msleep(30);
-
- snd_pmic_ops_nc.pb_on = 1;
-
- /*
- * There is a mismatch between Playback Sources and the enumerated
- * values of output sources. This mismatch causes ALSA upper to send
- * Item 1 for Internal Speaker, but the expected enumeration is 2! For
- * now, treat MONO_EARPIECE and INTERNAL_SPKR identically and power up
- * the needed resources
- */
- if (snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE ||
- snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)
- nc_set_amp_power(1);
- nc_enable_audiodac(UNMUTE);
- mutex_unlock(&snd_pmic_ops_nc.lock);
- return 0;
-}
-
-static int nc_power_up_cp(unsigned int port)
-{
- struct sc_reg_access sc_access[5];
- int retval = 0;
-
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
-
- pr_debug("powering up cp....\n");
-
- if (port == 0xFF)
- return 0;
- sc_access[0].reg_addr = VAUDIOCNT;
- sc_access[0].value = 0x27;
- sc_access[0].mask = 0x27;
- sc_access[1].reg_addr = VREFPLL;
- if (port == 0) {
- sc_access[1].value = 0x3E;
- sc_access[1].mask = 0x3E;
- } else if (port == 1) {
- sc_access[1].value = 0x35;
- sc_access[1].mask = 0x35;
- }
-
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-
-
- sc_access[0].reg_addr = POWERCTRL1;
- if (port == 0) {
- sc_access[0].value = 0xB4;
- sc_access[0].mask = 0xB4;
- } else if (port == 1) {
- sc_access[0].value = 0xBF;
- sc_access[0].mask = 0xBF;
- }
- sc_access[1].reg_addr = POWERCTRL2;
- if (port == 0) {
- sc_access[1].value = 0x0C;
- sc_access[1].mask = 0x0C;
- } else if (port == 1) {
- sc_access[1].value = 0x02;
- sc_access[1].mask = 0x02;
- }
-
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-
-}
-
-static int nc_power_down(void)
-{
- int retval = 0;
- struct sc_reg_access sc_access[5];
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
- nc_enable_audiodac(MUTE);
-
-
- pr_debug("powering dn nc_power_down ....\n");
-
- if (snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE ||
- snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)
- nc_set_amp_power(0);
-
- msleep(30);
-
- sc_access[0].reg_addr = DRVPOWERCTRL;
- sc_access[0].value = 0x00;
- sc_access[0].mask = 0x00;
-
- sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
-
- sc_access[0].reg_addr = POWERCTRL1;
- sc_access[0].value = 0x00;
- sc_access[0].mask = 0x00;
-
- sc_access[1].reg_addr = POWERCTRL2;
- sc_access[1].value = 0x00;
- sc_access[1].mask = 0x00;
-
-
-
- sst_sc_reg_access(sc_access, PMIC_WRITE, 2);
-
- msleep(30);
- sc_access[0].reg_addr = VREFPLL;
- sc_access[0].value = 0x10;
- sc_access[0].mask = 0x10;
-
- sc_access[1].reg_addr = VAUDIOCNT;
- sc_access[1].value = 0x25;
- sc_access[1].mask = 0x25;
-
-
- retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 2);
-
- msleep(30);
- return nc_enable_audiodac(UNMUTE);
-}
-
-static int nc_power_down_pb(unsigned int device)
-{
-
- int retval = 0;
- struct sc_reg_access sc_access[5];
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- pr_debug("powering dn pb....\n");
- mutex_lock(&snd_pmic_ops_nc.lock);
- nc_enable_audiodac(MUTE);
-
-
- msleep(30);
-
-
- sc_access[0].reg_addr = DRVPOWERCTRL;
- sc_access[0].value = 0x00;
- sc_access[0].mask = 0x00;
-
- sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
-
- msleep(30);
-
- sc_access[0].reg_addr = POWERCTRL1;
- sc_access[0].value = 0x00;
- sc_access[0].mask = 0x41;
-
- sc_access[1].reg_addr = POWERCTRL2;
- sc_access[1].value = 0x00;
- sc_access[1].mask = 0x0C;
-
- sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
-
- msleep(30);
-
- snd_pmic_ops_nc.pb_on = 0;
-
- nc_enable_audiodac(UNMUTE);
- mutex_unlock(&snd_pmic_ops_nc.lock);
- return 0;
-}
-
-static int nc_power_down_cp(unsigned int device)
-{
- struct sc_reg_access sc_access[] = {
- {POWERCTRL1, 0x00, 0xBE},
- {POWERCTRL2, 0x00, 0x02},
- };
- int retval = 0;
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- pr_debug("powering dn cp....\n");
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
-}
-
-static int nc_set_pcm_voice_params(void)
-{
- struct sc_reg_access sc_access[] = {
- {0x100, 0xD5, 0},
- {0x101, 0x08, 0},
- {0x104, 0x03, 0},
- {0x107, 0x10, 0},
- {0x10B, 0x0E, 0},
- {0x10E, 0x03, 0},
- {0x10F, 0x03, 0},
- {0x114, 0x13, 0},
- {0x115, 0x00, 0},
- {0x128, 0xFE, 0},
- {0x129, 0xFE, 0},
- {0x12A, 0xFE, 0},
- {0x12B, 0xDE, 0},
- {0x12C, 0xDE, 0},
- };
- int retval = 0;
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- sst_sc_reg_access(sc_access, PMIC_WRITE, 14);
- pr_debug("Voice parameters set successfully!!\n");
- return 0;
-}
-
-
-static int nc_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
-{
- int config2 = 0;
- struct sc_reg_access sc_access;
- int retval = 0;
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- switch (sfreq) {
- case 8000:
- config2 = 0x00;
- break;
- case 11025:
- config2 = 0x01;
- break;
- case 12000:
- config2 = 0x02;
- break;
- case 16000:
- config2 = 0x03;
- break;
- case 22050:
- config2 = 0x04;
- break;
- case 24000:
- config2 = 0x05;
- break;
- case 32000:
- config2 = 0x07;
- break;
- case 44100:
- config2 = 0x08;
- break;
- case 48000:
- config2 = 0x09;
- break;
- }
-
- snd_pmic_ops_nc.num_channel = num_channel;
- if (snd_pmic_ops_nc.num_channel == 1) {
-
- sc_access.value = 0x07;
- sc_access.reg_addr = RMUTE;
- pr_debug("RIGHT_HP_MUTE value%d\n", sc_access.value);
- sc_access.mask = MASK2;
- sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
- } else {
- sc_access.value = 0x00;
- sc_access.reg_addr = RMUTE;
- pr_debug("RIGHT_HP_MUTE value %d\n", sc_access.value);
- sc_access.mask = MASK2;
- sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
-
-
- }
-
- pr_debug("word_size = %d\n", word_size);
-
- if (word_size == 24) {
- sc_access.reg_addr = AUDIOPORT2;
- sc_access.value = config2 | 0x10;
- sc_access.mask = 0x1F;
- } else {
- sc_access.value = config2;
- sc_access.mask = 0x1F;
- sc_access.reg_addr = AUDIOPORT2;
- }
- sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
-
- pr_debug("word_size = %d\n", word_size);
- sc_access.reg_addr = AUDIOPORT1;
- sc_access.mask = MASK5|MASK4|MASK1|MASK0;
- if (word_size == 16)
- sc_access.value = 0x98;
- else if (word_size == 24)
- sc_access.value = 0xAB;
-
- return sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
-
-
-
-}
-
-static int nc_set_selected_output_dev(u8 value)
-{
- struct sc_reg_access sc_access_HP[] = {
- {LMUTE, 0x02, 0x06},
- {RMUTE, 0x02, 0x06},
- {DRVPOWERCTRL, 0x06, 0x06},
- };
- struct sc_reg_access sc_access_IS[] = {
- {LMUTE, 0x04, 0x06},
- {RMUTE, 0x04, 0x06},
- {DRVPOWERCTRL, 0x00, 0x06},
- };
- int retval = 0;
-
- snd_pmic_ops_nc.output_dev_id = value;
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
- pr_debug("nc set selected output:%d\n", value);
- mutex_lock(&snd_pmic_ops_nc.lock);
- switch (value) {
- case STEREO_HEADPHONE:
- if (snd_pmic_ops_nc.pb_on)
- sst_sc_reg_access(sc_access_HP+2, PMIC_WRITE, 1);
- retval = sst_sc_reg_access(sc_access_HP, PMIC_WRITE, 2);
- nc_set_amp_power(0);
- break;
- case MONO_EARPIECE:
- case INTERNAL_SPKR:
- retval = sst_sc_reg_access(sc_access_IS, PMIC_WRITE, 3);
- if (snd_pmic_ops_nc.pb_on)
- nc_set_amp_power(1);
- break;
- default:
- pr_err("rcvd illegal request: %d\n", value);
- mutex_unlock(&snd_pmic_ops_nc.lock);
- return -EINVAL;
- }
- mutex_unlock(&snd_pmic_ops_nc.lock);
- return retval;
-}
-
-static int nc_audio_init(void)
-{
- struct sc_reg_access sc_acces, sc_access[] = {
- {0x100, 0x00, 0},
- {0x101, 0x00, 0},
- {0x104, 0x8B, 0},
- {0x107, 0x11, 0},
- {0x10B, 0x0E, 0},
- {0x114, 0x00, 0},
- {0x115, 0x00, 0},
- {0x128, 0x00, 0},
- {0x129, 0x00, 0},
- {0x12A, 0x00, 0},
- {0x12B, 0xee, 0},
- {0x12C, 0xf6, 0},
- };
-
- sst_sc_reg_access(sc_access, PMIC_WRITE, 12);
- pr_debug("Audio Init successfully!!\n");
-
- /*set output device */
- nc_set_selected_output_dev(snd_pmic_ops_nc.output_dev_id);
-
- if (snd_pmic_ops_nc.num_channel == 1) {
- sc_acces.value = 0x07;
- sc_acces.reg_addr = RMUTE;
- pr_debug("RIGHT_HP_MUTE value%d\n", sc_acces.value);
- sc_acces.mask = MASK2;
- sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
- } else {
- sc_acces.value = 0x00;
- sc_acces.reg_addr = RMUTE;
- pr_debug("RIGHT_HP_MUTE value%d\n", sc_acces.value);
- sc_acces.mask = MASK2;
- sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
- }
-
- return 0;
-}
-
-static int nc_set_audio_port(int status)
-{
- struct sc_reg_access sc_access[2] = {{0,},};
- int retval = 0;
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- if (status == DEACTIVATE) {
- /* Deactivate audio port-tristate and power */
- sc_access[0].value = 0x00;
- sc_access[0].mask = MASK4|MASK5;
- sc_access[0].reg_addr = AUDIOPORT1;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- } else if (status == ACTIVATE) {
- /* activate audio port */
- nc_audio_init();
- sc_access[0].value = 0x10;
- sc_access[0].mask = MASK4|MASK5 ;
- sc_access[0].reg_addr = AUDIOPORT1;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- } else
- return -EINVAL;
-
-}
-
-static int nc_set_voice_port(int status)
-{
- struct sc_reg_access sc_access[2] = {{0,},};
- int retval = 0;
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- if (status == DEACTIVATE) {
- /* Activate Voice port */
- sc_access[0].value = 0x00;
- sc_access[0].mask = MASK4;
- sc_access[0].reg_addr = VOICEPORT1;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- } else if (status == ACTIVATE) {
- /* Deactivate voice port */
- nc_set_pcm_voice_params();
- sc_access[0].value = 0x10;
- sc_access[0].mask = MASK4;
- sc_access[0].reg_addr = VOICEPORT1;
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- } else
- return -EINVAL;
-}
-
-static int nc_set_mute(int dev_id, u8 value)
-{
- struct sc_reg_access sc_access[3];
- u8 mute_val, cap_mute;
- int retval = 0;
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- pr_debug("set device id::%d, value %d\n", dev_id, value);
-
- switch (dev_id) {
- case PMIC_SND_MUTE_ALL:
- pr_debug("PMIC_SND_MUTE_ALL value %d\n", value);
- snd_pmic_ops_nc.mute_status = value;
- snd_pmic_ops_nc.master_mute = value;
- if (value == UNMUTE) {
- /* unmute the system, set the 7th bit to zero */
- mute_val = cap_mute = 0x00;
- } else {
- /* MUTE:Set the seventh bit */
- mute_val = 0x80;
- cap_mute = 0x40;
- }
- sc_access[0].reg_addr = AUDIOLVOL;
- sc_access[1].reg_addr = AUDIORVOL;
- sc_access[0].mask = sc_access[1].mask = MASK7;
- sc_access[0].value = sc_access[1].value = mute_val;
- if (snd_pmic_ops_nc.num_channel == 1)
- sc_access[1].value = 0x80;
- if (!sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2)) {
- sc_access[0].reg_addr = 0x109;
- sc_access[1].reg_addr = 0x10a;
- sc_access[2].reg_addr = 0x105;
- sc_access[0].mask = sc_access[1].mask =
- sc_access[2].mask = MASK6;
- sc_access[0].value = sc_access[1].value =
- sc_access[2].value = cap_mute;
-
- if ((snd_pmic_ops_nc.input_dev_id == AMIC) ||
- (snd_pmic_ops_nc.input_dev_id == DMIC))
- sc_access[1].value = 0x40;
- if (snd_pmic_ops_nc.input_dev_id == HS_MIC)
- sc_access[0].value = 0x40;
- retval = sst_sc_reg_access(sc_access,
- PMIC_READ_MODIFY, 3);
- }
- break;
- case PMIC_SND_HP_MIC_MUTE:
- pr_debug("PMIC_SND_HPMIC_MUTE value %d\n", value);
- if (value == UNMUTE) {
- /* unmute the system, set the 6th bit to one */
- sc_access[0].value = 0x00;
- } else {
- /* mute the system, reset the 6th bit to zero */
- sc_access[0].value = 0x40;
- }
- sc_access[0].reg_addr = LIRSEL;
- sc_access[0].mask = MASK6;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- break;
- case PMIC_SND_AMIC_MUTE:
- pr_debug("PMIC_SND_AMIC_MUTE value %d\n", value);
- if (value == UNMUTE) {
- /* unmute the system, set the 6th bit to one */
- sc_access[0].value = 0x00;
- } else {
- /* mute the system, reset the 6th bit to zero */
- sc_access[0].value = 0x40;
- }
- sc_access[0].reg_addr = LILSEL;
- sc_access[0].mask = MASK6;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- break;
-
- case PMIC_SND_DMIC_MUTE:
- pr_debug("INPUT_MUTE_DMIC value%d\n", value);
- if (value == UNMUTE) {
- /* unmute the system, set the 6th bit to one */
- sc_access[1].value = 0x00;
- sc_access[0].value = 0x00;
- } else {
- /* mute the system, reset the 6th bit to zero */
- sc_access[1].value = 0x40;
- sc_access[0].value = 0x40;
- }
- sc_access[0].reg_addr = DMICCTRL1;
- sc_access[0].mask = MASK6;
- sc_access[1].reg_addr = LILSEL;
- sc_access[1].mask = MASK6;
- retval = sst_sc_reg_access(sc_access,
- PMIC_READ_MODIFY, 2);
- break;
-
- case PMIC_SND_LEFT_HP_MUTE:
- case PMIC_SND_RIGHT_HP_MUTE:
- snd_pmic_ops_nc.mute_status = value;
- if (value == UNMUTE)
- sc_access[0].value = 0x0;
- else
- sc_access[0].value = 0x04;
-
- if (dev_id == PMIC_SND_LEFT_HP_MUTE) {
- sc_access[0].reg_addr = LMUTE;
- pr_debug("LEFT_HP_MUTE value %d\n",
- sc_access[0].value);
- } else {
- if (snd_pmic_ops_nc.num_channel == 1)
- sc_access[0].value = 0x04;
- sc_access[0].reg_addr = RMUTE;
- pr_debug("RIGHT_HP_MUTE value %d\n",
- sc_access[0].value);
- }
- sc_access[0].mask = MASK2;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- break;
- case PMIC_SND_LEFT_SPEAKER_MUTE:
- case PMIC_SND_RIGHT_SPEAKER_MUTE:
- if (value == UNMUTE)
- sc_access[0].value = 0x00;
- else
- sc_access[0].value = 0x03;
- sc_access[0].reg_addr = LMUTE;
- pr_debug("SPEAKER_MUTE %d\n", sc_access[0].value);
- sc_access[0].mask = MASK1;
- retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
- break;
- default:
- return -EINVAL;
- }
- return retval ;
-
-}
-
-static int nc_set_vol(int dev_id, int value)
-{
- struct sc_reg_access sc_access[3];
- int retval = 0, entries = 0;
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- pr_debug("set volume:%d\n", dev_id);
- switch (dev_id) {
- case PMIC_SND_CAPTURE_VOL:
- pr_debug("PMIC_SND_CAPTURE_VOL:value::%d\n", value);
- sc_access[0].value = sc_access[1].value =
- sc_access[2].value = -value;
- sc_access[0].mask = sc_access[1].mask = sc_access[2].mask =
- (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
- sc_access[0].reg_addr = 0x10a;
- sc_access[1].reg_addr = 0x109;
- sc_access[2].reg_addr = 0x105;
- entries = 3;
- break;
-
- case PMIC_SND_LEFT_PB_VOL:
- pr_debug("PMIC_SND_LEFT_HP_VOL %d\n", value);
- sc_access[0].value = -value;
- sc_access[0].reg_addr = HPLVOL;
- sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
- entries = 1;
- break;
-
- case PMIC_SND_RIGHT_PB_VOL:
- pr_debug("PMIC_SND_RIGHT_HP_VOL value %d\n", value);
- if (snd_pmic_ops_nc.num_channel == 1) {
- sc_access[0].value = 0x04;
- sc_access[0].reg_addr = RMUTE;
- sc_access[0].mask = MASK2;
- } else {
- sc_access[0].value = -value;
- sc_access[0].reg_addr = HPRVOL;
- sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
- }
- entries = 1;
- break;
-
- case PMIC_SND_LEFT_MASTER_VOL:
- pr_debug("PMIC_SND_LEFT_MASTER_VOL value %d\n", value);
- sc_access[0].value = -value;
- sc_access[0].reg_addr = AUDIOLVOL;
- sc_access[0].mask =
- (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
- entries = 1;
- break;
-
- case PMIC_SND_RIGHT_MASTER_VOL:
- pr_debug("PMIC_SND_RIGHT_MASTER_VOL value %d\n", value);
- sc_access[0].value = -value;
- sc_access[0].reg_addr = AUDIORVOL;
- sc_access[0].mask =
- (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
- entries = 1;
- break;
-
- default:
- return -EINVAL;
-
- }
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, entries);
-}
-
-static int nc_set_selected_input_dev(u8 value)
-{
- struct sc_reg_access sc_access[6];
- u8 num_val;
- int retval = 0;
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
- snd_pmic_ops_nc.input_dev_id = value;
-
- pr_debug("nc set selected input:%d\n", value);
-
- switch (value) {
- case AMIC:
- pr_debug("Selecting AMIC\n");
- sc_access[0].reg_addr = 0x107;
- sc_access[0].value = 0x40;
- sc_access[0].mask = MASK6|MASK3|MASK1|MASK0;
- sc_access[1].reg_addr = 0x10a;
- sc_access[1].value = 0x40;
- sc_access[1].mask = MASK6;
- sc_access[2].reg_addr = 0x109;
- sc_access[2].value = 0x00;
- sc_access[2].mask = MASK6;
- sc_access[3].reg_addr = 0x105;
- sc_access[3].value = 0x40;
- sc_access[3].mask = MASK6;
- num_val = 4;
- break;
-
- case HS_MIC:
- pr_debug("Selecting HS_MIC\n");
- sc_access[0].reg_addr = MICCTRL;
- sc_access[0].mask = MASK6|MASK3|MASK1|MASK0;
- sc_access[0].value = 0x00;
- sc_access[1].reg_addr = 0x109;
- sc_access[1].mask = MASK6;
- sc_access[1].value = 0x40;
- sc_access[2].reg_addr = 0x10a;
- sc_access[2].mask = MASK6;
- sc_access[2].value = 0x00;
- sc_access[3].reg_addr = 0x105;
- sc_access[3].value = 0x40;
- sc_access[3].mask = MASK6;
- sc_access[4].reg_addr = ADCSAMPLERATE;
- sc_access[4].mask = MASK7|MASK6|MASK5|MASK4|MASK3;
- sc_access[4].value = 0xc8;
- num_val = 5;
- break;
-
- case DMIC:
- pr_debug("DMIC\n");
- sc_access[0].reg_addr = MICCTRL;
- sc_access[0].mask = MASK6|MASK3|MASK1|MASK0;
- sc_access[0].value = 0x0B;
- sc_access[1].reg_addr = 0x105;
- sc_access[1].value = 0x80;
- sc_access[1].mask = MASK7|MASK6;
- sc_access[2].reg_addr = 0x10a;
- sc_access[2].value = 0x40;
- sc_access[2].mask = MASK6;
- sc_access[3].reg_addr = LILSEL;
- sc_access[3].mask = MASK6;
- sc_access[3].value = 0x00;
- sc_access[4].reg_addr = ADCSAMPLERATE;
- sc_access[4].mask = MASK7|MASK6|MASK5|MASK4|MASK3;
- sc_access[4].value = 0x33;
- num_val = 5;
- break;
- default:
- return -EINVAL;
- }
- return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_val);
-}
-
-static int nc_get_mute(int dev_id, u8 *value)
-{
- int retval = 0, mask = 0;
- struct sc_reg_access sc_access = {0,};
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- pr_debug("get mute::%d\n", dev_id);
-
- switch (dev_id) {
- case PMIC_SND_AMIC_MUTE:
- pr_debug("PMIC_SND_INPUT_MUTE_MIC1\n");
- sc_access.reg_addr = LILSEL;
- mask = MASK6;
- break;
- case PMIC_SND_HP_MIC_MUTE:
- pr_debug("PMIC_SND_INPUT_MUTE_MIC2\n");
- sc_access.reg_addr = LIRSEL;
- mask = MASK6;
- break;
- case PMIC_SND_LEFT_HP_MUTE:
- case PMIC_SND_RIGHT_HP_MUTE:
- mask = MASK2;
- pr_debug("PMIC_SN_LEFT/RIGHT_HP_MUTE\n");
- if (dev_id == PMIC_SND_RIGHT_HP_MUTE)
- sc_access.reg_addr = RMUTE;
- else
- sc_access.reg_addr = LMUTE;
- break;
-
- case PMIC_SND_LEFT_SPEAKER_MUTE:
- pr_debug("PMIC_MONO_EARPIECE_MUTE\n");
- sc_access.reg_addr = RMUTE;
- mask = MASK1;
- break;
- case PMIC_SND_DMIC_MUTE:
- pr_debug("PMIC_SND_INPUT_MUTE_DMIC\n");
- sc_access.reg_addr = 0x105;
- mask = MASK6;
- break;
- default:
- return -EINVAL;
-
- }
- retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
- pr_debug("reg value = %d\n", sc_access.value);
- if (retval)
- return retval;
- *value = (sc_access.value) & mask;
- pr_debug("masked value = %d\n", *value);
- if (*value)
- *value = 0;
- else
- *value = 1;
- pr_debug("value returned = 0x%x\n", *value);
- return retval;
-}
-
-static int nc_get_vol(int dev_id, int *value)
-{
- int retval = 0, mask = 0;
- struct sc_reg_access sc_access = {0,};
-
- if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
- retval = nc_init_card();
- if (retval)
- return retval;
-
- switch (dev_id) {
- case PMIC_SND_CAPTURE_VOL:
- pr_debug("PMIC_SND_INPUT_CAPTURE_VOL\n");
- sc_access.reg_addr = LILSEL;
- mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
- break;
-
- case PMIC_SND_LEFT_MASTER_VOL:
- pr_debug("GET_VOLUME_PMIC_LEFT_MASTER_VOL\n");
- sc_access.reg_addr = AUDIOLVOL;
- mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
- break;
-
- case PMIC_SND_RIGHT_MASTER_VOL:
- pr_debug("GET_VOLUME_PMIC_RIGHT_MASTER_VOL\n");
- sc_access.reg_addr = AUDIORVOL;
- mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
- break;
-
- case PMIC_SND_RIGHT_PB_VOL:
- pr_debug("GET_VOLUME_PMIC_RIGHT_HP_VOL\n");
- sc_access.reg_addr = HPRVOL;
- mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
- break;
-
- case PMIC_SND_LEFT_PB_VOL:
- pr_debug("GET_VOLUME_PMIC_LEFT_HP_VOL\n");
- sc_access.reg_addr = HPLVOL;
- mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
- break;
-
- default:
- return -EINVAL;
-
- }
- retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
- pr_debug("value read = 0x%x\n", sc_access.value);
- *value = -((sc_access.value) & mask);
- pr_debug("get vol value returned = %d\n", *value);
- return retval;
-}
-
-static void hp_automute(enum snd_jack_types type, int present)
-{
- u8 in = DMIC;
- u8 out = INTERNAL_SPKR;
- if (present) {
- if (type == SND_JACK_HEADSET)
- in = HS_MIC;
- out = STEREO_HEADPHONE;
- }
- nc_set_selected_input_dev(in);
- nc_set_selected_output_dev(out);
-}
-
-static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
-{
- u8 value = 0;
- struct mad_jack *mjack = NULL;
- unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
- struct snd_intelmad *intelmaddata = cb_data;
- struct sc_reg_access sc_access_read = {0,};
-
- sc_access_read.reg_addr = 0x132;
- sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
- value = (sc_access_read.value);
- pr_debug("value returned = 0x%x\n", value);
-
- mjack = &intelmaddata->jack[0];
- if (intsts & 0x1) {
- pr_debug("SST DBG:MAD headset detected\n");
- /* send headset detect/undetect */
- present = (value == 0x1) ? 3 : 0;
- jack_event_flag = 1;
- mjack->jack.type = SND_JACK_HEADSET;
- hp_automute(SND_JACK_HEADSET, present);
- }
-
- if (intsts & 0x2) {
- pr_debug(":MAD headphone detected\n");
- /* send headphone detect/undetect */
- present = (value == 0x2) ? 1 : 0;
- jack_event_flag = 1;
- mjack->jack.type = SND_JACK_HEADPHONE;
- hp_automute(SND_JACK_HEADPHONE, present);
- }
-
- if (intsts & 0x4) {
- pr_debug("MAD short push detected\n");
- /* send short push */
- present = 1;
- jack_event_flag = 1;
- buttonpressflag = 1;
- mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
- }
-
- if (intsts & 0x8) {
- pr_debug(":MAD long push detected\n");
- /* send long push */
- present = 1;
- jack_event_flag = 1;
- buttonpressflag = 1;
- mjack->jack.type = MID_JACK_HS_LONG_PRESS;
- }
-
- if (jack_event_flag)
- sst_mad_send_jack_report(&mjack->jack,
- buttonpressflag, present);
-}
-static int nc_jack_enable(void)
-{
- return 0;
-}
-
-struct snd_pmic_ops snd_pmic_ops_nc = {
- .input_dev_id = DMIC,
- .output_dev_id = INTERNAL_SPKR,
- .set_input_dev = nc_set_selected_input_dev,
- .set_output_dev = nc_set_selected_output_dev,
- .set_mute = nc_set_mute,
- .get_mute = nc_get_mute,
- .set_vol = nc_set_vol,
- .get_vol = nc_get_vol,
- .init_card = nc_init_card,
- .set_pcm_audio_params = nc_set_pcm_audio_params,
- .set_pcm_voice_params = nc_set_pcm_voice_params,
- .set_voice_port = nc_set_voice_port,
- .set_audio_port = nc_set_audio_port,
- .power_up_pmic_pb = nc_power_up_pb,
- .power_up_pmic_cp = nc_power_up_cp,
- .power_down_pmic_pb = nc_power_down_pb,
- .power_down_pmic_cp = nc_power_down_cp,
- .power_down_pmic = nc_power_down,
- .pmic_irq_cb = nc_pmic_irq_cb,
- .pmic_jack_enable = nc_jack_enable,
-};
diff --git a/drivers/staging/line6/Makefile b/drivers/staging/line6/Makefile
index de6bd12e9736..34a2ddacc7e9 100644
--- a/drivers/staging/line6/Makefile
+++ b/drivers/staging/line6/Makefile
@@ -12,4 +12,5 @@ line6usb-y := \
playback.o \
pod.o \
toneport.o \
- variax.o
+ variax.o \
+ podhd.o
diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c
index 9647154a4923..127f95247749 100644
--- a/drivers/staging/line6/capture.c
+++ b/drivers/staging/line6/capture.c
@@ -9,6 +9,7 @@
*
*/
+#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -192,6 +193,31 @@ void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)
}
}
+int line6_alloc_capture_buffer(struct snd_line6_pcm *line6pcm)
+{
+ /* We may be invoked multiple times in a row so allocate once only */
+ if (line6pcm->buffer_in)
+ return 0;
+
+ line6pcm->buffer_in =
+ kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
+ line6pcm->max_packet_size, GFP_KERNEL);
+
+ if (!line6pcm->buffer_in) {
+ dev_err(line6pcm->line6->ifcdev,
+ "cannot malloc capture buffer\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm)
+{
+ kfree(line6pcm->buffer_in);
+ line6pcm->buffer_in = NULL;
+}
+
/*
* Callback for completed capture URB.
*/
@@ -243,11 +269,7 @@ static void audio_in_callback(struct urb *urb)
length += fsize;
/* the following assumes LINE6_ISO_PACKETS == 1: */
-#if LINE6_BACKUP_MONITOR_SIGNAL
- memcpy(line6pcm->prev_fbuf, fbuf, fsize);
-#else
line6pcm->prev_fbuf = fbuf;
-#endif
line6pcm->prev_fsize = fsize;
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
@@ -319,6 +341,13 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
}
/* -- [FD] end */
+ if ((line6pcm->flags & MASK_CAPTURE) == 0) {
+ ret = line6_alloc_capture_buffer(line6pcm);
+
+ if (ret < 0)
+ return ret;
+ }
+
ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
if (ret < 0)
@@ -331,6 +360,13 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
/* hw_free capture callback */
static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream)
{
+ struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+
+ if ((line6pcm->flags & MASK_CAPTURE) == 0) {
+ line6_unlink_wait_clear_audio_in_urbs(line6pcm);
+ line6_free_capture_buffer(line6pcm);
+ }
+
return snd_pcm_lib_free_pages(substream);
}
diff --git a/drivers/staging/line6/capture.h b/drivers/staging/line6/capture.h
index a7509fbbb954..366cbaa7c88d 100644
--- a/drivers/staging/line6/capture.h
+++ b/drivers/staging/line6/capture.h
@@ -19,11 +19,13 @@
extern struct snd_pcm_ops snd_line6_capture_ops;
+extern int line6_alloc_capture_buffer(struct snd_line6_pcm *line6pcm);
extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf,
int fsize);
extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm,
int length);
extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm);
+extern void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm);
extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm);
extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm);
extern void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm
diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
index 851b762319cf..6a1959e16e00 100644
--- a/drivers/staging/line6/driver.c
+++ b/drivers/staging/line6/driver.c
@@ -21,6 +21,7 @@
#include "midi.h"
#include "playback.h"
#include "pod.h"
+#include "podhd.h"
#include "revision.h"
#include "toneport.h"
#include "usbdefs.h"
@@ -37,6 +38,8 @@ static const struct usb_device_id line6_id_table[] = {
{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO)},
{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_GUITARPORT)},
{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_POCKETPOD)},
+ {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD300)},
+ {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD500)},
{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_GX)},
{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX1)},
{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX2)},
@@ -56,23 +59,25 @@ MODULE_DEVICE_TABLE(usb, line6_id_table);
/* *INDENT-OFF* */
static struct line6_properties line6_properties_table[] = {
- { "BassPODxt", "BassPODxt", LINE6_BIT_BASSPODXT, LINE6_BIT_CONTROL_PCM_HWMON },
- { "BassPODxtLive", "BassPODxt Live", LINE6_BIT_BASSPODXTLIVE, LINE6_BIT_CONTROL_PCM_HWMON },
- { "BassPODxtPro", "BassPODxt Pro", LINE6_BIT_BASSPODXTPRO, LINE6_BIT_CONTROL_PCM_HWMON },
- { "GuitarPort", "GuitarPort", LINE6_BIT_GUITARPORT, LINE6_BIT_PCM },
- { "PocketPOD", "Pocket POD", LINE6_BIT_POCKETPOD, LINE6_BIT_CONTROL },
- { "PODStudioGX", "POD Studio GX", LINE6_BIT_PODSTUDIO_GX, LINE6_BIT_PCM },
- { "PODStudioUX1", "POD Studio UX1", LINE6_BIT_PODSTUDIO_UX1, LINE6_BIT_PCM },
- { "PODStudioUX2", "POD Studio UX2", LINE6_BIT_PODSTUDIO_UX2, LINE6_BIT_PCM },
- { "PODX3", "POD X3", LINE6_BIT_PODX3, LINE6_BIT_PCM },
- { "PODX3Live", "POD X3 Live", LINE6_BIT_PODX3LIVE, LINE6_BIT_PCM },
- { "PODxt", "PODxt", LINE6_BIT_PODXT, LINE6_BIT_CONTROL_PCM_HWMON },
- { "PODxtLive", "PODxt Live", LINE6_BIT_PODXTLIVE, LINE6_BIT_CONTROL_PCM_HWMON },
- { "PODxtPro", "PODxt Pro", LINE6_BIT_PODXTPRO, LINE6_BIT_CONTROL_PCM_HWMON },
- { "TonePortGX", "TonePort GX", LINE6_BIT_TONEPORT_GX, LINE6_BIT_PCM },
- { "TonePortUX1", "TonePort UX1", LINE6_BIT_TONEPORT_UX1, LINE6_BIT_PCM },
- { "TonePortUX2", "TonePort UX2", LINE6_BIT_TONEPORT_UX2, LINE6_BIT_PCM },
- { "Variax", "Variax Workbench", LINE6_BIT_VARIAX, LINE6_BIT_CONTROL }
+ { LINE6_BIT_BASSPODXT, "BassPODxt", "BassPODxt", LINE6_BIT_CONTROL_PCM_HWMON },
+ { LINE6_BIT_BASSPODXTLIVE, "BassPODxtLive", "BassPODxt Live", LINE6_BIT_CONTROL_PCM_HWMON },
+ { LINE6_BIT_BASSPODXTPRO, "BassPODxtPro", "BassPODxt Pro", LINE6_BIT_CONTROL_PCM_HWMON },
+ { LINE6_BIT_GUITARPORT, "GuitarPort", "GuitarPort", LINE6_BIT_PCM },
+ { LINE6_BIT_POCKETPOD, "PocketPOD", "Pocket POD", LINE6_BIT_CONTROL },
+ { LINE6_BIT_PODHD300, "PODHD300", "POD HD300", LINE6_BIT_CONTROL_PCM_HWMON },
+ { LINE6_BIT_PODHD500, "PODHD500", "POD HD500", LINE6_BIT_CONTROL_PCM_HWMON },
+ { LINE6_BIT_PODSTUDIO_GX, "PODStudioGX", "POD Studio GX", LINE6_BIT_PCM },
+ { LINE6_BIT_PODSTUDIO_UX1, "PODStudioUX1", "POD Studio UX1", LINE6_BIT_PCM },
+ { LINE6_BIT_PODSTUDIO_UX2, "PODStudioUX2", "POD Studio UX2", LINE6_BIT_PCM },
+ { LINE6_BIT_PODX3, "PODX3", "POD X3", LINE6_BIT_PCM },
+ { LINE6_BIT_PODX3LIVE, "PODX3Live", "POD X3 Live", LINE6_BIT_PCM },
+ { LINE6_BIT_PODXT, "PODxt", "PODxt", LINE6_BIT_CONTROL_PCM_HWMON },
+ { LINE6_BIT_PODXTLIVE, "PODxtLive", "PODxt Live", LINE6_BIT_CONTROL_PCM_HWMON },
+ { LINE6_BIT_PODXTPRO, "PODxtPro", "PODxt Pro", LINE6_BIT_CONTROL_PCM_HWMON },
+ { LINE6_BIT_TONEPORT_GX, "TonePortGX", "TonePort GX", LINE6_BIT_PCM },
+ { LINE6_BIT_TONEPORT_UX1, "TonePortUX1", "TonePort UX1", LINE6_BIT_PCM },
+ { LINE6_BIT_TONEPORT_UX2, "TonePortUX2", "TonePort UX2", LINE6_BIT_PCM },
+ { LINE6_BIT_VARIAX, "Variax", "Variax Workbench", LINE6_BIT_CONTROL },
};
/* *INDENT-ON* */
@@ -437,6 +442,10 @@ static void line6_data_received(struct urb *urb)
line6);
break;
+ case LINE6_DEVID_PODHD300:
+ case LINE6_DEVID_PODHD500:
+ break; /* let userspace handle MIDI */
+
case LINE6_DEVID_PODXTLIVE:
switch (line6->interface_number) {
case PODXTLIVE_INTERFACE_POD:
@@ -720,8 +729,8 @@ static int line6_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
int devtype;
- struct usb_device *usbdev = NULL;
- struct usb_line6 *line6 = NULL;
+ struct usb_device *usbdev;
+ struct usb_line6 *line6;
const struct line6_properties *properties;
int devnum;
int interface_number, alternate = 0;
@@ -794,6 +803,7 @@ static int line6_probe(struct usb_interface *interface,
}
break;
+ case LINE6_DEVID_PODHD500:
case LINE6_DEVID_PODX3:
case LINE6_DEVID_PODX3LIVE:
switch (interface_number) {
@@ -812,6 +822,7 @@ static int line6_probe(struct usb_interface *interface,
case LINE6_DEVID_BASSPODXTPRO:
case LINE6_DEVID_PODXT:
case LINE6_DEVID_PODXTPRO:
+ case LINE6_DEVID_PODHD300:
alternate = 5;
break;
@@ -865,6 +876,18 @@ static int line6_probe(struct usb_interface *interface,
ep_write = 0x03;
break;
+ case LINE6_DEVID_PODHD300:
+ size = sizeof(struct usb_line6_podhd);
+ ep_read = 0x84;
+ ep_write = 0x03;
+ break;
+
+ case LINE6_DEVID_PODHD500:
+ size = sizeof(struct usb_line6_podhd);
+ ep_read = 0x81;
+ ep_write = 0x01;
+ break;
+
case LINE6_DEVID_POCKETPOD:
size = sizeof(struct usb_line6_pod);
ep_read = 0x82;
@@ -923,7 +946,7 @@ static int line6_probe(struct usb_interface *interface,
}
if (size == 0) {
- dev_err(line6->ifcdev,
+ dev_err(&interface->dev,
"driver bug: interface data size not set\n");
ret = -ENODEV;
goto err_put;
@@ -1017,6 +1040,12 @@ static int line6_probe(struct usb_interface *interface,
ret = line6_pod_init(interface, (struct usb_line6_pod *)line6);
break;
+ case LINE6_DEVID_PODHD300:
+ case LINE6_DEVID_PODHD500:
+ ret = line6_podhd_init(interface,
+ (struct usb_line6_podhd *)line6);
+ break;
+
case LINE6_DEVID_PODXTLIVE:
switch (interface_number) {
case PODXTLIVE_INTERFACE_POD:
@@ -1139,6 +1168,11 @@ static void line6_disconnect(struct usb_interface *interface)
line6_pod_disconnect(interface);
break;
+ case LINE6_DEVID_PODHD300:
+ case LINE6_DEVID_PODHD500:
+ line6_podhd_disconnect(interface);
+ break;
+
case LINE6_DEVID_PODXTLIVE:
switch (interface_number) {
case PODXTLIVE_INTERFACE_POD:
diff --git a/drivers/staging/line6/driver.h b/drivers/staging/line6/driver.h
index 553192f49317..117bf9943568 100644
--- a/drivers/staging/line6/driver.h
+++ b/drivers/staging/line6/driver.h
@@ -88,6 +88,11 @@ static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4;
*/
struct line6_properties {
/**
+ Bit identifying this device in the line6usb driver.
+ */
+ int device_bit;
+
+ /**
Card id string (maximum 16 characters).
This can be used to address the device in ALSA programs as
"default:CARD=<id>"
@@ -100,11 +105,6 @@ struct line6_properties {
const char *name;
/**
- Bit identifying this device in the line6usb driver.
- */
- int device_bit;
-
- /**
Bit vector defining this device's capabilities in the
line6usb driver.
*/
diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c
index e554a2da643a..13d02939c3cb 100644
--- a/drivers/staging/line6/midi.c
+++ b/drivers/staging/line6/midi.c
@@ -135,7 +135,7 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
line6_write_hexdump(line6, 'S', data, length);
#endif
- transfer_buffer = kmalloc(length, GFP_ATOMIC);
+ transfer_buffer = kmemdup(data, length, GFP_ATOMIC);
if (transfer_buffer == NULL) {
usb_free_urb(urb);
@@ -143,7 +143,6 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
return -ENOMEM;
}
- memcpy(transfer_buffer, data, length);
usb_fill_int_urb(urb, line6->usbdev,
usb_sndbulkpipe(line6->usbdev,
line6->ep_control_write),
@@ -173,6 +172,8 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
break;
case LINE6_DEVID_VARIAX:
+ case LINE6_DEVID_PODHD300:
+ case LINE6_DEVID_PODHD500:
break;
default:
@@ -307,10 +308,10 @@ static ssize_t midi_set_midi_mask_transmit(struct device *dev,
{
struct usb_interface *interface = to_usb_interface(dev);
struct usb_line6 *line6 = usb_get_intfdata(interface);
- unsigned long value;
+ unsigned short value;
int ret;
- ret = strict_strtoul(buf, 10, &value);
+ ret = kstrtou16(buf, 10, &value);
if (ret)
return ret;
@@ -339,10 +340,10 @@ static ssize_t midi_set_midi_mask_receive(struct device *dev,
{
struct usb_interface *interface = to_usb_interface(dev);
struct usb_line6 *line6 = usb_get_intfdata(interface);
- unsigned long value;
+ unsigned short value;
int ret;
- ret = strict_strtoul(buf, 10, &value);
+ ret = kstrtou16(buf, 10, &value);
if (ret)
return ret;
@@ -391,16 +392,32 @@ int line6_init_midi(struct usb_line6 *line6)
return -ENOMEM;
err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0);
- if (err < 0)
+ if (err < 0) {
+ kfree(line6midi);
return err;
+ }
err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1);
- if (err < 0)
+ if (err < 0) {
+ kfree(line6midi->midibuf_in.buf);
+ kfree(line6midi);
return err;
+ }
line6midi->line6 = line6;
- line6midi->midi_mask_transmit = 1;
- line6midi->midi_mask_receive = 4;
+
+ switch(line6->product) {
+ case LINE6_DEVID_PODHD300:
+ case LINE6_DEVID_PODHD500:
+ line6midi->midi_mask_transmit = 1;
+ line6midi->midi_mask_receive = 1;
+ break;
+
+ default:
+ line6midi->midi_mask_transmit = 1;
+ line6midi->midi_mask_receive = 4;
+ }
+
line6->line6midi = line6midi;
err = snd_device_new(line6->card, SNDRV_DEV_RAWMIDI, line6midi,
diff --git a/drivers/staging/line6/midi.h b/drivers/staging/line6/midi.h
index b73a025d8be9..4a9e9f947297 100644
--- a/drivers/staging/line6/midi.h
+++ b/drivers/staging/line6/midi.h
@@ -57,12 +57,12 @@ struct snd_line6_midi {
/**
Bit mask for output MIDI channels.
*/
- int midi_mask_transmit;
+ unsigned short midi_mask_transmit;
/**
Bit mask for input MIDI channels.
*/
- int midi_mask_receive;
+ unsigned short midi_mask_receive;
/**
Buffer for incoming MIDI stream.
diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c
index 9d4c8a606eea..37675e66da81 100644
--- a/drivers/staging/line6/pcm.c
+++ b/drivers/staging/line6/pcm.c
@@ -86,31 +86,22 @@ static DEVICE_ATTR(impulse_period, S_IWUSR | S_IRUGO, pcm_get_impulse_period,
#endif
+static bool test_flags(unsigned long flags0, unsigned long flags1,
+ unsigned long mask)
+{
+ return ((flags0 & mask) == 0) && ((flags1 & mask) != 0);
+}
+
int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
{
unsigned long flags_old =
__sync_fetch_and_or(&line6pcm->flags, channels);
unsigned long flags_new = flags_old | channels;
int err = 0;
-
-#if LINE6_BACKUP_MONITOR_SIGNAL
- if (!(line6pcm->line6->properties->capabilities & LINE6_BIT_HWMON)) {
- line6pcm->prev_fbuf =
- kmalloc(LINE6_ISO_PACKETS * line6pcm->max_packet_size,
- GFP_KERNEL);
-
- if (!line6pcm->prev_fbuf) {
- dev_err(line6pcm->line6->ifcdev,
- "cannot malloc monitor buffer\n");
- return -ENOMEM;
- }
- }
-#else
+
line6pcm->prev_fbuf = NULL;
-#endif
- if (((flags_old & MASK_CAPTURE) == 0) &&
- ((flags_new & MASK_CAPTURE) != 0)) {
+ if (test_flags(flags_old, flags_new, MASK_CAPTURE)) {
/*
Waiting for completion of active URBs in the stop handler is
a bug, we therefore report an error if capturing is restarted
@@ -119,54 +110,47 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
if (line6pcm->active_urb_in | line6pcm->unlink_urb_in)
return -EBUSY;
- line6pcm->buffer_in =
- kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
- line6pcm->max_packet_size, GFP_KERNEL);
+ if (!(flags_new & MASK_PCM_ALSA_CAPTURE)) {
+ err = line6_alloc_capture_buffer(line6pcm);
- if (!line6pcm->buffer_in) {
- dev_err(line6pcm->line6->ifcdev,
- "cannot malloc capture buffer\n");
- return -ENOMEM;
+ if (err < 0)
+ goto pcm_start_error;
}
line6pcm->count_in = 0;
line6pcm->prev_fsize = 0;
err = line6_submit_audio_in_all_urbs(line6pcm);
- if (err < 0) {
- __sync_fetch_and_and(&line6pcm->flags, ~channels);
- return err;
- }
+ if (err < 0)
+ goto pcm_start_error;
}
- if (((flags_old & MASK_PLAYBACK) == 0) &&
- ((flags_new & MASK_PLAYBACK) != 0)) {
+ if (test_flags(flags_old, flags_new, MASK_PLAYBACK)) {
/*
See comment above regarding PCM restart.
*/
if (line6pcm->active_urb_out | line6pcm->unlink_urb_out)
return -EBUSY;
- line6pcm->buffer_out =
- kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
- line6pcm->max_packet_size, GFP_KERNEL);
+ if (!(flags_new & MASK_PCM_ALSA_PLAYBACK)) {
+ err = line6_alloc_playback_buffer(line6pcm);
- if (!line6pcm->buffer_out) {
- dev_err(line6pcm->line6->ifcdev,
- "cannot malloc playback buffer\n");
- return -ENOMEM;
+ if (err < 0)
+ goto pcm_start_error;
}
line6pcm->count_out = 0;
err = line6_submit_audio_out_all_urbs(line6pcm);
- if (err < 0) {
- __sync_fetch_and_and(&line6pcm->flags, ~channels);
- return err;
- }
+ if (err < 0)
+ goto pcm_start_error;
}
return 0;
+
+pcm_start_error:
+ __sync_fetch_and_and(&line6pcm->flags, ~channels);
+ return err;
}
int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
@@ -175,22 +159,19 @@ int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
__sync_fetch_and_and(&line6pcm->flags, ~channels);
unsigned long flags_new = flags_old & ~channels;
- if (((flags_old & MASK_CAPTURE) != 0) &&
- ((flags_new & MASK_CAPTURE) == 0)) {
+ if (test_flags(flags_new, flags_old, MASK_CAPTURE)) {
line6_unlink_audio_in_urbs(line6pcm);
- kfree(line6pcm->buffer_in);
- line6pcm->buffer_in = NULL;
+
+ if (!(flags_old & MASK_PCM_ALSA_CAPTURE))
+ line6_free_capture_buffer(line6pcm);
}
- if (((flags_old & MASK_PLAYBACK) != 0) &&
- ((flags_new & MASK_PLAYBACK) == 0)) {
+ if (test_flags(flags_new, flags_old, MASK_PLAYBACK)) {
line6_unlink_audio_out_urbs(line6pcm);
- kfree(line6pcm->buffer_out);
- line6pcm->buffer_out = NULL;
+
+ if (!(flags_old & MASK_PCM_ALSA_PLAYBACK))
+ line6_free_playback_buffer(line6pcm);
}
-#if LINE6_BACKUP_MONITOR_SIGNAL
- kfree(line6pcm->prev_fbuf);
-#endif
return 0;
}
@@ -403,10 +384,12 @@ int line6_init_pcm(struct usb_line6 *line6,
case LINE6_DEVID_PODXT:
case LINE6_DEVID_PODXTLIVE:
case LINE6_DEVID_PODXTPRO:
+ case LINE6_DEVID_PODHD300:
ep_read = 0x82;
ep_write = 0x01;
break;
+ case LINE6_DEVID_PODHD500:
case LINE6_DEVID_PODX3:
case LINE6_DEVID_PODX3LIVE:
ep_read = 0x86;
@@ -451,9 +434,14 @@ int line6_init_pcm(struct usb_line6 *line6,
line6pcm->line6 = line6;
line6pcm->ep_audio_read = ep_read;
line6pcm->ep_audio_write = ep_write;
- line6pcm->max_packet_size = usb_maxpacket(line6->usbdev,
- usb_rcvintpipe(line6->usbdev,
- ep_read), 0);
+
+ /* Read and write buffers are sized identically, so choose minimum */
+ line6pcm->max_packet_size = min(
+ usb_maxpacket(line6->usbdev,
+ usb_rcvisocpipe(line6->usbdev, ep_read), 0),
+ usb_maxpacket(line6->usbdev,
+ usb_sndisocpipe(line6->usbdev, ep_write), 1));
+
line6pcm->properties = properties;
line6->line6pcm = line6pcm;
@@ -508,6 +496,23 @@ int snd_line6_prepare(struct snd_pcm_substream *substream)
{
struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+ switch (substream->stream) {
+ case SNDRV_PCM_STREAM_PLAYBACK:
+ if ((line6pcm->flags & MASK_PLAYBACK) == 0)
+ line6_unlink_wait_clear_audio_out_urbs(line6pcm);
+
+ break;
+
+ case SNDRV_PCM_STREAM_CAPTURE:
+ if ((line6pcm->flags & MASK_CAPTURE) == 0)
+ line6_unlink_wait_clear_audio_in_urbs(line6pcm);
+
+ break;
+
+ default:
+ MISSING_CASE;
+ }
+
if (!test_and_set_bit(BIT_PREPARED, &line6pcm->flags)) {
line6pcm->count_out = 0;
line6pcm->pos_out = 0;
diff --git a/drivers/staging/line6/pcm.h b/drivers/staging/line6/pcm.h
index 77055b3724ad..55d8297dd3d9 100644
--- a/drivers/staging/line6/pcm.h
+++ b/drivers/staging/line6/pcm.h
@@ -39,9 +39,6 @@
#define LINE6_IMPULSE_DEFAULT_PERIOD 100
#endif
-#define LINE6_BACKUP_MONITOR_SIGNAL 0
-#define LINE6_REUSE_DMA_AREA_FOR_PLAYBACK 0
-
/*
Get substream from Line6 PCM data structure
*/
@@ -149,11 +146,6 @@ struct snd_line6_pcm {
unsigned char *buffer_in;
/**
- Temporary buffer index for playback.
- */
- int index_out;
-
- /**
Previously captured frame (for software monitoring).
*/
unsigned char *prev_fbuf;
diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c
index 10c543836583..4152db2328b7 100644
--- a/drivers/staging/line6/playback.c
+++ b/drivers/staging/line6/playback.c
@@ -9,6 +9,7 @@
*
*/
+#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -191,13 +192,10 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
urb_frames = urb_size / bytes_per_frame;
urb_out->transfer_buffer =
line6pcm->buffer_out +
- line6pcm->max_packet_size * line6pcm->index_out;
+ index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
urb_out->transfer_buffer_length = urb_size;
urb_out->context = line6pcm;
- if (++line6pcm->index_out == LINE6_ISO_BUFFERS)
- line6pcm->index_out = 0;
-
if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags) &&
!test_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags)) {
struct snd_pcm_runtime *runtime =
@@ -222,18 +220,10 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
} else
dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", len); /* this is somewhat paranoid */
} else {
-#if LINE6_REUSE_DMA_AREA_FOR_PLAYBACK
- /* set the buffer pointer */
- urb_out->transfer_buffer =
- runtime->dma_area +
- line6pcm->pos_out * bytes_per_frame;
-#else
- /* copy data */
memcpy(urb_out->transfer_buffer,
runtime->dma_area +
line6pcm->pos_out * bytes_per_frame,
urb_out->transfer_buffer_length);
-#endif
}
line6pcm->pos_out += urb_frames;
@@ -361,6 +351,31 @@ void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
wait_clear_audio_out_urbs(line6pcm);
}
+int line6_alloc_playback_buffer(struct snd_line6_pcm *line6pcm)
+{
+ /* We may be invoked multiple times in a row so allocate once only */
+ if (line6pcm->buffer_out)
+ return 0;
+
+ line6pcm->buffer_out =
+ kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
+ line6pcm->max_packet_size, GFP_KERNEL);
+
+ if (!line6pcm->buffer_out) {
+ dev_err(line6pcm->line6->ifcdev,
+ "cannot malloc playback buffer\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm)
+{
+ kfree(line6pcm->buffer_out);
+ line6pcm->buffer_out = NULL;
+}
+
/*
Callback for completed playback URB.
*/
@@ -469,6 +484,13 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream,
}
/* -- [FD] end */
+ if ((line6pcm->flags & MASK_PLAYBACK) == 0) {
+ ret = line6_alloc_playback_buffer(line6pcm);
+
+ if (ret < 0)
+ return ret;
+ }
+
ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
if (ret < 0)
@@ -481,6 +503,13 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream,
/* hw_free playback callback */
static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream)
{
+ struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+
+ if ((line6pcm->flags & MASK_PLAYBACK) == 0) {
+ line6_unlink_wait_clear_audio_out_urbs(line6pcm);
+ line6_free_playback_buffer(line6pcm);
+ }
+
return snd_pcm_lib_free_pages(substream);
}
diff --git a/drivers/staging/line6/playback.h b/drivers/staging/line6/playback.h
index f2fc8c0526e3..02487ff24538 100644
--- a/drivers/staging/line6/playback.h
+++ b/drivers/staging/line6/playback.h
@@ -29,7 +29,9 @@
extern struct snd_pcm_ops snd_line6_playback_ops;
+extern int line6_alloc_playback_buffer(struct snd_line6_pcm *line6pcm);
extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm);
+extern void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm);
extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm);
extern void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm);
extern void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm
diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c
index d9b30212585c..4dadc571d961 100644
--- a/drivers/staging/line6/pod.c
+++ b/drivers/staging/line6/pod.c
@@ -1149,14 +1149,10 @@ static struct snd_kcontrol_new pod_control_monitor = {
static void pod_destruct(struct usb_interface *interface)
{
struct usb_line6_pod *pod = usb_get_intfdata(interface);
- struct usb_line6 *line6;
if (pod == NULL)
return;
- line6 = &pod->line6;
- if (line6 == NULL)
- return;
- line6_cleanup_audio(line6);
+ line6_cleanup_audio(&pod->line6);
del_timer(&pod->startup_timer);
cancel_work_sync(&pod->startup_work);
diff --git a/drivers/staging/line6/podhd.c b/drivers/staging/line6/podhd.c
new file mode 100644
index 000000000000..7ef45437b4f2
--- /dev/null
+++ b/drivers/staging/line6/podhd.c
@@ -0,0 +1,154 @@
+/*
+ * Line6 Pod HD
+ *
+ * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "audio.h"
+#include "driver.h"
+#include "pcm.h"
+#include "podhd.h"
+
+#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
+
+static struct snd_ratden podhd_ratden = {
+ .num_min = 48000,
+ .num_max = 48000,
+ .num_step = 1,
+ .den = 1,
+};
+
+static struct line6_pcm_properties podhd_pcm_properties = {
+ .snd_line6_playback_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+#ifdef CONFIG_PM
+ SNDRV_PCM_INFO_RESUME |
+#endif
+ SNDRV_PCM_INFO_SYNC_START),
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 60000,
+ .period_bytes_min = 64,
+ .period_bytes_max = 8192,
+ .periods_min = 1,
+ .periods_max = 1024},
+ .snd_line6_capture_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+#ifdef CONFIG_PM
+ SNDRV_PCM_INFO_RESUME |
+#endif
+ SNDRV_PCM_INFO_SYNC_START),
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 60000,
+ .period_bytes_min = 64,
+ .period_bytes_max = 8192,
+ .periods_min = 1,
+ .periods_max = 1024},
+ .snd_line6_rates = {
+ .nrats = 1,
+ .rats = &podhd_ratden},
+ .bytes_per_frame = PODHD_BYTES_PER_FRAME
+};
+
+/*
+ POD HD destructor.
+*/
+static void podhd_destruct(struct usb_interface *interface)
+{
+ struct usb_line6_podhd *podhd = usb_get_intfdata(interface);
+
+ if (podhd == NULL)
+ return;
+ line6_cleanup_audio(&podhd->line6);
+}
+
+/*
+ Try to init POD HD device.
+*/
+static int podhd_try_init(struct usb_interface *interface,
+ struct usb_line6_podhd *podhd)
+{
+ int err;
+ struct usb_line6 *line6 = &podhd->line6;
+
+ if ((interface == NULL) || (podhd == NULL))
+ return -ENODEV;
+
+ /* initialize audio system: */
+ err = line6_init_audio(line6);
+ if (err < 0)
+ return err;
+
+ /* initialize MIDI subsystem: */
+ err = line6_init_midi(line6);
+ if (err < 0)
+ return err;
+
+ /* initialize PCM subsystem: */
+ err = line6_init_pcm(line6, &podhd_pcm_properties);
+ if (err < 0)
+ return err;
+
+ /* register USB audio system: */
+ err = line6_register_audio(line6);
+ return err;
+}
+
+/*
+ Init POD HD device (and clean up in case of failure).
+*/
+int line6_podhd_init(struct usb_interface *interface,
+ struct usb_line6_podhd *podhd)
+{
+ int err = podhd_try_init(interface, podhd);
+
+ if (err < 0)
+ podhd_destruct(interface);
+
+ return err;
+}
+
+/*
+ POD HD device disconnected.
+*/
+void line6_podhd_disconnect(struct usb_interface *interface)
+{
+ struct usb_line6_podhd *podhd;
+
+ if (interface == NULL)
+ return;
+ podhd = usb_get_intfdata(interface);
+
+ if (podhd != NULL) {
+ struct snd_line6_pcm *line6pcm = podhd->line6.line6pcm;
+
+ if (line6pcm != NULL)
+ line6_pcm_disconnect(line6pcm);
+ }
+
+ podhd_destruct(interface);
+}
diff --git a/drivers/staging/line6/podhd.h b/drivers/staging/line6/podhd.h
new file mode 100644
index 000000000000..652f74056bb9
--- /dev/null
+++ b/drivers/staging/line6/podhd.h
@@ -0,0 +1,30 @@
+/*
+ * Line6 Pod HD
+ *
+ * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef PODHD_H
+#define PODHD_H
+
+#include <linux/usb.h>
+
+#include "driver.h"
+
+struct usb_line6_podhd {
+ /**
+ Generic Line6 USB data.
+ */
+ struct usb_line6 line6;
+};
+
+extern void line6_podhd_disconnect(struct usb_interface *interface);
+extern int line6_podhd_init(struct usb_interface *interface,
+ struct usb_line6_podhd *podhd);
+
+#endif /* PODHD_H */
diff --git a/drivers/staging/line6/revision.h b/drivers/staging/line6/revision.h
index 350d0dfff8f8..b4eee2b73831 100644
--- a/drivers/staging/line6/revision.h
+++ b/drivers/staging/line6/revision.h
@@ -1,4 +1,4 @@
#ifndef DRIVER_REVISION
/* current subversion revision */
-#define DRIVER_REVISION " (revision 690)"
+#define DRIVER_REVISION " (904)"
#endif
diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c
index 879e6992bbc6..f31057830dbc 100644
--- a/drivers/staging/line6/toneport.c
+++ b/drivers/staging/line6/toneport.c
@@ -295,14 +295,10 @@ static struct snd_kcontrol_new toneport_control_source = {
static void toneport_destruct(struct usb_interface *interface)
{
struct usb_line6_toneport *toneport = usb_get_intfdata(interface);
- struct usb_line6 *line6;
if (toneport == NULL)
return;
- line6 = &toneport->line6;
- if (line6 == NULL)
- return;
- line6_cleanup_audio(line6);
+ line6_cleanup_audio(&toneport->line6);
}
/*
diff --git a/drivers/staging/line6/usbdefs.h b/drivers/staging/line6/usbdefs.h
index c6dffe6bc1a5..aff9e5caea46 100644
--- a/drivers/staging/line6/usbdefs.h
+++ b/drivers/staging/line6/usbdefs.h
@@ -24,6 +24,8 @@
#define LINE6_DEVID_BASSPODXTPRO 0x4252
#define LINE6_DEVID_GUITARPORT 0x4750
#define LINE6_DEVID_POCKETPOD 0x5051
+#define LINE6_DEVID_PODHD300 0x5057
+#define LINE6_DEVID_PODHD500 0x414D
#define LINE6_DEVID_PODSTUDIO_GX 0x4153
#define LINE6_DEVID_PODSTUDIO_UX1 0x4150
#define LINE6_DEVID_PODSTUDIO_UX2 0x4151
@@ -37,48 +39,71 @@
#define LINE6_DEVID_TONEPORT_UX2 0x4142
#define LINE6_DEVID_VARIAX 0x534d
-#define LINE6_BIT_BASSPODXT (1 << 0)
-#define LINE6_BIT_BASSPODXTLIVE (1 << 1)
-#define LINE6_BIT_BASSPODXTPRO (1 << 2)
-#define LINE6_BIT_GUITARPORT (1 << 3)
-#define LINE6_BIT_POCKETPOD (1 << 4)
-#define LINE6_BIT_PODSTUDIO_GX (1 << 5)
-#define LINE6_BIT_PODSTUDIO_UX1 (1 << 6)
-#define LINE6_BIT_PODSTUDIO_UX2 (1 << 7)
-#define LINE6_BIT_PODX3 (1 << 8)
-#define LINE6_BIT_PODX3LIVE (1 << 9)
-#define LINE6_BIT_PODXT (1 << 10)
-#define LINE6_BIT_PODXTLIVE (1 << 11)
-#define LINE6_BIT_PODXTPRO (1 << 12)
-#define LINE6_BIT_TONEPORT_GX (1 << 13)
-#define LINE6_BIT_TONEPORT_UX1 (1 << 14)
-#define LINE6_BIT_TONEPORT_UX2 (1 << 15)
-#define LINE6_BIT_VARIAX (1 << 16)
+enum {
+ LINE6_ID_BASSPODXT,
+ LINE6_ID_BASSPODXTLIVE,
+ LINE6_ID_BASSPODXTPRO,
+ LINE6_ID_GUITARPORT,
+ LINE6_ID_POCKETPOD,
+ LINE6_ID_PODHD300,
+ LINE6_ID_PODHD500,
+ LINE6_ID_PODSTUDIO_GX,
+ LINE6_ID_PODSTUDIO_UX1,
+ LINE6_ID_PODSTUDIO_UX2,
+ LINE6_ID_PODX3,
+ LINE6_ID_PODX3LIVE,
+ LINE6_ID_PODXT,
+ LINE6_ID_PODXTLIVE,
+ LINE6_ID_PODXTPRO,
+ LINE6_ID_TONEPORT_GX,
+ LINE6_ID_TONEPORT_UX1,
+ LINE6_ID_TONEPORT_UX2,
+ LINE6_ID_VARIAX
+};
-#define LINE6_BITS_PRO (LINE6_BIT_BASSPODXTPRO | \
- LINE6_BIT_PODXTPRO)
-#define LINE6_BITS_LIVE (LINE6_BIT_BASSPODXTLIVE | \
- LINE6_BIT_PODXTLIVE | \
- LINE6_BIT_PODX3LIVE)
-#define LINE6_BITS_PODXTALL (LINE6_BIT_PODXT | \
- LINE6_BIT_PODXTLIVE | \
- LINE6_BIT_PODXTPRO)
-#define LINE6_BITS_BASSPODXTALL (LINE6_BIT_BASSPODXT | \
- LINE6_BIT_BASSPODXTLIVE | \
- LINE6_BIT_BASSPODXTPRO)
+#define LINE6_BIT(x) LINE6_BIT_ ## x = 1 << LINE6_ID_ ## x
+
+enum {
+ LINE6_BIT(BASSPODXT),
+ LINE6_BIT(BASSPODXTLIVE),
+ LINE6_BIT(BASSPODXTPRO),
+ LINE6_BIT(GUITARPORT),
+ LINE6_BIT(POCKETPOD),
+ LINE6_BIT(PODHD300),
+ LINE6_BIT(PODHD500),
+ LINE6_BIT(PODSTUDIO_GX),
+ LINE6_BIT(PODSTUDIO_UX1),
+ LINE6_BIT(PODSTUDIO_UX2),
+ LINE6_BIT(PODX3),
+ LINE6_BIT(PODX3LIVE),
+ LINE6_BIT(PODXT),
+ LINE6_BIT(PODXTLIVE),
+ LINE6_BIT(PODXTPRO),
+ LINE6_BIT(TONEPORT_GX),
+ LINE6_BIT(TONEPORT_UX1),
+ LINE6_BIT(TONEPORT_UX2),
+ LINE6_BIT(VARIAX),
+
+ LINE6_BITS_PRO = LINE6_BIT_BASSPODXTPRO | LINE6_BIT_PODXTPRO,
+ LINE6_BITS_LIVE = LINE6_BIT_BASSPODXTLIVE | LINE6_BIT_PODXTLIVE | LINE6_BIT_PODX3LIVE,
+ LINE6_BITS_PODXTALL = LINE6_BIT_PODXT | LINE6_BIT_PODXTLIVE | LINE6_BIT_PODXTPRO,
+ LINE6_BITS_PODX3ALL = LINE6_BIT_PODX3 | LINE6_BIT_PODX3LIVE,
+ LINE6_BITS_PODHDALL = LINE6_BIT_PODHD300 | LINE6_BIT_PODHD500,
+ LINE6_BITS_BASSPODXTALL = LINE6_BIT_BASSPODXT | LINE6_BIT_BASSPODXTLIVE | LINE6_BIT_BASSPODXTPRO
+};
/* device supports settings parameter via USB */
-#define LINE6_BIT_CONTROL (1 << 0)
+#define LINE6_BIT_CONTROL (1 << 0)
/* device supports PCM input/output via USB */
-#define LINE6_BIT_PCM (1 << 1)
+#define LINE6_BIT_PCM (1 << 1)
/* device support hardware monitoring */
-#define LINE6_BIT_HWMON (1 << 2)
+#define LINE6_BIT_HWMON (1 << 2)
#define LINE6_BIT_CONTROL_PCM_HWMON (LINE6_BIT_CONTROL | \
LINE6_BIT_PCM | \
LINE6_BIT_HWMON)
-#define LINE6_FALLBACK_INTERVAL 10
-#define LINE6_FALLBACK_MAXPACKETSIZE 16
+#define LINE6_FALLBACK_INTERVAL 10
+#define LINE6_FALLBACK_MAXPACKETSIZE 16
#endif
diff --git a/drivers/staging/line6/variax.c b/drivers/staging/line6/variax.c
index 81241cdf1be9..d36622228b2d 100644
--- a/drivers/staging/line6/variax.c
+++ b/drivers/staging/line6/variax.c
@@ -572,14 +572,10 @@ static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2);
static void variax_destruct(struct usb_interface *interface)
{
struct usb_line6_variax *variax = usb_get_intfdata(interface);
- struct usb_line6 *line6;
if (variax == NULL)
return;
- line6 = &variax->line6;
- if (line6 == NULL)
- return;
- line6_cleanup_audio(line6);
+ line6_cleanup_audio(&variax->line6);
del_timer(&variax->startup_timer1);
del_timer(&variax->startup_timer2);
diff --git a/drivers/staging/mei/init.c b/drivers/staging/mei/init.c
index 8bf34794489c..4ac3696883cb 100644
--- a/drivers/staging/mei/init.c
+++ b/drivers/staging/mei/init.c
@@ -38,7 +38,6 @@ void mei_io_list_init(struct mei_io_list *list)
{
/* initialize our queue list */
INIT_LIST_HEAD(&list->mei_cb.cb_list);
- list->status = 0;
}
/**
@@ -49,22 +48,15 @@ void mei_io_list_init(struct mei_io_list *list)
*/
void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
{
- struct mei_cl_cb *cb_pos = NULL;
- struct mei_cl_cb *cb_next = NULL;
+ struct mei_cl_cb *pos;
+ struct mei_cl_cb *next;
- if (list->status != 0)
- return;
-
- if (list_empty(&list->mei_cb.cb_list))
- return;
-
- list_for_each_entry_safe(cb_pos, cb_next,
- &list->mei_cb.cb_list, cb_list) {
- if (cb_pos) {
+ list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
+ if (pos->file_private) {
struct mei_cl *cl_tmp;
- cl_tmp = (struct mei_cl *)cb_pos->file_private;
+ cl_tmp = (struct mei_cl *)pos->file_private;
if (mei_cl_cmp_id(cl, cl_tmp))
- list_del(&cb_pos->cb_list);
+ list_del(&pos->cb_list);
}
}
}
@@ -338,16 +330,10 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
}
}
/* remove all waiting requests */
- if (dev->write_list.status == 0 &&
- !list_empty(&dev->write_list.mei_cb.cb_list)) {
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->write_list.mei_cb.cb_list, cb_list) {
- if (cb_pos) {
- list_del(&cb_pos->cb_list);
- mei_free_cb_private(cb_pos);
- cb_pos = NULL;
- }
- }
+ list_for_each_entry_safe(cb_pos, cb_next,
+ &dev->write_list.mei_cb.cb_list, cb_list) {
+ list_del(&cb_pos->cb_list);
+ mei_free_cb_private(cb_pos);
}
}
@@ -380,8 +366,7 @@ void mei_host_start_message(struct mei_device *dev)
host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
dev->recvd_msg = false;
- if (!mei_write_message(dev, mei_hdr,
- (unsigned char *) (host_start_req),
+ if (!mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
mei_hdr->length)) {
dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
dev->mei_state = MEI_RESETING;
@@ -414,8 +399,7 @@ void mei_host_enum_clients_message(struct mei_device *dev)
host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request));
host_enum_req->cmd.cmd = HOST_ENUM_REQ_CMD;
- if (!mei_write_message(dev, mei_hdr,
- (unsigned char *) (host_enum_req),
+ if (!mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
mei_hdr->length)) {
dev->mei_state = MEI_RESETING;
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
@@ -605,15 +589,10 @@ void mei_host_init_iamthif(struct mei_device *dev)
return;
}
- /* Do not render the system unusable when iamthif_mtu is not equal to
- the value received from ME.
- Assign iamthif_mtu to the value received from ME in order to solve the
- hardware macro incompatibility. */
+ /* Assign iamthif_mtu to the value received from ME */
- dev_dbg(&dev->pdev->dev, "[DEFAULT] IAMTHIF = %d\n", dev->iamthif_mtu);
dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
- dev_dbg(&dev->pdev->dev,
- "IAMTHIF = %d\n",
+ dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
dev->me_clients[i].props.max_msg_length);
kfree(dev->iamthif_msg_buf);
diff --git a/drivers/staging/mei/interface.c b/drivers/staging/mei/interface.c
index a65dacf00213..eb5df7fc2269 100644
--- a/drivers/staging/mei/interface.c
+++ b/drivers/staging/mei/interface.c
@@ -128,9 +128,9 @@ int mei_count_empty_write_slots(struct mei_device *dev)
* returns 1 if success, 0 - otherwise.
*/
int mei_write_message(struct mei_device *dev,
- struct mei_msg_hdr *header,
- unsigned char *write_buffer,
- unsigned long write_length)
+ struct mei_msg_hdr *header,
+ unsigned char *write_buffer,
+ unsigned long write_length)
{
u32 temp_msg = 0;
unsigned long bytes_written = 0;
@@ -216,7 +216,7 @@ int mei_count_full_read_slots(struct mei_device *dev)
* @buffer_length: message size will be read
*/
void mei_read_slots(struct mei_device *dev,
- unsigned char *buffer, unsigned long buffer_length)
+ unsigned char *buffer, unsigned long buffer_length)
{
u32 i = 0;
unsigned char temp_buf[sizeof(u32)];
diff --git a/drivers/staging/mei/interface.h b/drivers/staging/mei/interface.h
index 7bd38ae2c233..aeae511419c7 100644
--- a/drivers/staging/mei/interface.h
+++ b/drivers/staging/mei/interface.h
@@ -52,6 +52,17 @@ int mei_wd_send(struct mei_device *dev);
int mei_wd_stop(struct mei_device *dev, bool preserve);
bool mei_wd_host_init(struct mei_device *dev);
void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout);
+/*
+ * mei_watchdog_register - Registering watchdog interface
+ * once we got connection to the WD Client
+ * @dev - mei device
+ */
+void mei_watchdog_register(struct mei_device *dev);
+/*
+ * mei_watchdog_unregister - Uegistering watchdog interface
+ * @dev - mei device
+ */
+void mei_watchdog_unregister(struct mei_device *dev);
int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl);
diff --git a/drivers/staging/mei/interrupt.c b/drivers/staging/mei/interrupt.c
index 882d106d54e5..3544fee34e48 100644
--- a/drivers/staging/mei/interrupt.c
+++ b/drivers/staging/mei/interrupt.c
@@ -198,8 +198,7 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
unsigned char *buffer = NULL;
dev_dbg(&dev->pdev->dev, "start client msg\n");
- if (!(dev->read_list.status == 0 &&
- !list_empty(&dev->read_list.mei_cb.cb_list)))
+ if (list_empty(&dev->read_list.mei_cb.cb_list))
goto quit;
list_for_each_entry_safe(cb_pos, cb_next,
@@ -210,9 +209,6 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
buffer = (unsigned char *)
(cb_pos->response_buffer.data +
cb_pos->information);
- BUG_ON(cb_pos->response_buffer.size <
- mei_hdr->length +
- cb_pos->information);
if (cb_pos->response_buffer.size <
mei_hdr->length + cb_pos->information) {
@@ -390,24 +386,10 @@ static void mei_client_connect_response(struct mei_device *dev,
/* if WD or iamthif client treat specially */
if (is_treat_specially_client(&(dev->wd_cl), rs)) {
- dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n",
- dev->wd_timeout);
-
- dev->wd_due_counter = (dev->wd_timeout) ? 1 : 0;
-
dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
+ mei_watchdog_register(dev);
- /* Registering watchdog interface device once we got connection
- to the WD Client
- */
- if (watchdog_register_device(&amt_wd_dev)) {
- printk(KERN_ERR "mei: unable to register watchdog device.\n");
- dev->wd_interface_reg = false;
- } else {
- dev_dbg(&dev->pdev->dev, "successfully register watchdog interface.\n");
- dev->wd_interface_reg = true;
- }
-
+ /* next step in the state maching */
mei_host_init_iamthif(dev);
return;
}
@@ -416,22 +398,20 @@ static void mei_client_connect_response(struct mei_device *dev,
dev->iamthif_state = MEI_IAMTHIF_IDLE;
return;
}
- if (!dev->ctrl_rd_list.status &&
- !list_empty(&dev->ctrl_rd_list.mei_cb.cb_list)) {
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
- if (!cl) {
+ list_for_each_entry_safe(cb_pos, cb_next,
+ &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
+
+ cl = (struct mei_cl *)cb_pos->file_private;
+ if (!cl) {
+ list_del(&cb_pos->cb_list);
+ return;
+ }
+ if (MEI_IOCTL == cb_pos->major_file_operations) {
+ if (is_treat_specially_client(cl, rs)) {
list_del(&cb_pos->cb_list);
- return;
- }
- if (MEI_IOCTL == cb_pos->major_file_operations) {
- if (is_treat_specially_client(cl, rs)) {
- list_del(&cb_pos->cb_list);
- cl->status = 0;
- cl->timer_count = 0;
- break;
- }
+ cl->status = 0;
+ cl->timer_count = 0;
+ break;
}
}
}
@@ -458,29 +438,26 @@ static void mei_client_disconnect_response(struct mei_device *dev,
rs->host_addr,
rs->status);
- if (!dev->ctrl_rd_list.status &&
- !list_empty(&dev->ctrl_rd_list.mei_cb.cb_list)) {
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
+ list_for_each_entry_safe(cb_pos, cb_next,
+ &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
+ cl = (struct mei_cl *)cb_pos->file_private;
- if (!cl) {
- list_del(&cb_pos->cb_list);
- return;
- }
+ if (!cl) {
+ list_del(&cb_pos->cb_list);
+ return;
+ }
- dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
- if (cl->host_client_id == rs->host_addr &&
- cl->me_client_id == rs->me_addr) {
+ dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
+ if (cl->host_client_id == rs->host_addr &&
+ cl->me_client_id == rs->me_addr) {
- list_del(&cb_pos->cb_list);
- if (!rs->status)
- cl->state = MEI_FILE_DISCONNECTED;
+ list_del(&cb_pos->cb_list);
+ if (!rs->status)
+ cl->state = MEI_FILE_DISCONNECTED;
- cl->status = 0;
- cl->timer_count = 0;
- break;
- }
+ cl->status = 0;
+ cl->timer_count = 0;
+ break;
}
}
}
@@ -718,7 +695,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
case CLIENT_DISCONNECT_RES_CMD:
disconnect_res =
(struct hbm_client_connect_response *) mei_msg;
- mei_client_disconnect_response(dev, disconnect_res);
+ mei_client_disconnect_response(dev, disconnect_res);
dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
wake_up(&dev->wait_recvd_msg);
break;
@@ -736,7 +713,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
mei_reset(dev, 1);
return;
}
- if (dev->me_clients[dev->me_client_presentation_num]
+ if (dev->me_clients[dev->me_client_presentation_num]
.client_id == props_res->address) {
dev->me_clients[dev->me_client_presentation_num].props
@@ -1228,7 +1205,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
{
struct mei_cl *cl;
- struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
+ struct mei_cl_cb *pos = NULL, *next = NULL;
struct mei_io_list *list;
int ret;
@@ -1241,36 +1218,31 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
list = &dev->write_waiting_list;
- if (!list->status && !list_empty(&list->mei_cb.cb_list)) {
- list_for_each_entry_safe(cb_pos, cb_next,
- &list->mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
- if (cl) {
- cl->status = 0;
- list_del(&cb_pos->cb_list);
- if (MEI_WRITING == cl->writing_state &&
- (cb_pos->major_file_operations ==
- MEI_WRITE) &&
- (cl != &dev->iamthif_cl)) {
- dev_dbg(&dev->pdev->dev,
- "MEI WRITE COMPLETE\n");
- cl->writing_state =
- MEI_WRITE_COMPLETE;
- list_add_tail(&cb_pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
- }
- if (cl == &dev->iamthif_cl) {
- dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
- if (dev->iamthif_flow_control_pending) {
- ret =
- _mei_irq_thread_iamthif_read(
- dev, slots);
- if (ret)
- return ret;
- }
- }
+ list_for_each_entry_safe(pos, next,
+ &list->mei_cb.cb_list, cb_list) {
+ cl = (struct mei_cl *)pos->file_private;
+ if (cl == NULL)
+ continue;
+
+ cl->status = 0;
+ list_del(&pos->cb_list);
+ if (MEI_WRITING == cl->writing_state &&
+ (pos->major_file_operations == MEI_WRITE) &&
+ (cl != &dev->iamthif_cl)) {
+ dev_dbg(&dev->pdev->dev,
+ "MEI WRITE COMPLETE\n");
+ cl->writing_state = MEI_WRITE_COMPLETE;
+ list_add_tail(&pos->cb_list,
+ &cmpl_list->mei_cb.cb_list);
+ }
+ if (cl == &dev->iamthif_cl) {
+ dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
+ if (dev->iamthif_flow_control_pending) {
+ ret = _mei_irq_thread_iamthif_read(
+ dev, slots);
+ if (ret)
+ return ret;
}
-
}
}
@@ -1317,101 +1289,88 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
return ~ENODEV;
/* complete control write list CB */
- if (!dev->ctrl_wr_list.status) {
- /* complete control write list CB */
- dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
- list_for_each_entry_safe(cb_pos, cb_next,
+ dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
+ list_for_each_entry_safe(pos, next,
&dev->ctrl_wr_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)
- cb_pos->file_private;
- if (!cl) {
- list_del(&cb_pos->cb_list);
- return -ENODEV;
- }
- switch (cb_pos->major_file_operations) {
- case MEI_CLOSE:
- /* send disconnect message */
- ret = _mei_irq_thread_close(dev, slots,
- cb_pos, cl, cmpl_list);
- if (ret)
- return ret;
-
- break;
- case MEI_READ:
- /* send flow control message */
- ret = _mei_irq_thread_read(dev, slots,
- cb_pos, cl, cmpl_list);
- if (ret)
- return ret;
+ cl = (struct mei_cl *) pos->file_private;
+ if (!cl) {
+ list_del(&pos->cb_list);
+ return -ENODEV;
+ }
+ switch (pos->major_file_operations) {
+ case MEI_CLOSE:
+ /* send disconnect message */
+ ret = _mei_irq_thread_close(dev, slots, pos, cl, cmpl_list);
+ if (ret)
+ return ret;
- break;
- case MEI_IOCTL:
- /* connect message */
- if (!mei_other_client_is_connecting(dev,
- cl))
- continue;
- ret = _mei_irq_thread_ioctl(dev, slots,
- cb_pos, cl, cmpl_list);
- if (ret)
- return ret;
+ break;
+ case MEI_READ:
+ /* send flow control message */
+ ret = _mei_irq_thread_read(dev, slots, pos, cl, cmpl_list);
+ if (ret)
+ return ret;
- break;
+ break;
+ case MEI_IOCTL:
+ /* connect message */
+ if (mei_other_client_is_connecting(dev, cl))
+ continue;
+ ret = _mei_irq_thread_ioctl(dev, slots, pos, cl, cmpl_list);
+ if (ret)
+ return ret;
- default:
- BUG();
- }
+ break;
+ default:
+ BUG();
}
+
}
/* complete write list CB */
- if (!dev->write_list.status &&
- !list_empty(&dev->write_list.mei_cb.cb_list)) {
- dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->write_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
-
- if (cl) {
- if (cl != &dev->iamthif_cl) {
- if (!mei_flow_ctrl_creds(dev,
- cl)) {
- dev_dbg(&dev->pdev->dev,
- "No flow control"
- " credentials for client"
- " %d, not sending.\n",
- cl->host_client_id);
- continue;
- }
- ret = _mei_irq_thread_cmpl(dev, slots,
- cb_pos,
- cl, cmpl_list);
- if (ret)
- return ret;
-
- } else if (cl == &dev->iamthif_cl) {
- /* IAMTHIF IOCTL */
- dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
- if (!mei_flow_ctrl_creds(dev,
- cl)) {
- dev_dbg(&dev->pdev->dev,
- "No flow control"
- " credentials for amthi"
- " client %d.\n",
- cl->host_client_id);
- continue;
- }
- ret = _mei_irq_thread_cmpl_iamthif(dev,
- slots,
- cb_pos,
- cl,
- cmpl_list);
- if (ret)
- return ret;
-
- }
+ dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
+ list_for_each_entry_safe(pos, next,
+ &dev->write_list.mei_cb.cb_list, cb_list) {
+ cl = (struct mei_cl *)pos->file_private;
+ if (cl == NULL)
+ continue;
+
+ if (cl != &dev->iamthif_cl) {
+ if (!mei_flow_ctrl_creds(dev, cl)) {
+ dev_dbg(&dev->pdev->dev,
+ "No flow control"
+ " credentials for client"
+ " %d, not sending.\n",
+ cl->host_client_id);
+ continue;
+ }
+ ret = _mei_irq_thread_cmpl(dev, slots,
+ pos,
+ cl, cmpl_list);
+ if (ret)
+ return ret;
+
+ } else if (cl == &dev->iamthif_cl) {
+ /* IAMTHIF IOCTL */
+ dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
+ if (!mei_flow_ctrl_creds(dev, cl)) {
+ dev_dbg(&dev->pdev->dev,
+ "No flow control"
+ " credentials for amthi"
+ " client %d.\n",
+ cl->host_client_id);
+ continue;
}
+ ret = _mei_irq_thread_cmpl_iamthif(dev,
+ slots,
+ pos,
+ cl,
+ cmpl_list);
+ if (ret)
+ return ret;
}
+
}
return 0;
}
@@ -1502,18 +1461,13 @@ void mei_timer(struct work_struct *work)
amthi_complete_list = &dev->amthi_read_complete_list.
mei_cb.cb_list;
- if (!list_empty(amthi_complete_list)) {
-
- list_for_each_entry_safe(cb_pos, cb_next,
- amthi_complete_list,
- cb_list) {
+ list_for_each_entry_safe(cb_pos, cb_next, amthi_complete_list, cb_list) {
- cl_pos = cb_pos->file_object->private_data;
+ cl_pos = cb_pos->file_object->private_data;
- /* Finding the AMTHI entry. */
- if (cl_pos == &dev->iamthif_cl)
- list_del(&cb_pos->cb_list);
- }
+ /* Finding the AMTHI entry. */
+ if (cl_pos == &dev->iamthif_cl)
+ list_del(&cb_pos->cb_list);
}
if (dev->iamthif_current_cb)
mei_free_cb_private(dev->iamthif_current_cb);
@@ -1527,8 +1481,8 @@ void mei_timer(struct work_struct *work)
}
}
out:
- schedule_delayed_work(&dev->timer_work, 2 * HZ);
- mutex_unlock(&dev->device_lock);
+ schedule_delayed_work(&dev->timer_work, 2 * HZ);
+ mutex_unlock(&dev->device_lock);
}
/**
@@ -1624,7 +1578,7 @@ end:
wake_up_interruptible(&dev->wait_recvd_msg);
bus_message_received = false;
}
- if (complete_list.status || list_empty(&complete_list.mei_cb.cb_list))
+ if (list_empty(&complete_list.mei_cb.cb_list))
return IRQ_HANDLED;
diff --git a/drivers/staging/mei/iorw.c b/drivers/staging/mei/iorw.c
index 8a61d1266515..0752ead4269a 100644
--- a/drivers/staging/mei/iorw.c
+++ b/drivers/staging/mei/iorw.c
@@ -228,18 +228,15 @@ struct mei_cl_cb *find_amthi_read_list_entry(
struct file *file)
{
struct mei_cl *cl_temp;
- struct mei_cl_cb *cb_pos = NULL;
- struct mei_cl_cb *cb_next = NULL;
-
- if (!dev->amthi_read_complete_list.status &&
- !list_empty(&dev->amthi_read_complete_list.mei_cb.cb_list)) {
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
- cl_temp = (struct mei_cl *)cb_pos->file_private;
- if (cl_temp && cl_temp == &dev->iamthif_cl &&
- cb_pos->file_object == file)
- return cb_pos;
- }
+ struct mei_cl_cb *pos = NULL;
+ struct mei_cl_cb *next = NULL;
+
+ list_for_each_entry_safe(pos, next,
+ &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
+ cl_temp = (struct mei_cl *)pos->file_private;
+ if (cl_temp && cl_temp == &dev->iamthif_cl &&
+ pos->file_object == file)
+ return pos;
}
return NULL;
}
@@ -262,7 +259,7 @@ struct mei_cl_cb *find_amthi_read_list_entry(
* negative on failure.
*/
int amthi_read(struct mei_device *dev, struct file *file,
- char __user *ubuf, size_t length, loff_t *offset)
+ char __user *ubuf, size_t length, loff_t *offset)
{
int rets;
int wait_ret;
@@ -334,8 +331,7 @@ int amthi_read(struct mei_device *dev, struct file *file,
}
}
/* if the whole message will fit remove it from the list */
- if (cb->information >= *offset &&
- length >= (cb->information - *offset))
+ if (cb->information >= *offset && length >= (cb->information - *offset))
list_del(&cb->cb_list);
else if (cb->information > 0 && cb->information <= *offset) {
/* end of the message has been reached */
@@ -356,9 +352,7 @@ int amthi_read(struct mei_device *dev, struct file *file,
* the information may be longer */
length = min_t(size_t, length, (cb->information - *offset));
- if (copy_to_user(ubuf,
- cb->response_buffer.data + *offset,
- length))
+ if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
rets = -EFAULT;
else {
rets = length;
@@ -427,7 +421,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
cb->response_buffer.data =
- kmalloc(cb->response_buffer.size, GFP_KERNEL);
+ kmalloc(cb->response_buffer.size, GFP_KERNEL);
if (!cb->response_buffer.data) {
rets = -ENOMEM;
goto unlock;
@@ -448,8 +442,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
&dev->read_list.mei_cb.cb_list);
}
} else {
- list_add_tail(&cb->cb_list,
- &dev->ctrl_wr_list.mei_cb.cb_list);
+ list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
}
return rets;
unlock:
@@ -482,7 +475,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
dev->iamthif_ioctl = true;
dev->iamthif_msg_buf_size = cb->request_buffer.size;
memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
- cb->request_buffer.size);
+ cb->request_buffer.size);
ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
if (ret < 0)
@@ -534,8 +527,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
dev_dbg(&dev->pdev->dev, "No flow control credentials, "
"so add iamthif cb to write list.\n");
- list_add_tail(&cb->cb_list,
- &dev->write_list.mei_cb.cb_list);
+ list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list);
}
return 0;
}
@@ -550,8 +542,8 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
void mei_run_next_iamthif_cmd(struct mei_device *dev)
{
struct mei_cl *cl_tmp;
- struct mei_cl_cb *cb_pos = NULL;
- struct mei_cl_cb *cb_next = NULL;
+ struct mei_cl_cb *pos = NULL;
+ struct mei_cl_cb *next = NULL;
int status;
if (!dev)
@@ -565,25 +557,22 @@ void mei_run_next_iamthif_cmd(struct mei_device *dev)
dev->iamthif_timer = 0;
dev->iamthif_file_object = NULL;
- if (dev->amthi_cmd_list.status == 0 &&
- !list_empty(&dev->amthi_cmd_list.mei_cb.cb_list)) {
- dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
-
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
- list_del(&cb_pos->cb_list);
- cl_tmp = (struct mei_cl *)cb_pos->file_private;
-
- if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
- status = amthi_write(dev, cb_pos);
- if (status) {
- dev_dbg(&dev->pdev->dev,
- "amthi write failed status = %d\n",
- status);
- return;
- }
- break;
+ dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
+
+ list_for_each_entry_safe(pos, next,
+ &dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
+ list_del(&pos->cb_list);
+ cl_tmp = (struct mei_cl *)pos->file_private;
+
+ if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
+ status = amthi_write(dev, pos);
+ if (status) {
+ dev_dbg(&dev->pdev->dev,
+ "amthi write failed status = %d\n",
+ status);
+ return;
}
+ break;
}
}
}
diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c
index eb05c36f45d4..1e1a9f996e7c 100644
--- a/drivers/staging/mei/main.c
+++ b/drivers/staging/mei/main.c
@@ -33,6 +33,7 @@
#include <linux/compat.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
+#include <linux/miscdevice.h>
#include "mei_dev.h"
#include "mei.h"
@@ -51,18 +52,10 @@ static char mei_driver_name[] = MEI_DRIVER_NAME;
static const char mei_driver_string[] = "Intel(R) Management Engine Interface";
static const char mei_driver_version[] = MEI_DRIVER_VERSION;
-/* mei char device for registration */
-static struct cdev mei_cdev;
-
-/* major number for device */
-static int mei_major;
/* The device pointer */
/* Currently this driver works as long as there is only a single AMT device. */
struct pci_dev *mei_device;
-static struct class *mei_class;
-
-
/* mei_pci_tbl - PCI Device ID Table */
static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)},
@@ -105,173 +98,6 @@ MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
static DEFINE_MUTEX(mei_mutex);
-/**
- * mei_probe - Device Initialization Routine
- *
- * @pdev: PCI device structure
- * @ent: entry in kcs_pci_tbl
- *
- * returns 0 on success, <0 on failure.
- */
-static int __devinit mei_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct mei_device *dev;
- int err;
-
- mutex_lock(&mei_mutex);
- if (mei_device) {
- err = -EEXIST;
- goto end;
- }
- /* enable pci dev */
- err = pci_enable_device(pdev);
- if (err) {
- printk(KERN_ERR "mei: Failed to enable pci device.\n");
- goto end;
- }
- /* set PCI host mastering */
- pci_set_master(pdev);
- /* pci request regions for mei driver */
- err = pci_request_regions(pdev, mei_driver_name);
- if (err) {
- printk(KERN_ERR "mei: Failed to get pci regions.\n");
- goto disable_device;
- }
- /* allocates and initializes the mei dev structure */
- dev = mei_device_init(pdev);
- if (!dev) {
- err = -ENOMEM;
- goto release_regions;
- }
- /* mapping IO device memory */
- dev->mem_addr = pci_iomap(pdev, 0, 0);
- if (!dev->mem_addr) {
- printk(KERN_ERR "mei: mapping I/O device memory failure.\n");
- err = -ENOMEM;
- goto free_device;
- }
- pci_enable_msi(pdev);
-
- /* request and enable interrupt */
- if (pci_dev_msi_enabled(pdev))
- err = request_threaded_irq(pdev->irq,
- NULL,
- mei_interrupt_thread_handler,
- 0, mei_driver_name, dev);
- else
- err = request_threaded_irq(pdev->irq,
- mei_interrupt_quick_handler,
- mei_interrupt_thread_handler,
- IRQF_SHARED, mei_driver_name, dev);
-
- if (err) {
- printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n",
- pdev->irq);
- goto unmap_memory;
- }
- INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
- if (mei_hw_init(dev)) {
- printk(KERN_ERR "mei: Init hw failure.\n");
- err = -ENODEV;
- goto release_irq;
- }
- mei_device = pdev;
- pci_set_drvdata(pdev, dev);
- schedule_delayed_work(&dev->timer_work, HZ);
-
- mutex_unlock(&mei_mutex);
-
- pr_debug("mei: Driver initialization successful.\n");
-
- return 0;
-
-release_irq:
- /* disable interrupts */
- dev->host_hw_state = mei_hcsr_read(dev);
- mei_disable_interrupts(dev);
- flush_scheduled_work();
- free_irq(pdev->irq, dev);
- pci_disable_msi(pdev);
-unmap_memory:
- pci_iounmap(pdev, dev->mem_addr);
-free_device:
- kfree(dev);
-release_regions:
- pci_release_regions(pdev);
-disable_device:
- pci_disable_device(pdev);
-end:
- mutex_unlock(&mei_mutex);
- printk(KERN_ERR "mei: Driver initialization failed.\n");
- return err;
-}
-
-/**
- * mei_remove - Device Removal Routine
- *
- * @pdev: PCI device structure
- *
- * mei_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.
- */
-static void __devexit mei_remove(struct pci_dev *pdev)
-{
- struct mei_device *dev;
-
- if (mei_device != pdev)
- return;
-
- dev = pci_get_drvdata(pdev);
- if (!dev)
- return;
-
- mutex_lock(&dev->device_lock);
-
- mei_wd_stop(dev, false);
-
- mei_device = NULL;
-
- if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
- dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
- mei_disconnect_host_client(dev, &dev->iamthif_cl);
- }
- if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
- dev->wd_cl.state = MEI_FILE_DISCONNECTING;
- mei_disconnect_host_client(dev, &dev->wd_cl);
- }
-
- /* Unregistering watchdog device */
- if (dev->wd_interface_reg)
- watchdog_unregister_device(&amt_wd_dev);
-
- /* remove entry if already in list */
- dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
- mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
- mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
-
- dev->iamthif_current_cb = NULL;
- dev->me_clients_num = 0;
-
- mutex_unlock(&dev->device_lock);
-
- flush_scheduled_work();
-
- /* disable interrupts */
- mei_disable_interrupts(dev);
-
- free_irq(pdev->irq, dev);
- pci_disable_msi(pdev);
- pci_set_drvdata(pdev, NULL);
-
- if (dev->mem_addr)
- pci_iounmap(pdev, dev->mem_addr);
-
- kfree(dev);
-
- pci_release_regions(pdev);
- pci_disable_device(pdev);
-}
/**
* mei_clear_list - removes all callbacks associated with file
@@ -372,21 +198,17 @@ static struct mei_cl_cb *find_read_list_entry(
struct mei_device *dev,
struct mei_cl *cl)
{
- struct mei_cl_cb *cb_pos = NULL;
- struct mei_cl_cb *cb_next = NULL;
-
- if (!dev->read_list.status &&
- !list_empty(&dev->read_list.mei_cb.cb_list)) {
+ struct mei_cl_cb *pos = NULL;
+ struct mei_cl_cb *next = NULL;
- dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->read_list.mei_cb.cb_list, cb_list) {
- struct mei_cl *cl_temp;
- cl_temp = (struct mei_cl *)cb_pos->file_private;
+ dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
+ list_for_each_entry_safe(pos, next,
+ &dev->read_list.mei_cb.cb_list, cb_list) {
+ struct mei_cl *cl_temp;
+ cl_temp = (struct mei_cl *)pos->file_private;
- if (mei_cl_cmp_id(cl, cl_temp))
- return cb_pos;
- }
+ if (mei_cl_cmp_id(cl, cl_temp))
+ return pos;
}
return NULL;
}
@@ -402,15 +224,16 @@ static struct mei_cl_cb *find_read_list_entry(
static int mei_open(struct inode *inode, struct file *file)
{
struct mei_cl *cl;
- int if_num = iminor(inode), err;
struct mei_device *dev;
+ unsigned long cl_id;
+ int err;
err = -ENODEV;
if (!mei_device)
goto out;
dev = pci_get_drvdata(mei_device);
- if (if_num != MEI_MINOR_NUMBER || !dev)
+ if (!dev)
goto out;
mutex_lock(&dev->device_lock);
@@ -429,14 +252,16 @@ static int mei_open(struct inode *inode, struct file *file)
if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT)
goto out_unlock;
- cl->host_client_id = find_first_zero_bit(dev->host_clients_map,
- MEI_CLIENTS_MAX);
- if (cl->host_client_id > MEI_CLIENTS_MAX)
+ cl_id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX);
+ if (cl_id >= MEI_CLIENTS_MAX)
goto out_unlock;
+ cl->host_client_id = cl_id;
+
dev_dbg(&dev->pdev->dev, "client_id = %d\n", cl->host_client_id);
dev->open_handle_count++;
+
list_add_tail(&cl->link, &dev->file_list);
set_bit(cl->host_client_id, dev->host_clients_map);
@@ -446,7 +271,7 @@ static int mei_open(struct inode *inode, struct file *file)
file->private_data = cl;
mutex_unlock(&dev->device_lock);
- return 0;
+ return nonseekable_open(inode, file);
out_unlock:
mutex_unlock(&dev->device_lock);
@@ -492,8 +317,7 @@ static int mei_release(struct inode *inode, struct file *file)
cl->me_client_id);
if (dev->open_handle_count > 0) {
- clear_bit(cl->host_client_id,
- dev->host_clients_map);
+ clear_bit(cl->host_client_id, dev->host_clients_map);
dev->open_handle_count--;
}
mei_remove_client_from_file_list(dev, cl->host_client_id);
@@ -554,7 +378,7 @@ static int mei_release(struct inode *inode, struct file *file)
* returns >=0 data length on success , <0 on error
*/
static ssize_t mei_read(struct file *file, char __user *ubuf,
- size_t length, loff_t *offset)
+ size_t length, loff_t *offset)
{
struct mei_cl *cl = file->private_data;
struct mei_cl_cb *cb_pos = NULL;
@@ -673,9 +497,7 @@ copy_buffer:
/* information size may be longer */
length = min_t(size_t, length, (cb->information - *offset));
- if (copy_to_user(ubuf,
- cb->response_buffer.data + *offset,
- length)) {
+ if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
rets = -EFAULT;
goto free;
}
@@ -711,7 +533,7 @@ out:
* returns >=0 data length on success , <0 on error
*/
static ssize_t mei_write(struct file *file, const char __user *ubuf,
- size_t length, loff_t *offset)
+ size_t length, loff_t *offset)
{
struct mei_cl *cl = file->private_data;
struct mei_cl_cb *write_cb = NULL;
@@ -762,8 +584,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
cl->read_cb = NULL;
cl->read_pending = 0;
}
- } else if (cl->reading_state == MEI_IDLE &&
- !cl->read_pending)
+ } else if (cl->reading_state == MEI_IDLE && !cl->read_pending)
*offset = 0;
@@ -1034,7 +855,7 @@ out:
*/
#ifdef CONFIG_COMPAT
static long mei_compat_ioctl(struct file *file,
- unsigned int cmd, unsigned long data)
+ unsigned int cmd, unsigned long data)
{
return mei_ioctl(file, cmd, (unsigned long)compat_ptr(data));
}
@@ -1090,6 +911,206 @@ out:
return mask;
}
+/*
+ * file operations structure will be used for mei char device.
+ */
+static const struct file_operations mei_fops = {
+ .owner = THIS_MODULE,
+ .read = mei_read,
+ .unlocked_ioctl = mei_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = mei_compat_ioctl,
+#endif
+ .open = mei_open,
+ .release = mei_release,
+ .write = mei_write,
+ .poll = mei_poll,
+ .llseek = no_llseek
+};
+
+
+/*
+ * Misc Device Struct
+ */
+static struct miscdevice mei_misc_device = {
+ .name = MEI_DRIVER_NAME,
+ .fops = &mei_fops,
+ .minor = MISC_DYNAMIC_MINOR,
+};
+
+/**
+ * mei_probe - Device Initialization Routine
+ *
+ * @pdev: PCI device structure
+ * @ent: entry in kcs_pci_tbl
+ *
+ * returns 0 on success, <0 on failure.
+ */
+static int __devinit mei_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct mei_device *dev;
+ int err;
+
+ mutex_lock(&mei_mutex);
+ if (mei_device) {
+ err = -EEXIST;
+ goto end;
+ }
+ /* enable pci dev */
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR "mei: Failed to enable pci device.\n");
+ goto end;
+ }
+ /* set PCI host mastering */
+ pci_set_master(pdev);
+ /* pci request regions for mei driver */
+ err = pci_request_regions(pdev, mei_driver_name);
+ if (err) {
+ printk(KERN_ERR "mei: Failed to get pci regions.\n");
+ goto disable_device;
+ }
+ /* allocates and initializes the mei dev structure */
+ dev = mei_device_init(pdev);
+ if (!dev) {
+ err = -ENOMEM;
+ goto release_regions;
+ }
+ /* mapping IO device memory */
+ dev->mem_addr = pci_iomap(pdev, 0, 0);
+ if (!dev->mem_addr) {
+ printk(KERN_ERR "mei: mapping I/O device memory failure.\n");
+ err = -ENOMEM;
+ goto free_device;
+ }
+ pci_enable_msi(pdev);
+
+ /* request and enable interrupt */
+ if (pci_dev_msi_enabled(pdev))
+ err = request_threaded_irq(pdev->irq,
+ NULL,
+ mei_interrupt_thread_handler,
+ 0, mei_driver_name, dev);
+ else
+ err = request_threaded_irq(pdev->irq,
+ mei_interrupt_quick_handler,
+ mei_interrupt_thread_handler,
+ IRQF_SHARED, mei_driver_name, dev);
+
+ if (err) {
+ printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n",
+ pdev->irq);
+ goto unmap_memory;
+ }
+ INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
+ if (mei_hw_init(dev)) {
+ printk(KERN_ERR "mei: Init hw failure.\n");
+ err = -ENODEV;
+ goto release_irq;
+ }
+
+ err = misc_register(&mei_misc_device);
+ if (err)
+ goto release_irq;
+
+ mei_device = pdev;
+ pci_set_drvdata(pdev, dev);
+
+
+ schedule_delayed_work(&dev->timer_work, HZ);
+
+ mutex_unlock(&mei_mutex);
+
+ pr_debug("mei: Driver initialization successful.\n");
+
+ return 0;
+
+release_irq:
+ /* disable interrupts */
+ dev->host_hw_state = mei_hcsr_read(dev);
+ mei_disable_interrupts(dev);
+ flush_scheduled_work();
+ free_irq(pdev->irq, dev);
+ pci_disable_msi(pdev);
+unmap_memory:
+ pci_iounmap(pdev, dev->mem_addr);
+free_device:
+ kfree(dev);
+release_regions:
+ pci_release_regions(pdev);
+disable_device:
+ pci_disable_device(pdev);
+end:
+ mutex_unlock(&mei_mutex);
+ printk(KERN_ERR "mei: Driver initialization failed.\n");
+ return err;
+}
+
+/**
+ * mei_remove - Device Removal Routine
+ *
+ * @pdev: PCI device structure
+ *
+ * mei_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.
+ */
+static void __devexit mei_remove(struct pci_dev *pdev)
+{
+ struct mei_device *dev;
+
+ if (mei_device != pdev)
+ return;
+
+ dev = pci_get_drvdata(pdev);
+ if (!dev)
+ return;
+
+ mutex_lock(&dev->device_lock);
+
+ mei_wd_stop(dev, false);
+
+ mei_device = NULL;
+
+ if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
+ dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
+ mei_disconnect_host_client(dev, &dev->iamthif_cl);
+ }
+ if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
+ dev->wd_cl.state = MEI_FILE_DISCONNECTING;
+ mei_disconnect_host_client(dev, &dev->wd_cl);
+ }
+
+ /* Unregistering watchdog device */
+ mei_watchdog_unregister(dev);
+
+ /* remove entry if already in list */
+ dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
+ mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
+ mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
+
+ dev->iamthif_current_cb = NULL;
+ dev->me_clients_num = 0;
+
+ mutex_unlock(&dev->device_lock);
+
+ flush_scheduled_work();
+
+ /* disable interrupts */
+ mei_disable_interrupts(dev);
+
+ free_irq(pdev->irq, dev);
+ pci_disable_msi(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+ if (dev->mem_addr)
+ pci_iounmap(pdev, dev->mem_addr);
+
+ kfree(dev);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
#ifdef CONFIG_PM
static int mei_pci_suspend(struct device *device)
{
@@ -1173,131 +1194,6 @@ static struct pci_driver mei_driver = {
.driver.pm = MEI_PM_OPS,
};
-/*
- * file operations structure will be used for mei char device.
- */
-static const struct file_operations mei_fops = {
- .owner = THIS_MODULE,
- .read = mei_read,
- .unlocked_ioctl = mei_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = mei_compat_ioctl,
-#endif
- .open = mei_open,
- .release = mei_release,
- .write = mei_write,
- .poll = mei_poll,
-};
-
-/**
- * mei_registration_cdev - sets up the cdev structure for mei device.
- *
- * @dev: char device struct
- * @hminor: minor number for registration char device
- * @fops: file operations structure
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_registration_cdev(struct cdev *dev, int hminor,
- const struct file_operations *fops)
-{
- int ret, devno = MKDEV(mei_major, hminor);
-
- cdev_init(dev, fops);
- dev->owner = THIS_MODULE;
- ret = cdev_add(dev, devno, 1);
- /* Fail gracefully if need be */
- if (ret)
- printk(KERN_ERR "mei: Error %d registering mei device %d\n",
- ret, hminor);
- return ret;
-}
-
-/**
- * mei_register_cdev - registers mei char device
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_register_cdev(void)
-{
- int ret;
- dev_t dev;
-
- /* registration of char devices */
- ret = alloc_chrdev_region(&dev, MEI_MINORS_BASE, MEI_MINORS_COUNT,
- MEI_DRIVER_NAME);
- if (ret) {
- printk(KERN_ERR "mei: Error allocating char device region.\n");
- return ret;
- }
-
- mei_major = MAJOR(dev);
-
- ret = mei_registration_cdev(&mei_cdev, MEI_MINOR_NUMBER,
- &mei_fops);
- if (ret)
- unregister_chrdev_region(MKDEV(mei_major, MEI_MINORS_BASE),
- MEI_MINORS_COUNT);
-
- return ret;
-}
-
-/**
- * mei_unregister_cdev - unregisters mei char device
- */
-static void mei_unregister_cdev(void)
-{
- cdev_del(&mei_cdev);
- unregister_chrdev_region(MKDEV(mei_major, MEI_MINORS_BASE),
- MEI_MINORS_COUNT);
-}
-
-/**
- * mei_sysfs_device_create - adds device entry to sysfs
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_sysfs_device_create(void)
-{
- struct class *class;
- void *tmphdev;
- int err;
-
- class = class_create(THIS_MODULE, MEI_DRIVER_NAME);
- if (IS_ERR(class)) {
- err = PTR_ERR(class);
- printk(KERN_ERR "mei: Error creating mei class.\n");
- goto err_out;
- }
-
- tmphdev = device_create(class, NULL, mei_cdev.dev, NULL,
- MEI_DEV_NAME);
- if (IS_ERR(tmphdev)) {
- err = PTR_ERR(tmphdev);
- goto err_destroy;
- }
-
- mei_class = class;
- return 0;
-
-err_destroy:
- class_destroy(class);
-err_out:
- return err;
-}
-
-/**
- * mei_sysfs_device_remove - unregisters the device entry on sysfs
- */
-static void mei_sysfs_device_remove(void)
-{
- if (IS_ERR_OR_NULL(mei_class))
- return;
-
- device_destroy(mei_class, mei_cdev.dev);
- class_destroy(mei_class);
-}
-
/**
* mei_init_module - Driver Registration Routine
*
@@ -1314,26 +1210,9 @@ static int __init mei_init_module(void)
mei_driver_string, mei_driver_version);
/* init pci module */
ret = pci_register_driver(&mei_driver);
- if (ret < 0) {
+ if (ret < 0)
printk(KERN_ERR "mei: Error registering driver.\n");
- goto end;
- }
- ret = mei_register_cdev();
- if (ret)
- goto unregister_pci;
-
- ret = mei_sysfs_device_create();
- if (ret)
- goto unregister_cdev;
-
- return ret;
-
-unregister_cdev:
- mei_unregister_cdev();
-unregister_pci:
- pci_unregister_driver(&mei_driver);
-end:
return ret;
}
@@ -1347,8 +1226,7 @@ module_init(mei_init_module);
*/
static void __exit mei_exit_module(void)
{
- mei_sysfs_device_remove();
- mei_unregister_cdev();
+ misc_deregister(&mei_misc_device);
pci_unregister_driver(&mei_driver);
pr_debug("mei: Driver unloaded successfully.\n");
diff --git a/drivers/staging/mei/mei.txt b/drivers/staging/mei/mei.txt
index 17302ad2531f..516bfe7319a6 100644
--- a/drivers/staging/mei/mei.txt
+++ b/drivers/staging/mei/mei.txt
@@ -1,78 +1,74 @@
-Intel MEI
+Intel(R) Management Engine Interface (Intel(R) MEI)
=======================
Introduction
=======================
-The Intel Management Engine (Intel ME) is an isolated and
-protected computing resource (Coprocessor) residing inside
-Intel chipsets. The Intel ME provides support for computer/IT
-management features.
-The Feature set depends on the Intel chipset SKU.
+The Intel Management Engine (Intel ME) is an isolated andprotected computing
+resource (Co-processor) residing inside certain Intel chipsets. The Intel ME
+provides support for computer/IT management features. The feature set
+depends on the Intel chipset SKU.
-The Intel Management Engine Interface (Intel MEI, previously known
-as HECI) is the interface between the Host and Intel ME.
-This interface is exposed to the host as a PCI device.
-The Intel MEI Driver is in charge of the communication channel
-between a host application and the ME feature.
+The Intel Management Engine Interface (Intel MEI, previously known as HECI)
+is the interface between the Host and Intel ME. This interface is exposed
+to the host as a PCI device. The Intel MEI Driver is in charge of the
+communication channel between a host application and the Intel ME feature.
-Each Intel ME feature (Intel ME Client) is addressed by
-GUID/UUID and each feature defines its own protocol.
-The protocol is message-based with a header and payload up to
-512 bytes.
+Each Intel ME feature (Intel ME Client) is addressed by a GUID/UUID and
+each client has its own protocol. The protocol is message-based with a
+header and payload up to 512 bytes.
-[place holder to URL to protocol definitions]
-
-Prominent usage of the Interface is to communicate with
-Intel Active Management Technology (Intel AMT)
-implemented in firmware running on the Intel ME.
+Prominent usage of the Intel ME Interface is to communicate with Intel(R)
+Active Management Technology (Intel AMT)implemented in firmware running on
+the Intel ME.
Intel AMT provides the ability to manage a host remotely out-of-band (OOB)
-even when the host processor has crashed or is in a sleep state.
+even when the operating system running on the host processor has crashed or
+is in a sleep state.
Some examples of Intel AMT usage are:
- Monitoring hardware state and platform components
- - Remote power off/on (useful for green computing or overnight IT maintenance)
+ - Remote power off/on (useful for green computing or overnight IT
+ maintenance)
- OS updates
- Storage of useful platform information such as software assets
- - built-in hardware KVM
- - selective network isolation of Ethernet and IP protocol flows based on
- policies set by a remote management console
+ - Built-in hardware KVM
+ - Selective network isolation of Ethernet and IP protocol flows based
+ on policies set by a remote management console
- IDE device redirection from remote management console
Intel AMT (OOB) communication is based on SOAP (deprecated
-starting with Release 6.0) over HTTP/HTTPS or WS-Management protocol
-over HTTP and HTTPS that are received from a remote
-management console application.
+starting with Release 6.0) over HTTP/S or WS-Management protocol over
+HTTP/S that are received from a remote management console application.
For more information about Intel AMT:
-http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/WordDocuments/aboutintelamt.htm
-
+http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide
-MEI Driver
+Intel MEI Driver
=======================
-The driver exposes a character device called /dev/mei.
+The driver exposes a misc device called /dev/mei.
-An application maintains communication with an ME feature while
-/dev/mei is open. The binding to a specific features is performed
-by calling MEI_CONNECT_CLIENT_IOCTL, which passes the desired UUID.
-The number of instances of an ME feature that can be opened
-at the same time depends on the ME feature, but most of the
+An application maintains communication with an Intel ME feature while
+/dev/mei is open. The binding to a specific features is performed by calling
+MEI_CONNECT_CLIENT_IOCTL, which passes the desired UUID.
+The number of instances of an Intel ME feature that can be opened
+at the same time depends on the Intel ME feature, but most of the
features allow only a single instance.
-
-The Intel AMT Host Interface (AMTHI) feature requires multiple
-simultaneous user applications, therefore the MEI driver handles
+The Intel AMT Host Interface (Intel AMTHI) feature supports multiple
+simultaneous user applications. Therefore, the Intel MEI driver handles
this internally by maintaining request queues for the applications.
-The driver is oblivious to data that are passed between
+The driver is oblivious to data that is passed between firmware feature
+and host application.
-Because some of the ME features can change the system
-configuration, the driver by default allows only privileged
+Because some of the Intel ME features can change the system
+configuration, the driver by default allows only a privileged
user to access it.
-A Code snippet for application communicating with AMTHI client:
+A code snippet for an application communicating with
+Intel AMTHI client:
struct mei_connect_client_data data;
fd = open(MEI_DEVICE);
@@ -80,7 +76,7 @@ A Code snippet for application communicating with AMTHI client:
ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &data);
- printf(“Ver=%d, MaxLen=%ld\n”,
+ printf("Ver=%d, MaxLen=%ld\n",
data.d.in_client_uuid.protocol_version,
data.d.in_client_uuid.max_msg_length);
@@ -95,76 +91,106 @@ A Code snippet for application communicating with AMTHI client:
[...]
close(fd);
-ME Applications:
+IOCTL:
+======
+The Intel MEI Driver supports the following IOCTL command:
+ IOCTL_MEI_CONNECT_CLIENT Connect to firmware Feature (client).
+
+ usage:
+ struct mei_connect_client_data clientData;
+ ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &clientData);
+
+ inputs:
+ mei_connect_client_data struct contain the following
+ input field:
+
+ in_client_uuid - UUID of the FW Feature that needs
+ to connect to.
+ outputs:
+ out_client_properties - Client Properties: MTU and Protocol Version.
+
+ error returns:
+ EINVAL Wrong IOCTL Number
+ ENODEV Device or Connection is not initialized or ready.
+ (e.g. Wrong UUID)
+ ENOMEM Unable to allocate memory to client internal data.
+ EFAULT Fatal Error (e.g. Unable to access user input data)
+ EBUSY Connection Already Open
+
+ Notes:
+ max_msg_length (MTU) in client properties describes the maximum
+ data that can be sent or received. (e.g. if MTU=2K, can send
+ requests up to bytes 2k and received responses upto 2k bytes).
+
+Intel ME Applications:
==============
1) Intel Local Management Service (Intel LMS)
- Applications running locally on the platform communicate with
- Intel AMT Release 2.0 and later releases in the same way
- that network applications do via SOAP over HTTP (deprecated
- starting with Release 6.0) or with WS-Management over SOAP over
- HTTP. which means that some Intel AMT feature can be access
- from a local application using same Network interface as for
- remote application.
-
- When a local application sends a message addressed to the local
- Intel AMT host name, the Local Manageability Service (LMS),
- which listens for traffic directed to the host name, intercepts
- the message and routes it to the Intel Management Engine Interface.
+
+ Applications running locally on the platform communicate with Intel AMT Release
+ 2.0 and later releases in the same way that network applications do via SOAP
+ over HTTP (deprecated starting with Release 6.0) or with WS-Management over
+ SOAP over HTTP. This means that some Intel AMT features can be accessed from a
+ local application using the same network interface as a remote application
+ communicating with Intel AMT over the network.
+
+ When a local application sends a message addressed to the local Intel AMT host
+ name, the Intel LMS, which listens for traffic directed to the host name,
+ intercepts the message and routes it to the Intel MEI.
For more information:
- http://software.intel.com/sites/manageability/AMT_Implementation_and_
- Reference_Guide/WordDocuments/localaccess1.htm
-
- The LMS opens a connection using the MEI driver to the LMS
- FW feature using a defined UUID and then communicates with the
- feature using a protocol
- called Intel(R) AMT Port Forwarding Protocol (APF protocol).
- The protocol is used to maintain multiple sessions with
- Intel AMT from a single application.
- See the protocol specification in
- the Intel(R) AMT Implementation and Reference Guide
- http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/HTMLDocuments/MPSDocuments/Intel%20AMT%20Port%20Forwarding%20Protocol%20Reference%20Manual.pdf
-
- 2) Intel AMT Remote configuration using a Local Agent:
+ http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide
+ Under "About Intel AMT" => "Local Access"
+
+ For downloading Intel LMS:
+ http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/
+
+ The Intel LMS opens a connection using the Intel MEI driver to the Intel LMS
+ firmware feature using a defined UUID and then communicates with the feature
+ using a protocol called Intel AMT Port Forwarding Protocol(Intel APF protocol).
+ The protocol is used to maintain multiple sessions with Intel AMT from a
+ single application.
+
+ See the protocol specification in the Intel AMT Software Development Kit(SDK)
+ http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide
+ Under "SDK Resources" => "Intel(R) vPro(TM) Gateway(MPS)"
+ => "Information for Intel(R) vPro(TM) Gateway Developers"
+ => "Description of the Intel AMT Port Forwarding (APF)Protocol"
+
+ 2) Intel AMT Remote configuration using a Local Agent
A Local Agent enables IT personnel to configure Intel AMT out-of-the-box
- without requiring installing additional data to enable setup.
- The remote configuration process may involve an ISV-developed remote
- configuration agent that runs on the host.
+ without requiring installing additional data to enable setup. The remote
+ configuration process may involve an ISV-developed remote configuration
+ agent that runs on the host.
For more information:
- http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/WordDocuments/remoteconfigurationwithalocalagent.htm
+ http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide
+ Under "Setup and Configuration of Intel AMT" =>
+ "SDK Tools Supporting Setup and Configuration" =>
+ "Using the Local Agent Sample"
+
+ An open source Intel AMT configuration utility, implementing a local agent
+ that accesses the Intel MEI driver, can be found here:
+ http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/
- How the Local Agent Works (including Command structs):
- http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/WordDocuments/howthelocalagentsampleworks.htm
Intel AMT OS Health Watchdog:
=============================
The Intel AMT Watchdog is an OS Health (Hang/Crash) watchdog.
Whenever the OS hangs or crashes, Intel AMT will send an event
-to whoever subscribed to this event. This mechanism means that
-IT knows when a platform crashes even when there is a hard failure
-on the host.
-The AMT Watchdog is composed of two parts:
- 1) FW Feature - that receives the heartbeats
- and sends an event when the heartbeats stop.
- 2) MEI driver – connects to the watchdog (WD) feature,
- configures the watchdog and sends the heartbeats.
-
-The MEI driver configures the Watchdog to expire by default
-every 120sec unless set by the user using module parameters.
-The Driver then sends heartbeats every 2sec.
+to any subsciber to this event. This mechanism means that
+IT knows when a platform crashes even when there is a hard failureon the host.
-If WD feature does not exist (i.e. the connection failed),
-the MEI driver will disable the sending of heartbeats.
+The Intel AMT Watchdog is composed of two parts:
+ 1) Firmware feature - receives the heartbeats
+ and sends an event when the heartbeats stop.
+ 2) Intel MEI driver - connects to the watchdog feature, configures the
+ watchdog and sends the heartbeats.
-Module Parameters
-=================
-watchdog_timeout - the user can use this module parameter
-to change the watchdog timeout setting.
+The Intel MEI driver uses the kernel watchdog to configure the Intel AMT
+Watchdog and to send heartbeats to it. The default timeout of the
+watchdog is 120 seconds.
-This value sets the Intel AMT watchdog timeout interval in seconds;
-the default value is 120sec.
-in order to disable the watchdog activites set the value to 0.
-Normal values should be between 120 and 65535
+If the Intel AMT Watchdog feature does not exist (i.e. the connection failed),
+the Intel MEI driver will disable the sending of heartbeats.
Supported Chipsets:
==================
diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h
index af4b1af9eeac..82bacfc624c5 100644
--- a/drivers/staging/mei/mei_dev.h
+++ b/drivers/staging/mei/mei_dev.h
@@ -23,13 +23,6 @@
#include "hw.h"
/*
- * MEI Char Driver Minors
- */
-#define MEI_MINORS_BASE 1
-#define MEI_MINORS_COUNT 1
-#define MEI_MINOR_NUMBER 1
-
-/*
* watch dog definition
*/
#define MEI_WATCHDOG_DATA_SIZE 16
@@ -42,11 +35,6 @@
*/
extern struct pci_dev *mei_device;
-/*
- * AMT Watchdog Device
- */
-#define INTEL_AMT_WATCHDOG_ID "INTCAMT"
-extern struct watchdog_device amt_wd_dev;
/*
* AMTHI Client UUID
@@ -175,7 +163,6 @@ struct mei_cl {
struct mei_io_list {
struct mei_cl_cb mei_cb;
- int status;
};
/* MEI private device struct */
diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c
index ffca7ca32658..8094941a98f1 100644
--- a/drivers/staging/mei/wd.c
+++ b/drivers/staging/mei/wd.c
@@ -35,12 +35,16 @@ const u8 mei_wd_state_independence_msg[3][4] = {
{0x07, 0x02, 0x01, 0x10}
};
+/*
+ * AMT Watchdog Device
+ */
+#define INTEL_AMT_WATCHDOG_ID "INTCAMT"
+
/* UUIDs for AMT F/W clients */
const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89,
0x9D, 0xA9, 0x15, 0x14, 0xCB,
0x32, 0xAB);
-
void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
{
dev_dbg(&dev->pdev->dev, "timeout=%d.\n", timeout);
@@ -331,14 +335,14 @@ static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int t
/*
* Watchdog Device structs
*/
-const struct watchdog_ops wd_ops = {
+static const struct watchdog_ops wd_ops = {
.owner = THIS_MODULE,
.start = mei_wd_ops_start,
.stop = mei_wd_ops_stop,
.ping = mei_wd_ops_ping,
.set_timeout = mei_wd_ops_set_timeout,
};
-const struct watchdog_info wd_info = {
+static const struct watchdog_info wd_info = {
.identity = INTEL_AMT_WATCHDOG_ID,
.options = WDIOF_KEEPALIVEPING,
};
@@ -352,3 +356,25 @@ struct watchdog_device amt_wd_dev = {
};
+void mei_watchdog_register(struct mei_device *dev)
+{
+ dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout);
+
+ dev->wd_due_counter = !!dev->wd_timeout;
+
+ if (watchdog_register_device(&amt_wd_dev)) {
+ dev_err(&dev->pdev->dev, "unable to register watchdog device.\n");
+ dev->wd_interface_reg = false;
+ } else {
+ dev_dbg(&dev->pdev->dev, "successfully register watchdog interface.\n");
+ dev->wd_interface_reg = true;
+ }
+}
+
+void mei_watchdog_unregister(struct mei_device *dev)
+{
+ if (dev->wd_interface_reg)
+ watchdog_unregister_device(&amt_wd_dev);
+ dev->wd_interface_reg = false;
+}
+
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index e06b867d1e0c..fafdfa25e139 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -27,6 +27,8 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/list.h>
#include <linux/mfd/core.h>
#include <linux/mutex.h>
@@ -727,8 +729,24 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, nvec);
nvec->dev = &pdev->dev;
- nvec->gpio = pdata->gpio;
- nvec->i2c_addr = pdata->i2c_addr;
+
+ if (pdata) {
+ nvec->gpio = pdata->gpio;
+ nvec->i2c_addr = pdata->i2c_addr;
+ } else if (nvec->dev->of_node) {
+ nvec->gpio = of_get_named_gpio(nvec->dev->of_node, "request-gpios", 0);
+ if (nvec->gpio < 0) {
+ dev_err(&pdev->dev, "no gpio specified");
+ goto failed;
+ }
+ if (of_property_read_u32(nvec->dev->of_node, "slave-addr", &nvec->i2c_addr)) {
+ dev_err(&pdev->dev, "no i2c address specified");
+ goto failed;
+ }
+ } else {
+ dev_err(&pdev->dev, "no platform data\n");
+ goto failed;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -893,6 +911,13 @@ static int tegra_nvec_resume(struct platform_device *pdev)
#define tegra_nvec_resume NULL
#endif
+/* Match table for of_platform binding */
+static const struct of_device_id nvidia_nvec_of_match[] __devinitconst = {
+ { .compatible = "nvidia,nvec", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, nvidia_nvec_of_match);
+
static struct platform_driver nvec_device_driver = {
.probe = tegra_nvec_probe,
.remove = __devexit_p(tegra_nvec_remove),
@@ -901,6 +926,7 @@ static struct platform_driver nvec_device_driver = {
.driver = {
.name = "nvec",
.owner = THIS_MODULE,
+ .of_match_table = nvidia_nvec_of_match,
}
};
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index af24ddfb58c9..3d9199320d86 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -34,8 +34,8 @@
/* Module definitions */
-static int resumeline = 898;
-module_param(resumeline, int, 0444);
+static ushort resumeline = 898;
+module_param(resumeline, ushort, 0444);
/* Default off since it doesn't work on DCON ASIC in B-test OLPC board */
static int useaa = 1;
@@ -456,7 +456,7 @@ static ssize_t dcon_mono_store(struct device *dev,
unsigned long enable_mono;
int rc;
- rc = strict_strtoul(buf, 10, &enable_mono);
+ rc = kstrtoul(buf, 10, &enable_mono);
if (rc)
return rc;
@@ -472,7 +472,7 @@ static ssize_t dcon_freeze_store(struct device *dev,
unsigned long output;
int ret;
- ret = strict_strtoul(buf, 10, &output);
+ ret = kstrtoul(buf, 10, &output);
if (ret)
return ret;
@@ -498,10 +498,10 @@ static ssize_t dcon_freeze_store(struct device *dev,
static ssize_t dcon_resumeline_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- unsigned long rl;
+ unsigned short rl;
int rc;
- rc = strict_strtoul(buf, 10, &rl);
+ rc = kstrtou16(buf, 10, &rl);
if (rc)
return rc;
@@ -517,7 +517,7 @@ static ssize_t dcon_sleep_store(struct device *dev,
unsigned long output;
int ret;
- ret = strict_strtoul(buf, 10, &output);
+ ret = kstrtoul(buf, 10, &output);
if (ret)
return ret;
@@ -755,9 +755,9 @@ static int dcon_resume(struct i2c_client *client)
irqreturn_t dcon_interrupt(int irq, void *id)
{
struct dcon_priv *dcon = id;
- int status = pdata->read_status();
+ u8 status;
- if (status == -1)
+ if (pdata->read_status(&status))
return IRQ_NONE;
switch (status & 3) {
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h
index 0264c94375aa..167a41778be6 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.h
+++ b/drivers/staging/olpc_dcon/olpc_dcon.h
@@ -84,7 +84,7 @@ struct dcon_platform_data {
int (*init)(struct dcon_priv *);
void (*bus_stabilize_wiggle)(void);
void (*set_dconload)(int);
- u8 (*read_status)(void);
+ int (*read_status)(u8 *);
};
#include <linux/interrupt.h>
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
index 2245213df607..cb6ce0cf92a0 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
@@ -183,17 +183,15 @@ static void dcon_set_dconload_1(int val)
gpio_set_value(OLPC_GPIO_DCON_LOAD, val);
}
-static u8 dcon_read_status_xo_1(void)
+static int dcon_read_status_xo_1(u8 *status)
{
- u8 status;
-
- status = gpio_get_value(OLPC_GPIO_DCON_STAT0);
- status |= gpio_get_value(OLPC_GPIO_DCON_STAT1) << 1;
+ *status = gpio_get_value(OLPC_GPIO_DCON_STAT0);
+ *status |= gpio_get_value(OLPC_GPIO_DCON_STAT1) << 1;
/* Clear the negative edge status for GPIO7 */
cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS);
- return status;
+ return 0;
}
struct dcon_platform_data dcon_pdata_xo_1 = {
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
index a6a6cf2adc4d..69415eec425c 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
@@ -167,20 +167,18 @@ static void dcon_set_dconload_xo_1_5(int val)
gpio_set_value(VX855_GPIO(1), val);
}
-static u8 dcon_read_status_xo_1_5(void)
+static int dcon_read_status_xo_1_5(u8 *status)
{
- u8 status;
-
if (!dcon_was_irq())
return -1;
/* i believe this is the same as "inb(0x44b) & 3" */
- status = gpio_get_value(VX855_GPI(10));
- status |= gpio_get_value(VX855_GPI(11)) << 1;
+ *status = gpio_get_value(VX855_GPI(10));
+ *status |= gpio_get_value(VX855_GPI(11)) << 1;
dcon_clear_irq();
- return status;
+ return 0;
}
struct dcon_platform_data dcon_pdata_xo_1_5 = {
diff --git a/drivers/staging/omapdrm/Kconfig b/drivers/staging/omapdrm/Kconfig
new file mode 100644
index 000000000000..81a7cba4a0c5
--- /dev/null
+++ b/drivers/staging/omapdrm/Kconfig
@@ -0,0 +1,25 @@
+
+config DRM_OMAP
+ tristate "OMAP DRM"
+ depends on DRM && !CONFIG_FB_OMAP2
+ depends on ARCH_OMAP2PLUS
+ select DRM_KMS_HELPER
+ select OMAP2_DSS
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ default n
+ help
+ DRM display driver for OMAP2/3/4 based boards.
+
+config DRM_OMAP_NUM_CRTCS
+ int "Number of CRTCs"
+ range 1 10
+ default 1 if ARCH_OMAP2 || ARCH_OMAP3
+ default 2 if ARCH_OMAP4
+ depends on DRM_OMAP
+ help
+ Select the number of video overlays which can be used as framebuffers.
+ The remaining overlays are reserved for video.
+
diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile
new file mode 100644
index 000000000000..592cf69020cd
--- /dev/null
+++ b/drivers/staging/omapdrm/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the drm device driver. This driver provides support for the
+# Direct Rendering Infrastructure (DRI)
+#
+
+ccflags-y := -Iinclude/drm -Werror
+omapdrm-y := omap_drv.o \
+ omap_debugfs.o \
+ omap_crtc.o \
+ omap_encoder.o \
+ omap_connector.o \
+ omap_fb.o \
+ omap_fbdev.o \
+ omap_gem.o \
+ omap_dmm_tiler.o \
+ tcm-sita.o
+
+# temporary:
+omapdrm-y += omap_gem_helpers.o
+
+obj-$(CONFIG_DRM_OMAP) += omapdrm.o
diff --git a/drivers/staging/omapdrm/TODO b/drivers/staging/omapdrm/TODO
new file mode 100644
index 000000000000..55b18377ac4f
--- /dev/null
+++ b/drivers/staging/omapdrm/TODO
@@ -0,0 +1,38 @@
+TODO
+. check error handling/cleanup paths
+. add drm_plane / overlay support
+. add video decode/encode support (via syslink3 + codec-engine)
+. still some rough edges with flipping.. event back to userspace should
+ really come after VSYNC interrupt
+. where should we do eviction (detatch_pages())? We aren't necessarily
+ accessing the pages via a GART, so maybe we need some other threshold
+ to put a cap on the # of pages that can be pin'd. (It is mostly only
+ of interest in case you have a swap partition/file.. which a lot of
+ these devices do not.. but it doesn't hurt for the driver to do the
+ right thing anyways.)
+ . Use mm_shrinker to trigger unpinning pages. Need to figure out how
+ to handle next issue first (I think?)
+ . Note TTM already has some mm_shrinker stuff.. maybe an argument to
+ move to TTM? Or maybe something that could be factored out in common?
+. GEM/shmem backed pages can have existing mappings (kernel linear map,
+ etc..), which isn't really ideal.
+. Revisit GEM sync object infrastructure.. TTM has some framework for this
+ already. Possibly this could be refactored out and made more common?
+ There should be some way to do this with less wheel-reinvention.
+. Review DSS vs KMS mismatches. The omap_dss_device is sort of part encoder,
+ part connector. Which results in a bit of duct tape to fwd calls from
+ encoder to connector. Possibly this could be done a bit better.
+. Solve PM sequencing on resume. DMM/TILER must be reloaded before any
+ access is made from any component in the system. Which means on suspend
+ CRTC's should be disabled, and on resume the LUT should be reprogrammed
+ before CRTC's are re-enabled, to prevent DSS from trying to DMA from a
+ buffer mapped in DMM/TILER before LUT is reloaded.
+. Add debugfs information for DMM/TILER
+
+Userspace:
+. git://github.com/robclark/xf86-video-omap.git
+
+Currently tested on
+. OMAP3530 beagleboard
+. OMAP4430 pandaboard
+. OMAP4460 pandaboard
diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c
new file mode 100644
index 000000000000..5e2856c0e0bb
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_connector.c
@@ -0,0 +1,371 @@
+/*
+ * drivers/staging/omapdrm/omap_connector.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+/*
+ * connector funcs
+ */
+
+#define to_omap_connector(x) container_of(x, struct omap_connector, base)
+
+struct omap_connector {
+ struct drm_connector base;
+ struct omap_dss_device *dssdev;
+};
+
+static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
+ struct omap_video_timings *timings)
+{
+ mode->clock = timings->pixel_clock;
+
+ mode->hdisplay = timings->x_res;
+ mode->hsync_start = mode->hdisplay + timings->hfp;
+ mode->hsync_end = mode->hsync_start + timings->hsw;
+ mode->htotal = mode->hsync_end + timings->hbp;
+
+ mode->vdisplay = timings->y_res;
+ mode->vsync_start = mode->vdisplay + timings->vfp;
+ mode->vsync_end = mode->vsync_start + timings->vsw;
+ mode->vtotal = mode->vsync_end + timings->vbp;
+
+ /* note: whether or not it is interlaced, +/- h/vsync, etc,
+ * which should be set in the mode flags, is not exposed in
+ * the omap_video_timings struct.. but hdmi driver tracks
+ * those separately so all we have to have to set the mode
+ * is the way to recover these timings values, and the
+ * omap_dss_driver would do the rest.
+ */
+}
+
+static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
+ struct drm_display_mode *mode)
+{
+ timings->pixel_clock = mode->clock;
+
+ timings->x_res = mode->hdisplay;
+ timings->hfp = mode->hsync_start - mode->hdisplay;
+ timings->hsw = mode->hsync_end - mode->hsync_start;
+ timings->hbp = mode->htotal - mode->hsync_end;
+
+ timings->y_res = mode->vdisplay;
+ timings->vfp = mode->vsync_start - mode->vdisplay;
+ timings->vsw = mode->vsync_end - mode->vsync_start;
+ timings->vbp = mode->vtotal - mode->vsync_end;
+}
+
+static void omap_connector_dpms(struct drm_connector *connector, int mode)
+{
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+ struct omap_dss_device *dssdev = omap_connector->dssdev;
+ int old_dpms;
+
+ DBG("%s: %d", dssdev->name, mode);
+
+ old_dpms = connector->dpms;
+
+ /* from off to on, do from crtc to connector */
+ if (mode < old_dpms)
+ drm_helper_connector_dpms(connector, mode);
+
+ if (mode == DRM_MODE_DPMS_ON) {
+ /* store resume info for suspended displays */
+ switch (dssdev->state) {
+ case OMAP_DSS_DISPLAY_SUSPENDED:
+ dssdev->activate_after_resume = true;
+ break;
+ case OMAP_DSS_DISPLAY_DISABLED: {
+ int ret = dssdev->driver->enable(dssdev);
+ if (ret) {
+ DBG("%s: failed to enable: %d",
+ dssdev->name, ret);
+ dssdev->driver->disable(dssdev);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ } else {
+ /* TODO */
+ }
+
+ /* from on to off, do from connector to crtc */
+ if (mode > old_dpms)
+ drm_helper_connector_dpms(connector, mode);
+}
+
+enum drm_connector_status omap_connector_detect(
+ struct drm_connector *connector, bool force)
+{
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+ struct omap_dss_device *dssdev = omap_connector->dssdev;
+ struct omap_dss_driver *dssdrv = dssdev->driver;
+ enum drm_connector_status ret;
+
+ if (dssdrv->detect) {
+ if (dssdrv->detect(dssdev)) {
+ ret = connector_status_connected;
+ } else {
+ ret = connector_status_disconnected;
+ }
+ } else {
+ ret = connector_status_unknown;
+ }
+
+ VERB("%s: %d (force=%d)", omap_connector->dssdev->name, ret, force);
+
+ return ret;
+}
+
+static void omap_connector_destroy(struct drm_connector *connector)
+{
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+ struct omap_dss_device *dssdev = omap_connector->dssdev;
+
+ dssdev->driver->disable(dssdev);
+
+ DBG("%s", omap_connector->dssdev->name);
+ drm_sysfs_connector_remove(connector);
+ drm_connector_cleanup(connector);
+ kfree(omap_connector);
+
+ omap_dss_put_device(dssdev);
+}
+
+#define MAX_EDID 512
+
+static int omap_connector_get_modes(struct drm_connector *connector)
+{
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+ struct omap_dss_device *dssdev = omap_connector->dssdev;
+ struct omap_dss_driver *dssdrv = dssdev->driver;
+ struct drm_device *dev = connector->dev;
+ int n = 0;
+
+ DBG("%s", omap_connector->dssdev->name);
+
+ /* if display exposes EDID, then we parse that in the normal way to
+ * build table of supported modes.. otherwise (ie. fixed resolution
+ * LCD panels) we just return a single mode corresponding to the
+ * currently configured timings:
+ */
+ if (dssdrv->read_edid) {
+ void *edid = kzalloc(MAX_EDID, GFP_KERNEL);
+
+ if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) &&
+ drm_edid_is_valid(edid)) {
+ drm_mode_connector_update_edid_property(
+ connector, edid);
+ n = drm_add_edid_modes(connector, edid);
+ kfree(connector->display_info.raw_edid);
+ connector->display_info.raw_edid = edid;
+ } else {
+ drm_mode_connector_update_edid_property(
+ connector, NULL);
+ connector->display_info.raw_edid = NULL;
+ kfree(edid);
+ }
+ } else {
+ struct drm_display_mode *mode = drm_mode_create(dev);
+ struct omap_video_timings timings;
+
+ dssdrv->get_timings(dssdev, &timings);
+
+ copy_timings_omap_to_drm(mode, &timings);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+
+ n = 1;
+ }
+
+ return n;
+}
+
+static int omap_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+ struct omap_dss_device *dssdev = omap_connector->dssdev;
+ struct omap_dss_driver *dssdrv = dssdev->driver;
+ struct omap_video_timings timings = {0};
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *new_mode;
+ int ret = MODE_BAD;
+
+ copy_timings_drm_to_omap(&timings, mode);
+ mode->vrefresh = drm_mode_vrefresh(mode);
+
+ if (!dssdrv->check_timings(dssdev, &timings)) {
+ /* check if vrefresh is still valid */
+ new_mode = drm_mode_duplicate(dev, mode);
+ new_mode->clock = timings.pixel_clock;
+ new_mode->vrefresh = 0;
+ if (mode->vrefresh == drm_mode_vrefresh(new_mode))
+ ret = MODE_OK;
+ drm_mode_destroy(dev, new_mode);
+ }
+
+ DBG("connector: mode %s: "
+ "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+ (ret == MODE_OK) ? "valid" : "invalid",
+ mode->base.id, mode->name, mode->vrefresh, mode->clock,
+ mode->hdisplay, mode->hsync_start,
+ mode->hsync_end, mode->htotal,
+ mode->vdisplay, mode->vsync_start,
+ mode->vsync_end, mode->vtotal, mode->type, mode->flags);
+
+ return ret;
+}
+
+struct drm_encoder *omap_connector_attached_encoder(
+ struct drm_connector *connector)
+{
+ int i;
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+
+ for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+ struct drm_mode_object *obj;
+
+ if (connector->encoder_ids[i] == 0)
+ break;
+
+ obj = drm_mode_object_find(connector->dev,
+ connector->encoder_ids[i],
+ DRM_MODE_OBJECT_ENCODER);
+
+ if (obj) {
+ struct drm_encoder *encoder = obj_to_encoder(obj);
+ struct omap_overlay_manager *mgr =
+ omap_encoder_get_manager(encoder);
+ DBG("%s: found %s", omap_connector->dssdev->name,
+ mgr->name);
+ return encoder;
+ }
+ }
+
+ DBG("%s: no encoder", omap_connector->dssdev->name);
+
+ return NULL;
+}
+
+static const struct drm_connector_funcs omap_connector_funcs = {
+ .dpms = omap_connector_dpms,
+ .detect = omap_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = omap_connector_destroy,
+};
+
+static const struct drm_connector_helper_funcs omap_connector_helper_funcs = {
+ .get_modes = omap_connector_get_modes,
+ .mode_valid = omap_connector_mode_valid,
+ .best_encoder = omap_connector_attached_encoder,
+};
+
+/* called from encoder when mode is set, to propagate settings to the dssdev */
+void omap_connector_mode_set(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ struct drm_device *dev = connector->dev;
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+ struct omap_dss_device *dssdev = omap_connector->dssdev;
+ struct omap_dss_driver *dssdrv = dssdev->driver;
+ struct omap_video_timings timings;
+
+ copy_timings_drm_to_omap(&timings, mode);
+
+ DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+ omap_connector->dssdev->name,
+ mode->base.id, mode->name, mode->vrefresh, mode->clock,
+ mode->hdisplay, mode->hsync_start,
+ mode->hsync_end, mode->htotal,
+ mode->vdisplay, mode->vsync_start,
+ mode->vsync_end, mode->vtotal, mode->type, mode->flags);
+
+ if (dssdrv->check_timings(dssdev, &timings)) {
+ dev_err(dev->dev, "could not set timings\n");
+ return;
+ }
+
+ dssdrv->set_timings(dssdev, &timings);
+}
+
+/* flush an area of the framebuffer (in case of manual update display that
+ * is not automatically flushed)
+ */
+void omap_connector_flush(struct drm_connector *connector,
+ int x, int y, int w, int h)
+{
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+
+ /* TODO: enable when supported in dss */
+ VERB("%s: %d,%d, %dx%d", omap_connector->dssdev->name, x, y, w, h);
+}
+
+/* initialize connector */
+struct drm_connector *omap_connector_init(struct drm_device *dev,
+ int connector_type, struct omap_dss_device *dssdev)
+{
+ struct drm_connector *connector = NULL;
+ struct omap_connector *omap_connector;
+
+ DBG("%s", dssdev->name);
+
+ omap_dss_get_device(dssdev);
+
+ omap_connector = kzalloc(sizeof(struct omap_connector), GFP_KERNEL);
+ if (!omap_connector) {
+ dev_err(dev->dev, "could not allocate connector\n");
+ goto fail;
+ }
+
+ omap_connector->dssdev = dssdev;
+ connector = &omap_connector->base;
+
+ drm_connector_init(dev, connector, &omap_connector_funcs,
+ connector_type);
+ drm_connector_helper_add(connector, &omap_connector_helper_funcs);
+
+#if 0 /* enable when dss2 supports hotplug */
+ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_HPD)
+ connector->polled = 0;
+ else
+#endif
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT;
+
+ connector->interlace_allowed = 1;
+ connector->doublescan_allowed = 0;
+
+ drm_sysfs_connector_add(connector);
+
+ return connector;
+
+fail:
+ if (connector) {
+ omap_connector_destroy(connector);
+ }
+
+ return NULL;
+}
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c
new file mode 100644
index 000000000000..cffdf5e12394
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_crtc.c
@@ -0,0 +1,326 @@
+/*
+ * drivers/staging/omapdrm/omap_crtc.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+#include "drm_mode.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+#define to_omap_crtc(x) container_of(x, struct omap_crtc, base)
+
+struct omap_crtc {
+ struct drm_crtc base;
+ struct omap_overlay *ovl;
+ struct omap_overlay_info info;
+ int id;
+
+ /* if there is a pending flip, this will be non-null: */
+ struct drm_pending_vblank_event *event;
+};
+
+/* push changes down to dss2 */
+static int commit(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ struct omap_overlay *ovl = omap_crtc->ovl;
+ struct omap_overlay_info *info = &omap_crtc->info;
+ int ret;
+
+ DBG("%s", omap_crtc->ovl->name);
+ DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width,
+ info->out_height, info->screen_width);
+ DBG("%d,%d %08x", info->pos_x, info->pos_y, info->paddr);
+
+ /* NOTE: do we want to do this at all here, or just wait
+ * for dpms(ON) since other CRTC's may not have their mode
+ * set yet, so fb dimensions may still change..
+ */
+ ret = ovl->set_overlay_info(ovl, info);
+ if (ret) {
+ dev_err(dev->dev, "could not set overlay info\n");
+ return ret;
+ }
+
+ /* our encoder doesn't necessarily get a commit() after this, in
+ * particular in the dpms() and mode_set_base() cases, so force the
+ * manager to update:
+ *
+ * could this be in the encoder somehow?
+ */
+ if (ovl->manager) {
+ ret = ovl->manager->apply(ovl->manager);
+ if (ret) {
+ dev_err(dev->dev, "could not apply settings\n");
+ return ret;
+ }
+ }
+
+ if (info->enabled) {
+ omap_framebuffer_flush(crtc->fb, crtc->x, crtc->y,
+ crtc->fb->width, crtc->fb->height);
+ }
+
+ return 0;
+}
+
+/* update parameters that are dependent on the framebuffer dimensions and
+ * position within the fb that this crtc scans out from. This is called
+ * when framebuffer dimensions or x,y base may have changed, either due
+ * to our mode, or a change in another crtc that is scanning out of the
+ * same fb.
+ */
+static void update_scanout(struct drm_crtc *crtc)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ dma_addr_t paddr;
+ unsigned int screen_width;
+
+ omap_framebuffer_get_buffer(crtc->fb, crtc->x, crtc->y,
+ NULL, &paddr, &screen_width);
+
+ DBG("%s: %d,%d: %08x (%d)", omap_crtc->ovl->name,
+ crtc->x, crtc->y, (u32)paddr, screen_width);
+
+ omap_crtc->info.paddr = paddr;
+ omap_crtc->info.screen_width = screen_width;
+}
+
+static void omap_crtc_gamma_set(struct drm_crtc *crtc,
+ u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ DBG("%s", omap_crtc->ovl->name);
+}
+
+static void omap_crtc_destroy(struct drm_crtc *crtc)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ DBG("%s", omap_crtc->ovl->name);
+ drm_crtc_cleanup(crtc);
+ kfree(omap_crtc);
+}
+
+static void omap_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+
+ DBG("%s: %d", omap_crtc->ovl->name, mode);
+
+ if (mode == DRM_MODE_DPMS_ON) {
+ update_scanout(crtc);
+ omap_crtc->info.enabled = true;
+ } else {
+ omap_crtc->info.enabled = false;
+ }
+
+ WARN_ON(commit(crtc));
+}
+
+static bool omap_crtc_mode_fixup(struct drm_crtc *crtc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ DBG("%s", omap_crtc->ovl->name);
+ return true;
+}
+
+static int omap_crtc_mode_set(struct drm_crtc *crtc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode,
+ int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+
+ DBG("%s: %d,%d: %dx%d", omap_crtc->ovl->name, x, y,
+ mode->hdisplay, mode->vdisplay);
+
+ /* just use adjusted mode */
+ mode = adjusted_mode;
+
+ omap_crtc->info.width = mode->hdisplay;
+ omap_crtc->info.height = mode->vdisplay;
+ omap_crtc->info.out_width = mode->hdisplay;
+ omap_crtc->info.out_height = mode->vdisplay;
+ omap_crtc->info.color_mode = OMAP_DSS_COLOR_RGB24U;
+ omap_crtc->info.rotation_type = OMAP_DSS_ROT_DMA;
+ omap_crtc->info.rotation = OMAP_DSS_ROT_0;
+ omap_crtc->info.global_alpha = 0xff;
+ omap_crtc->info.mirror = 0;
+ omap_crtc->info.mirror = 0;
+ omap_crtc->info.pos_x = 0;
+ omap_crtc->info.pos_y = 0;
+#if 0 /* re-enable when these are available in DSS2 driver */
+ omap_crtc->info.zorder = 3; /* GUI in the front, video behind */
+ omap_crtc->info.min_x_decim = 1;
+ omap_crtc->info.max_x_decim = 1;
+ omap_crtc->info.min_y_decim = 1;
+ omap_crtc->info.max_y_decim = 1;
+#endif
+
+ update_scanout(crtc);
+
+ return 0;
+}
+
+static void omap_crtc_prepare(struct drm_crtc *crtc)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ struct omap_overlay *ovl = omap_crtc->ovl;
+
+ DBG("%s", omap_crtc->ovl->name);
+
+ ovl->get_overlay_info(ovl, &omap_crtc->info);
+
+ omap_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void omap_crtc_commit(struct drm_crtc *crtc)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ DBG("%s", omap_crtc->ovl->name);
+ omap_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+
+ DBG("%s %d,%d: fb=%p", omap_crtc->ovl->name, x, y, old_fb);
+
+ update_scanout(crtc);
+
+ return commit(crtc);
+}
+
+static void omap_crtc_load_lut(struct drm_crtc *crtc)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ DBG("%s", omap_crtc->ovl->name);
+}
+
+static void page_flip_cb(void *arg)
+{
+ struct drm_crtc *crtc = arg;
+ struct drm_device *dev = crtc->dev;
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ struct drm_pending_vblank_event *event = omap_crtc->event;
+ struct timeval now;
+ unsigned long flags;
+
+ WARN_ON(!event);
+
+ omap_crtc->event = NULL;
+
+ update_scanout(crtc);
+ WARN_ON(commit(crtc));
+
+ /* wakeup userspace */
+ /* TODO: this should happen *after* flip in vsync IRQ handler */
+ if (event) {
+ spin_lock_irqsave(&dev->event_lock, flags);
+ event->event.sequence = drm_vblank_count_and_time(
+ dev, omap_crtc->id, &now);
+ event->event.tv_sec = now.tv_sec;
+ event->event.tv_usec = now.tv_usec;
+ list_add_tail(&event->base.link,
+ &event->base.file_priv->event_list);
+ wake_up_interruptible(&event->base.file_priv->event_wait);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
+}
+
+static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event)
+{
+ struct drm_device *dev = crtc->dev;
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+
+ DBG("%d -> %d", crtc->fb ? crtc->fb->base.id : -1, fb->base.id);
+
+ if (omap_crtc->event) {
+ dev_err(dev->dev, "already a pending flip\n");
+ return -EINVAL;
+ }
+
+ crtc->fb = fb;
+ omap_crtc->event = event;
+
+ omap_gem_op_async(omap_framebuffer_bo(fb), OMAP_GEM_READ,
+ page_flip_cb, crtc);
+
+ return 0;
+}
+
+static const struct drm_crtc_funcs omap_crtc_funcs = {
+ .gamma_set = omap_crtc_gamma_set,
+ .set_config = drm_crtc_helper_set_config,
+ .destroy = omap_crtc_destroy,
+ .page_flip = omap_crtc_page_flip_locked,
+};
+
+static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
+ .dpms = omap_crtc_dpms,
+ .mode_fixup = omap_crtc_mode_fixup,
+ .mode_set = omap_crtc_mode_set,
+ .prepare = omap_crtc_prepare,
+ .commit = omap_crtc_commit,
+ .mode_set_base = omap_crtc_mode_set_base,
+ .load_lut = omap_crtc_load_lut,
+};
+
+struct omap_overlay *omap_crtc_get_overlay(struct drm_crtc *crtc)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ return omap_crtc->ovl;
+}
+
+/* initialize crtc */
+struct drm_crtc *omap_crtc_init(struct drm_device *dev,
+ struct omap_overlay *ovl, int id)
+{
+ struct drm_crtc *crtc = NULL;
+ struct omap_crtc *omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
+
+ DBG("%s", ovl->name);
+
+ if (!omap_crtc) {
+ dev_err(dev->dev, "could not allocate CRTC\n");
+ goto fail;
+ }
+
+ omap_crtc->ovl = ovl;
+ omap_crtc->id = id;
+ crtc = &omap_crtc->base;
+ drm_crtc_init(dev, crtc, &omap_crtc_funcs);
+ drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
+
+ return crtc;
+
+fail:
+ if (crtc) {
+ omap_crtc_destroy(crtc);
+ }
+ return NULL;
+}
diff --git a/drivers/staging/omapdrm/omap_debugfs.c b/drivers/staging/omapdrm/omap_debugfs.c
new file mode 100644
index 000000000000..da920dfdc59c
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_debugfs.c
@@ -0,0 +1,42 @@
+/*
+ * drivers/staging/omapdrm/omap_debugfs.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+#include "omap_dmm_tiler.h"
+
+#ifdef CONFIG_DEBUG_FS
+
+static struct drm_info_list omap_debugfs_list[] = {
+ {"tiler_map", tiler_map_show, 0},
+};
+
+int omap_debugfs_init(struct drm_minor *minor)
+{
+ return drm_debugfs_create_files(omap_debugfs_list,
+ ARRAY_SIZE(omap_debugfs_list),
+ minor->debugfs_root, minor);
+}
+
+void omap_debugfs_cleanup(struct drm_minor *minor)
+{
+ drm_debugfs_remove_files(omap_debugfs_list,
+ ARRAY_SIZE(omap_debugfs_list), minor);
+}
+
+#endif
diff --git a/drivers/staging/omapdrm/omap_dmm_priv.h b/drivers/staging/omapdrm/omap_dmm_priv.h
new file mode 100644
index 000000000000..2f529ab4b7c7
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_dmm_priv.h
@@ -0,0 +1,187 @@
+/*
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Rob Clark <rob@ti.com>
+ * Andy Gross <andy.gross@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef OMAP_DMM_PRIV_H
+#define OMAP_DMM_PRIV_H
+
+#define DMM_REVISION 0x000
+#define DMM_HWINFO 0x004
+#define DMM_LISA_HWINFO 0x008
+#define DMM_DMM_SYSCONFIG 0x010
+#define DMM_LISA_LOCK 0x01C
+#define DMM_LISA_MAP__0 0x040
+#define DMM_LISA_MAP__1 0x044
+#define DMM_TILER_HWINFO 0x208
+#define DMM_TILER_OR__0 0x220
+#define DMM_TILER_OR__1 0x224
+#define DMM_PAT_HWINFO 0x408
+#define DMM_PAT_GEOMETRY 0x40C
+#define DMM_PAT_CONFIG 0x410
+#define DMM_PAT_VIEW__0 0x420
+#define DMM_PAT_VIEW__1 0x424
+#define DMM_PAT_VIEW_MAP__0 0x440
+#define DMM_PAT_VIEW_MAP_BASE 0x460
+#define DMM_PAT_IRQ_EOI 0x478
+#define DMM_PAT_IRQSTATUS_RAW 0x480
+#define DMM_PAT_IRQSTATUS 0x490
+#define DMM_PAT_IRQENABLE_SET 0x4A0
+#define DMM_PAT_IRQENABLE_CLR 0x4B0
+#define DMM_PAT_STATUS__0 0x4C0
+#define DMM_PAT_STATUS__1 0x4C4
+#define DMM_PAT_STATUS__2 0x4C8
+#define DMM_PAT_STATUS__3 0x4CC
+#define DMM_PAT_DESCR__0 0x500
+#define DMM_PAT_DESCR__1 0x510
+#define DMM_PAT_DESCR__2 0x520
+#define DMM_PAT_DESCR__3 0x530
+#define DMM_PEG_HWINFO 0x608
+#define DMM_PEG_PRIO 0x620
+#define DMM_PEG_PRIO_PAT 0x640
+
+#define DMM_IRQSTAT_DST (1<<0)
+#define DMM_IRQSTAT_LST (1<<1)
+#define DMM_IRQSTAT_ERR_INV_DSC (1<<2)
+#define DMM_IRQSTAT_ERR_INV_DATA (1<<3)
+#define DMM_IRQSTAT_ERR_UPD_AREA (1<<4)
+#define DMM_IRQSTAT_ERR_UPD_CTRL (1<<5)
+#define DMM_IRQSTAT_ERR_UPD_DATA (1<<6)
+#define DMM_IRQSTAT_ERR_LUT_MISS (1<<7)
+
+#define DMM_IRQSTAT_ERR_MASK (DMM_IRQ_STAT_ERR_INV_DSC | \
+ DMM_IRQ_STAT_ERR_INV_DATA | \
+ DMM_IRQ_STAT_ERR_UPD_AREA | \
+ DMM_IRQ_STAT_ERR_UPD_CTRL | \
+ DMM_IRQ_STAT_ERR_UPD_DATA | \
+ DMM_IRQ_STAT_ERR_LUT_MISS)
+
+#define DMM_PATSTATUS_READY (1<<0)
+#define DMM_PATSTATUS_VALID (1<<1)
+#define DMM_PATSTATUS_RUN (1<<2)
+#define DMM_PATSTATUS_DONE (1<<3)
+#define DMM_PATSTATUS_LINKED (1<<4)
+#define DMM_PATSTATUS_BYPASSED (1<<7)
+#define DMM_PATSTATUS_ERR_INV_DESCR (1<<10)
+#define DMM_PATSTATUS_ERR_INV_DATA (1<<11)
+#define DMM_PATSTATUS_ERR_UPD_AREA (1<<12)
+#define DMM_PATSTATUS_ERR_UPD_CTRL (1<<13)
+#define DMM_PATSTATUS_ERR_UPD_DATA (1<<14)
+#define DMM_PATSTATUS_ERR_ACCESS (1<<15)
+
+/* note: don't treat DMM_PATSTATUS_ERR_ACCESS as an error */
+#define DMM_PATSTATUS_ERR (DMM_PATSTATUS_ERR_INV_DESCR | \
+ DMM_PATSTATUS_ERR_INV_DATA | \
+ DMM_PATSTATUS_ERR_UPD_AREA | \
+ DMM_PATSTATUS_ERR_UPD_CTRL | \
+ DMM_PATSTATUS_ERR_UPD_DATA)
+
+
+
+enum {
+ PAT_STATUS,
+ PAT_DESCR
+};
+
+struct pat_ctrl {
+ u32 start:4;
+ u32 dir:4;
+ u32 lut_id:8;
+ u32 sync:12;
+ u32 ini:4;
+};
+
+struct pat {
+ uint32_t next_pa;
+ struct pat_area area;
+ struct pat_ctrl ctrl;
+ uint32_t data_pa;
+};
+
+#define DMM_FIXED_RETRY_COUNT 1000
+
+/* create refill buffer big enough to refill all slots, plus 3 descriptors..
+ * 3 descriptors is probably the worst-case for # of 2d-slices in a 1d area,
+ * but I guess you don't hit that worst case at the same time as full area
+ * refill
+ */
+#define DESCR_SIZE 128
+#define REFILL_BUFFER_SIZE ((4 * 128 * 256) + (3 * DESCR_SIZE))
+
+struct dmm;
+
+struct dmm_txn {
+ void *engine_handle;
+ struct tcm *tcm;
+
+ uint8_t *current_va;
+ dma_addr_t current_pa;
+
+ struct pat *last_pat;
+};
+
+struct refill_engine {
+ int id;
+ struct dmm *dmm;
+ struct tcm *tcm;
+
+ uint8_t *refill_va;
+ dma_addr_t refill_pa;
+
+ /* only one trans per engine for now */
+ struct dmm_txn txn;
+
+ /* offset to lut associated with container */
+ u32 *lut_offset;
+
+ wait_queue_head_t wait_for_refill;
+
+ struct list_head idle_node;
+};
+
+struct dmm {
+ struct device *dev;
+ void __iomem *base;
+ int irq;
+
+ struct page *dummy_page;
+ dma_addr_t dummy_pa;
+
+ void *refill_va;
+ dma_addr_t refill_pa;
+
+ /* refill engines */
+ struct semaphore engine_sem;
+ struct list_head idle_head;
+ struct refill_engine *engines;
+ int num_engines;
+
+ /* container information */
+ int container_width;
+ int container_height;
+ int lut_width;
+ int lut_height;
+ int num_lut;
+
+ /* array of LUT - TCM containers */
+ struct tcm **tcm;
+
+ /* LUT table storage */
+ u32 *lut;
+
+ /* allocation list and lock */
+ struct list_head alloc_head;
+ spinlock_t list_lock;
+};
+
+#endif
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c
new file mode 100644
index 000000000000..852d9440f725
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.c
@@ -0,0 +1,830 @@
+/*
+ * DMM IOMMU driver support functions for TI OMAP processors.
+ *
+ * Author: Rob Clark <rob@ti.com>
+ * Andy Gross <andy.gross@ti.com>
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h> /* platform_device() */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/time.h>
+#include <linux/list.h>
+#include <linux/semaphore.h>
+
+#include "omap_dmm_tiler.h"
+#include "omap_dmm_priv.h"
+
+/* mappings for associating views to luts */
+static struct tcm *containers[TILFMT_NFORMATS];
+static struct dmm *omap_dmm;
+
+/* Geometry table */
+#define GEOM(xshift, yshift, bytes_per_pixel) { \
+ .x_shft = (xshift), \
+ .y_shft = (yshift), \
+ .cpp = (bytes_per_pixel), \
+ .slot_w = 1 << (SLOT_WIDTH_BITS - (xshift)), \
+ .slot_h = 1 << (SLOT_HEIGHT_BITS - (yshift)), \
+ }
+
+static const struct {
+ uint32_t x_shft; /* unused X-bits (as part of bpp) */
+ uint32_t y_shft; /* unused Y-bits (as part of bpp) */
+ uint32_t cpp; /* bytes/chars per pixel */
+ uint32_t slot_w; /* width of each slot (in pixels) */
+ uint32_t slot_h; /* height of each slot (in pixels) */
+} geom[TILFMT_NFORMATS] = {
+ [TILFMT_8BIT] = GEOM(0, 0, 1),
+ [TILFMT_16BIT] = GEOM(0, 1, 2),
+ [TILFMT_32BIT] = GEOM(1, 1, 4),
+ [TILFMT_PAGE] = GEOM(SLOT_WIDTH_BITS, SLOT_HEIGHT_BITS, 1),
+};
+
+
+/* lookup table for registers w/ per-engine instances */
+static const uint32_t reg[][4] = {
+ [PAT_STATUS] = {DMM_PAT_STATUS__0, DMM_PAT_STATUS__1,
+ DMM_PAT_STATUS__2, DMM_PAT_STATUS__3},
+ [PAT_DESCR] = {DMM_PAT_DESCR__0, DMM_PAT_DESCR__1,
+ DMM_PAT_DESCR__2, DMM_PAT_DESCR__3},
+};
+
+/* simple allocator to grab next 16 byte aligned memory from txn */
+static void *alloc_dma(struct dmm_txn *txn, size_t sz, dma_addr_t *pa)
+{
+ void *ptr;
+ struct refill_engine *engine = txn->engine_handle;
+
+ /* dmm programming requires 16 byte aligned addresses */
+ txn->current_pa = round_up(txn->current_pa, 16);
+ txn->current_va = (void *)round_up((long)txn->current_va, 16);
+
+ ptr = txn->current_va;
+ *pa = txn->current_pa;
+
+ txn->current_pa += sz;
+ txn->current_va += sz;
+
+ BUG_ON((txn->current_va - engine->refill_va) > REFILL_BUFFER_SIZE);
+
+ return ptr;
+}
+
+/* check status and spin until wait_mask comes true */
+static int wait_status(struct refill_engine *engine, uint32_t wait_mask)
+{
+ struct dmm *dmm = engine->dmm;
+ uint32_t r = 0, err, i;
+
+ i = DMM_FIXED_RETRY_COUNT;
+ while (true) {
+ r = readl(dmm->base + reg[PAT_STATUS][engine->id]);
+ err = r & DMM_PATSTATUS_ERR;
+ if (err)
+ return -EFAULT;
+
+ if ((r & wait_mask) == wait_mask)
+ break;
+
+ if (--i == 0)
+ return -ETIMEDOUT;
+
+ udelay(1);
+ }
+
+ return 0;
+}
+
+irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
+{
+ struct dmm *dmm = arg;
+ uint32_t status = readl(dmm->base + DMM_PAT_IRQSTATUS);
+ int i;
+
+ /* ack IRQ */
+ writel(status, dmm->base + DMM_PAT_IRQSTATUS);
+
+ for (i = 0; i < dmm->num_engines; i++) {
+ if (status & DMM_IRQSTAT_LST)
+ wake_up_interruptible(&dmm->engines[i].wait_for_refill);
+
+ status >>= 8;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * Get a handle for a DMM transaction
+ */
+static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
+{
+ struct dmm_txn *txn = NULL;
+ struct refill_engine *engine = NULL;
+
+ down(&dmm->engine_sem);
+
+ /* grab an idle engine */
+ spin_lock(&dmm->list_lock);
+ if (!list_empty(&dmm->idle_head)) {
+ engine = list_entry(dmm->idle_head.next, struct refill_engine,
+ idle_node);
+ list_del(&engine->idle_node);
+ }
+ spin_unlock(&dmm->list_lock);
+
+ BUG_ON(!engine);
+
+ txn = &engine->txn;
+ engine->tcm = tcm;
+ txn->engine_handle = engine;
+ txn->last_pat = NULL;
+ txn->current_va = engine->refill_va;
+ txn->current_pa = engine->refill_pa;
+
+ return txn;
+}
+
+/**
+ * Add region to DMM transaction. If pages or pages[i] is NULL, then the
+ * corresponding slot is cleared (ie. dummy_pa is programmed)
+ */
+static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
+ struct page **pages, uint32_t npages, uint32_t roll)
+{
+ dma_addr_t pat_pa = 0;
+ uint32_t *data;
+ struct pat *pat;
+ struct refill_engine *engine = txn->engine_handle;
+ int columns = (1 + area->x1 - area->x0);
+ int rows = (1 + area->y1 - area->y0);
+ int i = columns*rows;
+ u32 *lut = omap_dmm->lut + (engine->tcm->lut_id * omap_dmm->lut_width *
+ omap_dmm->lut_height) +
+ (area->y0 * omap_dmm->lut_width) + area->x0;
+
+ pat = alloc_dma(txn, sizeof(struct pat), &pat_pa);
+
+ if (txn->last_pat)
+ txn->last_pat->next_pa = (uint32_t)pat_pa;
+
+ pat->area = *area;
+ pat->ctrl = (struct pat_ctrl){
+ .start = 1,
+ .lut_id = engine->tcm->lut_id,
+ };
+
+ data = alloc_dma(txn, 4*i, &pat->data_pa);
+
+ while (i--) {
+ int n = i + roll;
+ if (n >= npages)
+ n -= npages;
+ data[i] = (pages && pages[n]) ?
+ page_to_phys(pages[n]) : engine->dmm->dummy_pa;
+ }
+
+ /* fill in lut with new addresses */
+ for (i = 0; i < rows; i++, lut += omap_dmm->lut_width)
+ memcpy(lut, &data[i*columns], columns * sizeof(u32));
+
+ txn->last_pat = pat;
+
+ return 0;
+}
+
+/**
+ * Commit the DMM transaction.
+ */
+static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
+{
+ int ret = 0;
+ struct refill_engine *engine = txn->engine_handle;
+ struct dmm *dmm = engine->dmm;
+
+ if (!txn->last_pat) {
+ dev_err(engine->dmm->dev, "need at least one txn\n");
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ txn->last_pat->next_pa = 0;
+
+ /* write to PAT_DESCR to clear out any pending transaction */
+ writel(0x0, dmm->base + reg[PAT_DESCR][engine->id]);
+
+ /* wait for engine ready: */
+ ret = wait_status(engine, DMM_PATSTATUS_READY);
+ if (ret) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ /* kick reload */
+ writel(engine->refill_pa,
+ dmm->base + reg[PAT_DESCR][engine->id]);
+
+ if (wait) {
+ if (wait_event_interruptible_timeout(engine->wait_for_refill,
+ wait_status(engine, DMM_PATSTATUS_READY) == 0,
+ msecs_to_jiffies(1)) <= 0) {
+ dev_err(dmm->dev, "timed out waiting for done\n");
+ ret = -ETIMEDOUT;
+ }
+ }
+
+cleanup:
+ spin_lock(&dmm->list_lock);
+ list_add(&engine->idle_node, &dmm->idle_head);
+ spin_unlock(&dmm->list_lock);
+
+ up(&omap_dmm->engine_sem);
+ return ret;
+}
+
+/*
+ * DMM programming
+ */
+static int fill(struct tcm_area *area, struct page **pages,
+ uint32_t npages, uint32_t roll, bool wait)
+{
+ int ret = 0;
+ struct tcm_area slice, area_s;
+ struct dmm_txn *txn;
+
+ txn = dmm_txn_init(omap_dmm, area->tcm);
+ if (IS_ERR_OR_NULL(txn))
+ return PTR_ERR(txn);
+
+ tcm_for_each_slice(slice, *area, area_s) {
+ struct pat_area p_area = {
+ .x0 = slice.p0.x, .y0 = slice.p0.y,
+ .x1 = slice.p1.x, .y1 = slice.p1.y,
+ };
+
+ ret = dmm_txn_append(txn, &p_area, pages, npages, roll);
+ if (ret)
+ goto fail;
+
+ roll += tcm_sizeof(slice);
+ }
+
+ ret = dmm_txn_commit(txn, wait);
+
+fail:
+ return ret;
+}
+
+/*
+ * Pin/unpin
+ */
+
+/* note: slots for which pages[i] == NULL are filled w/ dummy page
+ */
+int tiler_pin(struct tiler_block *block, struct page **pages,
+ uint32_t npages, uint32_t roll, bool wait)
+{
+ int ret;
+
+ ret = fill(&block->area, pages, npages, roll, wait);
+
+ if (ret)
+ tiler_unpin(block);
+
+ return ret;
+}
+
+int tiler_unpin(struct tiler_block *block)
+{
+ return fill(&block->area, NULL, 0, 0, false);
+}
+
+/*
+ * Reserve/release
+ */
+struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
+ uint16_t h, uint16_t align)
+{
+ struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
+ u32 min_align = 128;
+ int ret;
+
+ BUG_ON(!validfmt(fmt));
+
+ /* convert width/height to slots */
+ w = DIV_ROUND_UP(w, geom[fmt].slot_w);
+ h = DIV_ROUND_UP(h, geom[fmt].slot_h);
+
+ /* convert alignment to slots */
+ min_align = max(min_align, (geom[fmt].slot_w * geom[fmt].cpp));
+ align = ALIGN(align, min_align);
+ align /= geom[fmt].slot_w * geom[fmt].cpp;
+
+ block->fmt = fmt;
+
+ ret = tcm_reserve_2d(containers[fmt], w, h, align, &block->area);
+ if (ret) {
+ kfree(block);
+ return 0;
+ }
+
+ /* add to allocation list */
+ spin_lock(&omap_dmm->list_lock);
+ list_add(&block->alloc_node, &omap_dmm->alloc_head);
+ spin_unlock(&omap_dmm->list_lock);
+
+ return block;
+}
+
+struct tiler_block *tiler_reserve_1d(size_t size)
+{
+ struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
+ int num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ if (!block)
+ return 0;
+
+ block->fmt = TILFMT_PAGE;
+
+ if (tcm_reserve_1d(containers[TILFMT_PAGE], num_pages,
+ &block->area)) {
+ kfree(block);
+ return 0;
+ }
+
+ spin_lock(&omap_dmm->list_lock);
+ list_add(&block->alloc_node, &omap_dmm->alloc_head);
+ spin_unlock(&omap_dmm->list_lock);
+
+ return block;
+}
+
+/* note: if you have pin'd pages, you should have already unpin'd first! */
+int tiler_release(struct tiler_block *block)
+{
+ int ret = tcm_free(&block->area);
+
+ if (block->area.tcm)
+ dev_err(omap_dmm->dev, "failed to release block\n");
+
+ spin_lock(&omap_dmm->list_lock);
+ list_del(&block->alloc_node);
+ spin_unlock(&omap_dmm->list_lock);
+
+ kfree(block);
+ return ret;
+}
+
+/*
+ * Utils
+ */
+
+/* calculate the tiler space address of a pixel in a view orientation */
+static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y)
+{
+ u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;
+
+ x_bits = CONT_WIDTH_BITS - geom[fmt].x_shft;
+ y_bits = CONT_HEIGHT_BITS - geom[fmt].y_shft;
+ alignment = geom[fmt].x_shft + geom[fmt].y_shft;
+
+ /* validate coordinate */
+ x_mask = MASK(x_bits);
+ y_mask = MASK(y_bits);
+
+ if (x < 0 || x > x_mask || y < 0 || y > y_mask)
+ return 0;
+
+ /* account for mirroring */
+ if (orient & MASK_X_INVERT)
+ x ^= x_mask;
+ if (orient & MASK_Y_INVERT)
+ y ^= y_mask;
+
+ /* get coordinate address */
+ if (orient & MASK_XY_FLIP)
+ tmp = ((x << y_bits) + y);
+ else
+ tmp = ((y << x_bits) + x);
+
+ return TIL_ADDR((tmp << alignment), orient, fmt);
+}
+
+dma_addr_t tiler_ssptr(struct tiler_block *block)
+{
+ BUG_ON(!validfmt(block->fmt));
+
+ return TILVIEW_8BIT + tiler_get_address(0, block->fmt,
+ block->area.p0.x * geom[block->fmt].slot_w,
+ block->area.p0.y * geom[block->fmt].slot_h);
+}
+
+void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h)
+{
+ BUG_ON(!validfmt(fmt));
+ *w = round_up(*w, geom[fmt].slot_w);
+ *h = round_up(*h, geom[fmt].slot_h);
+}
+
+uint32_t tiler_stride(enum tiler_fmt fmt)
+{
+ BUG_ON(!validfmt(fmt));
+
+ return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
+}
+
+size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h)
+{
+ tiler_align(fmt, &w, &h);
+ return geom[fmt].cpp * w * h;
+}
+
+size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h)
+{
+ BUG_ON(!validfmt(fmt));
+ return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
+}
+
+int omap_dmm_remove(void)
+{
+ struct tiler_block *block, *_block;
+ int i;
+
+ if (omap_dmm) {
+ /* free all area regions */
+ spin_lock(&omap_dmm->list_lock);
+ list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
+ alloc_node) {
+ list_del(&block->alloc_node);
+ kfree(block);
+ }
+ spin_unlock(&omap_dmm->list_lock);
+
+ for (i = 0; i < omap_dmm->num_lut; i++)
+ if (omap_dmm->tcm && omap_dmm->tcm[i])
+ omap_dmm->tcm[i]->deinit(omap_dmm->tcm[i]);
+ kfree(omap_dmm->tcm);
+
+ kfree(omap_dmm->engines);
+ if (omap_dmm->refill_va)
+ dma_free_coherent(omap_dmm->dev,
+ REFILL_BUFFER_SIZE * omap_dmm->num_engines,
+ omap_dmm->refill_va,
+ omap_dmm->refill_pa);
+ if (omap_dmm->dummy_page)
+ __free_page(omap_dmm->dummy_page);
+
+ vfree(omap_dmm->lut);
+
+ if (omap_dmm->irq != -1)
+ free_irq(omap_dmm->irq, omap_dmm);
+
+ kfree(omap_dmm);
+ }
+
+ return 0;
+}
+
+int omap_dmm_init(struct drm_device *dev)
+{
+ int ret = -EFAULT, i;
+ struct tcm_area area = {0};
+ u32 hwinfo, pat_geom, lut_table_size;
+ struct omap_drm_platform_data *pdata = dev->dev->platform_data;
+
+ if (!pdata || !pdata->dmm_pdata) {
+ dev_err(dev->dev, "dmm platform data not present, skipping\n");
+ return ret;
+ }
+
+ omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
+ if (!omap_dmm) {
+ dev_err(dev->dev, "failed to allocate driver data section\n");
+ goto fail;
+ }
+
+ /* lookup hwmod data - base address and irq */
+ omap_dmm->base = pdata->dmm_pdata->base;
+ omap_dmm->irq = pdata->dmm_pdata->irq;
+ omap_dmm->dev = dev->dev;
+
+ if (!omap_dmm->base) {
+ dev_err(dev->dev, "failed to get dmm base address\n");
+ goto fail;
+ }
+
+ hwinfo = readl(omap_dmm->base + DMM_PAT_HWINFO);
+ omap_dmm->num_engines = (hwinfo >> 24) & 0x1F;
+ omap_dmm->num_lut = (hwinfo >> 16) & 0x1F;
+ omap_dmm->container_width = 256;
+ omap_dmm->container_height = 128;
+
+ /* read out actual LUT width and height */
+ pat_geom = readl(omap_dmm->base + DMM_PAT_GEOMETRY);
+ omap_dmm->lut_width = ((pat_geom >> 16) & 0xF) << 5;
+ omap_dmm->lut_height = ((pat_geom >> 24) & 0xF) << 5;
+
+ /* initialize DMM registers */
+ writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__0);
+ writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__1);
+ writel(0x80808080, omap_dmm->base + DMM_PAT_VIEW_MAP__0);
+ writel(0x80000000, omap_dmm->base + DMM_PAT_VIEW_MAP_BASE);
+ writel(0x88888888, omap_dmm->base + DMM_TILER_OR__0);
+ writel(0x88888888, omap_dmm->base + DMM_TILER_OR__1);
+
+ ret = request_irq(omap_dmm->irq, omap_dmm_irq_handler, IRQF_SHARED,
+ "omap_dmm_irq_handler", omap_dmm);
+
+ if (ret) {
+ dev_err(dev->dev, "couldn't register IRQ %d, error %d\n",
+ omap_dmm->irq, ret);
+ omap_dmm->irq = -1;
+ goto fail;
+ }
+
+ /* Enable all interrupts for each refill engine except
+ * ERR_LUT_MISS<n> (which is just advisory, and we don't care
+ * about because we want to be able to refill live scanout
+ * buffers for accelerated pan/scroll) and FILL_DSC<n> which
+ * we just generally don't care about.
+ */
+ writel(0x7e7e7e7e, omap_dmm->base + DMM_PAT_IRQENABLE_SET);
+
+ lut_table_size = omap_dmm->lut_width * omap_dmm->lut_height *
+ omap_dmm->num_lut;
+
+ omap_dmm->lut = vmalloc(lut_table_size * sizeof(*omap_dmm->lut));
+ if (!omap_dmm->lut) {
+ dev_err(dev->dev, "could not allocate lut table\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
+ if (!omap_dmm->dummy_page) {
+ dev_err(dev->dev, "could not allocate dummy page\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+ omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
+
+ /* alloc refill memory */
+ omap_dmm->refill_va = dma_alloc_coherent(dev->dev,
+ REFILL_BUFFER_SIZE * omap_dmm->num_engines,
+ &omap_dmm->refill_pa, GFP_KERNEL);
+ if (!omap_dmm->refill_va) {
+ dev_err(dev->dev, "could not allocate refill memory\n");
+ goto fail;
+ }
+
+ /* alloc engines */
+ omap_dmm->engines = kzalloc(
+ omap_dmm->num_engines * sizeof(struct refill_engine),
+ GFP_KERNEL);
+ if (!omap_dmm->engines) {
+ dev_err(dev->dev, "could not allocate engines\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ sema_init(&omap_dmm->engine_sem, omap_dmm->num_engines);
+ INIT_LIST_HEAD(&omap_dmm->idle_head);
+ for (i = 0; i < omap_dmm->num_engines; i++) {
+ omap_dmm->engines[i].id = i;
+ omap_dmm->engines[i].dmm = omap_dmm;
+ omap_dmm->engines[i].refill_va = omap_dmm->refill_va +
+ (REFILL_BUFFER_SIZE * i);
+ omap_dmm->engines[i].refill_pa = omap_dmm->refill_pa +
+ (REFILL_BUFFER_SIZE * i);
+ init_waitqueue_head(&omap_dmm->engines[i].wait_for_refill);
+
+ list_add(&omap_dmm->engines[i].idle_node, &omap_dmm->idle_head);
+ }
+
+ omap_dmm->tcm = kzalloc(omap_dmm->num_lut * sizeof(*omap_dmm->tcm),
+ GFP_KERNEL);
+ if (!omap_dmm->tcm) {
+ dev_err(dev->dev, "failed to allocate lut ptrs\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ /* init containers */
+ for (i = 0; i < omap_dmm->num_lut; i++) {
+ omap_dmm->tcm[i] = sita_init(omap_dmm->container_width,
+ omap_dmm->container_height,
+ NULL);
+
+ if (!omap_dmm->tcm[i]) {
+ dev_err(dev->dev, "failed to allocate container\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ omap_dmm->tcm[i]->lut_id = i;
+ }
+
+ /* assign access mode containers to applicable tcm container */
+ /* OMAP 4 has 1 container for all 4 views */
+ containers[TILFMT_8BIT] = omap_dmm->tcm[0];
+ containers[TILFMT_16BIT] = omap_dmm->tcm[0];
+ containers[TILFMT_32BIT] = omap_dmm->tcm[0];
+ containers[TILFMT_PAGE] = omap_dmm->tcm[0];
+
+ INIT_LIST_HEAD(&omap_dmm->alloc_head);
+ spin_lock_init(&omap_dmm->list_lock);
+
+ area = (struct tcm_area) {
+ .is2d = true,
+ .tcm = NULL,
+ .p1.x = omap_dmm->container_width - 1,
+ .p1.y = omap_dmm->container_height - 1,
+ };
+
+ for (i = 0; i < lut_table_size; i++)
+ omap_dmm->lut[i] = omap_dmm->dummy_pa;
+
+ /* initialize all LUTs to dummy page entries */
+ for (i = 0; i < omap_dmm->num_lut; i++) {
+ area.tcm = omap_dmm->tcm[i];
+ if (fill(&area, NULL, 0, 0, true))
+ dev_err(omap_dmm->dev, "refill failed");
+ }
+
+ dev_info(omap_dmm->dev, "initialized all PAT entries\n");
+
+ return 0;
+
+fail:
+ omap_dmm_remove();
+ return ret;
+}
+
+/*
+ * debugfs support
+ */
+
+#ifdef CONFIG_DEBUG_FS
+
+static const char *alphabet = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+static const char *special = ".,:;'\"`~!^-+";
+
+static void fill_map(char **map, int xdiv, int ydiv, struct tcm_area *a,
+ char c, bool ovw)
+{
+ int x, y;
+ for (y = a->p0.y / ydiv; y <= a->p1.y / ydiv; y++)
+ for (x = a->p0.x / xdiv; x <= a->p1.x / xdiv; x++)
+ if (map[y][x] == ' ' || ovw)
+ map[y][x] = c;
+}
+
+static void fill_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p,
+ char c)
+{
+ map[p->y / ydiv][p->x / xdiv] = c;
+}
+
+static char read_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p)
+{
+ return map[p->y / ydiv][p->x / xdiv];
+}
+
+static int map_width(int xdiv, int x0, int x1)
+{
+ return (x1 / xdiv) - (x0 / xdiv) + 1;
+}
+
+static void text_map(char **map, int xdiv, char *nice, int yd, int x0, int x1)
+{
+ char *p = map[yd] + (x0 / xdiv);
+ int w = (map_width(xdiv, x0, x1) - strlen(nice)) / 2;
+ if (w >= 0) {
+ p += w;
+ while (*nice)
+ *p++ = *nice++;
+ }
+}
+
+static void map_1d_info(char **map, int xdiv, int ydiv, char *nice,
+ struct tcm_area *a)
+{
+ sprintf(nice, "%dK", tcm_sizeof(*a) * 4);
+ if (a->p0.y + 1 < a->p1.y) {
+ text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv, 0,
+ 256 - 1);
+ } else if (a->p0.y < a->p1.y) {
+ if (strlen(nice) < map_width(xdiv, a->p0.x, 256 - 1))
+ text_map(map, xdiv, nice, a->p0.y / ydiv,
+ a->p0.x + xdiv, 256 - 1);
+ else if (strlen(nice) < map_width(xdiv, 0, a->p1.x))
+ text_map(map, xdiv, nice, a->p1.y / ydiv,
+ 0, a->p1.y - xdiv);
+ } else if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x)) {
+ text_map(map, xdiv, nice, a->p0.y / ydiv, a->p0.x, a->p1.x);
+ }
+}
+
+static void map_2d_info(char **map, int xdiv, int ydiv, char *nice,
+ struct tcm_area *a)
+{
+ sprintf(nice, "(%d*%d)", tcm_awidth(*a), tcm_aheight(*a));
+ if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x))
+ text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv,
+ a->p0.x, a->p1.x);
+}
+
+int tiler_map_show(struct seq_file *s, void *arg)
+{
+ int xdiv = 2, ydiv = 1;
+ char **map = NULL, *global_map;
+ struct tiler_block *block;
+ struct tcm_area a, p;
+ int i;
+ const char *m2d = alphabet;
+ const char *a2d = special;
+ const char *m2dp = m2d, *a2dp = a2d;
+ char nice[128];
+ int h_adj = omap_dmm->lut_height / ydiv;
+ int w_adj = omap_dmm->lut_width / xdiv;
+ unsigned long flags;
+
+ map = kzalloc(h_adj * sizeof(*map), GFP_KERNEL);
+ global_map = kzalloc((w_adj + 1) * h_adj, GFP_KERNEL);
+
+ if (!map || !global_map)
+ goto error;
+
+ memset(global_map, ' ', (w_adj + 1) * h_adj);
+ for (i = 0; i < omap_dmm->lut_height; i++) {
+ map[i] = global_map + i * (w_adj + 1);
+ map[i][w_adj] = 0;
+ }
+ spin_lock_irqsave(&omap_dmm->list_lock, flags);
+
+ list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) {
+ if (block->fmt != TILFMT_PAGE) {
+ fill_map(map, xdiv, ydiv, &block->area, *m2dp, true);
+ if (!*++a2dp)
+ a2dp = a2d;
+ if (!*++m2dp)
+ m2dp = m2d;
+ map_2d_info(map, xdiv, ydiv, nice, &block->area);
+ } else {
+ bool start = read_map_pt(map, xdiv, ydiv,
+ &block->area.p0)
+ == ' ';
+ bool end = read_map_pt(map, xdiv, ydiv, &block->area.p1)
+ == ' ';
+ tcm_for_each_slice(a, block->area, p)
+ fill_map(map, xdiv, ydiv, &a, '=', true);
+ fill_map_pt(map, xdiv, ydiv, &block->area.p0,
+ start ? '<' : 'X');
+ fill_map_pt(map, xdiv, ydiv, &block->area.p1,
+ end ? '>' : 'X');
+ map_1d_info(map, xdiv, ydiv, nice, &block->area);
+ }
+ }
+
+ spin_unlock_irqrestore(&omap_dmm->list_lock, flags);
+
+ if (s) {
+ seq_printf(s, "BEGIN DMM TILER MAP\n");
+ for (i = 0; i < 128; i++)
+ seq_printf(s, "%03d:%s\n", i, map[i]);
+ seq_printf(s, "END TILER MAP\n");
+ } else {
+ dev_dbg(omap_dmm->dev, "BEGIN DMM TILER MAP\n");
+ for (i = 0; i < 128; i++)
+ dev_dbg(omap_dmm->dev, "%03d:%s\n", i, map[i]);
+ dev_dbg(omap_dmm->dev, "END TILER MAP\n");
+ }
+
+error:
+ kfree(map);
+ kfree(global_map);
+
+ return 0;
+}
+#endif
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.h b/drivers/staging/omapdrm/omap_dmm_tiler.h
new file mode 100644
index 000000000000..f87cb657d683
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.h
@@ -0,0 +1,135 @@
+/*
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Rob Clark <rob@ti.com>
+ * Andy Gross <andy.gross@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef OMAP_DMM_TILER_H
+#define OMAP_DMM_TILER_H
+
+#include "omap_drv.h"
+#include "tcm.h"
+
+enum tiler_fmt {
+ TILFMT_8BIT = 0,
+ TILFMT_16BIT,
+ TILFMT_32BIT,
+ TILFMT_PAGE,
+ TILFMT_NFORMATS
+};
+
+struct pat_area {
+ u32 x0:8;
+ u32 y0:8;
+ u32 x1:8;
+ u32 y1:8;
+};
+
+struct tiler_block {
+ struct list_head alloc_node; /* node for global block list */
+ struct tcm_area area; /* area */
+ enum tiler_fmt fmt; /* format */
+};
+
+/* bits representing the same slot in DMM-TILER hw-block */
+#define SLOT_WIDTH_BITS 6
+#define SLOT_HEIGHT_BITS 6
+
+/* bits reserved to describe coordinates in DMM-TILER hw-block */
+#define CONT_WIDTH_BITS 14
+#define CONT_HEIGHT_BITS 13
+
+/* calculated constants */
+#define TILER_PAGE (1 << (SLOT_WIDTH_BITS + SLOT_HEIGHT_BITS))
+#define TILER_WIDTH (1 << (CONT_WIDTH_BITS - SLOT_WIDTH_BITS))
+#define TILER_HEIGHT (1 << (CONT_HEIGHT_BITS - SLOT_HEIGHT_BITS))
+
+/* tiler space addressing bitfields */
+#define MASK_XY_FLIP (1 << 31)
+#define MASK_Y_INVERT (1 << 30)
+#define MASK_X_INVERT (1 << 29)
+#define SHIFT_ACC_MODE 27
+#define MASK_ACC_MODE 3
+
+#define MASK(bits) ((1 << (bits)) - 1)
+
+#define TILVIEW_8BIT 0x60000000u
+#define TILVIEW_16BIT (TILVIEW_8BIT + VIEW_SIZE)
+#define TILVIEW_32BIT (TILVIEW_16BIT + VIEW_SIZE)
+#define TILVIEW_PAGE (TILVIEW_32BIT + VIEW_SIZE)
+#define TILVIEW_END (TILVIEW_PAGE + VIEW_SIZE)
+
+/* create tsptr by adding view orientation and access mode */
+#define TIL_ADDR(x, orient, a)\
+ ((u32) (x) | (orient) | ((a) << SHIFT_ACC_MODE))
+
+/* externally accessible functions */
+int omap_dmm_init(struct drm_device *dev);
+int omap_dmm_remove(void);
+
+#ifdef CONFIG_DEBUG_FS
+int tiler_map_show(struct seq_file *s, void *arg);
+#endif
+
+/* pin/unpin */
+int tiler_pin(struct tiler_block *block, struct page **pages,
+ uint32_t npages, uint32_t roll, bool wait);
+int tiler_unpin(struct tiler_block *block);
+
+/* reserve/release */
+struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w, uint16_t h,
+ uint16_t align);
+struct tiler_block *tiler_reserve_1d(size_t size);
+int tiler_release(struct tiler_block *block);
+
+/* utilities */
+dma_addr_t tiler_ssptr(struct tiler_block *block);
+uint32_t tiler_stride(enum tiler_fmt fmt);
+size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h);
+size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h);
+void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h);
+
+
+/* GEM bo flags -> tiler fmt */
+static inline enum tiler_fmt gem2fmt(uint32_t flags)
+{
+ switch (flags & OMAP_BO_TILED) {
+ case OMAP_BO_TILED_8:
+ return TILFMT_8BIT;
+ case OMAP_BO_TILED_16:
+ return TILFMT_16BIT;
+ case OMAP_BO_TILED_32:
+ return TILFMT_32BIT;
+ default:
+ return TILFMT_PAGE;
+ }
+}
+
+static inline bool validfmt(enum tiler_fmt fmt)
+{
+ switch (fmt) {
+ case TILFMT_8BIT:
+ case TILFMT_16BIT:
+ case TILFMT_32BIT:
+ case TILFMT_PAGE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+struct omap_dmm_platform_data {
+ void __iomem *base;
+ int irq;
+};
+
+#endif
diff --git a/drivers/staging/omapdrm/omap_drm.h b/drivers/staging/omapdrm/omap_drm.h
new file mode 100644
index 000000000000..f0ac34a8973e
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_drm.h
@@ -0,0 +1,123 @@
+/*
+ * include/drm/omap_drm.h
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP_DRM_H__
+#define __OMAP_DRM_H__
+
+#include <drm/drm.h>
+
+/* Please note that modifications to all structs defined here are
+ * subject to backwards-compatibility constraints.
+ */
+
+#define OMAP_PARAM_CHIPSET_ID 1 /* ie. 0x3430, 0x4430, etc */
+
+struct drm_omap_param {
+ uint64_t param; /* in */
+ uint64_t value; /* in (set_param), out (get_param) */
+};
+
+#define OMAP_BO_SCANOUT 0x00000001 /* scanout capable (phys contiguous) */
+#define OMAP_BO_CACHE_MASK 0x00000006 /* cache type mask, see cache modes */
+#define OMAP_BO_TILED_MASK 0x00000f00 /* tiled mapping mask, see tiled modes */
+
+/* cache modes */
+#define OMAP_BO_CACHED 0x00000000 /* default */
+#define OMAP_BO_WC 0x00000002 /* write-combine */
+#define OMAP_BO_UNCACHED 0x00000004 /* strongly-ordered (uncached) */
+
+/* tiled modes */
+#define OMAP_BO_TILED_8 0x00000100
+#define OMAP_BO_TILED_16 0x00000200
+#define OMAP_BO_TILED_32 0x00000300
+#define OMAP_BO_TILED (OMAP_BO_TILED_8 | OMAP_BO_TILED_16 | OMAP_BO_TILED_32)
+
+union omap_gem_size {
+ uint32_t bytes; /* (for non-tiled formats) */
+ struct {
+ uint16_t width;
+ uint16_t height;
+ } tiled; /* (for tiled formats) */
+};
+
+struct drm_omap_gem_new {
+ union omap_gem_size size; /* in */
+ uint32_t flags; /* in */
+ uint32_t handle; /* out */
+ uint32_t __pad;
+};
+
+/* mask of operations: */
+enum omap_gem_op {
+ OMAP_GEM_READ = 0x01,
+ OMAP_GEM_WRITE = 0x02,
+};
+
+struct drm_omap_gem_cpu_prep {
+ uint32_t handle; /* buffer handle (in) */
+ uint32_t op; /* mask of omap_gem_op (in) */
+};
+
+struct drm_omap_gem_cpu_fini {
+ uint32_t handle; /* buffer handle (in) */
+ uint32_t op; /* mask of omap_gem_op (in) */
+ /* TODO maybe here we pass down info about what regions are touched
+ * by sw so we can be clever about cache ops? For now a placeholder,
+ * set to zero and we just do full buffer flush..
+ */
+ uint32_t nregions;
+ uint32_t __pad;
+};
+
+struct drm_omap_gem_info {
+ uint32_t handle; /* buffer handle (in) */
+ uint32_t pad;
+ uint64_t offset; /* mmap offset (out) */
+ /* note: in case of tiled buffers, the user virtual size can be
+ * different from the physical size (ie. how many pages are needed
+ * to back the object) which is returned in DRM_IOCTL_GEM_OPEN..
+ * This size here is the one that should be used if you want to
+ * mmap() the buffer:
+ */
+ uint32_t size; /* virtual size for mmap'ing (out) */
+ uint32_t __pad;
+};
+
+#define DRM_OMAP_GET_PARAM 0x00
+#define DRM_OMAP_SET_PARAM 0x01
+/* placeholder for plugin-api
+#define DRM_OMAP_GET_BASE 0x02
+*/
+#define DRM_OMAP_GEM_NEW 0x03
+#define DRM_OMAP_GEM_CPU_PREP 0x04
+#define DRM_OMAP_GEM_CPU_FINI 0x05
+#define DRM_OMAP_GEM_INFO 0x06
+#define DRM_OMAP_NUM_IOCTLS 0x07
+
+#define DRM_IOCTL_OMAP_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_PARAM, struct drm_omap_param)
+#define DRM_IOCTL_OMAP_SET_PARAM DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_SET_PARAM, struct drm_omap_param)
+/* placeholder for plugin-api
+#define DRM_IOCTL_OMAP_GET_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_BASE, struct drm_omap_get_base)
+*/
+#define DRM_IOCTL_OMAP_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GEM_NEW, struct drm_omap_gem_new)
+#define DRM_IOCTL_OMAP_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_PREP, struct drm_omap_gem_cpu_prep)
+#define DRM_IOCTL_OMAP_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_FINI, struct drm_omap_gem_cpu_fini)
+#define DRM_IOCTL_OMAP_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GEM_INFO, struct drm_omap_gem_info)
+
+#endif /* __OMAP_DRM_H__ */
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
new file mode 100644
index 000000000000..602aa2dd49c8
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -0,0 +1,821 @@
+/*
+ * drivers/staging/omapdrm/omap_drv.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+#include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
+
+#define DRIVER_NAME MODULE_NAME
+#define DRIVER_DESC "OMAP DRM"
+#define DRIVER_DATE "20110917"
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
+
+struct drm_device *drm_device;
+
+static int num_crtc = CONFIG_DRM_OMAP_NUM_CRTCS;
+
+MODULE_PARM_DESC(num_crtc, "Number of overlays to use as CRTCs");
+module_param(num_crtc, int, 0600);
+
+/*
+ * mode config funcs
+ */
+
+/* Notes about mapping DSS and DRM entities:
+ * CRTC: overlay
+ * encoder: manager.. with some extension to allow one primary CRTC
+ * and zero or more video CRTC's to be mapped to one encoder?
+ * connector: dssdev.. manager can be attached/detached from different
+ * devices
+ */
+
+static void omap_fb_output_poll_changed(struct drm_device *dev)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ DBG("dev=%p", dev);
+ if (priv->fbdev) {
+ drm_fb_helper_hotplug_event(priv->fbdev);
+ }
+}
+
+static struct drm_mode_config_funcs omap_mode_config_funcs = {
+ .fb_create = omap_framebuffer_create,
+ .output_poll_changed = omap_fb_output_poll_changed,
+};
+
+static int get_connector_type(struct omap_dss_device *dssdev)
+{
+ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_HDMI:
+ return DRM_MODE_CONNECTOR_HDMIA;
+ case OMAP_DISPLAY_TYPE_DPI:
+ if (!strcmp(dssdev->name, "dvi"))
+ return DRM_MODE_CONNECTOR_DVID;
+ /* fallthrough */
+ default:
+ return DRM_MODE_CONNECTOR_Unknown;
+ }
+}
+
+#if 0 /* enable when dss2 supports hotplug */
+static int omap_drm_notifier(struct notifier_block *nb,
+ unsigned long evt, void *arg)
+{
+ switch (evt) {
+ case OMAP_DSS_SIZE_CHANGE:
+ case OMAP_DSS_HOTPLUG_CONNECT:
+ case OMAP_DSS_HOTPLUG_DISCONNECT: {
+ struct drm_device *dev = drm_device;
+ DBG("hotplug event: evt=%d, dev=%p", evt, dev);
+ if (dev) {
+ drm_sysfs_hotplug_event(dev);
+ }
+ return NOTIFY_OK;
+ }
+ default: /* don't care about other events for now */
+ return NOTIFY_DONE;
+ }
+}
+#endif
+
+static void dump_video_chains(void)
+{
+ int i;
+
+ DBG("dumping video chains: ");
+ for (i = 0; i < omap_dss_get_num_overlays(); i++) {
+ struct omap_overlay *ovl = omap_dss_get_overlay(i);
+ struct omap_overlay_manager *mgr = ovl->manager;
+ struct omap_dss_device *dssdev = mgr ? mgr->device : NULL;
+ if (dssdev) {
+ DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name,
+ dssdev->name);
+ } else if (mgr) {
+ DBG("%d: %s -> %s", i, ovl->name, mgr->name);
+ } else {
+ DBG("%d: %s", i, ovl->name);
+ }
+ }
+}
+
+/* create encoders for each manager */
+static int create_encoder(struct drm_device *dev,
+ struct omap_overlay_manager *mgr)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ struct drm_encoder *encoder = omap_encoder_init(dev, mgr);
+
+ if (!encoder) {
+ dev_err(dev->dev, "could not create encoder: %s\n",
+ mgr->name);
+ return -ENOMEM;
+ }
+
+ BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders));
+
+ priv->encoders[priv->num_encoders++] = encoder;
+
+ return 0;
+}
+
+/* create connectors for each display device */
+static int create_connector(struct drm_device *dev,
+ struct omap_dss_device *dssdev)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ static struct notifier_block *notifier;
+ struct drm_connector *connector;
+ int j;
+
+ if (!dssdev->driver) {
+ dev_warn(dev->dev, "%s has no driver.. skipping it\n",
+ dssdev->name);
+ return 0;
+ }
+
+ if (!(dssdev->driver->get_timings ||
+ dssdev->driver->read_edid)) {
+ dev_warn(dev->dev, "%s driver does not support "
+ "get_timings or read_edid.. skipping it!\n",
+ dssdev->name);
+ return 0;
+ }
+
+ connector = omap_connector_init(dev,
+ get_connector_type(dssdev), dssdev);
+
+ if (!connector) {
+ dev_err(dev->dev, "could not create connector: %s\n",
+ dssdev->name);
+ return -ENOMEM;
+ }
+
+ BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors));
+
+ priv->connectors[priv->num_connectors++] = connector;
+
+#if 0 /* enable when dss2 supports hotplug */
+ notifier = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
+ notifier->notifier_call = omap_drm_notifier;
+ omap_dss_add_notify(dssdev, notifier);
+#else
+ notifier = NULL;
+#endif
+
+ for (j = 0; j < priv->num_encoders; j++) {
+ struct omap_overlay_manager *mgr =
+ omap_encoder_get_manager(priv->encoders[j]);
+ if (mgr->device == dssdev) {
+ drm_mode_connector_attach_encoder(connector,
+ priv->encoders[j]);
+ }
+ }
+
+ return 0;
+}
+
+/* create up to max_overlays CRTCs mapping to overlays.. by default,
+ * connect the overlays to different managers/encoders, giving priority
+ * to encoders connected to connectors with a detected connection
+ */
+static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
+ int *j, unsigned int connected_connectors)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ struct omap_overlay_manager *mgr = NULL;
+ struct drm_crtc *crtc;
+
+ if (ovl->manager) {
+ DBG("disconnecting %s from %s", ovl->name,
+ ovl->manager->name);
+ ovl->unset_manager(ovl);
+ }
+
+ /* find next best connector, ones with detected connection first
+ */
+ while (*j < priv->num_connectors && !mgr) {
+ if (connected_connectors & (1 << *j)) {
+ struct drm_encoder *encoder =
+ omap_connector_attached_encoder(
+ priv->connectors[*j]);
+ if (encoder) {
+ mgr = omap_encoder_get_manager(encoder);
+ }
+ }
+ (*j)++;
+ }
+
+ /* if we couldn't find another connected connector, lets start
+ * looking at the unconnected connectors:
+ *
+ * note: it might not be immediately apparent, but thanks to
+ * the !mgr check in both this loop and the one above, the only
+ * way to enter this loop is with *j == priv->num_connectors,
+ * so idx can never go negative.
+ */
+ while (*j < 2 * priv->num_connectors && !mgr) {
+ int idx = *j - priv->num_connectors;
+ if (!(connected_connectors & (1 << idx))) {
+ struct drm_encoder *encoder =
+ omap_connector_attached_encoder(
+ priv->connectors[idx]);
+ if (encoder) {
+ mgr = omap_encoder_get_manager(encoder);
+ }
+ }
+ (*j)++;
+ }
+
+ if (mgr) {
+ DBG("connecting %s to %s", ovl->name, mgr->name);
+ ovl->set_manager(ovl, mgr);
+ }
+
+ crtc = omap_crtc_init(dev, ovl, priv->num_crtcs);
+
+ if (!crtc) {
+ dev_err(dev->dev, "could not create CRTC: %s\n",
+ ovl->name);
+ return -ENOMEM;
+ }
+
+ BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
+
+ priv->crtcs[priv->num_crtcs++] = crtc;
+
+ return 0;
+}
+
+static int match_dev_name(struct omap_dss_device *dssdev, void *data)
+{
+ return !strcmp(dssdev->name, data);
+}
+
+static unsigned int detect_connectors(struct drm_device *dev)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ unsigned int connected_connectors = 0;
+ int i;
+
+ for (i = 0; i < priv->num_connectors; i++) {
+ struct drm_connector *connector = priv->connectors[i];
+ if (omap_connector_detect(connector, true) ==
+ connector_status_connected) {
+ connected_connectors |= (1 << i);
+ }
+ }
+
+ return connected_connectors;
+}
+
+static int omap_modeset_init(struct drm_device *dev)
+{
+ const struct omap_drm_platform_data *pdata = dev->dev->platform_data;
+ struct omap_kms_platform_data *kms_pdata = NULL;
+ struct omap_drm_private *priv = dev->dev_private;
+ struct omap_dss_device *dssdev = NULL;
+ int i, j;
+ unsigned int connected_connectors = 0;
+
+ drm_mode_config_init(dev);
+
+ if (pdata && pdata->kms_pdata) {
+ kms_pdata = pdata->kms_pdata;
+
+ /* if platform data is provided by the board file, use it to
+ * control which overlays, managers, and devices we own.
+ */
+ for (i = 0; i < kms_pdata->mgr_cnt; i++) {
+ struct omap_overlay_manager *mgr =
+ omap_dss_get_overlay_manager(
+ kms_pdata->mgr_ids[i]);
+ create_encoder(dev, mgr);
+ }
+
+ for (i = 0; i < kms_pdata->dev_cnt; i++) {
+ struct omap_dss_device *dssdev =
+ omap_dss_find_device(
+ (void *)kms_pdata->dev_names[i],
+ match_dev_name);
+ if (!dssdev) {
+ dev_warn(dev->dev, "no such dssdev: %s\n",
+ kms_pdata->dev_names[i]);
+ continue;
+ }
+ create_connector(dev, dssdev);
+ }
+
+ connected_connectors = detect_connectors(dev);
+
+ j = 0;
+ for (i = 0; i < kms_pdata->ovl_cnt; i++) {
+ struct omap_overlay *ovl =
+ omap_dss_get_overlay(kms_pdata->ovl_ids[i]);
+ create_crtc(dev, ovl, &j, connected_connectors);
+ }
+ } else {
+ /* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try
+ * to make educated guesses about everything else
+ */
+ int max_overlays = min(omap_dss_get_num_overlays(), num_crtc);
+
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+ create_encoder(dev, omap_dss_get_overlay_manager(i));
+ }
+
+ for_each_dss_dev(dssdev) {
+ create_connector(dev, dssdev);
+ }
+
+ connected_connectors = detect_connectors(dev);
+
+ j = 0;
+ for (i = 0; i < max_overlays; i++) {
+ create_crtc(dev, omap_dss_get_overlay(i),
+ &j, connected_connectors);
+ }
+ }
+
+ /* for now keep the mapping of CRTCs and encoders static.. */
+ for (i = 0; i < priv->num_encoders; i++) {
+ struct drm_encoder *encoder = priv->encoders[i];
+ struct omap_overlay_manager *mgr =
+ omap_encoder_get_manager(encoder);
+
+ encoder->possible_crtcs = 0;
+
+ for (j = 0; j < priv->num_crtcs; j++) {
+ struct omap_overlay *ovl =
+ omap_crtc_get_overlay(priv->crtcs[j]);
+ if (ovl->manager == mgr) {
+ encoder->possible_crtcs |= (1 << j);
+ }
+ }
+
+ DBG("%s: possible_crtcs=%08x", mgr->name,
+ encoder->possible_crtcs);
+ }
+
+ dump_video_chains();
+
+ dev->mode_config.min_width = 256;
+ dev->mode_config.min_height = 256;
+
+ /* note: eventually will need some cpu_is_omapXYZ() type stuff here
+ * to fill in these limits properly on different OMAP generations..
+ */
+ dev->mode_config.max_width = 2048;
+ dev->mode_config.max_height = 2048;
+
+ dev->mode_config.funcs = &omap_mode_config_funcs;
+
+ return 0;
+}
+
+static void omap_modeset_free(struct drm_device *dev)
+{
+ drm_mode_config_cleanup(dev);
+}
+
+/*
+ * drm ioctl funcs
+ */
+
+
+static int ioctl_get_param(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_omap_param *args = data;
+
+ DBG("%p: param=%llu", dev, args->param);
+
+ switch (args->param) {
+ case OMAP_PARAM_CHIPSET_ID:
+ args->value = GET_OMAP_TYPE;
+ break;
+ default:
+ DBG("unknown parameter %lld", args->param);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ioctl_set_param(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_omap_param *args = data;
+
+ switch (args->param) {
+ default:
+ DBG("unknown parameter %lld", args->param);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ioctl_gem_new(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_omap_gem_new *args = data;
+ DBG("%p:%p: size=0x%08x, flags=%08x", dev, file_priv,
+ args->size.bytes, args->flags);
+ return omap_gem_new_handle(dev, file_priv, args->size,
+ args->flags, &args->handle);
+}
+
+static int ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_omap_gem_cpu_prep *args = data;
+ struct drm_gem_object *obj;
+ int ret;
+
+ VERB("%p:%p: handle=%d, op=%x", dev, file_priv, args->handle, args->op);
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (!obj) {
+ return -ENOENT;
+ }
+
+ ret = omap_gem_op_sync(obj, args->op);
+
+ if (!ret) {
+ ret = omap_gem_op_start(obj, args->op);
+ }
+
+ drm_gem_object_unreference_unlocked(obj);
+
+ return ret;
+}
+
+static int ioctl_gem_cpu_fini(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_omap_gem_cpu_fini *args = data;
+ struct drm_gem_object *obj;
+ int ret;
+
+ VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (!obj) {
+ return -ENOENT;
+ }
+
+ /* XXX flushy, flushy */
+ ret = 0;
+
+ if (!ret) {
+ ret = omap_gem_op_finish(obj, args->op);
+ }
+
+ drm_gem_object_unreference_unlocked(obj);
+
+ return ret;
+}
+
+static int ioctl_gem_info(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_omap_gem_info *args = data;
+ struct drm_gem_object *obj;
+ int ret = 0;
+
+ DBG("%p:%p: handle=%d", dev, file_priv, args->handle);
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (!obj) {
+ return -ENOENT;
+ }
+
+ args->size = omap_gem_mmap_size(obj);
+ args->offset = omap_gem_mmap_offset(obj);
+
+ drm_gem_object_unreference_unlocked(obj);
+
+ return ret;
+}
+
+struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
+ DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, ioctl_gem_cpu_prep, DRM_UNLOCKED|DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, ioctl_gem_cpu_fini, DRM_UNLOCKED|DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info, DRM_UNLOCKED|DRM_AUTH),
+};
+
+/*
+ * drm driver funcs
+ */
+
+/**
+ * load - setup chip and create an initial config
+ * @dev: DRM device
+ * @flags: startup flags
+ *
+ * The driver load routine has to do several things:
+ * - initialize the memory manager
+ * - allocate initial config memory
+ * - setup the DRM framebuffer with the allocated memory
+ */
+static int dev_load(struct drm_device *dev, unsigned long flags)
+{
+ struct omap_drm_private *priv;
+ int ret;
+
+ DBG("load: dev=%p", dev);
+
+ drm_device = dev;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(dev->dev, "could not allocate priv\n");
+ return -ENOMEM;
+ }
+
+ dev->dev_private = priv;
+
+ omap_gem_init(dev);
+
+ ret = omap_modeset_init(dev);
+ if (ret) {
+ dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
+ dev->dev_private = NULL;
+ kfree(priv);
+ return ret;
+ }
+
+ priv->fbdev = omap_fbdev_init(dev);
+ if (!priv->fbdev) {
+ dev_warn(dev->dev, "omap_fbdev_init failed\n");
+ /* well, limp along without an fbdev.. maybe X11 will work? */
+ }
+
+ drm_kms_helper_poll_init(dev);
+
+ ret = drm_vblank_init(dev, priv->num_crtcs);
+ if (ret) {
+ dev_warn(dev->dev, "could not init vblank\n");
+ }
+
+ return 0;
+}
+
+static int dev_unload(struct drm_device *dev)
+{
+ DBG("unload: dev=%p", dev);
+
+ drm_vblank_cleanup(dev);
+ drm_kms_helper_poll_fini(dev);
+
+ omap_fbdev_free(dev);
+ omap_modeset_free(dev);
+ omap_gem_deinit(dev);
+
+ kfree(dev->dev_private);
+ dev->dev_private = NULL;
+
+ return 0;
+}
+
+static int dev_open(struct drm_device *dev, struct drm_file *file)
+{
+ file->driver_priv = NULL;
+
+ DBG("open: dev=%p, file=%p", dev, file);
+
+ return 0;
+}
+
+static int dev_firstopen(struct drm_device *dev)
+{
+ DBG("firstopen: dev=%p", dev);
+ return 0;
+}
+
+/**
+ * lastclose - clean up after all DRM clients have exited
+ * @dev: DRM device
+ *
+ * Take care of cleaning up after all DRM clients have exited. In the
+ * mode setting case, we want to restore the kernel's initial mode (just
+ * in case the last client left us in a bad state).
+ */
+static void dev_lastclose(struct drm_device *dev)
+{
+ /* we don't support vga-switcheroo.. so just make sure the fbdev
+ * mode is active
+ */
+ struct omap_drm_private *priv = dev->dev_private;
+ int ret;
+
+ DBG("lastclose: dev=%p", dev);
+
+ ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
+ if (ret)
+ DBG("failed to restore crtc mode");
+}
+
+static void dev_preclose(struct drm_device *dev, struct drm_file *file)
+{
+ DBG("preclose: dev=%p", dev);
+}
+
+static void dev_postclose(struct drm_device *dev, struct drm_file *file)
+{
+ DBG("postclose: dev=%p, file=%p", dev, file);
+}
+
+/**
+ * enable_vblank - enable vblank interrupt events
+ * @dev: DRM device
+ * @crtc: which irq to enable
+ *
+ * Enable vblank interrupts for @crtc. If the device doesn't have
+ * a hardware vblank counter, this routine should be a no-op, since
+ * interrupts will have to stay on to keep the count accurate.
+ *
+ * RETURNS
+ * Zero on success, appropriate errno if the given @crtc's vblank
+ * interrupt cannot be enabled.
+ */
+static int dev_enable_vblank(struct drm_device *dev, int crtc)
+{
+ DBG("enable_vblank: dev=%p, crtc=%d", dev, crtc);
+ return 0;
+}
+
+/**
+ * disable_vblank - disable vblank interrupt events
+ * @dev: DRM device
+ * @crtc: which irq to enable
+ *
+ * Disable vblank interrupts for @crtc. If the device doesn't have
+ * a hardware vblank counter, this routine should be a no-op, since
+ * interrupts will have to stay on to keep the count accurate.
+ */
+static void dev_disable_vblank(struct drm_device *dev, int crtc)
+{
+ DBG("disable_vblank: dev=%p, crtc=%d", dev, crtc);
+}
+
+static irqreturn_t dev_irq_handler(DRM_IRQ_ARGS)
+{
+ return IRQ_HANDLED;
+}
+
+static void dev_irq_preinstall(struct drm_device *dev)
+{
+ DBG("irq_preinstall: dev=%p", dev);
+}
+
+static int dev_irq_postinstall(struct drm_device *dev)
+{
+ DBG("irq_postinstall: dev=%p", dev);
+ return 0;
+}
+
+static void dev_irq_uninstall(struct drm_device *dev)
+{
+ DBG("irq_uninstall: dev=%p", dev);
+}
+
+static struct vm_operations_struct omap_gem_vm_ops = {
+ .fault = omap_gem_fault,
+ .open = drm_gem_vm_open,
+ .close = drm_gem_vm_close,
+};
+
+static struct drm_driver omap_drm_driver = {
+ .driver_features =
+ DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM,
+ .load = dev_load,
+ .unload = dev_unload,
+ .open = dev_open,
+ .firstopen = dev_firstopen,
+ .lastclose = dev_lastclose,
+ .preclose = dev_preclose,
+ .postclose = dev_postclose,
+ .get_vblank_counter = drm_vblank_count,
+ .enable_vblank = dev_enable_vblank,
+ .disable_vblank = dev_disable_vblank,
+ .irq_preinstall = dev_irq_preinstall,
+ .irq_postinstall = dev_irq_postinstall,
+ .irq_uninstall = dev_irq_uninstall,
+ .irq_handler = dev_irq_handler,
+ .reclaim_buffers = drm_core_reclaim_buffers,
+#ifdef CONFIG_DEBUG_FS
+ .debugfs_init = omap_debugfs_init,
+ .debugfs_cleanup = omap_debugfs_cleanup,
+#endif
+ .gem_init_object = omap_gem_init_object,
+ .gem_free_object = omap_gem_free_object,
+ .gem_vm_ops = &omap_gem_vm_ops,
+ .dumb_create = omap_gem_dumb_create,
+ .dumb_map_offset = omap_gem_dumb_map_offset,
+ .dumb_destroy = omap_gem_dumb_destroy,
+ .ioctls = ioctls,
+ .num_ioctls = DRM_OMAP_NUM_IOCTLS,
+ .fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .unlocked_ioctl = drm_ioctl,
+ .release = drm_release,
+ .mmap = omap_gem_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ .read = drm_read,
+ .llseek = noop_llseek,
+ },
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int pdev_suspend(struct platform_device *pDevice, pm_message_t state)
+{
+ DBG("");
+ return 0;
+}
+
+static int pdev_resume(struct platform_device *device)
+{
+ DBG("");
+ return 0;
+}
+
+static void pdev_shutdown(struct platform_device *device)
+{
+ DBG("");
+}
+
+static int pdev_probe(struct platform_device *device)
+{
+ DBG("%s", device->name);
+ return drm_platform_init(&omap_drm_driver, device);
+}
+
+static int pdev_remove(struct platform_device *device)
+{
+ DBG("");
+ drm_platform_exit(&omap_drm_driver, device);
+ return 0;
+}
+
+struct platform_driver pdev = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = pdev_probe,
+ .remove = pdev_remove,
+ .suspend = pdev_suspend,
+ .resume = pdev_resume,
+ .shutdown = pdev_shutdown,
+};
+
+static int __init omap_drm_init(void)
+{
+ DBG("init");
+ return platform_driver_register(&pdev);
+}
+
+static void __exit omap_drm_fini(void)
+{
+ DBG("fini");
+ platform_driver_unregister(&pdev);
+}
+
+/* need late_initcall() so we load after dss_driver's are loaded */
+late_initcall(omap_drm_init);
+module_exit(omap_drm_fini);
+
+MODULE_AUTHOR("Rob Clark <rob@ti.com>");
+MODULE_DESCRIPTION("OMAP DRM Display Driver");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
new file mode 100644
index 000000000000..76c42515ecc5
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -0,0 +1,135 @@
+/*
+ * drivers/staging/omapdrm/omap_drv.h
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP_DRV_H__
+#define __OMAP_DRV_H__
+
+#include <video/omapdss.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <drm/drmP.h>
+#include "omap_drm.h"
+#include "omap_priv.h"
+
+#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */
+
+#define MODULE_NAME "omapdrm"
+
+/* max # of mapper-id's that can be assigned.. todo, come up with a better
+ * (but still inexpensive) way to store/access per-buffer mapper private
+ * data..
+ */
+#define MAX_MAPPERS 2
+
+struct omap_drm_private {
+ unsigned int num_crtcs;
+ struct drm_crtc *crtcs[8];
+ unsigned int num_encoders;
+ struct drm_encoder *encoders[8];
+ unsigned int num_connectors;
+ struct drm_connector *connectors[8];
+
+ struct drm_fb_helper *fbdev;
+
+ bool has_dmm;
+};
+
+#ifdef CONFIG_DEBUG_FS
+int omap_debugfs_init(struct drm_minor *minor);
+void omap_debugfs_cleanup(struct drm_minor *minor);
+#endif
+
+struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev);
+void omap_fbdev_free(struct drm_device *dev);
+
+struct drm_crtc *omap_crtc_init(struct drm_device *dev,
+ struct omap_overlay *ovl, int id);
+struct omap_overlay *omap_crtc_get_overlay(struct drm_crtc *crtc);
+
+struct drm_encoder *omap_encoder_init(struct drm_device *dev,
+ struct omap_overlay_manager *mgr);
+struct omap_overlay_manager *omap_encoder_get_manager(
+ struct drm_encoder *encoder);
+struct drm_encoder *omap_connector_attached_encoder(
+ struct drm_connector *connector);
+enum drm_connector_status omap_connector_detect(
+ struct drm_connector *connector, bool force);
+
+struct drm_connector *omap_connector_init(struct drm_device *dev,
+ int connector_type, struct omap_dss_device *dssdev);
+void omap_connector_mode_set(struct drm_connector *connector,
+ struct drm_display_mode *mode);
+void omap_connector_flush(struct drm_connector *connector,
+ int x, int y, int w, int h);
+
+struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
+ struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd);
+struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
+ struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo);
+struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb);
+int omap_framebuffer_get_buffer(struct drm_framebuffer *fb, int x, int y,
+ void **vaddr, dma_addr_t *paddr, unsigned int *screen_width);
+struct drm_connector *omap_framebuffer_get_next_connector(
+ struct drm_framebuffer *fb, struct drm_connector *from);
+void omap_framebuffer_flush(struct drm_framebuffer *fb,
+ int x, int y, int w, int h);
+
+void omap_gem_init(struct drm_device *dev);
+void omap_gem_deinit(struct drm_device *dev);
+
+struct drm_gem_object *omap_gem_new(struct drm_device *dev,
+ union omap_gem_size gsize, uint32_t flags);
+int omap_gem_new_handle(struct drm_device *dev, struct drm_file *file,
+ union omap_gem_size gsize, uint32_t flags, uint32_t *handle);
+void omap_gem_free_object(struct drm_gem_object *obj);
+int omap_gem_init_object(struct drm_gem_object *obj);
+void *omap_gem_vaddr(struct drm_gem_object *obj);
+int omap_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
+ uint32_t handle, uint64_t *offset);
+int omap_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
+ uint32_t handle);
+int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+int omap_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+int omap_gem_op_start(struct drm_gem_object *obj, enum omap_gem_op op);
+int omap_gem_op_finish(struct drm_gem_object *obj, enum omap_gem_op op);
+int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op);
+int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op,
+ void (*fxn)(void *arg), void *arg);
+int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll);
+int omap_gem_get_paddr(struct drm_gem_object *obj,
+ dma_addr_t *paddr, bool remap);
+int omap_gem_put_paddr(struct drm_gem_object *obj);
+uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj);
+size_t omap_gem_mmap_size(struct drm_gem_object *obj);
+
+static inline int align_pitch(int pitch, int width, int bpp)
+{
+ int bytespp = (bpp + 7) / 8;
+ /* in case someone tries to feed us a completely bogus stride: */
+ pitch = max(pitch, width * bytespp);
+ /* PVR needs alignment to 8 pixels.. right now that is the most
+ * restrictive stride requirement..
+ */
+ return ALIGN(pitch, 8 * bytespp);
+}
+
+#endif /* __OMAP_DRV_H__ */
diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c
new file mode 100644
index 000000000000..06c52cb62d2f
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_encoder.c
@@ -0,0 +1,171 @@
+/*
+ * drivers/staging/omapdrm/omap_encoder.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+/*
+ * encoder funcs
+ */
+
+#define to_omap_encoder(x) container_of(x, struct omap_encoder, base)
+
+struct omap_encoder {
+ struct drm_encoder base;
+ struct omap_overlay_manager *mgr;
+};
+
+static void omap_encoder_destroy(struct drm_encoder *encoder)
+{
+ struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+ DBG("%s", omap_encoder->mgr->name);
+ drm_encoder_cleanup(encoder);
+ kfree(omap_encoder);
+}
+
+static void omap_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+ DBG("%s: %d", omap_encoder->mgr->name, mode);
+}
+
+static bool omap_encoder_mode_fixup(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+ DBG("%s", omap_encoder->mgr->name);
+ return true;
+}
+
+static void omap_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+ struct drm_device *dev = encoder->dev;
+ struct omap_drm_private *priv = dev->dev_private;
+ int i;
+
+ mode = adjusted_mode;
+
+ DBG("%s: set mode: %dx%d", omap_encoder->mgr->name,
+ mode->hdisplay, mode->vdisplay);
+
+ for (i = 0; i < priv->num_connectors; i++) {
+ struct drm_connector *connector = priv->connectors[i];
+ if (connector->encoder == encoder) {
+ omap_connector_mode_set(connector, mode);
+ }
+ }
+}
+
+static void omap_encoder_prepare(struct drm_encoder *encoder)
+{
+ struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+ struct drm_encoder_helper_funcs *encoder_funcs =
+ encoder->helper_private;
+ DBG("%s", omap_encoder->mgr->name);
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void omap_encoder_commit(struct drm_encoder *encoder)
+{
+ struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+ struct drm_encoder_helper_funcs *encoder_funcs =
+ encoder->helper_private;
+ DBG("%s", omap_encoder->mgr->name);
+ omap_encoder->mgr->apply(omap_encoder->mgr);
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static const struct drm_encoder_funcs omap_encoder_funcs = {
+ .destroy = omap_encoder_destroy,
+};
+
+static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
+ .dpms = omap_encoder_dpms,
+ .mode_fixup = omap_encoder_mode_fixup,
+ .mode_set = omap_encoder_mode_set,
+ .prepare = omap_encoder_prepare,
+ .commit = omap_encoder_commit,
+};
+
+struct omap_overlay_manager *omap_encoder_get_manager(
+ struct drm_encoder *encoder)
+{
+ struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+ return omap_encoder->mgr;
+}
+
+/* initialize encoder */
+struct drm_encoder *omap_encoder_init(struct drm_device *dev,
+ struct omap_overlay_manager *mgr)
+{
+ struct drm_encoder *encoder = NULL;
+ struct omap_encoder *omap_encoder;
+ struct omap_overlay_manager_info info;
+ int ret;
+
+ DBG("%s", mgr->name);
+
+ omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL);
+ if (!omap_encoder) {
+ dev_err(dev->dev, "could not allocate encoder\n");
+ goto fail;
+ }
+
+ omap_encoder->mgr = mgr;
+ encoder = &omap_encoder->base;
+
+ drm_encoder_init(dev, encoder, &omap_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS);
+ drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);
+
+ mgr->get_manager_info(mgr, &info);
+
+ /* TODO: fix hard-coded setup.. */
+ info.default_color = 0x00000000;
+ info.trans_key = 0x00000000;
+ info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+ info.trans_enabled = false;
+
+ ret = mgr->set_manager_info(mgr, &info);
+ if (ret) {
+ dev_err(dev->dev, "could not set manager info\n");
+ goto fail;
+ }
+
+ ret = mgr->apply(mgr);
+ if (ret) {
+ dev_err(dev->dev, "could not apply\n");
+ goto fail;
+ }
+
+ return encoder;
+
+fail:
+ if (encoder) {
+ omap_encoder_destroy(encoder);
+ }
+
+ return NULL;
+}
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
new file mode 100644
index 000000000000..0b50c5b3b564
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -0,0 +1,243 @@
+/*
+ * drivers/staging/omapdrm/omap_fb.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+
+/*
+ * framebuffer funcs
+ */
+
+#define to_omap_framebuffer(x) container_of(x, struct omap_framebuffer, base)
+
+struct omap_framebuffer {
+ struct drm_framebuffer base;
+ struct drm_gem_object *bo;
+ int size;
+ dma_addr_t paddr;
+};
+
+static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv,
+ unsigned int *handle)
+{
+ struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+ return drm_gem_handle_create(file_priv, omap_fb->bo, handle);
+}
+
+static void omap_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+ struct drm_device *dev = fb->dev;
+ struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+
+ DBG("destroy: FB ID: %d (%p)", fb->base.id, fb);
+
+ drm_framebuffer_cleanup(fb);
+
+ if (omap_fb->bo) {
+ if (omap_fb->paddr && omap_gem_put_paddr(omap_fb->bo))
+ dev_err(dev->dev, "could not unmap!\n");
+ drm_gem_object_unreference_unlocked(omap_fb->bo);
+ }
+
+ kfree(omap_fb);
+}
+
+static int omap_framebuffer_dirty(struct drm_framebuffer *fb,
+ struct drm_file *file_priv, unsigned flags, unsigned color,
+ struct drm_clip_rect *clips, unsigned num_clips)
+{
+ int i;
+
+ for (i = 0; i < num_clips; i++) {
+ omap_framebuffer_flush(fb, clips[i].x1, clips[i].y1,
+ clips[i].x2 - clips[i].x1,
+ clips[i].y2 - clips[i].y1);
+ }
+
+ return 0;
+}
+
+static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
+ .create_handle = omap_framebuffer_create_handle,
+ .destroy = omap_framebuffer_destroy,
+ .dirty = omap_framebuffer_dirty,
+};
+
+/* returns the buffer size */
+int omap_framebuffer_get_buffer(struct drm_framebuffer *fb, int x, int y,
+ void **vaddr, dma_addr_t *paddr, unsigned int *screen_width)
+{
+ struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+ int bpp = fb->bits_per_pixel / 8;
+ unsigned long offset;
+
+ offset = (x * bpp) + (y * fb->pitch);
+
+ if (vaddr) {
+ void *bo_vaddr = omap_gem_vaddr(omap_fb->bo);
+ /* note: we can only count on having a vaddr for buffers that
+ * are allocated physically contiguously to begin with (ie.
+ * dma_alloc_coherent()). But this should be ok because it
+ * is only used by legacy fbdev
+ */
+ BUG_ON(IS_ERR_OR_NULL(bo_vaddr));
+ *vaddr = bo_vaddr + offset;
+ }
+
+ *paddr = omap_fb->paddr + offset;
+ *screen_width = fb->pitch / bpp;
+
+ return omap_fb->size - offset;
+}
+
+struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb)
+{
+ struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+ return omap_fb->bo;
+}
+
+/* iterate thru all the connectors, returning ones that are attached
+ * to the same fb..
+ */
+struct drm_connector *omap_framebuffer_get_next_connector(
+ struct drm_framebuffer *fb, struct drm_connector *from)
+{
+ struct drm_device *dev = fb->dev;
+ struct list_head *connector_list = &dev->mode_config.connector_list;
+ struct drm_connector *connector = from;
+
+ if (!from) {
+ return list_first_entry(connector_list, typeof(*from), head);
+ }
+
+ list_for_each_entry_from(connector, connector_list, head) {
+ if (connector != from) {
+ struct drm_encoder *encoder = connector->encoder;
+ struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
+ if (crtc && crtc->fb == fb) {
+ return connector;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/* flush an area of the framebuffer (in case of manual update display that
+ * is not automatically flushed)
+ */
+void omap_framebuffer_flush(struct drm_framebuffer *fb,
+ int x, int y, int w, int h)
+{
+ struct drm_connector *connector = NULL;
+
+ VERB("flush: %d,%d %dx%d, fb=%p", x, y, w, h, fb);
+
+ while ((connector = omap_framebuffer_get_next_connector(fb, connector))) {
+ /* only consider connectors that are part of a chain */
+ if (connector->encoder && connector->encoder->crtc) {
+ /* TODO: maybe this should propagate thru the crtc who
+ * could do the coordinate translation..
+ */
+ struct drm_crtc *crtc = connector->encoder->crtc;
+ int cx = max(0, x - crtc->x);
+ int cy = max(0, y - crtc->y);
+ int cw = w + (x - crtc->x) - cx;
+ int ch = h + (y - crtc->y) - cy;
+
+ omap_connector_flush(connector, cx, cy, cw, ch);
+ }
+ }
+}
+
+struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
+ struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd)
+{
+ struct drm_gem_object *bo;
+ struct drm_framebuffer *fb;
+ bo = drm_gem_object_lookup(dev, file, mode_cmd->handle);
+ if (!bo) {
+ return ERR_PTR(-ENOENT);
+ }
+ fb = omap_framebuffer_init(dev, mode_cmd, bo);
+ if (!fb) {
+ return ERR_PTR(-ENOMEM);
+ }
+ return fb;
+}
+
+struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
+ struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo)
+{
+ struct omap_framebuffer *omap_fb;
+ struct drm_framebuffer *fb = NULL;
+ int size, ret;
+
+ DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%d)",
+ dev, mode_cmd, mode_cmd->width, mode_cmd->height,
+ mode_cmd->bpp);
+
+ /* in case someone tries to feed us a completely bogus stride: */
+ mode_cmd->pitch = align_pitch(mode_cmd->pitch,
+ mode_cmd->width, mode_cmd->bpp);
+
+ omap_fb = kzalloc(sizeof(*omap_fb), GFP_KERNEL);
+ if (!omap_fb) {
+ dev_err(dev->dev, "could not allocate fb\n");
+ goto fail;
+ }
+
+ fb = &omap_fb->base;
+ ret = drm_framebuffer_init(dev, fb, &omap_framebuffer_funcs);
+ if (ret) {
+ dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
+ goto fail;
+ }
+
+ DBG("create: FB ID: %d (%p)", fb->base.id, fb);
+
+ size = PAGE_ALIGN(mode_cmd->pitch * mode_cmd->height);
+
+ if (size > bo->size) {
+ dev_err(dev->dev, "provided buffer object is too small!\n");
+ goto fail;
+ }
+
+ omap_fb->bo = bo;
+ omap_fb->size = size;
+
+ if (omap_gem_get_paddr(bo, &omap_fb->paddr, true)) {
+ dev_err(dev->dev, "could not map (paddr)!\n");
+ goto fail;
+ }
+
+ drm_helper_mode_fill_fb_struct(fb, mode_cmd);
+
+ return fb;
+
+fail:
+ if (fb) {
+ omap_framebuffer_destroy(fb);
+ }
+ return NULL;
+}
diff --git a/drivers/staging/omapdrm/omap_fbdev.c b/drivers/staging/omapdrm/omap_fbdev.c
new file mode 100644
index 000000000000..093ae2f87b20
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_fbdev.c
@@ -0,0 +1,372 @@
+/*
+ * drivers/staging/omapdrm/omap_fbdev.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+#include "drm_crtc.h"
+#include "drm_fb_helper.h"
+
+MODULE_PARM_DESC(ywrap, "Enable ywrap scrolling (omap44xx and later, default 'y')");
+static bool ywrap_enabled = true;
+module_param_named(ywrap, ywrap_enabled, bool, 0644);
+
+/*
+ * fbdev funcs, to implement legacy fbdev interface on top of drm driver
+ */
+
+#define to_omap_fbdev(x) container_of(x, struct omap_fbdev, base)
+
+struct omap_fbdev {
+ struct drm_fb_helper base;
+ struct drm_framebuffer *fb;
+ struct drm_gem_object *bo;
+ bool ywrap_enabled;
+};
+
+static void omap_fbdev_flush(struct fb_info *fbi, int x, int y, int w, int h);
+static struct drm_fb_helper *get_fb(struct fb_info *fbi);
+
+static ssize_t omap_fbdev_write(struct fb_info *fbi, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t res;
+
+ res = fb_sys_write(fbi, buf, count, ppos);
+ omap_fbdev_flush(fbi, 0, 0, fbi->var.xres, fbi->var.yres);
+
+ return res;
+}
+
+static void omap_fbdev_fillrect(struct fb_info *fbi,
+ const struct fb_fillrect *rect)
+{
+ sys_fillrect(fbi, rect);
+ omap_fbdev_flush(fbi, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+static void omap_fbdev_copyarea(struct fb_info *fbi,
+ const struct fb_copyarea *area)
+{
+ sys_copyarea(fbi, area);
+ omap_fbdev_flush(fbi, area->dx, area->dy, area->width, area->height);
+}
+
+static void omap_fbdev_imageblit(struct fb_info *fbi,
+ const struct fb_image *image)
+{
+ sys_imageblit(fbi, image);
+ omap_fbdev_flush(fbi, image->dx, image->dy,
+ image->width, image->height);
+}
+
+static int omap_fbdev_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *fbi)
+{
+ struct drm_fb_helper *helper = get_fb(fbi);
+ struct omap_fbdev *fbdev = to_omap_fbdev(helper);
+ int npages;
+
+ if (!helper)
+ goto fallback;
+
+ if (!fbdev->ywrap_enabled)
+ goto fallback;
+
+ /* DMM roll shifts in 4K pages: */
+ npages = fbi->fix.line_length >> PAGE_SHIFT;
+ omap_gem_roll(fbdev->bo, var->yoffset * npages);
+
+ return 0;
+
+fallback:
+ return drm_fb_helper_pan_display(var, fbi);
+}
+
+static struct fb_ops omap_fb_ops = {
+ .owner = THIS_MODULE,
+
+ /* Note: to properly handle manual update displays, we wrap the
+ * basic fbdev ops which write to the framebuffer
+ */
+ .fb_read = fb_sys_read,
+ .fb_write = omap_fbdev_write,
+ .fb_fillrect = omap_fbdev_fillrect,
+ .fb_copyarea = omap_fbdev_copyarea,
+ .fb_imageblit = omap_fbdev_imageblit,
+
+ .fb_check_var = drm_fb_helper_check_var,
+ .fb_set_par = drm_fb_helper_set_par,
+ .fb_pan_display = omap_fbdev_pan_display,
+ .fb_blank = drm_fb_helper_blank,
+ .fb_setcmap = drm_fb_helper_setcmap,
+
+ .fb_debug_enter = drm_fb_helper_debug_enter,
+ .fb_debug_leave = drm_fb_helper_debug_leave,
+};
+
+static int omap_fbdev_create(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct omap_fbdev *fbdev = to_omap_fbdev(helper);
+ struct drm_device *dev = helper->dev;
+ struct omap_drm_private *priv = dev->dev_private;
+ struct drm_framebuffer *fb = NULL;
+ union omap_gem_size gsize;
+ struct fb_info *fbi = NULL;
+ struct drm_mode_fb_cmd mode_cmd = {0};
+ dma_addr_t paddr;
+ void __iomem *vaddr;
+ int size, screen_width;
+ int ret;
+
+ /* only doing ARGB32 since this is what is needed to alpha-blend
+ * with video overlays:
+ */
+ sizes->surface_bpp = 32;
+ sizes->surface_depth = 32;
+
+ DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width,
+ sizes->surface_height, sizes->surface_bpp,
+ sizes->fb_width, sizes->fb_height);
+
+ mode_cmd.width = sizes->surface_width;
+ mode_cmd.height = sizes->surface_height;
+
+ mode_cmd.bpp = sizes->surface_bpp;
+ mode_cmd.depth = sizes->surface_depth;
+
+ mode_cmd.pitch = align_pitch(
+ mode_cmd.width * ((mode_cmd.bpp + 7) / 8),
+ mode_cmd.width, mode_cmd.bpp);
+
+ fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled;
+ if (fbdev->ywrap_enabled) {
+ /* need to align pitch to page size if using DMM scrolling */
+ mode_cmd.pitch = ALIGN(mode_cmd.pitch, PAGE_SIZE);
+ }
+
+ /* allocate backing bo */
+ gsize = (union omap_gem_size){
+ .bytes = PAGE_ALIGN(mode_cmd.pitch * mode_cmd.height),
+ };
+ DBG("allocating %d bytes for fb %d", gsize.bytes, dev->primary->index);
+ fbdev->bo = omap_gem_new(dev, gsize, OMAP_BO_SCANOUT | OMAP_BO_WC);
+ if (!fbdev->bo) {
+ dev_err(dev->dev, "failed to allocate buffer object\n");
+ goto fail;
+ }
+
+ fb = omap_framebuffer_init(dev, &mode_cmd, fbdev->bo);
+ if (!fb) {
+ dev_err(dev->dev, "failed to allocate fb\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ mutex_lock(&dev->struct_mutex);
+
+ fbi = framebuffer_alloc(0, dev->dev);
+ if (!fbi) {
+ dev_err(dev->dev, "failed to allocate fb info\n");
+ ret = -ENOMEM;
+ goto fail_unlock;
+ }
+
+ DBG("fbi=%p, dev=%p", fbi, dev);
+
+ fbdev->fb = fb;
+ helper->fb = fb;
+ helper->fbdev = fbi;
+
+ fbi->par = helper;
+ fbi->flags = FBINFO_DEFAULT;
+ fbi->fbops = &omap_fb_ops;
+
+ strcpy(fbi->fix.id, MODULE_NAME);
+
+ ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+ if (ret) {
+ ret = -ENOMEM;
+ goto fail_unlock;
+ }
+
+ drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
+ drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
+
+ size = omap_framebuffer_get_buffer(fb, 0, 0,
+ &vaddr, &paddr, &screen_width);
+
+ dev->mode_config.fb_base = paddr;
+
+ fbi->screen_base = vaddr;
+ fbi->screen_size = size;
+ fbi->fix.smem_start = paddr;
+ fbi->fix.smem_len = size;
+
+ /* if we have DMM, then we can use it for scrolling by just
+ * shuffling pages around in DMM rather than doing sw blit.
+ */
+ if (fbdev->ywrap_enabled) {
+ DRM_INFO("Enabling DMM ywrap scrolling\n");
+ fbi->flags |= FBINFO_HWACCEL_YWRAP | FBINFO_READS_FAST;
+ fbi->fix.ywrapstep = 1;
+ }
+
+
+ DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres);
+ DBG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height);
+
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+
+fail_unlock:
+ mutex_unlock(&dev->struct_mutex);
+fail:
+
+ if (ret) {
+ if (fbi)
+ framebuffer_release(fbi);
+ if (fb)
+ fb->funcs->destroy(fb);
+ }
+
+ return ret;
+}
+
+static void omap_crtc_fb_gamma_set(struct drm_crtc *crtc,
+ u16 red, u16 green, u16 blue, int regno)
+{
+ DBG("fbdev: set gamma");
+}
+
+static void omap_crtc_fb_gamma_get(struct drm_crtc *crtc,
+ u16 *red, u16 *green, u16 *blue, int regno)
+{
+ DBG("fbdev: get gamma");
+}
+
+static int omap_fbdev_probe(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ int new_fb = 0;
+ int ret;
+
+ if (!helper->fb) {
+ ret = omap_fbdev_create(helper, sizes);
+ if (ret)
+ return ret;
+ new_fb = 1;
+ }
+ return new_fb;
+}
+
+static struct drm_fb_helper_funcs omap_fb_helper_funcs = {
+ .gamma_set = omap_crtc_fb_gamma_set,
+ .gamma_get = omap_crtc_fb_gamma_get,
+ .fb_probe = omap_fbdev_probe,
+};
+
+static struct drm_fb_helper *get_fb(struct fb_info *fbi)
+{
+ if (!fbi || strcmp(fbi->fix.id, MODULE_NAME)) {
+ /* these are not the fb's you're looking for */
+ return NULL;
+ }
+ return fbi->par;
+}
+
+/* flush an area of the framebuffer (in case of manual update display that
+ * is not automatically flushed)
+ */
+static void omap_fbdev_flush(struct fb_info *fbi, int x, int y, int w, int h)
+{
+ struct drm_fb_helper *helper = get_fb(fbi);
+
+ if (!helper)
+ return;
+
+ VERB("flush fbdev: %d,%d %dx%d, fbi=%p", x, y, w, h, fbi);
+
+ omap_framebuffer_flush(helper->fb, x, y, w, h);
+}
+
+/* initialize fbdev helper */
+struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ struct omap_fbdev *fbdev = NULL;
+ struct drm_fb_helper *helper;
+ int ret = 0;
+
+ fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+ if (!fbdev) {
+ dev_err(dev->dev, "could not allocate fbdev\n");
+ goto fail;
+ }
+
+ helper = &fbdev->base;
+
+ helper->funcs = &omap_fb_helper_funcs;
+
+ ret = drm_fb_helper_init(dev, helper,
+ priv->num_crtcs, priv->num_connectors);
+ if (ret) {
+ dev_err(dev->dev, "could not init fbdev: ret=%d\n", ret);
+ goto fail;
+ }
+
+ drm_fb_helper_single_add_all_connectors(helper);
+ drm_fb_helper_initial_config(helper, 32);
+
+ priv->fbdev = helper;
+
+ return helper;
+
+fail:
+ kfree(fbdev);
+ return NULL;
+}
+
+void omap_fbdev_free(struct drm_device *dev)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ struct drm_fb_helper *helper = priv->fbdev;
+ struct omap_fbdev *fbdev;
+ struct fb_info *fbi;
+
+ DBG();
+
+ fbi = helper->fbdev;
+
+ unregister_framebuffer(fbi);
+ framebuffer_release(fbi);
+
+ drm_fb_helper_fini(helper);
+
+ fbdev = to_omap_fbdev(priv->fbdev);
+
+ kfree(fbdev);
+
+ /* this will free the backing object */
+ if (fbdev->fb)
+ fbdev->fb->funcs->destroy(fbdev->fb);
+
+ priv->fbdev = NULL;
+}
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
new file mode 100644
index 000000000000..e0ebd1d139f6
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_gem.c
@@ -0,0 +1,1231 @@
+/*
+ * drivers/staging/omapdrm/omap_gem.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <linux/spinlock.h>
+#include <linux/shmem_fs.h>
+
+#include "omap_drv.h"
+#include "omap_dmm_tiler.h"
+
+/* remove these once drm core helpers are merged */
+struct page ** _drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
+void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
+ bool dirty, bool accessed);
+int _drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
+
+/*
+ * GEM buffer object implementation.
+ */
+
+#define to_omap_bo(x) container_of(x, struct omap_gem_object, base)
+
+/* note: we use upper 8 bits of flags for driver-internal flags: */
+#define OMAP_BO_DMA 0x01000000 /* actually is physically contiguous */
+#define OMAP_BO_EXT_SYNC 0x02000000 /* externally allocated sync object */
+#define OMAP_BO_EXT_MEM 0x04000000 /* externally allocated memory */
+
+
+struct omap_gem_object {
+ struct drm_gem_object base;
+
+ uint32_t flags;
+
+ /** width/height for tiled formats (rounded up to slot boundaries) */
+ uint16_t width, height;
+
+ /** roll applied when mapping to DMM */
+ uint32_t roll;
+
+ /**
+ * If buffer is allocated physically contiguous, the OMAP_BO_DMA flag
+ * is set and the paddr is valid. Also if the buffer is remapped in
+ * TILER and paddr_cnt > 0, then paddr is valid. But if you are using
+ * the physical address and OMAP_BO_DMA is not set, then you should
+ * be going thru omap_gem_{get,put}_paddr() to ensure the mapping is
+ * not removed from under your feet.
+ *
+ * Note that OMAP_BO_SCANOUT is a hint from userspace that DMA capable
+ * buffer is requested, but doesn't mean that it is. Use the
+ * OMAP_BO_DMA flag to determine if the buffer has a DMA capable
+ * physical address.
+ */
+ dma_addr_t paddr;
+
+ /**
+ * # of users of paddr
+ */
+ uint32_t paddr_cnt;
+
+ /**
+ * tiler block used when buffer is remapped in DMM/TILER.
+ */
+ struct tiler_block *block;
+
+ /**
+ * Array of backing pages, if allocated. Note that pages are never
+ * allocated for buffers originally allocated from contiguous memory
+ */
+ struct page **pages;
+
+ /** addresses corresponding to pages in above array */
+ dma_addr_t *addrs;
+
+ /**
+ * Virtual address, if mapped.
+ */
+ void *vaddr;
+
+ /**
+ * sync-object allocated on demand (if needed)
+ *
+ * Per-buffer sync-object for tracking pending and completed hw/dma
+ * read and write operations. The layout in memory is dictated by
+ * the SGX firmware, which uses this information to stall the command
+ * stream if a surface is not ready yet.
+ *
+ * Note that when buffer is used by SGX, the sync-object needs to be
+ * allocated from a special heap of sync-objects. This way many sync
+ * objects can be packed in a page, and not waste GPU virtual address
+ * space. Because of this we have to have a omap_gem_set_sync_object()
+ * API to allow replacement of the syncobj after it has (potentially)
+ * already been allocated. A bit ugly but I haven't thought of a
+ * better alternative.
+ */
+ struct {
+ uint32_t write_pending;
+ uint32_t write_complete;
+ uint32_t read_pending;
+ uint32_t read_complete;
+ } *sync;
+};
+
+/* To deal with userspace mmap'ings of 2d tiled buffers, which (a) are
+ * not necessarily pinned in TILER all the time, and (b) when they are
+ * they are not necessarily page aligned, we reserve one or more small
+ * regions in each of the 2d containers to use as a user-GART where we
+ * can create a second page-aligned mapping of parts of the buffer
+ * being accessed from userspace.
+ *
+ * Note that we could optimize slightly when we know that multiple
+ * tiler containers are backed by the same PAT.. but I'll leave that
+ * for later..
+ */
+#define NUM_USERGART_ENTRIES 2
+struct usergart_entry {
+ struct tiler_block *block; /* the reserved tiler block */
+ dma_addr_t paddr;
+ struct drm_gem_object *obj; /* the current pinned obj */
+ pgoff_t obj_pgoff; /* page offset of obj currently
+ mapped in */
+};
+static struct {
+ struct usergart_entry entry[NUM_USERGART_ENTRIES];
+ int height; /* height in rows */
+ int height_shift; /* ilog2(height in rows) */
+ int slot_shift; /* ilog2(width per slot) */
+ int stride_pfn; /* stride in pages */
+ int last; /* index of last used entry */
+} *usergart;
+
+static void evict_entry(struct drm_gem_object *obj,
+ enum tiler_fmt fmt, struct usergart_entry *entry)
+{
+ if (obj->dev->dev_mapping) {
+ size_t size = PAGE_SIZE * usergart[fmt].height;
+ loff_t off = omap_gem_mmap_offset(obj) +
+ (entry->obj_pgoff << PAGE_SHIFT);
+ unmap_mapping_range(obj->dev->dev_mapping, off, size, 1);
+ }
+
+ entry->obj = NULL;
+}
+
+/* Evict a buffer from usergart, if it is mapped there */
+static void evict(struct drm_gem_object *obj)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+
+ if (omap_obj->flags & OMAP_BO_TILED) {
+ enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
+ int i;
+
+ if (!usergart)
+ return;
+
+ for (i = 0; i < NUM_USERGART_ENTRIES; i++) {
+ struct usergart_entry *entry = &usergart[fmt].entry[i];
+ if (entry->obj == obj)
+ evict_entry(obj, fmt, entry);
+ }
+ }
+}
+
+/* GEM objects can either be allocated from contiguous memory (in which
+ * case obj->filp==NULL), or w/ shmem backing (obj->filp!=NULL). But non
+ * contiguous buffers can be remapped in TILER/DMM if they need to be
+ * contiguous... but we don't do this all the time to reduce pressure
+ * on TILER/DMM space when we know at allocation time that the buffer
+ * will need to be scanned out.
+ */
+static inline bool is_shmem(struct drm_gem_object *obj)
+{
+ return obj->filp != NULL;
+}
+
+static int get_pages(struct drm_gem_object *obj, struct page ***pages);
+
+static DEFINE_SPINLOCK(sync_lock);
+
+/** ensure backing pages are allocated */
+static int omap_gem_attach_pages(struct drm_gem_object *obj)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ struct page **pages;
+
+ WARN_ON(omap_obj->pages);
+
+ /* TODO: __GFP_DMA32 .. but somehow GFP_HIGHMEM is coming from the
+ * mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably
+ * we actually want CMA memory for it all anyways..
+ */
+ pages = _drm_gem_get_pages(obj, GFP_KERNEL);
+ if (IS_ERR(pages)) {
+ dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages));
+ return PTR_ERR(pages);
+ }
+
+ /* for non-cached buffers, ensure the new pages are clean because
+ * DSS, GPU, etc. are not cache coherent:
+ */
+ if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
+ int i, npages = obj->size >> PAGE_SHIFT;
+ dma_addr_t *addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL);
+ for (i = 0; i < npages; i++) {
+ addrs[i] = dma_map_page(obj->dev->dev, pages[i],
+ 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
+ }
+ omap_obj->addrs = addrs;
+ }
+
+ omap_obj->pages = pages;
+ return 0;
+}
+
+/** release backing pages */
+static void omap_gem_detach_pages(struct drm_gem_object *obj)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+
+ /* for non-cached buffers, ensure the new pages are clean because
+ * DSS, GPU, etc. are not cache coherent:
+ */
+ if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
+ int i, npages = obj->size >> PAGE_SHIFT;
+ for (i = 0; i < npages; i++) {
+ dma_unmap_page(obj->dev->dev, omap_obj->addrs[i],
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ }
+ kfree(omap_obj->addrs);
+ omap_obj->addrs = NULL;
+ }
+
+ _drm_gem_put_pages(obj, omap_obj->pages, true, false);
+ omap_obj->pages = NULL;
+}
+
+/** get mmap offset */
+uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
+{
+ if (!obj->map_list.map) {
+ /* Make it mmapable */
+ size_t size = omap_gem_mmap_size(obj);
+ int ret = _drm_gem_create_mmap_offset_size(obj, size);
+
+ if (ret) {
+ dev_err(obj->dev->dev, "could not allocate mmap offset");
+ return 0;
+ }
+ }
+
+ return (uint64_t)obj->map_list.hash.key << PAGE_SHIFT;
+}
+
+/** get mmap size */
+size_t omap_gem_mmap_size(struct drm_gem_object *obj)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ size_t size = obj->size;
+
+ if (omap_obj->flags & OMAP_BO_TILED) {
+ /* for tiled buffers, the virtual size has stride rounded up
+ * to 4kb.. (to hide the fact that row n+1 might start 16kb or
+ * 32kb later!). But we don't back the entire buffer with
+ * pages, only the valid picture part.. so need to adjust for
+ * this in the size used to mmap and generate mmap offset
+ */
+ size = tiler_vsize(gem2fmt(omap_obj->flags),
+ omap_obj->width, omap_obj->height);
+ }
+
+ return size;
+}
+
+
+/* Normal handling for the case of faulting in non-tiled buffers */
+static int fault_1d(struct drm_gem_object *obj,
+ struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ unsigned long pfn;
+ pgoff_t pgoff;
+
+ /* We don't use vmf->pgoff since that has the fake offset: */
+ pgoff = ((unsigned long)vmf->virtual_address -
+ vma->vm_start) >> PAGE_SHIFT;
+
+ if (omap_obj->pages) {
+ pfn = page_to_pfn(omap_obj->pages[pgoff]);
+ } else {
+ BUG_ON(!(omap_obj->flags & OMAP_BO_DMA));
+ pfn = (omap_obj->paddr >> PAGE_SHIFT) + pgoff;
+ }
+
+ VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
+ pfn, pfn << PAGE_SHIFT);
+
+ return vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
+}
+
+/* Special handling for the case of faulting in 2d tiled buffers */
+static int fault_2d(struct drm_gem_object *obj,
+ struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ struct usergart_entry *entry;
+ enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
+ struct page *pages[64]; /* XXX is this too much to have on stack? */
+ unsigned long pfn;
+ pgoff_t pgoff, base_pgoff;
+ void __user *vaddr;
+ int i, ret, slots;
+
+ if (!usergart)
+ return -EFAULT;
+
+ /* TODO: this fxn might need a bit tweaking to deal w/ tiled buffers
+ * that are wider than 4kb
+ */
+
+ /* We don't use vmf->pgoff since that has the fake offset: */
+ pgoff = ((unsigned long)vmf->virtual_address -
+ vma->vm_start) >> PAGE_SHIFT;
+
+ /* actual address we start mapping at is rounded down to previous slot
+ * boundary in the y direction:
+ */
+ base_pgoff = round_down(pgoff, usergart[fmt].height);
+ vaddr = vmf->virtual_address - ((pgoff - base_pgoff) << PAGE_SHIFT);
+ entry = &usergart[fmt].entry[usergart[fmt].last];
+
+ slots = omap_obj->width >> usergart[fmt].slot_shift;
+
+ /* evict previous buffer using this usergart entry, if any: */
+ if (entry->obj)
+ evict_entry(entry->obj, fmt, entry);
+
+ entry->obj = obj;
+ entry->obj_pgoff = base_pgoff;
+
+ /* now convert base_pgoff to phys offset from virt offset:
+ */
+ base_pgoff = (base_pgoff >> usergart[fmt].height_shift) * slots;
+
+ /* map in pages. Note the height of the slot is also equal to the
+ * number of pages that need to be mapped in to fill 4kb wide CPU page.
+ * If the height is 64, then 64 pages fill a 4kb wide by 64 row region.
+ * Beyond the valid pixel part of the buffer, we set pages[i] to NULL to
+ * get a dummy page mapped in.. if someone reads/writes it they will get
+ * random/undefined content, but at least it won't be corrupting
+ * whatever other random page used to be mapped in, or other undefined
+ * behavior.
+ */
+ memcpy(pages, &omap_obj->pages[base_pgoff],
+ sizeof(struct page *) * slots);
+ memset(pages + slots, 0,
+ sizeof(struct page *) * (usergart[fmt].height - slots));
+
+ ret = tiler_pin(entry->block, pages, ARRAY_SIZE(pages), 0, true);
+ if (ret) {
+ dev_err(obj->dev->dev, "failed to pin: %d\n", ret);
+ return ret;
+ }
+
+ i = usergart[fmt].height;
+ pfn = entry->paddr >> PAGE_SHIFT;
+
+ VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
+ pfn, pfn << PAGE_SHIFT);
+
+ while (i--) {
+ vm_insert_mixed(vma, (unsigned long)vaddr, pfn);
+ pfn += usergart[fmt].stride_pfn;
+ vaddr += PAGE_SIZE;
+ }
+
+ /* simple round-robin: */
+ usergart[fmt].last = (usergart[fmt].last + 1) % NUM_USERGART_ENTRIES;
+
+ return 0;
+}
+
+/**
+ * omap_gem_fault - pagefault handler for GEM objects
+ * @vma: the VMA of the GEM object
+ * @vmf: fault detail
+ *
+ * Invoked when a fault occurs on an mmap of a GEM managed area. GEM
+ * does most of the work for us including the actual map/unmap calls
+ * but we need to do the actual page work.
+ *
+ * The VMA was set up by GEM. In doing so it also ensured that the
+ * vma->vm_private_data points to the GEM object that is backing this
+ * mapping.
+ */
+int omap_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct drm_gem_object *obj = vma->vm_private_data;
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ struct drm_device *dev = obj->dev;
+ struct page **pages;
+ int ret;
+
+ /* Make sure we don't parallel update on a fault, nor move or remove
+ * something from beneath our feet
+ */
+ mutex_lock(&dev->struct_mutex);
+
+ /* if a shmem backed object, make sure we have pages attached now */
+ ret = get_pages(obj, &pages);
+ if (ret) {
+ goto fail;
+ }
+
+ /* where should we do corresponding put_pages().. we are mapping
+ * the original page, rather than thru a GART, so we can't rely
+ * on eviction to trigger this. But munmap() or all mappings should
+ * probably trigger put_pages()?
+ */
+
+ if (omap_obj->flags & OMAP_BO_TILED)
+ ret = fault_2d(obj, vma, vmf);
+ else
+ ret = fault_1d(obj, vma, vmf);
+
+
+fail:
+ mutex_unlock(&dev->struct_mutex);
+ switch (ret) {
+ case 0:
+ case -ERESTARTSYS:
+ case -EINTR:
+ return VM_FAULT_NOPAGE;
+ case -ENOMEM:
+ return VM_FAULT_OOM;
+ default:
+ return VM_FAULT_SIGBUS;
+ }
+}
+
+/** We override mainly to fix up some of the vm mapping flags.. */
+int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct omap_gem_object *omap_obj;
+ int ret;
+
+ ret = drm_gem_mmap(filp, vma);
+ if (ret) {
+ DBG("mmap failed: %d", ret);
+ return ret;
+ }
+
+ /* after drm_gem_mmap(), it is safe to access the obj */
+ omap_obj = to_omap_bo(vma->vm_private_data);
+
+ vma->vm_flags &= ~VM_PFNMAP;
+ vma->vm_flags |= VM_MIXEDMAP;
+
+ if (omap_obj->flags & OMAP_BO_WC) {
+ vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+ } else if (omap_obj->flags & OMAP_BO_UNCACHED) {
+ vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags));
+ } else {
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+ }
+
+ return ret;
+}
+
+/**
+ * omap_gem_dumb_create - create a dumb buffer
+ * @drm_file: our client file
+ * @dev: our device
+ * @args: the requested arguments copied from userspace
+ *
+ * Allocate a buffer suitable for use for a frame buffer of the
+ * form described by user space. Give userspace a handle by which
+ * to reference it.
+ */
+int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+ struct drm_mode_create_dumb *args)
+{
+ union omap_gem_size gsize;
+
+ /* in case someone tries to feed us a completely bogus stride: */
+ args->pitch = align_pitch(args->pitch, args->width, args->bpp);
+ args->size = PAGE_ALIGN(args->pitch * args->height);
+
+ gsize = (union omap_gem_size){
+ .bytes = args->size,
+ };
+
+ return omap_gem_new_handle(dev, file, gsize,
+ OMAP_BO_SCANOUT | OMAP_BO_WC, &args->handle);
+}
+
+/**
+ * omap_gem_dumb_destroy - destroy a dumb buffer
+ * @file: client file
+ * @dev: our DRM device
+ * @handle: the object handle
+ *
+ * Destroy a handle that was created via omap_gem_dumb_create.
+ */
+int omap_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
+ uint32_t handle)
+{
+ /* No special work needed, drop the reference and see what falls out */
+ return drm_gem_handle_delete(file, handle);
+}
+
+/**
+ * omap_gem_dumb_map - buffer mapping for dumb interface
+ * @file: our drm client file
+ * @dev: drm device
+ * @handle: GEM handle to the object (from dumb_create)
+ *
+ * Do the necessary setup to allow the mapping of the frame buffer
+ * into user memory. We don't have to do much here at the moment.
+ */
+int omap_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
+ uint32_t handle, uint64_t *offset)
+{
+ struct drm_gem_object *obj;
+ int ret = 0;
+
+ /* GEM does all our handle to object mapping */
+ obj = drm_gem_object_lookup(dev, file, handle);
+ if (obj == NULL) {
+ ret = -ENOENT;
+ goto fail;
+ }
+
+ *offset = omap_gem_mmap_offset(obj);
+
+ drm_gem_object_unreference_unlocked(obj);
+
+fail:
+ return ret;
+}
+
+/* Set scrolling position. This allows us to implement fast scrolling
+ * for console.
+ */
+int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ uint32_t npages = obj->size >> PAGE_SHIFT;
+ int ret = 0;
+
+ if (roll > npages) {
+ dev_err(obj->dev->dev, "invalid roll: %d\n", roll);
+ return -EINVAL;
+ }
+
+ omap_obj->roll = roll;
+
+ if (in_atomic() || mutex_is_locked(&obj->dev->struct_mutex)) {
+ /* this can get called from fbcon in atomic context.. so
+ * just ignore it and wait for next time called from
+ * interruptible context to update the PAT.. the result
+ * may be that user sees wrap-around instead of scrolling
+ * momentarily on the screen. If we wanted to be fancier
+ * we could perhaps schedule some workqueue work at this
+ * point.
+ */
+ return 0;
+ }
+
+ mutex_lock(&obj->dev->struct_mutex);
+
+ /* if we aren't mapped yet, we don't need to do anything */
+ if (omap_obj->block) {
+ struct page **pages;
+ ret = get_pages(obj, &pages);
+ if (ret)
+ goto fail;
+ ret = tiler_pin(omap_obj->block, pages, npages, roll, true);
+ if (ret)
+ dev_err(obj->dev->dev, "could not repin: %d\n", ret);
+ }
+
+fail:
+ mutex_unlock(&obj->dev->struct_mutex);
+
+ return ret;
+}
+
+/* Get physical address for DMA.. if 'remap' is true, and the buffer is not
+ * already contiguous, remap it to pin in physically contiguous memory.. (ie.
+ * map in TILER)
+ */
+int omap_gem_get_paddr(struct drm_gem_object *obj,
+ dma_addr_t *paddr, bool remap)
+{
+ struct omap_drm_private *priv = obj->dev->dev_private;
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ int ret = 0;
+
+ mutex_lock(&obj->dev->struct_mutex);
+
+ if (remap && is_shmem(obj) && priv->has_dmm) {
+ if (omap_obj->paddr_cnt == 0) {
+ struct page **pages;
+ uint32_t npages = obj->size >> PAGE_SHIFT;
+ enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
+ struct tiler_block *block;
+
+ BUG_ON(omap_obj->block);
+
+ ret = get_pages(obj, &pages);
+ if (ret)
+ goto fail;
+
+ if (omap_obj->flags & OMAP_BO_TILED) {
+ block = tiler_reserve_2d(fmt,
+ omap_obj->width,
+ omap_obj->height, 0);
+ } else {
+ block = tiler_reserve_1d(obj->size);
+ }
+
+ if (IS_ERR(block)) {
+ ret = PTR_ERR(block);
+ dev_err(obj->dev->dev,
+ "could not remap: %d (%d)\n", ret, fmt);
+ goto fail;
+ }
+
+ /* TODO: enable async refill.. */
+ ret = tiler_pin(block, pages, npages,
+ omap_obj->roll, true);
+ if (ret) {
+ tiler_release(block);
+ dev_err(obj->dev->dev,
+ "could not pin: %d\n", ret);
+ goto fail;
+ }
+
+ omap_obj->paddr = tiler_ssptr(block);
+ omap_obj->block = block;
+
+ DBG("got paddr: %08x", omap_obj->paddr);
+ }
+
+ omap_obj->paddr_cnt++;
+
+ *paddr = omap_obj->paddr;
+ } else if (omap_obj->flags & OMAP_BO_DMA) {
+ *paddr = omap_obj->paddr;
+ } else {
+ ret = -EINVAL;
+ }
+
+fail:
+ mutex_unlock(&obj->dev->struct_mutex);
+
+ return ret;
+}
+
+/* Release physical address, when DMA is no longer being performed.. this
+ * could potentially unpin and unmap buffers from TILER
+ */
+int omap_gem_put_paddr(struct drm_gem_object *obj)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ int ret = 0;
+
+ mutex_lock(&obj->dev->struct_mutex);
+ if (omap_obj->paddr_cnt > 0) {
+ omap_obj->paddr_cnt--;
+ if (omap_obj->paddr_cnt == 0) {
+ ret = tiler_unpin(omap_obj->block);
+ if (ret) {
+ dev_err(obj->dev->dev,
+ "could not unpin pages: %d\n", ret);
+ goto fail;
+ }
+ ret = tiler_release(omap_obj->block);
+ if (ret) {
+ dev_err(obj->dev->dev,
+ "could not release unmap: %d\n", ret);
+ }
+ omap_obj->block = NULL;
+ }
+ }
+fail:
+ mutex_unlock(&obj->dev->struct_mutex);
+ return ret;
+}
+
+/* acquire pages when needed (for example, for DMA where physically
+ * contiguous buffer is not required
+ */
+static int get_pages(struct drm_gem_object *obj, struct page ***pages)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ int ret = 0;
+
+ if (is_shmem(obj) && !omap_obj->pages) {
+ ret = omap_gem_attach_pages(obj);
+ if (ret) {
+ dev_err(obj->dev->dev, "could not attach pages\n");
+ return ret;
+ }
+ }
+
+ /* TODO: even phys-contig.. we should have a list of pages? */
+ *pages = omap_obj->pages;
+
+ return 0;
+}
+
+int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages)
+{
+ int ret;
+ mutex_lock(&obj->dev->struct_mutex);
+ ret = get_pages(obj, pages);
+ mutex_unlock(&obj->dev->struct_mutex);
+ return ret;
+}
+
+/* release pages when DMA no longer being performed */
+int omap_gem_put_pages(struct drm_gem_object *obj)
+{
+ /* do something here if we dynamically attach/detach pages.. at
+ * least they would no longer need to be pinned if everyone has
+ * released the pages..
+ */
+ return 0;
+}
+
+/* Get kernel virtual address for CPU access.. this more or less only
+ * exists for omap_fbdev. This should be called with struct_mutex
+ * held.
+ */
+void *omap_gem_vaddr(struct drm_gem_object *obj)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ WARN_ON(! mutex_is_locked(&obj->dev->struct_mutex));
+ if (!omap_obj->vaddr) {
+ struct page **pages;
+ int ret = get_pages(obj, &pages);
+ if (ret)
+ return ERR_PTR(ret);
+ omap_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
+ VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+ }
+ return omap_obj->vaddr;
+}
+
+/* Buffer Synchronization:
+ */
+
+struct omap_gem_sync_waiter {
+ struct list_head list;
+ struct omap_gem_object *omap_obj;
+ enum omap_gem_op op;
+ uint32_t read_target, write_target;
+ /* notify called w/ sync_lock held */
+ void (*notify)(void *arg);
+ void *arg;
+};
+
+/* list of omap_gem_sync_waiter.. the notify fxn gets called back when
+ * the read and/or write target count is achieved which can call a user
+ * callback (ex. to kick 3d and/or 2d), wakeup blocked task (prep for
+ * cpu access), etc.
+ */
+static LIST_HEAD(waiters);
+
+static inline bool is_waiting(struct omap_gem_sync_waiter *waiter)
+{
+ struct omap_gem_object *omap_obj = waiter->omap_obj;
+ if ((waiter->op & OMAP_GEM_READ) &&
+ (omap_obj->sync->read_complete < waiter->read_target))
+ return true;
+ if ((waiter->op & OMAP_GEM_WRITE) &&
+ (omap_obj->sync->write_complete < waiter->write_target))
+ return true;
+ return false;
+}
+
+/* macro for sync debug.. */
+#define SYNCDBG 0
+#define SYNC(fmt, ...) do { if (SYNCDBG) \
+ printk(KERN_ERR "%s:%d: "fmt"\n", \
+ __func__, __LINE__, ##__VA_ARGS__); \
+ } while (0)
+
+
+static void sync_op_update(void)
+{
+ struct omap_gem_sync_waiter *waiter, *n;
+ list_for_each_entry_safe(waiter, n, &waiters, list) {
+ if (!is_waiting(waiter)) {
+ list_del(&waiter->list);
+ SYNC("notify: %p", waiter);
+ waiter->notify(waiter->arg);
+ kfree(waiter);
+ }
+ }
+}
+
+static inline int sync_op(struct drm_gem_object *obj,
+ enum omap_gem_op op, bool start)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ int ret = 0;
+
+ spin_lock(&sync_lock);
+
+ if (!omap_obj->sync) {
+ omap_obj->sync = kzalloc(sizeof(*omap_obj->sync), GFP_ATOMIC);
+ if (!omap_obj->sync) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+ }
+
+ if (start) {
+ if (op & OMAP_GEM_READ)
+ omap_obj->sync->read_pending++;
+ if (op & OMAP_GEM_WRITE)
+ omap_obj->sync->write_pending++;
+ } else {
+ if (op & OMAP_GEM_READ)
+ omap_obj->sync->read_complete++;
+ if (op & OMAP_GEM_WRITE)
+ omap_obj->sync->write_complete++;
+ sync_op_update();
+ }
+
+unlock:
+ spin_unlock(&sync_lock);
+
+ return ret;
+}
+
+/* it is a bit lame to handle updates in this sort of polling way, but
+ * in case of PVR, the GPU can directly update read/write complete
+ * values, and not really tell us which ones it updated.. this also
+ * means that sync_lock is not quite sufficient. So we'll need to
+ * do something a bit better when it comes time to add support for
+ * separate 2d hw..
+ */
+void omap_gem_op_update(void)
+{
+ spin_lock(&sync_lock);
+ sync_op_update();
+ spin_unlock(&sync_lock);
+}
+
+/* mark the start of read and/or write operation */
+int omap_gem_op_start(struct drm_gem_object *obj, enum omap_gem_op op)
+{
+ return sync_op(obj, op, true);
+}
+
+int omap_gem_op_finish(struct drm_gem_object *obj, enum omap_gem_op op)
+{
+ return sync_op(obj, op, false);
+}
+
+static DECLARE_WAIT_QUEUE_HEAD(sync_event);
+
+static void sync_notify(void *arg)
+{
+ struct task_struct **waiter_task = arg;
+ *waiter_task = NULL;
+ wake_up_all(&sync_event);
+}
+
+int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ int ret = 0;
+ if (omap_obj->sync) {
+ struct task_struct *waiter_task = current;
+ struct omap_gem_sync_waiter *waiter =
+ kzalloc(sizeof(*waiter), GFP_KERNEL);
+
+ if (!waiter) {
+ return -ENOMEM;
+ }
+
+ waiter->omap_obj = omap_obj;
+ waiter->op = op;
+ waiter->read_target = omap_obj->sync->read_pending;
+ waiter->write_target = omap_obj->sync->write_pending;
+ waiter->notify = sync_notify;
+ waiter->arg = &waiter_task;
+
+ spin_lock(&sync_lock);
+ if (is_waiting(waiter)) {
+ SYNC("waited: %p", waiter);
+ list_add_tail(&waiter->list, &waiters);
+ spin_unlock(&sync_lock);
+ ret = wait_event_interruptible(sync_event,
+ (waiter_task == NULL));
+ spin_lock(&sync_lock);
+ if (waiter_task) {
+ SYNC("interrupted: %p", waiter);
+ /* we were interrupted */
+ list_del(&waiter->list);
+ waiter_task = NULL;
+ } else {
+ /* freed in sync_op_update() */
+ waiter = NULL;
+ }
+ }
+ spin_unlock(&sync_lock);
+
+ if (waiter) {
+ kfree(waiter);
+ }
+ }
+ return ret;
+}
+
+/* call fxn(arg), either synchronously or asynchronously if the op
+ * is currently blocked.. fxn() can be called from any context
+ *
+ * (TODO for now fxn is called back from whichever context calls
+ * omap_gem_op_update().. but this could be better defined later
+ * if needed)
+ *
+ * TODO more code in common w/ _sync()..
+ */
+int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op,
+ void (*fxn)(void *arg), void *arg)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ if (omap_obj->sync) {
+ struct omap_gem_sync_waiter *waiter =
+ kzalloc(sizeof(*waiter), GFP_ATOMIC);
+
+ if (!waiter) {
+ return -ENOMEM;
+ }
+
+ waiter->omap_obj = omap_obj;
+ waiter->op = op;
+ waiter->read_target = omap_obj->sync->read_pending;
+ waiter->write_target = omap_obj->sync->write_pending;
+ waiter->notify = fxn;
+ waiter->arg = arg;
+
+ spin_lock(&sync_lock);
+ if (is_waiting(waiter)) {
+ SYNC("waited: %p", waiter);
+ list_add_tail(&waiter->list, &waiters);
+ spin_unlock(&sync_lock);
+ return 0;
+ }
+
+ spin_unlock(&sync_lock);
+ }
+
+ /* no waiting.. */
+ fxn(arg);
+
+ return 0;
+}
+
+/* special API so PVR can update the buffer to use a sync-object allocated
+ * from it's sync-obj heap. Only used for a newly allocated (from PVR's
+ * perspective) sync-object, so we overwrite the new syncobj w/ values
+ * from the already allocated syncobj (if there is one)
+ */
+int omap_gem_set_sync_object(struct drm_gem_object *obj, void *syncobj)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ int ret = 0;
+
+ spin_lock(&sync_lock);
+
+ if ((omap_obj->flags & OMAP_BO_EXT_SYNC) && !syncobj) {
+ /* clearing a previously set syncobj */
+ syncobj = kzalloc(sizeof(*omap_obj->sync), GFP_ATOMIC);
+ if (!syncobj) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+ memcpy(syncobj, omap_obj->sync, sizeof(*omap_obj->sync));
+ omap_obj->flags &= ~OMAP_BO_EXT_SYNC;
+ omap_obj->sync = syncobj;
+ } else if (syncobj && !(omap_obj->flags & OMAP_BO_EXT_SYNC)) {
+ /* replacing an existing syncobj */
+ if (omap_obj->sync) {
+ memcpy(syncobj, omap_obj->sync, sizeof(*omap_obj->sync));
+ kfree(omap_obj->sync);
+ }
+ omap_obj->flags |= OMAP_BO_EXT_SYNC;
+ omap_obj->sync = syncobj;
+ }
+
+unlock:
+ spin_unlock(&sync_lock);
+ return ret;
+}
+
+int omap_gem_init_object(struct drm_gem_object *obj)
+{
+ return -EINVAL; /* unused */
+}
+
+/* don't call directly.. called from GEM core when it is time to actually
+ * free the object..
+ */
+void omap_gem_free_object(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+
+ evict(obj);
+
+ if (obj->map_list.map) {
+ drm_gem_free_mmap_offset(obj);
+ }
+
+ /* don't free externally allocated backing memory */
+ if (!(omap_obj->flags & OMAP_BO_EXT_MEM)) {
+ if (omap_obj->pages) {
+ omap_gem_detach_pages(obj);
+ }
+ if (!is_shmem(obj)) {
+ dma_free_writecombine(dev->dev, obj->size,
+ omap_obj->vaddr, omap_obj->paddr);
+ } else if (omap_obj->vaddr) {
+ vunmap(omap_obj->vaddr);
+ }
+ }
+
+ /* don't free externally allocated syncobj */
+ if (!(omap_obj->flags & OMAP_BO_EXT_SYNC)) {
+ kfree(omap_obj->sync);
+ }
+
+ drm_gem_object_release(obj);
+
+ kfree(obj);
+}
+
+/* convenience method to construct a GEM buffer object, and userspace handle */
+int omap_gem_new_handle(struct drm_device *dev, struct drm_file *file,
+ union omap_gem_size gsize, uint32_t flags, uint32_t *handle)
+{
+ struct drm_gem_object *obj;
+ int ret;
+
+ obj = omap_gem_new(dev, gsize, flags);
+ if (!obj)
+ return -ENOMEM;
+
+ ret = drm_gem_handle_create(file, obj, handle);
+ if (ret) {
+ drm_gem_object_release(obj);
+ kfree(obj); /* TODO isn't there a dtor to call? just copying i915 */
+ return ret;
+ }
+
+ /* drop reference from allocate - handle holds it now */
+ drm_gem_object_unreference_unlocked(obj);
+
+ return 0;
+}
+
+/* GEM buffer object constructor */
+struct drm_gem_object *omap_gem_new(struct drm_device *dev,
+ union omap_gem_size gsize, uint32_t flags)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ struct omap_gem_object *omap_obj;
+ struct drm_gem_object *obj = NULL;
+ size_t size;
+ int ret;
+
+ if (flags & OMAP_BO_TILED) {
+ if (!usergart) {
+ dev_err(dev->dev, "Tiled buffers require DMM\n");
+ goto fail;
+ }
+
+ /* tiled buffers are always shmem paged backed.. when they are
+ * scanned out, they are remapped into DMM/TILER
+ */
+ flags &= ~OMAP_BO_SCANOUT;
+
+ /* currently don't allow cached buffers.. there is some caching
+ * stuff that needs to be handled better
+ */
+ flags &= ~(OMAP_BO_CACHED|OMAP_BO_UNCACHED);
+ flags |= OMAP_BO_WC;
+
+ /* align dimensions to slot boundaries... */
+ tiler_align(gem2fmt(flags),
+ &gsize.tiled.width, &gsize.tiled.height);
+
+ /* ...and calculate size based on aligned dimensions */
+ size = tiler_size(gem2fmt(flags),
+ gsize.tiled.width, gsize.tiled.height);
+ } else {
+ size = PAGE_ALIGN(gsize.bytes);
+ }
+
+ omap_obj = kzalloc(sizeof(*omap_obj), GFP_KERNEL);
+ if (!omap_obj) {
+ dev_err(dev->dev, "could not allocate GEM object\n");
+ goto fail;
+ }
+
+ obj = &omap_obj->base;
+
+ if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) {
+ /* attempt to allocate contiguous memory if we don't
+ * have DMM for remappign discontiguous buffers
+ */
+ omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size,
+ &omap_obj->paddr, GFP_KERNEL);
+ if (omap_obj->vaddr) {
+ flags |= OMAP_BO_DMA;
+ }
+ }
+
+ omap_obj->flags = flags;
+
+ if (flags & OMAP_BO_TILED) {
+ omap_obj->width = gsize.tiled.width;
+ omap_obj->height = gsize.tiled.height;
+ }
+
+ if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM)) {
+ ret = drm_gem_private_object_init(dev, obj, size);
+ } else {
+ ret = drm_gem_object_init(dev, obj, size);
+ }
+
+ if (ret) {
+ goto fail;
+ }
+
+ return obj;
+
+fail:
+ if (obj) {
+ omap_gem_free_object(obj);
+ }
+ return NULL;
+}
+
+/* init/cleanup.. if DMM is used, we need to set some stuff up.. */
+void omap_gem_init(struct drm_device *dev)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ const enum tiler_fmt fmts[] = {
+ TILFMT_8BIT, TILFMT_16BIT, TILFMT_32BIT
+ };
+ int i, j, ret;
+
+ ret = omap_dmm_init(dev);
+ if (ret) {
+ /* DMM only supported on OMAP4 and later, so this isn't fatal */
+ dev_warn(dev->dev, "omap_dmm_init failed, disabling DMM\n");
+ return;
+ }
+
+ usergart = kzalloc(3 * sizeof(*usergart), GFP_KERNEL);
+ if (!usergart) {
+ dev_warn(dev->dev, "could not allocate usergart\n");
+ return;
+ }
+
+ /* reserve 4k aligned/wide regions for userspace mappings: */
+ for (i = 0; i < ARRAY_SIZE(fmts); i++) {
+ uint16_t h = 1, w = PAGE_SIZE >> i;
+ tiler_align(fmts[i], &w, &h);
+ /* note: since each region is 1 4kb page wide, and minimum
+ * number of rows, the height ends up being the same as the
+ * # of pages in the region
+ */
+ usergart[i].height = h;
+ usergart[i].height_shift = ilog2(h);
+ usergart[i].stride_pfn = tiler_stride(fmts[i]) >> PAGE_SHIFT;
+ usergart[i].slot_shift = ilog2((PAGE_SIZE / h) >> i);
+ for (j = 0; j < NUM_USERGART_ENTRIES; j++) {
+ struct usergart_entry *entry = &usergart[i].entry[j];
+ struct tiler_block *block =
+ tiler_reserve_2d(fmts[i], w, h,
+ PAGE_SIZE);
+ if (IS_ERR(block)) {
+ dev_err(dev->dev,
+ "reserve failed: %d, %d, %ld\n",
+ i, j, PTR_ERR(block));
+ return;
+ }
+ entry->paddr = tiler_ssptr(block);
+ entry->block = block;
+
+ DBG("%d:%d: %dx%d: paddr=%08x stride=%d", i, j, w, h,
+ entry->paddr,
+ usergart[i].stride_pfn << PAGE_SHIFT);
+ }
+ }
+
+ priv->has_dmm = true;
+}
+
+void omap_gem_deinit(struct drm_device *dev)
+{
+ /* I believe we can rely on there being no more outstanding GEM
+ * objects which could depend on usergart/dmm at this point.
+ */
+ omap_dmm_remove();
+ kfree(usergart);
+}
diff --git a/drivers/staging/omapdrm/omap_gem_helpers.c b/drivers/staging/omapdrm/omap_gem_helpers.c
new file mode 100644
index 000000000000..29275c7209e9
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_gem_helpers.c
@@ -0,0 +1,169 @@
+/*
+ * drivers/staging/omapdrm/omap_gem_helpers.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* temporary copy of drm_gem_{get,put}_pages() until the
+ * "drm/gem: add functions to get/put pages" patch is merged..
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/shmem_fs.h>
+
+#include <drm/drmP.h>
+
+/**
+ * drm_gem_get_pages - helper to allocate backing pages for a GEM object
+ * @obj: obj in question
+ * @gfpmask: gfp mask of requested pages
+ */
+struct page ** _drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
+{
+ struct inode *inode;
+ struct address_space *mapping;
+ struct page *p, **pages;
+ int i, npages;
+
+ /* This is the shared memory object that backs the GEM resource */
+ inode = obj->filp->f_path.dentry->d_inode;
+ mapping = inode->i_mapping;
+
+ npages = obj->size >> PAGE_SHIFT;
+
+ pages = drm_malloc_ab(npages, sizeof(struct page *));
+ if (pages == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ gfpmask |= mapping_gfp_mask(mapping);
+
+ for (i = 0; i < npages; i++) {
+ p = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
+ if (IS_ERR(p))
+ goto fail;
+ pages[i] = p;
+
+ /* There is a hypothetical issue w/ drivers that require
+ * buffer memory in the low 4GB.. if the pages are un-
+ * pinned, and swapped out, they can end up swapped back
+ * in above 4GB. If pages are already in memory, then
+ * shmem_read_mapping_page_gfp will ignore the gfpmask,
+ * even if the already in-memory page disobeys the mask.
+ *
+ * It is only a theoretical issue today, because none of
+ * the devices with this limitation can be populated with
+ * enough memory to trigger the issue. But this BUG_ON()
+ * is here as a reminder in case the problem with
+ * shmem_read_mapping_page_gfp() isn't solved by the time
+ * it does become a real issue.
+ *
+ * See this thread: http://lkml.org/lkml/2011/7/11/238
+ */
+ BUG_ON((gfpmask & __GFP_DMA32) &&
+ (page_to_pfn(p) >= 0x00100000UL));
+ }
+
+ return pages;
+
+fail:
+ while (i--) {
+ page_cache_release(pages[i]);
+ }
+ drm_free_large(pages);
+ return ERR_PTR(PTR_ERR(p));
+}
+
+/**
+ * drm_gem_put_pages - helper to free backing pages for a GEM object
+ * @obj: obj in question
+ * @pages: pages to free
+ */
+void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
+ bool dirty, bool accessed)
+{
+ int i, npages;
+
+ npages = obj->size >> PAGE_SHIFT;
+
+ for (i = 0; i < npages; i++) {
+ if (dirty)
+ set_page_dirty(pages[i]);
+
+ if (accessed)
+ mark_page_accessed(pages[i]);
+
+ /* Undo the reference we took when populating the table */
+ page_cache_release(pages[i]);
+ }
+
+ drm_free_large(pages);
+}
+
+int
+_drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_gem_mm *mm = dev->mm_private;
+ struct drm_map_list *list;
+ struct drm_local_map *map;
+ int ret = 0;
+
+ /* Set the object up for mmap'ing */
+ list = &obj->map_list;
+ list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
+ if (!list->map)
+ return -ENOMEM;
+
+ map = list->map;
+ map->type = _DRM_GEM;
+ map->size = size;
+ map->handle = obj;
+
+ /* Get a DRM GEM mmap offset allocated... */
+ list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
+ size / PAGE_SIZE, 0, 0);
+
+ if (!list->file_offset_node) {
+ DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
+ ret = -ENOSPC;
+ goto out_free_list;
+ }
+
+ list->file_offset_node = drm_mm_get_block(list->file_offset_node,
+ size / PAGE_SIZE, 0);
+ if (!list->file_offset_node) {
+ ret = -ENOMEM;
+ goto out_free_list;
+ }
+
+ list->hash.key = list->file_offset_node->start;
+ ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
+ if (ret) {
+ DRM_ERROR("failed to add to map hash\n");
+ goto out_free_mm;
+ }
+
+ return 0;
+
+out_free_mm:
+ drm_mm_put_block(list->file_offset_node);
+out_free_list:
+ kfree(list->map);
+ list->map = NULL;
+
+ return ret;
+}
diff --git a/drivers/staging/omapdrm/omap_priv.h b/drivers/staging/omapdrm/omap_priv.h
new file mode 100644
index 000000000000..c324709aa9a1
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_priv.h
@@ -0,0 +1,47 @@
+/*
+ * include/drm/omap_priv.h
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP_PRIV_H__
+#define __OMAP_PRIV_H__
+
+/* Non-userspace facing APIs
+ */
+
+/* optional platform data to configure the default configuration of which
+ * pipes/overlays/CRTCs are used.. if this is not provided, then instead the
+ * first CONFIG_DRM_OMAP_NUM_CRTCS are used, and they are each connected to
+ * one manager, with priority given to managers that are connected to
+ * detected devices. This should be a good default behavior for most cases,
+ * but yet there still might be times when you wish to do something different.
+ */
+struct omap_kms_platform_data {
+ int ovl_cnt;
+ const int *ovl_ids;
+ int mgr_cnt;
+ const int *mgr_ids;
+ int dev_cnt;
+ const char **dev_names;
+};
+
+struct omap_drm_platform_data {
+ struct omap_kms_platform_data *kms_pdata;
+ struct omap_dmm_platform_data *dmm_pdata;
+};
+
+#endif /* __OMAP_DRM_H__ */
diff --git a/drivers/staging/omapdrm/tcm-sita.c b/drivers/staging/omapdrm/tcm-sita.c
new file mode 100644
index 000000000000..10d5ac3dae4b
--- /dev/null
+++ b/drivers/staging/omapdrm/tcm-sita.c
@@ -0,0 +1,703 @@
+/*
+ * tcm-sita.c
+ *
+ * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation) algorithm
+ *
+ * Authors: Ravi Ramachandra <r.ramachandra@ti.com>,
+ * Lajos Molnar <molnar@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "tcm-sita.h"
+
+#define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
+
+/* Individual selection criteria for different scan areas */
+static s32 CR_L2R_T2B = CR_BIAS_HORIZONTAL;
+static s32 CR_R2L_T2B = CR_DIAGONAL_BALANCE;
+
+/*********************************************
+ * TCM API - Sita Implementation
+ *********************************************/
+static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
+ struct tcm_area *area);
+static s32 sita_reserve_1d(struct tcm *tcm, u32 slots, struct tcm_area *area);
+static s32 sita_free(struct tcm *tcm, struct tcm_area *area);
+static void sita_deinit(struct tcm *tcm);
+
+/*********************************************
+ * Main Scanner functions
+ *********************************************/
+static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *area);
+
+static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *field, struct tcm_area *area);
+
+static s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *field, struct tcm_area *area);
+
+static s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_slots,
+ struct tcm_area *field, struct tcm_area *area);
+
+/*********************************************
+ * Support Infrastructure Methods
+ *********************************************/
+static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h);
+
+static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
+ struct tcm_area *field, s32 criteria,
+ struct score *best);
+
+static void get_nearness_factor(struct tcm_area *field,
+ struct tcm_area *candidate,
+ struct nearness_factor *nf);
+
+static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
+ struct neighbor_stats *stat);
+
+static void fill_area(struct tcm *tcm,
+ struct tcm_area *area, struct tcm_area *parent);
+
+
+/*********************************************/
+
+/*********************************************
+ * Utility Methods
+ *********************************************/
+struct tcm *sita_init(u16 width, u16 height, struct tcm_pt *attr)
+{
+ struct tcm *tcm;
+ struct sita_pvt *pvt;
+ struct tcm_area area = {0};
+ s32 i;
+
+ if (width == 0 || height == 0)
+ return NULL;
+
+ tcm = kmalloc(sizeof(*tcm), GFP_KERNEL);
+ pvt = kmalloc(sizeof(*pvt), GFP_KERNEL);
+ if (!tcm || !pvt)
+ goto error;
+
+ memset(tcm, 0, sizeof(*tcm));
+ memset(pvt, 0, sizeof(*pvt));
+
+ /* Updating the pointers to SiTA implementation APIs */
+ tcm->height = height;
+ tcm->width = width;
+ tcm->reserve_2d = sita_reserve_2d;
+ tcm->reserve_1d = sita_reserve_1d;
+ tcm->free = sita_free;
+ tcm->deinit = sita_deinit;
+ tcm->pvt = (void *)pvt;
+
+ spin_lock_init(&(pvt->lock));
+
+ /* Creating tam map */
+ pvt->map = kmalloc(sizeof(*pvt->map) * tcm->width, GFP_KERNEL);
+ if (!pvt->map)
+ goto error;
+
+ for (i = 0; i < tcm->width; i++) {
+ pvt->map[i] =
+ kmalloc(sizeof(**pvt->map) * tcm->height,
+ GFP_KERNEL);
+ if (pvt->map[i] == NULL) {
+ while (i--)
+ kfree(pvt->map[i]);
+ kfree(pvt->map);
+ goto error;
+ }
+ }
+
+ if (attr && attr->x <= tcm->width && attr->y <= tcm->height) {
+ pvt->div_pt.x = attr->x;
+ pvt->div_pt.y = attr->y;
+
+ } else {
+ /* Defaulting to 3:1 ratio on width for 2D area split */
+ /* Defaulting to 3:1 ratio on height for 2D and 1D split */
+ pvt->div_pt.x = (tcm->width * 3) / 4;
+ pvt->div_pt.y = (tcm->height * 3) / 4;
+ }
+
+ spin_lock(&(pvt->lock));
+ assign(&area, 0, 0, width - 1, height - 1);
+ fill_area(tcm, &area, NULL);
+ spin_unlock(&(pvt->lock));
+ return tcm;
+
+error:
+ kfree(tcm);
+ kfree(pvt);
+ return NULL;
+}
+
+static void sita_deinit(struct tcm *tcm)
+{
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+ struct tcm_area area = {0};
+ s32 i;
+
+ area.p1.x = tcm->width - 1;
+ area.p1.y = tcm->height - 1;
+
+ spin_lock(&(pvt->lock));
+ fill_area(tcm, &area, NULL);
+ spin_unlock(&(pvt->lock));
+
+ for (i = 0; i < tcm->height; i++)
+ kfree(pvt->map[i]);
+ kfree(pvt->map);
+ kfree(pvt);
+}
+
+/**
+ * Reserve a 1D area in the container
+ *
+ * @param num_slots size of 1D area
+ * @param area pointer to the area that will be populated with the
+ * reserved area
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static s32 sita_reserve_1d(struct tcm *tcm, u32 num_slots,
+ struct tcm_area *area)
+{
+ s32 ret;
+ struct tcm_area field = {0};
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+ spin_lock(&(pvt->lock));
+
+ /* Scanning entire container */
+ assign(&field, tcm->width - 1, tcm->height - 1, 0, 0);
+
+ ret = scan_r2l_b2t_one_dim(tcm, num_slots, &field, area);
+ if (!ret)
+ /* update map */
+ fill_area(tcm, area, area);
+
+ spin_unlock(&(pvt->lock));
+ return ret;
+}
+
+/**
+ * Reserve a 2D area in the container
+ *
+ * @param w width
+ * @param h height
+ * @param area pointer to the area that will be populated with the reesrved
+ * area
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
+ struct tcm_area *area)
+{
+ s32 ret;
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+ /* not supporting more than 64 as alignment */
+ if (align > 64)
+ return -EINVAL;
+
+ /* we prefer 1, 32 and 64 as alignment */
+ align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
+
+ spin_lock(&(pvt->lock));
+ ret = scan_areas_and_find_fit(tcm, w, h, align, area);
+ if (!ret)
+ /* update map */
+ fill_area(tcm, area, area);
+
+ spin_unlock(&(pvt->lock));
+ return ret;
+}
+
+/**
+ * Unreserve a previously allocated 2D or 1D area
+ * @param area area to be freed
+ * @return 0 - success
+ */
+static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
+{
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+ spin_lock(&(pvt->lock));
+
+ /* check that this is in fact an existing area */
+ WARN_ON(pvt->map[area->p0.x][area->p0.y] != area ||
+ pvt->map[area->p1.x][area->p1.y] != area);
+
+ /* Clear the contents of the associated tiles in the map */
+ fill_area(tcm, area, NULL);
+
+ spin_unlock(&(pvt->lock));
+
+ return 0;
+}
+
+/**
+ * Note: In general the cordinates in the scan field area relevant to the can
+ * sweep directions. The scan origin (e.g. top-left corner) will always be
+ * the p0 member of the field. Therfore, for a scan from top-left p0.x <= p1.x
+ * and p0.y <= p1.y; whereas, for a scan from bottom-right p1.x <= p0.x and p1.y
+ * <= p0.y
+ */
+
+/**
+ * Raster scan horizontally right to left from top to bottom to find a place for
+ * a 2D area of given size inside a scan field.
+ *
+ * @param w width of desired area
+ * @param h height of desired area
+ * @param align desired area alignment
+ * @param area pointer to the area that will be set to the best position
+ * @param field area to scan (inclusive)
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *field, struct tcm_area *area)
+{
+ s32 x, y;
+ s16 start_x, end_x, start_y, end_y, found_x = -1;
+ struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
+ struct score best = {{0}, {0}, {0}, 0};
+
+ start_x = field->p0.x;
+ end_x = field->p1.x;
+ start_y = field->p0.y;
+ end_y = field->p1.y;
+
+ /* check scan area co-ordinates */
+ if (field->p0.x < field->p1.x ||
+ field->p1.y < field->p0.y)
+ return -EINVAL;
+
+ /* check if allocation would fit in scan area */
+ if (w > LEN(start_x, end_x) || h > LEN(end_y, start_y))
+ return -ENOSPC;
+
+ /* adjust start_x and end_y, as allocation would not fit beyond */
+ start_x = ALIGN_DOWN(start_x - w + 1, align); /* - 1 to be inclusive */
+ end_y = end_y - h + 1;
+
+ /* check if allocation would still fit in scan area */
+ if (start_x < end_x)
+ return -ENOSPC;
+
+ /* scan field top-to-bottom, right-to-left */
+ for (y = start_y; y <= end_y; y++) {
+ for (x = start_x; x >= end_x; x -= align) {
+ if (is_area_free(map, x, y, w, h)) {
+ found_x = x;
+
+ /* update best candidate */
+ if (update_candidate(tcm, x, y, w, h, field,
+ CR_R2L_T2B, &best))
+ goto done;
+
+ /* change upper x bound */
+ end_x = x + 1;
+ break;
+ } else if (map[x][y] && map[x][y]->is2d) {
+ /* step over 2D areas */
+ x = ALIGN(map[x][y]->p0.x - w + 1, align);
+ }
+ }
+
+ /* break if you find a free area shouldering the scan field */
+ if (found_x == start_x)
+ break;
+ }
+
+ if (!best.a.tcm)
+ return -ENOSPC;
+done:
+ assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
+ return 0;
+}
+
+/**
+ * Raster scan horizontally left to right from top to bottom to find a place for
+ * a 2D area of given size inside a scan field.
+ *
+ * @param w width of desired area
+ * @param h height of desired area
+ * @param align desired area alignment
+ * @param area pointer to the area that will be set to the best position
+ * @param field area to scan (inclusive)
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *field, struct tcm_area *area)
+{
+ s32 x, y;
+ s16 start_x, end_x, start_y, end_y, found_x = -1;
+ struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
+ struct score best = {{0}, {0}, {0}, 0};
+
+ start_x = field->p0.x;
+ end_x = field->p1.x;
+ start_y = field->p0.y;
+ end_y = field->p1.y;
+
+ /* check scan area co-ordinates */
+ if (field->p1.x < field->p0.x ||
+ field->p1.y < field->p0.y)
+ return -EINVAL;
+
+ /* check if allocation would fit in scan area */
+ if (w > LEN(end_x, start_x) || h > LEN(end_y, start_y))
+ return -ENOSPC;
+
+ start_x = ALIGN(start_x, align);
+
+ /* check if allocation would still fit in scan area */
+ if (w > LEN(end_x, start_x))
+ return -ENOSPC;
+
+ /* adjust end_x and end_y, as allocation would not fit beyond */
+ end_x = end_x - w + 1; /* + 1 to be inclusive */
+ end_y = end_y - h + 1;
+
+ /* scan field top-to-bottom, left-to-right */
+ for (y = start_y; y <= end_y; y++) {
+ for (x = start_x; x <= end_x; x += align) {
+ if (is_area_free(map, x, y, w, h)) {
+ found_x = x;
+
+ /* update best candidate */
+ if (update_candidate(tcm, x, y, w, h, field,
+ CR_L2R_T2B, &best))
+ goto done;
+ /* change upper x bound */
+ end_x = x - 1;
+
+ break;
+ } else if (map[x][y] && map[x][y]->is2d) {
+ /* step over 2D areas */
+ x = ALIGN_DOWN(map[x][y]->p1.x, align);
+ }
+ }
+
+ /* break if you find a free area shouldering the scan field */
+ if (found_x == start_x)
+ break;
+ }
+
+ if (!best.a.tcm)
+ return -ENOSPC;
+done:
+ assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
+ return 0;
+}
+
+/**
+ * Raster scan horizontally right to left from bottom to top to find a place
+ * for a 1D area of given size inside a scan field.
+ *
+ * @param num_slots size of desired area
+ * @param align desired area alignment
+ * @param area pointer to the area that will be set to the best
+ * position
+ * @param field area to scan (inclusive)
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_slots,
+ struct tcm_area *field, struct tcm_area *area)
+{
+ s32 found = 0;
+ s16 x, y;
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+ struct tcm_area *p;
+
+ /* check scan area co-ordinates */
+ if (field->p0.y < field->p1.y)
+ return -EINVAL;
+
+ /**
+ * Currently we only support full width 1D scan field, which makes sense
+ * since 1D slot-ordering spans the full container width.
+ */
+ if (tcm->width != field->p0.x - field->p1.x + 1)
+ return -EINVAL;
+
+ /* check if allocation would fit in scan area */
+ if (num_slots > tcm->width * LEN(field->p0.y, field->p1.y))
+ return -ENOSPC;
+
+ x = field->p0.x;
+ y = field->p0.y;
+
+ /* find num_slots consecutive free slots to the left */
+ while (found < num_slots) {
+ if (y < 0)
+ return -ENOSPC;
+
+ /* remember bottom-right corner */
+ if (found == 0) {
+ area->p1.x = x;
+ area->p1.y = y;
+ }
+
+ /* skip busy regions */
+ p = pvt->map[x][y];
+ if (p) {
+ /* move to left of 2D areas, top left of 1D */
+ x = p->p0.x;
+ if (!p->is2d)
+ y = p->p0.y;
+
+ /* start over */
+ found = 0;
+ } else {
+ /* count consecutive free slots */
+ found++;
+ if (found == num_slots)
+ break;
+ }
+
+ /* move to the left */
+ if (x == 0)
+ y--;
+ x = (x ? : tcm->width) - 1;
+
+ }
+
+ /* set top-left corner */
+ area->p0.x = x;
+ area->p0.y = y;
+ return 0;
+}
+
+/**
+ * Find a place for a 2D area of given size inside a scan field based on its
+ * alignment needs.
+ *
+ * @param w width of desired area
+ * @param h height of desired area
+ * @param align desired area alignment
+ * @param area pointer to the area that will be set to the best position
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *area)
+{
+ s32 ret = 0;
+ struct tcm_area field = {0};
+ u16 boundary_x, boundary_y;
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+ if (align > 1) {
+ /* prefer top-left corner */
+ boundary_x = pvt->div_pt.x - 1;
+ boundary_y = pvt->div_pt.y - 1;
+
+ /* expand width and height if needed */
+ if (w > pvt->div_pt.x)
+ boundary_x = tcm->width - 1;
+ if (h > pvt->div_pt.y)
+ boundary_y = tcm->height - 1;
+
+ assign(&field, 0, 0, boundary_x, boundary_y);
+ ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
+
+ /* scan whole container if failed, but do not scan 2x */
+ if (ret != 0 && (boundary_x != tcm->width - 1 ||
+ boundary_y != tcm->height - 1)) {
+ /* scan the entire container if nothing found */
+ assign(&field, 0, 0, tcm->width - 1, tcm->height - 1);
+ ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
+ }
+ } else if (align == 1) {
+ /* prefer top-right corner */
+ boundary_x = pvt->div_pt.x;
+ boundary_y = pvt->div_pt.y - 1;
+
+ /* expand width and height if needed */
+ if (w > (tcm->width - pvt->div_pt.x))
+ boundary_x = 0;
+ if (h > pvt->div_pt.y)
+ boundary_y = tcm->height - 1;
+
+ assign(&field, tcm->width - 1, 0, boundary_x, boundary_y);
+ ret = scan_r2l_t2b(tcm, w, h, align, &field, area);
+
+ /* scan whole container if failed, but do not scan 2x */
+ if (ret != 0 && (boundary_x != 0 ||
+ boundary_y != tcm->height - 1)) {
+ /* scan the entire container if nothing found */
+ assign(&field, tcm->width - 1, 0, 0, tcm->height - 1);
+ ret = scan_r2l_t2b(tcm, w, h, align, &field,
+ area);
+ }
+ }
+
+ return ret;
+}
+
+/* check if an entire area is free */
+static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h)
+{
+ u16 x = 0, y = 0;
+ for (y = y0; y < y0 + h; y++) {
+ for (x = x0; x < x0 + w; x++) {
+ if (map[x][y])
+ return false;
+ }
+ }
+ return true;
+}
+
+/* fills an area with a parent tcm_area */
+static void fill_area(struct tcm *tcm, struct tcm_area *area,
+ struct tcm_area *parent)
+{
+ s32 x, y;
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+ struct tcm_area a, a_;
+
+ /* set area's tcm; otherwise, enumerator considers it invalid */
+ area->tcm = tcm;
+
+ tcm_for_each_slice(a, *area, a_) {
+ for (x = a.p0.x; x <= a.p1.x; ++x)
+ for (y = a.p0.y; y <= a.p1.y; ++y)
+ pvt->map[x][y] = parent;
+
+ }
+}
+
+/**
+ * Compares a candidate area to the current best area, and if it is a better
+ * fit, it updates the best to this one.
+ *
+ * @param x0, y0, w, h top, left, width, height of candidate area
+ * @param field scan field
+ * @param criteria scan criteria
+ * @param best best candidate and its scores
+ *
+ * @return 1 (true) if the candidate area is known to be the final best, so no
+ * more searching should be performed
+ */
+static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
+ struct tcm_area *field, s32 criteria,
+ struct score *best)
+{
+ struct score me; /* score for area */
+
+ /*
+ * NOTE: For horizontal bias we always give the first found, because our
+ * scan is horizontal-raster-based and the first candidate will always
+ * have the horizontal bias.
+ */
+ bool first = criteria & CR_BIAS_HORIZONTAL;
+
+ assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
+
+ /* calculate score for current candidate */
+ if (!first) {
+ get_neighbor_stats(tcm, &me.a, &me.n);
+ me.neighs = me.n.edge + me.n.busy;
+ get_nearness_factor(field, &me.a, &me.f);
+ }
+
+ /* the 1st candidate is always the best */
+ if (!best->a.tcm)
+ goto better;
+
+ BUG_ON(first);
+
+ /* diagonal balance check */
+ if ((criteria & CR_DIAGONAL_BALANCE) &&
+ best->neighs <= me.neighs &&
+ (best->neighs < me.neighs ||
+ /* this implies that neighs and occupied match */
+ best->n.busy < me.n.busy ||
+ (best->n.busy == me.n.busy &&
+ /* check the nearness factor */
+ best->f.x + best->f.y > me.f.x + me.f.y)))
+ goto better;
+
+ /* not better, keep going */
+ return 0;
+
+better:
+ /* save current area as best */
+ memcpy(best, &me, sizeof(me));
+ best->a.tcm = tcm;
+ return first;
+}
+
+/**
+ * Calculate the nearness factor of an area in a search field. The nearness
+ * factor is smaller if the area is closer to the search origin.
+ */
+static void get_nearness_factor(struct tcm_area *field, struct tcm_area *area,
+ struct nearness_factor *nf)
+{
+ /**
+ * Using signed math as field coordinates may be reversed if
+ * search direction is right-to-left or bottom-to-top.
+ */
+ nf->x = (s32)(area->p0.x - field->p0.x) * 1000 /
+ (field->p1.x - field->p0.x);
+ nf->y = (s32)(area->p0.y - field->p0.y) * 1000 /
+ (field->p1.y - field->p0.y);
+}
+
+/* get neighbor statistics */
+static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
+ struct neighbor_stats *stat)
+{
+ s16 x = 0, y = 0;
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+ /* Clearing any exisiting values */
+ memset(stat, 0, sizeof(*stat));
+
+ /* process top & bottom edges */
+ for (x = area->p0.x; x <= area->p1.x; x++) {
+ if (area->p0.y == 0)
+ stat->edge++;
+ else if (pvt->map[x][area->p0.y - 1])
+ stat->busy++;
+
+ if (area->p1.y == tcm->height - 1)
+ stat->edge++;
+ else if (pvt->map[x][area->p1.y + 1])
+ stat->busy++;
+ }
+
+ /* process left & right edges */
+ for (y = area->p0.y; y <= area->p1.y; ++y) {
+ if (area->p0.x == 0)
+ stat->edge++;
+ else if (pvt->map[area->p0.x - 1][y])
+ stat->busy++;
+
+ if (area->p1.x == tcm->width - 1)
+ stat->edge++;
+ else if (pvt->map[area->p1.x + 1][y])
+ stat->busy++;
+ }
+}
diff --git a/drivers/staging/omapdrm/tcm-sita.h b/drivers/staging/omapdrm/tcm-sita.h
new file mode 100644
index 000000000000..0444f868671c
--- /dev/null
+++ b/drivers/staging/omapdrm/tcm-sita.h
@@ -0,0 +1,95 @@
+/*
+ * tcm_sita.h
+ *
+ * SImple Tiler Allocator (SiTA) private structures.
+ *
+ * Author: Ravi Ramachandra <r.ramachandra@ti.com>
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TCM_SITA_H
+#define _TCM_SITA_H
+
+#include "tcm.h"
+
+/* length between two coordinates */
+#define LEN(a, b) ((a) > (b) ? (a) - (b) + 1 : (b) - (a) + 1)
+
+enum criteria {
+ CR_MAX_NEIGHS = 0x01,
+ CR_FIRST_FOUND = 0x10,
+ CR_BIAS_HORIZONTAL = 0x20,
+ CR_BIAS_VERTICAL = 0x40,
+ CR_DIAGONAL_BALANCE = 0x80
+};
+
+/* nearness to the beginning of the search field from 0 to 1000 */
+struct nearness_factor {
+ s32 x;
+ s32 y;
+};
+
+/*
+ * Statistics on immediately neighboring slots. Edge is the number of
+ * border segments that are also border segments of the scan field. Busy
+ * refers to the number of neighbors that are occupied.
+ */
+struct neighbor_stats {
+ u16 edge;
+ u16 busy;
+};
+
+/* structure to keep the score of a potential allocation */
+struct score {
+ struct nearness_factor f;
+ struct neighbor_stats n;
+ struct tcm_area a;
+ u16 neighs; /* number of busy neighbors */
+};
+
+struct sita_pvt {
+ spinlock_t lock; /* spinlock to protect access */
+ struct tcm_pt div_pt; /* divider point splitting container */
+ struct tcm_area ***map; /* pointers to the parent area for each slot */
+};
+
+/* assign coordinates to area */
+static inline
+void assign(struct tcm_area *a, u16 x0, u16 y0, u16 x1, u16 y1)
+{
+ a->p0.x = x0;
+ a->p0.y = y0;
+ a->p1.x = x1;
+ a->p1.y = y1;
+}
+
+#endif
diff --git a/drivers/staging/omapdrm/tcm.h b/drivers/staging/omapdrm/tcm.h
new file mode 100644
index 000000000000..d273e3ee0b4c
--- /dev/null
+++ b/drivers/staging/omapdrm/tcm.h
@@ -0,0 +1,326 @@
+/*
+ * tcm.h
+ *
+ * TILER container manager specification and support functions for TI
+ * TILER driver.
+ *
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TCM_H
+#define TCM_H
+
+struct tcm;
+
+/* point */
+struct tcm_pt {
+ u16 x;
+ u16 y;
+};
+
+/* 1d or 2d area */
+struct tcm_area {
+ bool is2d; /* whether area is 1d or 2d */
+ struct tcm *tcm; /* parent */
+ struct tcm_pt p0;
+ struct tcm_pt p1;
+};
+
+struct tcm {
+ u16 width, height; /* container dimensions */
+ int lut_id; /* Lookup table identifier */
+
+ /* 'pvt' structure shall contain any tcm details (attr) along with
+ linked list of allocated areas and mutex for mutually exclusive access
+ to the list. It may also contain copies of width and height to notice
+ any changes to the publicly available width and height fields. */
+ void *pvt;
+
+ /* function table */
+ s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u8 align,
+ struct tcm_area *area);
+ s32 (*reserve_1d)(struct tcm *tcm, u32 slots, struct tcm_area *area);
+ s32 (*free) (struct tcm *tcm, struct tcm_area *area);
+ void (*deinit) (struct tcm *tcm);
+};
+
+/*=============================================================================
+ BASIC TILER CONTAINER MANAGER INTERFACE
+=============================================================================*/
+
+/*
+ * NOTE:
+ *
+ * Since some basic parameter checking is done outside the TCM algorithms,
+ * TCM implementation do NOT have to check the following:
+ *
+ * area pointer is NULL
+ * width and height fits within container
+ * number of pages is more than the size of the container
+ *
+ */
+
+struct tcm *sita_init(u16 width, u16 height, struct tcm_pt *attr);
+
+
+/**
+ * Deinitialize tiler container manager.
+ *
+ * @param tcm Pointer to container manager.
+ *
+ * @return 0 on success, non-0 error value on error. The call
+ * should free as much memory as possible and meaningful
+ * even on failure. Some error codes: -ENODEV: invalid
+ * manager.
+ */
+static inline void tcm_deinit(struct tcm *tcm)
+{
+ if (tcm)
+ tcm->deinit(tcm);
+}
+
+/**
+ * Reserves a 2D area in the container.
+ *
+ * @param tcm Pointer to container manager.
+ * @param height Height(in pages) of area to be reserved.
+ * @param width Width(in pages) of area to be reserved.
+ * @param align Alignment requirement for top-left corner of area. Not
+ * all values may be supported by the container manager,
+ * but it must support 0 (1), 32 and 64.
+ * 0 value is equivalent to 1.
+ * @param area Pointer to where the reserved area should be stored.
+ *
+ * @return 0 on success. Non-0 error code on failure. Also,
+ * the tcm field of the area will be set to NULL on
+ * failure. Some error codes: -ENODEV: invalid manager,
+ * -EINVAL: invalid area, -ENOMEM: not enough space for
+ * allocation.
+ */
+static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 width, u16 height,
+ u16 align, struct tcm_area *area)
+{
+ /* perform rudimentary error checking */
+ s32 res = tcm == NULL ? -ENODEV :
+ (area == NULL || width == 0 || height == 0 ||
+ /* align must be a 2 power */
+ (align & (align - 1))) ? -EINVAL :
+ (height > tcm->height || width > tcm->width) ? -ENOMEM : 0;
+
+ if (!res) {
+ area->is2d = true;
+ res = tcm->reserve_2d(tcm, height, width, align, area);
+ area->tcm = res ? NULL : tcm;
+ }
+
+ return res;
+}
+
+/**
+ * Reserves a 1D area in the container.
+ *
+ * @param tcm Pointer to container manager.
+ * @param slots Number of (contiguous) slots to reserve.
+ * @param area Pointer to where the reserved area should be stored.
+ *
+ * @return 0 on success. Non-0 error code on failure. Also,
+ * the tcm field of the area will be set to NULL on
+ * failure. Some error codes: -ENODEV: invalid manager,
+ * -EINVAL: invalid area, -ENOMEM: not enough space for
+ * allocation.
+ */
+static inline s32 tcm_reserve_1d(struct tcm *tcm, u32 slots,
+ struct tcm_area *area)
+{
+ /* perform rudimentary error checking */
+ s32 res = tcm == NULL ? -ENODEV :
+ (area == NULL || slots == 0) ? -EINVAL :
+ slots > (tcm->width * (u32) tcm->height) ? -ENOMEM : 0;
+
+ if (!res) {
+ area->is2d = false;
+ res = tcm->reserve_1d(tcm, slots, area);
+ area->tcm = res ? NULL : tcm;
+ }
+
+ return res;
+}
+
+/**
+ * Free a previously reserved area from the container.
+ *
+ * @param area Pointer to area reserved by a prior call to
+ * tcm_reserve_1d or tcm_reserve_2d call, whether
+ * it was successful or not. (Note: all fields of
+ * the structure must match.)
+ *
+ * @return 0 on success. Non-0 error code on failure. Also, the tcm
+ * field of the area is set to NULL on success to avoid subsequent
+ * freeing. This call will succeed even if supplying
+ * the area from a failed reserved call.
+ */
+static inline s32 tcm_free(struct tcm_area *area)
+{
+ s32 res = 0; /* free succeeds by default */
+
+ if (area && area->tcm) {
+ res = area->tcm->free(area->tcm, area);
+ if (res == 0)
+ area->tcm = NULL;
+ }
+
+ return res;
+}
+
+/*=============================================================================
+ HELPER FUNCTION FOR ANY TILER CONTAINER MANAGER
+=============================================================================*/
+
+/**
+ * This method slices off the topmost 2D slice from the parent area, and stores
+ * it in the 'slice' parameter. The 'parent' parameter will get modified to
+ * contain the remaining portion of the area. If the whole parent area can
+ * fit in a 2D slice, its tcm pointer is set to NULL to mark that it is no
+ * longer a valid area.
+ *
+ * @param parent Pointer to a VALID parent area that will get modified
+ * @param slice Pointer to the slice area that will get modified
+ */
+static inline void tcm_slice(struct tcm_area *parent, struct tcm_area *slice)
+{
+ *slice = *parent;
+
+ /* check if we need to slice */
+ if (slice->tcm && !slice->is2d &&
+ slice->p0.y != slice->p1.y &&
+ (slice->p0.x || (slice->p1.x != slice->tcm->width - 1))) {
+ /* set end point of slice (start always remains) */
+ slice->p1.x = slice->tcm->width - 1;
+ slice->p1.y = (slice->p0.x) ? slice->p0.y : slice->p1.y - 1;
+ /* adjust remaining area */
+ parent->p0.x = 0;
+ parent->p0.y = slice->p1.y + 1;
+ } else {
+ /* mark this as the last slice */
+ parent->tcm = NULL;
+ }
+}
+
+/* Verify if a tcm area is logically valid */
+static inline bool tcm_area_is_valid(struct tcm_area *area)
+{
+ return area && area->tcm &&
+ /* coordinate bounds */
+ area->p1.x < area->tcm->width &&
+ area->p1.y < area->tcm->height &&
+ area->p0.y <= area->p1.y &&
+ /* 1D coordinate relationship + p0.x check */
+ ((!area->is2d &&
+ area->p0.x < area->tcm->width &&
+ area->p0.x + area->p0.y * area->tcm->width <=
+ area->p1.x + area->p1.y * area->tcm->width) ||
+ /* 2D coordinate relationship */
+ (area->is2d &&
+ area->p0.x <= area->p1.x));
+}
+
+/* see if a coordinate is within an area */
+static inline bool __tcm_is_in(struct tcm_pt *p, struct tcm_area *a)
+{
+ u16 i;
+
+ if (a->is2d) {
+ return p->x >= a->p0.x && p->x <= a->p1.x &&
+ p->y >= a->p0.y && p->y <= a->p1.y;
+ } else {
+ i = p->x + p->y * a->tcm->width;
+ return i >= a->p0.x + a->p0.y * a->tcm->width &&
+ i <= a->p1.x + a->p1.y * a->tcm->width;
+ }
+}
+
+/* calculate area width */
+static inline u16 __tcm_area_width(struct tcm_area *area)
+{
+ return area->p1.x - area->p0.x + 1;
+}
+
+/* calculate area height */
+static inline u16 __tcm_area_height(struct tcm_area *area)
+{
+ return area->p1.y - area->p0.y + 1;
+}
+
+/* calculate number of slots in an area */
+static inline u16 __tcm_sizeof(struct tcm_area *area)
+{
+ return area->is2d ?
+ __tcm_area_width(area) * __tcm_area_height(area) :
+ (area->p1.x - area->p0.x + 1) + (area->p1.y - area->p0.y) *
+ area->tcm->width;
+}
+#define tcm_sizeof(area) __tcm_sizeof(&(area))
+#define tcm_awidth(area) __tcm_area_width(&(area))
+#define tcm_aheight(area) __tcm_area_height(&(area))
+#define tcm_is_in(pt, area) __tcm_is_in(&(pt), &(area))
+
+/* limit a 1D area to the first N pages */
+static inline s32 tcm_1d_limit(struct tcm_area *a, u32 num_pg)
+{
+ if (__tcm_sizeof(a) < num_pg)
+ return -ENOMEM;
+ if (!num_pg)
+ return -EINVAL;
+
+ a->p1.x = (a->p0.x + num_pg - 1) % a->tcm->width;
+ a->p1.y = a->p0.y + ((a->p0.x + num_pg - 1) / a->tcm->width);
+ return 0;
+}
+
+/**
+ * Iterate through 2D slices of a valid area. Behaves
+ * syntactically as a for(;;) statement.
+ *
+ * @param var Name of a local variable of type 'struct
+ * tcm_area *' that will get modified to
+ * contain each slice.
+ * @param area Pointer to the VALID parent area. This
+ * structure will not get modified
+ * throughout the loop.
+ *
+ */
+#define tcm_for_each_slice(var, area, safe) \
+ for (safe = area, \
+ tcm_slice(&safe, &var); \
+ var.tcm; tcm_slice(&safe, &var))
+
+#endif
diff --git a/drivers/staging/phison/phison.c b/drivers/staging/phison/phison.c
index 683657cb21f5..d77b21f1eb2d 100644
--- a/drivers/staging/phison/phison.c
+++ b/drivers/staging/phison/phison.c
@@ -70,7 +70,7 @@ static int phison_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
static DEFINE_PCI_DEVICE_TABLE(phison_pci_tbl) = {
- { PCI_VENDOR_ID_PHISON, PCI_DEVICE_ID_PS5000, PCI_ANY_ID, PCI_ANY_ID,
+ { PCI_DEVICE(PCI_VENDOR_ID_PHISON, PCI_DEVICE_ID_PS5000),
PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 },
{ 0, },
};
diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig
index 750c347bfbe1..f87e21101857 100644
--- a/drivers/staging/rtl8192e/Kconfig
+++ b/drivers/staging/rtl8192e/Kconfig
@@ -1,9 +1,43 @@
-config RTL8192E
- tristate "RealTek RTL8192E Wireless LAN NIC driver"
- depends on PCI && WLAN
- depends on m
- select WIRELESS_EXT
- select WEXT_PRIV
- select CRYPTO
- default N
+config RTLLIB
+ tristate "Support for rtllib wireless devices"
+ depends on WLAN && m
+ default n
+ select LIB80211
---help---
+ If you have a wireless card that uses rtllib, say
+ Y. Currently the only card is the rtl8192e.
+
+ If unsure, say N.
+
+if RTLLIB
+
+config RTLLIB_CRYPTO_CCMP
+ tristate "Support for rtllib CCMP crypto"
+ depends on RTLLIB
+ default y
+ ---help---
+ CCMP crypto driver for rtllib.
+
+ If you enabled RTLLIB, you want this.
+
+config RTLLIB_CRYPTO_TKIP
+ tristate "Support for rtllib TKIP crypto"
+ depends on RTLLIB
+ default y
+ ---help---
+ TKIP crypto driver for rtllib.
+
+ If you enabled RTLLIB, you want this.
+
+config RTLLIB_CRYPTO_WEP
+ tristate "Support for rtllib WEP crypto"
+ depends on RTLLIB
+ default y
+ ---help---
+ TKIP crypto driver for rtllib.
+
+ If you enabled RTLLIB, you want this.
+
+source "drivers/staging/rtl8192e/rtl8192e/Kconfig"
+
+endif
diff --git a/drivers/staging/rtl8192e/Makefile b/drivers/staging/rtl8192e/Makefile
index a66a9ad33686..cb18db74d78c 100644
--- a/drivers/staging/rtl8192e/Makefile
+++ b/drivers/staging/rtl8192e/Makefile
@@ -1,41 +1,21 @@
-ccflags-y += -DUSE_FW_SOURCE_IMG_FILE
-ccflags-y += -DCONFIG_PM_RTL
-ccflags-y += -DCONFIG_PM
-ccflags-y += -DHAVE_NET_DEVICE_OPS
-ccflags-y += -DENABLE_DOT11D
-
-r8192e_pci-objs := \
- rtl_core.o \
- rtl_eeprom.o \
- rtl_ps.o \
- rtl_wx.o \
- rtl_cam.o \
- rtl_dm.o \
- rtl_pm.o \
- rtl_pci.o \
- rtl_debug.o \
- rtl_ethtool.o \
- r8192E_dev.o \
- r8192E_phy.o \
- r8192E_firmware.o \
- r8192E_cmdpkt.o \
- r8192E_hwimg.o \
- r8190P_rtl8256.o \
+rtllib-objs := \
+ dot11d.o \
+ rtllib_module.o \
rtllib_rx.o \
- rtllib_softmac.o \
rtllib_tx.o \
rtllib_wx.o \
- rtllib_module.o \
+ rtllib_softmac.o \
rtllib_softmac_wx.o \
- rtl819x_HTProc.o \
- rtl819x_TSProc.o \
rtl819x_BAProc.o \
- dot11d.o \
- rtllib_crypt.o \
- rtllib_crypt_tkip.o \
- rtllib_crypt_ccmp.o \
- rtllib_crypt_wep.o
+ rtl819x_HTProc.o \
+ rtl819x_TSProc.o
+
+obj-$(CONFIG_RTLLIB) += rtllib.o
+
+obj-$(CONFIG_RTLLIB_CRYPTO_CCMP) += rtllib_crypt_ccmp.o
+obj-$(CONFIG_RTLLIB_CRYPTO_TKIP) += rtllib_crypt_tkip.o
+obj-$(CONFIG_RTLLIB_CRYPTO_WEP) += rtllib_crypt_wep.o
-obj-$(CONFIG_RTL8192E) += r8192e_pci.o
+obj-$(CONFIG_RTL8192E) += rtl8192e/
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c
index ee0381e0a81f..f7b14f8b7b83 100644
--- a/drivers/staging/rtl8192e/dot11d.c
+++ b/drivers/staging/rtl8192e/dot11d.c
@@ -46,7 +46,7 @@ static struct channel_list ChannelPlan[] = {
56, 60, 64}, 21}
};
-void Dot11d_Init(struct rtllib_device *ieee)
+void dot11d_init(struct rtllib_device *ieee)
{
struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee);
pDot11dInfo->bEnabled = false;
@@ -58,6 +58,7 @@ void Dot11d_Init(struct rtllib_device *ieee)
RESET_CIE_WATCHDOG(ieee);
}
+EXPORT_SYMBOL(dot11d_init);
void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee)
{
@@ -99,6 +100,7 @@ void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee)
break;
}
}
+EXPORT_SYMBOL(Dot11d_Channelmap);
void Dot11d_Reset(struct rtllib_device *ieee)
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 032f7004a7f0..71f4549a378f 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -93,7 +93,7 @@ static inline void cpMacAddr(unsigned char *des, unsigned char *src)
#define IS_DOT11D_STATE_DONE(__pIeeeDev) \
(GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
-void Dot11d_Init(struct rtllib_device *dev);
+void dot11d_init(struct rtllib_device *dev);
void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee);
void Dot11d_Reset(struct rtllib_device *dev);
void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr,
diff --git a/drivers/staging/rtl8192e/rtl8192e/Kconfig b/drivers/staging/rtl8192e/rtl8192e/Kconfig
new file mode 100644
index 000000000000..50e0d91a409a
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/Kconfig
@@ -0,0 +1,9 @@
+config RTL8192E
+ tristate "RealTek RTL8192E Wireless LAN NIC driver"
+ depends on PCI && WLAN && RTLLIB
+ depends on m
+ select WIRELESS_EXT
+ select WEXT_PRIV
+ select CRYPTO
+ default N
+ ---help---
diff --git a/drivers/staging/rtl8192e/rtl8192e/Makefile b/drivers/staging/rtl8192e/rtl8192e/Makefile
new file mode 100644
index 000000000000..313a92ec6833
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/Makefile
@@ -0,0 +1,21 @@
+r8192e_pci-objs := \
+ r8192E_dev.o \
+ r8192E_phy.o \
+ r8192E_firmware.o \
+ r8192E_cmdpkt.o \
+ r8192E_hwimg.o \
+ r8190P_rtl8256.o \
+ rtl_cam.o \
+ rtl_core.o \
+ rtl_debug.o \
+ rtl_dm.o \
+ rtl_eeprom.o \
+ rtl_ethtool.o \
+ rtl_pci.o \
+ rtl_pm.o \
+ rtl_ps.o \
+ rtl_wx.o \
+
+obj-$(CONFIG_RTL8192E) += r8192e_pci.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/staging/rtl8192e/r8190P_def.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
index b7bb71fa9ecd..b7bb71fa9ecd 100644
--- a/drivers/staging/rtl8192e/r8190P_def.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
diff --git a/drivers/staging/rtl8192e/r8190P_rtl8256.c b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
index 0da56c80f088..0da56c80f088 100644
--- a/drivers/staging/rtl8192e/r8190P_rtl8256.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
diff --git a/drivers/staging/rtl8192e/r8190P_rtl8256.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h
index 64e831d2f4e5..64e831d2f4e5 100644
--- a/drivers/staging/rtl8192e/r8190P_rtl8256.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h
diff --git a/drivers/staging/rtl8192e/r8192E_cmdpkt.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
index 58d044ea5524..58d044ea5524 100644
--- a/drivers/staging/rtl8192e/r8192E_cmdpkt.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
diff --git a/drivers/staging/rtl8192e/r8192E_cmdpkt.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
index 23219e17e5a1..23219e17e5a1 100644
--- a/drivers/staging/rtl8192e/r8192E_cmdpkt.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
diff --git a/drivers/staging/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index 808aab6fa5ef..808aab6fa5ef 100644
--- a/drivers/staging/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
diff --git a/drivers/staging/rtl8192e/r8192E_dev.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h
index b9b3b52f9120..b9b3b52f9120 100644
--- a/drivers/staging/rtl8192e/r8192E_dev.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h
diff --git a/drivers/staging/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
index 37719859bdae..37719859bdae 100644
--- a/drivers/staging/rtl8192e/r8192E_firmware.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
diff --git a/drivers/staging/rtl8192e/r8192E_firmware.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
index caa878833106..caa878833106 100644
--- a/drivers/staging/rtl8192e/r8192E_firmware.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
diff --git a/drivers/staging/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
index 43c3fb859d10..43c3fb859d10 100644
--- a/drivers/staging/rtl8192e/r8192E_hw.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
diff --git a/drivers/staging/rtl8192e/r8192E_hwimg.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c
index 08e7dbb6694b..08e7dbb6694b 100644
--- a/drivers/staging/rtl8192e/r8192E_hwimg.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c
diff --git a/drivers/staging/rtl8192e/r8192E_hwimg.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.h
index 019836bb36c2..019836bb36c2 100644
--- a/drivers/staging/rtl8192e/r8192E_hwimg.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.h
diff --git a/drivers/staging/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
index 7fe69a3348d7..3e705efaaf22 100644
--- a/drivers/staging/rtl8192e/r8192E_phy.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
@@ -23,7 +23,6 @@
#include "r8190P_rtl8256.h"
#include "r8192E_phy.h"
#include "rtl_dm.h"
-#include "dot11d.h"
#include "r8192E_hwimg.h"
@@ -859,7 +858,7 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
RT_TRACE(COMP_TRACE, "====>%s()====stage:%d, step:%d, channel:%d\n",
__func__, *stage, *step, channel);
- if (!IsLegalChannel(priv->rtllib, channel)) {
+ if (!rtllib_legal_channel(priv->rtllib, channel)) {
RT_TRACE(COMP_ERR, "=============>set to illegal channel:%d\n",
channel);
return true;
diff --git a/drivers/staging/rtl8192e/r8192E_phy.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h
index 7318f8857af2..7318f8857af2 100644
--- a/drivers/staging/rtl8192e/r8192E_phy.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h
diff --git a/drivers/staging/rtl8192e/r8192E_phyreg.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h
index 7899dd538dcd..7899dd538dcd 100644
--- a/drivers/staging/rtl8192e/r8192E_phyreg.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h
diff --git a/drivers/staging/rtl8192e/r819xE_phyreg.h b/drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h
index d5de279f6644..d5de279f6644 100644
--- a/drivers/staging/rtl8192e/r819xE_phyreg.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h
diff --git a/drivers/staging/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
index baf3b6342e44..baf3b6342e44 100644
--- a/drivers/staging/rtl8192e/rtl_cam.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
diff --git a/drivers/staging/rtl8192e/rtl_cam.h b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h
index fa607f98b172..fa607f98b172 100644
--- a/drivers/staging/rtl8192e/rtl_cam.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h
diff --git a/drivers/staging/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index 5ad96649f407..71adb6b3344d 100644
--- a/drivers/staging/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -53,9 +53,7 @@
#include "rtl_wx.h"
#include "rtl_dm.h"
-#ifdef CONFIG_PM_RTL
#include "rtl_pm.h"
-#endif
int hwwep = 1;
static int channels = 0x3fff;
@@ -581,7 +579,7 @@ static void rtl8192_update_beacon(void *data)
struct rtllib_network *net = &ieee->current_network;
if (ieee->pHTInfo->bCurrentHTSupport)
- HTUpdateSelfAndPeerSetting(ieee, net);
+ HT_update_self_and_peer_setting(ieee, net);
ieee->pHTInfo->bCurrentRT2RTLongSlotTime =
net->bssht.bdRT2RTLongSlotTime;
ieee->pHTInfo->RT2RT_HT_Mode = net->bssht.RT2RT_HT_Mode;
@@ -1289,7 +1287,7 @@ static short rtl8192_get_channel_map(struct net_device *dev)
priv->ChannelPlan = COUNTRY_CODE_FCC;
}
RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
- Dot11d_Init(priv->rtllib);
+ dot11d_init(priv->rtllib);
Dot11d_Channelmap(priv->ChannelPlan, priv->rtllib);
for (i = 1; i <= 11; i++)
(priv->rtllib->active_channel_map)[i] = 1;
@@ -1305,7 +1303,6 @@ static short rtl8192_init(struct net_device *dev)
memset(&(priv->stats), 0, sizeof(struct rt_stats));
- rtl8192_dbgp_flag_init(dev);
rtl8192_init_priv_handler(dev);
rtl8192_init_priv_constant(dev);
rtl8192_init_priv_variable(dev);
@@ -2839,7 +2836,6 @@ done:
/****************************************************************************
---------------------------- PCI_STUFF---------------------------
*****************************************************************************/
-#ifdef HAVE_NET_DEVICE_OPS
static const struct net_device_ops rtl8192_netdev_ops = {
.ndo_open = rtl8192_open,
.ndo_stop = rtl8192_close,
@@ -2851,7 +2847,6 @@ static const struct net_device_ops rtl8192_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
.ndo_start_xmit = rtllib_xmit,
};
-#endif
static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
@@ -2938,17 +2933,7 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
dev->irq = pdev->irq;
priv->irq = 0;
-#ifdef HAVE_NET_DEVICE_OPS
dev->netdev_ops = &rtl8192_netdev_ops;
-#else
- dev->open = rtl8192_open;
- dev->stop = rtl8192_close;
- dev->tx_timeout = rtl8192_tx_timeout;
- dev->do_ioctl = rtl8192_ioctl;
- dev->set_multicast_list = r8192_set_multicast;
- dev->set_mac_address = r8192_set_mac_adr;
- dev->hard_start_xmit = rtllib_xmit;
-#endif
dev->wireless_handlers = (struct iw_handler_def *)
&r8192_wx_handlers_def;
@@ -2974,10 +2959,7 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
register_netdev(dev);
RT_TRACE(COMP_INIT, "dev name: %s\n", dev->name);
- err = rtl_debug_module_init(priv, dev->name);
- if (err)
- RT_TRACE(COMP_DBG, "failed to create debugfs files. Ignoring "
- "error: %d\n", err);
+
rtl8192_proc_init_one(dev);
if (priv->polling_timer_on == 0)
@@ -3015,7 +2997,6 @@ static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
del_timer_sync(&priv->gpio_polling_timer);
cancel_delayed_work(&priv->gpio_change_rf_wq);
priv->polling_timer_on = 0;
- rtl_debug_module_remove(priv);
rtl8192_proc_remove_one(dev);
rtl8192_down(dev, true);
deinit_hal_dm(dev);
@@ -3103,43 +3084,9 @@ bool NicIFDisableNIC(struct net_device *dev)
static int __init rtl8192_pci_module_init(void)
{
- int ret;
- int error;
-
- ret = rtllib_init();
- if (ret) {
- printk(KERN_ERR "rtllib_init() failed %d\n", ret);
- return ret;
- }
- ret = rtllib_crypto_init();
- if (ret) {
- printk(KERN_ERR "rtllib_crypto_init() failed %d\n", ret);
- return ret;
- }
- ret = rtllib_crypto_tkip_init();
- if (ret) {
- printk(KERN_ERR "rtllib_crypto_tkip_init() failed %d\n", ret);
- return ret;
- }
- ret = rtllib_crypto_ccmp_init();
- if (ret) {
- printk(KERN_ERR "rtllib_crypto_ccmp_init() failed %d\n", ret);
- return ret;
- }
- ret = rtllib_crypto_wep_init();
- if (ret) {
- printk(KERN_ERR "rtllib_crypto_wep_init() failed %d\n", ret);
- return ret;
- }
printk(KERN_INFO "\nLinux kernel driver for RTL8192E WLAN cards\n");
printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan Driver\n");
- error = rtl_create_debugfs_root();
- if (error) {
- RT_TRACE(COMP_DBG, "Create debugfs root fail: %d\n", error);
- goto err_out;
- }
-
rtl8192_proc_module_init();
if (0 != pci_register_driver(&rtl8192_pci_driver)) {
DMESG("No device found");
@@ -3147,9 +3094,6 @@ static int __init rtl8192_pci_module_init(void)
return -ENODEV;
}
return 0;
-err_out:
- return error;
-
}
static void __exit rtl8192_pci_module_exit(void)
@@ -3158,12 +3102,6 @@ static void __exit rtl8192_pci_module_exit(void)
RT_TRACE(COMP_DOWN, "Exiting");
rtl8192_proc_module_remove();
- rtl_remove_debugfs_root();
- rtllib_crypto_tkip_exit();
- rtllib_crypto_ccmp_exit();
- rtllib_crypto_wep_exit();
- rtllib_crypto_deinit();
- rtllib_exit();
}
void check_rfctrl_gpio_timer(unsigned long data)
diff --git a/drivers/staging/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
index f9af5153d9cf..2a2519cc284d 100644
--- a/drivers/staging/rtl8192e/rtl_core.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
@@ -44,11 +44,14 @@
#include <linux/proc_fs.h>
#include <linux/if_arp.h>
#include <linux/random.h>
-#include <linux/version.h>
#include <linux/io.h>
-#include "rtllib.h"
-#include "dot11d.h"
+/* Need this defined before including local include files */
+#define DRV_NAME "rtl819xE"
+
+#include "../rtllib.h"
+
+#include "../dot11d.h"
#include "r8192E_firmware.h"
#include "r8192E_hw.h"
@@ -56,7 +59,6 @@
#include "r8190P_def.h"
#include "r8192E_dev.h"
-#include "rtl_debug.h"
#include "rtl_eeprom.h"
#include "rtl_ps.h"
#include "rtl_pci.h"
@@ -67,8 +69,6 @@
#define DRV_AUTHOR "<wlanfae@realtek.com>"
#define DRV_VERSION "0014.0401.2010"
-#define DRV_NAME "rtl819xE"
-
#define IS_HARDWARE_TYPE_819xP(_priv) \
((((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8190P) || \
(((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8192E))
@@ -215,41 +215,6 @@ enum RTL819x_PHY_PARAM {
RTL819X_EFUSE_MAP = 19,
};
-enum RTL_DEBUG {
- COMP_TRACE = BIT0,
- COMP_DBG = BIT1,
- COMP_INIT = BIT2,
- COMP_RECV = BIT3,
- COMP_SEND = BIT4,
- COMP_CMD = BIT5,
- COMP_POWER = BIT6,
- COMP_EPROM = BIT7,
- COMP_SWBW = BIT8,
- COMP_SEC = BIT9,
- COMP_LPS = BIT10,
- COMP_QOS = BIT11,
- COMP_RATE = BIT12,
- COMP_RXDESC = BIT13,
- COMP_PHY = BIT14,
- COMP_DIG = BIT15,
- COMP_TXAGC = BIT16,
- COMP_HALDM = BIT17,
- COMP_POWER_TRACKING = BIT18,
- COMP_CH = BIT19,
- COMP_RF = BIT20,
- COMP_FIRMWARE = BIT21,
- COMP_HT = BIT22,
- COMP_RESET = BIT23,
- COMP_CMDPKT = BIT24,
- COMP_SCAN = BIT25,
- COMP_PS = BIT26,
- COMP_DOWN = BIT27,
- COMP_INTR = BIT28,
- COMP_LED = BIT29,
- COMP_MLME = BIT30,
- COMP_ERR = BIT31
-};
-
enum nic_t {
NIC_UNKNOWN = 0,
NIC_8192E = 1,
@@ -1121,4 +1086,10 @@ void ActUpdateChannelAccessSetting(struct net_device *dev,
enum wireless_mode WirelessMode,
struct channel_access_setting *ChnlAccessSetting);
+/* proc stuff from rtl_debug.c */
+void rtl8192_proc_init_one(struct net_device *dev);
+void rtl8192_proc_remove_one(struct net_device *dev);
+void rtl8192_proc_module_init(void);
+void rtl8192_proc_module_remove(void);
+
#endif
diff --git a/drivers/staging/rtl8192e/rtl_crypto.h b/drivers/staging/rtl8192e/rtl8192e/rtl_crypto.h
index ee57c0f4fa69..ee57c0f4fa69 100644
--- a/drivers/staging/rtl8192e/rtl_crypto.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_crypto.h
diff --git a/drivers/staging/rtl8192e/rtl_debug.c b/drivers/staging/rtl8192e/rtl8192e/rtl_debug.c
index 22bc2dd6e438..c19b14cd6f77 100644
--- a/drivers/staging/rtl8192e/rtl_debug.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_debug.c
@@ -22,91 +22,12 @@
* Contact Information:
* wlanfae <wlanfae@realtek.com>
******************************************************************************/
-#include "rtl_debug.h"
#include "rtl_core.h"
#include "r8192E_phy.h"
#include "r8192E_phyreg.h"
#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
#include "r8192E_cmdpkt.h"
-u32 rt_global_debug_component = \
- COMP_ERR ;
-
-/*------------------Declare variable-----------------------*/
-u32 DBGP_Type[DBGP_TYPE_MAX];
-
-/*-----------------------------------------------------------------------------
- * Function: DBGP_Flag_Init
- *
- * Overview: Refresh all debug print control flag content to zero.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 10/20/2006 MHC Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-void rtl8192_dbgp_flag_init(struct net_device *dev)
-{
- u8 i;
-
- for (i = 0; i < DBGP_TYPE_MAX; i++)
- DBGP_Type[i] = 0;
-
-
-} /* DBGP_Flag_Init */
-
-/* this is only for debugging */
-void print_buffer(u32 *buffer, int len)
-{
- int i;
- u8 *buf = (u8 *)buffer;
-
- printk(KERN_INFO "ASCII BUFFER DUMP (len: %x):\n", len);
-
- for (i = 0; i < len; i++)
- printk(KERN_INFO "%c", buf[i]);
-
- printk(KERN_INFO "\nBINARY BUFFER DUMP (len: %x):\n", len);
-
- for (i = 0; i < len; i++)
- printk(KERN_INFO "%x", buf[i]);
-
- printk(KERN_INFO "\n");
-}
-
-/* this is only for debug */
-void dump_eprom(struct net_device *dev)
-{
- int i;
-
- for (i = 0; i < 0xff; i++)
- RT_TRACE(COMP_INIT, "EEPROM addr %x : %x", i,
- eprom_read(dev, i));
-}
-
-/* this is only for debug */
-void rtl8192_dump_reg(struct net_device *dev)
-{
- int i;
- int n;
- int max = 0x5ff;
-
- RT_TRACE(COMP_INIT, "Dumping NIC register map");
-
- for (n = 0; n <= max; ) {
- printk(KERN_INFO "\nD: %2x> ", n);
- for (i = 0; i < 16 && n <= max; i++, n++)
- printk(KERN_INFO "%2x ", read_nic_byte(dev, n));
- }
- printk(KERN_INFO "\n");
-}
-
/****************************************************************************
-----------------------------PROCFS STUFF-------------------------
*****************************************************************************/
diff --git a/drivers/staging/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
index a7fa9aad6f2d..a7fa9aad6f2d 100644
--- a/drivers/staging/rtl8192e/rtl_dm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
diff --git a/drivers/staging/rtl8192e/rtl_dm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h
index ab44a9a6927c..ab44a9a6927c 100644
--- a/drivers/staging/rtl8192e/rtl_dm.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h
diff --git a/drivers/staging/rtl8192e/rtl_eeprom.c b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c
index c1ccff4a8321..c1ccff4a8321 100644
--- a/drivers/staging/rtl8192e/rtl_eeprom.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c
diff --git a/drivers/staging/rtl8192e/rtl_eeprom.h b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h
index 9452e1683a72..9452e1683a72 100644
--- a/drivers/staging/rtl8192e/rtl_eeprom.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h
diff --git a/drivers/staging/rtl8192e/rtl_ethtool.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c
index 36452fb7cef8..36452fb7cef8 100644
--- a/drivers/staging/rtl8192e/rtl_ethtool.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c
diff --git a/drivers/staging/rtl8192e/rtl_pci.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c
index ddadcc3e4e7c..ddadcc3e4e7c 100644
--- a/drivers/staging/rtl8192e/rtl_pci.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c
diff --git a/drivers/staging/rtl8192e/rtl_pci.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
index 7ea5a47dfd2b..28c7da677a80 100644
--- a/drivers/staging/rtl8192e/rtl_pci.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
@@ -27,7 +27,6 @@
#include <linux/types.h>
#include <linux/pci.h>
-#include "rtllib.h"
static inline void NdisRawWritePortUlong(u32 port, u32 val)
{
diff --git a/drivers/staging/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
index 92e2fde7f5f4..8e1a5d55dce8 100644
--- a/drivers/staging/rtl8192e/rtl_pm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
@@ -17,7 +17,6 @@
* wlanfae <wlanfae@realtek.com>
******************************************************************************/
-#ifdef CONFIG_PM_RTL
#include "rtl_core.h"
#include "r8192E_hw.h"
#include "r8190P_rtl8256.h"
@@ -133,4 +132,3 @@ int rtl8192E_enable_wake(struct pci_dev *dev, pm_message_t state, int enable)
return -EAGAIN;
}
-#endif
diff --git a/drivers/staging/rtl8192e/rtl_pm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h
index 4d7f4067cc78..e5299fc3b34a 100644
--- a/drivers/staging/rtl8192e/rtl_pm.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h
@@ -17,8 +17,6 @@
* wlanfae <wlanfae@realtek.com>
******************************************************************************/
-#ifdef CONFIG_PM_RTL
-
#ifndef R8192E_PM_H
#define R8192E_PM_H
@@ -31,5 +29,3 @@ int rtl8192E_resume(struct pci_dev *dev);
int rtl8192E_enable_wake(struct pci_dev *dev, pm_message_t state, int enable);
#endif
-
-#endif
diff --git a/drivers/staging/rtl8192e/rtl_ps.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
index c9a7c563b682..c9a7c563b682 100644
--- a/drivers/staging/rtl8192e/rtl_ps.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
diff --git a/drivers/staging/rtl8192e/rtl_ps.h b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h
index a9c2d799c08f..df79d6c4ca03 100644
--- a/drivers/staging/rtl8192e/rtl_ps.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h
@@ -26,7 +26,7 @@
#define _RTL_PS_H
#include <linux/types.h>
-#include "rtllib.h"
+
struct net_device;
#define RT_CHECK_FOR_HANG_PERIOD 2
diff --git a/drivers/staging/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
index 93b1edbe6bae..4e93669210af 100644
--- a/drivers/staging/rtl8192e/rtl_wx.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
@@ -19,7 +19,6 @@
#include <linux/string.h>
#include "rtl_core.h"
-#include "dot11d.h"
#define RATE_COUNT 12
static u32 rtl8192_rates[] = {
@@ -803,7 +802,7 @@ static int r8192_wx_set_enc(struct net_device *dev,
switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
case 0:
- key_idx = ieee->tx_keyidx;
+ key_idx = ieee->crypt_info.tx_keyidx;
break;
case 1:
key_idx = 0;
diff --git a/drivers/staging/rtl8192e/rtl_wx.h b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.h
index 6a51a25ec87d..6a51a25ec87d 100644
--- a/drivers/staging/rtl8192e/rtl_wx.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.h
diff --git a/drivers/staging/rtl8192e/rtl819x_BAProc.c b/drivers/staging/rtl8192e/rtl819x_BAProc.c
index 8b9d85c48be6..32fbbc9d0d92 100644
--- a/drivers/staging/rtl8192e/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_BAProc.c
@@ -18,7 +18,6 @@
******************************************************************************/
#include "rtllib.h"
#include "rtl819x_BA.h"
-#include "rtl_core.h"
static void ActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA,
u16 Time)
diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c
index b1c0c566882f..8b7412980ebb 100644
--- a/drivers/staging/rtl8192e/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c
@@ -943,8 +943,8 @@ void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee,
}
}
-void HTUpdateSelfAndPeerSetting(struct rtllib_device *ieee,
- struct rtllib_network *pNetwork)
+void HT_update_self_and_peer_setting(struct rtllib_device *ieee,
+ struct rtllib_network *pNetwork)
{
struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
struct ht_info_ele *pPeerHTInfo =
@@ -955,6 +955,7 @@ void HTUpdateSelfAndPeerSetting(struct rtllib_device *ieee,
pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
}
}
+EXPORT_SYMBOL(HT_update_self_and_peer_setting);
void HTUseDefaultSetting(struct rtllib_device *ieee)
{
diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c
index 09a602f74329..711a096be7a7 100644
--- a/drivers/staging/rtl8192e/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c
@@ -497,6 +497,7 @@ void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr)
}
}
}
+EXPORT_SYMBOL(RemovePeerTS);
void RemoveAllTS(struct rtllib_device *ieee)
{
diff --git a/drivers/staging/rtl8192e/rtl_debug.h b/drivers/staging/rtl8192e/rtl_debug.h
deleted file mode 100644
index 50fb9a9b828a..000000000000
--- a/drivers/staging/rtl8192e/rtl_debug.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/******************************************************************************
- * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
- *
- * Based on the r8180 driver, which is:
- * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
-******************************************************************************/
-#ifndef _RTL_DEBUG_H
-#define _RTL_DEBUG_H
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/debugfs.h>
-
-struct r8192_priv;
-struct _tx_desc_8192se;
-struct _TX_DESC_8192CE;
-struct net_device;
-
-#define DBG_LOUD 4
-
-#define RT_ASSERT(_Exp, Fmt) \
- if (!(_Exp)) { \
- printk("Rtl819x: "); \
- printk Fmt; \
- }
-
-enum dbgp_flag {
- FQoS = 0,
- FTX = 1,
- FRX = 2,
- FSEC = 3,
- FMGNT = 4,
- FMLME = 5,
- FRESOURCE = 6,
- FBEACON = 7,
- FISR = 8,
- FPHY = 9,
- FMP = 10,
- FEEPROM = 11,
- FPWR = 12,
- FDM = 13,
- FDBGCtrl = 14,
- FC2H = 15,
- FBT = 16,
- FINIT = 17,
- FIOCTL = 18,
- DBGP_TYPE_MAX
-};
-
-#define QoS_INIT BIT0
-#define QoS_VISTA BIT1
-
-#define TX_DESC BIT0
-#define TX_DESC_TID BIT1
-
-#define RX_DATA BIT0
-#define RX_PHY_STS BIT1
-#define RX_PHY_SS BIT2
-#define RX_PHY_SQ BIT3
-#define RX_PHY_ASTS BIT4
-#define RX_ERR_LEN BIT5
-#define RX_DEFRAG BIT6
-#define RX_ERR_RATE BIT7
-
-
-
-#define MEDIA_STS BIT0
-#define LINK_STS BIT1
-
-#define OS_CHK BIT0
-
-#define BCN_SHOW BIT0
-#define BCN_PEER BIT1
-
-#define ISR_CHK BIT0
-
-#define PHY_BBR BIT0
-#define PHY_BBW BIT1
-#define PHY_RFR BIT2
-#define PHY_RFW BIT3
-#define PHY_MACR BIT4
-#define PHY_MACW BIT5
-#define PHY_ALLR BIT6
-#define PHY_ALLW BIT7
-#define PHY_TXPWR BIT8
-#define PHY_PWRDIFF BIT9
-
-#define MP_RX BIT0
-#define MP_SWICH_CH BIT1
-
-#define EEPROM_W BIT0
-#define EFUSE_PG BIT1
-#define EFUSE_READ_ALL BIT2
-
-#define LPS BIT0
-#define IPS BIT1
-#define PWRSW BIT2
-#define PWRHW BIT3
-#define PWRHAL BIT4
-
-#define WA_IOT BIT0
-#define DM_PWDB BIT1
-#define DM_Monitor BIT2
-#define DM_DIG BIT3
-#define DM_EDCA_Turbo BIT4
-
-#define DbgCtrl_Trace BIT0
-#define DbgCtrl_InbandNoise BIT1
-
-#define BT_TRACE BIT0
-#define BT_RFPoll BIT1
-
-#define C2H_Summary BIT0
-#define C2H_PacketData BIT1
-#define C2H_ContentData BIT2
-#define BT_TRACE BIT0
-#define BT_RFPoll BIT1
-
-#define INIT_EEPROM BIT0
-#define INIT_TxPower BIT1
-#define INIT_IQK BIT2
-#define INIT_RF BIT3
-
-#define IOCTL_TRACE BIT0
-#define IOCTL_BT_EVENT BIT1
-#define IOCTL_BT_EVENT_DETAIL BIT2
-#define IOCTL_BT_TX_ACLDATA BIT3
-#define IOCTL_BT_TX_ACLDATA_DETAIL BIT4
-#define IOCTL_BT_RX_ACLDATA BIT5
-#define IOCTL_BT_RX_ACLDATA_DETAIL BIT6
-#define IOCTL_BT_HCICMD BIT7
-#define IOCTL_BT_HCICMD_DETAIL BIT8
-#define IOCTL_IRP BIT9
-#define IOCTL_IRP_DETAIL BIT10
-#define IOCTL_CALLBACK_FUN BIT11
-#define IOCTL_STATE BIT12
-#define IOCTL_BT_TP BIT13
-#define IOCTL_BT_LOGO BIT14
-
-/* 2007/07/13 MH ------For DeBuG Print modeue------*/
-/*------------------------------Define structure----------------------------*/
-
-
-/*------------------------Export Marco Definition---------------------------*/
-#define DEBUG_PRINT 1
-
-#if (DEBUG_PRINT == 1)
-#define RTPRINT(dbgtype, dbgflag, printstr) \
-{ \
- if (DBGP_Type[dbgtype] & dbgflag) { \
- printk printstr; \
- } \
-}
-
-#define RTPRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr) \
-{ \
- if (DBGP_Type[dbgtype] & dbgflag) { \
- int __i; \
- u8 *ptr = (u8 *)_Ptr; \
- printk printstr; \
- printk(" "); \
- for (__i = 0; __i < 6; __i++) \
- printk("%02X%s", ptr[__i], \
- (__i == 5) ? "" : "-"); \
- printk("\n"); \
- } \
-}
-
-#define RTPRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)\
-{ \
- if (DBGP_Type[dbgtype] & dbgflag) { \
- int __i; \
- u8 *ptr = (u8 *)_HexData; \
- printk(_TitleString); \
- for (__i = 0; __i < (int)_HexDataLen; __i++) { \
- printk("%02X%s", ptr[__i], (((__i + 1) \
- % 4) == 0) ? " " : " "); \
- if (((__i + 1) % 16) == 0) \
- printk("\n"); \
- } \
- printk("\n"); \
- } \
-}
-#else
-#define RTPRINT(dbgtype, dbgflag, printstr)
-#define RTPRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr)
-#define RTPRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)
-#endif
-
-extern u32 DBGP_Type[DBGP_TYPE_MAX];
-
-#define RT_PRINT_DATA(_Comp, _Level, _TitleString, _HexData, _HexDataLen) \
-do {\
- if (((_Comp) & rt_global_debug_component) && \
- (_Level <= rt_global_debug_component)) { \
- int __i; \
- u8* ptr = (u8 *)_HexData; \
- printk(KERN_INFO "Rtl819x: "); \
- printk(_TitleString); \
- for (__i = 0; __i < (int)_HexDataLen; __i++) { \
- printk("%02X%s", ptr[__i], (((__i + 1) % \
- 4) == 0) ? " " : " "); \
- if (((__i + 1) % 16) == 0) \
- printk("\n"); \
- } \
- printk("\n"); \
- } \
-} while (0);
-
-#define DMESG(x, a...)
-#define DMESGW(x, a...)
-#define DMESGE(x, a...)
-extern u32 rt_global_debug_component;
-#define RT_TRACE(component, x, args...) \
-do { \
- if (rt_global_debug_component & component) \
- printk(KERN_DEBUG DRV_NAME ":" x "\n" , \
- ##args);\
-} while (0);
-
-#define assert(expr) \
- if (!(expr)) { \
- printk(KERN_INFO "Assertion failed! %s,%s,%s,line=%d\n", \
- #expr, __FILE__, __func__, __LINE__); \
- }
-#define RT_DEBUG_DATA(level, data, datalen) \
- do { \
- if ((rt_global_debug_component & (level)) == (level)) {\
- int _i; \
- u8 *_pdata = (u8 *)data; \
- printk(KERN_DEBUG DRV_NAME ": %s()\n", __func__); \
- for (_i = 0; _i < (int)(datalen); _i++) { \
- printk(KERN_INFO "%2x ", _pdata[_i]); \
- if ((_i+1) % 16 == 0) \
- printk("\n"); \
- } \
- printk(KERN_INFO "\n"); \
- } \
- } while (0)
-
-struct rtl_fs_debug {
- const char *name;
- struct dentry *dir_drv;
- struct dentry *debug_register;
- u32 hw_type;
- u32 hw_offset;
- bool hw_holding;
-};
-
-void print_buffer(u32 *buffer, int len);
-void dump_eprom(struct net_device *dev);
-void rtl8192_dump_reg(struct net_device *dev);
-
-/* debugfs stuff */
-static inline int rtl_debug_module_init(struct r8192_priv *priv,
- const char *name)
-{
- return 0;
-}
-
-static inline void rtl_debug_module_remove(struct r8192_priv *priv)
-{
-}
-
-static inline int rtl_create_debugfs_root(void)
-{
- return 0;
-}
-
-static inline void rtl_remove_debugfs_root(void)
-{
-}
-
-/* proc stuff */
-void rtl8192_proc_init_one(struct net_device *dev);
-void rtl8192_proc_remove_one(struct net_device *dev);
-void rtl8192_proc_module_init(void);
-void rtl8192_proc_module_remove(void);
-void rtl8192_dbgp_flag_init(struct net_device *dev);
-
-#endif
diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
index de25975ccee4..e26aec86a5c8 100644
--- a/drivers/staging/rtl8192e/rtllib.h
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -25,7 +25,6 @@
#define RTLLIB_H
#include <linux/if_ether.h> /* ETH_ALEN */
#include <linux/kernel.h> /* ARRAY_SIZE */
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
@@ -36,12 +35,14 @@
#include <linux/delay.h>
#include <linux/wireless.h>
+#include "rtllib_debug.h"
#include "rtl819x_HT.h"
#include "rtl819x_BA.h"
#include "rtl819x_TS.h"
#include <linux/netdevice.h>
#include <linux/if_arp.h> /* ARPHRD_ETHER */
+#include <net/lib80211.h>
#define MAX_PRECMD_CNT 16
#define MAX_RFDEPENDCMD_CNT 16
@@ -870,69 +871,6 @@ enum _REG_PREAMBLE_MODE {
#define WLAN_ERP_USE_PROTECTION (1<<1)
#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
-/* Status codes */
-enum rtllib_statuscode {
- WLAN_STATUS_SUCCESS = 0,
- WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
- WLAN_STATUS_CAPS_UNSUPPORTED = 10,
- WLAN_STATUS_REASSOC_NO_ASSOC = 11,
- WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
- WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
- WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
- WLAN_STATUS_CHALLENGE_FAIL = 15,
- WLAN_STATUS_AUTH_TIMEOUT = 16,
- WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
- WLAN_STATUS_ASSOC_DENIED_RATES = 18,
- /* 802.11b */
- WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
- WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
- WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
- /* 802.11h */
- WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
- WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
- WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
- /* 802.11g */
- WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
- WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
- /* 802.11i */
- WLAN_STATUS_INVALID_IE = 40,
- WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
- WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
- WLAN_STATUS_INVALID_AKMP = 43,
- WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
- WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
- WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
-};
-
-/* Reason codes */
-enum rtllib_reasoncode {
- WLAN_REASON_UNSPECIFIED = 1,
- WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
- WLAN_REASON_DEAUTH_LEAVING = 3,
- WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
- WLAN_REASON_DISASSOC_AP_BUSY = 5,
- WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
- WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
- WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
- WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
- /* 802.11h */
- WLAN_REASON_DISASSOC_BAD_POWER = 10,
- WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
- /* 802.11i */
- WLAN_REASON_INVALID_IE = 13,
- WLAN_REASON_MIC_FAILURE = 14,
- WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
- WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
- WLAN_REASON_IE_DIFFERENT = 17,
- WLAN_REASON_INVALID_GROUP_CIPHER = 18,
- WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
- WLAN_REASON_INVALID_AKMP = 20,
- WLAN_REASON_UNSUPP_RSN_VERSION = 21,
- WLAN_REASON_INVALID_RSN_IE_CAP = 22,
- WLAN_REASON_IEEE8021X_FAILED = 23,
- WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
-};
-
#define RTLLIB_STATMASK_SIGNAL (1<<0)
#define RTLLIB_STATMASK_RSSI (1<<1)
#define RTLLIB_STATMASK_NOISE (1<<2)
@@ -1122,8 +1060,6 @@ struct rtllib_stats {
struct rtllib_device;
-#include "rtllib_crypt.h"
-
#define SEC_KEY_1 (1<<0)
#define SEC_KEY_2 (1<<1)
#define SEC_KEY_3 (1<<2)
@@ -1146,7 +1082,6 @@ struct rtllib_device;
#define SEC_ALG_TKIP 2
#define SEC_ALG_CCMP 4
-#define WEP_KEYS 4
#define WEP_KEY_LEN 13
#define SCM_KEY_LEN 32
#define SCM_TEMPORAL_KEY_LENGTH 16
@@ -1158,8 +1093,8 @@ struct rtllib_security {
auth_algo:4,
unicast_uses_group:1,
encrypt:1;
- u8 key_sizes[WEP_KEYS];
- u8 keys[WEP_KEYS][SCM_KEY_LEN];
+ u8 key_sizes[NUM_WEP_KEYS];
+ u8 keys[NUM_WEP_KEYS][SCM_KEY_LEN];
u8 level;
u16 flags;
} __packed;
@@ -2251,14 +2186,10 @@ struct rtllib_device {
u8 ap_mac_addr[6];
u16 pairwise_key_type;
u16 group_key_type;
- struct list_head crypt_deinit_list;
- struct rtllib_crypt_data *crypt[WEP_KEYS];
- int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
- struct sw_cam_table swcamtable[TOTAL_CAM_ENTRY];
- struct timer_list crypt_deinit_timer;
- int crypt_quiesced;
+ struct lib80211_crypt_info crypt_info;
+ struct sw_cam_table swcamtable[TOTAL_CAM_ENTRY];
int bcrx_sta_key; /* use individual keys to override default keys even
* with RX of broad/multicast frames */
@@ -2774,7 +2705,7 @@ extern void rtllib_rx_mgt(struct rtllib_device *ieee,
struct rtllib_rx_stats *stats);
extern void rtllib_rx_probe_rq(struct rtllib_device *ieee,
struct sk_buff *skb);
-extern int IsLegalChannel(struct rtllib_device *rtllib, u8 channel);
+extern int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel);
/* rtllib_wx.c */
extern int rtllib_wx_get_scan(struct rtllib_device *ieee,
@@ -2804,7 +2735,7 @@ extern int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len);
/* rtllib_softmac.c */
extern short rtllib_is_54g(struct rtllib_network *net);
-extern short rtllib_is_shortslot(struct rtllib_network net);
+extern short rtllib_is_shortslot(const struct rtllib_network *net);
extern int rtllib_rx_frame_softmac(struct rtllib_device *ieee,
struct sk_buff *skb,
struct rtllib_rx_stats *rx_stats, u16 type,
@@ -2971,8 +2902,8 @@ extern void HTInitializeHTInfo(struct rtllib_device *ieee);
extern void HTInitializeBssDesc(struct bss_ht *pBssHT);
extern void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee,
struct rtllib_network *pNetwork);
-extern void HTUpdateSelfAndPeerSetting(struct rtllib_device *ieee,
- struct rtllib_network *pNetwork);
+extern void HT_update_self_and_peer_setting(struct rtllib_device *ieee,
+ struct rtllib_network *pNetwork);
extern u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
u8 *pMCSFilter);
extern u8 MCS_FILTER_ALL[];
@@ -3052,21 +2983,6 @@ static inline const char *escape_essid(const char *essid, u8 essid_len)
(HTMcsToDataRate(_ieee, (u8)_MGN_RATE)))
/* fun with the built-in rtllib stack... */
-int rtllib_init(void);
-void rtllib_exit(void);
-int rtllib_crypto_init(void);
-void rtllib_crypto_deinit(void);
-int rtllib_crypto_tkip_init(void);
-void rtllib_crypto_tkip_exit(void);
-int rtllib_crypto_ccmp_init(void);
-void rtllib_crypto_ccmp_exit(void);
-int rtllib_crypto_wep_init(void);
-void rtllib_crypto_wep_exit(void);
-
-void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib);
-void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib, u8 *asSta,
- u8 asRsn);
-void rtllib_MgntDisconnectAP(struct rtllib_device *rtllib, u8 asRsn);
bool rtllib_MgntDisconnect(struct rtllib_device *rtllib, u8 asRsn);
@@ -3133,12 +3049,5 @@ extern void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p);
#define MUTEX_LOCK_PRIV(pmutex) mutex_lock(pmutex)
#define MUTEX_UNLOCK_PRIV(pmutex) mutex_unlock(pmutex)
#endif
-static inline void dump_buf(u8 *buf, u32 len)
-{
- u32 i;
- printk(KERN_INFO "-----------------Len %d----------------\n", len);
- for (i = 0; i < len; i++)
- printk("%2.2x-", *(buf+i));
- printk("\n");
-}
+
#endif /* RTLLIB_H */
diff --git a/drivers/staging/rtl8192e/rtllib_crypt.c b/drivers/staging/rtl8192e/rtllib_crypt.c
index acda37b81848..86152d0e6b5d 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt.c
+++ b/drivers/staging/rtl8192e/rtllib_crypt.c
@@ -11,7 +11,6 @@
*
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -22,7 +21,7 @@
struct rtllib_crypto_alg {
struct list_head list;
- struct rtllib_crypto_ops *ops;
+ struct lib80211_crypto_ops *ops;
};
@@ -33,15 +32,15 @@ struct rtllib_crypto {
static struct rtllib_crypto *hcrypt;
-void rtllib_crypt_deinit_entries(struct rtllib_device *ieee,
+void rtllib_crypt_deinit_entries(struct lib80211_crypt_info *info,
int force)
{
struct list_head *ptr, *n;
- struct rtllib_crypt_data *entry;
+ struct lib80211_crypt_data *entry;
- for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
- ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
- entry = list_entry(ptr, struct rtllib_crypt_data, list);
+ for (ptr = info->crypt_deinit_list.next, n = ptr->next;
+ ptr != &info->crypt_deinit_list; ptr = n, n = ptr->next) {
+ entry = list_entry(ptr, struct lib80211_crypt_data, list);
if (atomic_read(&entry->refcnt) != 0 && !force)
continue;
@@ -53,28 +52,30 @@ void rtllib_crypt_deinit_entries(struct rtllib_device *ieee,
kfree(entry);
}
}
+EXPORT_SYMBOL(rtllib_crypt_deinit_entries);
void rtllib_crypt_deinit_handler(unsigned long data)
{
- struct rtllib_device *ieee = (struct rtllib_device *)data;
+ struct lib80211_crypt_info *info = (struct lib80211_crypt_info *)data;
unsigned long flags;
- spin_lock_irqsave(&ieee->lock, flags);
- rtllib_crypt_deinit_entries(ieee, 0);
- if (!list_empty(&ieee->crypt_deinit_list)) {
+ spin_lock_irqsave(info->lock, flags);
+ rtllib_crypt_deinit_entries(info, 0);
+ if (!list_empty(&info->crypt_deinit_list)) {
printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
- "deletion list\n", ieee->dev->name);
- ieee->crypt_deinit_timer.expires = jiffies + HZ;
- add_timer(&ieee->crypt_deinit_timer);
+ "deletion list\n", info->name);
+ info->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&info->crypt_deinit_timer);
}
- spin_unlock_irqrestore(&ieee->lock, flags);
+ spin_unlock_irqrestore(info->lock, flags);
}
+EXPORT_SYMBOL(rtllib_crypt_deinit_handler);
-void rtllib_crypt_delayed_deinit(struct rtllib_device *ieee,
- struct rtllib_crypt_data **crypt)
+void rtllib_crypt_delayed_deinit(struct lib80211_crypt_info *info,
+ struct lib80211_crypt_data **crypt)
{
- struct rtllib_crypt_data *tmp;
+ struct lib80211_crypt_data *tmp;
unsigned long flags;
if (*crypt == NULL)
@@ -87,16 +88,17 @@ void rtllib_crypt_delayed_deinit(struct rtllib_device *ieee,
* decrypt operations. Use a list of delayed deinits to avoid needing
* locking. */
- spin_lock_irqsave(&ieee->lock, flags);
- list_add(&tmp->list, &ieee->crypt_deinit_list);
- if (!timer_pending(&ieee->crypt_deinit_timer)) {
- ieee->crypt_deinit_timer.expires = jiffies + HZ;
- add_timer(&ieee->crypt_deinit_timer);
+ spin_lock_irqsave(info->lock, flags);
+ list_add(&tmp->list, &info->crypt_deinit_list);
+ if (!timer_pending(&info->crypt_deinit_timer)) {
+ info->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&info->crypt_deinit_timer);
}
- spin_unlock_irqrestore(&ieee->lock, flags);
+ spin_unlock_irqrestore(info->lock, flags);
}
+EXPORT_SYMBOL(rtllib_crypt_delayed_deinit);
-int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops)
+int rtllib_register_crypto_ops(struct lib80211_crypto_ops *ops)
{
unsigned long flags;
struct rtllib_crypto_alg *alg;
@@ -104,11 +106,10 @@ int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops)
if (hcrypt == NULL)
return -1;
- alg = kmalloc(sizeof(*alg), GFP_KERNEL);
+ alg = kzalloc(sizeof(*alg), GFP_KERNEL);
if (alg == NULL)
return -ENOMEM;
- memset(alg, 0, sizeof(*alg));
alg->ops = ops;
spin_lock_irqsave(&hcrypt->lock, flags);
@@ -120,8 +121,9 @@ int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops)
return 0;
}
+EXPORT_SYMBOL(rtllib_register_crypto_ops);
-int rtllib_unregister_crypto_ops(struct rtllib_crypto_ops *ops)
+int rtllib_unregister_crypto_ops(struct lib80211_crypto_ops *ops)
{
unsigned long flags;
struct list_head *ptr;
@@ -150,9 +152,10 @@ int rtllib_unregister_crypto_ops(struct rtllib_crypto_ops *ops)
return del_alg ? 0 : -1;
}
+EXPORT_SYMBOL(rtllib_unregister_crypto_ops);
-struct rtllib_crypto_ops *rtllib_get_crypto_ops(const char *name)
+struct lib80211_crypto_ops *rtllib_get_crypto_ops(const char *name)
{
unsigned long flags;
struct list_head *ptr;
@@ -177,12 +180,13 @@ struct rtllib_crypto_ops *rtllib_get_crypto_ops(const char *name)
else
return NULL;
}
+EXPORT_SYMBOL(rtllib_get_crypto_ops);
static void * rtllib_crypt_null_init(int keyidx) { return (void *) 1; }
static void rtllib_crypt_null_deinit(void *priv) {}
-static struct rtllib_crypto_ops rtllib_crypt_null = {
+static struct lib80211_crypto_ops rtllib_crypt_null = {
.name = "NULL",
.init = rtllib_crypt_null_init,
.deinit = rtllib_crypt_null_deinit,
@@ -192,8 +196,10 @@ static struct rtllib_crypto_ops rtllib_crypt_null = {
.decrypt_msdu = NULL,
.set_key = NULL,
.get_key = NULL,
- .extra_prefix_len = 0,
- .extra_postfix_len = 0,
+ .extra_mpdu_prefix_len = 0,
+ .extra_mpdu_postfix_len = 0,
+ .extra_msdu_prefix_len = 0,
+ .extra_msdu_postfix_len = 0,
.owner = THIS_MODULE,
};
@@ -202,15 +208,14 @@ int __init rtllib_crypto_init(void)
{
int ret = -ENOMEM;
- hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL);
+ hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
if (!hcrypt)
goto out;
- memset(hcrypt, 0, sizeof(*hcrypt));
INIT_LIST_HEAD(&hcrypt->algs);
spin_lock_init(&hcrypt->lock);
- ret = rtllib_register_crypto_ops(&rtllib_crypt_null);
+ ret = lib80211_register_crypto_ops(&rtllib_crypt_null);
if (ret < 0) {
kfree(hcrypt);
hcrypt = NULL;
@@ -239,3 +244,8 @@ void __exit rtllib_crypto_deinit(void)
kfree(hcrypt);
}
+
+module_init(rtllib_crypto_init);
+module_exit(rtllib_crypto_deinit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_crypt.h b/drivers/staging/rtl8192e/rtllib_crypt.h
index 49b90b73ed9c..e177c9287b44 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt.h
+++ b/drivers/staging/rtl8192e/rtllib_crypt.h
@@ -25,61 +25,11 @@
#include <linux/skbuff.h>
-struct rtllib_crypto_ops {
- const char *name;
-
- /* init new crypto context (e.g., allocate private data space,
- * select IV, etc.); returns NULL on failure or pointer to allocated
- * private data on success */
- void * (*init)(int keyidx);
-
- /* deinitialize crypto context and free allocated private data */
- void (*deinit)(void *priv);
-
- /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
- * value from decrypt_mpdu is passed as the keyidx value for
- * decrypt_msdu. skb must have enough head and tail room for the
- * encryption; if not, error will be returned; these functions are
- * called for all MPDUs (i.e., fragments).
- */
- int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
- int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-
- /* These functions are called for full MSDUs, i.e. full frames.
- * These can be NULL if full MSDU operations are not needed. */
- int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
- int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
- void *priv, struct rtllib_device* ieee);
-
- int (*set_key)(void *key, int len, u8 *seq, void *priv);
- int (*get_key)(void *key, int len, u8 *seq, void *priv);
-
- /* procfs handler for printing out key information and possible
- * statistics */
- char * (*print_stats)(char *p, void *priv);
-
- /* maximum number of bytes added by encryption; encrypt buf is
- * allocated with extra_prefix_len bytes, copy of in_buf, and
- * extra_postfix_len; encrypt need not use all this space, but
- * the result must start at the beginning of the struct buffer and
- * correct length must be returned */
- int extra_prefix_len, extra_postfix_len;
-
- struct module *owner;
-};
-
-struct rtllib_crypt_data {
- struct list_head list; /* delayed deletion list */
- struct rtllib_crypto_ops *ops;
- void *priv;
- atomic_t refcnt;
-};
-
-int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops);
-int rtllib_unregister_crypto_ops(struct rtllib_crypto_ops *ops);
-struct rtllib_crypto_ops *rtllib_get_crypto_ops(const char *name);
-void rtllib_crypt_deinit_entries(struct rtllib_device *, int);
-void rtllib_crypt_deinit_handler(unsigned long);
-void rtllib_crypt_delayed_deinit(struct rtllib_device *ieee,
- struct rtllib_crypt_data **crypt);
+int rtllib_register_crypto_ops(struct lib80211_crypto_ops *ops);
+int rtllib_unregister_crypto_ops(struct lib80211_crypto_ops *ops);
+struct lib80211_crypto_ops *rtllib_get_crypto_ops(const char *name);
+void rtllib_crypt_deinit_entries(struct lib80211_crypt_info *info, int force);
+void rtllib_crypt_deinit_handler(unsigned long data);
+void rtllib_crypt_delayed_deinit(struct lib80211_crypt_info *info,
+ struct lib80211_crypt_data **crypt);
#endif
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
index 6196b9aa3a09..4217b88e6fc3 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
+++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
@@ -9,7 +9,6 @@
* more details.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -63,10 +62,9 @@ static void *rtllib_ccmp_init(int key_idx)
{
struct rtllib_ccmp_data *priv;
- priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+ priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
- memset(priv, 0, sizeof(*priv));
priv->key_idx = key_idx;
priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
@@ -429,13 +427,8 @@ static char *rtllib_ccmp_print_stats(char *p, void *priv)
return p;
}
-void rtllib_ccmp_null(void)
-{
- return;
-}
-
-static struct rtllib_crypto_ops rtllib_crypt_ccmp = {
- .name = "CCMP",
+static struct lib80211_crypto_ops rtllib_crypt_ccmp = {
+ .name = "R-CCMP",
.init = rtllib_ccmp_init,
.deinit = rtllib_ccmp_deinit,
.encrypt_mpdu = rtllib_ccmp_encrypt,
@@ -445,19 +438,24 @@ static struct rtllib_crypto_ops rtllib_crypt_ccmp = {
.set_key = rtllib_ccmp_set_key,
.get_key = rtllib_ccmp_get_key,
.print_stats = rtllib_ccmp_print_stats,
- .extra_prefix_len = CCMP_HDR_LEN,
- .extra_postfix_len = CCMP_MIC_LEN,
+ .extra_mpdu_prefix_len = CCMP_HDR_LEN,
+ .extra_mpdu_postfix_len = CCMP_MIC_LEN,
.owner = THIS_MODULE,
};
int __init rtllib_crypto_ccmp_init(void)
{
- return rtllib_register_crypto_ops(&rtllib_crypt_ccmp);
+ return lib80211_register_crypto_ops(&rtllib_crypt_ccmp);
}
void __exit rtllib_crypto_ccmp_exit(void)
{
- rtllib_unregister_crypto_ops(&rtllib_crypt_ccmp);
+ lib80211_unregister_crypto_ops(&rtllib_crypt_ccmp);
}
+
+module_init(rtllib_crypto_ccmp_init);
+module_exit(rtllib_crypto_ccmp_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
index 6a0c87886422..800925053fb0 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
+++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
@@ -9,7 +9,6 @@
* more details.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -60,10 +59,9 @@ static void *rtllib_tkip_init(int key_idx)
{
struct rtllib_tkip_data *priv;
- priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+ priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
- memset(priv, 0, sizeof(*priv));
priv->key_idx = key_idx;
priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
CRYPTO_ALG_ASYNC);
@@ -598,8 +596,7 @@ static void rtllib_michael_mic_failure(struct net_device *dev,
}
static int rtllib_michael_mic_verify(struct sk_buff *skb, int keyidx,
- int hdr_len, void *priv,
- struct rtllib_device *ieee)
+ int hdr_len, void *priv)
{
struct rtllib_tkip_data *tkey = priv;
u8 mic[8];
@@ -618,23 +615,20 @@ static int rtllib_michael_mic_verify(struct sk_buff *skb, int keyidx,
skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
return -1;
- if ((memcmp(mic, skb->data + skb->len - 8, 8) != 0) ||
- (ieee->force_mic_error)) {
+ if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
struct rtllib_hdr_4addr *hdr;
hdr = (struct rtllib_hdr_4addr *) skb->data;
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
"MSDU from %pM keyidx=%d\n",
skb->dev ? skb->dev->name : "N/A", hdr->addr2,
keyidx);
- printk(KERN_DEBUG "%d, force_mic_error = %d\n",
- (memcmp(mic, skb->data + skb->len - 8, 8) != 0),\
- ieee->force_mic_error);
+ printk(KERN_DEBUG "%d\n",
+ memcmp(mic, skb->data + skb->len - 8, 8) != 0);
if (skb->dev) {
printk(KERN_INFO "skb->dev != NULL\n");
rtllib_michael_mic_failure(skb->dev, hdr, keyidx);
}
tkey->dot11RSNAStatsTKIPLocalMICFailures++;
- ieee->force_mic_error = false;
return -1;
}
@@ -740,9 +734,8 @@ static char *rtllib_tkip_print_stats(char *p, void *priv)
return p;
}
-
-static struct rtllib_crypto_ops rtllib_crypt_tkip = {
- .name = "TKIP",
+static struct lib80211_crypto_ops rtllib_crypt_tkip = {
+ .name = "R-TKIP",
.init = rtllib_tkip_init,
.deinit = rtllib_tkip_deinit,
.encrypt_mpdu = rtllib_tkip_encrypt,
@@ -752,24 +745,25 @@ static struct rtllib_crypto_ops rtllib_crypt_tkip = {
.set_key = rtllib_tkip_set_key,
.get_key = rtllib_tkip_get_key,
.print_stats = rtllib_tkip_print_stats,
- .extra_prefix_len = 4 + 4, /* IV + ExtIV */
- .extra_postfix_len = 8 + 4, /* MIC + ICV */
+ .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
+ .extra_mpdu_postfix_len = 4, /* ICV */
+ .extra_msdu_postfix_len = 8, /* MIC */
.owner = THIS_MODULE,
};
int __init rtllib_crypto_tkip_init(void)
{
- return rtllib_register_crypto_ops(&rtllib_crypt_tkip);
+ return lib80211_register_crypto_ops(&rtllib_crypt_tkip);
}
void __exit rtllib_crypto_tkip_exit(void)
{
- rtllib_unregister_crypto_ops(&rtllib_crypt_tkip);
+ lib80211_unregister_crypto_ops(&rtllib_crypt_tkip);
}
-void rtllib_tkip_null(void)
-{
- return;
-}
+module_init(rtllib_crypto_tkip_init);
+module_exit(rtllib_crypto_tkip_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_wep.c b/drivers/staging/rtl8192e/rtllib_crypt_wep.c
index c59bf10fe780..8cdf38913a33 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt_wep.c
+++ b/drivers/staging/rtl8192e/rtllib_crypt_wep.c
@@ -9,7 +9,6 @@
* more details.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -38,10 +37,9 @@ static void *prism2_wep_init(int keyidx)
{
struct prism2_wep_data *priv;
- priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+ priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
- memset(priv, 0, sizeof(*priv));
priv->key_idx = keyidx;
priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
@@ -257,9 +255,8 @@ static char *prism2_wep_print_stats(char *p, void *priv)
return p;
}
-
-static struct rtllib_crypto_ops rtllib_crypt_wep = {
- .name = "WEP",
+static struct lib80211_crypto_ops rtllib_crypt_wep = {
+ .name = "R-WEP",
.init = prism2_wep_init,
.deinit = prism2_wep_deinit,
.encrypt_mpdu = prism2_wep_encrypt,
@@ -269,24 +266,24 @@ static struct rtllib_crypto_ops rtllib_crypt_wep = {
.set_key = prism2_wep_set_key,
.get_key = prism2_wep_get_key,
.print_stats = prism2_wep_print_stats,
- .extra_prefix_len = 4, /* IV */
- .extra_postfix_len = 4, /* ICV */
+ .extra_mpdu_prefix_len = 4, /* IV */
+ .extra_mpdu_postfix_len = 4, /* ICV */
.owner = THIS_MODULE,
};
int __init rtllib_crypto_wep_init(void)
{
- return rtllib_register_crypto_ops(&rtllib_crypt_wep);
+ return lib80211_register_crypto_ops(&rtllib_crypt_wep);
}
void __exit rtllib_crypto_wep_exit(void)
{
- rtllib_unregister_crypto_ops(&rtllib_crypt_wep);
+ lib80211_unregister_crypto_ops(&rtllib_crypt_wep);
}
-void rtllib_wep_null(void)
-{
- return;
-}
+module_init(rtllib_crypto_wep_init);
+module_exit(rtllib_crypto_wep_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_debug.h b/drivers/staging/rtl8192e/rtllib_debug.h
new file mode 100644
index 000000000000..2bfc1155f505
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_debug.h
@@ -0,0 +1,86 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL_DEBUG_H
+#define _RTL_DEBUG_H
+
+/* Allow files to override DRV_NAME */
+#ifndef DRV_NAME
+#define DRV_NAME "rtllib_92e"
+#endif
+
+#define DMESG(x, a...)
+
+extern u32 rt_global_debug_component;
+
+/* These are the defines for rt_global_debug_component */
+enum RTL_DEBUG {
+ COMP_TRACE = (1 << 0),
+ COMP_DBG = (1 << 1),
+ COMP_INIT = (1 << 2),
+ COMP_RECV = (1 << 3),
+ COMP_SEND = (1 << 4),
+ COMP_CMD = (1 << 5),
+ COMP_POWER = (1 << 6),
+ COMP_EPROM = (1 << 7),
+ COMP_SWBW = (1 << 8),
+ COMP_SEC = (1 << 9),
+ COMP_LPS = (1 << 10),
+ COMP_QOS = (1 << 11),
+ COMP_RATE = (1 << 12),
+ COMP_RXDESC = (1 << 13),
+ COMP_PHY = (1 << 14),
+ COMP_DIG = (1 << 15),
+ COMP_TXAGC = (1 << 16),
+ COMP_HALDM = (1 << 17),
+ COMP_POWER_TRACKING = (1 << 18),
+ COMP_CH = (1 << 19),
+ COMP_RF = (1 << 20),
+ COMP_FIRMWARE = (1 << 21),
+ COMP_HT = (1 << 22),
+ COMP_RESET = (1 << 23),
+ COMP_CMDPKT = (1 << 24),
+ COMP_SCAN = (1 << 25),
+ COMP_PS = (1 << 26),
+ COMP_DOWN = (1 << 27),
+ COMP_INTR = (1 << 28),
+ COMP_LED = (1 << 29),
+ COMP_MLME = (1 << 30),
+ COMP_ERR = (1 << 31)
+};
+
+#define RT_TRACE(component, x, args...) \
+do { \
+ if (rt_global_debug_component & component) \
+ printk(KERN_DEBUG DRV_NAME ":" x "\n" , \
+ ##args);\
+} while (0);
+
+#define assert(expr) \
+ if (!(expr)) { \
+ printk(KERN_INFO "Assertion failed! %s,%s,%s,line=%d\n", \
+ #expr, __FILE__, __func__, __LINE__); \
+ }
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c
index c36a140a4568..f9dae958a5d4 100644
--- a/drivers/staging/rtl8192e/rtllib_module.c
+++ b/drivers/staging/rtl8192e/rtllib_module.c
@@ -45,7 +45,6 @@
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
-#include <linux/version.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <linux/uaccess.h>
@@ -54,7 +53,9 @@
#include "rtllib.h"
-#define DRV_NAME "rtllib_92e"
+u32 rt_global_debug_component = COMP_ERR;
+EXPORT_SYMBOL(rt_global_debug_component);
+
void _setup_timer(struct timer_list *ptimer, void *fun, unsigned long data)
{
@@ -135,10 +136,6 @@ struct net_device *alloc_rtllib(int sizeof_priv)
ieee->host_decrypt = 1;
ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
- INIT_LIST_HEAD(&ieee->crypt_deinit_list);
- _setup_timer(&ieee->crypt_deinit_timer,
- rtllib_crypt_deinit_handler,
- (unsigned long) ieee);
ieee->rtllib_ap_sec_type = rtllib_ap_sec_type;
spin_lock_init(&ieee->lock);
@@ -148,6 +145,9 @@ struct net_device *alloc_rtllib(int sizeof_priv)
atomic_set(&(ieee->atm_chnlop), 0);
atomic_set(&(ieee->atm_swbw), 0);
+ /* SAM FIXME */
+ lib80211_crypt_info_init(&ieee->crypt_info, "RTLLIB", &ieee->lock);
+
ieee->bHalfNMode = false;
ieee->wpa_enabled = 0;
ieee->tkip_countermeasures = 0;
@@ -177,10 +177,6 @@ struct net_device *alloc_rtllib(int sizeof_priv)
ieee->last_packet_time[i] = 0;
}
- rtllib_tkip_null();
- rtllib_wep_null();
- rtllib_ccmp_null();
-
return dev;
failed:
@@ -188,32 +184,23 @@ struct net_device *alloc_rtllib(int sizeof_priv)
free_netdev(dev);
return NULL;
}
+EXPORT_SYMBOL(alloc_rtllib);
void free_rtllib(struct net_device *dev)
{
struct rtllib_device *ieee = (struct rtllib_device *)
netdev_priv_rsl(dev);
- int i;
kfree(ieee->pHTInfo);
ieee->pHTInfo = NULL;
rtllib_softmac_free(ieee);
- del_timer_sync(&ieee->crypt_deinit_timer);
- rtllib_crypt_deinit_entries(ieee, 1);
-
- for (i = 0; i < WEP_KEYS; i++) {
- struct rtllib_crypt_data *crypt = ieee->crypt[i];
- if (crypt) {
- if (crypt->ops)
- crypt->ops->deinit(crypt->priv);
- kfree(crypt);
- ieee->crypt[i] = NULL;
- }
- }
+
+ lib80211_crypt_info_free(&ieee->crypt_info);
rtllib_networks_free(ieee);
free_netdev(dev);
}
+EXPORT_SYMBOL(free_rtllib);
u32 rtllib_debug_level;
static int debug = \
@@ -287,3 +274,8 @@ void __exit rtllib_exit(void)
rtllib_proc = NULL;
}
}
+
+module_init(rtllib_init);
+module_exit(rtllib_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index 8d0af5ed8ecf..6c5061f12bad 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -36,7 +36,6 @@
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
-#include <linux/version.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <linux/uaccess.h>
@@ -281,7 +280,7 @@ static int rtllib_is_eapol_frame(struct rtllib_device *ieee,
/* Called only as a tasklet (software IRQ), by rtllib_rx */
static inline int
rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
- struct rtllib_crypt_data *crypt)
+ struct lib80211_crypt_data *crypt)
{
struct rtllib_hdr_4addr *hdr;
int res, hdrlen;
@@ -322,7 +321,7 @@ rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
/* Called only as a tasklet (software IRQ), by rtllib_rx */
static inline int
rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb,
- int keyidx, struct rtllib_crypt_data *crypt)
+ int keyidx, struct lib80211_crypt_data *crypt)
{
struct rtllib_hdr_4addr *hdr;
int res, hdrlen;
@@ -341,7 +340,7 @@ rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb,
hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
atomic_inc(&crypt->refcnt);
- res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv, ieee);
+ res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
atomic_dec(&crypt->refcnt);
if (res < 0) {
printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
@@ -1010,7 +1009,7 @@ static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc,
}
static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb,
- struct rtllib_crypt_data **crypt, size_t hdrlen)
+ struct lib80211_crypt_data **crypt, size_t hdrlen)
{
struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
u16 fc = le16_to_cpu(hdr->frame_ctl);
@@ -1020,7 +1019,7 @@ static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb,
if (skb->len >= hdrlen + 3)
idx = skb->data[hdrlen + 3] >> 6;
- *crypt = ieee->crypt[idx];
+ *crypt = ieee->crypt_info.crypt[idx];
/* allow NULL decrypt to indicate an station specific override
* for default encryption */
if (*crypt && ((*crypt)->ops == NULL ||
@@ -1045,7 +1044,7 @@ static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb,
static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
struct rtllib_rx_stats *rx_stats,
- struct rtllib_crypt_data *crypt, size_t hdrlen)
+ struct lib80211_crypt_data *crypt, size_t hdrlen)
{
struct rtllib_hdr_4addr *hdr;
int keyidx = 0;
@@ -1253,7 +1252,7 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
{
struct net_device *dev = ieee->dev;
struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
- struct rtllib_crypt_data *crypt = NULL;
+ struct lib80211_crypt_data *crypt = NULL;
struct rtllib_rxb *rxb = NULL;
struct rx_ts_record *pTS = NULL;
u16 fc, sc, SeqNum = 0;
@@ -1497,6 +1496,7 @@ int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
ieee->stats.rx_dropped++;
return 0;
}
+EXPORT_SYMBOL(rtllib_rx);
static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
@@ -2492,7 +2492,7 @@ static int IsPassiveChannel(struct rtllib_device *rtllib, u8 channel)
return 0;
}
-int IsLegalChannel(struct rtllib_device *rtllib, u8 channel)
+int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel)
{
if (MAX_CHANNEL_NUMBER < channel) {
printk(KERN_INFO "%s(): Invalid Channel\n", __func__);
@@ -2503,6 +2503,7 @@ int IsLegalChannel(struct rtllib_device *rtllib, u8 channel)
return 0;
}
+EXPORT_SYMBOL(rtllib_legal_channel);
static inline void rtllib_process_probe_response(
struct rtllib_device *ieee,
@@ -2553,7 +2554,7 @@ static inline void rtllib_process_probe_response(
}
- if (!IsLegalChannel(ieee, network->channel))
+ if (!rtllib_legal_channel(ieee, network->channel))
goto free_network;
if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
index b5086850f0de..1637f1110991 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -15,11 +15,9 @@
#include "rtllib.h"
-#include "rtl_core.h"
#include <linux/random.h>
#include <linux/delay.h>
-#include <linux/version.h>
#include <linux/uaccess.h>
#include "dot11d.h"
@@ -28,9 +26,9 @@ short rtllib_is_54g(struct rtllib_network *net)
return (net->rates_ex_len > 0) || (net->rates_len > 4);
}
-short rtllib_is_shortslot(struct rtllib_network net)
+short rtllib_is_shortslot(const struct rtllib_network *net)
{
- return net.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME;
+ return net->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME;
}
/* returns the total length needed for pleacing the RATE MFIE
@@ -468,6 +466,7 @@ void rtllib_EnableIntelPromiscuousMode(struct net_device *dev,
ieee->bNetPromiscuousMode = true;
}
+EXPORT_SYMBOL(rtllib_EnableIntelPromiscuousMode);
/*
@@ -490,6 +489,7 @@ void rtllib_DisableIntelPromiscuousMode(struct net_device *dev,
ieee->bNetPromiscuousMode = false;
}
+EXPORT_SYMBOL(rtllib_DisableIntelPromiscuousMode);
static void rtllib_send_probe(struct rtllib_device *ieee, u8 is_mesh)
{
@@ -685,6 +685,7 @@ void rtllib_stop_send_beacons(struct rtllib_device *ieee)
if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
rtllib_beacons_stop(ieee);
}
+EXPORT_SYMBOL(rtllib_stop_send_beacons);
void rtllib_start_send_beacons(struct rtllib_device *ieee)
@@ -694,6 +695,7 @@ void rtllib_start_send_beacons(struct rtllib_device *ieee)
if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
rtllib_beacons_start(ieee);
}
+EXPORT_SYMBOL(rtllib_start_send_beacons);
static void rtllib_softmac_stop_scan(struct rtllib_device *ieee)
@@ -719,6 +721,7 @@ void rtllib_stop_scan(struct rtllib_device *ieee)
ieee->rtllib_stop_hw_scan(ieee->dev);
}
}
+EXPORT_SYMBOL(rtllib_stop_scan);
void rtllib_stop_scan_syncro(struct rtllib_device *ieee)
{
@@ -729,6 +732,7 @@ void rtllib_stop_scan_syncro(struct rtllib_device *ieee)
ieee->rtllib_stop_hw_scan(ieee->dev);
}
}
+EXPORT_SYMBOL(rtllib_stop_scan_syncro);
bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan)
{
@@ -741,6 +745,7 @@ bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan)
return test_bit(STATUS_SCANNING, &ieee->status);
}
}
+EXPORT_SYMBOL(rtllib_act_scanning);
/* called with ieee->lock held */
static void rtllib_start_scan(struct rtllib_device *ieee)
@@ -781,6 +786,7 @@ void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
ieee->rtllib_start_hw_scan(ieee->dev);
}
}
+EXPORT_SYMBOL(rtllib_start_scan_syncro);
inline struct sk_buff *rtllib_authentication_req(struct rtllib_network *beacon,
struct rtllib_device *ieee, int challengelen, u8 *daddr)
@@ -830,7 +836,7 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, u8 *dest)
struct sk_buff *skb = NULL;
int encrypt;
int atim_len, erp_len;
- struct rtllib_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
char *ssid = ieee->current_network.ssid;
int ssid_len = ieee->current_network.ssid_len;
@@ -865,9 +871,9 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, u8 *dest)
} else
erp_len = 0;
- crypt = ieee->crypt[ieee->tx_keyidx];
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
encrypt = ieee->host_encrypt && crypt && crypt->ops &&
- ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
+ ((0 == strcmp(crypt->ops->name, "R-WEP") || wpa_ie_len));
if (ieee->pHTInfo->bCurrentHTSupport) {
tmp_ht_cap_buf = (u8 *) &(ieee->pHTInfo->SelfHTCap);
tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
@@ -917,7 +923,7 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, u8 *dest)
cpu_to_le16((beacon_buf->capability |=
WLAN_CAPABILITY_SHORT_SLOT_TIME));
- crypt = ieee->crypt[ieee->tx_keyidx];
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
if (encrypt)
beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
@@ -976,7 +982,7 @@ static struct sk_buff *rtllib_assoc_resp(struct rtllib_device *ieee, u8 *dest)
struct sk_buff *skb;
u8 *tag;
- struct rtllib_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
struct rtllib_assoc_response_frame *assoc;
short encrypt;
@@ -1007,7 +1013,7 @@ static struct sk_buff *rtllib_assoc_resp(struct rtllib_device *ieee, u8 *dest)
cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
if (ieee->host_encrypt)
- crypt = ieee->crypt[ieee->tx_keyidx];
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
else
crypt = NULL;
@@ -1172,7 +1178,7 @@ inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon,
unsigned int ckip_ie_len = 0;
unsigned int ccxrm_ie_len = 0;
unsigned int cxvernum_ie_len = 0;
- struct rtllib_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
int encrypt;
int PMKCacheIdx;
@@ -1185,10 +1191,10 @@ inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon,
unsigned int turbo_info_len = beacon->Turbo_Enable ? 9 : 0;
int len = 0;
- crypt = ieee->crypt[ieee->tx_keyidx];
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
if (crypt != NULL)
encrypt = ieee->host_encrypt && crypt && crypt->ops &&
- ((0 == strcmp(crypt->ops->name, "WEP") ||
+ ((0 == strcmp(crypt->ops->name, "R-WEP") ||
wpa_ie_len));
else
encrypt = 0;
@@ -1956,6 +1962,7 @@ void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr)
if (buf)
softmac_ps_mgmt_xmit(buf, ieee);
}
+EXPORT_SYMBOL(rtllib_sta_ps_send_null_frame);
void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee)
{
@@ -2168,6 +2175,7 @@ void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success)
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
+EXPORT_SYMBOL(rtllib_ps_tx_ack);
static void rtllib_process_action(struct rtllib_device *ieee, struct sk_buff *skb)
{
@@ -2540,6 +2548,7 @@ void rtllib_reset_queue(struct rtllib_device *ieee)
spin_unlock_irqrestore(&ieee->lock, flags);
}
+EXPORT_SYMBOL(rtllib_reset_queue);
void rtllib_wake_queue(struct rtllib_device *ieee)
{
@@ -2928,6 +2937,7 @@ struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee)
return skb;
}
+EXPORT_SYMBOL(rtllib_get_beacon);
void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag,
u8 shutdown)
@@ -2937,6 +2947,7 @@ void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag,
rtllib_stop_protocol(ieee, shutdown);
up(&ieee->wx_sem);
}
+EXPORT_SYMBOL(rtllib_softmac_stop_protocol);
void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown)
@@ -2985,6 +2996,7 @@ void rtllib_softmac_start_protocol(struct rtllib_device *ieee, u8 mesh_flag)
rtllib_start_protocol(ieee);
up(&ieee->wx_sem);
}
+EXPORT_SYMBOL(rtllib_softmac_start_protocol);
void rtllib_start_protocol(struct rtllib_device *ieee)
{
@@ -3048,10 +3060,9 @@ void rtllib_softmac_init(struct rtllib_device *ieee)
ieee->state = RTLLIB_NOLINK;
for (i = 0; i < 5; i++)
ieee->seq_ctrl[i] = 0;
- ieee->pDot11dInfo = kmalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC);
+ ieee->pDot11dInfo = kzalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC);
if (!ieee->pDot11dInfo)
RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc memory for DOT11D\n");
- memset(ieee->pDot11dInfo, 0, sizeof(struct rt_dot11d_info));
ieee->LinkDetectInfo.SlotIndex = 0;
ieee->LinkDetectInfo.SlotNum = 2;
ieee->LinkDetectInfo.NumRecvBcnInPeriod = 0;
@@ -3207,11 +3218,11 @@ static int rtllib_wpa_set_wpa_ie(struct rtllib_device *ieee,
return -EINVAL;
if (param->u.wpa_ie.len) {
- buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
+ buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
+ GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
- memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
kfree(ieee->wpa_ie);
ieee->wpa_ie = buf;
ieee->wpa_ie_len = param->u.wpa_ie.len;
@@ -3334,8 +3345,8 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
u8 is_mesh)
{
int ret = 0;
- struct rtllib_crypto_ops *ops;
- struct rtllib_crypt_data **crypt;
+ struct lib80211_crypto_ops *ops;
+ struct lib80211_crypt_data **crypt;
struct rtllib_security sec = {
.flags = 0,
@@ -3354,9 +3365,9 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
- if (param->u.crypt.idx >= WEP_KEYS)
+ if (param->u.crypt.idx >= NUM_WEP_KEYS)
return -EINVAL;
- crypt = &ieee->crypt[param->u.crypt.idx];
+ crypt = &ieee->crypt_info.crypt[param->u.crypt.idx];
} else {
return -EINVAL;
}
@@ -3366,7 +3377,7 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
sec.enabled = 0;
sec.level = SEC_LEVEL_0;
sec.flags |= SEC_ENABLED | SEC_LEVEL;
- rtllib_crypt_delayed_deinit(ieee, crypt);
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
}
goto done;
}
@@ -3375,19 +3386,19 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
/* IPW HW cannot build TKIP MIC, host decryption still needed. */
if (!(ieee->host_encrypt || ieee->host_decrypt) &&
- strcmp(param->u.crypt.alg, "TKIP"))
+ strcmp(param->u.crypt.alg, "R-TKIP"))
goto skip_host_crypt;
- ops = rtllib_get_crypto_ops(param->u.crypt.alg);
- if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
+ if (ops == NULL && strcmp(param->u.crypt.alg, "R-WEP") == 0) {
request_module("rtllib_crypt_wep");
- ops = rtllib_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "R-TKIP") == 0) {
request_module("rtllib_crypt_tkip");
- ops = rtllib_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "R-CCMP") == 0) {
request_module("rtllib_crypt_ccmp");
- ops = rtllib_get_crypto_ops(param->u.crypt.alg);
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
}
if (ops == NULL) {
printk(KERN_INFO "unknown crypto alg '%s'\n",
@@ -3397,17 +3408,17 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
goto done;
}
if (*crypt == NULL || (*crypt)->ops != ops) {
- struct rtllib_crypt_data *new_crypt;
+ struct lib80211_crypt_data *new_crypt;
- rtllib_crypt_delayed_deinit(ieee, crypt);
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
- new_crypt = (struct rtllib_crypt_data *)
+ new_crypt = (struct lib80211_crypt_data *)
kmalloc(sizeof(*new_crypt), GFP_KERNEL);
if (new_crypt == NULL) {
ret = -ENOMEM;
goto done;
}
- memset(new_crypt, 0, sizeof(struct rtllib_crypt_data));
+ memset(new_crypt, 0, sizeof(struct lib80211_crypt_data));
new_crypt->ops = ops;
if (new_crypt->ops)
new_crypt->priv =
@@ -3435,7 +3446,7 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
skip_host_crypt:
if (param->u.crypt.set_tx) {
- ieee->tx_keyidx = param->u.crypt.idx;
+ ieee->crypt_info.tx_keyidx = param->u.crypt.idx;
sec.active_key = param->u.crypt.idx;
sec.flags |= SEC_ACTIVE_KEY;
} else
@@ -3448,13 +3459,13 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
sec.flags |= (1 << param->u.crypt.idx);
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ if (strcmp(param->u.crypt.alg, "R-WEP") == 0) {
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_1;
- } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ } else if (strcmp(param->u.crypt.alg, "R-TKIP") == 0) {
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_2;
- } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ } else if (strcmp(param->u.crypt.alg, "R-CCMP") == 0) {
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_3;
}
@@ -3551,13 +3562,13 @@ u8 rtllib_ap_sec_type(struct rtllib_device *ieee)
static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
int wpa_ie_len = ieee->wpa_ie_len;
- struct rtllib_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
int encrypt;
- crypt = ieee->crypt[ieee->tx_keyidx];
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY)
|| (ieee->host_encrypt && crypt && crypt->ops &&
- (0 == strcmp(crypt->ops->name, "WEP")));
+ (0 == strcmp(crypt->ops->name, "R-WEP")));
/* simply judge */
if (encrypt && (wpa_ie_len == 0)) {
@@ -3634,6 +3645,7 @@ out:
return ret;
}
+EXPORT_SYMBOL(rtllib_wpa_supplicant_ioctl);
void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib)
{
@@ -3719,6 +3731,7 @@ bool rtllib_MgntDisconnect(struct rtllib_device *rtllib, u8 asRsn)
return true;
}
+EXPORT_SYMBOL(rtllib_MgntDisconnect);
void notify_wx_assoc_event(struct rtllib_device *ieee)
{
@@ -3739,3 +3752,4 @@ void notify_wx_assoc_event(struct rtllib_device *ieee)
}
wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
}
+EXPORT_SYMBOL(notify_wx_assoc_event);
diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
index 22988fbd444b..1523bc7a2105 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
@@ -15,7 +15,6 @@
#include "rtllib.h"
-#include "rtl_core.h"
#include "dot11d.h"
/* FIXME: add A freqs */
@@ -25,6 +24,7 @@ const long rtllib_wlan_frequencies[] = {
2452, 2457, 2462, 2467,
2472, 2484
};
+EXPORT_SYMBOL(rtllib_wlan_frequencies);
int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
@@ -82,6 +82,7 @@ out:
up(&ieee->wx_sem);
return ret;
}
+EXPORT_SYMBOL(rtllib_wx_set_freq);
int rtllib_wx_get_freq(struct rtllib_device *ieee,
@@ -97,6 +98,7 @@ int rtllib_wx_get_freq(struct rtllib_device *ieee,
fwrq->e = 1;
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_get_freq);
int rtllib_wx_get_wap(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -125,6 +127,7 @@ int rtllib_wx_get_wap(struct rtllib_device *ieee,
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_get_wap);
int rtllib_wx_set_wap(struct rtllib_device *ieee,
@@ -184,6 +187,7 @@ out:
up(&ieee->wx_sem);
return ret;
}
+EXPORT_SYMBOL(rtllib_wx_set_wap);
int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
@@ -220,6 +224,7 @@ out:
return ret;
}
+EXPORT_SYMBOL(rtllib_wx_get_essid);
int rtllib_wx_set_rate(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -231,6 +236,7 @@ int rtllib_wx_set_rate(struct rtllib_device *ieee,
ieee->rate = target_rate/100000;
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_set_rate);
int rtllib_wx_get_rate(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -243,6 +249,7 @@ int rtllib_wx_get_rate(struct rtllib_device *ieee,
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_get_rate);
int rtllib_wx_set_rts(struct rtllib_device *ieee,
@@ -259,6 +266,7 @@ int rtllib_wx_set_rts(struct rtllib_device *ieee,
}
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_set_rts);
int rtllib_wx_get_rts(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -269,6 +277,7 @@ int rtllib_wx_get_rts(struct rtllib_device *ieee,
wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_get_rts);
int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
@@ -314,6 +323,7 @@ out:
up(&ieee->wx_sem);
return set_mode_status;
}
+EXPORT_SYMBOL(rtllib_wx_set_mode);
void rtllib_wx_sync_scan_wq(void *data)
{
@@ -428,6 +438,7 @@ out:
up(&ieee->wx_sem);
return ret;
}
+EXPORT_SYMBOL(rtllib_wx_set_scan);
int rtllib_wx_set_essid(struct rtllib_device *ieee,
struct iw_request_info *a,
@@ -490,6 +501,7 @@ out:
up(&ieee->wx_sem);
return ret;
}
+EXPORT_SYMBOL(rtllib_wx_set_essid);
int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
@@ -497,6 +509,7 @@ int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a,
wrqu->mode = ieee->iw_mode;
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_get_mode);
int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -533,6 +546,7 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_set_rawtx);
int rtllib_wx_get_name(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -548,6 +562,7 @@ int rtllib_wx_get_name(struct rtllib_device *ieee,
strcat(wrqu->name, "n");
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_get_name);
/* this is mostly stolen from hostap */
@@ -605,6 +620,7 @@ exit:
return ret;
}
+EXPORT_SYMBOL(rtllib_wx_set_power);
/* this is stolen from hostap */
int rtllib_wx_get_power(struct rtllib_device *ieee,
@@ -643,3 +659,4 @@ exit:
return ret;
}
+EXPORT_SYMBOL(rtllib_wx_get_power);
diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c
index 44e8006bc1af..f451bfc27a86 100644
--- a/drivers/staging/rtl8192e/rtllib_tx.c
+++ b/drivers/staging/rtl8192e/rtllib_tx.c
@@ -46,7 +46,6 @@
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
-#include <linux/version.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <linux/uaccess.h>
@@ -180,10 +179,10 @@ inline int rtllib_put_snap(u8 *data, u16 h_proto)
int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
int hdr_len)
{
- struct rtllib_crypt_data *crypt = NULL;
+ struct lib80211_crypt_data *crypt = NULL;
int res;
- crypt = ieee->crypt[ieee->tx_keyidx];
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
if (!(crypt && crypt->ops)) {
printk(KERN_INFO "=========>%s(), crypt is null\n", __func__);
@@ -569,7 +568,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
};
u8 dest[ETH_ALEN], src[ETH_ALEN];
int qos_actived = ieee->current_network.qos_data.active;
- struct rtllib_crypt_data *crypt = NULL;
+ struct lib80211_crypt_data *crypt = NULL;
struct cb_desc *tcb_desc;
u8 bIsMulticast = false;
u8 IsAmsdu = false;
@@ -646,7 +645,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
}
skb->priority = rtllib_classify(skb, IsAmsdu);
- crypt = ieee->crypt[ieee->tx_keyidx];
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
ieee->host_encrypt && crypt && crypt->ops;
if (!encrypt && ieee->ieee802_1x &&
@@ -742,8 +741,10 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
/* Each fragment may need to have room for encryptiong
* pre/postfix */
if (encrypt) {
- bytes_per_frag -= crypt->ops->extra_prefix_len +
- crypt->ops->extra_postfix_len;
+ bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
+ crypt->ops->extra_mpdu_postfix_len +
+ crypt->ops->extra_msdu_prefix_len +
+ crypt->ops->extra_msdu_postfix_len;
}
/* Number of fragments is the total bytes_per_frag /
* payload_per_fragment */
@@ -791,7 +792,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
else
tcb_desc->bHwSec = 0;
skb_reserve(skb_frag,
- crypt->ops->extra_prefix_len);
+ crypt->ops->extra_mpdu_prefix_len +
+ crypt->ops->extra_msdu_prefix_len);
} else {
tcb_desc->bHwSec = 0;
}
@@ -965,3 +967,4 @@ int rtllib_xmit(struct sk_buff *skb, struct net_device *dev)
memset(skb->cb, 0, sizeof(skb->cb));
return rtllib_xmit_inter(skb, dev);
}
+EXPORT_SYMBOL(rtllib_xmit);
diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c
index 8cea4a60e1b3..c27ff7edbaf2 100644
--- a/drivers/staging/rtl8192e/rtllib_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_wx.c
@@ -30,7 +30,6 @@
******************************************************************************/
#include <linux/wireless.h>
-#include <linux/version.h>
#include <linux/kmod.h>
#include <linux/module.h>
@@ -295,6 +294,7 @@ int rtllib_wx_get_scan(struct rtllib_device *ieee,
return err;
}
+EXPORT_SYMBOL(rtllib_wx_get_scan);
int rtllib_wx_set_encode(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -306,44 +306,44 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
.flags = 0
};
int i, key, key_provided, len;
- struct rtllib_crypt_data **crypt;
+ struct lib80211_crypt_data **crypt;
RTLLIB_DEBUG_WX("SET_ENCODE\n");
key = erq->flags & IW_ENCODE_INDEX;
if (key) {
- if (key > WEP_KEYS)
+ if (key > NUM_WEP_KEYS)
return -EINVAL;
key--;
key_provided = 1;
} else {
key_provided = 0;
- key = ieee->tx_keyidx;
+ key = ieee->crypt_info.tx_keyidx;
}
RTLLIB_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
"provided" : "default");
- crypt = &ieee->crypt[key];
+ crypt = &ieee->crypt_info.crypt[key];
if (erq->flags & IW_ENCODE_DISABLED) {
if (key_provided && *crypt) {
RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
key);
- rtllib_crypt_delayed_deinit(ieee, crypt);
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
} else
RTLLIB_DEBUG_WX("Disabling encryption.\n");
/* Check all the keys to see if any are still configured,
* and if no key index was provided, de-init them all */
- for (i = 0; i < WEP_KEYS; i++) {
- if (ieee->crypt[i] != NULL) {
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ if (ieee->crypt_info.crypt[i] != NULL) {
if (key_provided)
break;
- rtllib_crypt_delayed_deinit(ieee,
- &ieee->crypt[i]);
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info,
+ &ieee->crypt_info.crypt[i]);
}
}
- if (i == WEP_KEYS) {
+ if (i == NUM_WEP_KEYS) {
sec.enabled = 0;
sec.level = SEC_LEVEL_0;
sec.flags |= SEC_ENABLED | SEC_LEVEL;
@@ -358,25 +358,24 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
sec.flags |= SEC_ENABLED;
if (*crypt != NULL && (*crypt)->ops != NULL &&
- strcmp((*crypt)->ops->name, "WEP") != 0) {
+ strcmp((*crypt)->ops->name, "R-WEP") != 0) {
/* changing to use WEP; deinit previously used algorithm
* on this key */
- rtllib_crypt_delayed_deinit(ieee, crypt);
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
}
if (*crypt == NULL) {
- struct rtllib_crypt_data *new_crypt;
+ struct lib80211_crypt_data *new_crypt;
/* take WEP into use */
- new_crypt = kmalloc(sizeof(struct rtllib_crypt_data),
+ new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
GFP_KERNEL);
if (new_crypt == NULL)
return -ENOMEM;
- memset(new_crypt, 0, sizeof(struct rtllib_crypt_data));
- new_crypt->ops = rtllib_get_crypto_ops("WEP");
+ new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
if (!new_crypt->ops) {
request_module("rtllib_crypt_wep");
- new_crypt->ops = rtllib_get_crypto_ops("WEP");
+ new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
}
if (new_crypt->ops)
@@ -412,7 +411,7 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
* explicitely set */
if (key == sec.active_key)
sec.flags |= SEC_ACTIVE_KEY;
- ieee->tx_keyidx = key;
+ ieee->crypt_info.tx_keyidx = key;
} else {
len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
@@ -435,7 +434,7 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
if (key_provided) {
RTLLIB_DEBUG_WX(
"Setting key %d to default Tx key.\n", key);
- ieee->tx_keyidx = key;
+ ieee->crypt_info.tx_keyidx = key;
sec.active_key = key;
sec.flags |= SEC_ACTIVE_KEY;
}
@@ -470,6 +469,7 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
}
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_set_encode);
int rtllib_wx_get_encode(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -477,7 +477,7 @@ int rtllib_wx_get_encode(struct rtllib_device *ieee,
{
struct iw_point *erq = &(wrqu->encoding);
int len, key;
- struct rtllib_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
RTLLIB_DEBUG_WX("GET_ENCODE\n");
@@ -486,13 +486,13 @@ int rtllib_wx_get_encode(struct rtllib_device *ieee,
key = erq->flags & IW_ENCODE_INDEX;
if (key) {
- if (key > WEP_KEYS)
+ if (key > NUM_WEP_KEYS)
return -EINVAL;
key--;
} else {
- key = ieee->tx_keyidx;
+ key = ieee->crypt_info.tx_keyidx;
}
- crypt = ieee->crypt[key];
+ crypt = ieee->crypt_info.crypt[key];
erq->flags = key + 1;
@@ -513,6 +513,7 @@ int rtllib_wx_get_encode(struct rtllib_device *ieee,
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_get_encode);
int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -525,29 +526,29 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
int i, idx;
int group_key = 0;
const char *alg, *module;
- struct rtllib_crypto_ops *ops;
- struct rtllib_crypt_data **crypt;
+ struct lib80211_crypto_ops *ops;
+ struct lib80211_crypt_data **crypt;
struct rtllib_security sec = {
.flags = 0,
};
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if (idx < 1 || idx > WEP_KEYS)
+ if (idx < 1 || idx > NUM_WEP_KEYS)
return -EINVAL;
idx--;
} else{
- idx = ieee->tx_keyidx;
+ idx = ieee->crypt_info.tx_keyidx;
}
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
- crypt = &ieee->crypt[idx];
+ crypt = &ieee->crypt_info.crypt[idx];
group_key = 1;
} else {
/* some Cisco APs use idx>0 for unicast in dynamic WEP */
if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
return -EINVAL;
if (ieee->iw_mode == IW_MODE_INFRA)
- crypt = &ieee->crypt[idx];
+ crypt = &ieee->crypt_info.crypt[idx];
else
return -EINVAL;
}
@@ -556,13 +557,13 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
if ((encoding->flags & IW_ENCODE_DISABLED) ||
ext->alg == IW_ENCODE_ALG_NONE) {
if (*crypt)
- rtllib_crypt_delayed_deinit(ieee, crypt);
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
- for (i = 0; i < WEP_KEYS; i++) {
- if (ieee->crypt[i] != NULL)
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ if (ieee->crypt_info.crypt[i] != NULL)
break;
}
- if (i == WEP_KEYS) {
+ if (i == NUM_WEP_KEYS) {
sec.enabled = 0;
sec.level = SEC_LEVEL_0;
sec.flags |= SEC_LEVEL;
@@ -573,15 +574,15 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
sec.enabled = 1;
switch (ext->alg) {
case IW_ENCODE_ALG_WEP:
- alg = "WEP";
+ alg = "R-WEP";
module = "rtllib_crypt_wep";
break;
case IW_ENCODE_ALG_TKIP:
- alg = "TKIP";
+ alg = "R-TKIP";
module = "rtllib_crypt_tkip";
break;
case IW_ENCODE_ALG_CCMP:
- alg = "CCMP";
+ alg = "R-CCMP";
module = "rtllib_crypt_ccmp";
break;
default:
@@ -592,14 +593,14 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
}
printk(KERN_INFO "alg name:%s\n", alg);
- ops = rtllib_get_crypto_ops(alg);
+ ops = lib80211_get_crypto_ops(alg);
if (ops == NULL) {
char tempbuf[100];
memset(tempbuf, 0x00, 100);
sprintf(tempbuf, "%s", module);
request_module("%s", tempbuf);
- ops = rtllib_get_crypto_ops(alg);
+ ops = lib80211_get_crypto_ops(alg);
}
if (ops == NULL) {
RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
@@ -610,9 +611,9 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
}
if (*crypt == NULL || (*crypt)->ops != ops) {
- struct rtllib_crypt_data *new_crypt;
+ struct lib80211_crypt_data *new_crypt;
- rtllib_crypt_delayed_deinit(ieee, crypt);
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
if (new_crypt == NULL) {
@@ -641,7 +642,7 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
goto done;
}
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
- ieee->tx_keyidx = idx;
+ ieee->crypt_info.tx_keyidx = idx;
sec.active_key = idx;
sec.flags |= SEC_ACTIVE_KEY;
}
@@ -674,6 +675,7 @@ done:
}
return ret;
}
+EXPORT_SYMBOL(rtllib_wx_set_encode_ext);
int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -681,7 +683,7 @@ int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
{
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- struct rtllib_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
int idx, max_key_len;
max_key_len = encoding->length - sizeof(*ext);
@@ -690,18 +692,18 @@ int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if (idx < 1 || idx > WEP_KEYS)
+ if (idx < 1 || idx > NUM_WEP_KEYS)
return -EINVAL;
idx--;
} else {
- idx = ieee->tx_keyidx;
+ idx = ieee->crypt_info.tx_keyidx;
}
if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
(ext->alg != IW_ENCODE_ALG_WEP))
if (idx != 0 || (ieee->iw_mode != IW_MODE_INFRA))
return -EINVAL;
- crypt = ieee->crypt[idx];
+ crypt = ieee->crypt_info.crypt[idx];
encoding->flags = idx + 1;
memset(ext, 0, sizeof(*ext));
@@ -711,11 +713,11 @@ int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
ext->key_len = 0;
encoding->flags |= IW_ENCODE_DISABLED;
} else {
- if (strcmp(crypt->ops->name, "WEP") == 0)
+ if (strcmp(crypt->ops->name, "R-WEP") == 0)
ext->alg = IW_ENCODE_ALG_WEP;
- else if (strcmp(crypt->ops->name, "TKIP"))
+ else if (strcmp(crypt->ops->name, "R-TKIP"))
ext->alg = IW_ENCODE_ALG_TKIP;
- else if (strcmp(crypt->ops->name, "CCMP"))
+ else if (strcmp(crypt->ops->name, "R-CCMP"))
ext->alg = IW_ENCODE_ALG_CCMP;
else
return -EINVAL;
@@ -778,6 +780,7 @@ int rtllib_wx_set_mlme(struct rtllib_device *ieee,
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_set_mlme);
int rtllib_wx_set_auth(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -830,6 +833,7 @@ int rtllib_wx_set_auth(struct rtllib_device *ieee,
}
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_set_auth);
int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
{
@@ -846,10 +850,9 @@ int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len) :
(MAX_WZC_IE_LEN);
- buf = kmalloc(ieee->wps_ie_len, GFP_KERNEL);
+ buf = kmemdup(ie, ieee->wps_ie_len, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
- memcpy(buf, ie, ieee->wps_ie_len);
ieee->wps_ie = buf;
return 0;
}
@@ -860,10 +863,9 @@ int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
if (len) {
if (len != ie[1]+2)
return -EINVAL;
- buf = kmalloc(len, GFP_KERNEL);
+ buf = kmemdup(ie, len, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
- memcpy(buf, ie, len);
kfree(ieee->wpa_ie);
ieee->wpa_ie = buf;
ieee->wpa_ie_len = len;
@@ -874,3 +876,4 @@ int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
}
return 0;
}
+EXPORT_SYMBOL(rtllib_wx_set_gen_ie);
diff --git a/drivers/staging/rtl8192u/ieee80211/api.c b/drivers/staging/rtl8192u/ieee80211/api.c
deleted file mode 100644
index 5f46e50e586e..000000000000
--- a/drivers/staging/rtl8192u/ieee80211/api.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Scatterlist Cryptographic API.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Copyright (c) 2002 David S. Miller (davem@redhat.com)
- *
- * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
- * and Nettle, by Niels M鰈ler.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 "kmap_types.h"
-
-#include <linux/init.h>
-#include <linux/module.h>
-//#include <linux/crypto.h>
-#include "rtl_crypto.h"
-#include <linux/errno.h>
-#include <linux/rwsem.h>
-#include <linux/slab.h>
-#include "internal.h"
-
-LIST_HEAD(crypto_alg_list);
-DECLARE_RWSEM(crypto_alg_sem);
-
-static inline int crypto_alg_get(struct crypto_alg *alg)
-{
- return try_inc_mod_count(alg->cra_module);
-}
-
-static inline void crypto_alg_put(struct crypto_alg *alg)
-{
- if (alg->cra_module)
- __MOD_DEC_USE_COUNT(alg->cra_module);
-}
-
-struct crypto_alg *crypto_alg_lookup(const char *name)
-{
- struct crypto_alg *q, *alg = NULL;
-
- if (!name)
- return NULL;
-
- down_read(&crypto_alg_sem);
-
- list_for_each_entry(q, &crypto_alg_list, cra_list) {
- if (!(strcmp(q->cra_name, name))) {
- if (crypto_alg_get(q))
- alg = q;
- break;
- }
- }
-
- up_read(&crypto_alg_sem);
- return alg;
-}
-
-static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
-{
- tfm->crt_flags = 0;
-
- switch (crypto_tfm_alg_type(tfm)) {
- case CRYPTO_ALG_TYPE_CIPHER:
- return crypto_init_cipher_flags(tfm, flags);
-
- case CRYPTO_ALG_TYPE_DIGEST:
- return crypto_init_digest_flags(tfm, flags);
-
- case CRYPTO_ALG_TYPE_COMPRESS:
- return crypto_init_compress_flags(tfm, flags);
-
- default:
- break;
- }
-
- BUG();
- return -EINVAL;
-}
-
-static int crypto_init_ops(struct crypto_tfm *tfm)
-{
- switch (crypto_tfm_alg_type(tfm)) {
- case CRYPTO_ALG_TYPE_CIPHER:
- return crypto_init_cipher_ops(tfm);
-
- case CRYPTO_ALG_TYPE_DIGEST:
- return crypto_init_digest_ops(tfm);
-
- case CRYPTO_ALG_TYPE_COMPRESS:
- return crypto_init_compress_ops(tfm);
-
- default:
- break;
- }
-
- BUG();
- return -EINVAL;
-}
-
-static void crypto_exit_ops(struct crypto_tfm *tfm)
-{
- switch (crypto_tfm_alg_type(tfm)) {
- case CRYPTO_ALG_TYPE_CIPHER:
- crypto_exit_cipher_ops(tfm);
- break;
-
- case CRYPTO_ALG_TYPE_DIGEST:
- crypto_exit_digest_ops(tfm);
- break;
-
- case CRYPTO_ALG_TYPE_COMPRESS:
- crypto_exit_compress_ops(tfm);
- break;
-
- default:
- BUG();
-
- }
-}
-
-struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
-{
- struct crypto_tfm *tfm = NULL;
- struct crypto_alg *alg;
-
- alg = crypto_alg_mod_lookup(name);
- if (alg == NULL)
- goto out;
-
- tfm = kzalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL);
- if (tfm == NULL)
- goto out_put;
-
- tfm->__crt_alg = alg;
-
- if (crypto_init_flags(tfm, flags))
- goto out_free_tfm;
-
- if (crypto_init_ops(tfm)) {
- crypto_exit_ops(tfm);
- goto out_free_tfm;
- }
-
- goto out;
-
-out_free_tfm:
- kfree(tfm);
- tfm = NULL;
-out_put:
- crypto_alg_put(alg);
-out:
- return tfm;
-}
-
-void crypto_free_tfm(struct crypto_tfm *tfm)
-{
- struct crypto_alg *alg = tfm->__crt_alg;
- int size = sizeof(*tfm) + alg->cra_ctxsize;
-
- crypto_exit_ops(tfm);
- crypto_alg_put(alg);
- memset(tfm, 0, size);
- kfree(tfm);
-}
-
-int crypto_register_alg(struct crypto_alg *alg)
-{
- int ret = 0;
- struct crypto_alg *q;
-
- down_write(&crypto_alg_sem);
-
- list_for_each_entry(q, &crypto_alg_list, cra_list) {
- if (!(strcmp(q->cra_name, alg->cra_name))) {
- ret = -EEXIST;
- goto out;
- }
- }
-
- list_add_tail(&alg->cra_list, &crypto_alg_list);
-out:
- up_write(&crypto_alg_sem);
- return ret;
-}
-
-int crypto_unregister_alg(struct crypto_alg *alg)
-{
- int ret = -ENOENT;
- struct crypto_alg *q;
-
- BUG_ON(!alg->cra_module);
-
- down_write(&crypto_alg_sem);
- list_for_each_entry(q, &crypto_alg_list, cra_list) {
- if (alg == q) {
- list_del(&alg->cra_list);
- ret = 0;
- goto out;
- }
- }
-out:
- up_write(&crypto_alg_sem);
- return ret;
-}
-
-int crypto_alg_available(const char *name, u32 flags)
-{
- int ret = 0;
- struct crypto_alg *alg = crypto_alg_mod_lookup(name);
-
- if (alg) {
- crypto_alg_put(alg);
- ret = 1;
- }
-
- return ret;
-}
-
-static int __init init_crypto(void)
-{
- printk(KERN_INFO "Initializing Cryptographic API\n");
- crypto_init_proc();
- return 0;
-}
-
-__initcall(init_crypto);
-
-/*
-EXPORT_SYMBOL_GPL(crypto_register_alg);
-EXPORT_SYMBOL_GPL(crypto_unregister_alg);
-EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
-EXPORT_SYMBOL_GPL(crypto_free_tfm);
-EXPORT_SYMBOL_GPL(crypto_alg_available);
-*/
-
-EXPORT_SYMBOL_NOVERS(crypto_register_alg);
-EXPORT_SYMBOL_NOVERS(crypto_unregister_alg);
-EXPORT_SYMBOL_NOVERS(crypto_alloc_tfm);
-EXPORT_SYMBOL_NOVERS(crypto_free_tfm);
-EXPORT_SYMBOL_NOVERS(crypto_alg_available);
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
index ef8eb6c7ee41..4277d0304b7a 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ b/drivers/staging/rtl8712/rtl871x_mlme.c
@@ -551,7 +551,7 @@ void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
ibss_wlan = r8712_find_network(
&pmlmepriv->scanned_queue,
pnetwork->MacAddress);
- if (!ibss_wlan) {
+ if (ibss_wlan) {
memcpy(ibss_wlan->network.IEs,
pnetwork->IEs, 8);
goto exit;
diff --git a/drivers/staging/rts5139/rts51x.h b/drivers/staging/rts5139/rts51x.h
index 9415d5c05502..b2c58390bfc5 100644
--- a/drivers/staging/rts5139/rts51x.h
+++ b/drivers/staging/rts5139/rts51x.h
@@ -34,7 +34,6 @@
#include <linux/mutex.h>
#include <linux/cdrom.h>
#include <linux/kernel.h>
-#include <linux/version.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
diff --git a/drivers/staging/rts5139/rts51x_transport.h b/drivers/staging/rts5139/rts51x_transport.h
index f7aa87f7f1a9..8464c4836d5b 100644
--- a/drivers/staging/rts5139/rts51x_transport.h
+++ b/drivers/staging/rts5139/rts51x_transport.h
@@ -28,7 +28,6 @@
#define __RTS51X_TRANSPORT_H
#include <linux/kernel.h>
-#include <linux/version.h>
#include "rts51x.h"
#include "rts51x_chip.h"
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index f47571ea745d..6b3d156d4140 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -2120,6 +2120,8 @@ static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
}
}
if (tail_size) {
+ if (tail_size > sizeof(dcb_table_ptr->tail_data))
+ return -EINVAL;
if (is_kva == true) {
memcpy(dcb_table_ptr->tail_data,
(void *)(app_in_address + data_in_size -
diff --git a/drivers/staging/serial/68360serial.c b/drivers/staging/serial/68360serial.c
index 0a3e8787ed50..daf0b1d0dc28 100644
--- a/drivers/staging/serial/68360serial.c
+++ b/drivers/staging/serial/68360serial.c
@@ -2771,8 +2771,8 @@ static int __init rs_360_init(void)
*/
/* cpm_install_handler(IRQ_MACHSPEC | state->irq, rs_360_interrupt, info); */
/*request_irq(IRQ_MACHSPEC | state->irq, rs_360_interrupt, */
- request_irq(state->irq, rs_360_interrupt,
- IRQ_FLG_LOCK, "ttyS", (void *)info);
+ request_irq(state->irq, rs_360_interrupt, 0, "ttyS",
+ (void *)info);
/* Set up the baud rate generator.
*/
diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c
index 39dbf339a4fc..ae0035f327e7 100644
--- a/drivers/staging/sm7xx/smtcfb.c
+++ b/drivers/staging/sm7xx/smtcfb.c
@@ -1024,9 +1024,9 @@ failed_free:
/* Jason (08/11/2009) PCI_DRV wrapper essential structs */
static DEFINE_PCI_DEVICE_TABLE(smtcfb_pci_table) = {
- {0x126f, 0x710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x126f, 0x712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x126f, 0x720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_DEVICE(0x126f, 0x710), },
+ { PCI_DEVICE(0x126f, 0x712), },
+ { PCI_DEVICE(0x126f, 0x720), },
{0,}
};
diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
index 07a7f5432597..2093896c546b 100644
--- a/drivers/staging/speakup/kobjects.c
+++ b/drivers/staging/speakup/kobjects.c
@@ -265,12 +265,11 @@ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr,
unsigned long flags;
spk_lock(flags);
- in_buff = kmalloc(count + 1, GFP_ATOMIC);
+ in_buff = kmemdup(buf, count + 1, GFP_ATOMIC);
if (!in_buff) {
spk_unlock(flags);
return -ENOMEM;
}
- memcpy(in_buff, buf, count + 1);
if (strchr("dDrR", *in_buff)) {
set_key_info(key_defaults, key_buf);
pr_info("keymap set to default values\n");
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index 8be560458977..c7b03f0ef2dd 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -2268,8 +2268,6 @@ static int __init speakup_init(void)
set_mask_bits(0, i, 2);
set_key_info(key_defaults, key_buf);
- if (quiet_boot)
- spk_shut_up |= 0x01;
/* From here on out, initializations can fail. */
err = speakup_add_virtual_keyboard();
@@ -2292,6 +2290,9 @@ static int __init speakup_init(void)
goto error_kobjects;
}
+ if (quiet_boot)
+ spk_shut_up |= 0x01;
+
err = speakup_kobj_init();
if (err)
goto error_kobjects;
diff --git a/drivers/staging/spectra/Kconfig b/drivers/staging/spectra/Kconfig
deleted file mode 100644
index 4fc206484830..000000000000
--- a/drivers/staging/spectra/Kconfig
+++ /dev/null
@@ -1,41 +0,0 @@
-
-menuconfig SPECTRA
- tristate "Denali Spectra Flash Translation Layer"
- depends on BLOCK
- depends on X86_MRST
- default n
- ---help---
- Enable the FTL pseudo-filesystem used with the NAND Flash
- controller on Intel Moorestown Platform to pretend to be a disk.
-
-choice
- prompt "Compile for"
- depends on SPECTRA
- default SPECTRA_MRST_HW
-
-config SPECTRA_MRST_HW
- bool "Moorestown hardware mode"
- help
- Driver communicates with the Moorestown hardware's register interface.
- in DMA mode.
-
-config SPECTRA_MTD
- bool "Linux MTD mode"
- depends on MTD
- help
- Driver communicates with the kernel MTD subsystem instead of its own
- built-in hardware driver.
-
-config SPECTRA_EMU
- bool "RAM emulator testing"
- help
- Driver emulates Flash on a RAM buffer and / or disk file. Useful to test the behavior of FTL layer.
-
-endchoice
-
-config SPECTRA_MRST_HW_DMA
- bool
- default n
- depends on SPECTRA_MRST_HW
- help
- Use DMA for native hardware interface.
diff --git a/drivers/staging/spectra/Makefile b/drivers/staging/spectra/Makefile
deleted file mode 100644
index f777dfba05a5..000000000000
--- a/drivers/staging/spectra/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile of Intel Moorestown NAND controller driver
-#
-
-obj-$(CONFIG_SPECTRA) += spectra.o
-spectra-y := ffsport.o flash.o lld.o
-spectra-$(CONFIG_SPECTRA_MRST_HW) += lld_nand.o
-spectra-$(CONFIG_SPECTRA_MRST_HW_DMA) += lld_cdma.o
-spectra-$(CONFIG_SPECTRA_EMU) += lld_emu.o
-spectra-$(CONFIG_SPECTRA_MTD) += lld_mtd.o
-
diff --git a/drivers/staging/spectra/README b/drivers/staging/spectra/README
deleted file mode 100644
index ecba559b899c..000000000000
--- a/drivers/staging/spectra/README
+++ /dev/null
@@ -1,29 +0,0 @@
-This is a driver for NAND controller of Intel Moorestown platform.
-
-This driver is a standalone linux block device driver, it acts as if it's a normal hard disk.
-It includes three layer:
- block layer interface - file ffsport.c
- Flash Translation Layer (FTL) - file flash.c (implement the NAND flash Translation Layer, includs address mapping, garbage collection, wear-leveling and so on)
- Low level layer - file lld_nand.c/lld_cdma.c/lld_emu.c (which implements actual controller hardware registers access)
-
-This driver can be build as modules or build-in.
-
-Dependency:
-This driver has dependency on IA Firmware of Intel Moorestown platform.
-It need the IA Firmware to create the block table for the first time.
-And to validate this driver code without IA Firmware, you can change the
-macro AUTO_FORMAT_FLASH from 0 to 1 in file spectraswconfig.h. Thus the
-driver will erase the whole nand flash and create a new block table.
-
-TODO:
- - Enable Command DMA feature support
- - lower the memory footprint
- - Remove most of the unnecessary global variables
- - Change all the upcase variable / functions name to lowercase
- - Some other misc bugs
-
-Please send patches to:
- Greg Kroah-Hartman <gregkh@suse.de>
-
-And Cc to: Gao Yunpeng <yunpeng.gao@intel.com>
-
diff --git a/drivers/staging/spectra/ffsdefs.h b/drivers/staging/spectra/ffsdefs.h
deleted file mode 100644
index a9e9cd233d2a..000000000000
--- a/drivers/staging/spectra/ffsdefs.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef _FFSDEFS_
-#define _FFSDEFS_
-
-#define CLEAR 0 /*use this to clear a field instead of "fail"*/
-#define SET 1 /*use this to set a field instead of "pass"*/
-#define FAIL 1 /*failed flag*/
-#define PASS 0 /*success flag*/
-#define ERR -1 /*error flag*/
-
-#define ERASE_CMD 10
-#define WRITE_MAIN_CMD 11
-#define READ_MAIN_CMD 12
-#define WRITE_SPARE_CMD 13
-#define READ_SPARE_CMD 14
-#define WRITE_MAIN_SPARE_CMD 15
-#define READ_MAIN_SPARE_CMD 16
-#define MEMCOPY_CMD 17
-#define DUMMY_CMD 99
-
-#define EVENT_PASS 0x00
-#define EVENT_CORRECTABLE_DATA_ERROR_FIXED 0x01
-#define EVENT_UNCORRECTABLE_DATA_ERROR 0x02
-#define EVENT_TIME_OUT 0x03
-#define EVENT_PROGRAM_FAILURE 0x04
-#define EVENT_ERASE_FAILURE 0x05
-#define EVENT_MEMCOPY_FAILURE 0x06
-#define EVENT_FAIL 0x07
-
-#define EVENT_NONE 0x22
-#define EVENT_DMA_CMD_COMP 0x77
-#define EVENT_ECC_TRANSACTION_DONE 0x88
-#define EVENT_DMA_CMD_FAIL 0x99
-
-#define CMD_PASS 0
-#define CMD_FAIL 1
-#define CMD_ABORT 2
-#define CMD_NOT_DONE 3
-
-#endif /* _FFSDEFS_ */
diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c
deleted file mode 100644
index 86d556d6cf98..000000000000
--- a/drivers/staging/spectra/ffsport.c
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "ffsport.h"
-#include "flash.h"
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/blkdev.h>
-#include <linux/wait.h>
-#include <linux/mutex.h>
-#include <linux/kthread.h>
-#include <linux/log2.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/async.h>
-
-/**** Helper functions used for Div, Remainder operation on u64 ****/
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_Calc_Used_Bits
-* Inputs: Power of 2 number
-* Outputs: Number of Used Bits
-* 0, if the argument is 0
-* Description: Calculate the number of bits used by a given power of 2 number
-* Number can be up to 32 bit
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_Calc_Used_Bits(u32 n)
-{
- int tot_bits = 0;
-
- if (n >= 1 << 16) {
- n >>= 16;
- tot_bits += 16;
- }
-
- if (n >= 1 << 8) {
- n >>= 8;
- tot_bits += 8;
- }
-
- if (n >= 1 << 4) {
- n >>= 4;
- tot_bits += 4;
- }
-
- if (n >= 1 << 2) {
- n >>= 2;
- tot_bits += 2;
- }
-
- if (n >= 1 << 1)
- tot_bits += 1;
-
- return ((n == 0) ? (0) : tot_bits);
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_u64_Div
-* Inputs: Number of u64
-* A power of 2 number as Division
-* Outputs: Quotient of the Divisor operation
-* Description: It divides the address by divisor by using bit shift operation
-* (essentially without explicitely using "/").
-* Divisor is a power of 2 number and Divided is of u64
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u64 GLOB_u64_Div(u64 addr, u32 divisor)
-{
- return (u64)(addr >> GLOB_Calc_Used_Bits(divisor));
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_u64_Remainder
-* Inputs: Number of u64
-* Divisor Type (1 -PageAddress, 2- BlockAddress)
-* Outputs: Remainder of the Division operation
-* Description: It calculates the remainder of a number (of u64) by
-* divisor(power of 2 number ) by using bit shifting and multiply
-* operation(essentially without explicitely using "/").
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type)
-{
- u64 result = 0;
-
- if (divisor_type == 1) { /* Remainder -- Page */
- result = (addr >> DeviceInfo.nBitsInPageDataSize);
- result = result * DeviceInfo.wPageDataSize;
- } else if (divisor_type == 2) { /* Remainder -- Block */
- result = (addr >> DeviceInfo.nBitsInBlockDataSize);
- result = result * DeviceInfo.wBlockDataSize;
- }
-
- result = addr - result;
-
- return result;
-}
-
-#define NUM_DEVICES 1
-#define PARTITIONS 8
-
-#define GLOB_SBD_NAME "nd"
-#define GLOB_SBD_IRQ_NUM (29)
-
-#define GLOB_SBD_IOCTL_GC (0x7701)
-#define GLOB_SBD_IOCTL_WL (0x7702)
-#define GLOB_SBD_IOCTL_FORMAT (0x7703)
-#define GLOB_SBD_IOCTL_ERASE_FLASH (0x7704)
-#define GLOB_SBD_IOCTL_FLUSH_CACHE (0x7705)
-#define GLOB_SBD_IOCTL_COPY_BLK_TABLE (0x7706)
-#define GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE (0x7707)
-#define GLOB_SBD_IOCTL_GET_NAND_INFO (0x7708)
-#define GLOB_SBD_IOCTL_WRITE_DATA (0x7709)
-#define GLOB_SBD_IOCTL_READ_DATA (0x770A)
-
-static int reserved_mb = 0;
-module_param(reserved_mb, int, 0);
-MODULE_PARM_DESC(reserved_mb, "Reserved space for OS image, in MiB (default 25 MiB)");
-
-int nand_debug_level;
-module_param(nand_debug_level, int, 0644);
-MODULE_PARM_DESC(nand_debug_level, "debug level value: 1-3");
-
-MODULE_LICENSE("GPL");
-
-struct spectra_nand_dev {
- struct pci_dev *dev;
- u64 size;
- u16 users;
- spinlock_t qlock;
- void __iomem *ioaddr; /* Mapped address */
- struct request_queue *queue;
- struct task_struct *thread;
- struct gendisk *gd;
- u8 *tmp_buf;
-};
-
-
-static int GLOB_SBD_majornum;
-
-static char *GLOB_version = GLOB_VERSION;
-
-static struct spectra_nand_dev nand_device[NUM_DEVICES];
-
-static struct mutex spectra_lock;
-
-static int res_blks_os = 1;
-
-struct spectra_indentfy_dev_tag IdentifyDeviceData;
-
-static int force_flush_cache(void)
-{
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (ERR == GLOB_FTL_Flush_Cache()) {
- printk(KERN_ERR "Fail to Flush FTL Cache!\n");
- return -EFAULT;
- }
-#if CMD_DMA
- if (glob_ftl_execute_cmds())
- return -EIO;
- else
- return 0;
-#endif
- return 0;
-}
-
-struct ioctl_rw_page_info {
- u8 *data;
- unsigned int page;
-};
-
-static int ioctl_read_page_data(unsigned long arg)
-{
- u8 *buf;
- struct ioctl_rw_page_info info;
- int result = PASS;
-
- if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
- return -EFAULT;
-
- buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC);
- if (!buf) {
- printk(KERN_ERR "ioctl_read_page_data: "
- "failed to allocate memory\n");
- return -ENOMEM;
- }
-
- mutex_lock(&spectra_lock);
- result = GLOB_FTL_Page_Read(buf,
- (u64)info.page * IdentifyDeviceData.PageDataSize);
- mutex_unlock(&spectra_lock);
-
- if (copy_to_user((void __user *)info.data, buf,
- IdentifyDeviceData.PageDataSize)) {
- printk(KERN_ERR "ioctl_read_page_data: "
- "failed to copy user data\n");
- kfree(buf);
- return -EFAULT;
- }
-
- kfree(buf);
- return result;
-}
-
-static int ioctl_write_page_data(unsigned long arg)
-{
- u8 *buf;
- struct ioctl_rw_page_info info;
- int result = PASS;
-
- if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
- return -EFAULT;
-
- buf = memdup_user((void __user *)info.data,
- IdentifyDeviceData.PageDataSize);
- if (IS_ERR(buf)) {
- printk(KERN_ERR "ioctl_write_page_data: "
- "failed to copy user data\n");
- return PTR_ERR(buf);
- }
-
- mutex_lock(&spectra_lock);
- result = GLOB_FTL_Page_Write(buf,
- (u64)info.page * IdentifyDeviceData.PageDataSize);
- mutex_unlock(&spectra_lock);
-
- kfree(buf);
- return result;
-}
-
-/* Return how many blocks should be reserved for bad block replacement */
-static int get_res_blk_num_bad_blk(void)
-{
- return IdentifyDeviceData.wDataBlockNum / 10;
-}
-
-/* Return how many blocks should be reserved for OS image */
-static int get_res_blk_num_os(void)
-{
- u32 res_blks, blk_size;
-
- blk_size = IdentifyDeviceData.PageDataSize *
- IdentifyDeviceData.PagesPerBlock;
-
- res_blks = (reserved_mb * 1024 * 1024) / blk_size;
-
- if ((res_blks < 1) || (res_blks >= IdentifyDeviceData.wDataBlockNum))
- res_blks = 1; /* Reserved 1 block for block table */
-
- return res_blks;
-}
-
-/* Transfer a full request. */
-static int do_transfer(struct spectra_nand_dev *tr, struct request *req)
-{
- u64 start_addr, addr;
- u32 logical_start_sect, hd_start_sect;
- u32 nsect, hd_sects;
- u32 rsect, tsect = 0;
- char *buf;
- u32 ratio = IdentifyDeviceData.PageDataSize >> 9;
-
- start_addr = (u64)(blk_rq_pos(req)) << 9;
- /* Add a big enough offset to prevent the OS Image from
- * being accessed or damaged by file system */
- start_addr += IdentifyDeviceData.PageDataSize *
- IdentifyDeviceData.PagesPerBlock *
- res_blks_os;
-
- if (req->cmd_type & REQ_FLUSH) {
- if (force_flush_cache()) /* Fail to flush cache */
- return -EIO;
- else
- return 0;
- }
-
- if (req->cmd_type != REQ_TYPE_FS)
- return -EIO;
-
- if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(tr->gd)) {
- printk(KERN_ERR "Spectra error: request over the NAND "
- "capacity!sector %d, current_nr_sectors %d, "
- "while capacity is %d\n",
- (int)blk_rq_pos(req),
- blk_rq_cur_sectors(req),
- (int)get_capacity(tr->gd));
- return -EIO;
- }
-
- logical_start_sect = start_addr >> 9;
- hd_start_sect = logical_start_sect / ratio;
- rsect = logical_start_sect - hd_start_sect * ratio;
-
- addr = (u64)hd_start_sect * ratio * 512;
- buf = req->buffer;
- nsect = blk_rq_cur_sectors(req);
-
- if (rsect)
- tsect = (ratio - rsect) < nsect ? (ratio - rsect) : nsect;
-
- switch (rq_data_dir(req)) {
- case READ:
- /* Read the first NAND page */
- if (rsect) {
- if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
- printk(KERN_ERR "Error in %s, Line %d\n",
- __FILE__, __LINE__);
- return -EIO;
- }
- memcpy(buf, tr->tmp_buf + (rsect << 9), tsect << 9);
- addr += IdentifyDeviceData.PageDataSize;
- buf += tsect << 9;
- nsect -= tsect;
- }
-
- /* Read the other NAND pages */
- for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) {
- if (GLOB_FTL_Page_Read(buf, addr)) {
- printk(KERN_ERR "Error in %s, Line %d\n",
- __FILE__, __LINE__);
- return -EIO;
- }
- addr += IdentifyDeviceData.PageDataSize;
- buf += IdentifyDeviceData.PageDataSize;
- }
-
- /* Read the last NAND pages */
- if (nsect % ratio) {
- if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
- printk(KERN_ERR "Error in %s, Line %d\n",
- __FILE__, __LINE__);
- return -EIO;
- }
- memcpy(buf, tr->tmp_buf, (nsect % ratio) << 9);
- }
-#if CMD_DMA
- if (glob_ftl_execute_cmds())
- return -EIO;
- else
- return 0;
-#endif
- return 0;
-
- case WRITE:
- /* Write the first NAND page */
- if (rsect) {
- if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
- printk(KERN_ERR "Error in %s, Line %d\n",
- __FILE__, __LINE__);
- return -EIO;
- }
- memcpy(tr->tmp_buf + (rsect << 9), buf, tsect << 9);
- if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) {
- printk(KERN_ERR "Error in %s, Line %d\n",
- __FILE__, __LINE__);
- return -EIO;
- }
- addr += IdentifyDeviceData.PageDataSize;
- buf += tsect << 9;
- nsect -= tsect;
- }
-
- /* Write the other NAND pages */
- for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) {
- if (GLOB_FTL_Page_Write(buf, addr)) {
- printk(KERN_ERR "Error in %s, Line %d\n",
- __FILE__, __LINE__);
- return -EIO;
- }
- addr += IdentifyDeviceData.PageDataSize;
- buf += IdentifyDeviceData.PageDataSize;
- }
-
- /* Write the last NAND pages */
- if (nsect % ratio) {
- if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
- printk(KERN_ERR "Error in %s, Line %d\n",
- __FILE__, __LINE__);
- return -EIO;
- }
- memcpy(tr->tmp_buf, buf, (nsect % ratio) << 9);
- if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) {
- printk(KERN_ERR "Error in %s, Line %d\n",
- __FILE__, __LINE__);
- return -EIO;
- }
- }
-#if CMD_DMA
- if (glob_ftl_execute_cmds())
- return -EIO;
- else
- return 0;
-#endif
- return 0;
-
- default:
- printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req));
- return -EIO;
- }
-}
-
-/* This function is copied from drivers/mtd/mtd_blkdevs.c */
-static int spectra_trans_thread(void *arg)
-{
- struct spectra_nand_dev *tr = arg;
- struct request_queue *rq = tr->queue;
- struct request *req = NULL;
-
- /* we might get involved when memory gets low, so use PF_MEMALLOC */
- current->flags |= PF_MEMALLOC;
-
- spin_lock_irq(rq->queue_lock);
- while (!kthread_should_stop()) {
- int res;
-
- if (!req) {
- req = blk_fetch_request(rq);
- if (!req) {
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(rq->queue_lock);
- schedule();
- spin_lock_irq(rq->queue_lock);
- continue;
- }
- }
-
- spin_unlock_irq(rq->queue_lock);
-
- mutex_lock(&spectra_lock);
- res = do_transfer(tr, req);
- mutex_unlock(&spectra_lock);
-
- spin_lock_irq(rq->queue_lock);
-
- if (!__blk_end_request_cur(req, res))
- req = NULL;
- }
-
- if (req)
- __blk_end_request_all(req, -EIO);
-
- spin_unlock_irq(rq->queue_lock);
-
- return 0;
-}
-
-
-/* Request function that "handles clustering". */
-static void GLOB_SBD_request(struct request_queue *rq)
-{
- struct spectra_nand_dev *pdev = rq->queuedata;
- wake_up_process(pdev->thread);
-}
-
-static int GLOB_SBD_open(struct block_device *bdev, fmode_t mode)
-
-{
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
- return 0;
-}
-
-static int GLOB_SBD_release(struct gendisk *disk, fmode_t mode)
-{
- int ret;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- mutex_lock(&spectra_lock);
- ret = force_flush_cache();
- mutex_unlock(&spectra_lock);
-
- return 0;
-}
-
-static int GLOB_SBD_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
- geo->heads = 4;
- geo->sectors = 16;
- geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "heads: %d, sectors: %d, cylinders: %d\n",
- geo->heads, geo->sectors, geo->cylinders);
-
- return 0;
-}
-
-int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- int ret;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- switch (cmd) {
- case GLOB_SBD_IOCTL_GC:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Spectra IOCTL: Garbage Collection "
- "being performed\n");
- if (PASS != GLOB_FTL_Garbage_Collection())
- return -EFAULT;
- return 0;
-
- case GLOB_SBD_IOCTL_WL:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Spectra IOCTL: Static Wear Leveling "
- "being performed\n");
- if (PASS != GLOB_FTL_Wear_Leveling())
- return -EFAULT;
- return 0;
-
- case GLOB_SBD_IOCTL_FORMAT:
- nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Flash format "
- "being performed\n");
- if (PASS != GLOB_FTL_Flash_Format())
- return -EFAULT;
- return 0;
-
- case GLOB_SBD_IOCTL_FLUSH_CACHE:
- nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Cache flush "
- "being performed\n");
- mutex_lock(&spectra_lock);
- ret = force_flush_cache();
- mutex_unlock(&spectra_lock);
- return ret;
-
- case GLOB_SBD_IOCTL_COPY_BLK_TABLE:
- nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
- "Copy block table\n");
- if (copy_to_user((void __user *)arg,
- get_blk_table_start_addr(),
- get_blk_table_len()))
- return -EFAULT;
- return 0;
-
- case GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE:
- nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
- "Copy wear leveling table\n");
- if (copy_to_user((void __user *)arg,
- get_wear_leveling_table_start_addr(),
- get_wear_leveling_table_len()))
- return -EFAULT;
- return 0;
-
- case GLOB_SBD_IOCTL_GET_NAND_INFO:
- nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
- "Get NAND info\n");
- if (copy_to_user((void __user *)arg, &IdentifyDeviceData,
- sizeof(IdentifyDeviceData)))
- return -EFAULT;
- return 0;
-
- case GLOB_SBD_IOCTL_WRITE_DATA:
- nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
- "Write one page data\n");
- return ioctl_write_page_data(arg);
-
- case GLOB_SBD_IOCTL_READ_DATA:
- nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
- "Read one page data\n");
- return ioctl_read_page_data(arg);
- }
-
- return -ENOTTY;
-}
-
-static DEFINE_MUTEX(ffsport_mutex);
-
-int GLOB_SBD_unlocked_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- int ret;
-
- mutex_lock(&ffsport_mutex);
- ret = GLOB_SBD_ioctl(bdev, mode, cmd, arg);
- mutex_unlock(&ffsport_mutex);
-
- return ret;
-}
-
-static struct block_device_operations GLOB_SBD_ops = {
- .owner = THIS_MODULE,
- .open = GLOB_SBD_open,
- .release = GLOB_SBD_release,
- .ioctl = GLOB_SBD_unlocked_ioctl,
- .getgeo = GLOB_SBD_getgeo,
-};
-
-static int SBD_setup_device(struct spectra_nand_dev *dev, int which)
-{
- int res_blks;
- u32 sects;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- memset(dev, 0, sizeof(struct spectra_nand_dev));
-
- nand_dbg_print(NAND_DBG_WARN, "Reserved %d blocks "
- "for OS image, %d blocks for bad block replacement.\n",
- get_res_blk_num_os(),
- get_res_blk_num_bad_blk());
-
- res_blks = get_res_blk_num_bad_blk() + get_res_blk_num_os();
-
- dev->size = (u64)IdentifyDeviceData.PageDataSize *
- IdentifyDeviceData.PagesPerBlock *
- (IdentifyDeviceData.wDataBlockNum - res_blks);
-
- res_blks_os = get_res_blk_num_os();
-
- spin_lock_init(&dev->qlock);
-
- dev->tmp_buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC);
- if (!dev->tmp_buf) {
- printk(KERN_ERR "Failed to kmalloc memory in %s Line %d, exit.\n",
- __FILE__, __LINE__);
- goto out_vfree;
- }
-
- dev->queue = blk_init_queue(GLOB_SBD_request, &dev->qlock);
- if (dev->queue == NULL) {
- printk(KERN_ERR
- "Spectra: Request queue could not be initialized."
- " Aborting\n ");
- goto out_vfree;
- }
- dev->queue->queuedata = dev;
-
- /* As Linux block layer doesn't support >4KB hardware sector, */
- /* Here we force report 512 byte hardware sector size to Kernel */
- blk_queue_logical_block_size(dev->queue, 512);
-
- blk_queue_flush(dev->queue, REQ_FLUSH);
-
- dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd");
- if (IS_ERR(dev->thread)) {
- blk_cleanup_queue(dev->queue);
- unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME);
- return PTR_ERR(dev->thread);
- }
-
- dev->gd = alloc_disk(PARTITIONS);
- if (!dev->gd) {
- printk(KERN_ERR
- "Spectra: Could not allocate disk. Aborting \n ");
- goto out_vfree;
- }
- dev->gd->major = GLOB_SBD_majornum;
- dev->gd->first_minor = which * PARTITIONS;
- dev->gd->fops = &GLOB_SBD_ops;
- dev->gd->queue = dev->queue;
- dev->gd->private_data = dev;
- snprintf(dev->gd->disk_name, 32, "%s%c", GLOB_SBD_NAME, which + 'a');
-
- sects = dev->size >> 9;
- nand_dbg_print(NAND_DBG_WARN, "Capacity sects: %d\n", sects);
- set_capacity(dev->gd, sects);
-
- add_disk(dev->gd);
-
- return 0;
-out_vfree:
- return -ENOMEM;
-}
-
-/*
-static ssize_t show_nand_block_num(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%d\n",
- (int)IdentifyDeviceData.wDataBlockNum);
-}
-
-static ssize_t show_nand_pages_per_block(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%d\n",
- (int)IdentifyDeviceData.PagesPerBlock);
-}
-
-static ssize_t show_nand_page_size(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%d\n",
- (int)IdentifyDeviceData.PageDataSize);
-}
-
-static DEVICE_ATTR(nand_block_num, 0444, show_nand_block_num, NULL);
-static DEVICE_ATTR(nand_pages_per_block, 0444, show_nand_pages_per_block, NULL);
-static DEVICE_ATTR(nand_page_size, 0444, show_nand_page_size, NULL);
-
-static void create_sysfs_entry(struct device *dev)
-{
- if (device_create_file(dev, &dev_attr_nand_block_num))
- printk(KERN_ERR "Spectra: "
- "failed to create sysfs entry nand_block_num.\n");
- if (device_create_file(dev, &dev_attr_nand_pages_per_block))
- printk(KERN_ERR "Spectra: "
- "failed to create sysfs entry nand_pages_per_block.\n");
- if (device_create_file(dev, &dev_attr_nand_page_size))
- printk(KERN_ERR "Spectra: "
- "failed to create sysfs entry nand_page_size.\n");
-}
-*/
-
-static void register_spectra_ftl_async(void *unused, async_cookie_t cookie)
-{
- int i;
-
- /* create_sysfs_entry(&dev->dev); */
-
- if (PASS != GLOB_FTL_IdentifyDevice(&IdentifyDeviceData)) {
- printk(KERN_ERR "Spectra: Unable to Read Flash Device. "
- "Aborting\n");
- return;
- } else {
- nand_dbg_print(NAND_DBG_WARN, "In GLOB_SBD_init: "
- "Num blocks=%d, pagesperblock=%d, "
- "pagedatasize=%d, ECCBytesPerSector=%d\n",
- (int)IdentifyDeviceData.NumBlocks,
- (int)IdentifyDeviceData.PagesPerBlock,
- (int)IdentifyDeviceData.PageDataSize,
- (int)IdentifyDeviceData.wECCBytesPerSector);
- }
-
- printk(KERN_ALERT "Spectra: searching block table, please wait ...\n");
- if (GLOB_FTL_Init() != PASS) {
- printk(KERN_ERR "Spectra: Unable to Initialize FTL Layer. "
- "Aborting\n");
- goto out_ftl_flash_register;
- }
- printk(KERN_ALERT "Spectra: block table has been found.\n");
-
- GLOB_SBD_majornum = register_blkdev(0, GLOB_SBD_NAME);
- if (GLOB_SBD_majornum <= 0) {
- printk(KERN_ERR "Unable to get the major %d for Spectra",
- GLOB_SBD_majornum);
- goto out_ftl_flash_register;
- }
-
- for (i = 0; i < NUM_DEVICES; i++)
- if (SBD_setup_device(&nand_device[i], i) == -ENOMEM)
- goto out_blk_register;
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Spectra: module loaded with major number %d\n",
- GLOB_SBD_majornum);
-
- return;
-
-out_blk_register:
- unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME);
-out_ftl_flash_register:
- GLOB_FTL_Cache_Release();
- printk(KERN_ERR "Spectra: Module load failed.\n");
-}
-
-int register_spectra_ftl()
-{
- async_schedule(register_spectra_ftl_async, NULL);
- return 0;
-}
-EXPORT_SYMBOL_GPL(register_spectra_ftl);
-
-static int GLOB_SBD_init(void)
-{
- /* Set debug output level (0~3) here. 3 is most verbose */
- printk(KERN_ALERT "Spectra: %s\n", GLOB_version);
-
- mutex_init(&spectra_lock);
-
- if (PASS != GLOB_FTL_Flash_Init()) {
- printk(KERN_ERR "Spectra: Unable to Initialize Flash Device. "
- "Aborting\n");
- return -ENODEV;
- }
- return 0;
-}
-
-static void __exit GLOB_SBD_exit(void)
-{
- int i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < NUM_DEVICES; i++) {
- struct spectra_nand_dev *dev = &nand_device[i];
- if (dev->gd) {
- del_gendisk(dev->gd);
- put_disk(dev->gd);
- }
- if (dev->queue)
- blk_cleanup_queue(dev->queue);
- kfree(dev->tmp_buf);
- }
-
- unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME);
-
- mutex_lock(&spectra_lock);
- force_flush_cache();
- mutex_unlock(&spectra_lock);
-
- GLOB_FTL_Cache_Release();
-
- GLOB_FTL_Flash_Release();
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Spectra FTL module (major number %d) unloaded.\n",
- GLOB_SBD_majornum);
-}
-
-module_init(GLOB_SBD_init);
-module_exit(GLOB_SBD_exit);
diff --git a/drivers/staging/spectra/ffsport.h b/drivers/staging/spectra/ffsport.h
deleted file mode 100644
index 85c0750612f6..000000000000
--- a/drivers/staging/spectra/ffsport.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef _FFSPORT_
-#define _FFSPORT_
-
-#include "ffsdefs.h"
-
-#if defined __GNUC__
-#define PACKED
-#define PACKED_GNU __attribute__ ((packed))
-#define UNALIGNED
-#endif
-
-#include <linux/semaphore.h>
-#include <linux/string.h> /* for strcpy(), stricmp(), etc */
-#include <linux/mm.h> /* for kmalloc(), kfree() */
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-
-#include <linux/kernel.h> /* printk() */
-#include <linux/fs.h> /* everything... */
-#include <linux/errno.h> /* error codes */
-#include <linux/types.h> /* size_t */
-#include <linux/genhd.h>
-#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-#include <linux/pci.h>
-#include "flash.h"
-
-#define VERBOSE 1
-
-#define NAND_DBG_WARN 1
-#define NAND_DBG_DEBUG 2
-#define NAND_DBG_TRACE 3
-
-extern int nand_debug_level;
-
-#ifdef VERBOSE
-#define nand_dbg_print(level, args...) \
- do { \
- if (level <= nand_debug_level) \
- printk(KERN_ALERT args); \
- } while (0)
-#else
-#define nand_dbg_print(level, args...)
-#endif
-
-#ifdef SUPPORT_BIG_ENDIAN
-#define INVERTUINT16(w) ((u16)(((u16)(w)) << 8) | \
- (u16)((u16)(w) >> 8))
-
-#define INVERTUINT32(dw) (((u32)(dw) << 24) | \
- (((u32)(dw) << 8) & 0x00ff0000) | \
- (((u32)(dw) >> 8) & 0x0000ff00) | \
- ((u32)(dw) >> 24))
-#else
-#define INVERTUINT16(w) w
-#define INVERTUINT32(dw) dw
-#endif
-
-extern int GLOB_Calc_Used_Bits(u32 n);
-extern u64 GLOB_u64_Div(u64 addr, u32 divisor);
-extern u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type);
-extern int register_spectra_ftl(void);
-
-#endif /* _FFSPORT_ */
diff --git a/drivers/staging/spectra/flash.c b/drivers/staging/spectra/flash.c
deleted file mode 100644
index aead358e5c2a..000000000000
--- a/drivers/staging/spectra/flash.c
+++ /dev/null
@@ -1,4305 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-
-#include "flash.h"
-#include "ffsdefs.h"
-#include "lld.h"
-#include "lld_nand.h"
-#if CMD_DMA
-#include "lld_cdma.h"
-#endif
-
-#define BLK_FROM_ADDR(addr) ((u32)(addr >> DeviceInfo.nBitsInBlockDataSize))
-#define PAGE_FROM_ADDR(addr, Block) ((u16)((addr - (u64)Block * \
- DeviceInfo.wBlockDataSize) >> DeviceInfo.nBitsInPageDataSize))
-
-#define IS_SPARE_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\
- BAD_BLOCK) && SPARE_BLOCK == (pbt[blk] & SPARE_BLOCK))
-
-#define IS_DATA_BLOCK(blk) (0 == (pbt[blk] & BAD_BLOCK))
-
-#define IS_DISCARDED_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\
- BAD_BLOCK) && DISCARD_BLOCK == (pbt[blk] & DISCARD_BLOCK))
-
-#define IS_BAD_BLOCK(blk) (BAD_BLOCK == (pbt[blk] & BAD_BLOCK))
-
-#if DEBUG_BNDRY
-void debug_boundary_lineno_error(int chnl, int limit, int no,
- int lineno, char *filename)
-{
- if (chnl >= limit)
- printk(KERN_ERR "Boundary Check Fail value %d >= limit %d, "
- "at %s:%d. Other info:%d. Aborting...\n",
- chnl, limit, filename, lineno, no);
-}
-/* static int globalmemsize; */
-#endif
-
-static u16 FTL_Cache_If_Hit(u64 dwPageAddr);
-static int FTL_Cache_Read(u64 dwPageAddr);
-static void FTL_Cache_Read_Page(u8 *pData, u64 dwPageAddr,
- u16 cache_blk);
-static void FTL_Cache_Write_Page(u8 *pData, u64 dwPageAddr,
- u8 cache_blk, u16 flag);
-static int FTL_Cache_Write(void);
-static void FTL_Calculate_LRU(void);
-static u32 FTL_Get_Block_Index(u32 wBlockNum);
-
-static int FTL_Search_Block_Table_IN_Block(u32 BT_Block,
- u8 BT_Tag, u16 *Page);
-static int FTL_Read_Block_Table(void);
-static int FTL_Write_Block_Table(int wForce);
-static int FTL_Write_Block_Table_Data(void);
-static int FTL_Check_Block_Table(int wOldTable);
-static int FTL_Static_Wear_Leveling(void);
-static u32 FTL_Replace_Block_Table(void);
-static int FTL_Write_IN_Progress_Block_Table_Page(void);
-
-static u32 FTL_Get_Page_Num(u64 length);
-static u64 FTL_Get_Physical_Block_Addr(u64 blk_addr);
-
-static u32 FTL_Replace_OneBlock(u32 wBlockNum,
- u32 wReplaceNum);
-static u32 FTL_Replace_LWBlock(u32 wBlockNum,
- int *pGarbageCollect);
-static u32 FTL_Replace_MWBlock(void);
-static int FTL_Replace_Block(u64 blk_addr);
-static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX);
-
-struct device_info_tag DeviceInfo;
-struct flash_cache_tag Cache;
-static struct spectra_l2_cache_info cache_l2;
-
-static u8 *cache_l2_page_buf;
-static u8 *cache_l2_blk_buf;
-
-u8 *g_pBlockTable;
-u8 *g_pWearCounter;
-u16 *g_pReadCounter;
-u32 *g_pBTBlocks;
-static u16 g_wBlockTableOffset;
-static u32 g_wBlockTableIndex;
-static u8 g_cBlockTableStatus;
-
-static u8 *g_pTempBuf;
-static u8 *flag_check_blk_table;
-static u8 *tmp_buf_search_bt_in_block;
-static u8 *spare_buf_search_bt_in_block;
-static u8 *spare_buf_bt_search_bt_in_block;
-static u8 *tmp_buf1_read_blk_table;
-static u8 *tmp_buf2_read_blk_table;
-static u8 *flags_static_wear_leveling;
-static u8 *tmp_buf_write_blk_table_data;
-static u8 *tmp_buf_read_disturbance;
-
-u8 *buf_read_page_main_spare;
-u8 *buf_write_page_main_spare;
-u8 *buf_read_page_spare;
-u8 *buf_get_bad_block;
-
-#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA)
-struct flash_cache_delta_list_tag int_cache[MAX_CHANS + MAX_DESCS];
-struct flash_cache_tag cache_start_copy;
-#endif
-
-int g_wNumFreeBlocks;
-u8 g_SBDCmdIndex;
-
-static u8 *g_pIPF;
-static u8 bt_flag = FIRST_BT_ID;
-static u8 bt_block_changed;
-
-static u16 cache_block_to_write;
-static u8 last_erased = FIRST_BT_ID;
-
-static u8 GC_Called;
-static u8 BT_GC_Called;
-
-#if CMD_DMA
-#define COPY_BACK_BUF_NUM 10
-
-static u8 ftl_cmd_cnt; /* Init value is 0 */
-u8 *g_pBTDelta;
-u8 *g_pBTDelta_Free;
-u8 *g_pBTStartingCopy;
-u8 *g_pWearCounterCopy;
-u16 *g_pReadCounterCopy;
-u8 *g_pBlockTableCopies;
-u8 *g_pNextBlockTable;
-static u8 *cp_back_buf_copies[COPY_BACK_BUF_NUM];
-static int cp_back_buf_idx;
-
-static u8 *g_temp_buf;
-
-#pragma pack(push, 1)
-#pragma pack(1)
-struct BTableChangesDelta {
- u8 ftl_cmd_cnt;
- u8 ValidFields;
- u16 g_wBlockTableOffset;
- u32 g_wBlockTableIndex;
- u32 BT_Index;
- u32 BT_Entry_Value;
- u32 WC_Index;
- u8 WC_Entry_Value;
- u32 RC_Index;
- u16 RC_Entry_Value;
-};
-
-#pragma pack(pop)
-
-struct BTableChangesDelta *p_BTableChangesDelta;
-#endif
-
-
-#define MARK_BLOCK_AS_BAD(blocknode) (blocknode |= BAD_BLOCK)
-#define MARK_BLK_AS_DISCARD(blk) (blk = (blk & ~SPARE_BLOCK) | DISCARD_BLOCK)
-
-#define FTL_Get_LBAPBA_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\
- sizeof(u32))
-#define FTL_Get_WearCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\
- sizeof(u8))
-#define FTL_Get_ReadCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\
- sizeof(u16))
-#if SUPPORT_LARGE_BLOCKNUM
-#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\
- sizeof(u8) * 3)
-#else
-#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\
- sizeof(u16))
-#endif
-#define FTL_Get_WearCounter_Table_Flash_Size_Bytes \
- FTL_Get_WearCounter_Table_Mem_Size_Bytes
-#define FTL_Get_ReadCounter_Table_Flash_Size_Bytes \
- FTL_Get_ReadCounter_Table_Mem_Size_Bytes
-
-static u32 FTL_Get_Block_Table_Flash_Size_Bytes(void)
-{
- u32 byte_num;
-
- if (DeviceInfo.MLCDevice) {
- byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() +
- DeviceInfo.wDataBlockNum * sizeof(u8) +
- DeviceInfo.wDataBlockNum * sizeof(u16);
- } else {
- byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() +
- DeviceInfo.wDataBlockNum * sizeof(u8);
- }
-
- byte_num += 4 * sizeof(u8);
-
- return byte_num;
-}
-
-static u16 FTL_Get_Block_Table_Flash_Size_Pages(void)
-{
- return (u16)FTL_Get_Page_Num(FTL_Get_Block_Table_Flash_Size_Bytes());
-}
-
-static int FTL_Copy_Block_Table_To_Flash(u8 *flashBuf, u32 sizeToTx,
- u32 sizeTxed)
-{
- u32 wBytesCopied, blk_tbl_size, wBytes;
- u32 *pbt = (u32 *)g_pBlockTable;
-
- blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes();
- for (wBytes = 0;
- (wBytes < sizeToTx) && ((wBytes + sizeTxed) < blk_tbl_size);
- wBytes++) {
-#if SUPPORT_LARGE_BLOCKNUM
- flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 3]
- >> (((wBytes + sizeTxed) % 3) ?
- ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)) & 0xFF;
-#else
- flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 2]
- >> (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF;
-#endif
- }
-
- sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0;
- blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes();
- wBytesCopied = wBytes;
- wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ?
- (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed);
- memcpy(flashBuf + wBytesCopied, g_pWearCounter + sizeTxed, wBytes);
-
- sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0;
-
- if (DeviceInfo.MLCDevice) {
- blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes();
- wBytesCopied += wBytes;
- for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) &&
- ((wBytes + sizeTxed) < blk_tbl_size); wBytes++)
- flashBuf[wBytes + wBytesCopied] =
- (g_pReadCounter[(wBytes + sizeTxed) / 2] >>
- (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF;
- }
-
- return wBytesCopied + wBytes;
-}
-
-static int FTL_Copy_Block_Table_From_Flash(u8 *flashBuf,
- u32 sizeToTx, u32 sizeTxed)
-{
- u32 wBytesCopied, blk_tbl_size, wBytes;
- u32 *pbt = (u32 *)g_pBlockTable;
-
- blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes();
- for (wBytes = 0; (wBytes < sizeToTx) &&
- ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) {
-#if SUPPORT_LARGE_BLOCKNUM
- if (!((wBytes + sizeTxed) % 3))
- pbt[(wBytes + sizeTxed) / 3] = 0;
- pbt[(wBytes + sizeTxed) / 3] |=
- (flashBuf[wBytes] << (((wBytes + sizeTxed) % 3) ?
- ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16));
-#else
- if (!((wBytes + sizeTxed) % 2))
- pbt[(wBytes + sizeTxed) / 2] = 0;
- pbt[(wBytes + sizeTxed) / 2] |=
- (flashBuf[wBytes] << (((wBytes + sizeTxed) % 2) ?
- 0 : 8));
-#endif
- }
-
- sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0;
- blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes();
- wBytesCopied = wBytes;
- wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ?
- (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed);
- memcpy(g_pWearCounter + sizeTxed, flashBuf + wBytesCopied, wBytes);
- sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0;
-
- if (DeviceInfo.MLCDevice) {
- wBytesCopied += wBytes;
- blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes();
- for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) &&
- ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) {
- if (((wBytes + sizeTxed) % 2))
- g_pReadCounter[(wBytes + sizeTxed) / 2] = 0;
- g_pReadCounter[(wBytes + sizeTxed) / 2] |=
- (flashBuf[wBytes] <<
- (((wBytes + sizeTxed) % 2) ? 0 : 8));
- }
- }
-
- return wBytesCopied+wBytes;
-}
-
-static int FTL_Insert_Block_Table_Signature(u8 *buf, u8 tag)
-{
- int i;
-
- for (i = 0; i < BTSIG_BYTES; i++)
- buf[BTSIG_OFFSET + i] =
- ((tag + (i * BTSIG_DELTA) - FIRST_BT_ID) %
- (1 + LAST_BT_ID-FIRST_BT_ID)) + FIRST_BT_ID;
-
- return PASS;
-}
-
-static int FTL_Extract_Block_Table_Tag(u8 *buf, u8 **tagarray)
-{
- static u8 tag[BTSIG_BYTES >> 1];
- int i, j, k, tagi, tagtemp, status;
-
- *tagarray = (u8 *)tag;
- tagi = 0;
-
- for (i = 0; i < (BTSIG_BYTES - 1); i++) {
- for (j = i + 1; (j < BTSIG_BYTES) &&
- (tagi < (BTSIG_BYTES >> 1)); j++) {
- tagtemp = buf[BTSIG_OFFSET + j] -
- buf[BTSIG_OFFSET + i];
- if (tagtemp && !(tagtemp % BTSIG_DELTA)) {
- tagtemp = (buf[BTSIG_OFFSET + i] +
- (1 + LAST_BT_ID - FIRST_BT_ID) -
- (i * BTSIG_DELTA)) %
- (1 + LAST_BT_ID - FIRST_BT_ID);
- status = FAIL;
- for (k = 0; k < tagi; k++) {
- if (tagtemp == tag[k])
- status = PASS;
- }
-
- if (status == FAIL) {
- tag[tagi++] = tagtemp;
- i = (j == (i + 1)) ? i + 1 : i;
- j = (j == (i + 1)) ? i + 1 : i;
- }
- }
- }
- }
-
- return tagi;
-}
-
-
-static int FTL_Execute_SPL_Recovery(void)
-{
- u32 j, block, blks;
- u32 *pbt = (u32 *)g_pBlockTable;
- int ret;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- blks = DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock;
- for (j = 0; j <= blks; j++) {
- block = (pbt[j]);
- if (((block & BAD_BLOCK) != BAD_BLOCK) &&
- ((block & SPARE_BLOCK) == SPARE_BLOCK)) {
- ret = GLOB_LLD_Erase_Block(block & ~BAD_BLOCK);
- if (FAIL == ret) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, new Bad Block %d "
- "generated!\n",
- __FILE__, __LINE__, __func__,
- (int)(block & ~BAD_BLOCK));
- MARK_BLOCK_AS_BAD(pbt[j]);
- }
- }
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_IdentifyDevice
-* Inputs: pointer to identify data structure
-* Outputs: PASS / FAIL
-* Description: the identify data structure is filled in with
-* information for the block driver.
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- dev_data->NumBlocks = DeviceInfo.wTotalBlocks;
- dev_data->PagesPerBlock = DeviceInfo.wPagesPerBlock;
- dev_data->PageDataSize = DeviceInfo.wPageDataSize;
- dev_data->wECCBytesPerSector = DeviceInfo.wECCBytesPerSector;
- dev_data->wDataBlockNum = DeviceInfo.wDataBlockNum;
-
- return PASS;
-}
-
-/* ..... */
-static int allocate_memory(void)
-{
- u32 block_table_size, page_size, block_size, mem_size;
- u32 total_bytes = 0;
- int i;
-#if CMD_DMA
- int j;
-#endif
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- page_size = DeviceInfo.wPageSize;
- block_size = DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize;
-
- block_table_size = DeviceInfo.wDataBlockNum *
- (sizeof(u32) + sizeof(u8) + sizeof(u16));
- block_table_size += (DeviceInfo.wPageDataSize -
- (block_table_size % DeviceInfo.wPageDataSize)) %
- DeviceInfo.wPageDataSize;
-
- /* Malloc memory for block tables */
- g_pBlockTable = kzalloc(block_table_size, GFP_ATOMIC);
- if (!g_pBlockTable)
- goto block_table_fail;
- total_bytes += block_table_size;
-
- g_pWearCounter = (u8 *)(g_pBlockTable +
- DeviceInfo.wDataBlockNum * sizeof(u32));
-
- if (DeviceInfo.MLCDevice)
- g_pReadCounter = (u16 *)(g_pBlockTable +
- DeviceInfo.wDataBlockNum *
- (sizeof(u32) + sizeof(u8)));
-
- /* Malloc memory and init for cache items */
- for (i = 0; i < CACHE_ITEM_NUM; i++) {
- Cache.array[i].address = NAND_CACHE_INIT_ADDR;
- Cache.array[i].use_cnt = 0;
- Cache.array[i].changed = CLEAR;
- Cache.array[i].buf = kzalloc(Cache.cache_item_size,
- GFP_ATOMIC);
- if (!Cache.array[i].buf)
- goto cache_item_fail;
- total_bytes += Cache.cache_item_size;
- }
-
- /* Malloc memory for IPF */
- g_pIPF = kzalloc(page_size, GFP_ATOMIC);
- if (!g_pIPF)
- goto ipf_fail;
- total_bytes += page_size;
-
- /* Malloc memory for data merging during Level2 Cache flush */
- cache_l2_page_buf = kmalloc(page_size, GFP_ATOMIC);
- if (!cache_l2_page_buf)
- goto cache_l2_page_buf_fail;
- memset(cache_l2_page_buf, 0xff, page_size);
- total_bytes += page_size;
-
- cache_l2_blk_buf = kmalloc(block_size, GFP_ATOMIC);
- if (!cache_l2_blk_buf)
- goto cache_l2_blk_buf_fail;
- memset(cache_l2_blk_buf, 0xff, block_size);
- total_bytes += block_size;
-
- /* Malloc memory for temp buffer */
- g_pTempBuf = kzalloc(Cache.cache_item_size, GFP_ATOMIC);
- if (!g_pTempBuf)
- goto Temp_buf_fail;
- total_bytes += Cache.cache_item_size;
-
- /* Malloc memory for block table blocks */
- mem_size = (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32);
- g_pBTBlocks = kmalloc(mem_size, GFP_ATOMIC);
- if (!g_pBTBlocks)
- goto bt_blocks_fail;
- memset(g_pBTBlocks, 0xff, mem_size);
- total_bytes += mem_size;
-
- /* Malloc memory for function FTL_Check_Block_Table */
- flag_check_blk_table = kmalloc(DeviceInfo.wDataBlockNum, GFP_ATOMIC);
- if (!flag_check_blk_table)
- goto flag_check_blk_table_fail;
- total_bytes += DeviceInfo.wDataBlockNum;
-
- /* Malloc memory for function FTL_Search_Block_Table_IN_Block */
- tmp_buf_search_bt_in_block = kmalloc(page_size, GFP_ATOMIC);
- if (!tmp_buf_search_bt_in_block)
- goto tmp_buf_search_bt_in_block_fail;
- memset(tmp_buf_search_bt_in_block, 0xff, page_size);
- total_bytes += page_size;
-
- mem_size = DeviceInfo.wPageSize - DeviceInfo.wPageDataSize;
- spare_buf_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC);
- if (!spare_buf_search_bt_in_block)
- goto spare_buf_search_bt_in_block_fail;
- memset(spare_buf_search_bt_in_block, 0xff, mem_size);
- total_bytes += mem_size;
-
- spare_buf_bt_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC);
- if (!spare_buf_bt_search_bt_in_block)
- goto spare_buf_bt_search_bt_in_block_fail;
- memset(spare_buf_bt_search_bt_in_block, 0xff, mem_size);
- total_bytes += mem_size;
-
- /* Malloc memory for function FTL_Read_Block_Table */
- tmp_buf1_read_blk_table = kmalloc(page_size, GFP_ATOMIC);
- if (!tmp_buf1_read_blk_table)
- goto tmp_buf1_read_blk_table_fail;
- memset(tmp_buf1_read_blk_table, 0xff, page_size);
- total_bytes += page_size;
-
- tmp_buf2_read_blk_table = kmalloc(page_size, GFP_ATOMIC);
- if (!tmp_buf2_read_blk_table)
- goto tmp_buf2_read_blk_table_fail;
- memset(tmp_buf2_read_blk_table, 0xff, page_size);
- total_bytes += page_size;
-
- /* Malloc memory for function FTL_Static_Wear_Leveling */
- flags_static_wear_leveling = kmalloc(DeviceInfo.wDataBlockNum,
- GFP_ATOMIC);
- if (!flags_static_wear_leveling)
- goto flags_static_wear_leveling_fail;
- total_bytes += DeviceInfo.wDataBlockNum;
-
- /* Malloc memory for function FTL_Write_Block_Table_Data */
- if (FTL_Get_Block_Table_Flash_Size_Pages() > 3)
- mem_size = FTL_Get_Block_Table_Flash_Size_Bytes() -
- 2 * DeviceInfo.wPageSize;
- else
- mem_size = DeviceInfo.wPageSize;
- tmp_buf_write_blk_table_data = kmalloc(mem_size, GFP_ATOMIC);
- if (!tmp_buf_write_blk_table_data)
- goto tmp_buf_write_blk_table_data_fail;
- memset(tmp_buf_write_blk_table_data, 0xff, mem_size);
- total_bytes += mem_size;
-
- /* Malloc memory for function FTL_Read_Disturbance */
- tmp_buf_read_disturbance = kmalloc(block_size, GFP_ATOMIC);
- if (!tmp_buf_read_disturbance)
- goto tmp_buf_read_disturbance_fail;
- memset(tmp_buf_read_disturbance, 0xff, block_size);
- total_bytes += block_size;
-
- /* Alloc mem for function NAND_Read_Page_Main_Spare of lld_nand.c */
- buf_read_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC);
- if (!buf_read_page_main_spare)
- goto buf_read_page_main_spare_fail;
- total_bytes += DeviceInfo.wPageSize;
-
- /* Alloc mem for function NAND_Write_Page_Main_Spare of lld_nand.c */
- buf_write_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC);
- if (!buf_write_page_main_spare)
- goto buf_write_page_main_spare_fail;
- total_bytes += DeviceInfo.wPageSize;
-
- /* Alloc mem for function NAND_Read_Page_Spare of lld_nand.c */
- buf_read_page_spare = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC);
- if (!buf_read_page_spare)
- goto buf_read_page_spare_fail;
- memset(buf_read_page_spare, 0xff, DeviceInfo.wPageSpareSize);
- total_bytes += DeviceInfo.wPageSpareSize;
-
- /* Alloc mem for function NAND_Get_Bad_Block of lld_nand.c */
- buf_get_bad_block = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC);
- if (!buf_get_bad_block)
- goto buf_get_bad_block_fail;
- memset(buf_get_bad_block, 0xff, DeviceInfo.wPageSpareSize);
- total_bytes += DeviceInfo.wPageSpareSize;
-
-#if CMD_DMA
- g_temp_buf = kmalloc(block_size, GFP_ATOMIC);
- if (!g_temp_buf)
- goto temp_buf_fail;
- memset(g_temp_buf, 0xff, block_size);
- total_bytes += block_size;
-
- /* Malloc memory for copy of block table used in CDMA mode */
- g_pBTStartingCopy = kzalloc(block_table_size, GFP_ATOMIC);
- if (!g_pBTStartingCopy)
- goto bt_starting_copy;
- total_bytes += block_table_size;
-
- g_pWearCounterCopy = (u8 *)(g_pBTStartingCopy +
- DeviceInfo.wDataBlockNum * sizeof(u32));
-
- if (DeviceInfo.MLCDevice)
- g_pReadCounterCopy = (u16 *)(g_pBTStartingCopy +
- DeviceInfo.wDataBlockNum *
- (sizeof(u32) + sizeof(u8)));
-
- /* Malloc memory for block table copies */
- mem_size = 5 * DeviceInfo.wDataBlockNum * sizeof(u32) +
- 5 * DeviceInfo.wDataBlockNum * sizeof(u8);
- if (DeviceInfo.MLCDevice)
- mem_size += 5 * DeviceInfo.wDataBlockNum * sizeof(u16);
- g_pBlockTableCopies = kzalloc(mem_size, GFP_ATOMIC);
- if (!g_pBlockTableCopies)
- goto blk_table_copies_fail;
- total_bytes += mem_size;
- g_pNextBlockTable = g_pBlockTableCopies;
-
- /* Malloc memory for Block Table Delta */
- mem_size = MAX_DESCS * sizeof(struct BTableChangesDelta);
- g_pBTDelta = kzalloc(mem_size, GFP_ATOMIC);
- if (!g_pBTDelta)
- goto bt_delta_fail;
- total_bytes += mem_size;
- g_pBTDelta_Free = g_pBTDelta;
-
- /* Malloc memory for Copy Back Buffers */
- for (j = 0; j < COPY_BACK_BUF_NUM; j++) {
- cp_back_buf_copies[j] = kzalloc(block_size, GFP_ATOMIC);
- if (!cp_back_buf_copies[j])
- goto cp_back_buf_copies_fail;
- total_bytes += block_size;
- }
- cp_back_buf_idx = 0;
-
- /* Malloc memory for pending commands list */
- mem_size = sizeof(struct pending_cmd) * MAX_DESCS;
- info.pcmds = kzalloc(mem_size, GFP_KERNEL);
- if (!info.pcmds)
- goto pending_cmds_buf_fail;
- total_bytes += mem_size;
-
- /* Malloc memory for CDMA descripter table */
- mem_size = sizeof(struct cdma_descriptor) * MAX_DESCS;
- info.cdma_desc_buf = kzalloc(mem_size, GFP_KERNEL);
- if (!info.cdma_desc_buf)
- goto cdma_desc_buf_fail;
- total_bytes += mem_size;
-
- /* Malloc memory for Memcpy descripter table */
- mem_size = sizeof(struct memcpy_descriptor) * MAX_DESCS;
- info.memcp_desc_buf = kzalloc(mem_size, GFP_KERNEL);
- if (!info.memcp_desc_buf)
- goto memcp_desc_buf_fail;
- total_bytes += mem_size;
-#endif
-
- nand_dbg_print(NAND_DBG_WARN,
- "Total memory allocated in FTL layer: %d\n", total_bytes);
-
- return PASS;
-
-#if CMD_DMA
-memcp_desc_buf_fail:
- kfree(info.cdma_desc_buf);
-cdma_desc_buf_fail:
- kfree(info.pcmds);
-pending_cmds_buf_fail:
-cp_back_buf_copies_fail:
- j--;
- for (; j >= 0; j--)
- kfree(cp_back_buf_copies[j]);
- kfree(g_pBTDelta);
-bt_delta_fail:
- kfree(g_pBlockTableCopies);
-blk_table_copies_fail:
- kfree(g_pBTStartingCopy);
-bt_starting_copy:
- kfree(g_temp_buf);
-temp_buf_fail:
- kfree(buf_get_bad_block);
-#endif
-
-buf_get_bad_block_fail:
- kfree(buf_read_page_spare);
-buf_read_page_spare_fail:
- kfree(buf_write_page_main_spare);
-buf_write_page_main_spare_fail:
- kfree(buf_read_page_main_spare);
-buf_read_page_main_spare_fail:
- kfree(tmp_buf_read_disturbance);
-tmp_buf_read_disturbance_fail:
- kfree(tmp_buf_write_blk_table_data);
-tmp_buf_write_blk_table_data_fail:
- kfree(flags_static_wear_leveling);
-flags_static_wear_leveling_fail:
- kfree(tmp_buf2_read_blk_table);
-tmp_buf2_read_blk_table_fail:
- kfree(tmp_buf1_read_blk_table);
-tmp_buf1_read_blk_table_fail:
- kfree(spare_buf_bt_search_bt_in_block);
-spare_buf_bt_search_bt_in_block_fail:
- kfree(spare_buf_search_bt_in_block);
-spare_buf_search_bt_in_block_fail:
- kfree(tmp_buf_search_bt_in_block);
-tmp_buf_search_bt_in_block_fail:
- kfree(flag_check_blk_table);
-flag_check_blk_table_fail:
- kfree(g_pBTBlocks);
-bt_blocks_fail:
- kfree(g_pTempBuf);
-Temp_buf_fail:
- kfree(cache_l2_blk_buf);
-cache_l2_blk_buf_fail:
- kfree(cache_l2_page_buf);
-cache_l2_page_buf_fail:
- kfree(g_pIPF);
-ipf_fail:
-cache_item_fail:
- i--;
- for (; i >= 0; i--)
- kfree(Cache.array[i].buf);
- kfree(g_pBlockTable);
-block_table_fail:
- printk(KERN_ERR "Failed to kmalloc memory in %s Line %d.\n",
- __FILE__, __LINE__);
-
- return -ENOMEM;
-}
-
-/* .... */
-static int free_memory(void)
-{
- int i;
-
-#if CMD_DMA
- kfree(info.memcp_desc_buf);
- kfree(info.cdma_desc_buf);
- kfree(info.pcmds);
- for (i = COPY_BACK_BUF_NUM - 1; i >= 0; i--)
- kfree(cp_back_buf_copies[i]);
- kfree(g_pBTDelta);
- kfree(g_pBlockTableCopies);
- kfree(g_pBTStartingCopy);
- kfree(g_temp_buf);
- kfree(buf_get_bad_block);
-#endif
- kfree(buf_read_page_spare);
- kfree(buf_write_page_main_spare);
- kfree(buf_read_page_main_spare);
- kfree(tmp_buf_read_disturbance);
- kfree(tmp_buf_write_blk_table_data);
- kfree(flags_static_wear_leveling);
- kfree(tmp_buf2_read_blk_table);
- kfree(tmp_buf1_read_blk_table);
- kfree(spare_buf_bt_search_bt_in_block);
- kfree(spare_buf_search_bt_in_block);
- kfree(tmp_buf_search_bt_in_block);
- kfree(flag_check_blk_table);
- kfree(g_pBTBlocks);
- kfree(g_pTempBuf);
- kfree(g_pIPF);
- for (i = CACHE_ITEM_NUM - 1; i >= 0; i--)
- kfree(Cache.array[i].buf);
- kfree(g_pBlockTable);
-
- return 0;
-}
-
-static void dump_cache_l2_table(void)
-{
- struct list_head *p;
- struct spectra_l2_cache_list *pnd;
- int n;
-
- n = 0;
- list_for_each(p, &cache_l2.table.list) {
- pnd = list_entry(p, struct spectra_l2_cache_list, list);
- nand_dbg_print(NAND_DBG_WARN, "dump_cache_l2_table node: %d, logical_blk_num: %d\n", n, pnd->logical_blk_num);
-/*
- for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) {
- if (pnd->pages_array[i] != MAX_U32_VALUE)
- nand_dbg_print(NAND_DBG_WARN, " pages_array[%d]: 0x%x\n", i, pnd->pages_array[i]);
- }
-*/
- n++;
- }
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Init
-* Inputs: none
-* Outputs: PASS=0 / FAIL=1
-* Description: allocates the memory for cache array,
-* important data structures
-* clears the cache array
-* reads the block table from flash into array
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Init(void)
-{
- int i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- Cache.pages_per_item = 1;
- Cache.cache_item_size = 1 * DeviceInfo.wPageDataSize;
-
- if (allocate_memory() != PASS)
- return FAIL;
-
-#if CMD_DMA
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- memcpy((void *)&cache_start_copy, (void *)&Cache,
- sizeof(struct flash_cache_tag));
- memset((void *)&int_cache, -1,
- sizeof(struct flash_cache_delta_list_tag) *
- (MAX_CHANS + MAX_DESCS));
-#endif
- ftl_cmd_cnt = 0;
-#endif
-
- if (FTL_Read_Block_Table() != PASS)
- return FAIL;
-
- /* Init the Level2 Cache data structure */
- for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++)
- cache_l2.blk_array[i] = MAX_U32_VALUE;
- cache_l2.cur_blk_idx = 0;
- cache_l2.cur_page_num = 0;
- INIT_LIST_HEAD(&cache_l2.table.list);
- cache_l2.table.logical_blk_num = MAX_U32_VALUE;
-
- dump_cache_l2_table();
-
- return 0;
-}
-
-
-#if CMD_DMA
-#if 0
-static void save_blk_table_changes(u16 idx)
-{
- u8 ftl_cmd;
- u32 *pbt = (u32 *)g_pBTStartingCopy;
-
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- u16 id;
- u8 cache_blks;
-
- id = idx - MAX_CHANS;
- if (int_cache[id].item != -1) {
- cache_blks = int_cache[id].item;
- cache_start_copy.array[cache_blks].address =
- int_cache[id].cache.address;
- cache_start_copy.array[cache_blks].changed =
- int_cache[id].cache.changed;
- }
-#endif
-
- ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
-
- while (ftl_cmd <= PendingCMD[idx].Tag) {
- if (p_BTableChangesDelta->ValidFields == 0x01) {
- g_wBlockTableOffset =
- p_BTableChangesDelta->g_wBlockTableOffset;
- } else if (p_BTableChangesDelta->ValidFields == 0x0C) {
- pbt[p_BTableChangesDelta->BT_Index] =
- p_BTableChangesDelta->BT_Entry_Value;
- debug_boundary_error(((
- p_BTableChangesDelta->BT_Index)),
- DeviceInfo.wDataBlockNum, 0);
- } else if (p_BTableChangesDelta->ValidFields == 0x03) {
- g_wBlockTableOffset =
- p_BTableChangesDelta->g_wBlockTableOffset;
- g_wBlockTableIndex =
- p_BTableChangesDelta->g_wBlockTableIndex;
- } else if (p_BTableChangesDelta->ValidFields == 0x30) {
- g_pWearCounterCopy[p_BTableChangesDelta->WC_Index] =
- p_BTableChangesDelta->WC_Entry_Value;
- } else if ((DeviceInfo.MLCDevice) &&
- (p_BTableChangesDelta->ValidFields == 0xC0)) {
- g_pReadCounterCopy[p_BTableChangesDelta->RC_Index] =
- p_BTableChangesDelta->RC_Entry_Value;
- nand_dbg_print(NAND_DBG_DEBUG,
- "In event status setting read counter "
- "GLOB_ftl_cmd_cnt %u Count %u Index %u\n",
- ftl_cmd,
- p_BTableChangesDelta->RC_Entry_Value,
- (unsigned int)p_BTableChangesDelta->RC_Index);
- } else {
- nand_dbg_print(NAND_DBG_DEBUG,
- "This should never occur \n");
- }
- p_BTableChangesDelta += 1;
- ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
- }
-}
-
-static void discard_cmds(u16 n)
-{
- u32 *pbt = (u32 *)g_pBTStartingCopy;
- u8 ftl_cmd;
- unsigned long k;
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- u8 cache_blks;
- u16 id;
-#endif
-
- if ((PendingCMD[n].CMD == WRITE_MAIN_CMD) ||
- (PendingCMD[n].CMD == WRITE_MAIN_SPARE_CMD)) {
- for (k = 0; k < DeviceInfo.wDataBlockNum; k++) {
- if (PendingCMD[n].Block == (pbt[k] & (~BAD_BLOCK)))
- MARK_BLK_AS_DISCARD(pbt[k]);
- }
- }
-
- ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
- while (ftl_cmd <= PendingCMD[n].Tag) {
- p_BTableChangesDelta += 1;
- ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
- }
-
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- id = n - MAX_CHANS;
-
- if (int_cache[id].item != -1) {
- cache_blks = int_cache[id].item;
- if (PendingCMD[n].CMD == MEMCOPY_CMD) {
- if ((cache_start_copy.array[cache_blks].buf <=
- PendingCMD[n].DataDestAddr) &&
- ((cache_start_copy.array[cache_blks].buf +
- Cache.cache_item_size) >
- PendingCMD[n].DataDestAddr)) {
- cache_start_copy.array[cache_blks].address =
- NAND_CACHE_INIT_ADDR;
- cache_start_copy.array[cache_blks].use_cnt =
- 0;
- cache_start_copy.array[cache_blks].changed =
- CLEAR;
- }
- } else {
- cache_start_copy.array[cache_blks].address =
- int_cache[id].cache.address;
- cache_start_copy.array[cache_blks].changed =
- int_cache[id].cache.changed;
- }
- }
-#endif
-}
-
-static void process_cmd_pass(int *first_failed_cmd, u16 idx)
-{
- if (0 == *first_failed_cmd)
- save_blk_table_changes(idx);
- else
- discard_cmds(idx);
-}
-
-static void process_cmd_fail_abort(int *first_failed_cmd,
- u16 idx, int event)
-{
- u32 *pbt = (u32 *)g_pBTStartingCopy;
- u8 ftl_cmd;
- unsigned long i;
- int erase_fail, program_fail;
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- u8 cache_blks;
- u16 id;
-#endif
-
- if (0 == *first_failed_cmd)
- *first_failed_cmd = PendingCMD[idx].SBDCmdIndex;
-
- nand_dbg_print(NAND_DBG_DEBUG, "Uncorrectable error has occurred "
- "while executing %u Command %u accesing Block %u\n",
- (unsigned int)p_BTableChangesDelta->ftl_cmd_cnt,
- PendingCMD[idx].CMD,
- (unsigned int)PendingCMD[idx].Block);
-
- ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
- while (ftl_cmd <= PendingCMD[idx].Tag) {
- p_BTableChangesDelta += 1;
- ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
- }
-
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- id = idx - MAX_CHANS;
-
- if (int_cache[id].item != -1) {
- cache_blks = int_cache[id].item;
- if ((PendingCMD[idx].CMD == WRITE_MAIN_CMD)) {
- cache_start_copy.array[cache_blks].address =
- int_cache[id].cache.address;
- cache_start_copy.array[cache_blks].changed = SET;
- } else if ((PendingCMD[idx].CMD == READ_MAIN_CMD)) {
- cache_start_copy.array[cache_blks].address =
- NAND_CACHE_INIT_ADDR;
- cache_start_copy.array[cache_blks].use_cnt = 0;
- cache_start_copy.array[cache_blks].changed =
- CLEAR;
- } else if (PendingCMD[idx].CMD == ERASE_CMD) {
- /* ? */
- } else if (PendingCMD[idx].CMD == MEMCOPY_CMD) {
- /* ? */
- }
- }
-#endif
-
- erase_fail = (event == EVENT_ERASE_FAILURE) &&
- (PendingCMD[idx].CMD == ERASE_CMD);
-
- program_fail = (event == EVENT_PROGRAM_FAILURE) &&
- ((PendingCMD[idx].CMD == WRITE_MAIN_CMD) ||
- (PendingCMD[idx].CMD == WRITE_MAIN_SPARE_CMD));
-
- if (erase_fail || program_fail) {
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- if (PendingCMD[idx].Block ==
- (pbt[i] & (~BAD_BLOCK)))
- MARK_BLOCK_AS_BAD(pbt[i]);
- }
- }
-}
-
-static void process_cmd(int *first_failed_cmd, u16 idx, int event)
-{
- u8 ftl_cmd;
- int cmd_match = 0;
-
- if (p_BTableChangesDelta->ftl_cmd_cnt == PendingCMD[idx].Tag)
- cmd_match = 1;
-
- if (PendingCMD[idx].Status == CMD_PASS) {
- process_cmd_pass(first_failed_cmd, idx);
- } else if ((PendingCMD[idx].Status == CMD_FAIL) ||
- (PendingCMD[idx].Status == CMD_ABORT)) {
- process_cmd_fail_abort(first_failed_cmd, idx, event);
- } else if ((PendingCMD[idx].Status == CMD_NOT_DONE) &&
- PendingCMD[idx].Tag) {
- nand_dbg_print(NAND_DBG_DEBUG,
- " Command no. %hu is not executed\n",
- (unsigned int)PendingCMD[idx].Tag);
- ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
- while (ftl_cmd <= PendingCMD[idx].Tag) {
- p_BTableChangesDelta += 1;
- ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
- }
- }
-}
-#endif
-
-static void process_cmd(int *first_failed_cmd, u16 idx, int event)
-{
- printk(KERN_ERR "temporary workaround function. "
- "Should not be called! \n");
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Event_Status
-* Inputs: none
-* Outputs: Event Code
-* Description: It is called by SBD after hardware interrupt signalling
-* completion of commands chain
-* It does following things
-* get event status from LLD
-* analyze command chain status
-* determine last command executed
-* analyze results
-* rebuild the block table in case of uncorrectable error
-* return event code
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Event_Status(int *first_failed_cmd)
-{
- int event_code = PASS;
- u16 i_P;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- *first_failed_cmd = 0;
-
- event_code = GLOB_LLD_Event_Status();
-
- switch (event_code) {
- case EVENT_PASS:
- nand_dbg_print(NAND_DBG_DEBUG, "Handling EVENT_PASS\n");
- break;
- case EVENT_UNCORRECTABLE_DATA_ERROR:
- nand_dbg_print(NAND_DBG_DEBUG, "Handling Uncorrectable ECC!\n");
- break;
- case EVENT_PROGRAM_FAILURE:
- case EVENT_ERASE_FAILURE:
- nand_dbg_print(NAND_DBG_WARN, "Handling Ugly case. "
- "Event code: 0x%x\n", event_code);
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta;
- for (i_P = MAX_CHANS; i_P < (ftl_cmd_cnt + MAX_CHANS);
- i_P++)
- process_cmd(first_failed_cmd, i_P, event_code);
- memcpy(g_pBlockTable, g_pBTStartingCopy,
- DeviceInfo.wDataBlockNum * sizeof(u32));
- memcpy(g_pWearCounter, g_pWearCounterCopy,
- DeviceInfo.wDataBlockNum * sizeof(u8));
- if (DeviceInfo.MLCDevice)
- memcpy(g_pReadCounter, g_pReadCounterCopy,
- DeviceInfo.wDataBlockNum * sizeof(u16));
-
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- memcpy((void *)&Cache, (void *)&cache_start_copy,
- sizeof(struct flash_cache_tag));
- memset((void *)&int_cache, -1,
- sizeof(struct flash_cache_delta_list_tag) *
- (MAX_DESCS + MAX_CHANS));
-#endif
- break;
- default:
- nand_dbg_print(NAND_DBG_WARN,
- "Handling unexpected event code - 0x%x\n",
- event_code);
- event_code = ERR;
- break;
- }
-
- memcpy(g_pBTStartingCopy, g_pBlockTable,
- DeviceInfo.wDataBlockNum * sizeof(u32));
- memcpy(g_pWearCounterCopy, g_pWearCounter,
- DeviceInfo.wDataBlockNum * sizeof(u8));
- if (DeviceInfo.MLCDevice)
- memcpy(g_pReadCounterCopy, g_pReadCounter,
- DeviceInfo.wDataBlockNum * sizeof(u16));
-
- g_pBTDelta_Free = g_pBTDelta;
- ftl_cmd_cnt = 0;
- g_pNextBlockTable = g_pBlockTableCopies;
- cp_back_buf_idx = 0;
-
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- memcpy((void *)&cache_start_copy, (void *)&Cache,
- sizeof(struct flash_cache_tag));
- memset((void *)&int_cache, -1,
- sizeof(struct flash_cache_delta_list_tag) *
- (MAX_DESCS + MAX_CHANS));
-#endif
-
- return event_code;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: glob_ftl_execute_cmds
-* Inputs: none
-* Outputs: none
-* Description: pass thru to LLD
-***************************************************************/
-u16 glob_ftl_execute_cmds(void)
-{
- nand_dbg_print(NAND_DBG_TRACE,
- "glob_ftl_execute_cmds: ftl_cmd_cnt %u\n",
- (unsigned int)ftl_cmd_cnt);
- g_SBDCmdIndex = 0;
- return glob_lld_execute_cmds();
-}
-
-#endif
-
-#if !CMD_DMA
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Read Immediate
-* Inputs: pointer to data
-* address of data
-* Outputs: PASS / FAIL
-* Description: Reads one page of data into RAM directly from flash without
-* using or disturbing cache.It is assumed this function is called
-* with CMD-DMA disabled.
-*****************************************************************/
-int GLOB_FTL_Read_Immediate(u8 *read_data, u64 addr)
-{
- int wResult = FAIL;
- u32 Block;
- u16 Page;
- u32 phy_blk;
- u32 *pbt = (u32 *)g_pBlockTable;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- Block = BLK_FROM_ADDR(addr);
- Page = PAGE_FROM_ADDR(addr, Block);
-
- if (!IS_SPARE_BLOCK(Block))
- return FAIL;
-
- phy_blk = pbt[Block];
- wResult = GLOB_LLD_Read_Page_Main(read_data, phy_blk, Page, 1);
-
- if (DeviceInfo.MLCDevice) {
- g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock]++;
- if (g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock]
- >= MAX_READ_COUNTER)
- FTL_Read_Disturbance(phy_blk);
- if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) {
- g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
- FTL_Write_IN_Progress_Block_Table_Page();
- }
- }
-
- return wResult;
-}
-#endif
-
-#ifdef SUPPORT_BIG_ENDIAN
-/*********************************************************************
-* Function: FTL_Invert_Block_Table
-* Inputs: none
-* Outputs: none
-* Description: Re-format the block table in ram based on BIG_ENDIAN and
-* LARGE_BLOCKNUM if necessary
-**********************************************************************/
-static void FTL_Invert_Block_Table(void)
-{
- u32 i;
- u32 *pbt = (u32 *)g_pBlockTable;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
-#ifdef SUPPORT_LARGE_BLOCKNUM
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- pbt[i] = INVERTUINT32(pbt[i]);
- g_pWearCounter[i] = INVERTUINT32(g_pWearCounter[i]);
- }
-#else
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- pbt[i] = INVERTUINT16(pbt[i]);
- g_pWearCounter[i] = INVERTUINT16(g_pWearCounter[i]);
- }
-#endif
-}
-#endif
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Flash_Init
-* Inputs: none
-* Outputs: PASS=0 / FAIL=0x01 (based on read ID)
-* Description: The flash controller is initialized
-* The flash device is reset
-* Perform a flash READ ID command to confirm that a
-* valid device is attached and active.
-* The DeviceInfo structure gets filled in
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Flash_Init(void)
-{
- int status = FAIL;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- g_SBDCmdIndex = 0;
-
- status = GLOB_LLD_Flash_Init();
-
- return status;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Inputs: none
-* Outputs: PASS=0 / FAIL=0x01 (based on read ID)
-* Description: The flash controller is released
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Flash_Release(void)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- return GLOB_LLD_Flash_Release();
-}
-
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Cache_Release
-* Inputs: none
-* Outputs: none
-* Description: release all allocated memory in GLOB_FTL_Init
-* (allocated in GLOB_FTL_Init)
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-void GLOB_FTL_Cache_Release(void)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- free_memory();
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Cache_If_Hit
-* Inputs: Page Address
-* Outputs: Block number/UNHIT BLOCK
-* Description: Determines if the addressed page is in cache
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static u16 FTL_Cache_If_Hit(u64 page_addr)
-{
- u16 item;
- u64 addr;
- int i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- item = UNHIT_CACHE_ITEM;
- for (i = 0; i < CACHE_ITEM_NUM; i++) {
- addr = Cache.array[i].address;
- if ((page_addr >= addr) &&
- (page_addr < (addr + Cache.cache_item_size))) {
- item = i;
- break;
- }
- }
-
- return item;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Calculate_LRU
-* Inputs: None
-* Outputs: None
-* Description: Calculate the least recently block in a cache and record its
-* index in LRU field.
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static void FTL_Calculate_LRU(void)
-{
- u16 i, bCurrentLRU, bTempCount;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- bCurrentLRU = 0;
- bTempCount = MAX_WORD_VALUE;
-
- for (i = 0; i < CACHE_ITEM_NUM; i++) {
- if (Cache.array[i].use_cnt < bTempCount) {
- bCurrentLRU = i;
- bTempCount = Cache.array[i].use_cnt;
- }
- }
-
- Cache.LRU = bCurrentLRU;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Cache_Read_Page
-* Inputs: pointer to read buffer, logical address and cache item number
-* Outputs: None
-* Description: Read the page from the cached block addressed by blocknumber
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static void FTL_Cache_Read_Page(u8 *data_buf, u64 logic_addr, u16 cache_item)
-{
- u8 *start_addr;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- start_addr = Cache.array[cache_item].buf;
- start_addr += (u32)(((logic_addr - Cache.array[cache_item].address) >>
- DeviceInfo.nBitsInPageDataSize) * DeviceInfo.wPageDataSize);
-
-#if CMD_DMA
- GLOB_LLD_MemCopy_CMD(data_buf, start_addr,
- DeviceInfo.wPageDataSize, 0);
- ftl_cmd_cnt++;
-#else
- memcpy(data_buf, start_addr, DeviceInfo.wPageDataSize);
-#endif
-
- if (Cache.array[cache_item].use_cnt < MAX_WORD_VALUE)
- Cache.array[cache_item].use_cnt++;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Cache_Read_All
-* Inputs: pointer to read buffer,block address
-* Outputs: PASS=0 / FAIL =1
-* Description: It reads pages in cache
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Cache_Read_All(u8 *pData, u64 phy_addr)
-{
- int wResult = PASS;
- u32 Block;
- u32 lba;
- u16 Page;
- u16 PageCount;
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 i;
-
- Block = BLK_FROM_ADDR(phy_addr);
- Page = PAGE_FROM_ADDR(phy_addr, Block);
- PageCount = Cache.pages_per_item;
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "%s, Line %d, Function: %s, Block: 0x%x\n",
- __FILE__, __LINE__, __func__, Block);
-
- lba = 0xffffffff;
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- if ((pbt[i] & (~BAD_BLOCK)) == Block) {
- lba = i;
- if (IS_SPARE_BLOCK(i) || IS_BAD_BLOCK(i) ||
- IS_DISCARDED_BLOCK(i)) {
- /* Add by yunpeng -2008.12.3 */
-#if CMD_DMA
- GLOB_LLD_MemCopy_CMD(pData, g_temp_buf,
- PageCount * DeviceInfo.wPageDataSize, 0);
- ftl_cmd_cnt++;
-#else
- memset(pData, 0xFF,
- PageCount * DeviceInfo.wPageDataSize);
-#endif
- return wResult;
- } else {
- continue; /* break ?? */
- }
- }
- }
-
- if (0xffffffff == lba)
- printk(KERN_ERR "FTL_Cache_Read_All: Block is not found in BT\n");
-
-#if CMD_DMA
- wResult = GLOB_LLD_Read_Page_Main_cdma(pData, Block, Page,
- PageCount, LLD_CMD_FLAG_MODE_CDMA);
- if (DeviceInfo.MLCDevice) {
- g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++;
- nand_dbg_print(NAND_DBG_DEBUG,
- "Read Counter modified in ftl_cmd_cnt %u"
- " Block %u Counter%u\n",
- ftl_cmd_cnt, (unsigned int)Block,
- g_pReadCounter[Block -
- DeviceInfo.wSpectraStartBlock]);
-
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
- p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
- p_BTableChangesDelta->RC_Index =
- Block - DeviceInfo.wSpectraStartBlock;
- p_BTableChangesDelta->RC_Entry_Value =
- g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock];
- p_BTableChangesDelta->ValidFields = 0xC0;
-
- ftl_cmd_cnt++;
-
- if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >=
- MAX_READ_COUNTER)
- FTL_Read_Disturbance(Block);
- if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) {
- g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
- FTL_Write_IN_Progress_Block_Table_Page();
- }
- } else {
- ftl_cmd_cnt++;
- }
-#else
- wResult = GLOB_LLD_Read_Page_Main(pData, Block, Page, PageCount);
- if (wResult == FAIL)
- return wResult;
-
- if (DeviceInfo.MLCDevice) {
- g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++;
- if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >=
- MAX_READ_COUNTER)
- FTL_Read_Disturbance(Block);
- if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) {
- g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
- FTL_Write_IN_Progress_Block_Table_Page();
- }
- }
-#endif
- return wResult;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Cache_Write_All
-* Inputs: pointer to cache in sys memory
-* address of free block in flash
-* Outputs: PASS=0 / FAIL=1
-* Description: writes all the pages of the block in cache to flash
-*
-* NOTE:need to make sure this works ok when cache is limited
-* to a partial block. This is where copy-back would be
-* activated. This would require knowing which pages in the
-* cached block are clean/dirty.Right now we only know if
-* the whole block is clean/dirty.
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Cache_Write_All(u8 *pData, u64 blk_addr)
-{
- u16 wResult = PASS;
- u32 Block;
- u16 Page;
- u16 PageCount;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- nand_dbg_print(NAND_DBG_DEBUG, "This block %d going to be written "
- "on %d\n", cache_block_to_write,
- (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize));
-
- Block = BLK_FROM_ADDR(blk_addr);
- Page = PAGE_FROM_ADDR(blk_addr, Block);
- PageCount = Cache.pages_per_item;
-
-#if CMD_DMA
- if (FAIL == GLOB_LLD_Write_Page_Main_cdma(pData,
- Block, Page, PageCount)) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, new Bad Block %d generated! "
- "Need Bad Block replacing.\n",
- __FILE__, __LINE__, __func__, Block);
- wResult = FAIL;
- }
- ftl_cmd_cnt++;
-#else
- if (FAIL == GLOB_LLD_Write_Page_Main(pData, Block, Page, PageCount)) {
- nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in %s,"
- " Line %d, Function %s, new Bad Block %d generated!"
- "Need Bad Block replacing.\n",
- __FILE__, __LINE__, __func__, Block);
- wResult = FAIL;
- }
-#endif
- return wResult;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Copy_Block
-* Inputs: source block address
-* Destination block address
-* Outputs: PASS=0 / FAIL=1
-* Description: used only for static wear leveling to move the block
-* containing static data to new blocks(more worn)
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int FTL_Copy_Block(u64 old_blk_addr, u64 blk_addr)
-{
- int i, r1, r2, wResult = PASS;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) {
- r1 = FTL_Cache_Read_All(g_pTempBuf, old_blk_addr +
- i * DeviceInfo.wPageDataSize);
- r2 = FTL_Cache_Write_All(g_pTempBuf, blk_addr +
- i * DeviceInfo.wPageDataSize);
- if ((ERR == r1) || (FAIL == r2)) {
- wResult = FAIL;
- break;
- }
- }
-
- return wResult;
-}
-
-/* Search the block table to find out the least wear block and then return it */
-static u32 find_least_worn_blk_for_l2_cache(void)
-{
- int i;
- u32 *pbt = (u32 *)g_pBlockTable;
- u8 least_wear_cnt = MAX_BYTE_VALUE;
- u32 least_wear_blk_idx = MAX_U32_VALUE;
- u32 phy_idx;
-
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- if (IS_SPARE_BLOCK(i)) {
- phy_idx = (u32)((~BAD_BLOCK) & pbt[i]);
- if (phy_idx > DeviceInfo.wSpectraEndBlock)
- printk(KERN_ERR "find_least_worn_blk_for_l2_cache: "
- "Too big phy block num (%d)\n", phy_idx);
- if (g_pWearCounter[phy_idx -DeviceInfo.wSpectraStartBlock] < least_wear_cnt) {
- least_wear_cnt = g_pWearCounter[phy_idx - DeviceInfo.wSpectraStartBlock];
- least_wear_blk_idx = i;
- }
- }
- }
-
- nand_dbg_print(NAND_DBG_WARN,
- "find_least_worn_blk_for_l2_cache: "
- "find block %d with least worn counter (%d)\n",
- least_wear_blk_idx, least_wear_cnt);
-
- return least_wear_blk_idx;
-}
-
-
-
-/* Get blocks for Level2 Cache */
-static int get_l2_cache_blks(void)
-{
- int n;
- u32 blk;
- u32 *pbt = (u32 *)g_pBlockTable;
-
- for (n = 0; n < BLK_NUM_FOR_L2_CACHE; n++) {
- blk = find_least_worn_blk_for_l2_cache();
- if (blk >= DeviceInfo.wDataBlockNum) {
- nand_dbg_print(NAND_DBG_WARN,
- "find_least_worn_blk_for_l2_cache: "
- "No enough free NAND blocks (n: %d) for L2 Cache!\n", n);
- return FAIL;
- }
- /* Tag the free block as discard in block table */
- pbt[blk] = (pbt[blk] & (~BAD_BLOCK)) | DISCARD_BLOCK;
- /* Add the free block to the L2 Cache block array */
- cache_l2.blk_array[n] = pbt[blk] & (~BAD_BLOCK);
- }
-
- return PASS;
-}
-
-static int erase_l2_cache_blocks(void)
-{
- int i, ret = PASS;
- u32 pblk, lblk = BAD_BLOCK;
- u64 addr;
- u32 *pbt = (u32 *)g_pBlockTable;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) {
- pblk = cache_l2.blk_array[i];
-
- /* If the L2 cache block is invalid, then just skip it */
- if (MAX_U32_VALUE == pblk)
- continue;
-
- BUG_ON(pblk > DeviceInfo.wSpectraEndBlock);
-
- addr = (u64)pblk << DeviceInfo.nBitsInBlockDataSize;
- if (PASS == GLOB_FTL_Block_Erase(addr)) {
- /* Get logical block number of the erased block */
- lblk = FTL_Get_Block_Index(pblk);
- BUG_ON(BAD_BLOCK == lblk);
- /* Tag it as free in the block table */
- pbt[lblk] &= (u32)(~DISCARD_BLOCK);
- pbt[lblk] |= (u32)(SPARE_BLOCK);
- } else {
- MARK_BLOCK_AS_BAD(pbt[lblk]);
- ret = ERR;
- }
- }
-
- return ret;
-}
-
-/*
- * Merge the valid data page in the L2 cache blocks into NAND.
-*/
-static int flush_l2_cache(void)
-{
- struct list_head *p;
- struct spectra_l2_cache_list *pnd, *tmp_pnd;
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 phy_blk, l2_blk;
- u64 addr;
- u16 l2_page;
- int i, ret = PASS;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (list_empty(&cache_l2.table.list)) /* No data to flush */
- return ret;
-
- //dump_cache_l2_table();
-
- if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
- g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
- FTL_Write_IN_Progress_Block_Table_Page();
- }
-
- list_for_each(p, &cache_l2.table.list) {
- pnd = list_entry(p, struct spectra_l2_cache_list, list);
- if (IS_SPARE_BLOCK(pnd->logical_blk_num) ||
- IS_BAD_BLOCK(pnd->logical_blk_num) ||
- IS_DISCARDED_BLOCK(pnd->logical_blk_num)) {
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__);
- memset(cache_l2_blk_buf, 0xff, DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize);
- } else {
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__);
- phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK);
- ret = GLOB_LLD_Read_Page_Main(cache_l2_blk_buf,
- phy_blk, 0, DeviceInfo.wPagesPerBlock);
- if (ret == FAIL) {
- printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__);
- }
- }
-
- for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) {
- if (pnd->pages_array[i] != MAX_U32_VALUE) {
- l2_blk = cache_l2.blk_array[(pnd->pages_array[i] >> 16) & 0xffff];
- l2_page = pnd->pages_array[i] & 0xffff;
- ret = GLOB_LLD_Read_Page_Main(cache_l2_page_buf, l2_blk, l2_page, 1);
- if (ret == FAIL) {
- printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__);
- }
- memcpy(cache_l2_blk_buf + i * DeviceInfo.wPageDataSize, cache_l2_page_buf, DeviceInfo.wPageDataSize);
- }
- }
-
- /* Find a free block and tag the original block as discarded */
- addr = (u64)pnd->logical_blk_num << DeviceInfo.nBitsInBlockDataSize;
- ret = FTL_Replace_Block(addr);
- if (ret == FAIL) {
- printk(KERN_ERR "FTL_Replace_Block fail in %s, Line %d\n", __FILE__, __LINE__);
- }
-
- /* Write back the updated data into NAND */
- phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK);
- if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) {
- nand_dbg_print(NAND_DBG_WARN,
- "Program NAND block %d fail in %s, Line %d\n",
- phy_blk, __FILE__, __LINE__);
- /* This may not be really a bad block. So just tag it as discarded. */
- /* Then it has a chance to be erased when garbage collection. */
- /* If it is really bad, then the erase will fail and it will be marked */
- /* as bad then. Otherwise it will be marked as free and can be used again */
- MARK_BLK_AS_DISCARD(pbt[pnd->logical_blk_num]);
- /* Find another free block and write it again */
- FTL_Replace_Block(addr);
- phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK);
- if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) {
- printk(KERN_ERR "Failed to write back block %d when flush L2 cache."
- "Some data will be lost!\n", phy_blk);
- MARK_BLOCK_AS_BAD(pbt[pnd->logical_blk_num]);
- }
- } else {
- /* tag the new free block as used block */
- pbt[pnd->logical_blk_num] &= (~SPARE_BLOCK);
- }
- }
-
- /* Destroy the L2 Cache table and free the memory of all nodes */
- list_for_each_entry_safe(pnd, tmp_pnd, &cache_l2.table.list, list) {
- list_del(&pnd->list);
- kfree(pnd);
- }
-
- /* Erase discard L2 cache blocks */
- if (erase_l2_cache_blocks() != PASS)
- nand_dbg_print(NAND_DBG_WARN,
- " Erase L2 cache blocks error in %s, Line %d\n",
- __FILE__, __LINE__);
-
- /* Init the Level2 Cache data structure */
- for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++)
- cache_l2.blk_array[i] = MAX_U32_VALUE;
- cache_l2.cur_blk_idx = 0;
- cache_l2.cur_page_num = 0;
- INIT_LIST_HEAD(&cache_l2.table.list);
- cache_l2.table.logical_blk_num = MAX_U32_VALUE;
-
- return ret;
-}
-
-/*
- * Write back a changed victim cache item to the Level2 Cache
- * and update the L2 Cache table to map the change.
- * If the L2 Cache is full, then start to do the L2 Cache flush.
-*/
-static int write_back_to_l2_cache(u8 *buf, u64 logical_addr)
-{
- u32 logical_blk_num;
- u16 logical_page_num;
- struct list_head *p;
- struct spectra_l2_cache_list *pnd, *pnd_new;
- u32 node_size;
- int i, found;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- /*
- * If Level2 Cache table is empty, then it means either:
- * 1. This is the first time that the function called after FTL_init
- * or
- * 2. The Level2 Cache has just been flushed
- *
- * So, 'steal' some free blocks from NAND for L2 Cache using
- * by just mask them as discard in the block table
- */
- if (list_empty(&cache_l2.table.list)) {
- BUG_ON(cache_l2.cur_blk_idx != 0);
- BUG_ON(cache_l2.cur_page_num!= 0);
- BUG_ON(cache_l2.table.logical_blk_num != MAX_U32_VALUE);
- if (FAIL == get_l2_cache_blks()) {
- GLOB_FTL_Garbage_Collection();
- if (FAIL == get_l2_cache_blks()) {
- printk(KERN_ALERT "Fail to get L2 cache blks!\n");
- return FAIL;
- }
- }
- }
-
- logical_blk_num = BLK_FROM_ADDR(logical_addr);
- logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num);
- BUG_ON(logical_blk_num == MAX_U32_VALUE);
-
- /* Write the cache item data into the current position of L2 Cache */
-#if CMD_DMA
- /*
- * TODO
- */
-#else
- if (FAIL == GLOB_LLD_Write_Page_Main(buf,
- cache_l2.blk_array[cache_l2.cur_blk_idx],
- cache_l2.cur_page_num, 1)) {
- nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in "
- "%s, Line %d, new Bad Block %d generated!\n",
- __FILE__, __LINE__,
- cache_l2.blk_array[cache_l2.cur_blk_idx]);
-
- /* TODO: tag the current block as bad and try again */
-
- return FAIL;
- }
-#endif
-
- /*
- * Update the L2 Cache table.
- *
- * First seaching in the table to see whether the logical block
- * has been mapped. If not, then kmalloc a new node for the
- * logical block, fill data, and then insert it to the list.
- * Otherwise, just update the mapped node directly.
- */
- found = 0;
- list_for_each(p, &cache_l2.table.list) {
- pnd = list_entry(p, struct spectra_l2_cache_list, list);
- if (pnd->logical_blk_num == logical_blk_num) {
- pnd->pages_array[logical_page_num] =
- (cache_l2.cur_blk_idx << 16) |
- cache_l2.cur_page_num;
- found = 1;
- break;
- }
- }
- if (!found) { /* Create new node for the logical block here */
-
- /* The logical pages to physical pages map array is
- * located at the end of struct spectra_l2_cache_list.
- */
- node_size = sizeof(struct spectra_l2_cache_list) +
- sizeof(u32) * DeviceInfo.wPagesPerBlock;
- pnd_new = kmalloc(node_size, GFP_ATOMIC);
- if (!pnd_new) {
- printk(KERN_ERR "Failed to kmalloc in %s Line %d\n",
- __FILE__, __LINE__);
- /*
- * TODO: Need to flush all the L2 cache into NAND ASAP
- * since no memory available here
- */
- }
- pnd_new->logical_blk_num = logical_blk_num;
- for (i = 0; i < DeviceInfo.wPagesPerBlock; i++)
- pnd_new->pages_array[i] = MAX_U32_VALUE;
- pnd_new->pages_array[logical_page_num] =
- (cache_l2.cur_blk_idx << 16) | cache_l2.cur_page_num;
- list_add(&pnd_new->list, &cache_l2.table.list);
- }
-
- /* Increasing the current position pointer of the L2 Cache */
- cache_l2.cur_page_num++;
- if (cache_l2.cur_page_num >= DeviceInfo.wPagesPerBlock) {
- cache_l2.cur_blk_idx++;
- if (cache_l2.cur_blk_idx >= BLK_NUM_FOR_L2_CACHE) {
- /* The L2 Cache is full. Need to flush it now */
- nand_dbg_print(NAND_DBG_WARN,
- "L2 Cache is full, will start to flush it\n");
- flush_l2_cache();
- } else {
- cache_l2.cur_page_num = 0;
- }
- }
-
- return PASS;
-}
-
-/*
- * Search in the Level2 Cache table to find the cache item.
- * If find, read the data from the NAND page of L2 Cache,
- * Otherwise, return FAIL.
- */
-static int search_l2_cache(u8 *buf, u64 logical_addr)
-{
- u32 logical_blk_num;
- u16 logical_page_num;
- struct list_head *p;
- struct spectra_l2_cache_list *pnd;
- u32 tmp = MAX_U32_VALUE;
- u32 phy_blk;
- u16 phy_page;
- int ret = FAIL;
-
- logical_blk_num = BLK_FROM_ADDR(logical_addr);
- logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num);
-
- list_for_each(p, &cache_l2.table.list) {
- pnd = list_entry(p, struct spectra_l2_cache_list, list);
- if (pnd->logical_blk_num == logical_blk_num) {
- tmp = pnd->pages_array[logical_page_num];
- break;
- }
- }
-
- if (tmp != MAX_U32_VALUE) { /* Found valid map */
- phy_blk = cache_l2.blk_array[(tmp >> 16) & 0xFFFF];
- phy_page = tmp & 0xFFFF;
-#if CMD_DMA
- /* TODO */
-#else
- ret = GLOB_LLD_Read_Page_Main(buf, phy_blk, phy_page, 1);
-#endif
- }
-
- return ret;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Cache_Write_Page
-* Inputs: Pointer to buffer, page address, cache block number
-* Outputs: PASS=0 / FAIL=1
-* Description: It writes the data in Cache Block
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static void FTL_Cache_Write_Page(u8 *pData, u64 page_addr,
- u8 cache_blk, u16 flag)
-{
- u8 *pDest;
- u64 addr;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- addr = Cache.array[cache_blk].address;
- pDest = Cache.array[cache_blk].buf;
-
- pDest += (unsigned long)(page_addr - addr);
- Cache.array[cache_blk].changed = SET;
-#if CMD_DMA
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- int_cache[ftl_cmd_cnt].item = cache_blk;
- int_cache[ftl_cmd_cnt].cache.address =
- Cache.array[cache_blk].address;
- int_cache[ftl_cmd_cnt].cache.changed =
- Cache.array[cache_blk].changed;
-#endif
- GLOB_LLD_MemCopy_CMD(pDest, pData, DeviceInfo.wPageDataSize, flag);
- ftl_cmd_cnt++;
-#else
- memcpy(pDest, pData, DeviceInfo.wPageDataSize);
-#endif
- if (Cache.array[cache_blk].use_cnt < MAX_WORD_VALUE)
- Cache.array[cache_blk].use_cnt++;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Cache_Write
-* Inputs: none
-* Outputs: PASS=0 / FAIL=1
-* Description: It writes least frequently used Cache block to flash if it
-* has been changed
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Cache_Write(void)
-{
- int i, bResult = PASS;
- u16 bNO, least_count = 0xFFFF;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- FTL_Calculate_LRU();
-
- bNO = Cache.LRU;
- nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: "
- "Least used cache block is %d\n", bNO);
-
- if (Cache.array[bNO].changed != SET)
- return bResult;
-
- nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: Cache"
- " Block %d containing logical block %d is dirty\n",
- bNO,
- (u32)(Cache.array[bNO].address >>
- DeviceInfo.nBitsInBlockDataSize));
-#if CMD_DMA
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- int_cache[ftl_cmd_cnt].item = bNO;
- int_cache[ftl_cmd_cnt].cache.address =
- Cache.array[bNO].address;
- int_cache[ftl_cmd_cnt].cache.changed = CLEAR;
-#endif
-#endif
- bResult = write_back_to_l2_cache(Cache.array[bNO].buf,
- Cache.array[bNO].address);
- if (bResult != ERR)
- Cache.array[bNO].changed = CLEAR;
-
- least_count = Cache.array[bNO].use_cnt;
-
- for (i = 0; i < CACHE_ITEM_NUM; i++) {
- if (i == bNO)
- continue;
- if (Cache.array[i].use_cnt > 0)
- Cache.array[i].use_cnt -= least_count;
- }
-
- return bResult;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Cache_Read
-* Inputs: Page address
-* Outputs: PASS=0 / FAIL=1
-* Description: It reads the block from device in Cache Block
-* Set the LRU count to 1
-* Mark the Cache Block as clean
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Cache_Read(u64 logical_addr)
-{
- u64 item_addr, phy_addr;
- u16 num;
- int ret;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- num = Cache.LRU; /* The LRU cache item will be overwritten */
-
- item_addr = (u64)GLOB_u64_Div(logical_addr, Cache.cache_item_size) *
- Cache.cache_item_size;
- Cache.array[num].address = item_addr;
- Cache.array[num].use_cnt = 1;
- Cache.array[num].changed = CLEAR;
-
-#if CMD_DMA
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- int_cache[ftl_cmd_cnt].item = num;
- int_cache[ftl_cmd_cnt].cache.address =
- Cache.array[num].address;
- int_cache[ftl_cmd_cnt].cache.changed =
- Cache.array[num].changed;
-#endif
-#endif
- /*
- * Search in L2 Cache. If hit, fill data into L1 Cache item buffer,
- * Otherwise, read it from NAND
- */
- ret = search_l2_cache(Cache.array[num].buf, logical_addr);
- if (PASS == ret) /* Hit in L2 Cache */
- return ret;
-
- /* Compute the physical start address of NAND device according to */
- /* the logical start address of the cache item (LRU cache item) */
- phy_addr = FTL_Get_Physical_Block_Addr(item_addr) +
- GLOB_u64_Remainder(item_addr, 2);
-
- return FTL_Cache_Read_All(Cache.array[num].buf, phy_addr);
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Check_Block_Table
-* Inputs: ?
-* Outputs: PASS=0 / FAIL=1
-* Description: It checks the correctness of each block table entry
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Check_Block_Table(int wOldTable)
-{
- u32 i;
- int wResult = PASS;
- u32 blk_idx;
- u32 *pbt = (u32 *)g_pBlockTable;
- u8 *pFlag = flag_check_blk_table;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (NULL != pFlag) {
- memset(pFlag, FAIL, DeviceInfo.wDataBlockNum);
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- blk_idx = (u32)(pbt[i] & (~BAD_BLOCK));
-
- /*
- * 20081006/KBV - Changed to pFlag[i] reference
- * to avoid buffer overflow
- */
-
- /*
- * 2008-10-20 Yunpeng Note: This change avoid
- * buffer overflow, but changed function of
- * the code, so it should be re-write later
- */
- if ((blk_idx > DeviceInfo.wSpectraEndBlock) ||
- PASS == pFlag[i]) {
- wResult = FAIL;
- break;
- } else {
- pFlag[i] = PASS;
- }
- }
- }
-
- return wResult;
-}
-
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Write_Block_Table
-* Inputs: flasg
-* Outputs: 0=Block Table was updated. No write done. 1=Block write needs to
-* happen. -1 Error
-* Description: It writes the block table
-* Block table always mapped to LBA 0 which inturn mapped
-* to any physical block
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Write_Block_Table(int wForce)
-{
- u32 *pbt = (u32 *)g_pBlockTable;
- int wSuccess = PASS;
- u32 wTempBlockTableIndex;
- u16 bt_pages, new_bt_offset;
- u8 blockchangeoccured = 0;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
-
- if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus)
- return 0;
-
- if (PASS == wForce) {
- g_wBlockTableOffset =
- (u16)(DeviceInfo.wPagesPerBlock - bt_pages);
-#if CMD_DMA
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
- p_BTableChangesDelta->g_wBlockTableOffset =
- g_wBlockTableOffset;
- p_BTableChangesDelta->ValidFields = 0x01;
-#endif
- }
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Inside FTL_Write_Block_Table: block %d Page:%d\n",
- g_wBlockTableIndex, g_wBlockTableOffset);
-
- do {
- new_bt_offset = g_wBlockTableOffset + bt_pages + 1;
- if ((0 == (new_bt_offset % DeviceInfo.wPagesPerBlock)) ||
- (new_bt_offset > DeviceInfo.wPagesPerBlock) ||
- (FAIL == wSuccess)) {
- wTempBlockTableIndex = FTL_Replace_Block_Table();
- if (BAD_BLOCK == wTempBlockTableIndex)
- return ERR;
- if (!blockchangeoccured) {
- bt_block_changed = 1;
- blockchangeoccured = 1;
- }
-
- g_wBlockTableIndex = wTempBlockTableIndex;
- g_wBlockTableOffset = 0;
- pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex;
-#if CMD_DMA
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->g_wBlockTableOffset =
- g_wBlockTableOffset;
- p_BTableChangesDelta->g_wBlockTableIndex =
- g_wBlockTableIndex;
- p_BTableChangesDelta->ValidFields = 0x03;
-
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free +=
- sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index =
- BLOCK_TABLE_INDEX;
- p_BTableChangesDelta->BT_Entry_Value =
- pbt[BLOCK_TABLE_INDEX];
- p_BTableChangesDelta->ValidFields = 0x0C;
-#endif
- }
-
- wSuccess = FTL_Write_Block_Table_Data();
- if (FAIL == wSuccess)
- MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]);
- } while (FAIL == wSuccess);
-
- g_cBlockTableStatus = CURRENT_BLOCK_TABLE;
-
- return 1;
-}
-
-static int force_format_nand(void)
-{
- u32 i;
-
- /* Force erase the whole unprotected physical partiton of NAND */
- printk(KERN_ALERT "Start to force erase whole NAND device ...\n");
- printk(KERN_ALERT "From phyical block %d to %d\n",
- DeviceInfo.wSpectraStartBlock, DeviceInfo.wSpectraEndBlock);
- for (i = DeviceInfo.wSpectraStartBlock; i <= DeviceInfo.wSpectraEndBlock; i++) {
- if (GLOB_LLD_Erase_Block(i))
- printk(KERN_ERR "Failed to force erase NAND block %d\n", i);
- }
- printk(KERN_ALERT "Force Erase ends. Please reboot the system ...\n");
- while(1);
-
- return PASS;
-}
-
-int GLOB_FTL_Flash_Format(void)
-{
- //return FTL_Format_Flash(1);
- return force_format_nand();
-
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Search_Block_Table_IN_Block
-* Inputs: Block Number
-* Pointer to page
-* Outputs: PASS / FAIL
-* Page contatining the block table
-* Description: It searches the block table in the block
-* passed as an argument.
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Search_Block_Table_IN_Block(u32 BT_Block,
- u8 BT_Tag, u16 *Page)
-{
- u16 i, j, k;
- u16 Result = PASS;
- u16 Last_IPF = 0;
- u8 BT_Found = 0;
- u8 *tagarray;
- u8 *tempbuf = tmp_buf_search_bt_in_block;
- u8 *pSpareBuf = spare_buf_search_bt_in_block;
- u8 *pSpareBufBTLastPage = spare_buf_bt_search_bt_in_block;
- u8 bt_flag_last_page = 0xFF;
- u8 search_in_previous_pages = 0;
- u16 bt_pages;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Searching block table in %u block\n",
- (unsigned int)BT_Block);
-
- bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
-
- for (i = bt_pages; i < DeviceInfo.wPagesPerBlock;
- i += (bt_pages + 1)) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "Searching last IPF: %d\n", i);
- Result = GLOB_LLD_Read_Page_Main_Polling(tempbuf,
- BT_Block, i, 1);
-
- if (0 == memcmp(tempbuf, g_pIPF, DeviceInfo.wPageDataSize)) {
- if ((i + bt_pages + 1) < DeviceInfo.wPagesPerBlock) {
- continue;
- } else {
- search_in_previous_pages = 1;
- Last_IPF = i;
- }
- }
-
- if (!search_in_previous_pages) {
- if (i != bt_pages) {
- i -= (bt_pages + 1);
- Last_IPF = i;
- }
- }
-
- if (0 == Last_IPF)
- break;
-
- if (!search_in_previous_pages) {
- i = i + 1;
- nand_dbg_print(NAND_DBG_DEBUG,
- "Reading the spare area of Block %u Page %u",
- (unsigned int)BT_Block, i);
- Result = GLOB_LLD_Read_Page_Spare(pSpareBuf,
- BT_Block, i, 1);
- nand_dbg_print(NAND_DBG_DEBUG,
- "Reading the spare area of Block %u Page %u",
- (unsigned int)BT_Block, i + bt_pages - 1);
- Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage,
- BT_Block, i + bt_pages - 1, 1);
-
- k = 0;
- j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray);
- if (j) {
- for (; k < j; k++) {
- if (tagarray[k] == BT_Tag)
- break;
- }
- }
-
- if (k < j)
- bt_flag = tagarray[k];
- else
- Result = FAIL;
-
- if (Result == PASS) {
- k = 0;
- j = FTL_Extract_Block_Table_Tag(
- pSpareBufBTLastPage, &tagarray);
- if (j) {
- for (; k < j; k++) {
- if (tagarray[k] == BT_Tag)
- break;
- }
- }
-
- if (k < j)
- bt_flag_last_page = tagarray[k];
- else
- Result = FAIL;
-
- if (Result == PASS) {
- if (bt_flag == bt_flag_last_page) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "Block table is found"
- " in page after IPF "
- "at block %d "
- "page %d\n",
- (int)BT_Block, i);
- BT_Found = 1;
- *Page = i;
- g_cBlockTableStatus =
- CURRENT_BLOCK_TABLE;
- break;
- } else {
- Result = FAIL;
- }
- }
- }
- }
-
- if (search_in_previous_pages)
- i = i - bt_pages;
- else
- i = i - (bt_pages + 1);
-
- Result = PASS;
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Reading the spare area of Block %d Page %d",
- (int)BT_Block, i);
-
- Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1);
- nand_dbg_print(NAND_DBG_DEBUG,
- "Reading the spare area of Block %u Page %u",
- (unsigned int)BT_Block, i + bt_pages - 1);
-
- Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage,
- BT_Block, i + bt_pages - 1, 1);
-
- k = 0;
- j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray);
- if (j) {
- for (; k < j; k++) {
- if (tagarray[k] == BT_Tag)
- break;
- }
- }
-
- if (k < j)
- bt_flag = tagarray[k];
- else
- Result = FAIL;
-
- if (Result == PASS) {
- k = 0;
- j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage,
- &tagarray);
- if (j) {
- for (; k < j; k++) {
- if (tagarray[k] == BT_Tag)
- break;
- }
- }
-
- if (k < j) {
- bt_flag_last_page = tagarray[k];
- } else {
- Result = FAIL;
- break;
- }
-
- if (Result == PASS) {
- if (bt_flag == bt_flag_last_page) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "Block table is found "
- "in page prior to IPF "
- "at block %u page %d\n",
- (unsigned int)BT_Block, i);
- BT_Found = 1;
- *Page = i;
- g_cBlockTableStatus =
- IN_PROGRESS_BLOCK_TABLE;
- break;
- } else {
- Result = FAIL;
- break;
- }
- }
- }
- }
-
- if (Result == FAIL) {
- if ((Last_IPF > bt_pages) && (i < Last_IPF) && (!BT_Found)) {
- BT_Found = 1;
- *Page = i - (bt_pages + 1);
- }
- if ((Last_IPF == bt_pages) && (i < Last_IPF) && (!BT_Found))
- goto func_return;
- }
-
- if (Last_IPF == 0) {
- i = 0;
- Result = PASS;
- nand_dbg_print(NAND_DBG_DEBUG, "Reading the spare area of "
- "Block %u Page %u", (unsigned int)BT_Block, i);
-
- Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1);
- nand_dbg_print(NAND_DBG_DEBUG,
- "Reading the spare area of Block %u Page %u",
- (unsigned int)BT_Block, i + bt_pages - 1);
- Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage,
- BT_Block, i + bt_pages - 1, 1);
-
- k = 0;
- j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray);
- if (j) {
- for (; k < j; k++) {
- if (tagarray[k] == BT_Tag)
- break;
- }
- }
-
- if (k < j)
- bt_flag = tagarray[k];
- else
- Result = FAIL;
-
- if (Result == PASS) {
- k = 0;
- j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage,
- &tagarray);
- if (j) {
- for (; k < j; k++) {
- if (tagarray[k] == BT_Tag)
- break;
- }
- }
-
- if (k < j)
- bt_flag_last_page = tagarray[k];
- else
- Result = FAIL;
-
- if (Result == PASS) {
- if (bt_flag == bt_flag_last_page) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "Block table is found "
- "in page after IPF at "
- "block %u page %u\n",
- (unsigned int)BT_Block,
- (unsigned int)i);
- BT_Found = 1;
- *Page = i;
- g_cBlockTableStatus =
- CURRENT_BLOCK_TABLE;
- goto func_return;
- } else {
- Result = FAIL;
- }
- }
- }
-
- if (Result == FAIL)
- goto func_return;
- }
-func_return:
- return Result;
-}
-
-u8 *get_blk_table_start_addr(void)
-{
- return g_pBlockTable;
-}
-
-unsigned long get_blk_table_len(void)
-{
- return DeviceInfo.wDataBlockNum * sizeof(u32);
-}
-
-u8 *get_wear_leveling_table_start_addr(void)
-{
- return g_pWearCounter;
-}
-
-unsigned long get_wear_leveling_table_len(void)
-{
- return DeviceInfo.wDataBlockNum * sizeof(u8);
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Read_Block_Table
-* Inputs: none
-* Outputs: PASS / FAIL
-* Description: read the flash spare area and find a block containing the
-* most recent block table(having largest block_table_counter).
-* Find the last written Block table in this block.
-* Check the correctness of Block Table
-* If CDMA is enabled, this function is called in
-* polling mode.
-* We don't need to store changes in Block table in this
-* function as it is called only at initialization
-*
-* Note: Currently this function is called at initialization
-* before any read/erase/write command issued to flash so,
-* there is no need to wait for CDMA list to complete as of now
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Read_Block_Table(void)
-{
- u16 i = 0;
- int k, j;
- u8 *tempBuf, *tagarray;
- int wResult = FAIL;
- int status = FAIL;
- u8 block_table_found = 0;
- int search_result;
- u32 Block;
- u16 Page = 0;
- u16 PageCount;
- u16 bt_pages;
- int wBytesCopied = 0, tempvar;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- tempBuf = tmp_buf1_read_blk_table;
- bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
-
- for (j = DeviceInfo.wSpectraStartBlock;
- j <= (int)DeviceInfo.wSpectraEndBlock;
- j++) {
- status = GLOB_LLD_Read_Page_Spare(tempBuf, j, 0, 1);
- k = 0;
- i = FTL_Extract_Block_Table_Tag(tempBuf, &tagarray);
- if (i) {
- status = GLOB_LLD_Read_Page_Main_Polling(tempBuf,
- j, 0, 1);
- for (; k < i; k++) {
- if (tagarray[k] == tempBuf[3])
- break;
- }
- }
-
- if (k < i)
- k = tagarray[k];
- else
- continue;
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Block table is contained in Block %d %d\n",
- (unsigned int)j, (unsigned int)k);
-
- if (g_pBTBlocks[k-FIRST_BT_ID] == BTBLOCK_INVAL) {
- g_pBTBlocks[k-FIRST_BT_ID] = j;
- block_table_found = 1;
- } else {
- printk(KERN_ERR "FTL_Read_Block_Table -"
- "This should never happens. "
- "Two block table have same counter %u!\n", k);
- }
- }
-
- if (block_table_found) {
- if (g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL &&
- g_pBTBlocks[LAST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) {
- j = LAST_BT_ID;
- while ((j > FIRST_BT_ID) &&
- (g_pBTBlocks[j - FIRST_BT_ID] != BTBLOCK_INVAL))
- j--;
- if (j == FIRST_BT_ID) {
- j = LAST_BT_ID;
- last_erased = LAST_BT_ID;
- } else {
- last_erased = (u8)j + 1;
- while ((j > FIRST_BT_ID) && (BTBLOCK_INVAL ==
- g_pBTBlocks[j - FIRST_BT_ID]))
- j--;
- }
- } else {
- j = FIRST_BT_ID;
- while (g_pBTBlocks[j - FIRST_BT_ID] == BTBLOCK_INVAL)
- j++;
- last_erased = (u8)j;
- while ((j < LAST_BT_ID) && (BTBLOCK_INVAL !=
- g_pBTBlocks[j - FIRST_BT_ID]))
- j++;
- if (g_pBTBlocks[j-FIRST_BT_ID] == BTBLOCK_INVAL)
- j--;
- }
-
- if (last_erased > j)
- j += (1 + LAST_BT_ID - FIRST_BT_ID);
-
- for (; (j >= last_erased) && (FAIL == wResult); j--) {
- i = (j - FIRST_BT_ID) %
- (1 + LAST_BT_ID - FIRST_BT_ID);
- search_result =
- FTL_Search_Block_Table_IN_Block(g_pBTBlocks[i],
- i + FIRST_BT_ID, &Page);
- if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE)
- block_table_found = 0;
-
- while ((search_result == PASS) && (FAIL == wResult)) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "FTL_Read_Block_Table:"
- "Block: %u Page: %u "
- "contains block table\n",
- (unsigned int)g_pBTBlocks[i],
- (unsigned int)Page);
-
- tempBuf = tmp_buf2_read_blk_table;
-
- for (k = 0; k < bt_pages; k++) {
- Block = g_pBTBlocks[i];
- PageCount = 1;
-
- status =
- GLOB_LLD_Read_Page_Main_Polling(
- tempBuf, Block, Page, PageCount);
-
- tempvar = k ? 0 : 4;
-
- wBytesCopied +=
- FTL_Copy_Block_Table_From_Flash(
- tempBuf + tempvar,
- DeviceInfo.wPageDataSize - tempvar,
- wBytesCopied);
-
- Page++;
- }
-
- wResult = FTL_Check_Block_Table(FAIL);
- if (FAIL == wResult) {
- block_table_found = 0;
- if (Page > bt_pages)
- Page -= ((bt_pages<<1) + 1);
- else
- search_result = FAIL;
- }
- }
- }
- }
-
- if (PASS == wResult) {
- if (!block_table_found)
- FTL_Execute_SPL_Recovery();
-
- if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE)
- g_wBlockTableOffset = (u16)Page + 1;
- else
- g_wBlockTableOffset = (u16)Page - bt_pages;
-
- g_wBlockTableIndex = (u32)g_pBTBlocks[i];
-
-#if CMD_DMA
- if (DeviceInfo.MLCDevice)
- memcpy(g_pBTStartingCopy, g_pBlockTable,
- DeviceInfo.wDataBlockNum * sizeof(u32)
- + DeviceInfo.wDataBlockNum * sizeof(u8)
- + DeviceInfo.wDataBlockNum * sizeof(u16));
- else
- memcpy(g_pBTStartingCopy, g_pBlockTable,
- DeviceInfo.wDataBlockNum * sizeof(u32)
- + DeviceInfo.wDataBlockNum * sizeof(u8));
-#endif
- }
-
- if (FAIL == wResult)
- printk(KERN_ERR "Yunpeng - "
- "Can not find valid spectra block table!\n");
-
-#if AUTO_FORMAT_FLASH
- if (FAIL == wResult) {
- nand_dbg_print(NAND_DBG_DEBUG, "doing auto-format\n");
- wResult = FTL_Format_Flash(0);
- }
-#endif
-
- return wResult;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Get_Page_Num
-* Inputs: Size in bytes
-* Outputs: Size in pages
-* Description: It calculates the pages required for the length passed
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static u32 FTL_Get_Page_Num(u64 length)
-{
- return (u32)((length >> DeviceInfo.nBitsInPageDataSize) +
- (GLOB_u64_Remainder(length , 1) > 0 ? 1 : 0));
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Get_Physical_Block_Addr
-* Inputs: Block Address (byte format)
-* Outputs: Physical address of the block.
-* Description: It translates LBA to PBA by returning address stored
-* at the LBA location in the block table
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static u64 FTL_Get_Physical_Block_Addr(u64 logical_addr)
-{
- u32 *pbt;
- u64 physical_addr;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- pbt = (u32 *)g_pBlockTable;
- physical_addr = (u64) DeviceInfo.wBlockDataSize *
- (pbt[BLK_FROM_ADDR(logical_addr)] & (~BAD_BLOCK));
-
- return physical_addr;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Get_Block_Index
-* Inputs: Physical Block no.
-* Outputs: Logical block no. /BAD_BLOCK
-* Description: It returns the logical block no. for the PBA passed
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static u32 FTL_Get_Block_Index(u32 wBlockNum)
-{
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++)
- if (wBlockNum == (pbt[i] & (~BAD_BLOCK)))
- return i;
-
- return BAD_BLOCK;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Wear_Leveling
-* Inputs: none
-* Outputs: PASS=0
-* Description: This is static wear leveling (done by explicit call)
-* do complete static wear leveling
-* do complete garbage collection
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Wear_Leveling(void)
-{
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- FTL_Static_Wear_Leveling();
- GLOB_FTL_Garbage_Collection();
-
- return PASS;
-}
-
-static void find_least_most_worn(u8 *chg,
- u32 *least_idx, u8 *least_cnt,
- u32 *most_idx, u8 *most_cnt)
-{
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 idx;
- u8 cnt;
- int i;
-
- for (i = BLOCK_TABLE_INDEX + 1; i < DeviceInfo.wDataBlockNum; i++) {
- if (IS_BAD_BLOCK(i) || PASS == chg[i])
- continue;
-
- idx = (u32) ((~BAD_BLOCK) & pbt[i]);
- cnt = g_pWearCounter[idx - DeviceInfo.wSpectraStartBlock];
-
- if (IS_SPARE_BLOCK(i)) {
- if (cnt > *most_cnt) {
- *most_cnt = cnt;
- *most_idx = idx;
- }
- }
-
- if (IS_DATA_BLOCK(i)) {
- if (cnt < *least_cnt) {
- *least_cnt = cnt;
- *least_idx = idx;
- }
- }
-
- if (PASS == chg[*most_idx] || PASS == chg[*least_idx]) {
- debug_boundary_error(*most_idx,
- DeviceInfo.wDataBlockNum, 0);
- debug_boundary_error(*least_idx,
- DeviceInfo.wDataBlockNum, 0);
- continue;
- }
- }
-}
-
-static int move_blks_for_wear_leveling(u8 *chg,
- u32 *least_idx, u32 *rep_blk_num, int *result)
-{
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 rep_blk;
- int j, ret_cp_blk, ret_erase;
- int ret = PASS;
-
- chg[*least_idx] = PASS;
- debug_boundary_error(*least_idx, DeviceInfo.wDataBlockNum, 0);
-
- rep_blk = FTL_Replace_MWBlock();
- if (rep_blk != BAD_BLOCK) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "More than two spare blocks exist so do it\n");
- nand_dbg_print(NAND_DBG_DEBUG, "Block Replaced is %d\n",
- rep_blk);
-
- chg[rep_blk] = PASS;
-
- if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
- g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
- FTL_Write_IN_Progress_Block_Table_Page();
- }
-
- for (j = 0; j < RETRY_TIMES; j++) {
- ret_cp_blk = FTL_Copy_Block((u64)(*least_idx) *
- DeviceInfo.wBlockDataSize,
- (u64)rep_blk * DeviceInfo.wBlockDataSize);
- if (FAIL == ret_cp_blk) {
- ret_erase = GLOB_FTL_Block_Erase((u64)rep_blk
- * DeviceInfo.wBlockDataSize);
- if (FAIL == ret_erase)
- MARK_BLOCK_AS_BAD(pbt[rep_blk]);
- } else {
- nand_dbg_print(NAND_DBG_DEBUG,
- "FTL_Copy_Block == OK\n");
- break;
- }
- }
-
- if (j < RETRY_TIMES) {
- u32 tmp;
- u32 old_idx = FTL_Get_Block_Index(*least_idx);
- u32 rep_idx = FTL_Get_Block_Index(rep_blk);
- tmp = (u32)(DISCARD_BLOCK | pbt[old_idx]);
- pbt[old_idx] = (u32)((~SPARE_BLOCK) &
- pbt[rep_idx]);
- pbt[rep_idx] = tmp;
-#if CMD_DMA
- p_BTableChangesDelta = (struct BTableChangesDelta *)
- g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index = old_idx;
- p_BTableChangesDelta->BT_Entry_Value = pbt[old_idx];
- p_BTableChangesDelta->ValidFields = 0x0C;
-
- p_BTableChangesDelta = (struct BTableChangesDelta *)
- g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index = rep_idx;
- p_BTableChangesDelta->BT_Entry_Value = pbt[rep_idx];
- p_BTableChangesDelta->ValidFields = 0x0C;
-#endif
- } else {
- pbt[FTL_Get_Block_Index(rep_blk)] |= BAD_BLOCK;
-#if CMD_DMA
- p_BTableChangesDelta = (struct BTableChangesDelta *)
- g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index =
- FTL_Get_Block_Index(rep_blk);
- p_BTableChangesDelta->BT_Entry_Value =
- pbt[FTL_Get_Block_Index(rep_blk)];
- p_BTableChangesDelta->ValidFields = 0x0C;
-#endif
- *result = FAIL;
- ret = FAIL;
- }
-
- if (((*rep_blk_num)++) > WEAR_LEVELING_BLOCK_NUM)
- ret = FAIL;
- } else {
- printk(KERN_ERR "Less than 3 spare blocks exist so quit\n");
- ret = FAIL;
- }
-
- return ret;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Static_Wear_Leveling
-* Inputs: none
-* Outputs: PASS=0 / FAIL=1
-* Description: This is static wear leveling (done by explicit call)
-* search for most&least used
-* if difference < GATE:
-* update the block table with exhange
-* mark block table in flash as IN_PROGRESS
-* copy flash block
-* the caller should handle GC clean up after calling this function
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int FTL_Static_Wear_Leveling(void)
-{
- u8 most_worn_cnt;
- u8 least_worn_cnt;
- u32 most_worn_idx;
- u32 least_worn_idx;
- int result = PASS;
- int go_on = PASS;
- u32 replaced_blks = 0;
- u8 *chang_flag = flags_static_wear_leveling;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (!chang_flag)
- return FAIL;
-
- memset(chang_flag, FAIL, DeviceInfo.wDataBlockNum);
- while (go_on == PASS) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "starting static wear leveling\n");
- most_worn_cnt = 0;
- least_worn_cnt = 0xFF;
- least_worn_idx = BLOCK_TABLE_INDEX;
- most_worn_idx = BLOCK_TABLE_INDEX;
-
- find_least_most_worn(chang_flag, &least_worn_idx,
- &least_worn_cnt, &most_worn_idx, &most_worn_cnt);
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Used and least worn is block %u, whos count is %u\n",
- (unsigned int)least_worn_idx,
- (unsigned int)least_worn_cnt);
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Free and most worn is block %u, whos count is %u\n",
- (unsigned int)most_worn_idx,
- (unsigned int)most_worn_cnt);
-
- if ((most_worn_cnt > least_worn_cnt) &&
- (most_worn_cnt - least_worn_cnt > WEAR_LEVELING_GATE))
- go_on = move_blks_for_wear_leveling(chang_flag,
- &least_worn_idx, &replaced_blks, &result);
- else
- go_on = FAIL;
- }
-
- return result;
-}
-
-#if CMD_DMA
-static int do_garbage_collection(u32 discard_cnt)
-{
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 pba;
- u8 bt_block_erased = 0;
- int i, cnt, ret = FAIL;
- u64 addr;
-
- i = 0;
- while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0) &&
- ((ftl_cmd_cnt + 28) < 256)) {
- if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) &&
- (pbt[i] & DISCARD_BLOCK)) {
- if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
- g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
- FTL_Write_IN_Progress_Block_Table_Page();
- }
-
- addr = FTL_Get_Physical_Block_Addr((u64)i *
- DeviceInfo.wBlockDataSize);
- pba = BLK_FROM_ADDR(addr);
-
- for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) {
- if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "GC will erase BT block %u\n",
- (unsigned int)pba);
- discard_cnt--;
- i++;
- bt_block_erased = 1;
- break;
- }
- }
-
- if (bt_block_erased) {
- bt_block_erased = 0;
- continue;
- }
-
- addr = FTL_Get_Physical_Block_Addr((u64)i *
- DeviceInfo.wBlockDataSize);
-
- if (PASS == GLOB_FTL_Block_Erase(addr)) {
- pbt[i] &= (u32)(~DISCARD_BLOCK);
- pbt[i] |= (u32)(SPARE_BLOCK);
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)
- g_pBTDelta_Free;
- g_pBTDelta_Free +=
- sizeof(struct BTableChangesDelta);
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt - 1;
- p_BTableChangesDelta->BT_Index = i;
- p_BTableChangesDelta->BT_Entry_Value = pbt[i];
- p_BTableChangesDelta->ValidFields = 0x0C;
- discard_cnt--;
- ret = PASS;
- } else {
- MARK_BLOCK_AS_BAD(pbt[i]);
- }
- }
-
- i++;
- }
-
- return ret;
-}
-
-#else
-static int do_garbage_collection(u32 discard_cnt)
-{
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 pba;
- u8 bt_block_erased = 0;
- int i, cnt, ret = FAIL;
- u64 addr;
-
- i = 0;
- while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0)) {
- if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) &&
- (pbt[i] & DISCARD_BLOCK)) {
- if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
- g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
- FTL_Write_IN_Progress_Block_Table_Page();
- }
-
- addr = FTL_Get_Physical_Block_Addr((u64)i *
- DeviceInfo.wBlockDataSize);
- pba = BLK_FROM_ADDR(addr);
-
- for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) {
- if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "GC will erase BT block %d\n",
- pba);
- discard_cnt--;
- i++;
- bt_block_erased = 1;
- break;
- }
- }
-
- if (bt_block_erased) {
- bt_block_erased = 0;
- continue;
- }
-
- /* If the discard block is L2 cache block, then just skip it */
- for (cnt = 0; cnt < BLK_NUM_FOR_L2_CACHE; cnt++) {
- if (cache_l2.blk_array[cnt] == pba) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "GC will erase L2 cache blk %d\n",
- pba);
- break;
- }
- }
- if (cnt < BLK_NUM_FOR_L2_CACHE) { /* Skip it */
- discard_cnt--;
- i++;
- continue;
- }
-
- addr = FTL_Get_Physical_Block_Addr((u64)i *
- DeviceInfo.wBlockDataSize);
-
- if (PASS == GLOB_FTL_Block_Erase(addr)) {
- pbt[i] &= (u32)(~DISCARD_BLOCK);
- pbt[i] |= (u32)(SPARE_BLOCK);
- discard_cnt--;
- ret = PASS;
- } else {
- MARK_BLOCK_AS_BAD(pbt[i]);
- }
- }
-
- i++;
- }
-
- return ret;
-}
-#endif
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Garbage_Collection
-* Inputs: none
-* Outputs: PASS / FAIL (returns the number of un-erased blocks
-* Description: search the block table for all discarded blocks to erase
-* for each discarded block:
-* set the flash block to IN_PROGRESS
-* erase the block
-* update the block table
-* write the block table to flash
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Garbage_Collection(void)
-{
- u32 i;
- u32 wDiscard = 0;
- int wResult = FAIL;
- u32 *pbt = (u32 *)g_pBlockTable;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (GC_Called) {
- printk(KERN_ALERT "GLOB_FTL_Garbage_Collection() "
- "has been re-entered! Exit.\n");
- return PASS;
- }
-
- GC_Called = 1;
-
- GLOB_FTL_BT_Garbage_Collection();
-
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- if (IS_DISCARDED_BLOCK(i))
- wDiscard++;
- }
-
- if (wDiscard <= 0) {
- GC_Called = 0;
- return wResult;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Found %d discarded blocks\n", wDiscard);
-
- FTL_Write_Block_Table(FAIL);
-
- wResult = do_garbage_collection(wDiscard);
-
- FTL_Write_Block_Table(FAIL);
-
- GC_Called = 0;
-
- return wResult;
-}
-
-
-#if CMD_DMA
-static int do_bt_garbage_collection(void)
-{
- u32 pba, lba;
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 *pBTBlocksNode = (u32 *)g_pBTBlocks;
- u64 addr;
- int i, ret = FAIL;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (BT_GC_Called)
- return PASS;
-
- BT_GC_Called = 1;
-
- for (i = last_erased; (i <= LAST_BT_ID) &&
- (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) +
- FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) &&
- ((ftl_cmd_cnt + 28)) < 256; i++) {
- pba = pBTBlocksNode[i - FIRST_BT_ID];
- lba = FTL_Get_Block_Index(pba);
- nand_dbg_print(NAND_DBG_DEBUG,
- "do_bt_garbage_collection: pba %d, lba %d\n",
- pba, lba);
- nand_dbg_print(NAND_DBG_DEBUG,
- "Block Table Entry: %d", pbt[lba]);
-
- if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) &&
- (pbt[lba] & DISCARD_BLOCK)) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "do_bt_garbage_collection_cdma: "
- "Erasing Block tables present in block %d\n",
- pba);
- addr = FTL_Get_Physical_Block_Addr((u64)lba *
- DeviceInfo.wBlockDataSize);
- if (PASS == GLOB_FTL_Block_Erase(addr)) {
- pbt[lba] &= (u32)(~DISCARD_BLOCK);
- pbt[lba] |= (u32)(SPARE_BLOCK);
-
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)
- g_pBTDelta_Free;
- g_pBTDelta_Free +=
- sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt - 1;
- p_BTableChangesDelta->BT_Index = lba;
- p_BTableChangesDelta->BT_Entry_Value =
- pbt[lba];
-
- p_BTableChangesDelta->ValidFields = 0x0C;
-
- ret = PASS;
- pBTBlocksNode[last_erased - FIRST_BT_ID] =
- BTBLOCK_INVAL;
- nand_dbg_print(NAND_DBG_DEBUG,
- "resetting bt entry at index %d "
- "value %d\n", i,
- pBTBlocksNode[i - FIRST_BT_ID]);
- if (last_erased == LAST_BT_ID)
- last_erased = FIRST_BT_ID;
- else
- last_erased++;
- } else {
- MARK_BLOCK_AS_BAD(pbt[lba]);
- }
- }
- }
-
- BT_GC_Called = 0;
-
- return ret;
-}
-
-#else
-static int do_bt_garbage_collection(void)
-{
- u32 pba, lba;
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 *pBTBlocksNode = (u32 *)g_pBTBlocks;
- u64 addr;
- int i, ret = FAIL;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (BT_GC_Called)
- return PASS;
-
- BT_GC_Called = 1;
-
- for (i = last_erased; (i <= LAST_BT_ID) &&
- (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) +
- FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL); i++) {
- pba = pBTBlocksNode[i - FIRST_BT_ID];
- lba = FTL_Get_Block_Index(pba);
- nand_dbg_print(NAND_DBG_DEBUG,
- "do_bt_garbage_collection_cdma: pba %d, lba %d\n",
- pba, lba);
- nand_dbg_print(NAND_DBG_DEBUG,
- "Block Table Entry: %d", pbt[lba]);
-
- if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) &&
- (pbt[lba] & DISCARD_BLOCK)) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "do_bt_garbage_collection: "
- "Erasing Block tables present in block %d\n",
- pba);
- addr = FTL_Get_Physical_Block_Addr((u64)lba *
- DeviceInfo.wBlockDataSize);
- if (PASS == GLOB_FTL_Block_Erase(addr)) {
- pbt[lba] &= (u32)(~DISCARD_BLOCK);
- pbt[lba] |= (u32)(SPARE_BLOCK);
- ret = PASS;
- pBTBlocksNode[last_erased - FIRST_BT_ID] =
- BTBLOCK_INVAL;
- nand_dbg_print(NAND_DBG_DEBUG,
- "resetting bt entry at index %d "
- "value %d\n", i,
- pBTBlocksNode[i - FIRST_BT_ID]);
- if (last_erased == LAST_BT_ID)
- last_erased = FIRST_BT_ID;
- else
- last_erased++;
- } else {
- MARK_BLOCK_AS_BAD(pbt[lba]);
- }
- }
- }
-
- BT_GC_Called = 0;
-
- return ret;
-}
-
-#endif
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_BT_Garbage_Collection
-* Inputs: none
-* Outputs: PASS / FAIL (returns the number of un-erased blocks
-* Description: Erases discarded blocks containing Block table
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_BT_Garbage_Collection(void)
-{
- return do_bt_garbage_collection();
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Replace_OneBlock
-* Inputs: Block number 1
-* Block number 2
-* Outputs: Replaced Block Number
-* Description: Interchange block table entries at wBlockNum and wReplaceNum
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static u32 FTL_Replace_OneBlock(u32 blk, u32 rep_blk)
-{
- u32 tmp_blk;
- u32 replace_node = BAD_BLOCK;
- u32 *pbt = (u32 *)g_pBlockTable;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (rep_blk != BAD_BLOCK) {
- if (IS_BAD_BLOCK(blk))
- tmp_blk = pbt[blk];
- else
- tmp_blk = DISCARD_BLOCK | (~SPARE_BLOCK & pbt[blk]);
-
- replace_node = (u32) ((~SPARE_BLOCK) & pbt[rep_blk]);
- pbt[blk] = replace_node;
- pbt[rep_blk] = tmp_blk;
-
-#if CMD_DMA
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index = blk;
- p_BTableChangesDelta->BT_Entry_Value = pbt[blk];
-
- p_BTableChangesDelta->ValidFields = 0x0C;
-
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index = rep_blk;
- p_BTableChangesDelta->BT_Entry_Value = pbt[rep_blk];
- p_BTableChangesDelta->ValidFields = 0x0C;
-#endif
- }
-
- return replace_node;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Write_Block_Table_Data
-* Inputs: Block table size in pages
-* Outputs: PASS=0 / FAIL=1
-* Description: Write block table data in flash
-* If first page and last page
-* Write data+BT flag
-* else
-* Write data
-* BT flag is a counter. Its value is incremented for block table
-* write in a new Block
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Write_Block_Table_Data(void)
-{
- u64 dwBlockTableAddr, pTempAddr;
- u32 Block;
- u16 Page, PageCount;
- u8 *tempBuf = tmp_buf_write_blk_table_data;
- int wBytesCopied;
- u16 bt_pages;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- dwBlockTableAddr =
- (u64)((u64)g_wBlockTableIndex * DeviceInfo.wBlockDataSize +
- (u64)g_wBlockTableOffset * DeviceInfo.wPageDataSize);
- pTempAddr = dwBlockTableAddr;
-
- bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
-
- nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: "
- "page= %d BlockTableIndex= %d "
- "BlockTableOffset=%d\n", bt_pages,
- g_wBlockTableIndex, g_wBlockTableOffset);
-
- Block = BLK_FROM_ADDR(pTempAddr);
- Page = PAGE_FROM_ADDR(pTempAddr, Block);
- PageCount = 1;
-
- if (bt_block_changed) {
- if (bt_flag == LAST_BT_ID) {
- bt_flag = FIRST_BT_ID;
- g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block;
- } else if (bt_flag < LAST_BT_ID) {
- bt_flag++;
- g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block;
- }
-
- if ((bt_flag > (LAST_BT_ID-4)) &&
- g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] !=
- BTBLOCK_INVAL) {
- bt_block_changed = 0;
- GLOB_FTL_BT_Garbage_Collection();
- }
-
- bt_block_changed = 0;
- nand_dbg_print(NAND_DBG_DEBUG,
- "Block Table Counter is %u Block %u\n",
- bt_flag, (unsigned int)Block);
- }
-
- memset(tempBuf, 0, 3);
- tempBuf[3] = bt_flag;
- wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf + 4,
- DeviceInfo.wPageDataSize - 4, 0);
- memset(&tempBuf[wBytesCopied + 4], 0xff,
- DeviceInfo.wPageSize - (wBytesCopied + 4));
- FTL_Insert_Block_Table_Signature(&tempBuf[DeviceInfo.wPageDataSize],
- bt_flag);
-
-#if CMD_DMA
- memcpy(g_pNextBlockTable, tempBuf,
- DeviceInfo.wPageSize * sizeof(u8));
- nand_dbg_print(NAND_DBG_DEBUG, "Writing First Page of Block Table "
- "Block %u Page %u\n", (unsigned int)Block, Page);
- if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma(g_pNextBlockTable,
- Block, Page, 1,
- LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST)) {
- nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in "
- "%s, Line %d, Function: %s, "
- "new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__, Block);
- goto func_return;
- }
-
- ftl_cmd_cnt++;
- g_pNextBlockTable += ((DeviceInfo.wPageSize * sizeof(u8)));
-#else
- if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, Block, Page, 1)) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, Function: %s, "
- "new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__, Block);
- goto func_return;
- }
-#endif
-
- if (bt_pages > 1) {
- PageCount = bt_pages - 1;
- if (PageCount > 1) {
- wBytesCopied += FTL_Copy_Block_Table_To_Flash(tempBuf,
- DeviceInfo.wPageDataSize * (PageCount - 1),
- wBytesCopied);
-
-#if CMD_DMA
- memcpy(g_pNextBlockTable, tempBuf,
- (PageCount - 1) * DeviceInfo.wPageDataSize);
- if (FAIL == GLOB_LLD_Write_Page_Main_cdma(
- g_pNextBlockTable, Block, Page + 1,
- PageCount - 1)) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, "
- "new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__,
- (int)Block);
- goto func_return;
- }
-
- ftl_cmd_cnt++;
- g_pNextBlockTable += (PageCount - 1) *
- DeviceInfo.wPageDataSize * sizeof(u8);
-#else
- if (FAIL == GLOB_LLD_Write_Page_Main(tempBuf,
- Block, Page + 1, PageCount - 1)) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, "
- "new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__,
- (int)Block);
- goto func_return;
- }
-#endif
- }
-
- wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf,
- DeviceInfo.wPageDataSize, wBytesCopied);
- memset(&tempBuf[wBytesCopied], 0xff,
- DeviceInfo.wPageSize-wBytesCopied);
- FTL_Insert_Block_Table_Signature(
- &tempBuf[DeviceInfo.wPageDataSize], bt_flag);
-#if CMD_DMA
- memcpy(g_pNextBlockTable, tempBuf,
- DeviceInfo.wPageSize * sizeof(u8));
- nand_dbg_print(NAND_DBG_DEBUG,
- "Writing the last Page of Block Table "
- "Block %u Page %u\n",
- (unsigned int)Block, Page + bt_pages - 1);
- if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma(
- g_pNextBlockTable, Block, Page + bt_pages - 1, 1,
- LLD_CMD_FLAG_MODE_CDMA |
- LLD_CMD_FLAG_ORDER_BEFORE_REST)) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__, Block);
- goto func_return;
- }
- ftl_cmd_cnt++;
-#else
- if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf,
- Block, Page+bt_pages - 1, 1)) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, "
- "new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__, Block);
- goto func_return;
- }
-#endif
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: done\n");
-
-func_return:
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Replace_Block_Table
-* Inputs: None
-* Outputs: PASS=0 / FAIL=1
-* Description: Get a new block to write block table
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static u32 FTL_Replace_Block_Table(void)
-{
- u32 blk;
- int gc;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc);
-
- if ((BAD_BLOCK == blk) && (PASS == gc)) {
- GLOB_FTL_Garbage_Collection();
- blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc);
- }
- if (BAD_BLOCK == blk)
- printk(KERN_ERR "%s, %s: There is no spare block. "
- "It should never happen\n",
- __FILE__, __func__);
-
- nand_dbg_print(NAND_DBG_DEBUG, "New Block table Block is %d\n", blk);
-
- return blk;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Replace_LWBlock
-* Inputs: Block number
-* Pointer to Garbage Collect flag
-* Outputs:
-* Description: Determine the least weared block by traversing
-* block table
-* Set Garbage collection to be called if number of spare
-* block is less than Free Block Gate count
-* Change Block table entry to map least worn block for current
-* operation
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static u32 FTL_Replace_LWBlock(u32 wBlockNum, int *pGarbageCollect)
-{
- u32 i;
- u32 *pbt = (u32 *)g_pBlockTable;
- u8 wLeastWornCounter = 0xFF;
- u32 wLeastWornIndex = BAD_BLOCK;
- u32 wSpareBlockNum = 0;
- u32 wDiscardBlockNum = 0;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (IS_SPARE_BLOCK(wBlockNum)) {
- *pGarbageCollect = FAIL;
- pbt[wBlockNum] = (u32)(pbt[wBlockNum] & (~SPARE_BLOCK));
-#if CMD_DMA
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index = (u32)(wBlockNum);
- p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum];
- p_BTableChangesDelta->ValidFields = 0x0C;
-#endif
- return pbt[wBlockNum];
- }
-
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- if (IS_DISCARDED_BLOCK(i))
- wDiscardBlockNum++;
-
- if (IS_SPARE_BLOCK(i)) {
- u32 wPhysicalIndex = (u32)((~BAD_BLOCK) & pbt[i]);
- if (wPhysicalIndex > DeviceInfo.wSpectraEndBlock)
- printk(KERN_ERR "FTL_Replace_LWBlock: "
- "This should never occur!\n");
- if (g_pWearCounter[wPhysicalIndex -
- DeviceInfo.wSpectraStartBlock] <
- wLeastWornCounter) {
- wLeastWornCounter =
- g_pWearCounter[wPhysicalIndex -
- DeviceInfo.wSpectraStartBlock];
- wLeastWornIndex = i;
- }
- wSpareBlockNum++;
- }
- }
-
- nand_dbg_print(NAND_DBG_WARN,
- "FTL_Replace_LWBlock: Least Worn Counter %d\n",
- (int)wLeastWornCounter);
-
- if ((wDiscardBlockNum >= NUM_FREE_BLOCKS_GATE) ||
- (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE))
- *pGarbageCollect = PASS;
- else
- *pGarbageCollect = FAIL;
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "FTL_Replace_LWBlock: Discarded Blocks %u Spare"
- " Blocks %u\n",
- (unsigned int)wDiscardBlockNum,
- (unsigned int)wSpareBlockNum);
-
- return FTL_Replace_OneBlock(wBlockNum, wLeastWornIndex);
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Replace_MWBlock
-* Inputs: None
-* Outputs: most worn spare block no./BAD_BLOCK
-* Description: It finds most worn spare block.
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static u32 FTL_Replace_MWBlock(void)
-{
- u32 i;
- u32 *pbt = (u32 *)g_pBlockTable;
- u8 wMostWornCounter = 0;
- u32 wMostWornIndex = BAD_BLOCK;
- u32 wSpareBlockNum = 0;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- if (IS_SPARE_BLOCK(i)) {
- u32 wPhysicalIndex = (u32)((~SPARE_BLOCK) & pbt[i]);
- if (g_pWearCounter[wPhysicalIndex -
- DeviceInfo.wSpectraStartBlock] >
- wMostWornCounter) {
- wMostWornCounter =
- g_pWearCounter[wPhysicalIndex -
- DeviceInfo.wSpectraStartBlock];
- wMostWornIndex = wPhysicalIndex;
- }
- wSpareBlockNum++;
- }
- }
-
- if (wSpareBlockNum <= 2)
- return BAD_BLOCK;
-
- return wMostWornIndex;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Replace_Block
-* Inputs: Block Address
-* Outputs: PASS=0 / FAIL=1
-* Description: If block specified by blk_addr parameter is not free,
-* replace it with the least worn block.
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Replace_Block(u64 blk_addr)
-{
- u32 current_blk = BLK_FROM_ADDR(blk_addr);
- u32 *pbt = (u32 *)g_pBlockTable;
- int wResult = PASS;
- int GarbageCollect = FAIL;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (IS_SPARE_BLOCK(current_blk)) {
- pbt[current_blk] = (~SPARE_BLOCK) & pbt[current_blk];
-#if CMD_DMA
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index = current_blk;
- p_BTableChangesDelta->BT_Entry_Value = pbt[current_blk];
- p_BTableChangesDelta->ValidFields = 0x0C ;
-#endif
- return wResult;
- }
-
- FTL_Replace_LWBlock(current_blk, &GarbageCollect);
-
- if (PASS == GarbageCollect)
- wResult = GLOB_FTL_Garbage_Collection();
-
- return wResult;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Is_BadBlock
-* Inputs: block number to test
-* Outputs: PASS (block is BAD) / FAIL (block is not bad)
-* Description: test if this block number is flagged as bad
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Is_BadBlock(u32 wBlockNum)
-{
- u32 *pbt = (u32 *)g_pBlockTable;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (wBlockNum >= DeviceInfo.wSpectraStartBlock
- && BAD_BLOCK == (pbt[wBlockNum] & BAD_BLOCK))
- return PASS;
- else
- return FAIL;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Flush_Cache
-* Inputs: none
-* Outputs: PASS=0 / FAIL=1
-* Description: flush all the cache blocks to flash
-* if a cache block is not dirty, don't do anything with it
-* else, write the block and update the block table
-* Note: This function should be called at shutdown/power down.
-* to write important data into device
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Flush_Cache(void)
-{
- int i, ret;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < CACHE_ITEM_NUM; i++) {
- if (SET == Cache.array[i].changed) {
-#if CMD_DMA
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
- int_cache[ftl_cmd_cnt].item = i;
- int_cache[ftl_cmd_cnt].cache.address =
- Cache.array[i].address;
- int_cache[ftl_cmd_cnt].cache.changed = CLEAR;
-#endif
-#endif
- ret = write_back_to_l2_cache(Cache.array[i].buf, Cache.array[i].address);
- if (PASS == ret) {
- Cache.array[i].changed = CLEAR;
- } else {
- printk(KERN_ALERT "Failed when write back to L2 cache!\n");
- /* TODO - How to handle this? */
- }
- }
- }
-
- flush_l2_cache();
-
- return FTL_Write_Block_Table(FAIL);
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Page_Read
-* Inputs: pointer to data
-* logical address of data (u64 is LBA * Bytes/Page)
-* Outputs: PASS=0 / FAIL=1
-* Description: reads a page of data into RAM from the cache
-* if the data is not already in cache, read from flash to cache
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Page_Read(u8 *data, u64 logical_addr)
-{
- u16 cache_item;
- int res = PASS;
-
- nand_dbg_print(NAND_DBG_DEBUG, "GLOB_FTL_Page_Read - "
- "page_addr: %llu\n", logical_addr);
-
- cache_item = FTL_Cache_If_Hit(logical_addr);
-
- if (UNHIT_CACHE_ITEM == cache_item) {
- nand_dbg_print(NAND_DBG_DEBUG,
- "GLOB_FTL_Page_Read: Cache not hit\n");
- res = FTL_Cache_Write();
- if (ERR == FTL_Cache_Read(logical_addr))
- res = ERR;
- cache_item = Cache.LRU;
- }
-
- FTL_Cache_Read_Page(data, logical_addr, cache_item);
-
- return res;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Page_Write
-* Inputs: pointer to data
-* address of data (ADDRESSTYPE is LBA * Bytes/Page)
-* Outputs: PASS=0 / FAIL=1
-* Description: writes a page of data from RAM to the cache
-* if the data is not already in cache, write back the
-* least recently used block and read the addressed block
-* from flash to cache
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Page_Write(u8 *pData, u64 dwPageAddr)
-{
- u16 cache_blk;
- u32 *pbt = (u32 *)g_pBlockTable;
- int wResult = PASS;
-
- nand_dbg_print(NAND_DBG_TRACE, "GLOB_FTL_Page_Write - "
- "dwPageAddr: %llu\n", dwPageAddr);
-
- cache_blk = FTL_Cache_If_Hit(dwPageAddr);
-
- if (UNHIT_CACHE_ITEM == cache_blk) {
- wResult = FTL_Cache_Write();
- if (IS_BAD_BLOCK(BLK_FROM_ADDR(dwPageAddr))) {
- wResult = FTL_Replace_Block(dwPageAddr);
- pbt[BLK_FROM_ADDR(dwPageAddr)] |= SPARE_BLOCK;
- if (wResult == FAIL)
- return FAIL;
- }
- if (ERR == FTL_Cache_Read(dwPageAddr))
- wResult = ERR;
- cache_blk = Cache.LRU;
- FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0);
- } else {
-#if CMD_DMA
- FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk,
- LLD_CMD_FLAG_ORDER_BEFORE_REST);
-#else
- FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0);
-#endif
- }
-
- return wResult;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: GLOB_FTL_Block_Erase
-* Inputs: address of block to erase (now in byte format, should change to
-* block format)
-* Outputs: PASS=0 / FAIL=1
-* Description: erases the specified block
-* increments the erase count
-* If erase count reaches its upper limit,call function to
-* do the adjustment as per the relative erase count values
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int GLOB_FTL_Block_Erase(u64 blk_addr)
-{
- int status;
- u32 BlkIdx;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- BlkIdx = (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize);
-
- if (BlkIdx < DeviceInfo.wSpectraStartBlock) {
- printk(KERN_ERR "GLOB_FTL_Block_Erase: "
- "This should never occur\n");
- return FAIL;
- }
-
-#if CMD_DMA
- status = GLOB_LLD_Erase_Block_cdma(BlkIdx, LLD_CMD_FLAG_MODE_CDMA);
- if (status == FAIL)
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__, BlkIdx);
-#else
- status = GLOB_LLD_Erase_Block(BlkIdx);
- if (status == FAIL) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__, BlkIdx);
- return status;
- }
-#endif
-
- if (DeviceInfo.MLCDevice) {
- g_pReadCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] = 0;
- if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) {
- g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
- FTL_Write_IN_Progress_Block_Table_Page();
- }
- }
-
- g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]++;
-
-#if CMD_DMA
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
- p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
- p_BTableChangesDelta->WC_Index =
- BlkIdx - DeviceInfo.wSpectraStartBlock;
- p_BTableChangesDelta->WC_Entry_Value =
- g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock];
- p_BTableChangesDelta->ValidFields = 0x30;
-
- if (DeviceInfo.MLCDevice) {
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->RC_Index =
- BlkIdx - DeviceInfo.wSpectraStartBlock;
- p_BTableChangesDelta->RC_Entry_Value =
- g_pReadCounter[BlkIdx -
- DeviceInfo.wSpectraStartBlock];
- p_BTableChangesDelta->ValidFields = 0xC0;
- }
-
- ftl_cmd_cnt++;
-#endif
-
- if (g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] == 0xFE)
- FTL_Adjust_Relative_Erase_Count(BlkIdx);
-
- return status;
-}
-
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Adjust_Relative_Erase_Count
-* Inputs: index to block that was just incremented and is at the max
-* Outputs: PASS=0 / FAIL=1
-* Description: If any erase counts at MAX, adjusts erase count of every
-* block by subtracting least worn
-* counter from counter value of every entry in wear table
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX)
-{
- u8 wLeastWornCounter = MAX_BYTE_VALUE;
- u8 wWearCounter;
- u32 i, wWearIndex;
- u32 *pbt = (u32 *)g_pBlockTable;
- int wResult = PASS;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
- if (IS_BAD_BLOCK(i))
- continue;
- wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK));
-
- if ((wWearIndex - DeviceInfo.wSpectraStartBlock) < 0)
- printk(KERN_ERR "FTL_Adjust_Relative_Erase_Count:"
- "This should never occur\n");
- wWearCounter = g_pWearCounter[wWearIndex -
- DeviceInfo.wSpectraStartBlock];
- if (wWearCounter < wLeastWornCounter)
- wLeastWornCounter = wWearCounter;
- }
-
- if (wLeastWornCounter == 0) {
- nand_dbg_print(NAND_DBG_WARN,
- "Adjusting Wear Levelling Counters: Special Case\n");
- g_pWearCounter[Index_of_MAX -
- DeviceInfo.wSpectraStartBlock]--;
-#if CMD_DMA
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
- p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
- p_BTableChangesDelta->WC_Index =
- Index_of_MAX - DeviceInfo.wSpectraStartBlock;
- p_BTableChangesDelta->WC_Entry_Value =
- g_pWearCounter[Index_of_MAX -
- DeviceInfo.wSpectraStartBlock];
- p_BTableChangesDelta->ValidFields = 0x30;
-#endif
- FTL_Static_Wear_Leveling();
- } else {
- for (i = 0; i < DeviceInfo.wDataBlockNum; i++)
- if (!IS_BAD_BLOCK(i)) {
- wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK));
- g_pWearCounter[wWearIndex -
- DeviceInfo.wSpectraStartBlock] =
- (u8)(g_pWearCounter
- [wWearIndex -
- DeviceInfo.wSpectraStartBlock] -
- wLeastWornCounter);
-#if CMD_DMA
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free +=
- sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->WC_Index = wWearIndex -
- DeviceInfo.wSpectraStartBlock;
- p_BTableChangesDelta->WC_Entry_Value =
- g_pWearCounter[wWearIndex -
- DeviceInfo.wSpectraStartBlock];
- p_BTableChangesDelta->ValidFields = 0x30;
-#endif
- }
- }
-
- return wResult;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Write_IN_Progress_Block_Table_Page
-* Inputs: None
-* Outputs: None
-* Description: It writes in-progress flag page to the page next to
-* block table
-***********************************************************************/
-static int FTL_Write_IN_Progress_Block_Table_Page(void)
-{
- int wResult = PASS;
- u16 bt_pages;
- u16 dwIPFPageAddr;
-#if CMD_DMA
-#else
- u32 *pbt = (u32 *)g_pBlockTable;
- u32 wTempBlockTableIndex;
-#endif
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
-
- dwIPFPageAddr = g_wBlockTableOffset + bt_pages;
-
- nand_dbg_print(NAND_DBG_DEBUG, "Writing IPF at "
- "Block %d Page %d\n",
- g_wBlockTableIndex, dwIPFPageAddr);
-
-#if CMD_DMA
- wResult = GLOB_LLD_Write_Page_Main_Spare_cdma(g_pIPF,
- g_wBlockTableIndex, dwIPFPageAddr, 1,
- LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST);
- if (wResult == FAIL) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__,
- g_wBlockTableIndex);
- }
- g_wBlockTableOffset = dwIPFPageAddr + 1;
- p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
- p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
- p_BTableChangesDelta->g_wBlockTableOffset = g_wBlockTableOffset;
- p_BTableChangesDelta->ValidFields = 0x01;
- ftl_cmd_cnt++;
-#else
- wResult = GLOB_LLD_Write_Page_Main_Spare(g_pIPF,
- g_wBlockTableIndex, dwIPFPageAddr, 1);
- if (wResult == FAIL) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in %s, Line %d, "
- "Function: %s, new Bad Block %d generated!\n",
- __FILE__, __LINE__, __func__,
- (int)g_wBlockTableIndex);
- MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]);
- wTempBlockTableIndex = FTL_Replace_Block_Table();
- bt_block_changed = 1;
- if (BAD_BLOCK == wTempBlockTableIndex)
- return ERR;
- g_wBlockTableIndex = wTempBlockTableIndex;
- g_wBlockTableOffset = 0;
- /* Block table tag is '00'. Means it's used one */
- pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex;
- return FAIL;
- }
- g_wBlockTableOffset = dwIPFPageAddr + 1;
-#endif
- return wResult;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: FTL_Read_Disturbance
-* Inputs: block address
-* Outputs: PASS=0 / FAIL=1
-* Description: used to handle read disturbance. Data in block that
-* reaches its read limit is moved to new block
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int FTL_Read_Disturbance(u32 blk_addr)
-{
- int wResult = FAIL;
- u32 *pbt = (u32 *) g_pBlockTable;
- u32 dwOldBlockAddr = blk_addr;
- u32 wBlockNum;
- u32 i;
- u32 wLeastReadCounter = 0xFFFF;
- u32 wLeastReadIndex = BAD_BLOCK;
- u32 wSpareBlockNum = 0;
- u32 wTempNode;
- u32 wReplacedNode;
- u8 *g_pTempBuf;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
-#if CMD_DMA
- g_pTempBuf = cp_back_buf_copies[cp_back_buf_idx];
- cp_back_buf_idx++;
- if (cp_back_buf_idx > COPY_BACK_BUF_NUM) {
- printk(KERN_ERR "cp_back_buf_copies overflow! Exit."
- "Maybe too many pending commands in your CDMA chain.\n");
- return FAIL;
- }
-#else
- g_pTempBuf = tmp_buf_read_disturbance;
-#endif
-
- wBlockNum = FTL_Get_Block_Index(blk_addr);
-
- do {
- /* This is a bug.Here 'i' should be logical block number
- * and start from 1 (0 is reserved for block table).
- * Have fixed it. - Yunpeng 2008. 12. 19
- */
- for (i = 1; i < DeviceInfo.wDataBlockNum; i++) {
- if (IS_SPARE_BLOCK(i)) {
- u32 wPhysicalIndex =
- (u32)((~SPARE_BLOCK) & pbt[i]);
- if (g_pReadCounter[wPhysicalIndex -
- DeviceInfo.wSpectraStartBlock] <
- wLeastReadCounter) {
- wLeastReadCounter =
- g_pReadCounter[wPhysicalIndex -
- DeviceInfo.wSpectraStartBlock];
- wLeastReadIndex = i;
- }
- wSpareBlockNum++;
- }
- }
-
- if (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE) {
- wResult = GLOB_FTL_Garbage_Collection();
- if (PASS == wResult)
- continue;
- else
- break;
- } else {
- wTempNode = (u32)(DISCARD_BLOCK | pbt[wBlockNum]);
- wReplacedNode = (u32)((~SPARE_BLOCK) &
- pbt[wLeastReadIndex]);
-#if CMD_DMA
- pbt[wBlockNum] = wReplacedNode;
- pbt[wLeastReadIndex] = wTempNode;
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index = wBlockNum;
- p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum];
- p_BTableChangesDelta->ValidFields = 0x0C;
-
- p_BTableChangesDelta =
- (struct BTableChangesDelta *)g_pBTDelta_Free;
- g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
-
- p_BTableChangesDelta->ftl_cmd_cnt =
- ftl_cmd_cnt;
- p_BTableChangesDelta->BT_Index = wLeastReadIndex;
- p_BTableChangesDelta->BT_Entry_Value =
- pbt[wLeastReadIndex];
- p_BTableChangesDelta->ValidFields = 0x0C;
-
- wResult = GLOB_LLD_Read_Page_Main_cdma(g_pTempBuf,
- dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock,
- LLD_CMD_FLAG_MODE_CDMA);
- if (wResult == FAIL)
- return wResult;
-
- ftl_cmd_cnt++;
-
- if (wResult != FAIL) {
- if (FAIL == GLOB_LLD_Write_Page_Main_cdma(
- g_pTempBuf, pbt[wBlockNum], 0,
- DeviceInfo.wPagesPerBlock)) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in "
- "%s, Line %d, Function: %s, "
- "new Bad Block %d "
- "generated!\n",
- __FILE__, __LINE__, __func__,
- (int)pbt[wBlockNum]);
- wResult = FAIL;
- MARK_BLOCK_AS_BAD(pbt[wBlockNum]);
- }
- ftl_cmd_cnt++;
- }
-#else
- wResult = GLOB_LLD_Read_Page_Main(g_pTempBuf,
- dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock);
- if (wResult == FAIL)
- return wResult;
-
- if (wResult != FAIL) {
- /* This is a bug. At this time, pbt[wBlockNum]
- is still the physical address of
- discard block, and should not be write.
- Have fixed it as below.
- -- Yunpeng 2008.12.19
- */
- wResult = GLOB_LLD_Write_Page_Main(g_pTempBuf,
- wReplacedNode, 0,
- DeviceInfo.wPagesPerBlock);
- if (wResult == FAIL) {
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Program fail in "
- "%s, Line %d, Function: %s, "
- "new Bad Block %d "
- "generated!\n",
- __FILE__, __LINE__, __func__,
- (int)wReplacedNode);
- MARK_BLOCK_AS_BAD(wReplacedNode);
- } else {
- pbt[wBlockNum] = wReplacedNode;
- pbt[wLeastReadIndex] = wTempNode;
- }
- }
-
- if ((wResult == PASS) && (g_cBlockTableStatus !=
- IN_PROGRESS_BLOCK_TABLE)) {
- g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
- FTL_Write_IN_Progress_Block_Table_Page();
- }
-#endif
- }
- } while (wResult != PASS)
- ;
-
-#if CMD_DMA
- /* ... */
-#endif
-
- return wResult;
-}
-
diff --git a/drivers/staging/spectra/flash.h b/drivers/staging/spectra/flash.h
deleted file mode 100644
index e59cf4ede551..000000000000
--- a/drivers/staging/spectra/flash.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef _FLASH_INTERFACE_
-#define _FLASH_INTERFACE_
-
-#include "ffsport.h"
-#include "spectraswconfig.h"
-
-#define MAX_BYTE_VALUE 0xFF
-#define MAX_WORD_VALUE 0xFFFF
-#define MAX_U32_VALUE 0xFFFFFFFF
-
-#define MAX_BLOCKNODE_VALUE 0xFFFFFF
-#define DISCARD_BLOCK 0x800000
-#define SPARE_BLOCK 0x400000
-#define BAD_BLOCK 0xC00000
-
-#define UNHIT_CACHE_ITEM 0xFFFF
-
-#define NAND_CACHE_INIT_ADDR 0xffffffffffffffffULL
-
-#define IN_PROGRESS_BLOCK_TABLE 0x00
-#define CURRENT_BLOCK_TABLE 0x01
-
-#define BTSIG_OFFSET (0)
-#define BTSIG_BYTES (5)
-#define BTSIG_DELTA (3)
-
-#define MAX_READ_COUNTER 0x2710
-
-#define FIRST_BT_ID (1)
-#define LAST_BT_ID (254)
-#define BTBLOCK_INVAL (u32)(0xFFFFFFFF)
-
-struct device_info_tag {
- u16 wDeviceMaker;
- u16 wDeviceID;
- u32 wDeviceType;
- u32 wSpectraStartBlock;
- u32 wSpectraEndBlock;
- u32 wTotalBlocks;
- u16 wPagesPerBlock;
- u16 wPageSize;
- u16 wPageDataSize;
- u16 wPageSpareSize;
- u16 wNumPageSpareFlag;
- u16 wECCBytesPerSector;
- u32 wBlockSize;
- u32 wBlockDataSize;
- u32 wDataBlockNum;
- u8 bPlaneNum;
- u16 wDeviceMainAreaSize;
- u16 wDeviceSpareAreaSize;
- u16 wDevicesConnected;
- u16 wDeviceWidth;
- u16 wHWRevision;
- u16 wHWFeatures;
-
- u16 wONFIDevFeatures;
- u16 wONFIOptCommands;
- u16 wONFITimingMode;
- u16 wONFIPgmCacheTimingMode;
-
- u16 MLCDevice;
- u16 wSpareSkipBytes;
-
- u8 nBitsInPageNumber;
- u8 nBitsInPageDataSize;
- u8 nBitsInBlockDataSize;
-};
-
-extern struct device_info_tag DeviceInfo;
-
-/* Cache item format */
-struct flash_cache_item_tag {
- u64 address;
- u16 use_cnt;
- u16 changed;
- u8 *buf;
-};
-
-struct flash_cache_tag {
- u32 cache_item_size; /* Size in bytes of each cache item */
- u16 pages_per_item; /* How many NAND pages in each cache item */
- u16 LRU; /* No. of the least recently used cache item */
- struct flash_cache_item_tag array[CACHE_ITEM_NUM];
-};
-
-/*
- *Data structure for each list node of the management table
- * used for the Level 2 Cache. Each node maps one logical NAND block.
- */
-struct spectra_l2_cache_list {
- struct list_head list;
- u32 logical_blk_num; /* Logical block number */
- u32 pages_array[]; /* Page map array of this logical block.
- * Array index is the logical block number,
- * and for every item of this arry:
- * high 16 bit is index of the L2 cache block num,
- * low 16 bit is the phy page num
- * of the above L2 cache block.
- * This array will be kmalloc during run time.
- */
-};
-
-struct spectra_l2_cache_info {
- u32 blk_array[BLK_NUM_FOR_L2_CACHE];
- u16 cur_blk_idx; /* idx to the phy block number of current using */
- u16 cur_page_num; /* pages number of current using */
- struct spectra_l2_cache_list table; /* First node of the table */
-};
-
-#define RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE 1
-
-#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
-struct flash_cache_mod_item_tag {
- u64 address;
- u8 changed;
-};
-
-struct flash_cache_delta_list_tag {
- u8 item; /* used cache item */
- struct flash_cache_mod_item_tag cache;
-};
-#endif
-
-extern struct flash_cache_tag Cache;
-
-extern u8 *buf_read_page_main_spare;
-extern u8 *buf_write_page_main_spare;
-extern u8 *buf_read_page_spare;
-extern u8 *buf_get_bad_block;
-extern u8 *cdma_desc_buf;
-extern u8 *memcp_desc_buf;
-
-/* struture used for IndentfyDevice function */
-struct spectra_indentfy_dev_tag {
- u32 NumBlocks;
- u16 PagesPerBlock;
- u16 PageDataSize;
- u16 wECCBytesPerSector;
- u32 wDataBlockNum;
-};
-
-int GLOB_FTL_Flash_Init(void);
-int GLOB_FTL_Flash_Release(void);
-/*void GLOB_FTL_Erase_Flash(void);*/
-int GLOB_FTL_Block_Erase(u64 block_addr);
-int GLOB_FTL_Is_BadBlock(u32 block_num);
-int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data);
-int GLOB_FTL_Event_Status(int *);
-u16 glob_ftl_execute_cmds(void);
-
-/*int FTL_Read_Disturbance(ADDRESSTYPE dwBlockAddr);*/
-int FTL_Read_Disturbance(u32 dwBlockAddr);
-
-/*Flash r/w based on cache*/
-int GLOB_FTL_Page_Read(u8 *read_data, u64 page_addr);
-int GLOB_FTL_Page_Write(u8 *write_data, u64 page_addr);
-int GLOB_FTL_Wear_Leveling(void);
-int GLOB_FTL_Flash_Format(void);
-int GLOB_FTL_Init(void);
-int GLOB_FTL_Flush_Cache(void);
-int GLOB_FTL_Garbage_Collection(void);
-int GLOB_FTL_BT_Garbage_Collection(void);
-void GLOB_FTL_Cache_Release(void);
-u8 *get_blk_table_start_addr(void);
-u8 *get_wear_leveling_table_start_addr(void);
-unsigned long get_blk_table_len(void);
-unsigned long get_wear_leveling_table_len(void);
-
-#if DEBUG_BNDRY
-void debug_boundary_lineno_error(int chnl, int limit, int no, int lineno,
- char *filename);
-#define debug_boundary_error(chnl, limit, no) debug_boundary_lineno_error(chnl,\
- limit, no, __LINE__, __FILE__)
-#else
-#define debug_boundary_error(chnl, limit, no) ;
-#endif
-
-#endif /*_FLASH_INTERFACE_*/
diff --git a/drivers/staging/spectra/lld.c b/drivers/staging/spectra/lld.c
deleted file mode 100644
index 5c3b9762dc3e..000000000000
--- a/drivers/staging/spectra/lld.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "spectraswconfig.h"
-#include "ffsport.h"
-#include "ffsdefs.h"
-#include "lld.h"
-#include "lld_nand.h"
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-#if FLASH_EMU /* vector all the LLD calls to the LLD_EMU code */
-#include "lld_emu.h"
-#include "lld_cdma.h"
-
-/* common functions: */
-u16 GLOB_LLD_Flash_Reset(void)
-{
- return emu_Flash_Reset();
-}
-
-u16 GLOB_LLD_Read_Device_ID(void)
-{
- return emu_Read_Device_ID();
-}
-
-int GLOB_LLD_Flash_Release(void)
-{
- return emu_Flash_Release();
-}
-
-u16 GLOB_LLD_Flash_Init(void)
-{
- return emu_Flash_Init();
-}
-
-u16 GLOB_LLD_Erase_Block(u32 block_add)
-{
- return emu_Erase_Block(block_add);
-}
-
-u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return emu_Write_Page_Main(write_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return emu_Read_Page_Main(read_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
- u32 block, u16 page, u16 page_count)
-{
- return emu_Read_Page_Main(read_data, block, page, page_count);
-}
-
-u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block,
- u16 Page, u16 PageCount)
-{
- return emu_Write_Page_Main_Spare(write_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block,
- u16 Page, u16 PageCount)
-{
- return emu_Read_Page_Main_Spare(read_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return emu_Write_Page_Spare(write_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return emu_Read_Page_Spare(read_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Get_Bad_Block(u32 block)
-{
- return emu_Get_Bad_Block(block);
-}
-
-#endif /* FLASH_EMU */
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-#if FLASH_MTD /* vector all the LLD calls to the LLD_MTD code */
-#include "lld_mtd.h"
-#include "lld_cdma.h"
-
-/* common functions: */
-u16 GLOB_LLD_Flash_Reset(void)
-{
- return mtd_Flash_Reset();
-}
-
-u16 GLOB_LLD_Read_Device_ID(void)
-{
- return mtd_Read_Device_ID();
-}
-
-int GLOB_LLD_Flash_Release(void)
-{
- return mtd_Flash_Release();
-}
-
-u16 GLOB_LLD_Flash_Init(void)
-{
- return mtd_Flash_Init();
-}
-
-u16 GLOB_LLD_Erase_Block(u32 block_add)
-{
- return mtd_Erase_Block(block_add);
-}
-
-u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return mtd_Write_Page_Main(write_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return mtd_Read_Page_Main(read_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
- u32 block, u16 page, u16 page_count)
-{
- return mtd_Read_Page_Main(read_data, block, page, page_count);
-}
-
-u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block,
- u16 Page, u16 PageCount)
-{
- return mtd_Write_Page_Main_Spare(write_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block,
- u16 Page, u16 PageCount)
-{
- return mtd_Read_Page_Main_Spare(read_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return mtd_Write_Page_Spare(write_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return mtd_Read_Page_Spare(read_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Get_Bad_Block(u32 block)
-{
- return mtd_Get_Bad_Block(block);
-}
-
-#endif /* FLASH_MTD */
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-#if FLASH_NAND /* vector all the LLD calls to the NAND controller code */
-#include "lld_nand.h"
-#include "lld_cdma.h"
-#include "flash.h"
-
-/* common functions for LLD_NAND */
-void GLOB_LLD_ECC_Control(int enable)
-{
- NAND_ECC_Ctrl(enable);
-}
-
-/* common functions for LLD_NAND */
-u16 GLOB_LLD_Flash_Reset(void)
-{
- return NAND_Flash_Reset();
-}
-
-u16 GLOB_LLD_Read_Device_ID(void)
-{
- return NAND_Read_Device_ID();
-}
-
-u16 GLOB_LLD_UnlockArrayAll(void)
-{
- return NAND_UnlockArrayAll();
-}
-
-u16 GLOB_LLD_Flash_Init(void)
-{
- return NAND_Flash_Init();
-}
-
-int GLOB_LLD_Flash_Release(void)
-{
- return nand_release_spectra();
-}
-
-u16 GLOB_LLD_Erase_Block(u32 block_add)
-{
- return NAND_Erase_Block(block_add);
-}
-
-
-u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return NAND_Write_Page_Main(write_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 page,
- u16 page_count)
-{
- if (page_count == 1) /* Using polling to improve read speed */
- return NAND_Read_Page_Main_Polling(read_data, block, page, 1);
- else
- return NAND_Read_Page_Main(read_data, block, page, page_count);
-}
-
-u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
- u32 block, u16 page, u16 page_count)
-{
- return NAND_Read_Page_Main_Polling(read_data,
- block, page, page_count);
-}
-
-u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block,
- u16 Page, u16 PageCount)
-{
- return NAND_Write_Page_Main_Spare(write_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return NAND_Write_Page_Spare(write_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block,
- u16 page, u16 page_count)
-{
- return NAND_Read_Page_Main_Spare(read_data, block, page, page_count);
-}
-
-u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page,
- u16 PageCount)
-{
- return NAND_Read_Page_Spare(read_data, block, Page, PageCount);
-}
-
-u16 GLOB_LLD_Get_Bad_Block(u32 block)
-{
- return NAND_Get_Bad_Block(block);
-}
-
-#if CMD_DMA
-u16 GLOB_LLD_Event_Status(void)
-{
- return CDMA_Event_Status();
-}
-
-u16 glob_lld_execute_cmds(void)
-{
- return CDMA_Execute_CMDs();
-}
-
-u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src,
- u32 ByteCount, u16 flag)
-{
- /* Replace the hardware memcopy with software memcpy function */
- if (CDMA_Execute_CMDs())
- return FAIL;
- memcpy(dest, src, ByteCount);
- return PASS;
-
- /* return CDMA_MemCopy_CMD(dest, src, ByteCount, flag); */
-}
-
-u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags)
-{
- return CDMA_Data_CMD(ERASE_CMD, 0, block, 0, 0, flags);
-}
-
-u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, u32 block, u16 page, u16 count)
-{
- return CDMA_Data_CMD(WRITE_MAIN_CMD, data, block, page, count, 0);
-}
-
-u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, u32 block, u16 page,
- u16 count, u16 flags)
-{
- return CDMA_Data_CMD(READ_MAIN_CMD, data, block, page, count, flags);
-}
-
-u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, u32 block, u16 page,
- u16 count, u16 flags)
-{
- return CDMA_Data_CMD(WRITE_MAIN_SPARE_CMD,
- data, block, page, count, flags);
-}
-
-u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data,
- u32 block, u16 page, u16 count)
-{
- return CDMA_Data_CMD(READ_MAIN_SPARE_CMD, data, block, page, count,
- LLD_CMD_FLAG_MODE_CDMA);
-}
-
-#endif /* CMD_DMA */
-#endif /* FLASH_NAND */
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-
-/* end of LLD.c */
diff --git a/drivers/staging/spectra/lld.h b/drivers/staging/spectra/lld.h
deleted file mode 100644
index d3738e0e1fea..000000000000
--- a/drivers/staging/spectra/lld.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-
-
-#ifndef _LLD_
-#define _LLD_
-
-#include "ffsport.h"
-#include "spectraswconfig.h"
-#include "flash.h"
-
-#define GOOD_BLOCK 0
-#define DEFECTIVE_BLOCK 1
-#define READ_ERROR 2
-
-#define CLK_X 5
-#define CLK_MULTI 4
-
-/* Typedefs */
-
-/* prototypes: API for LLD */
-/* Currently, Write_Page_Main
- * MemCopy
- * Read_Page_Main_Spare
- * do not have flag because they were not implemented prior to this
- * They are not being added to keep changes to a minimum for now.
- * Currently, they are not required (only reqd for Wr_P_M_S.)
- * Later on, these NEED to be changed.
- */
-
-extern void GLOB_LLD_ECC_Control(int enable);
-
-extern u16 GLOB_LLD_Flash_Reset(void);
-
-extern u16 GLOB_LLD_Read_Device_ID(void);
-
-extern u16 GLOB_LLD_UnlockArrayAll(void);
-
-extern u16 GLOB_LLD_Flash_Init(void);
-
-extern int GLOB_LLD_Flash_Release(void);
-
-extern u16 GLOB_LLD_Erase_Block(u32 block_add);
-
-extern u16 GLOB_LLD_Write_Page_Main(u8 *write_data,
- u32 block, u16 Page, u16 PageCount);
-
-extern u16 GLOB_LLD_Read_Page_Main(u8 *read_data,
- u32 block, u16 page, u16 page_count);
-
-extern u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
- u32 block, u16 page, u16 page_count);
-
-extern u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data,
- u32 block, u16 Page, u16 PageCount);
-
-extern u16 GLOB_LLD_Write_Page_Spare(u8 *write_data,
- u32 block, u16 Page, u16 PageCount);
-
-extern u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data,
- u32 block, u16 page, u16 page_count);
-
-extern u16 GLOB_LLD_Read_Page_Spare(u8 *read_data,
- u32 block, u16 Page, u16 PageCount);
-
-extern u16 GLOB_LLD_Get_Bad_Block(u32 block);
-
-extern u16 GLOB_LLD_Event_Status(void);
-
-extern u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, u32 ByteCount, u16 flag);
-
-extern u16 glob_lld_execute_cmds(void);
-
-extern u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags);
-
-extern u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data,
- u32 block, u16 page, u16 count);
-
-extern u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data,
- u32 block, u16 page, u16 count, u16 flags);
-
-extern u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data,
- u32 block, u16 page, u16 count, u16 flags);
-
-extern u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data,
- u32 block, u16 page, u16 count);
-
-#define LLD_CMD_FLAG_ORDER_BEFORE_REST (0x1)
-#define LLD_CMD_FLAG_MODE_CDMA (0x8)
-
-
-#endif /*_LLD_ */
-
-
diff --git a/drivers/staging/spectra/lld_cdma.c b/drivers/staging/spectra/lld_cdma.c
deleted file mode 100644
index c6e76103d43c..000000000000
--- a/drivers/staging/spectra/lld_cdma.c
+++ /dev/null
@@ -1,910 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-
-#include "spectraswconfig.h"
-#include "lld.h"
-#include "lld_nand.h"
-#include "lld_cdma.h"
-#include "lld_emu.h"
-#include "flash.h"
-#include "nand_regs.h"
-
-#define MAX_PENDING_CMDS 4
-#define MODE_02 (0x2 << 26)
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: CDMA_Data_Cmd
-* Inputs: cmd code (aligned for hw)
-* data: pointer to source or destination
-* block: block address
-* page: page address
-* num: num pages to transfer
-* Outputs: PASS
-* Description: This function takes the parameters and puts them
-* into the "pending commands" array.
-* It does not parse or validate the parameters.
-* The array index is same as the tag.
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags)
-{
- u8 bank;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (0 == cmd)
- nand_dbg_print(NAND_DBG_DEBUG,
- "%s, Line %d, Illegal cmd (0)\n", __FILE__, __LINE__);
-
- /* If a command of another bank comes, then first execute */
- /* pending commands of the current bank, then set the new */
- /* bank as current bank */
- bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
- if (bank != info.flash_bank) {
- nand_dbg_print(NAND_DBG_WARN,
- "Will access new bank. old bank: %d, new bank: %d\n",
- info.flash_bank, bank);
- if (CDMA_Execute_CMDs()) {
- printk(KERN_ERR "CDMA_Execute_CMDs fail!\n");
- return FAIL;
- }
- info.flash_bank = bank;
- }
-
- info.pcmds[info.pcmds_num].CMD = cmd;
- info.pcmds[info.pcmds_num].DataAddr = data;
- info.pcmds[info.pcmds_num].Block = block;
- info.pcmds[info.pcmds_num].Page = page;
- info.pcmds[info.pcmds_num].PageCount = num;
- info.pcmds[info.pcmds_num].DataDestAddr = 0;
- info.pcmds[info.pcmds_num].DataSrcAddr = 0;
- info.pcmds[info.pcmds_num].MemCopyByteCnt = 0;
- info.pcmds[info.pcmds_num].Flags = flags;
- info.pcmds[info.pcmds_num].Status = 0xB0B;
-
- switch (cmd) {
- case WRITE_MAIN_SPARE_CMD:
- Conv_Main_Spare_Data_Log2Phy_Format(data, num);
- break;
- case WRITE_SPARE_CMD:
- Conv_Spare_Data_Log2Phy_Format(data);
- break;
- default:
- break;
- }
-
- info.pcmds_num++;
-
- if (info.pcmds_num >= MAX_PENDING_CMDS) {
- if (CDMA_Execute_CMDs()) {
- printk(KERN_ERR "CDMA_Execute_CMDs fail!\n");
- return FAIL;
- }
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: CDMA_MemCopy_CMD
-* Inputs: dest: pointer to destination
-* src: pointer to source
-* count: num bytes to transfer
-* Outputs: PASS
-* Description: This function takes the parameters and puts them
-* into the "pending commands" array.
-* It does not parse or validate the parameters.
-* The array index is same as the tag.
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags)
-{
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- info.pcmds[info.pcmds_num].CMD = MEMCOPY_CMD;
- info.pcmds[info.pcmds_num].DataAddr = 0;
- info.pcmds[info.pcmds_num].Block = 0;
- info.pcmds[info.pcmds_num].Page = 0;
- info.pcmds[info.pcmds_num].PageCount = 0;
- info.pcmds[info.pcmds_num].DataDestAddr = dest;
- info.pcmds[info.pcmds_num].DataSrcAddr = src;
- info.pcmds[info.pcmds_num].MemCopyByteCnt = byte_cnt;
- info.pcmds[info.pcmds_num].Flags = flags;
- info.pcmds[info.pcmds_num].Status = 0xB0B;
-
- info.pcmds_num++;
-
- if (info.pcmds_num >= MAX_PENDING_CMDS) {
- if (CDMA_Execute_CMDs()) {
- printk(KERN_ERR "CDMA_Execute_CMDs fail!\n");
- return FAIL;
- }
- }
-
- return PASS;
-}
-
-#if 0
-/* Prints the PendingCMDs array */
-void print_pending_cmds(void)
-{
- u16 i;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < info.pcmds_num; i++) {
- nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i);
- switch (info.pcmds[i].CMD) {
- case ERASE_CMD:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Erase Command (0x%x)\n",
- info.pcmds[i].CMD);
- break;
- case WRITE_MAIN_CMD:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Write Main Command (0x%x)\n",
- info.pcmds[i].CMD);
- break;
- case WRITE_MAIN_SPARE_CMD:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Write Main Spare Command (0x%x)\n",
- info.pcmds[i].CMD);
- break;
- case READ_MAIN_SPARE_CMD:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Read Main Spare Command (0x%x)\n",
- info.pcmds[i].CMD);
- break;
- case READ_MAIN_CMD:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Read Main Command (0x%x)\n",
- info.pcmds[i].CMD);
- break;
- case MEMCOPY_CMD:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Memcopy Command (0x%x)\n",
- info.pcmds[i].CMD);
- break;
- case DUMMY_CMD:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Dummy Command (0x%x)\n",
- info.pcmds[i].CMD);
- break;
- default:
- nand_dbg_print(NAND_DBG_DEBUG,
- "Illegal Command (0x%x)\n",
- info.pcmds[i].CMD);
- break;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "DataAddr: 0x%x\n",
- (u32)info.pcmds[i].DataAddr);
- nand_dbg_print(NAND_DBG_DEBUG, "Block: %d\n",
- info.pcmds[i].Block);
- nand_dbg_print(NAND_DBG_DEBUG, "Page: %d\n",
- info.pcmds[i].Page);
- nand_dbg_print(NAND_DBG_DEBUG, "PageCount: %d\n",
- info.pcmds[i].PageCount);
- nand_dbg_print(NAND_DBG_DEBUG, "DataDestAddr: 0x%x\n",
- (u32)info.pcmds[i].DataDestAddr);
- nand_dbg_print(NAND_DBG_DEBUG, "DataSrcAddr: 0x%x\n",
- (u32)info.pcmds[i].DataSrcAddr);
- nand_dbg_print(NAND_DBG_DEBUG, "MemCopyByteCnt: %d\n",
- info.pcmds[i].MemCopyByteCnt);
- nand_dbg_print(NAND_DBG_DEBUG, "Flags: 0x%x\n",
- info.pcmds[i].Flags);
- nand_dbg_print(NAND_DBG_DEBUG, "Status: 0x%x\n",
- info.pcmds[i].Status);
- }
-}
-
-/* Print the CDMA descriptors */
-void print_cdma_descriptors(void)
-{
- struct cdma_descriptor *pc;
- int i;
-
- pc = (struct cdma_descriptor *)info.cdma_desc_buf;
-
- nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump cdma descriptors:\n");
-
- for (i = 0; i < info.cdma_num; i++) {
- nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i);
- nand_dbg_print(NAND_DBG_DEBUG,
- "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n",
- pc[i].NxtPointerHi, pc[i].NxtPointerLo);
- nand_dbg_print(NAND_DBG_DEBUG,
- "FlashPointerHi: 0x%x, FlashPointerLo: 0x%x\n",
- pc[i].FlashPointerHi, pc[i].FlashPointerLo);
- nand_dbg_print(NAND_DBG_DEBUG, "CommandType: 0x%x\n",
- pc[i].CommandType);
- nand_dbg_print(NAND_DBG_DEBUG,
- "MemAddrHi: 0x%x, MemAddrLo: 0x%x\n",
- pc[i].MemAddrHi, pc[i].MemAddrLo);
- nand_dbg_print(NAND_DBG_DEBUG, "CommandFlags: 0x%x\n",
- pc[i].CommandFlags);
- nand_dbg_print(NAND_DBG_DEBUG, "Channel: %d, Status: 0x%x\n",
- pc[i].Channel, pc[i].Status);
- nand_dbg_print(NAND_DBG_DEBUG,
- "MemCopyPointerHi: 0x%x, MemCopyPointerLo: 0x%x\n",
- pc[i].MemCopyPointerHi, pc[i].MemCopyPointerLo);
- nand_dbg_print(NAND_DBG_DEBUG,
- "Reserved12: 0x%x, Reserved13: 0x%x, "
- "Reserved14: 0x%x, pcmd: %d\n",
- pc[i].Reserved12, pc[i].Reserved13,
- pc[i].Reserved14, pc[i].pcmd);
- }
-}
-
-/* Print the Memory copy descriptors */
-static void print_memcp_descriptors(void)
-{
- struct memcpy_descriptor *pm;
- int i;
-
- pm = (struct memcpy_descriptor *)info.memcp_desc_buf;
-
- nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump mem_cpy descriptors:\n");
-
- for (i = 0; i < info.cdma_num; i++) {
- nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i);
- nand_dbg_print(NAND_DBG_DEBUG,
- "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n",
- pm[i].NxtPointerHi, pm[i].NxtPointerLo);
- nand_dbg_print(NAND_DBG_DEBUG,
- "SrcAddrHi: 0x%x, SrcAddrLo: 0x%x\n",
- pm[i].SrcAddrHi, pm[i].SrcAddrLo);
- nand_dbg_print(NAND_DBG_DEBUG,
- "DestAddrHi: 0x%x, DestAddrLo: 0x%x\n",
- pm[i].DestAddrHi, pm[i].DestAddrLo);
- nand_dbg_print(NAND_DBG_DEBUG, "XferSize: %d\n",
- pm[i].XferSize);
- nand_dbg_print(NAND_DBG_DEBUG, "MemCopyFlags: 0x%x\n",
- pm[i].MemCopyFlags);
- nand_dbg_print(NAND_DBG_DEBUG, "MemCopyStatus: %d\n",
- pm[i].MemCopyStatus);
- nand_dbg_print(NAND_DBG_DEBUG, "reserved9: 0x%x\n",
- pm[i].reserved9);
- nand_dbg_print(NAND_DBG_DEBUG, "reserved10: 0x%x\n",
- pm[i].reserved10);
- nand_dbg_print(NAND_DBG_DEBUG, "reserved11: 0x%x\n",
- pm[i].reserved11);
- nand_dbg_print(NAND_DBG_DEBUG, "reserved12: 0x%x\n",
- pm[i].reserved12);
- nand_dbg_print(NAND_DBG_DEBUG, "reserved13: 0x%x\n",
- pm[i].reserved13);
- nand_dbg_print(NAND_DBG_DEBUG, "reserved14: 0x%x\n",
- pm[i].reserved14);
- nand_dbg_print(NAND_DBG_DEBUG, "reserved15: 0x%x\n",
- pm[i].reserved15);
- }
-}
-#endif
-
-/* Reset cdma_descriptor chain to 0 */
-static void reset_cdma_desc(int i)
-{
- struct cdma_descriptor *ptr;
-
- BUG_ON(i >= MAX_DESCS);
-
- ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
-
- ptr[i].NxtPointerHi = 0;
- ptr[i].NxtPointerLo = 0;
- ptr[i].FlashPointerHi = 0;
- ptr[i].FlashPointerLo = 0;
- ptr[i].CommandType = 0;
- ptr[i].MemAddrHi = 0;
- ptr[i].MemAddrLo = 0;
- ptr[i].CommandFlags = 0;
- ptr[i].Channel = 0;
- ptr[i].Status = 0;
- ptr[i].MemCopyPointerHi = 0;
- ptr[i].MemCopyPointerLo = 0;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: CDMA_UpdateEventStatus
-* Inputs: none
-* Outputs: none
-* Description: This function update the event status of all the channels
-* when an error condition is reported.
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-void CDMA_UpdateEventStatus(void)
-{
- int i, j, active_chan;
- struct cdma_descriptor *ptr;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
-
- for (j = 0; j < info.cdma_num; j++) {
- /* Check for the descriptor with failure */
- if ((ptr[j].Status & CMD_DMA_DESC_FAIL))
- break;
-
- }
-
- /* All the previous cmd's status for this channel must be good */
- for (i = 0; i < j; i++) {
- if (ptr[i].pcmd != 0xff)
- info.pcmds[ptr[i].pcmd].Status = CMD_PASS;
- }
-
- /* Abort the channel with type 0 reset command. It resets the */
- /* selected channel after the descriptor completes the flash */
- /* operation and status has been updated for the descriptor. */
- /* Memory Copy and Sync associated with this descriptor will */
- /* not be executed */
- active_chan = ioread32(FlashReg + CHNL_ACTIVE);
- if ((active_chan & (1 << info.flash_bank)) == (1 << info.flash_bank)) {
- iowrite32(MODE_02 | (0 << 4), FlashMem); /* Type 0 reset */
- iowrite32((0xF << 4) | info.flash_bank, FlashMem + 0x10);
- } else { /* Should not reached here */
- printk(KERN_ERR "Error! Used bank is not set in"
- " reg CHNL_ACTIVE\n");
- }
-}
-
-static void cdma_trans(u16 chan)
-{
- u32 addr;
-
- addr = info.cdma_desc;
-
- iowrite32(MODE_10 | (chan << 24), FlashMem);
- iowrite32((1 << 7) | chan, FlashMem + 0x10);
-
- iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & (addr >> 16)) << 8),
- FlashMem);
- iowrite32((1 << 7) | (1 << 4) | 0, FlashMem + 0x10);
-
- iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & addr) << 8), FlashMem);
- iowrite32((1 << 7) | (1 << 5) | 0, FlashMem + 0x10);
-
- iowrite32(MODE_10 | (chan << 24), FlashMem);
- iowrite32((1 << 7) | (1 << 5) | (1 << 4) | 0, FlashMem + 0x10);
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: CDMA_Execute_CMDs (for use with CMD_DMA)
-* Inputs: tag_count: the number of pending cmds to do
-* Outputs: PASS/FAIL
-* Description: Build the SDMA chain(s) by making one CMD-DMA descriptor
-* for each pending command, start the CDMA engine, and return.
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 CDMA_Execute_CMDs(void)
-{
- int i, ret;
- u64 flash_add;
- u32 ptr;
- dma_addr_t map_addr, next_ptr;
- u16 status = PASS;
- u16 tmp_c;
- struct cdma_descriptor *pc;
- struct memcpy_descriptor *pm;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- /* No pending cmds to execute, just exit */
- if (0 == info.pcmds_num) {
- nand_dbg_print(NAND_DBG_TRACE,
- "No pending cmds to execute. Just exit.\n");
- return PASS;
- }
-
- for (i = 0; i < MAX_DESCS; i++)
- reset_cdma_desc(i);
-
- pc = (struct cdma_descriptor *)info.cdma_desc_buf;
- pm = (struct memcpy_descriptor *)info.memcp_desc_buf;
-
- info.cdma_desc = virt_to_bus(info.cdma_desc_buf);
- info.memcp_desc = virt_to_bus(info.memcp_desc_buf);
- next_ptr = info.cdma_desc;
- info.cdma_num = 0;
-
- for (i = 0; i < info.pcmds_num; i++) {
- if (info.pcmds[i].Block >= DeviceInfo.wTotalBlocks) {
- info.pcmds[i].Status = CMD_NOT_DONE;
- continue;
- }
-
- next_ptr += sizeof(struct cdma_descriptor);
- pc[info.cdma_num].NxtPointerHi = next_ptr >> 16;
- pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff;
-
- /* Use the Block offset within a bank */
- tmp_c = info.pcmds[i].Block /
- (DeviceInfo.wTotalBlocks / totalUsedBanks);
- flash_add = (u64)(info.pcmds[i].Block - tmp_c *
- (DeviceInfo.wTotalBlocks / totalUsedBanks)) *
- DeviceInfo.wBlockDataSize +
- (u64)(info.pcmds[i].Page) *
- DeviceInfo.wPageDataSize;
-
- ptr = MODE_10 | (info.flash_bank << 24) |
- (u32)GLOB_u64_Div(flash_add,
- DeviceInfo.wPageDataSize);
- pc[info.cdma_num].FlashPointerHi = ptr >> 16;
- pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
-
- if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) ||
- (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) {
- /* Descriptor to set Main+Spare Access Mode */
- pc[info.cdma_num].CommandType = 0x43;
- pc[info.cdma_num].CommandFlags =
- (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
- pc[info.cdma_num].MemAddrHi = 0;
- pc[info.cdma_num].MemAddrLo = 0;
- pc[info.cdma_num].Channel = 0;
- pc[info.cdma_num].Status = 0;
- pc[info.cdma_num].pcmd = i;
-
- info.cdma_num++;
- BUG_ON(info.cdma_num >= MAX_DESCS);
-
- reset_cdma_desc(info.cdma_num);
- next_ptr += sizeof(struct cdma_descriptor);
- pc[info.cdma_num].NxtPointerHi = next_ptr >> 16;
- pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff;
- pc[info.cdma_num].FlashPointerHi = ptr >> 16;
- pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
- }
-
- switch (info.pcmds[i].CMD) {
- case ERASE_CMD:
- pc[info.cdma_num].CommandType = 1;
- pc[info.cdma_num].CommandFlags =
- (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
- pc[info.cdma_num].MemAddrHi = 0;
- pc[info.cdma_num].MemAddrLo = 0;
- break;
-
- case WRITE_MAIN_CMD:
- pc[info.cdma_num].CommandType =
- 0x2100 | info.pcmds[i].PageCount;
- pc[info.cdma_num].CommandFlags =
- (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
- map_addr = virt_to_bus(info.pcmds[i].DataAddr);
- pc[info.cdma_num].MemAddrHi = map_addr >> 16;
- pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
- break;
-
- case READ_MAIN_CMD:
- pc[info.cdma_num].CommandType =
- 0x2000 | info.pcmds[i].PageCount;
- pc[info.cdma_num].CommandFlags =
- (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
- map_addr = virt_to_bus(info.pcmds[i].DataAddr);
- pc[info.cdma_num].MemAddrHi = map_addr >> 16;
- pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
- break;
-
- case WRITE_MAIN_SPARE_CMD:
- pc[info.cdma_num].CommandType =
- 0x2100 | info.pcmds[i].PageCount;
- pc[info.cdma_num].CommandFlags =
- (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
- map_addr = virt_to_bus(info.pcmds[i].DataAddr);
- pc[info.cdma_num].MemAddrHi = map_addr >> 16;
- pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
- break;
-
- case READ_MAIN_SPARE_CMD:
- pc[info.cdma_num].CommandType =
- 0x2000 | info.pcmds[i].PageCount;
- pc[info.cdma_num].CommandFlags =
- (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
- map_addr = virt_to_bus(info.pcmds[i].DataAddr);
- pc[info.cdma_num].MemAddrHi = map_addr >> 16;
- pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
- break;
-
- case MEMCOPY_CMD:
- pc[info.cdma_num].CommandType = 0xFFFF; /* NOP cmd */
- /* Set bit 11 to let the CDMA engine continue to */
- /* execute only after it has finished processing */
- /* the memcopy descriptor. */
- /* Also set bit 10 and bit 9 to 1 */
- pc[info.cdma_num].CommandFlags = 0x0E40;
- map_addr = info.memcp_desc + info.cdma_num *
- sizeof(struct memcpy_descriptor);
- pc[info.cdma_num].MemCopyPointerHi = map_addr >> 16;
- pc[info.cdma_num].MemCopyPointerLo = map_addr & 0xffff;
-
- pm[info.cdma_num].NxtPointerHi = 0;
- pm[info.cdma_num].NxtPointerLo = 0;
-
- map_addr = virt_to_bus(info.pcmds[i].DataSrcAddr);
- pm[info.cdma_num].SrcAddrHi = map_addr >> 16;
- pm[info.cdma_num].SrcAddrLo = map_addr & 0xffff;
- map_addr = virt_to_bus(info.pcmds[i].DataDestAddr);
- pm[info.cdma_num].DestAddrHi = map_addr >> 16;
- pm[info.cdma_num].DestAddrLo = map_addr & 0xffff;
-
- pm[info.cdma_num].XferSize =
- info.pcmds[i].MemCopyByteCnt;
- pm[info.cdma_num].MemCopyFlags =
- (0 << 15 | 0 << 14 | 27 << 8 | 0x40);
- pm[info.cdma_num].MemCopyStatus = 0;
- break;
-
- case DUMMY_CMD:
- default:
- pc[info.cdma_num].CommandType = 0XFFFF;
- pc[info.cdma_num].CommandFlags =
- (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
- pc[info.cdma_num].MemAddrHi = 0;
- pc[info.cdma_num].MemAddrLo = 0;
- break;
- }
-
- pc[info.cdma_num].Channel = 0;
- pc[info.cdma_num].Status = 0;
- pc[info.cdma_num].pcmd = i;
-
- info.cdma_num++;
- BUG_ON(info.cdma_num >= MAX_DESCS);
-
- if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) ||
- (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) {
- /* Descriptor to set back Main Area Access Mode */
- reset_cdma_desc(info.cdma_num);
- next_ptr += sizeof(struct cdma_descriptor);
- pc[info.cdma_num].NxtPointerHi = next_ptr >> 16;
- pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff;
-
- pc[info.cdma_num].FlashPointerHi = ptr >> 16;
- pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
-
- pc[info.cdma_num].CommandType = 0x42;
- pc[info.cdma_num].CommandFlags =
- (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
- pc[info.cdma_num].MemAddrHi = 0;
- pc[info.cdma_num].MemAddrLo = 0;
-
- pc[info.cdma_num].Channel = 0;
- pc[info.cdma_num].Status = 0;
- pc[info.cdma_num].pcmd = i;
-
- info.cdma_num++;
- BUG_ON(info.cdma_num >= MAX_DESCS);
- }
- }
-
- /* Add a dummy descriptor at end of the CDMA chain */
- reset_cdma_desc(info.cdma_num);
- ptr = MODE_10 | (info.flash_bank << 24);
- pc[info.cdma_num].FlashPointerHi = ptr >> 16;
- pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
- pc[info.cdma_num].CommandType = 0xFFFF; /* NOP command */
- /* Set Command Flags for the last CDMA descriptor: */
- /* set Continue bit (bit 9) to 0 and Interrupt bit (bit 8) to 1 */
- pc[info.cdma_num].CommandFlags =
- (0 << 10) | (0 << 9) | (1 << 8) | 0x40;
- pc[info.cdma_num].pcmd = 0xff; /* Set it to an illegal value */
- info.cdma_num++;
- BUG_ON(info.cdma_num >= MAX_DESCS);
-
- iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */
-
- iowrite32(1, FlashReg + DMA_ENABLE);
- /* Wait for DMA to be enabled before issuing the next command */
- while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
- cdma_trans(info.flash_bank);
-
- ret = wait_for_completion_timeout(&info.complete, 50 * HZ);
- if (!ret)
- printk(KERN_ERR "Wait for completion timeout "
- "in %s, Line %d\n", __FILE__, __LINE__);
- status = info.ret;
-
- info.pcmds_num = 0; /* Clear the pending cmds number to 0 */
-
- return status;
-}
-
-int is_cdma_interrupt(void)
-{
- u32 ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma;
- u32 int_en_mask;
- u32 cdma_int_en_mask;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- /* Set the global Enable masks for only those interrupts
- * that are supported */
- cdma_int_en_mask = (DMA_INTR__DESC_COMP_CHANNEL0 |
- DMA_INTR__DESC_COMP_CHANNEL1 |
- DMA_INTR__DESC_COMP_CHANNEL2 |
- DMA_INTR__DESC_COMP_CHANNEL3 |
- DMA_INTR__MEMCOPY_DESC_COMP);
-
- int_en_mask = (INTR_STATUS0__ECC_ERR |
- INTR_STATUS0__PROGRAM_FAIL |
- INTR_STATUS0__ERASE_FAIL);
-
- ints_b0 = ioread32(FlashReg + INTR_STATUS0) & int_en_mask;
- ints_b1 = ioread32(FlashReg + INTR_STATUS1) & int_en_mask;
- ints_b2 = ioread32(FlashReg + INTR_STATUS2) & int_en_mask;
- ints_b3 = ioread32(FlashReg + INTR_STATUS3) & int_en_mask;
- ints_cdma = ioread32(FlashReg + DMA_INTR) & cdma_int_en_mask;
-
- nand_dbg_print(NAND_DBG_WARN, "ints_bank0 to ints_bank3: "
- "0x%x, 0x%x, 0x%x, 0x%x, ints_cdma: 0x%x\n",
- ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma);
-
- if (ints_b0 || ints_b1 || ints_b2 || ints_b3 || ints_cdma) {
- return 1;
- } else {
- iowrite32(ints_b0, FlashReg + INTR_STATUS0);
- iowrite32(ints_b1, FlashReg + INTR_STATUS1);
- iowrite32(ints_b2, FlashReg + INTR_STATUS2);
- iowrite32(ints_b3, FlashReg + INTR_STATUS3);
- nand_dbg_print(NAND_DBG_DEBUG,
- "Not a NAND controller interrupt! Ignore it.\n");
- return 0;
- }
-}
-
-static void update_event_status(void)
-{
- int i;
- struct cdma_descriptor *ptr;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
-
- for (i = 0; i < info.cdma_num; i++) {
- if (ptr[i].pcmd != 0xff)
- info.pcmds[ptr[i].pcmd].Status = CMD_PASS;
- if ((ptr[i].CommandType == 0x41) ||
- (ptr[i].CommandType == 0x42) ||
- (ptr[i].CommandType == 0x43))
- continue;
-
- switch (info.pcmds[ptr[i].pcmd].CMD) {
- case READ_MAIN_SPARE_CMD:
- Conv_Main_Spare_Data_Phy2Log_Format(
- info.pcmds[ptr[i].pcmd].DataAddr,
- info.pcmds[ptr[i].pcmd].PageCount);
- break;
- case READ_SPARE_CMD:
- Conv_Spare_Data_Phy2Log_Format(
- info.pcmds[ptr[i].pcmd].DataAddr);
- break;
- }
- }
-}
-
-static u16 do_ecc_for_desc(u32 ch, u8 *buf, u16 page)
-{
- u16 event = EVENT_NONE;
- u16 err_byte;
- u16 err_page = 0;
- u8 err_sector;
- u8 err_device;
- u16 ecc_correction_info;
- u16 err_address;
- u32 eccSectorSize;
- u8 *err_pos;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
-
- do {
- if (0 == ch)
- err_page = ioread32(FlashReg + ERR_PAGE_ADDR0);
- else if (1 == ch)
- err_page = ioread32(FlashReg + ERR_PAGE_ADDR1);
- else if (2 == ch)
- err_page = ioread32(FlashReg + ERR_PAGE_ADDR2);
- else if (3 == ch)
- err_page = ioread32(FlashReg + ERR_PAGE_ADDR3);
-
- err_address = ioread32(FlashReg + ECC_ERROR_ADDRESS);
- err_byte = err_address & ECC_ERROR_ADDRESS__OFFSET;
- err_sector = ((err_address &
- ECC_ERROR_ADDRESS__SECTOR_NR) >> 12);
-
- ecc_correction_info = ioread32(FlashReg + ERR_CORRECTION_INFO);
- err_device = ((ecc_correction_info &
- ERR_CORRECTION_INFO__DEVICE_NR) >> 8);
-
- if (ecc_correction_info & ERR_CORRECTION_INFO__ERROR_TYPE) {
- event = EVENT_UNCORRECTABLE_DATA_ERROR;
- } else {
- event = EVENT_CORRECTABLE_DATA_ERROR_FIXED;
- if (err_byte < ECC_SECTOR_SIZE) {
- err_pos = buf +
- (err_page - page) *
- DeviceInfo.wPageDataSize +
- err_sector * eccSectorSize +
- err_byte *
- DeviceInfo.wDevicesConnected +
- err_device;
- *err_pos ^= ecc_correction_info &
- ERR_CORRECTION_INFO__BYTEMASK;
- }
- }
- } while (!(ecc_correction_info & ERR_CORRECTION_INFO__LAST_ERR_INFO));
-
- return event;
-}
-
-static u16 process_ecc_int(u32 c, u16 *p_desc_num)
-{
- struct cdma_descriptor *ptr;
- u16 j;
- int event = EVENT_PASS;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (c != info.flash_bank)
- printk(KERN_ERR "Error!info.flash_bank is %d, while c is %d\n",
- info.flash_bank, c);
-
- ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
-
- for (j = 0; j < info.cdma_num; j++)
- if ((ptr[j].Status & CMD_DMA_DESC_COMP) != CMD_DMA_DESC_COMP)
- break;
-
- *p_desc_num = j; /* Pass the descripter number found here */
-
- if (j >= info.cdma_num) {
- printk(KERN_ERR "Can not find the correct descriptor number "
- "when ecc interrupt triggered!"
- "info.cdma_num: %d, j: %d\n", info.cdma_num, j);
- return EVENT_UNCORRECTABLE_DATA_ERROR;
- }
-
- event = do_ecc_for_desc(c, info.pcmds[ptr[j].pcmd].DataAddr,
- info.pcmds[ptr[j].pcmd].Page);
-
- if (EVENT_UNCORRECTABLE_DATA_ERROR == event) {
- printk(KERN_ERR "Uncorrectable ECC error!"
- "info.cdma_num: %d, j: %d, "
- "pending cmd CMD: 0x%x, "
- "Block: 0x%x, Page: 0x%x, PageCount: 0x%x\n",
- info.cdma_num, j,
- info.pcmds[ptr[j].pcmd].CMD,
- info.pcmds[ptr[j].pcmd].Block,
- info.pcmds[ptr[j].pcmd].Page,
- info.pcmds[ptr[j].pcmd].PageCount);
-
- if (ptr[j].pcmd != 0xff)
- info.pcmds[ptr[j].pcmd].Status = CMD_FAIL;
- CDMA_UpdateEventStatus();
- }
-
- return event;
-}
-
-static void process_prog_erase_fail_int(u16 desc_num)
-{
- struct cdma_descriptor *ptr;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
-
- if (ptr[desc_num].pcmd != 0xFF)
- info.pcmds[ptr[desc_num].pcmd].Status = CMD_FAIL;
-
- CDMA_UpdateEventStatus();
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: CDMA_Event_Status (for use with CMD_DMA)
-* Inputs: none
-* Outputs: Event_Status code
-* Description: This function is called after an interrupt has happened
-* It reads the HW status register and ...tbd
-* It returns the appropriate event status
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 CDMA_Event_Status(void)
-{
- u32 ints_addr[4] = {INTR_STATUS0, INTR_STATUS1,
- INTR_STATUS2, INTR_STATUS3};
- u32 dma_intr_bit[4] = {DMA_INTR__DESC_COMP_CHANNEL0,
- DMA_INTR__DESC_COMP_CHANNEL1,
- DMA_INTR__DESC_COMP_CHANNEL2,
- DMA_INTR__DESC_COMP_CHANNEL3};
- u32 cdma_int_status, int_status;
- u32 ecc_enable = 0;
- u16 event = EVENT_PASS;
- u16 cur_desc = 0;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- ecc_enable = ioread32(FlashReg + ECC_ENABLE);
-
- while (1) {
- int_status = ioread32(FlashReg + ints_addr[info.flash_bank]);
- if (ecc_enable && (int_status & INTR_STATUS0__ECC_ERR)) {
- event = process_ecc_int(info.flash_bank, &cur_desc);
- iowrite32(INTR_STATUS0__ECC_ERR,
- FlashReg + ints_addr[info.flash_bank]);
- if (EVENT_UNCORRECTABLE_DATA_ERROR == event) {
- nand_dbg_print(NAND_DBG_WARN,
- "ints_bank0 to ints_bank3: "
- "0x%x, 0x%x, 0x%x, 0x%x, "
- "ints_cdma: 0x%x\n",
- ioread32(FlashReg + INTR_STATUS0),
- ioread32(FlashReg + INTR_STATUS1),
- ioread32(FlashReg + INTR_STATUS2),
- ioread32(FlashReg + INTR_STATUS3),
- ioread32(FlashReg + DMA_INTR));
- break;
- }
- } else if (int_status & INTR_STATUS0__PROGRAM_FAIL) {
- printk(KERN_ERR "NAND program fail interrupt!\n");
- process_prog_erase_fail_int(cur_desc);
- event = EVENT_PROGRAM_FAILURE;
- break;
- } else if (int_status & INTR_STATUS0__ERASE_FAIL) {
- printk(KERN_ERR "NAND erase fail interrupt!\n");
- process_prog_erase_fail_int(cur_desc);
- event = EVENT_ERASE_FAILURE;
- break;
- } else {
- cdma_int_status = ioread32(FlashReg + DMA_INTR);
- if (cdma_int_status & dma_intr_bit[info.flash_bank]) {
- iowrite32(dma_intr_bit[info.flash_bank],
- FlashReg + DMA_INTR);
- update_event_status();
- event = EVENT_PASS;
- break;
- }
- }
- }
-
- int_status = ioread32(FlashReg + ints_addr[info.flash_bank]);
- iowrite32(int_status, FlashReg + ints_addr[info.flash_bank]);
- cdma_int_status = ioread32(FlashReg + DMA_INTR);
- iowrite32(cdma_int_status, FlashReg + DMA_INTR);
-
- iowrite32(0, FlashReg + DMA_ENABLE);
- while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- return event;
-}
-
-
-
diff --git a/drivers/staging/spectra/lld_cdma.h b/drivers/staging/spectra/lld_cdma.h
deleted file mode 100644
index 854ea066f0c4..000000000000
--- a/drivers/staging/spectra/lld_cdma.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-/* header for LLD_CDMA.c module */
-
-#ifndef _LLD_CDMA_
-#define _LLD_CDMA_
-
-#include "flash.h"
-
-#define DEBUG_SYNC 1
-
-/*/////////// CDMA specific MACRO definition */
-#define MAX_DESCS (255)
-#define MAX_CHANS (4)
-#define MAX_SYNC_POINTS (16)
-#define MAX_DESC_PER_CHAN (MAX_DESCS * 3 + MAX_SYNC_POINTS + 2)
-
-#define CHANNEL_SYNC_MASK (0x000F)
-#define CHANNEL_DMA_MASK (0x00F0)
-#define CHANNEL_ID_MASK (0x0300)
-#define CHANNEL_CONT_MASK (0x4000)
-#define CHANNEL_INTR_MASK (0x8000)
-
-#define CHANNEL_SYNC_OFFSET (0)
-#define CHANNEL_DMA_OFFSET (4)
-#define CHANNEL_ID_OFFSET (8)
-#define CHANNEL_CONT_OFFSET (14)
-#define CHANNEL_INTR_OFFSET (15)
-
-u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags);
-u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags);
-u16 CDMA_Execute_CMDs(void);
-void print_pending_cmds(void);
-void print_cdma_descriptors(void);
-
-extern u8 g_SBDCmdIndex;
-extern struct mrst_nand_info info;
-
-
-/*/////////// prototypes: APIs for LLD_CDMA */
-int is_cdma_interrupt(void);
-u16 CDMA_Event_Status(void);
-
-/* CMD-DMA Descriptor Struct. These are defined by the CMD_DMA HW */
-struct cdma_descriptor {
- u32 NxtPointerHi;
- u32 NxtPointerLo;
- u32 FlashPointerHi;
- u32 FlashPointerLo;
- u32 CommandType;
- u32 MemAddrHi;
- u32 MemAddrLo;
- u32 CommandFlags;
- u32 Channel;
- u32 Status;
- u32 MemCopyPointerHi;
- u32 MemCopyPointerLo;
- u32 Reserved12;
- u32 Reserved13;
- u32 Reserved14;
- u32 pcmd; /* pending cmd num related to this descriptor */
-};
-
-/* This struct holds one MemCopy descriptor as defined by the HW */
-struct memcpy_descriptor {
- u32 NxtPointerHi;
- u32 NxtPointerLo;
- u32 SrcAddrHi;
- u32 SrcAddrLo;
- u32 DestAddrHi;
- u32 DestAddrLo;
- u32 XferSize;
- u32 MemCopyFlags;
- u32 MemCopyStatus;
- u32 reserved9;
- u32 reserved10;
- u32 reserved11;
- u32 reserved12;
- u32 reserved13;
- u32 reserved14;
- u32 reserved15;
-};
-
-/* Pending CMD table entries (includes MemCopy parameters */
-struct pending_cmd {
- u8 CMD;
- u8 *DataAddr;
- u32 Block;
- u16 Page;
- u16 PageCount;
- u8 *DataDestAddr;
- u8 *DataSrcAddr;
- u32 MemCopyByteCnt;
- u16 Flags;
- u16 Status;
-};
-
-#if DEBUG_SYNC
-extern u32 debug_sync_cnt;
-#endif
-
-/* Definitions for CMD DMA descriptor chain fields */
-#define CMD_DMA_DESC_COMP 0x8000
-#define CMD_DMA_DESC_FAIL 0x4000
-
-#endif /*_LLD_CDMA_*/
diff --git a/drivers/staging/spectra/lld_emu.c b/drivers/staging/spectra/lld_emu.c
deleted file mode 100644
index 095f2f0c2e5b..000000000000
--- a/drivers/staging/spectra/lld_emu.c
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "flash.h"
-#include "ffsdefs.h"
-#include "lld_emu.h"
-#include "lld.h"
-#if CMD_DMA
-#include "lld_cdma.h"
-#if FLASH_EMU
-u32 totalUsedBanks;
-u32 valid_banks[MAX_CHANS];
-#endif
-#endif
-
-#define GLOB_LLD_PAGES 64
-#define GLOB_LLD_PAGE_SIZE (512+16)
-#define GLOB_LLD_PAGE_DATA_SIZE 512
-#define GLOB_LLD_BLOCKS 2048
-
-#if FLASH_EMU /* This is for entire module */
-
-static u8 *flash_memory[GLOB_LLD_BLOCKS * GLOB_LLD_PAGES];
-
-/* Read nand emu file and then fill it's content to flash_memory */
-int emu_load_file_to_mem(void)
-{
- mm_segment_t fs;
- struct file *nef_filp = NULL;
- struct inode *inode = NULL;
- loff_t nef_size = 0;
- loff_t tmp_file_offset, file_offset;
- ssize_t nread;
- int i, rc = -EINVAL;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- fs = get_fs();
- set_fs(get_ds());
-
- nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
- if (IS_ERR(nef_filp)) {
- printk(KERN_ERR "filp_open error: "
- "Unable to open nand emu file!\n");
- return PTR_ERR(nef_filp);
- }
-
- if (nef_filp->f_path.dentry) {
- inode = nef_filp->f_path.dentry->d_inode;
- } else {
- printk(KERN_ERR "Can not get valid inode!\n");
- goto out;
- }
-
- nef_size = i_size_read(inode->i_mapping->host);
- if (nef_size <= 0) {
- printk(KERN_ERR "Invalid nand emu file size: "
- "0x%llx\n", nef_size);
- goto out;
- } else {
- nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n",
- nef_size);
- }
-
- file_offset = 0;
- for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
- tmp_file_offset = file_offset;
- nread = vfs_read(nef_filp,
- (char __user *)flash_memory[i],
- GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
- if (nread < GLOB_LLD_PAGE_SIZE) {
- printk(KERN_ERR "%s, Line %d - "
- "nand emu file partial read: "
- "%d bytes\n", __FILE__, __LINE__, (int)nread);
- goto out;
- }
- file_offset += GLOB_LLD_PAGE_SIZE;
- }
- rc = 0;
-
-out:
- filp_close(nef_filp, current->files);
- set_fs(fs);
- return rc;
-}
-
-/* Write contents of flash_memory to nand emu file */
-int emu_write_mem_to_file(void)
-{
- mm_segment_t fs;
- struct file *nef_filp = NULL;
- struct inode *inode = NULL;
- loff_t nef_size = 0;
- loff_t tmp_file_offset, file_offset;
- ssize_t nwritten;
- int i, rc = -EINVAL;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- fs = get_fs();
- set_fs(get_ds());
-
- nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
- if (IS_ERR(nef_filp)) {
- printk(KERN_ERR "filp_open error: "
- "Unable to open nand emu file!\n");
- return PTR_ERR(nef_filp);
- }
-
- if (nef_filp->f_path.dentry) {
- inode = nef_filp->f_path.dentry->d_inode;
- } else {
- printk(KERN_ERR "Invalid " "nef_filp->f_path.dentry value!\n");
- goto out;
- }
-
- nef_size = i_size_read(inode->i_mapping->host);
- if (nef_size <= 0) {
- printk(KERN_ERR "Invalid "
- "nand emu file size: 0x%llx\n", nef_size);
- goto out;
- } else {
- nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: "
- "%lld\n", nef_size);
- }
-
- file_offset = 0;
- for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
- tmp_file_offset = file_offset;
- nwritten = vfs_write(nef_filp,
- (char __user *)flash_memory[i],
- GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
- if (nwritten < GLOB_LLD_PAGE_SIZE) {
- printk(KERN_ERR "%s, Line %d - "
- "nand emu file partial write: "
- "%d bytes\n", __FILE__, __LINE__, (int)nwritten);
- goto out;
- }
- file_offset += GLOB_LLD_PAGE_SIZE;
- }
- rc = 0;
-
-out:
- filp_close(nef_filp, current->files);
- set_fs(fs);
- return rc;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Flash_Init
-* Inputs: none
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Creates & initializes the flash RAM array.
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_Flash_Init(void)
-{
- int i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- flash_memory[0] = vmalloc(GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS *
- GLOB_LLD_PAGES * sizeof(u8));
- if (!flash_memory[0]) {
- printk(KERN_ERR "Fail to allocate memory "
- "for nand emulator!\n");
- return ERR;
- }
-
- memset((char *)(flash_memory[0]), 0xFF,
- GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES *
- sizeof(u8));
-
- for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++)
- flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE;
-
- emu_load_file_to_mem(); /* Load nand emu file to mem */
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Flash_Release
-* Inputs: none
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Releases the flash.
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int emu_Flash_Release(void)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- emu_write_mem_to_file(); /* Write back mem to nand emu file */
-
- vfree(flash_memory[0]);
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Read_Device_ID
-* Inputs: none
-* Outputs: PASS=1 FAIL=0
-* Description: Reads the info from the controller registers.
-* Sets up DeviceInfo structure with device parameters
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-
-u16 emu_Read_Device_ID(void)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- DeviceInfo.wDeviceMaker = 0;
- DeviceInfo.wDeviceType = 8;
- DeviceInfo.wSpectraStartBlock = 36;
- DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1;
- DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS;
- DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES;
- DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE;
- DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE;
- DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE -
- GLOB_LLD_PAGE_DATA_SIZE;
- DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES;
- DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES;
- DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock -
- DeviceInfo.wSpectraStartBlock
- + 1);
- DeviceInfo.MLCDevice = 1; /* Emulate MLC device */
- DeviceInfo.nBitsInPageNumber =
- (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
- DeviceInfo.nBitsInPageDataSize =
- (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
- DeviceInfo.nBitsInBlockDataSize =
- (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
-
-#if CMD_DMA
- totalUsedBanks = 4;
- valid_banks[0] = 1;
- valid_banks[1] = 1;
- valid_banks[2] = 1;
- valid_banks[3] = 1;
-#endif
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Flash_Reset
-* Inputs: none
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Reset the flash
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_Flash_Reset(void)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Erase_Block
-* Inputs: Address
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Erase a block
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_Erase_Block(u32 block_add)
-{
- int i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (block_add >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "emu_Erase_Block error! "
- "Too big block address: %d\n", block_add);
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n",
- (int)block_add);
-
- for (i = block_add * GLOB_LLD_PAGES;
- i < ((block_add + 1) * GLOB_LLD_PAGES); i++) {
- if (flash_memory[i]) {
- memset((u8 *)(flash_memory[i]), 0xFF,
- DeviceInfo.wPageSize * sizeof(u8));
- }
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Write_Page_Main
-* Inputs: Write buffer address pointer
-* Block number
-* Page number
-* Number of pages to process
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Write the data in the buffer to main area of flash
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_Write_Page_Main(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- int i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks)
- return FAIL;
-
- if (Page + PageCount > DeviceInfo.wPagesPerBlock)
- return FAIL;
-
- nand_dbg_print(NAND_DBG_DEBUG, "emu_Write_Page_Main: "
- "lba %u Page %u PageCount %u\n",
- (unsigned int)Block,
- (unsigned int)Page, (unsigned int)PageCount);
-
- for (i = 0; i < PageCount; i++) {
- if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
- printk(KERN_ERR "Run out of memory\n");
- return FAIL;
- }
- memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
- write_data, DeviceInfo.wPageDataSize);
- write_data += DeviceInfo.wPageDataSize;
- Page++;
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Read_Page_Main
-* Inputs: Read buffer address pointer
-* Block number
-* Page number
-* Number of pages to process
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Read the data from the flash main area to the buffer
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_Read_Page_Main(u8 *read_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- int i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks)
- return FAIL;
-
- if (Page + PageCount > DeviceInfo.wPagesPerBlock)
- return FAIL;
-
- nand_dbg_print(NAND_DBG_DEBUG, "emu_Read_Page_Main: "
- "lba %u Page %u PageCount %u\n",
- (unsigned int)Block,
- (unsigned int)Page, (unsigned int)PageCount);
-
- for (i = 0; i < PageCount; i++) {
- if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
- memset(read_data, 0xFF, DeviceInfo.wPageDataSize);
- } else {
- memcpy(read_data,
- (u8 *) (flash_memory[Block * GLOB_LLD_PAGES
- + Page]),
- DeviceInfo.wPageDataSize);
- }
- read_data += DeviceInfo.wPageDataSize;
- Page++;
- }
-
- return PASS;
-}
-
-#ifndef ELDORA
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Read_Page_Main_Spare
-* Inputs: Write Buffer
-* Address
-* Buffer size
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Read from flash main+spare area
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- int i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "Read Page Main+Spare "
- "Error: Block Address too big\n");
- return FAIL;
- }
-
- if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
- printk(KERN_ERR "Read Page Main+Spare "
- "Error: Page number too big\n");
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - "
- "No. of pages %u block %u start page %u\n",
- (unsigned int)PageCount,
- (unsigned int)Block, (unsigned int)Page);
-
- for (i = 0; i < PageCount; i++) {
- if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
- memset(read_data, 0xFF, DeviceInfo.wPageSize);
- } else {
- memcpy(read_data, (u8 *) (flash_memory[Block *
- GLOB_LLD_PAGES
- + Page]),
- DeviceInfo.wPageSize);
- }
-
- read_data += DeviceInfo.wPageSize;
- Page++;
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Write_Page_Main_Spare
-* Inputs: Write buffer
-* address
-* buffer length
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Write the buffer to main+spare area of flash
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block,
- u16 Page, u16 page_count)
-{
- u16 i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "Write Page Main + Spare "
- "Error: Block Address too big\n");
- return FAIL;
- }
-
- if (Page + page_count > DeviceInfo.wPagesPerBlock) {
- printk(KERN_ERR "Write Page Main + Spare "
- "Error: Page number too big\n");
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - "
- "No. of pages %u block %u start page %u\n",
- (unsigned int)page_count,
- (unsigned int)Block, (unsigned int)Page);
-
- for (i = 0; i < page_count; i++) {
- if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
- printk(KERN_ERR "Run out of memory!\n");
- return FAIL;
- }
- memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
- write_data, DeviceInfo.wPageSize);
- write_data += DeviceInfo.wPageSize;
- Page++;
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Write_Page_Spare
-* Inputs: Write buffer
-* Address
-* buffer size
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Write the buffer in the spare area
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_Write_Page_Spare(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "Read Page Spare Error: "
- "Block Address too big\n");
- return FAIL;
- }
-
- if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
- printk(KERN_ERR "Read Page Spare Error: "
- "Page number too big\n");
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Write Page Spare- "
- "block %u page %u\n",
- (unsigned int)Block, (unsigned int)Page);
-
- if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
- printk(KERN_ERR "Run out of memory!\n");
- return FAIL;
- }
-
- memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] +
- DeviceInfo.wPageDataSize), write_data,
- (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Read_Page_Spare
-* Inputs: Write Buffer
-* Address
-* Buffer size
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Read data from the spare area
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_Read_Page_Spare(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "Read Page Spare "
- "Error: Block Address too big\n");
- return FAIL;
- }
-
- if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
- printk(KERN_ERR "Read Page Spare "
- "Error: Page number too big\n");
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- "
- "block %u page %u\n",
- (unsigned int)Block, (unsigned int)Page);
-
- if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
- memset(write_data, 0xFF,
- (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
- } else {
- memcpy(write_data,
- (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]
- + DeviceInfo.wPageDataSize),
- (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Enable_Disable_Interrupts
-* Inputs: enable or disable
-* Outputs: none
-* Description: NOP
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-void emu_Enable_Disable_Interrupts(u16 INT_ENABLE)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-}
-
-u16 emu_Get_Bad_Block(u32 block)
-{
- return 0;
-}
-
-#if CMD_DMA
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Support for CDMA functions
-************************************
-* emu_CDMA_Flash_Init
-* CDMA_process_data command (use LLD_CDMA)
-* CDMA_MemCopy_CMD (use LLD_CDMA)
-* emu_CDMA_execute all commands
-* emu_CDMA_Event_Status
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_CDMA_Flash_Init(void)
-{
- u16 i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) {
- PendingCMD[i].CMD = 0;
- PendingCMD[i].Tag = 0;
- PendingCMD[i].DataAddr = 0;
- PendingCMD[i].Block = 0;
- PendingCMD[i].Page = 0;
- PendingCMD[i].PageCount = 0;
- PendingCMD[i].DataDestAddr = 0;
- PendingCMD[i].DataSrcAddr = 0;
- PendingCMD[i].MemCopyByteCnt = 0;
- PendingCMD[i].ChanSync[0] = 0;
- PendingCMD[i].ChanSync[1] = 0;
- PendingCMD[i].ChanSync[2] = 0;
- PendingCMD[i].ChanSync[3] = 0;
- PendingCMD[i].ChanSync[4] = 0;
- PendingCMD[i].Status = 3;
- }
-
- return PASS;
-}
-
-static void emu_isr(int irq, void *dev_id)
-{
- /* TODO: ... */
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: CDMA_Execute_CMDs
-* Inputs: tag_count: the number of pending cmds to do
-* Outputs: PASS/FAIL
-* Description: execute each command in the pending CMD array
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_CDMA_Execute_CMDs(u16 tag_count)
-{
- u16 i, j;
- u8 CMD; /* cmd parameter */
- u8 *data;
- u32 block;
- u16 page;
- u16 count;
- u16 status = PASS;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: "
- "Tag Count %u\n", tag_count);
-
- for (i = 0; i < totalUsedBanks; i++) {
- PendingCMD[i].CMD = DUMMY_CMD;
- PendingCMD[i].Tag = 0xFF;
- PendingCMD[i].Block =
- (DeviceInfo.wTotalBlocks / totalUsedBanks) * i;
-
- for (j = 0; j <= MAX_CHANS; j++)
- PendingCMD[i].ChanSync[j] = 0;
- }
-
- CDMA_Execute_CMDs(tag_count);
-
- print_pending_cmds(tag_count);
-
-#if DEBUG_SYNC
- }
- debug_sync_cnt++;
-#endif
-
- for (i = MAX_CHANS;
- i < tag_count + MAX_CHANS; i++) {
- CMD = PendingCMD[i].CMD;
- data = PendingCMD[i].DataAddr;
- block = PendingCMD[i].Block;
- page = PendingCMD[i].Page;
- count = PendingCMD[i].PageCount;
-
- switch (CMD) {
- case ERASE_CMD:
- emu_Erase_Block(block);
- PendingCMD[i].Status = PASS;
- break;
- case WRITE_MAIN_CMD:
- emu_Write_Page_Main(data, block, page, count);
- PendingCMD[i].Status = PASS;
- break;
- case WRITE_MAIN_SPARE_CMD:
- emu_Write_Page_Main_Spare(data, block, page, count);
- PendingCMD[i].Status = PASS;
- break;
- case READ_MAIN_CMD:
- emu_Read_Page_Main(data, block, page, count);
- PendingCMD[i].Status = PASS;
- break;
- case MEMCOPY_CMD:
- memcpy(PendingCMD[i].DataDestAddr,
- PendingCMD[i].DataSrcAddr,
- PendingCMD[i].MemCopyByteCnt);
- case DUMMY_CMD:
- PendingCMD[i].Status = PASS;
- break;
- default:
- PendingCMD[i].Status = FAIL;
- break;
- }
- }
-
- /*
- * Temperory adding code to reset PendingCMD array for basic testing.
- * It should be done at the end of event status function.
- */
- for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) {
- PendingCMD[i].CMD = 0;
- PendingCMD[i].Tag = 0;
- PendingCMD[i].DataAddr = 0;
- PendingCMD[i].Block = 0;
- PendingCMD[i].Page = 0;
- PendingCMD[i].PageCount = 0;
- PendingCMD[i].DataDestAddr = 0;
- PendingCMD[i].DataSrcAddr = 0;
- PendingCMD[i].MemCopyByteCnt = 0;
- PendingCMD[i].ChanSync[0] = 0;
- PendingCMD[i].ChanSync[1] = 0;
- PendingCMD[i].ChanSync[2] = 0;
- PendingCMD[i].ChanSync[3] = 0;
- PendingCMD[i].ChanSync[4] = 0;
- PendingCMD[i].Status = CMD_NOT_DONE;
- }
-
- nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n");
-
- emu_isr(0, 0); /* This is a null isr now. Need fill it in future */
-
- return status;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: emu_Event_Status
-* Inputs: none
-* Outputs: Event_Status code
-* Description: This function can also be used to force errors
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 emu_CDMA_Event_Status(void)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- return EVENT_PASS;
-}
-
-#endif /* CMD_DMA */
-#endif /* !ELDORA */
-#endif /* FLASH_EMU */
diff --git a/drivers/staging/spectra/lld_emu.h b/drivers/staging/spectra/lld_emu.h
deleted file mode 100644
index 63f84c38d3c1..000000000000
--- a/drivers/staging/spectra/lld_emu.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef _LLD_EMU_
-#define _LLD_EMU_
-
-#include "ffsport.h"
-#include "ffsdefs.h"
-
-/* prototypes: emulator API functions */
-extern u16 emu_Flash_Reset(void);
-extern u16 emu_Flash_Init(void);
-extern int emu_Flash_Release(void);
-extern u16 emu_Read_Device_ID(void);
-extern u16 emu_Erase_Block(u32 block_addr);
-extern u16 emu_Write_Page_Main(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount);
-extern u16 emu_Read_Page_Main(u8 *read_data, u32 Block, u16 Page,
- u16 PageCount);
-extern u16 emu_Event_Status(void);
-extern void emu_Enable_Disable_Interrupts(u16 INT_ENABLE);
-extern u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount);
-extern u16 emu_Write_Page_Spare(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount);
-extern u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block,
- u16 Page, u16 PageCount);
-extern u16 emu_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page,
- u16 PageCount);
-extern u16 emu_Get_Bad_Block(u32 block);
-
-u16 emu_CDMA_Flash_Init(void);
-u16 emu_CDMA_Execute_CMDs(u16 tag_count);
-u16 emu_CDMA_Event_Status(void);
-#endif /*_LLD_EMU_*/
diff --git a/drivers/staging/spectra/lld_mtd.c b/drivers/staging/spectra/lld_mtd.c
deleted file mode 100644
index a9c309a167c2..000000000000
--- a/drivers/staging/spectra/lld_mtd.c
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/mtd/mtd.h>
-#include "flash.h"
-#include "ffsdefs.h"
-#include "lld_emu.h"
-#include "lld.h"
-#if CMD_DMA
-#include "lld_cdma.h"
-u32 totalUsedBanks;
-u32 valid_banks[MAX_CHANS];
-#endif
-
-#define GLOB_LLD_PAGES 64
-#define GLOB_LLD_PAGE_SIZE (512+16)
-#define GLOB_LLD_PAGE_DATA_SIZE 512
-#define GLOB_LLD_BLOCKS 2048
-
-static struct mtd_info *spectra_mtd;
-static int mtddev = -1;
-module_param(mtddev, int, 0);
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Flash_Init
-* Inputs: none
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Creates & initializes the flash RAM array.
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_Flash_Init(void)
-{
- if (mtddev == -1) {
- printk(KERN_ERR "No MTD device specified. Give mtddev parameter\n");
- return FAIL;
- }
-
- spectra_mtd = get_mtd_device(NULL, mtddev);
- if (!spectra_mtd) {
- printk(KERN_ERR "Failed to obtain MTD device #%d\n", mtddev);
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Flash_Release
-* Inputs: none
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Releases the flash.
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-int mtd_Flash_Release(void)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
- if (!spectra_mtd)
- return PASS;
-
- put_mtd_device(spectra_mtd);
- spectra_mtd = NULL;
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Read_Device_ID
-* Inputs: none
-* Outputs: PASS=1 FAIL=0
-* Description: Reads the info from the controller registers.
-* Sets up DeviceInfo structure with device parameters
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-
-u16 mtd_Read_Device_ID(void)
-{
- uint64_t tmp;
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (!spectra_mtd)
- return FAIL;
-
- DeviceInfo.wDeviceMaker = 0;
- DeviceInfo.wDeviceType = 8;
- DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK;
- tmp = spectra_mtd->size;
- do_div(tmp, spectra_mtd->erasesize);
- DeviceInfo.wTotalBlocks = tmp;
- DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1;
- DeviceInfo.wPagesPerBlock = spectra_mtd->erasesize / spectra_mtd->writesize;
- DeviceInfo.wPageSize = spectra_mtd->writesize + spectra_mtd->oobsize;
- DeviceInfo.wPageDataSize = spectra_mtd->writesize;
- DeviceInfo.wPageSpareSize = spectra_mtd->oobsize;
- DeviceInfo.wBlockSize = DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock;
- DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * DeviceInfo.wPagesPerBlock;
- DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock -
- DeviceInfo.wSpectraStartBlock
- + 1);
- DeviceInfo.MLCDevice = 0;//spectra_mtd->celltype & NAND_CI_CELLTYPE_MSK;
- DeviceInfo.nBitsInPageNumber =
- (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
- DeviceInfo.nBitsInPageDataSize =
- (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
- DeviceInfo.nBitsInBlockDataSize =
- (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
-
-#if CMD_DMA
- totalUsedBanks = 4;
- valid_banks[0] = 1;
- valid_banks[1] = 1;
- valid_banks[2] = 1;
- valid_banks[3] = 1;
-#endif
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Flash_Reset
-* Inputs: none
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Reset the flash
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_Flash_Reset(void)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- return PASS;
-}
-
-void erase_callback(struct erase_info *e)
-{
- complete((void *)e->priv);
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Erase_Block
-* Inputs: Address
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Erase a block
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_Erase_Block(u32 block_add)
-{
- struct erase_info erase;
- DECLARE_COMPLETION_ONSTACK(comp);
- int ret;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (block_add >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "mtd_Erase_Block error! "
- "Too big block address: %d\n", block_add);
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n",
- (int)block_add);
-
- erase.mtd = spectra_mtd;
- erase.callback = erase_callback;
- erase.addr = block_add * spectra_mtd->erasesize;
- erase.len = spectra_mtd->erasesize;
- erase.priv = (unsigned long)&comp;
-
- ret = spectra_mtd->erase(spectra_mtd, &erase);
- if (!ret) {
- wait_for_completion(&comp);
- if (erase.state != MTD_ERASE_DONE)
- ret = -EIO;
- }
- if (ret) {
- printk(KERN_WARNING "mtd_Erase_Block error! "
- "erase of region [0x%llx, 0x%llx] failed\n",
- erase.addr, erase.len);
- return FAIL;
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Write_Page_Main
-* Inputs: Write buffer address pointer
-* Block number
-* Page number
-* Number of pages to process
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Write the data in the buffer to main area of flash
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_Write_Page_Main(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- size_t retlen;
- int ret = 0;
-
- if (Block >= DeviceInfo.wTotalBlocks)
- return FAIL;
-
- if (Page + PageCount > DeviceInfo.wPagesPerBlock)
- return FAIL;
-
- nand_dbg_print(NAND_DBG_DEBUG, "mtd_Write_Page_Main: "
- "lba %u Page %u PageCount %u\n",
- (unsigned int)Block,
- (unsigned int)Page, (unsigned int)PageCount);
-
-
- while (PageCount) {
- ret = spectra_mtd->write(spectra_mtd,
- (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
- DeviceInfo.wPageDataSize, &retlen, write_data);
- if (ret) {
- printk(KERN_ERR "%s failed %d\n", __func__, ret);
- return FAIL;
- }
- write_data += DeviceInfo.wPageDataSize;
- Page++;
- PageCount--;
- }
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Read_Page_Main
-* Inputs: Read buffer address pointer
-* Block number
-* Page number
-* Number of pages to process
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Read the data from the flash main area to the buffer
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_Read_Page_Main(u8 *read_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- size_t retlen;
- int ret = 0;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks)
- return FAIL;
-
- if (Page + PageCount > DeviceInfo.wPagesPerBlock)
- return FAIL;
-
- nand_dbg_print(NAND_DBG_DEBUG, "mtd_Read_Page_Main: "
- "lba %u Page %u PageCount %u\n",
- (unsigned int)Block,
- (unsigned int)Page, (unsigned int)PageCount);
-
-
- while (PageCount) {
- ret = spectra_mtd->read(spectra_mtd,
- (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
- DeviceInfo.wPageDataSize, &retlen, read_data);
- if (ret) {
- printk(KERN_ERR "%s failed %d\n", __func__, ret);
- return FAIL;
- }
- read_data += DeviceInfo.wPageDataSize;
- Page++;
- PageCount--;
- }
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- return PASS;
-}
-
-#ifndef ELDORA
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Read_Page_Main_Spare
-* Inputs: Write Buffer
-* Address
-* Buffer size
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Read from flash main+spare area
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "Read Page Main+Spare "
- "Error: Block Address too big\n");
- return FAIL;
- }
-
- if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
- printk(KERN_ERR "Read Page Main+Spare "
- "Error: Page number %d+%d too big in block %d\n",
- Page, PageCount, Block);
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - "
- "No. of pages %u block %u start page %u\n",
- (unsigned int)PageCount,
- (unsigned int)Block, (unsigned int)Page);
-
-
- while (PageCount) {
- struct mtd_oob_ops ops;
- int ret;
-
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.datbuf = read_data;
- ops.len = DeviceInfo.wPageDataSize;
- ops.oobbuf = read_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
- ops.ooblen = BTSIG_BYTES;
- ops.ooboffs = 0;
-
- ret = spectra_mtd->read_oob(spectra_mtd,
- (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
- &ops);
- if (ret) {
- printk(KERN_ERR "%s failed %d\n", __func__, ret);
- return FAIL;
- }
- read_data += DeviceInfo.wPageSize;
- Page++;
- PageCount--;
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Write_Page_Main_Spare
-* Inputs: Write buffer
-* address
-* buffer length
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Write the buffer to main+spare area of flash
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block,
- u16 Page, u16 page_count)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "Write Page Main + Spare "
- "Error: Block Address too big\n");
- return FAIL;
- }
-
- if (Page + page_count > DeviceInfo.wPagesPerBlock) {
- printk(KERN_ERR "Write Page Main + Spare "
- "Error: Page number %d+%d too big in block %d\n",
- Page, page_count, Block);
- WARN_ON(1);
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - "
- "No. of pages %u block %u start page %u\n",
- (unsigned int)page_count,
- (unsigned int)Block, (unsigned int)Page);
-
- while (page_count) {
- struct mtd_oob_ops ops;
- int ret;
-
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.datbuf = write_data;
- ops.len = DeviceInfo.wPageDataSize;
- ops.oobbuf = write_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
- ops.ooblen = BTSIG_BYTES;
- ops.ooboffs = 0;
-
- ret = spectra_mtd->write_oob(spectra_mtd,
- (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
- &ops);
- if (ret) {
- printk(KERN_ERR "%s failed %d\n", __func__, ret);
- return FAIL;
- }
- write_data += DeviceInfo.wPageSize;
- Page++;
- page_count--;
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Write_Page_Spare
-* Inputs: Write buffer
-* Address
-* buffer size
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Write the buffer in the spare area
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- WARN_ON(1);
- return FAIL;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Read_Page_Spare
-* Inputs: Write Buffer
-* Address
-* Buffer size
-* Outputs: PASS=0 (notice 0=ok here)
-* Description: Read data from the spare area
-*
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block,
- u16 Page, u16 PageCount)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (Block >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "Read Page Spare "
- "Error: Block Address too big\n");
- return FAIL;
- }
-
- if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
- printk(KERN_ERR "Read Page Spare "
- "Error: Page number too big\n");
- return FAIL;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- "
- "block %u page %u (%u pages)\n",
- (unsigned int)Block, (unsigned int)Page, PageCount);
-
- while (PageCount) {
- struct mtd_oob_ops ops;
- int ret;
-
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.datbuf = NULL;
- ops.len = 0;
- ops.oobbuf = read_data;
- ops.ooblen = BTSIG_BYTES;
- ops.ooboffs = 0;
-
- ret = spectra_mtd->read_oob(spectra_mtd,
- (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
- &ops);
- if (ret) {
- printk(KERN_ERR "%s failed %d\n", __func__, ret);
- return FAIL;
- }
-
- read_data += DeviceInfo.wPageSize;
- Page++;
- PageCount--;
- }
-
- return PASS;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Enable_Disable_Interrupts
-* Inputs: enable or disable
-* Outputs: none
-* Description: NOP
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-}
-
-u16 mtd_Get_Bad_Block(u32 block)
-{
- return 0;
-}
-
-#if CMD_DMA
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Support for CDMA functions
-************************************
-* mtd_CDMA_Flash_Init
-* CDMA_process_data command (use LLD_CDMA)
-* CDMA_MemCopy_CMD (use LLD_CDMA)
-* mtd_CDMA_execute all commands
-* mtd_CDMA_Event_Status
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_CDMA_Flash_Init(void)
-{
- u16 i;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) {
- PendingCMD[i].CMD = 0;
- PendingCMD[i].Tag = 0;
- PendingCMD[i].DataAddr = 0;
- PendingCMD[i].Block = 0;
- PendingCMD[i].Page = 0;
- PendingCMD[i].PageCount = 0;
- PendingCMD[i].DataDestAddr = 0;
- PendingCMD[i].DataSrcAddr = 0;
- PendingCMD[i].MemCopyByteCnt = 0;
- PendingCMD[i].ChanSync[0] = 0;
- PendingCMD[i].ChanSync[1] = 0;
- PendingCMD[i].ChanSync[2] = 0;
- PendingCMD[i].ChanSync[3] = 0;
- PendingCMD[i].ChanSync[4] = 0;
- PendingCMD[i].Status = 3;
- }
-
- return PASS;
-}
-
-static void mtd_isr(int irq, void *dev_id)
-{
- /* TODO: ... */
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: CDMA_Execute_CMDs
-* Inputs: tag_count: the number of pending cmds to do
-* Outputs: PASS/FAIL
-* Description: execute each command in the pending CMD array
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_CDMA_Execute_CMDs(u16 tag_count)
-{
- u16 i, j;
- u8 CMD; /* cmd parameter */
- u8 *data;
- u32 block;
- u16 page;
- u16 count;
- u16 status = PASS;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: "
- "Tag Count %u\n", tag_count);
-
- for (i = 0; i < totalUsedBanks; i++) {
- PendingCMD[i].CMD = DUMMY_CMD;
- PendingCMD[i].Tag = 0xFF;
- PendingCMD[i].Block =
- (DeviceInfo.wTotalBlocks / totalUsedBanks) * i;
-
- for (j = 0; j <= MAX_CHANS; j++)
- PendingCMD[i].ChanSync[j] = 0;
- }
-
- CDMA_Execute_CMDs(tag_count);
-
-#ifdef VERBOSE
- print_pending_cmds(tag_count);
-#endif
-#if DEBUG_SYNC
- }
- debug_sync_cnt++;
-#endif
-
- for (i = MAX_CHANS;
- i < tag_count + MAX_CHANS; i++) {
- CMD = PendingCMD[i].CMD;
- data = PendingCMD[i].DataAddr;
- block = PendingCMD[i].Block;
- page = PendingCMD[i].Page;
- count = PendingCMD[i].PageCount;
-
- switch (CMD) {
- case ERASE_CMD:
- mtd_Erase_Block(block);
- PendingCMD[i].Status = PASS;
- break;
- case WRITE_MAIN_CMD:
- mtd_Write_Page_Main(data, block, page, count);
- PendingCMD[i].Status = PASS;
- break;
- case WRITE_MAIN_SPARE_CMD:
- mtd_Write_Page_Main_Spare(data, block, page, count);
- PendingCMD[i].Status = PASS;
- break;
- case READ_MAIN_CMD:
- mtd_Read_Page_Main(data, block, page, count);
- PendingCMD[i].Status = PASS;
- break;
- case MEMCOPY_CMD:
- memcpy(PendingCMD[i].DataDestAddr,
- PendingCMD[i].DataSrcAddr,
- PendingCMD[i].MemCopyByteCnt);
- case DUMMY_CMD:
- PendingCMD[i].Status = PASS;
- break;
- default:
- PendingCMD[i].Status = FAIL;
- break;
- }
- }
-
- /*
- * Temperory adding code to reset PendingCMD array for basic testing.
- * It should be done at the end of event status function.
- */
- for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) {
- PendingCMD[i].CMD = 0;
- PendingCMD[i].Tag = 0;
- PendingCMD[i].DataAddr = 0;
- PendingCMD[i].Block = 0;
- PendingCMD[i].Page = 0;
- PendingCMD[i].PageCount = 0;
- PendingCMD[i].DataDestAddr = 0;
- PendingCMD[i].DataSrcAddr = 0;
- PendingCMD[i].MemCopyByteCnt = 0;
- PendingCMD[i].ChanSync[0] = 0;
- PendingCMD[i].ChanSync[1] = 0;
- PendingCMD[i].ChanSync[2] = 0;
- PendingCMD[i].ChanSync[3] = 0;
- PendingCMD[i].ChanSync[4] = 0;
- PendingCMD[i].Status = CMD_NOT_DONE;
- }
-
- nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n");
-
- mtd_isr(0, 0); /* This is a null isr now. Need fill it in future */
-
- return status;
-}
-
-/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-* Function: mtd_Event_Status
-* Inputs: none
-* Outputs: Event_Status code
-* Description: This function can also be used to force errors
-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
-u16 mtd_CDMA_Event_Status(void)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- return EVENT_PASS;
-}
-
-#endif /* CMD_DMA */
-#endif /* !ELDORA */
diff --git a/drivers/staging/spectra/lld_mtd.h b/drivers/staging/spectra/lld_mtd.h
deleted file mode 100644
index 4e81ee87b53d..000000000000
--- a/drivers/staging/spectra/lld_mtd.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef _LLD_MTD_
-#define _LLD_MTD_
-
-#include "ffsport.h"
-#include "ffsdefs.h"
-
-/* prototypes: MTD API functions */
-extern u16 mtd_Flash_Reset(void);
-extern u16 mtd_Flash_Init(void);
-extern int mtd_Flash_Release(void);
-extern u16 mtd_Read_Device_ID(void);
-extern u16 mtd_Erase_Block(u32 block_addr);
-extern u16 mtd_Write_Page_Main(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount);
-extern u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, u16 Page,
- u16 PageCount);
-extern u16 mtd_Event_Status(void);
-extern void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE);
-extern u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount);
-extern u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block,
- u16 Page, u16 PageCount);
-extern u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block,
- u16 Page, u16 PageCount);
-extern u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page,
- u16 PageCount);
-extern u16 mtd_Get_Bad_Block(u32 block);
-
-u16 mtd_CDMA_Flash_Init(void);
-u16 mtd_CDMA_Execute_CMDs(u16 tag_count);
-u16 mtd_CDMA_Event_Status(void);
-#endif /*_LLD_MTD_*/
diff --git a/drivers/staging/spectra/lld_nand.c b/drivers/staging/spectra/lld_nand.c
deleted file mode 100644
index 60a14ff26c7f..000000000000
--- a/drivers/staging/spectra/lld_nand.c
+++ /dev/null
@@ -1,2619 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "lld.h"
-#include "lld_nand.h"
-#include "lld_cdma.h"
-
-#include "spectraswconfig.h"
-#include "flash.h"
-#include "ffsdefs.h"
-
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/mutex.h>
-
-#include "nand_regs.h"
-
-#define SPECTRA_NAND_NAME "nd"
-
-#define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y)))
-#define MAX_PAGES_PER_RW 128
-
-#define INT_IDLE_STATE 0
-#define INT_READ_PAGE_MAIN 0x01
-#define INT_WRITE_PAGE_MAIN 0x02
-#define INT_PIPELINE_READ_AHEAD 0x04
-#define INT_PIPELINE_WRITE_AHEAD 0x08
-#define INT_MULTI_PLANE_READ 0x10
-#define INT_MULTI_PLANE_WRITE 0x11
-
-static u32 enable_ecc;
-
-struct mrst_nand_info info;
-
-int totalUsedBanks;
-u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS];
-
-void __iomem *FlashReg;
-void __iomem *FlashMem;
-
-u16 conf_parameters[] = {
- 0x0000,
- 0x0000,
- 0x01F4,
- 0x01F4,
- 0x01F4,
- 0x01F4,
- 0x0000,
- 0x0000,
- 0x0001,
- 0x0000,
- 0x0000,
- 0x0000,
- 0x0000,
- 0x0040,
- 0x0001,
- 0x000A,
- 0x000A,
- 0x000A,
- 0x0000,
- 0x0000,
- 0x0005,
- 0x0012,
- 0x000C
-};
-
-u16 NAND_Get_Bad_Block(u32 block)
-{
- u32 status = PASS;
- u32 flag_bytes = 0;
- u32 skip_bytes = DeviceInfo.wSpareSkipBytes;
- u32 page, i;
- u8 *pReadSpareBuf = buf_get_bad_block;
-
- if (enable_ecc)
- flag_bytes = DeviceInfo.wNumPageSpareFlag;
-
- for (page = 0; page < 2; page++) {
- status = NAND_Read_Page_Spare(pReadSpareBuf, block, page, 1);
- if (status != PASS)
- return READ_ERROR;
- for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++)
- if (pReadSpareBuf[i] != 0xff)
- return DEFECTIVE_BLOCK;
- }
-
- for (page = 1; page < 3; page++) {
- status = NAND_Read_Page_Spare(pReadSpareBuf, block,
- DeviceInfo.wPagesPerBlock - page , 1);
- if (status != PASS)
- return READ_ERROR;
- for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++)
- if (pReadSpareBuf[i] != 0xff)
- return DEFECTIVE_BLOCK;
- }
-
- return GOOD_BLOCK;
-}
-
-
-u16 NAND_Flash_Reset(void)
-{
- u32 i;
- u32 intr_status_rst_comp[4] = {INTR_STATUS0__RST_COMP,
- INTR_STATUS1__RST_COMP,
- INTR_STATUS2__RST_COMP,
- INTR_STATUS3__RST_COMP};
- u32 intr_status_time_out[4] = {INTR_STATUS0__TIME_OUT,
- INTR_STATUS1__TIME_OUT,
- INTR_STATUS2__TIME_OUT,
- INTR_STATUS3__TIME_OUT};
- u32 intr_status[4] = {INTR_STATUS0, INTR_STATUS1,
- INTR_STATUS2, INTR_STATUS3};
- u32 device_reset_banks[4] = {DEVICE_RESET__BANK0,
- DEVICE_RESET__BANK1,
- DEVICE_RESET__BANK2,
- DEVICE_RESET__BANK3};
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++)
- iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i],
- FlashReg + intr_status[i]);
-
- for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) {
- iowrite32(device_reset_banks[i], FlashReg + DEVICE_RESET);
- while (!(ioread32(FlashReg + intr_status[i]) &
- (intr_status_rst_comp[i] | intr_status_time_out[i])))
- ;
- if (ioread32(FlashReg + intr_status[i]) &
- intr_status_time_out[i])
- nand_dbg_print(NAND_DBG_WARN,
- "NAND Reset operation timed out on bank %d\n", i);
- }
-
- for (i = 0; i < LLD_MAX_FLASH_BANKS; i++)
- iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i],
- FlashReg + intr_status[i]);
-
- return PASS;
-}
-
-static void NAND_ONFi_Timing_Mode(u16 mode)
-{
- u16 Trea[6] = {40, 30, 25, 20, 20, 16};
- u16 Trp[6] = {50, 25, 17, 15, 12, 10};
- u16 Treh[6] = {30, 15, 15, 10, 10, 7};
- u16 Trc[6] = {100, 50, 35, 30, 25, 20};
- u16 Trhoh[6] = {0, 15, 15, 15, 15, 15};
- u16 Trloh[6] = {0, 0, 0, 0, 5, 5};
- u16 Tcea[6] = {100, 45, 30, 25, 25, 25};
- u16 Tadl[6] = {200, 100, 100, 100, 70, 70};
- u16 Trhw[6] = {200, 100, 100, 100, 100, 100};
- u16 Trhz[6] = {200, 100, 100, 100, 100, 100};
- u16 Twhr[6] = {120, 80, 80, 60, 60, 60};
- u16 Tcs[6] = {70, 35, 25, 25, 20, 15};
-
- u16 TclsRising = 1;
- u16 data_invalid_rhoh, data_invalid_rloh, data_invalid;
- u16 dv_window = 0;
- u16 en_lo, en_hi;
- u16 acc_clks;
- u16 addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- en_lo = CEIL_DIV(Trp[mode], CLK_X);
- en_hi = CEIL_DIV(Treh[mode], CLK_X);
-
-#if ONFI_BLOOM_TIME
- if ((en_hi * CLK_X) < (Treh[mode] + 2))
- en_hi++;
-#endif
-
- if ((en_lo + en_hi) * CLK_X < Trc[mode])
- en_lo += CEIL_DIV((Trc[mode] - (en_lo + en_hi) * CLK_X), CLK_X);
-
- if ((en_lo + en_hi) < CLK_MULTI)
- en_lo += CLK_MULTI - en_lo - en_hi;
-
- while (dv_window < 8) {
- data_invalid_rhoh = en_lo * CLK_X + Trhoh[mode];
-
- data_invalid_rloh = (en_lo + en_hi) * CLK_X + Trloh[mode];
-
- data_invalid =
- data_invalid_rhoh <
- data_invalid_rloh ? data_invalid_rhoh : data_invalid_rloh;
-
- dv_window = data_invalid - Trea[mode];
-
- if (dv_window < 8)
- en_lo++;
- }
-
- acc_clks = CEIL_DIV(Trea[mode], CLK_X);
-
- while (((acc_clks * CLK_X) - Trea[mode]) < 3)
- acc_clks++;
-
- if ((data_invalid - acc_clks * CLK_X) < 2)
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d: Warning!\n",
- __FILE__, __LINE__);
-
- addr_2_data = CEIL_DIV(Tadl[mode], CLK_X);
- re_2_we = CEIL_DIV(Trhw[mode], CLK_X);
- re_2_re = CEIL_DIV(Trhz[mode], CLK_X);
- we_2_re = CEIL_DIV(Twhr[mode], CLK_X);
- cs_cnt = CEIL_DIV((Tcs[mode] - Trp[mode]), CLK_X);
- if (!TclsRising)
- cs_cnt = CEIL_DIV(Tcs[mode], CLK_X);
- if (cs_cnt == 0)
- cs_cnt = 1;
-
- if (Tcea[mode]) {
- while (((cs_cnt * CLK_X) + Trea[mode]) < Tcea[mode])
- cs_cnt++;
- }
-
-#if MODE5_WORKAROUND
- if (mode == 5)
- acc_clks = 5;
-#endif
-
- /* Sighting 3462430: Temporary hack for MT29F128G08CJABAWP:B */
- if ((ioread32(FlashReg + MANUFACTURER_ID) == 0) &&
- (ioread32(FlashReg + DEVICE_ID) == 0x88))
- acc_clks = 6;
-
- iowrite32(acc_clks, FlashReg + ACC_CLKS);
- iowrite32(re_2_we, FlashReg + RE_2_WE);
- iowrite32(re_2_re, FlashReg + RE_2_RE);
- iowrite32(we_2_re, FlashReg + WE_2_RE);
- iowrite32(addr_2_data, FlashReg + ADDR_2_DATA);
- iowrite32(en_lo, FlashReg + RDWR_EN_LO_CNT);
- iowrite32(en_hi, FlashReg + RDWR_EN_HI_CNT);
- iowrite32(cs_cnt, FlashReg + CS_SETUP_CNT);
-}
-
-static void index_addr(u32 address, u32 data)
-{
- iowrite32(address, FlashMem);
- iowrite32(data, FlashMem + 0x10);
-}
-
-static void index_addr_read_data(u32 address, u32 *pdata)
-{
- iowrite32(address, FlashMem);
- *pdata = ioread32(FlashMem + 0x10);
-}
-
-static void set_ecc_config(void)
-{
-#if SUPPORT_8BITECC
- if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) < 4096) ||
- (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) <= 128))
- iowrite32(8, FlashReg + ECC_CORRECTION);
-#endif
-
- if ((ioread32(FlashReg + ECC_CORRECTION) & ECC_CORRECTION__VALUE)
- == 1) {
- DeviceInfo.wECCBytesPerSector = 4;
- DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected;
- DeviceInfo.wNumPageSpareFlag =
- DeviceInfo.wPageSpareSize -
- DeviceInfo.wPageDataSize /
- (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) *
- DeviceInfo.wECCBytesPerSector
- - DeviceInfo.wSpareSkipBytes;
- } else {
- DeviceInfo.wECCBytesPerSector =
- (ioread32(FlashReg + ECC_CORRECTION) &
- ECC_CORRECTION__VALUE) * 13 / 8;
- if ((DeviceInfo.wECCBytesPerSector) % 2 == 0)
- DeviceInfo.wECCBytesPerSector += 2;
- else
- DeviceInfo.wECCBytesPerSector += 1;
-
- DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected;
- DeviceInfo.wNumPageSpareFlag = DeviceInfo.wPageSpareSize -
- DeviceInfo.wPageDataSize /
- (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) *
- DeviceInfo.wECCBytesPerSector
- - DeviceInfo.wSpareSkipBytes;
- }
-}
-
-static u16 get_onfi_nand_para(void)
-{
- int i;
- u16 blks_lun_l, blks_lun_h, n_of_luns;
- u32 blockperlun, id;
-
- iowrite32(DEVICE_RESET__BANK0, FlashReg + DEVICE_RESET);
-
- while (!((ioread32(FlashReg + INTR_STATUS0) &
- INTR_STATUS0__RST_COMP) |
- (ioread32(FlashReg + INTR_STATUS0) &
- INTR_STATUS0__TIME_OUT)))
- ;
-
- if (ioread32(FlashReg + INTR_STATUS0) & INTR_STATUS0__RST_COMP) {
- iowrite32(DEVICE_RESET__BANK1, FlashReg + DEVICE_RESET);
- while (!((ioread32(FlashReg + INTR_STATUS1) &
- INTR_STATUS1__RST_COMP) |
- (ioread32(FlashReg + INTR_STATUS1) &
- INTR_STATUS1__TIME_OUT)))
- ;
-
- if (ioread32(FlashReg + INTR_STATUS1) &
- INTR_STATUS1__RST_COMP) {
- iowrite32(DEVICE_RESET__BANK2,
- FlashReg + DEVICE_RESET);
- while (!((ioread32(FlashReg + INTR_STATUS2) &
- INTR_STATUS2__RST_COMP) |
- (ioread32(FlashReg + INTR_STATUS2) &
- INTR_STATUS2__TIME_OUT)))
- ;
-
- if (ioread32(FlashReg + INTR_STATUS2) &
- INTR_STATUS2__RST_COMP) {
- iowrite32(DEVICE_RESET__BANK3,
- FlashReg + DEVICE_RESET);
- while (!((ioread32(FlashReg + INTR_STATUS3) &
- INTR_STATUS3__RST_COMP) |
- (ioread32(FlashReg + INTR_STATUS3) &
- INTR_STATUS3__TIME_OUT)))
- ;
- } else {
- printk(KERN_ERR "Getting a time out for bank 2!\n");
- }
- } else {
- printk(KERN_ERR "Getting a time out for bank 1!\n");
- }
- }
-
- iowrite32(INTR_STATUS0__TIME_OUT, FlashReg + INTR_STATUS0);
- iowrite32(INTR_STATUS1__TIME_OUT, FlashReg + INTR_STATUS1);
- iowrite32(INTR_STATUS2__TIME_OUT, FlashReg + INTR_STATUS2);
- iowrite32(INTR_STATUS3__TIME_OUT, FlashReg + INTR_STATUS3);
-
- DeviceInfo.wONFIDevFeatures =
- ioread32(FlashReg + ONFI_DEVICE_FEATURES);
- DeviceInfo.wONFIOptCommands =
- ioread32(FlashReg + ONFI_OPTIONAL_COMMANDS);
- DeviceInfo.wONFITimingMode =
- ioread32(FlashReg + ONFI_TIMING_MODE);
- DeviceInfo.wONFIPgmCacheTimingMode =
- ioread32(FlashReg + ONFI_PGM_CACHE_TIMING_MODE);
-
- n_of_luns = ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) &
- ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS;
- blks_lun_l = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L);
- blks_lun_h = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U);
-
- blockperlun = (blks_lun_h << 16) | blks_lun_l;
-
- DeviceInfo.wTotalBlocks = n_of_luns * blockperlun;
-
- if (!(ioread32(FlashReg + ONFI_TIMING_MODE) &
- ONFI_TIMING_MODE__VALUE))
- return FAIL;
-
- for (i = 5; i > 0; i--) {
- if (ioread32(FlashReg + ONFI_TIMING_MODE) & (0x01 << i))
- break;
- }
-
- NAND_ONFi_Timing_Mode(i);
-
- index_addr(MODE_11 | 0, 0x90);
- index_addr(MODE_11 | 1, 0);
-
- for (i = 0; i < 3; i++)
- index_addr_read_data(MODE_11 | 2, &id);
-
- nand_dbg_print(NAND_DBG_DEBUG, "3rd ID: 0x%x\n", id);
-
- DeviceInfo.MLCDevice = id & 0x0C;
-
- /* By now, all the ONFI devices we know support the page cache */
- /* rw feature. So here we enable the pipeline_rw_ahead feature */
- /* iowrite32(1, FlashReg + CACHE_WRITE_ENABLE); */
- /* iowrite32(1, FlashReg + CACHE_READ_ENABLE); */
-
- return PASS;
-}
-
-static void get_samsung_nand_para(void)
-{
- u8 no_of_planes;
- u32 blk_size;
- u64 plane_size, capacity;
- u32 id_bytes[5];
- int i;
-
- index_addr((u32)(MODE_11 | 0), 0x90);
- index_addr((u32)(MODE_11 | 1), 0);
- for (i = 0; i < 5; i++)
- index_addr_read_data((u32)(MODE_11 | 2), &id_bytes[i]);
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
- id_bytes[0], id_bytes[1], id_bytes[2],
- id_bytes[3], id_bytes[4]);
-
- if ((id_bytes[1] & 0xff) == 0xd3) { /* Samsung K9WAG08U1A */
- /* Set timing register values according to datasheet */
- iowrite32(5, FlashReg + ACC_CLKS);
- iowrite32(20, FlashReg + RE_2_WE);
- iowrite32(12, FlashReg + WE_2_RE);
- iowrite32(14, FlashReg + ADDR_2_DATA);
- iowrite32(3, FlashReg + RDWR_EN_LO_CNT);
- iowrite32(2, FlashReg + RDWR_EN_HI_CNT);
- iowrite32(2, FlashReg + CS_SETUP_CNT);
- }
-
- no_of_planes = 1 << ((id_bytes[4] & 0x0c) >> 2);
- plane_size = (u64)64 << ((id_bytes[4] & 0x70) >> 4);
- blk_size = 64 << ((ioread32(FlashReg + DEVICE_PARAM_1) & 0x30) >> 4);
- capacity = (u64)128 * plane_size * no_of_planes;
-
- DeviceInfo.wTotalBlocks = (u32)GLOB_u64_Div(capacity, blk_size);
-}
-
-static void get_toshiba_nand_para(void)
-{
- void __iomem *scratch_reg;
- u32 tmp;
-
- /* Workaround to fix a controller bug which reports a wrong */
- /* spare area size for some kind of Toshiba NAND device */
- if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) == 4096) &&
- (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) == 64)) {
- iowrite32(216, FlashReg + DEVICE_SPARE_AREA_SIZE);
- tmp = ioread32(FlashReg + DEVICES_CONNECTED) *
- ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE);
- iowrite32(tmp, FlashReg + LOGICAL_PAGE_SPARE_SIZE);
-#if SUPPORT_15BITECC
- iowrite32(15, FlashReg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
- iowrite32(8, FlashReg + ECC_CORRECTION);
-#endif
- }
-
- /* As Toshiba NAND can not provide it's block number, */
- /* so here we need user to provide the correct block */
- /* number in a scratch register before the Linux NAND */
- /* driver is loaded. If no valid value found in the scratch */
- /* register, then we use default block number value */
- scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE);
- if (!scratch_reg) {
- printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d",
- __FILE__, __LINE__);
- DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
- } else {
- nand_dbg_print(NAND_DBG_WARN,
- "Spectra: ioremap reg address: 0x%p\n", scratch_reg);
- DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg);
- if (DeviceInfo.wTotalBlocks < 512)
- DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
- iounmap(scratch_reg);
- }
-}
-
-static void get_hynix_nand_para(void)
-{
- void __iomem *scratch_reg;
- u32 main_size, spare_size;
-
- switch (DeviceInfo.wDeviceID) {
- case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */
- case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */
- iowrite32(128, FlashReg + PAGES_PER_BLOCK);
- iowrite32(4096, FlashReg + DEVICE_MAIN_AREA_SIZE);
- iowrite32(224, FlashReg + DEVICE_SPARE_AREA_SIZE);
- main_size = 4096 * ioread32(FlashReg + DEVICES_CONNECTED);
- spare_size = 224 * ioread32(FlashReg + DEVICES_CONNECTED);
- iowrite32(main_size, FlashReg + LOGICAL_PAGE_DATA_SIZE);
- iowrite32(spare_size, FlashReg + LOGICAL_PAGE_SPARE_SIZE);
- iowrite32(0, FlashReg + DEVICE_WIDTH);
-#if SUPPORT_15BITECC
- iowrite32(15, FlashReg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
- iowrite32(8, FlashReg + ECC_CORRECTION);
-#endif
- DeviceInfo.MLCDevice = 1;
- break;
- default:
- nand_dbg_print(NAND_DBG_WARN,
- "Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
- "Will use default parameter values instead.\n",
- DeviceInfo.wDeviceID);
- }
-
- scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE);
- if (!scratch_reg) {
- printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d",
- __FILE__, __LINE__);
- DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
- } else {
- nand_dbg_print(NAND_DBG_WARN,
- "Spectra: ioremap reg address: 0x%p\n", scratch_reg);
- DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg);
- if (DeviceInfo.wTotalBlocks < 512)
- DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
- iounmap(scratch_reg);
- }
-}
-
-static void find_valid_banks(void)
-{
- u32 id[LLD_MAX_FLASH_BANKS];
- int i;
-
- totalUsedBanks = 0;
- for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) {
- index_addr((u32)(MODE_11 | (i << 24) | 0), 0x90);
- index_addr((u32)(MODE_11 | (i << 24) | 1), 0);
- index_addr_read_data((u32)(MODE_11 | (i << 24) | 2), &id[i]);
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "Return 1st ID for bank[%d]: %x\n", i, id[i]);
-
- if (i == 0) {
- if (id[i] & 0x0ff)
- GLOB_valid_banks[i] = 1;
- } else {
- if ((id[i] & 0x0ff) == (id[0] & 0x0ff))
- GLOB_valid_banks[i] = 1;
- }
-
- totalUsedBanks += GLOB_valid_banks[i];
- }
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "totalUsedBanks: %d\n", totalUsedBanks);
-}
-
-static void detect_partition_feature(void)
-{
- if (ioread32(FlashReg + FEATURES) & FEATURES__PARTITION) {
- if ((ioread32(FlashReg + PERM_SRC_ID_1) &
- PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) {
- DeviceInfo.wSpectraStartBlock =
- ((ioread32(FlashReg + MIN_MAX_BANK_1) &
- MIN_MAX_BANK_1__MIN_VALUE) *
- DeviceInfo.wTotalBlocks)
- +
- (ioread32(FlashReg + MIN_BLK_ADDR_1) &
- MIN_BLK_ADDR_1__VALUE);
-
- DeviceInfo.wSpectraEndBlock =
- (((ioread32(FlashReg + MIN_MAX_BANK_1) &
- MIN_MAX_BANK_1__MAX_VALUE) >> 2) *
- DeviceInfo.wTotalBlocks)
- +
- (ioread32(FlashReg + MAX_BLK_ADDR_1) &
- MAX_BLK_ADDR_1__VALUE);
-
- DeviceInfo.wTotalBlocks *= totalUsedBanks;
-
- if (DeviceInfo.wSpectraEndBlock >=
- DeviceInfo.wTotalBlocks) {
- DeviceInfo.wSpectraEndBlock =
- DeviceInfo.wTotalBlocks - 1;
- }
-
- DeviceInfo.wDataBlockNum =
- DeviceInfo.wSpectraEndBlock -
- DeviceInfo.wSpectraStartBlock + 1;
- } else {
- DeviceInfo.wTotalBlocks *= totalUsedBanks;
- DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK;
- DeviceInfo.wSpectraEndBlock =
- DeviceInfo.wTotalBlocks - 1;
- DeviceInfo.wDataBlockNum =
- DeviceInfo.wSpectraEndBlock -
- DeviceInfo.wSpectraStartBlock + 1;
- }
- } else {
- DeviceInfo.wTotalBlocks *= totalUsedBanks;
- DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK;
- DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1;
- DeviceInfo.wDataBlockNum =
- DeviceInfo.wSpectraEndBlock -
- DeviceInfo.wSpectraStartBlock + 1;
- }
-}
-
-static void dump_device_info(void)
-{
- nand_dbg_print(NAND_DBG_DEBUG, "DeviceInfo:\n");
- nand_dbg_print(NAND_DBG_DEBUG, "DeviceMaker: 0x%x\n",
- DeviceInfo.wDeviceMaker);
- nand_dbg_print(NAND_DBG_DEBUG, "DeviceID: 0x%x\n",
- DeviceInfo.wDeviceID);
- nand_dbg_print(NAND_DBG_DEBUG, "DeviceType: 0x%x\n",
- DeviceInfo.wDeviceType);
- nand_dbg_print(NAND_DBG_DEBUG, "SpectraStartBlock: %d\n",
- DeviceInfo.wSpectraStartBlock);
- nand_dbg_print(NAND_DBG_DEBUG, "SpectraEndBlock: %d\n",
- DeviceInfo.wSpectraEndBlock);
- nand_dbg_print(NAND_DBG_DEBUG, "TotalBlocks: %d\n",
- DeviceInfo.wTotalBlocks);
- nand_dbg_print(NAND_DBG_DEBUG, "PagesPerBlock: %d\n",
- DeviceInfo.wPagesPerBlock);
- nand_dbg_print(NAND_DBG_DEBUG, "PageSize: %d\n",
- DeviceInfo.wPageSize);
- nand_dbg_print(NAND_DBG_DEBUG, "PageDataSize: %d\n",
- DeviceInfo.wPageDataSize);
- nand_dbg_print(NAND_DBG_DEBUG, "PageSpareSize: %d\n",
- DeviceInfo.wPageSpareSize);
- nand_dbg_print(NAND_DBG_DEBUG, "NumPageSpareFlag: %d\n",
- DeviceInfo.wNumPageSpareFlag);
- nand_dbg_print(NAND_DBG_DEBUG, "ECCBytesPerSector: %d\n",
- DeviceInfo.wECCBytesPerSector);
- nand_dbg_print(NAND_DBG_DEBUG, "BlockSize: %d\n",
- DeviceInfo.wBlockSize);
- nand_dbg_print(NAND_DBG_DEBUG, "BlockDataSize: %d\n",
- DeviceInfo.wBlockDataSize);
- nand_dbg_print(NAND_DBG_DEBUG, "DataBlockNum: %d\n",
- DeviceInfo.wDataBlockNum);
- nand_dbg_print(NAND_DBG_DEBUG, "PlaneNum: %d\n",
- DeviceInfo.bPlaneNum);
- nand_dbg_print(NAND_DBG_DEBUG, "DeviceMainAreaSize: %d\n",
- DeviceInfo.wDeviceMainAreaSize);
- nand_dbg_print(NAND_DBG_DEBUG, "DeviceSpareAreaSize: %d\n",
- DeviceInfo.wDeviceSpareAreaSize);
- nand_dbg_print(NAND_DBG_DEBUG, "DevicesConnected: %d\n",
- DeviceInfo.wDevicesConnected);
- nand_dbg_print(NAND_DBG_DEBUG, "DeviceWidth: %d\n",
- DeviceInfo.wDeviceWidth);
- nand_dbg_print(NAND_DBG_DEBUG, "HWRevision: 0x%x\n",
- DeviceInfo.wHWRevision);
- nand_dbg_print(NAND_DBG_DEBUG, "HWFeatures: 0x%x\n",
- DeviceInfo.wHWFeatures);
- nand_dbg_print(NAND_DBG_DEBUG, "ONFIDevFeatures: 0x%x\n",
- DeviceInfo.wONFIDevFeatures);
- nand_dbg_print(NAND_DBG_DEBUG, "ONFIOptCommands: 0x%x\n",
- DeviceInfo.wONFIOptCommands);
- nand_dbg_print(NAND_DBG_DEBUG, "ONFITimingMode: 0x%x\n",
- DeviceInfo.wONFITimingMode);
- nand_dbg_print(NAND_DBG_DEBUG, "ONFIPgmCacheTimingMode: 0x%x\n",
- DeviceInfo.wONFIPgmCacheTimingMode);
- nand_dbg_print(NAND_DBG_DEBUG, "MLCDevice: %s\n",
- DeviceInfo.MLCDevice ? "Yes" : "No");
- nand_dbg_print(NAND_DBG_DEBUG, "SpareSkipBytes: %d\n",
- DeviceInfo.wSpareSkipBytes);
- nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageNumber: %d\n",
- DeviceInfo.nBitsInPageNumber);
- nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageDataSize: %d\n",
- DeviceInfo.nBitsInPageDataSize);
- nand_dbg_print(NAND_DBG_DEBUG, "BitsInBlockDataSize: %d\n",
- DeviceInfo.nBitsInBlockDataSize);
-}
-
-u16 NAND_Read_Device_ID(void)
-{
- u16 status = PASS;
- u8 no_of_planes;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- iowrite32(0x02, FlashReg + SPARE_AREA_SKIP_BYTES);
- iowrite32(0xffff, FlashReg + SPARE_AREA_MARKER);
- DeviceInfo.wDeviceMaker = ioread32(FlashReg + MANUFACTURER_ID);
- DeviceInfo.wDeviceID = ioread32(FlashReg + DEVICE_ID);
- DeviceInfo.MLCDevice = ioread32(FlashReg + DEVICE_PARAM_0) & 0x0c;
-
- if (ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) &
- ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */
- if (FAIL == get_onfi_nand_para())
- return FAIL;
- } else if (DeviceInfo.wDeviceMaker == 0xEC) { /* Samsung NAND */
- get_samsung_nand_para();
- } else if (DeviceInfo.wDeviceMaker == 0x98) { /* Toshiba NAND */
- get_toshiba_nand_para();
- } else if (DeviceInfo.wDeviceMaker == 0xAD) { /* Hynix NAND */
- get_hynix_nand_para();
- } else {
- DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
- }
-
- nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:"
- "acc_clks: %d, re_2_we: %d, we_2_re: %d,"
- "addr_2_data: %d, rdwr_en_lo_cnt: %d, "
- "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
- ioread32(FlashReg + ACC_CLKS),
- ioread32(FlashReg + RE_2_WE),
- ioread32(FlashReg + WE_2_RE),
- ioread32(FlashReg + ADDR_2_DATA),
- ioread32(FlashReg + RDWR_EN_LO_CNT),
- ioread32(FlashReg + RDWR_EN_HI_CNT),
- ioread32(FlashReg + CS_SETUP_CNT));
-
- DeviceInfo.wHWRevision = ioread32(FlashReg + REVISION);
- DeviceInfo.wHWFeatures = ioread32(FlashReg + FEATURES);
-
- DeviceInfo.wDeviceMainAreaSize =
- ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE);
- DeviceInfo.wDeviceSpareAreaSize =
- ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE);
-
- DeviceInfo.wPageDataSize =
- ioread32(FlashReg + LOGICAL_PAGE_DATA_SIZE);
-
- /* Note: When using the Micon 4K NAND device, the controller will report
- * Page Spare Size as 216 bytes. But Micron's Spec say it's 218 bytes.
- * And if force set it to 218 bytes, the controller can not work
- * correctly. So just let it be. But keep in mind that this bug may
- * cause
- * other problems in future. - Yunpeng 2008-10-10
- */
- DeviceInfo.wPageSpareSize =
- ioread32(FlashReg + LOGICAL_PAGE_SPARE_SIZE);
-
- DeviceInfo.wPagesPerBlock = ioread32(FlashReg + PAGES_PER_BLOCK);
-
- DeviceInfo.wPageSize =
- DeviceInfo.wPageDataSize + DeviceInfo.wPageSpareSize;
- DeviceInfo.wBlockSize =
- DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock;
- DeviceInfo.wBlockDataSize =
- DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize;
-
- DeviceInfo.wDeviceWidth = ioread32(FlashReg + DEVICE_WIDTH);
- DeviceInfo.wDeviceType =
- ((ioread32(FlashReg + DEVICE_WIDTH) > 0) ? 16 : 8);
-
- DeviceInfo.wDevicesConnected = ioread32(FlashReg + DEVICES_CONNECTED);
-
- DeviceInfo.wSpareSkipBytes =
- ioread32(FlashReg + SPARE_AREA_SKIP_BYTES) *
- DeviceInfo.wDevicesConnected;
-
- DeviceInfo.nBitsInPageNumber =
- (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
- DeviceInfo.nBitsInPageDataSize =
- (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
- DeviceInfo.nBitsInBlockDataSize =
- (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
-
- set_ecc_config();
-
- no_of_planes = ioread32(FlashReg + NUMBER_OF_PLANES) &
- NUMBER_OF_PLANES__VALUE;
-
- switch (no_of_planes) {
- case 0:
- case 1:
- case 3:
- case 7:
- DeviceInfo.bPlaneNum = no_of_planes + 1;
- break;
- default:
- status = FAIL;
- break;
- }
-
- find_valid_banks();
-
- detect_partition_feature();
-
- dump_device_info();
-
- return status;
-}
-
-u16 NAND_UnlockArrayAll(void)
-{
- u64 start_addr, end_addr;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- start_addr = 0;
- end_addr = ((u64)DeviceInfo.wBlockSize *
- (DeviceInfo.wTotalBlocks - 1)) >>
- DeviceInfo.nBitsInPageDataSize;
-
- index_addr((u32)(MODE_10 | (u32)start_addr), 0x10);
- index_addr((u32)(MODE_10 | (u32)end_addr), 0x11);
-
- return PASS;
-}
-
-void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE)
-{
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (INT_ENABLE)
- iowrite32(1, FlashReg + GLOBAL_INT_ENABLE);
- else
- iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
-}
-
-u16 NAND_Erase_Block(u32 block)
-{
- u16 status = PASS;
- u64 flash_add;
- u16 flash_bank;
- u32 intr_status = 0;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- * DeviceInfo.wBlockDataSize;
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- if (block >= DeviceInfo.wTotalBlocks)
- status = FAIL;
-
- if (status == PASS) {
- intr_status = intr_status_addresses[flash_bank];
-
- iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL,
- FlashReg + intr_status);
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)), 1);
-
- while (!(ioread32(FlashReg + intr_status) &
- (INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL)))
- ;
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ERASE_FAIL)
- status = FAIL;
-
- iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL,
- FlashReg + intr_status);
- }
-
- return status;
-}
-
-static u32 Boundary_Check_Block_Page(u32 block, u16 page,
- u16 page_count)
-{
- u32 status = PASS;
-
- if (block >= DeviceInfo.wTotalBlocks)
- status = FAIL;
-
- if (page + page_count > DeviceInfo.wPagesPerBlock)
- status = FAIL;
-
- return status;
-}
-
-u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page,
- u16 page_count)
-{
- u32 status = PASS;
- u32 i;
- u64 flash_add;
- u32 PageSpareSize = DeviceInfo.wPageSpareSize;
- u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
- u32 flash_bank;
- u32 intr_status = 0;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- u8 *page_spare = buf_read_page_spare;
-
- if (block >= DeviceInfo.wTotalBlocks) {
- printk(KERN_ERR "block too big: %d\n", (int)block);
- status = FAIL;
- }
-
- if (page >= DeviceInfo.wPagesPerBlock) {
- printk(KERN_ERR "page too big: %d\n", page);
- status = FAIL;
- }
-
- if (page_count > 1) {
- printk(KERN_ERR "page count too big: %d\n", page_count);
- status = FAIL;
- }
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- * DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- if (status == PASS) {
- intr_status = intr_status_addresses[flash_bank];
- iowrite32(ioread32(FlashReg + intr_status),
- FlashReg + intr_status);
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)),
- 0x41);
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)),
- 0x2000 | page_count);
- while (!(ioread32(FlashReg + intr_status) &
- INTR_STATUS0__LOAD_COMP))
- ;
-
- iowrite32((u32)(MODE_01 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)),
- FlashMem);
-
- for (i = 0; i < (PageSpareSize / 4); i++)
- *((u32 *)page_spare + i) =
- ioread32(FlashMem + 0x10);
-
- if (enable_ecc) {
- for (i = 0; i < spareFlagBytes; i++)
- read_data[i] =
- page_spare[PageSpareSize -
- spareFlagBytes + i];
- for (i = 0; i < (PageSpareSize - spareFlagBytes); i++)
- read_data[spareFlagBytes + i] =
- page_spare[i];
- } else {
- for (i = 0; i < PageSpareSize; i++)
- read_data[i] = page_spare[i];
- }
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
- }
-
- return status;
-}
-
-/* No use function. Should be removed later */
-u16 NAND_Write_Page_Spare(u8 *write_data, u32 block, u16 page,
- u16 page_count)
-{
- printk(KERN_ERR
- "Error! This function (NAND_Write_Page_Spare) should never"
- " be called!\n");
- return ERR;
-}
-
-/* op value: 0 - DDMA read; 1 - DDMA write */
-static void ddma_trans(u8 *data, u64 flash_add,
- u32 flash_bank, int op, u32 numPages)
-{
- u32 data_addr;
-
- /* Map virtual address to bus address for DDMA */
- data_addr = virt_to_bus(data);
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)),
- (u16)(2 << 12) | (op << 8) | numPages);
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- ((u16)(0x0FFFF & (data_addr >> 16)) << 8)),
- (u16)(2 << 12) | (2 << 8) | 0);
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- ((u16)(0x0FFFF & data_addr) << 8)),
- (u16)(2 << 12) | (3 << 8) | 0);
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (1 << 16) | (0x40 << 8)),
- (u16)(2 << 12) | (4 << 8) | 0);
-}
-
-/* If data in buf are all 0xff, then return 1; otherwise return 0 */
-static int check_all_1(u8 *buf)
-{
- int i, j, cnt;
-
- for (i = 0; i < DeviceInfo.wPageDataSize; i++) {
- if (buf[i] != 0xff) {
- cnt = 0;
- nand_dbg_print(NAND_DBG_WARN,
- "the first non-0xff data byte is: %d\n", i);
- for (j = i; j < DeviceInfo.wPageDataSize; j++) {
- nand_dbg_print(NAND_DBG_WARN, "0x%x ", buf[j]);
- cnt++;
- if (cnt > 8)
- break;
- }
- nand_dbg_print(NAND_DBG_WARN, "\n");
- return 0;
- }
- }
-
- return 1;
-}
-
-static int do_ecc_new(unsigned long bank, u8 *buf,
- u32 block, u16 page)
-{
- int status = PASS;
- u16 err_page = 0;
- u16 err_byte;
- u8 err_sect;
- u8 err_dev;
- u16 err_fix_info;
- u16 err_addr;
- u32 ecc_sect_size;
- u8 *err_pos;
- u32 err_page_addr[4] = {ERR_PAGE_ADDR0,
- ERR_PAGE_ADDR1, ERR_PAGE_ADDR2, ERR_PAGE_ADDR3};
-
- ecc_sect_size = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
-
- do {
- err_page = ioread32(FlashReg + err_page_addr[bank]);
- err_addr = ioread32(FlashReg + ECC_ERROR_ADDRESS);
- err_byte = err_addr & ECC_ERROR_ADDRESS__OFFSET;
- err_sect = ((err_addr & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12);
- err_fix_info = ioread32(FlashReg + ERR_CORRECTION_INFO);
- err_dev = ((err_fix_info & ERR_CORRECTION_INFO__DEVICE_NR)
- >> 8);
- if (err_fix_info & ERR_CORRECTION_INFO__ERROR_TYPE) {
- nand_dbg_print(NAND_DBG_WARN,
- "%s, Line %d Uncorrectable ECC error "
- "when read block %d page %d."
- "PTN_INTR register: 0x%x "
- "err_page: %d, err_sect: %d, err_byte: %d, "
- "err_dev: %d, ecc_sect_size: %d, "
- "err_fix_info: 0x%x\n",
- __FILE__, __LINE__, block, page,
- ioread32(FlashReg + PTN_INTR),
- err_page, err_sect, err_byte, err_dev,
- ecc_sect_size, (u32)err_fix_info);
-
- if (check_all_1(buf))
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d"
- "All 0xff!\n",
- __FILE__, __LINE__);
- else
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d"
- "Not all 0xff!\n",
- __FILE__, __LINE__);
- status = FAIL;
- } else {
- nand_dbg_print(NAND_DBG_WARN,
- "%s, Line %d Found ECC error "
- "when read block %d page %d."
- "err_page: %d, err_sect: %d, err_byte: %d, "
- "err_dev: %d, ecc_sect_size: %d, "
- "err_fix_info: 0x%x\n",
- __FILE__, __LINE__, block, page,
- err_page, err_sect, err_byte, err_dev,
- ecc_sect_size, (u32)err_fix_info);
- if (err_byte < ECC_SECTOR_SIZE) {
- err_pos = buf +
- (err_page - page) *
- DeviceInfo.wPageDataSize +
- err_sect * ecc_sect_size +
- err_byte *
- DeviceInfo.wDevicesConnected +
- err_dev;
-
- *err_pos ^= err_fix_info &
- ERR_CORRECTION_INFO__BYTEMASK;
- }
- }
- } while (!(err_fix_info & ERR_CORRECTION_INFO__LAST_ERR_INFO));
-
- return status;
-}
-
-u16 NAND_Read_Page_Main_Polling(u8 *read_data,
- u32 block, u16 page, u16 page_count)
-{
- u32 status = PASS;
- u64 flash_add;
- u32 intr_status = 0;
- u32 flash_bank;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- u8 *read_data_l;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
- if (status != PASS)
- return status;
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- * DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
-
- intr_status = intr_status_addresses[flash_bank];
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- if (page_count > 1) {
- read_data_l = read_data;
- while (page_count > MAX_PAGES_PER_RW) {
- if (ioread32(FlashReg + MULTIPLANE_OPERATION))
- status = NAND_Multiplane_Read(read_data_l,
- block, page, MAX_PAGES_PER_RW);
- else
- status = NAND_Pipeline_Read_Ahead_Polling(
- read_data_l, block, page,
- MAX_PAGES_PER_RW);
-
- if (status == FAIL)
- return status;
-
- read_data_l += DeviceInfo.wPageDataSize *
- MAX_PAGES_PER_RW;
- page_count -= MAX_PAGES_PER_RW;
- page += MAX_PAGES_PER_RW;
- }
- if (ioread32(FlashReg + MULTIPLANE_OPERATION))
- status = NAND_Multiplane_Read(read_data_l,
- block, page, page_count);
- else
- status = NAND_Pipeline_Read_Ahead_Polling(
- read_data_l, block, page, page_count);
-
- return status;
- }
-
- iowrite32(1, FlashReg + DMA_ENABLE);
- while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- ddma_trans(read_data, flash_add, flash_bank, 0, 1);
-
- if (enable_ecc) {
- while (!(ioread32(FlashReg + intr_status) &
- (INTR_STATUS0__ECC_TRANSACTION_DONE |
- INTR_STATUS0__ECC_ERR)))
- ;
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_ERR) {
- iowrite32(INTR_STATUS0__ECC_ERR,
- FlashReg + intr_status);
- status = do_ecc_new(flash_bank, read_data,
- block, page);
- }
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_TRANSACTION_DONE &
- INTR_STATUS0__ECC_ERR)
- iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE |
- INTR_STATUS0__ECC_ERR,
- FlashReg + intr_status);
- else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_TRANSACTION_DONE)
- iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE,
- FlashReg + intr_status);
- else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_ERR)
- iowrite32(INTR_STATUS0__ECC_ERR,
- FlashReg + intr_status);
- } else {
- while (!(ioread32(FlashReg + intr_status) &
- INTR_STATUS0__DMA_CMD_COMP))
- ;
- iowrite32(INTR_STATUS0__DMA_CMD_COMP, FlashReg + intr_status);
- }
-
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- iowrite32(0, FlashReg + DMA_ENABLE);
- while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- return status;
-}
-
-u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data,
- u32 block, u16 page, u16 page_count)
-{
- u32 status = PASS;
- u32 NumPages = page_count;
- u64 flash_add;
- u32 flash_bank;
- u32 intr_status = 0;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- u32 ecc_done_OR_dma_comp;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
-
- if (page_count < 2)
- status = FAIL;
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- *DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- if (status == PASS) {
- intr_status = intr_status_addresses[flash_bank];
- iowrite32(ioread32(FlashReg + intr_status),
- FlashReg + intr_status);
-
- iowrite32(1, FlashReg + DMA_ENABLE);
- while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
- ddma_trans(read_data, flash_add, flash_bank, 0, NumPages);
-
- ecc_done_OR_dma_comp = 0;
- while (1) {
- if (enable_ecc) {
- while (!ioread32(FlashReg + intr_status))
- ;
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_ERR) {
- iowrite32(INTR_STATUS0__ECC_ERR,
- FlashReg + intr_status);
- status = do_ecc_new(flash_bank,
- read_data, block, page);
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__DMA_CMD_COMP) {
- iowrite32(INTR_STATUS0__DMA_CMD_COMP,
- FlashReg + intr_status);
-
- if (1 == ecc_done_OR_dma_comp)
- break;
-
- ecc_done_OR_dma_comp = 1;
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_TRANSACTION_DONE) {
- iowrite32(
- INTR_STATUS0__ECC_TRANSACTION_DONE,
- FlashReg + intr_status);
-
- if (1 == ecc_done_OR_dma_comp)
- break;
-
- ecc_done_OR_dma_comp = 1;
- }
- } else {
- while (!(ioread32(FlashReg + intr_status) &
- INTR_STATUS0__DMA_CMD_COMP))
- ;
-
- iowrite32(INTR_STATUS0__DMA_CMD_COMP,
- FlashReg + intr_status);
- break;
- }
-
- iowrite32((~INTR_STATUS0__ECC_ERR) &
- (~INTR_STATUS0__ECC_TRANSACTION_DONE) &
- (~INTR_STATUS0__DMA_CMD_COMP),
- FlashReg + intr_status);
-
- }
-
- iowrite32(ioread32(FlashReg + intr_status),
- FlashReg + intr_status);
-
- iowrite32(0, FlashReg + DMA_ENABLE);
-
- while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
- }
- return status;
-}
-
-u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page,
- u16 page_count)
-{
- u32 status = PASS;
- u64 flash_add;
- u32 intr_status = 0;
- u32 flash_bank;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- int ret;
- u8 *read_data_l;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
- if (status != PASS)
- return status;
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- * DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
-
- intr_status = intr_status_addresses[flash_bank];
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- if (page_count > 1) {
- read_data_l = read_data;
- while (page_count > MAX_PAGES_PER_RW) {
- if (ioread32(FlashReg + MULTIPLANE_OPERATION))
- status = NAND_Multiplane_Read(read_data_l,
- block, page, MAX_PAGES_PER_RW);
- else
- status = NAND_Pipeline_Read_Ahead(
- read_data_l, block, page,
- MAX_PAGES_PER_RW);
-
- if (status == FAIL)
- return status;
-
- read_data_l += DeviceInfo.wPageDataSize *
- MAX_PAGES_PER_RW;
- page_count -= MAX_PAGES_PER_RW;
- page += MAX_PAGES_PER_RW;
- }
- if (ioread32(FlashReg + MULTIPLANE_OPERATION))
- status = NAND_Multiplane_Read(read_data_l,
- block, page, page_count);
- else
- status = NAND_Pipeline_Read_Ahead(
- read_data_l, block, page, page_count);
-
- return status;
- }
-
- iowrite32(1, FlashReg + DMA_ENABLE);
- while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- /* Fill the mrst_nand_info structure */
- info.state = INT_READ_PAGE_MAIN;
- info.read_data = read_data;
- info.flash_bank = flash_bank;
- info.block = block;
- info.page = page;
- info.ret = PASS;
-
- ddma_trans(read_data, flash_add, flash_bank, 0, 1);
-
- iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */
-
- ret = wait_for_completion_timeout(&info.complete, 10 * HZ);
- if (!ret) {
- printk(KERN_ERR "Wait for completion timeout "
- "in %s, Line %d\n", __FILE__, __LINE__);
- status = ERR;
- } else {
- status = info.ret;
- }
-
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- iowrite32(0, FlashReg + DMA_ENABLE);
- while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- return status;
-}
-
-void Conv_Spare_Data_Log2Phy_Format(u8 *data)
-{
- int i;
- const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
- const u32 PageSpareSize = DeviceInfo.wPageSpareSize;
-
- if (enable_ecc) {
- for (i = spareFlagBytes - 1; i >= 0; i--)
- data[PageSpareSize - spareFlagBytes + i] = data[i];
- }
-}
-
-void Conv_Spare_Data_Phy2Log_Format(u8 *data)
-{
- int i;
- const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
- const u32 PageSpareSize = DeviceInfo.wPageSpareSize;
-
- if (enable_ecc) {
- for (i = 0; i < spareFlagBytes; i++)
- data[i] = data[PageSpareSize - spareFlagBytes + i];
- }
-}
-
-
-void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count)
-{
- const u32 PageSize = DeviceInfo.wPageSize;
- const u32 PageDataSize = DeviceInfo.wPageDataSize;
- const u32 eccBytes = DeviceInfo.wECCBytesPerSector;
- const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes;
- const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
- u32 eccSectorSize;
- u32 page_offset;
- int i, j;
-
- eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
- if (enable_ecc) {
- while (page_count > 0) {
- page_offset = (page_count - 1) * PageSize;
- j = (DeviceInfo.wPageDataSize / eccSectorSize);
- for (i = spareFlagBytes - 1; i >= 0; i--)
- data[page_offset +
- (eccSectorSize + eccBytes) * j + i] =
- data[page_offset + PageDataSize + i];
- for (j--; j >= 1; j--) {
- for (i = eccSectorSize - 1; i >= 0; i--)
- data[page_offset +
- (eccSectorSize + eccBytes) * j + i] =
- data[page_offset +
- eccSectorSize * j + i];
- }
- for (i = (PageSize - spareSkipBytes) - 1;
- i >= PageDataSize; i--)
- data[page_offset + i + spareSkipBytes] =
- data[page_offset + i];
- page_count--;
- }
- }
-}
-
-void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count)
-{
- const u32 PageSize = DeviceInfo.wPageSize;
- const u32 PageDataSize = DeviceInfo.wPageDataSize;
- const u32 eccBytes = DeviceInfo.wECCBytesPerSector;
- const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes;
- const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
- u32 eccSectorSize;
- u32 page_offset;
- int i, j;
-
- eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
- if (enable_ecc) {
- while (page_count > 0) {
- page_offset = (page_count - 1) * PageSize;
- for (i = PageDataSize;
- i < PageSize - spareSkipBytes;
- i++)
- data[page_offset + i] =
- data[page_offset + i +
- spareSkipBytes];
- for (j = 1;
- j < DeviceInfo.wPageDataSize / eccSectorSize;
- j++) {
- for (i = 0; i < eccSectorSize; i++)
- data[page_offset +
- eccSectorSize * j + i] =
- data[page_offset +
- (eccSectorSize + eccBytes) * j
- + i];
- }
- for (i = 0; i < spareFlagBytes; i++)
- data[page_offset + PageDataSize + i] =
- data[page_offset +
- (eccSectorSize + eccBytes) * j + i];
- page_count--;
- }
- }
-}
-
-/* Un-tested function */
-u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page,
- u16 page_count)
-{
- u32 status = PASS;
- u32 NumPages = page_count;
- u64 flash_add;
- u32 flash_bank;
- u32 intr_status = 0;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- u32 ecc_done_OR_dma_comp;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- * DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- if (status == PASS) {
- intr_status = intr_status_addresses[flash_bank];
- iowrite32(ioread32(FlashReg + intr_status),
- FlashReg + intr_status);
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
- iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION);
-
- iowrite32(1, FlashReg + DMA_ENABLE);
- while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
- ddma_trans(read_data, flash_add, flash_bank, 0, NumPages);
-
- ecc_done_OR_dma_comp = 0;
- while (1) {
- if (enable_ecc) {
- while (!ioread32(FlashReg + intr_status))
- ;
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_ERR) {
- iowrite32(INTR_STATUS0__ECC_ERR,
- FlashReg + intr_status);
- status = do_ecc_new(flash_bank,
- read_data, block, page);
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__DMA_CMD_COMP) {
- iowrite32(INTR_STATUS0__DMA_CMD_COMP,
- FlashReg + intr_status);
-
- if (1 == ecc_done_OR_dma_comp)
- break;
-
- ecc_done_OR_dma_comp = 1;
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_TRANSACTION_DONE) {
- iowrite32(
- INTR_STATUS0__ECC_TRANSACTION_DONE,
- FlashReg + intr_status);
-
- if (1 == ecc_done_OR_dma_comp)
- break;
-
- ecc_done_OR_dma_comp = 1;
- }
- } else {
- while (!(ioread32(FlashReg + intr_status) &
- INTR_STATUS0__DMA_CMD_COMP))
- ;
- iowrite32(INTR_STATUS0__DMA_CMD_COMP,
- FlashReg + intr_status);
- break;
- }
-
- iowrite32((~INTR_STATUS0__ECC_ERR) &
- (~INTR_STATUS0__ECC_TRANSACTION_DONE) &
- (~INTR_STATUS0__DMA_CMD_COMP),
- FlashReg + intr_status);
-
- }
-
- iowrite32(ioread32(FlashReg + intr_status),
- FlashReg + intr_status);
-
- iowrite32(0, FlashReg + DMA_ENABLE);
-
- while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- iowrite32(0, FlashReg + MULTIPLANE_OPERATION);
- }
-
- return status;
-}
-
-u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block,
- u16 page, u16 page_count)
-{
- u32 status = PASS;
- u32 NumPages = page_count;
- u64 flash_add;
- u32 flash_bank;
- u32 intr_status = 0;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- int ret;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
-
- if (page_count < 2)
- status = FAIL;
-
- if (status != PASS)
- return status;
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- *DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- intr_status = intr_status_addresses[flash_bank];
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- iowrite32(1, FlashReg + DMA_ENABLE);
- while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
-
- /* Fill the mrst_nand_info structure */
- info.state = INT_PIPELINE_READ_AHEAD;
- info.read_data = read_data;
- info.flash_bank = flash_bank;
- info.block = block;
- info.page = page;
- info.ret = PASS;
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
-
- ddma_trans(read_data, flash_add, flash_bank, 0, NumPages);
-
- iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */
-
- ret = wait_for_completion_timeout(&info.complete, 10 * HZ);
- if (!ret) {
- printk(KERN_ERR "Wait for completion timeout "
- "in %s, Line %d\n", __FILE__, __LINE__);
- status = ERR;
- } else {
- status = info.ret;
- }
-
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- iowrite32(0, FlashReg + DMA_ENABLE);
-
- while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- return status;
-}
-
-
-u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page,
- u16 page_count)
-{
- u32 status = PASS;
- u64 flash_add;
- u32 intr_status = 0;
- u32 flash_bank;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- int ret;
- u8 *write_data_l;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
- if (status != PASS)
- return status;
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- * DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- intr_status = intr_status_addresses[flash_bank];
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
-
- iowrite32(INTR_STATUS0__PROGRAM_COMP |
- INTR_STATUS0__PROGRAM_FAIL, FlashReg + intr_status);
-
- if (page_count > 1) {
- write_data_l = write_data;
- while (page_count > MAX_PAGES_PER_RW) {
- if (ioread32(FlashReg + MULTIPLANE_OPERATION))
- status = NAND_Multiplane_Write(write_data_l,
- block, page, MAX_PAGES_PER_RW);
- else
- status = NAND_Pipeline_Write_Ahead(
- write_data_l, block, page,
- MAX_PAGES_PER_RW);
- if (status == FAIL)
- return status;
-
- write_data_l += DeviceInfo.wPageDataSize *
- MAX_PAGES_PER_RW;
- page_count -= MAX_PAGES_PER_RW;
- page += MAX_PAGES_PER_RW;
- }
- if (ioread32(FlashReg + MULTIPLANE_OPERATION))
- status = NAND_Multiplane_Write(write_data_l,
- block, page, page_count);
- else
- status = NAND_Pipeline_Write_Ahead(write_data_l,
- block, page, page_count);
-
- return status;
- }
-
- iowrite32(1, FlashReg + DMA_ENABLE);
- while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
-
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- /* Fill the mrst_nand_info structure */
- info.state = INT_WRITE_PAGE_MAIN;
- info.write_data = write_data;
- info.flash_bank = flash_bank;
- info.block = block;
- info.page = page;
- info.ret = PASS;
-
- ddma_trans(write_data, flash_add, flash_bank, 1, 1);
-
- iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */
-
- ret = wait_for_completion_timeout(&info.complete, 10 * HZ);
- if (!ret) {
- printk(KERN_ERR "Wait for completion timeout "
- "in %s, Line %d\n", __FILE__, __LINE__);
- status = ERR;
- } else {
- status = info.ret;
- }
-
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- iowrite32(0, FlashReg + DMA_ENABLE);
- while (ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)
- ;
-
- return status;
-}
-
-void NAND_ECC_Ctrl(int enable)
-{
- if (enable) {
- nand_dbg_print(NAND_DBG_WARN,
- "Will enable ECC in %s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
- iowrite32(1, FlashReg + ECC_ENABLE);
- enable_ecc = 1;
- } else {
- nand_dbg_print(NAND_DBG_WARN,
- "Will disable ECC in %s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
- iowrite32(0, FlashReg + ECC_ENABLE);
- enable_ecc = 0;
- }
-}
-
-u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block,
- u16 page, u16 page_count)
-{
- u32 status = PASS;
- u32 i, j, page_num = 0;
- u32 PageSize = DeviceInfo.wPageSize;
- u32 PageDataSize = DeviceInfo.wPageDataSize;
- u32 eccBytes = DeviceInfo.wECCBytesPerSector;
- u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
- u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes;
- u64 flash_add;
- u32 eccSectorSize;
- u32 flash_bank;
- u32 intr_status = 0;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- u8 *page_main_spare = buf_write_page_main_spare;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- if (status == PASS) {
- intr_status = intr_status_addresses[flash_bank];
-
- iowrite32(1, FlashReg + TRANSFER_SPARE_REG);
-
- while ((status != FAIL) && (page_count > 0)) {
- flash_add = (u64)(block %
- (DeviceInfo.wTotalBlocks / totalUsedBanks)) *
- DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
-
- iowrite32(ioread32(FlashReg + intr_status),
- FlashReg + intr_status);
-
- iowrite32((u32)(MODE_01 | (flash_bank << 24) |
- (flash_add >>
- DeviceInfo.nBitsInPageDataSize)),
- FlashMem);
-
- if (enable_ecc) {
- for (j = 0;
- j <
- DeviceInfo.wPageDataSize / eccSectorSize;
- j++) {
- for (i = 0; i < eccSectorSize; i++)
- page_main_spare[(eccSectorSize +
- eccBytes) * j +
- i] =
- write_data[eccSectorSize *
- j + i];
-
- for (i = 0; i < eccBytes; i++)
- page_main_spare[(eccSectorSize +
- eccBytes) * j +
- eccSectorSize +
- i] =
- write_data[PageDataSize +
- spareFlagBytes +
- eccBytes * j +
- i];
- }
-
- for (i = 0; i < spareFlagBytes; i++)
- page_main_spare[(eccSectorSize +
- eccBytes) * j + i] =
- write_data[PageDataSize + i];
-
- for (i = PageSize - 1; i >= PageDataSize +
- spareSkipBytes; i--)
- page_main_spare[i] = page_main_spare[i -
- spareSkipBytes];
-
- for (i = PageDataSize; i < PageDataSize +
- spareSkipBytes; i++)
- page_main_spare[i] = 0xff;
-
- for (i = 0; i < PageSize / 4; i++)
- iowrite32(
- *((u32 *)page_main_spare + i),
- FlashMem + 0x10);
- } else {
-
- for (i = 0; i < PageSize / 4; i++)
- iowrite32(*((u32 *)write_data + i),
- FlashMem + 0x10);
- }
-
- while (!(ioread32(FlashReg + intr_status) &
- (INTR_STATUS0__PROGRAM_COMP |
- INTR_STATUS0__PROGRAM_FAIL)))
- ;
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__PROGRAM_FAIL)
- status = FAIL;
-
- iowrite32(ioread32(FlashReg + intr_status),
- FlashReg + intr_status);
-
- page_num++;
- page_count--;
- write_data += PageSize;
- }
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
- }
-
- return status;
-}
-
-u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page,
- u16 page_count)
-{
- u32 status = PASS;
- u32 i, j;
- u64 flash_add = 0;
- u32 PageSize = DeviceInfo.wPageSize;
- u32 PageDataSize = DeviceInfo.wPageDataSize;
- u32 PageSpareSize = DeviceInfo.wPageSpareSize;
- u32 eccBytes = DeviceInfo.wECCBytesPerSector;
- u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
- u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes;
- u32 eccSectorSize;
- u32 flash_bank;
- u32 intr_status = 0;
- u8 *read_data_l = read_data;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- u8 *page_main_spare = buf_read_page_main_spare;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- if (status == PASS) {
- intr_status = intr_status_addresses[flash_bank];
-
- iowrite32(1, FlashReg + TRANSFER_SPARE_REG);
-
- iowrite32(ioread32(FlashReg + intr_status),
- FlashReg + intr_status);
-
- while ((status != FAIL) && (page_count > 0)) {
- flash_add = (u64)(block %
- (DeviceInfo.wTotalBlocks / totalUsedBanks))
- * DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)),
- 0x43);
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)),
- 0x2000 | page_count);
-
- while (!(ioread32(FlashReg + intr_status) &
- INTR_STATUS0__LOAD_COMP))
- ;
-
- iowrite32((u32)(MODE_01 | (flash_bank << 24) |
- (flash_add >>
- DeviceInfo.nBitsInPageDataSize)),
- FlashMem);
-
- for (i = 0; i < PageSize / 4; i++)
- *(((u32 *)page_main_spare) + i) =
- ioread32(FlashMem + 0x10);
-
- if (enable_ecc) {
- for (i = PageDataSize; i < PageSize -
- spareSkipBytes; i++)
- page_main_spare[i] = page_main_spare[i +
- spareSkipBytes];
-
- for (j = 0;
- j < DeviceInfo.wPageDataSize / eccSectorSize;
- j++) {
-
- for (i = 0; i < eccSectorSize; i++)
- read_data_l[eccSectorSize * j +
- i] =
- page_main_spare[
- (eccSectorSize +
- eccBytes) * j + i];
-
- for (i = 0; i < eccBytes; i++)
- read_data_l[PageDataSize +
- spareFlagBytes +
- eccBytes * j + i] =
- page_main_spare[
- (eccSectorSize +
- eccBytes) * j +
- eccSectorSize + i];
- }
-
- for (i = 0; i < spareFlagBytes; i++)
- read_data_l[PageDataSize + i] =
- page_main_spare[(eccSectorSize +
- eccBytes) * j + i];
- } else {
- for (i = 0; i < (PageDataSize + PageSpareSize);
- i++)
- read_data_l[i] = page_main_spare[i];
-
- }
-
- if (enable_ecc) {
- while (!(ioread32(FlashReg + intr_status) &
- (INTR_STATUS0__ECC_TRANSACTION_DONE |
- INTR_STATUS0__ECC_ERR)))
- ;
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_ERR) {
- iowrite32(INTR_STATUS0__ECC_ERR,
- FlashReg + intr_status);
- status = do_ecc_new(flash_bank,
- read_data, block, page);
- }
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_TRANSACTION_DONE &
- INTR_STATUS0__ECC_ERR) {
- iowrite32(INTR_STATUS0__ECC_ERR |
- INTR_STATUS0__ECC_TRANSACTION_DONE,
- FlashReg + intr_status);
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_TRANSACTION_DONE) {
- iowrite32(
- INTR_STATUS0__ECC_TRANSACTION_DONE,
- FlashReg + intr_status);
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_ERR) {
- iowrite32(INTR_STATUS0__ECC_ERR,
- FlashReg + intr_status);
- }
- }
-
- page++;
- page_count--;
- read_data_l += PageSize;
- }
- }
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
-
- return status;
-}
-
-u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block,
- u16 page, u16 page_count)
-{
- u16 status = PASS;
- u32 NumPages = page_count;
- u64 flash_add;
- u32 flash_bank;
- u32 intr_status = 0;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- int ret;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
-
- if (page_count < 2)
- status = FAIL;
-
- if (status != PASS)
- return status;
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- * DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- intr_status = intr_status_addresses[flash_bank];
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- iowrite32(1, FlashReg + DMA_ENABLE);
- while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
-
- /* Fill the mrst_nand_info structure */
- info.state = INT_PIPELINE_WRITE_AHEAD;
- info.write_data = write_data;
- info.flash_bank = flash_bank;
- info.block = block;
- info.page = page;
- info.ret = PASS;
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
-
- ddma_trans(write_data, flash_add, flash_bank, 1, NumPages);
-
- iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */
-
- ret = wait_for_completion_timeout(&info.complete, 10 * HZ);
- if (!ret) {
- printk(KERN_ERR "Wait for completion timeout "
- "in %s, Line %d\n", __FILE__, __LINE__);
- status = ERR;
- } else {
- status = info.ret;
- }
-
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- iowrite32(0, FlashReg + DMA_ENABLE);
- while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- return status;
-}
-
-/* Un-tested function */
-u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page,
- u16 page_count)
-{
- u16 status = PASS;
- u32 NumPages = page_count;
- u64 flash_add;
- u32 flash_bank;
- u32 intr_status = 0;
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- u16 status2 = PASS;
- u32 t;
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- status = Boundary_Check_Block_Page(block, page, page_count);
- if (status != PASS)
- return status;
-
- flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
- * DeviceInfo.wBlockDataSize +
- (u64)page * DeviceInfo.wPageDataSize;
-
- flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
-
- intr_status = intr_status_addresses[flash_bank];
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
- iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION);
-
- iowrite32(1, FlashReg + DMA_ENABLE);
- while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
-
- index_addr((u32)(MODE_10 | (flash_bank << 24) |
- (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
-
- ddma_trans(write_data, flash_add, flash_bank, 1, NumPages);
-
- while (1) {
- while (!ioread32(FlashReg + intr_status))
- ;
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__DMA_CMD_COMP) {
- iowrite32(INTR_STATUS0__DMA_CMD_COMP,
- FlashReg + intr_status);
- status = PASS;
- if (status2 == FAIL)
- status = FAIL;
- break;
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__PROGRAM_FAIL) {
- status2 = FAIL;
- status = FAIL;
- t = ioread32(FlashReg + intr_status) &
- INTR_STATUS0__PROGRAM_FAIL;
- iowrite32(t, FlashReg + intr_status);
- } else {
- iowrite32((~INTR_STATUS0__PROGRAM_FAIL) &
- (~INTR_STATUS0__DMA_CMD_COMP),
- FlashReg + intr_status);
- }
- }
-
- iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
-
- iowrite32(0, FlashReg + DMA_ENABLE);
-
- while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
- ;
-
- iowrite32(0, FlashReg + MULTIPLANE_OPERATION);
-
- return status;
-}
-
-
-#if CMD_DMA
-static irqreturn_t cdma_isr(int irq, void *dev_id)
-{
- struct mrst_nand_info *dev = dev_id;
- int first_failed_cmd;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- if (!is_cdma_interrupt())
- return IRQ_NONE;
-
- /* Disable controller interrupts */
- iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
- GLOB_FTL_Event_Status(&first_failed_cmd);
- complete(&dev->complete);
-
- return IRQ_HANDLED;
-}
-#else
-static void handle_nand_int_read(struct mrst_nand_info *dev)
-{
- u32 intr_status_addresses[4] = {INTR_STATUS0,
- INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
- u32 intr_status;
- u32 ecc_done_OR_dma_comp = 0;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- dev->ret = PASS;
- intr_status = intr_status_addresses[dev->flash_bank];
-
- while (1) {
- if (enable_ecc) {
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_ERR) {
- iowrite32(INTR_STATUS0__ECC_ERR,
- FlashReg + intr_status);
- dev->ret = do_ecc_new(dev->flash_bank,
- dev->read_data,
- dev->block, dev->page);
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__DMA_CMD_COMP) {
- iowrite32(INTR_STATUS0__DMA_CMD_COMP,
- FlashReg + intr_status);
- if (1 == ecc_done_OR_dma_comp)
- break;
- ecc_done_OR_dma_comp = 1;
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__ECC_TRANSACTION_DONE) {
- iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE,
- FlashReg + intr_status);
- if (1 == ecc_done_OR_dma_comp)
- break;
- ecc_done_OR_dma_comp = 1;
- }
- } else {
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__DMA_CMD_COMP) {
- iowrite32(INTR_STATUS0__DMA_CMD_COMP,
- FlashReg + intr_status);
- break;
- } else {
- printk(KERN_ERR "Illegal INTS "
- "(offset addr 0x%x) value: 0x%x\n",
- intr_status,
- ioread32(FlashReg + intr_status));
- }
- }
-
- iowrite32((~INTR_STATUS0__ECC_ERR) &
- (~INTR_STATUS0__ECC_TRANSACTION_DONE) &
- (~INTR_STATUS0__DMA_CMD_COMP),
- FlashReg + intr_status);
- }
-}
-
-static void handle_nand_int_write(struct mrst_nand_info *dev)
-{
- u32 intr_status;
- u32 intr[4] = {INTR_STATUS0, INTR_STATUS1,
- INTR_STATUS2, INTR_STATUS3};
- int status = PASS;
-
- nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- dev->ret = PASS;
- intr_status = intr[dev->flash_bank];
-
- while (1) {
- while (!ioread32(FlashReg + intr_status))
- ;
-
- if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__DMA_CMD_COMP) {
- iowrite32(INTR_STATUS0__DMA_CMD_COMP,
- FlashReg + intr_status);
- if (FAIL == status)
- dev->ret = FAIL;
- break;
- } else if (ioread32(FlashReg + intr_status) &
- INTR_STATUS0__PROGRAM_FAIL) {
- status = FAIL;
- iowrite32(INTR_STATUS0__PROGRAM_FAIL,
- FlashReg + intr_status);
- } else {
- iowrite32((~INTR_STATUS0__PROGRAM_FAIL) &
- (~INTR_STATUS0__DMA_CMD_COMP),
- FlashReg + intr_status);
- }
- }
-}
-
-static irqreturn_t ddma_isr(int irq, void *dev_id)
-{
- struct mrst_nand_info *dev = dev_id;
- u32 int_mask, ints0, ints1, ints2, ints3, ints_offset;
- u32 intr[4] = {INTR_STATUS0, INTR_STATUS1,
- INTR_STATUS2, INTR_STATUS3};
-
- int_mask = INTR_STATUS0__DMA_CMD_COMP |
- INTR_STATUS0__ECC_TRANSACTION_DONE |
- INTR_STATUS0__ECC_ERR |
- INTR_STATUS0__PROGRAM_FAIL |
- INTR_STATUS0__ERASE_FAIL;
-
- ints0 = ioread32(FlashReg + INTR_STATUS0);
- ints1 = ioread32(FlashReg + INTR_STATUS1);
- ints2 = ioread32(FlashReg + INTR_STATUS2);
- ints3 = ioread32(FlashReg + INTR_STATUS3);
-
- ints_offset = intr[dev->flash_bank];
-
- nand_dbg_print(NAND_DBG_DEBUG,
- "INTR0: 0x%x, INTR1: 0x%x, INTR2: 0x%x, INTR3: 0x%x, "
- "DMA_INTR: 0x%x, "
- "dev->state: 0x%x, dev->flash_bank: %d\n",
- ints0, ints1, ints2, ints3,
- ioread32(FlashReg + DMA_INTR),
- dev->state, dev->flash_bank);
-
- if (!(ioread32(FlashReg + ints_offset) & int_mask)) {
- iowrite32(ints0, FlashReg + INTR_STATUS0);
- iowrite32(ints1, FlashReg + INTR_STATUS1);
- iowrite32(ints2, FlashReg + INTR_STATUS2);
- iowrite32(ints3, FlashReg + INTR_STATUS3);
- nand_dbg_print(NAND_DBG_WARN,
- "ddma_isr: Invalid interrupt for NAND controller. "
- "Ignore it\n");
- return IRQ_NONE;
- }
-
- switch (dev->state) {
- case INT_READ_PAGE_MAIN:
- case INT_PIPELINE_READ_AHEAD:
- /* Disable controller interrupts */
- iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
- handle_nand_int_read(dev);
- break;
- case INT_WRITE_PAGE_MAIN:
- case INT_PIPELINE_WRITE_AHEAD:
- iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
- handle_nand_int_write(dev);
- break;
- default:
- printk(KERN_ERR "ddma_isr - Illegal state: 0x%x\n",
- dev->state);
- return IRQ_NONE;
- }
-
- dev->state = INT_IDLE_STATE;
- complete(&dev->complete);
- return IRQ_HANDLED;
-}
-#endif
-
-static const struct pci_device_id nand_pci_ids[] = {
- {
- .vendor = 0x8086,
- .device = 0x0809,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- { /* end: all zeroes */ }
-};
-
-static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
- int ret = -ENODEV;
- unsigned long csr_base;
- unsigned long csr_len;
- struct mrst_nand_info *pndev = &info;
- u32 int_mask;
-
- ret = pci_enable_device(dev);
- if (ret) {
- printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
- return ret;
- }
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- FlashReg = ioremap_nocache(GLOB_HWCTL_REG_BASE,
- GLOB_HWCTL_REG_SIZE);
- if (!FlashReg) {
- printk(KERN_ERR "Spectra: ioremap_nocache failed!");
- goto failed_disable;
- }
- nand_dbg_print(NAND_DBG_WARN,
- "Spectra: Remapped reg base address: "
- "0x%p, len: %d\n",
- FlashReg, GLOB_HWCTL_REG_SIZE);
-
- FlashMem = ioremap_nocache(GLOB_HWCTL_MEM_BASE,
- GLOB_HWCTL_MEM_SIZE);
- if (!FlashMem) {
- printk(KERN_ERR "Spectra: ioremap_nocache failed!");
- iounmap(FlashReg);
- goto failed_disable;
- }
- nand_dbg_print(NAND_DBG_WARN,
- "Spectra: Remapped flash base address: "
- "0x%p, len: %d\n",
- (void *)FlashMem, GLOB_HWCTL_MEM_SIZE);
-
- nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:"
- "acc_clks: %d, re_2_we: %d, we_2_re: %d,"
- "addr_2_data: %d, rdwr_en_lo_cnt: %d, "
- "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
- ioread32(FlashReg + ACC_CLKS),
- ioread32(FlashReg + RE_2_WE),
- ioread32(FlashReg + WE_2_RE),
- ioread32(FlashReg + ADDR_2_DATA),
- ioread32(FlashReg + RDWR_EN_LO_CNT),
- ioread32(FlashReg + RDWR_EN_HI_CNT),
- ioread32(FlashReg + CS_SETUP_CNT));
-
- NAND_Flash_Reset();
-
- iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
-
-#if CMD_DMA
- info.pcmds_num = 0;
- info.flash_bank = 0;
- info.cdma_num = 0;
- int_mask = (DMA_INTR__DESC_COMP_CHANNEL0 |
- DMA_INTR__DESC_COMP_CHANNEL1 |
- DMA_INTR__DESC_COMP_CHANNEL2 |
- DMA_INTR__DESC_COMP_CHANNEL3 |
- DMA_INTR__MEMCOPY_DESC_COMP);
- iowrite32(int_mask, FlashReg + DMA_INTR_EN);
- iowrite32(0xFFFF, FlashReg + DMA_INTR);
-
- int_mask = (INTR_STATUS0__ECC_ERR |
- INTR_STATUS0__PROGRAM_FAIL |
- INTR_STATUS0__ERASE_FAIL);
-#else
- int_mask = INTR_STATUS0__DMA_CMD_COMP |
- INTR_STATUS0__ECC_TRANSACTION_DONE |
- INTR_STATUS0__ECC_ERR |
- INTR_STATUS0__PROGRAM_FAIL |
- INTR_STATUS0__ERASE_FAIL;
-#endif
- iowrite32(int_mask, FlashReg + INTR_EN0);
- iowrite32(int_mask, FlashReg + INTR_EN1);
- iowrite32(int_mask, FlashReg + INTR_EN2);
- iowrite32(int_mask, FlashReg + INTR_EN3);
-
- /* Clear all status bits */
- iowrite32(0xFFFF, FlashReg + INTR_STATUS0);
- iowrite32(0xFFFF, FlashReg + INTR_STATUS1);
- iowrite32(0xFFFF, FlashReg + INTR_STATUS2);
- iowrite32(0xFFFF, FlashReg + INTR_STATUS3);
-
- iowrite32(0x0F, FlashReg + RB_PIN_ENABLED);
- iowrite32(CHIP_EN_DONT_CARE__FLAG, FlashReg + CHIP_ENABLE_DONT_CARE);
-
- /* Should set value for these registers when init */
- iowrite32(0, FlashReg + TWO_ROW_ADDR_CYCLES);
- iowrite32(1, FlashReg + ECC_ENABLE);
- enable_ecc = 1;
-
- pci_set_master(dev);
- pndev->dev = dev;
-
- csr_base = pci_resource_start(dev, 0);
- if (!csr_base) {
- printk(KERN_ERR "Spectra: pci_resource_start failed!\n");
- ret = -ENODEV;
- goto failed_req_csr;
- }
-
- csr_len = pci_resource_len(dev, 0);
- if (!csr_len) {
- printk(KERN_ERR "Spectra: pci_resource_len failed!\n");
- ret = -ENODEV;
- goto failed_req_csr;
- }
-
- ret = pci_request_regions(dev, SPECTRA_NAND_NAME);
- if (ret) {
- printk(KERN_ERR "Spectra: Unable to request "
- "memory region\n");
- goto failed_req_csr;
- }
-
- pndev->ioaddr = ioremap_nocache(csr_base, csr_len);
- if (!pndev->ioaddr) {
- printk(KERN_ERR "Spectra: Unable to remap memory region\n");
- ret = -ENOMEM;
- goto failed_remap_csr;
- }
- nand_dbg_print(NAND_DBG_DEBUG, "Spectra: CSR 0x%08lx -> 0x%p (0x%lx)\n",
- csr_base, pndev->ioaddr, csr_len);
-
- init_completion(&pndev->complete);
- nand_dbg_print(NAND_DBG_DEBUG, "Spectra: IRQ %d\n", dev->irq);
-
-#if CMD_DMA
- if (request_irq(dev->irq, cdma_isr, IRQF_SHARED,
- SPECTRA_NAND_NAME, &info)) {
- printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
- ret = -ENODEV;
- iounmap(pndev->ioaddr);
- goto failed_remap_csr;
- }
-#else
- if (request_irq(dev->irq, ddma_isr, IRQF_SHARED,
- SPECTRA_NAND_NAME, &info)) {
- printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
- ret = -ENODEV;
- iounmap(pndev->ioaddr);
- goto failed_remap_csr;
- }
-#endif
-
- pci_set_drvdata(dev, pndev);
-
- ret = GLOB_LLD_Read_Device_ID();
- if (ret) {
- iounmap(pndev->ioaddr);
- goto failed_remap_csr;
- }
-
- ret = register_spectra_ftl();
- if (ret) {
- iounmap(pndev->ioaddr);
- goto failed_remap_csr;
- }
-
- return 0;
-
-failed_remap_csr:
- pci_release_regions(dev);
-failed_req_csr:
- iounmap(FlashMem);
- iounmap(FlashReg);
-failed_disable:
- pci_disable_device(dev);
-
- return ret;
-}
-
-static void nand_pci_remove(struct pci_dev *dev)
-{
- struct mrst_nand_info *pndev = pci_get_drvdata(dev);
-
- nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
-#if CMD_DMA
- free_irq(dev->irq, pndev);
-#endif
- iounmap(pndev->ioaddr);
- pci_release_regions(dev);
- pci_disable_device(dev);
-}
-
-MODULE_DEVICE_TABLE(pci, nand_pci_ids);
-
-static struct pci_driver nand_pci_driver = {
- .name = SPECTRA_NAND_NAME,
- .id_table = nand_pci_ids,
- .probe = nand_pci_probe,
- .remove = nand_pci_remove,
-};
-
-int NAND_Flash_Init(void)
-{
- int retval;
-
- nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
- __FILE__, __LINE__, __func__);
-
- retval = pci_register_driver(&nand_pci_driver);
- if (retval)
- return -ENOMEM;
-
- return PASS;
-}
-
-/* Free memory */
-int nand_release_spectra(void)
-{
- pci_unregister_driver(&nand_pci_driver);
- iounmap(FlashMem);
- iounmap(FlashReg);
-
- return 0;
-}
-
-
-
diff --git a/drivers/staging/spectra/lld_nand.h b/drivers/staging/spectra/lld_nand.h
deleted file mode 100644
index d08388287da8..000000000000
--- a/drivers/staging/spectra/lld_nand.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef _LLD_NAND_
-#define _LLD_NAND_
-
-#ifdef ELDORA
-#include "defs.h"
-#else
-#include "flash.h"
-#include "ffsport.h"
-#endif
-
-#define MODE_00 0x00000000
-#define MODE_01 0x04000000
-#define MODE_10 0x08000000
-#define MODE_11 0x0C000000
-
-
-#define DATA_TRANSFER_MODE 0
-#define PROTECTION_PER_BLOCK 1
-#define LOAD_WAIT_COUNT 2
-#define PROGRAM_WAIT_COUNT 3
-#define ERASE_WAIT_COUNT 4
-#define INT_MONITOR_CYCLE_COUNT 5
-#define READ_BUSY_PIN_ENABLED 6
-#define MULTIPLANE_OPERATION_SUPPORT 7
-#define PRE_FETCH_MODE 8
-#define CE_DONT_CARE_SUPPORT 9
-#define COPYBACK_SUPPORT 10
-#define CACHE_WRITE_SUPPORT 11
-#define CACHE_READ_SUPPORT 12
-#define NUM_PAGES_IN_BLOCK 13
-#define ECC_ENABLE_SELECT 14
-#define WRITE_ENABLE_2_READ_ENABLE 15
-#define ADDRESS_2_DATA 16
-#define READ_ENABLE_2_WRITE_ENABLE 17
-#define TWO_ROW_ADDRESS_CYCLES 18
-#define MULTIPLANE_ADDRESS_RESTRICT 19
-#define ACC_CLOCKS 20
-#define READ_WRITE_ENABLE_LOW_COUNT 21
-#define READ_WRITE_ENABLE_HIGH_COUNT 22
-
-#define ECC_SECTOR_SIZE 512
-#define LLD_MAX_FLASH_BANKS 4
-
-struct mrst_nand_info {
- struct pci_dev *dev;
- u32 state;
- u32 flash_bank;
- u8 *read_data;
- u8 *write_data;
- u32 block;
- u16 page;
- u32 use_dma;
- void __iomem *ioaddr; /* Mapped io reg base address */
- int ret;
- u32 pcmds_num;
- struct pending_cmd *pcmds;
- int cdma_num; /* CDMA descriptor number in this chan */
- u8 *cdma_desc_buf; /* CDMA descriptor table */
- u8 *memcp_desc_buf; /* Memory copy descriptor table */
- dma_addr_t cdma_desc; /* Mapped CDMA descriptor table */
- dma_addr_t memcp_desc; /* Mapped memory copy descriptor table */
- struct completion complete;
-};
-
-int NAND_Flash_Init(void);
-int nand_release_spectra(void);
-u16 NAND_Flash_Reset(void);
-u16 NAND_Read_Device_ID(void);
-u16 NAND_Erase_Block(u32 flash_add);
-u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page,
- u16 page_count);
-u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page,
- u16 page_count);
-u16 NAND_UnlockArrayAll(void);
-u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block,
- u16 page, u16 page_count);
-u16 NAND_Write_Page_Spare(u8 *read_data, u32 block, u16 page,
- u16 page_count);
-u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page,
- u16 page_count);
-u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page,
- u16 page_count);
-void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE);
-u16 NAND_Get_Bad_Block(u32 block);
-u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, u16 page,
- u16 page_count);
-u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block,
- u16 page, u16 page_count);
-u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page,
- u16 page_count);
-u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page,
- u16 page_count);
-void NAND_ECC_Ctrl(int enable);
-u16 NAND_Read_Page_Main_Polling(u8 *read_data,
- u32 block, u16 page, u16 page_count);
-u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data,
- u32 block, u16 page, u16 page_count);
-void Conv_Spare_Data_Log2Phy_Format(u8 *data);
-void Conv_Spare_Data_Phy2Log_Format(u8 *data);
-void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count);
-void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count);
-
-extern void __iomem *FlashReg;
-extern void __iomem *FlashMem;
-
-extern int totalUsedBanks;
-extern u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS];
-
-#endif /*_LLD_NAND_*/
-
-
-
diff --git a/drivers/staging/spectra/nand_regs.h b/drivers/staging/spectra/nand_regs.h
deleted file mode 100644
index e192e4ae8c1e..000000000000
--- a/drivers/staging/spectra/nand_regs.h
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#define DEVICE_RESET 0x0
-#define DEVICE_RESET__BANK0 0x0001
-#define DEVICE_RESET__BANK1 0x0002
-#define DEVICE_RESET__BANK2 0x0004
-#define DEVICE_RESET__BANK3 0x0008
-
-#define TRANSFER_SPARE_REG 0x10
-#define TRANSFER_SPARE_REG__FLAG 0x0001
-
-#define LOAD_WAIT_CNT 0x20
-#define LOAD_WAIT_CNT__VALUE 0xffff
-
-#define PROGRAM_WAIT_CNT 0x30
-#define PROGRAM_WAIT_CNT__VALUE 0xffff
-
-#define ERASE_WAIT_CNT 0x40
-#define ERASE_WAIT_CNT__VALUE 0xffff
-
-#define INT_MON_CYCCNT 0x50
-#define INT_MON_CYCCNT__VALUE 0xffff
-
-#define RB_PIN_ENABLED 0x60
-#define RB_PIN_ENABLED__BANK0 0x0001
-#define RB_PIN_ENABLED__BANK1 0x0002
-#define RB_PIN_ENABLED__BANK2 0x0004
-#define RB_PIN_ENABLED__BANK3 0x0008
-
-#define MULTIPLANE_OPERATION 0x70
-#define MULTIPLANE_OPERATION__FLAG 0x0001
-
-#define MULTIPLANE_READ_ENABLE 0x80
-#define MULTIPLANE_READ_ENABLE__FLAG 0x0001
-
-#define COPYBACK_DISABLE 0x90
-#define COPYBACK_DISABLE__FLAG 0x0001
-
-#define CACHE_WRITE_ENABLE 0xa0
-#define CACHE_WRITE_ENABLE__FLAG 0x0001
-
-#define CACHE_READ_ENABLE 0xb0
-#define CACHE_READ_ENABLE__FLAG 0x0001
-
-#define PREFETCH_MODE 0xc0
-#define PREFETCH_MODE__PREFETCH_EN 0x0001
-#define PREFETCH_MODE__PREFETCH_BURST_LENGTH 0xfff0
-
-#define CHIP_ENABLE_DONT_CARE 0xd0
-#define CHIP_EN_DONT_CARE__FLAG 0x01
-
-#define ECC_ENABLE 0xe0
-#define ECC_ENABLE__FLAG 0x0001
-
-#define GLOBAL_INT_ENABLE 0xf0
-#define GLOBAL_INT_EN_FLAG 0x01
-
-#define WE_2_RE 0x100
-#define WE_2_RE__VALUE 0x003f
-
-#define ADDR_2_DATA 0x110
-#define ADDR_2_DATA__VALUE 0x003f
-
-#define RE_2_WE 0x120
-#define RE_2_WE__VALUE 0x003f
-
-#define ACC_CLKS 0x130
-#define ACC_CLKS__VALUE 0x000f
-
-#define NUMBER_OF_PLANES 0x140
-#define NUMBER_OF_PLANES__VALUE 0x0007
-
-#define PAGES_PER_BLOCK 0x150
-#define PAGES_PER_BLOCK__VALUE 0xffff
-
-#define DEVICE_WIDTH 0x160
-#define DEVICE_WIDTH__VALUE 0x0003
-
-#define DEVICE_MAIN_AREA_SIZE 0x170
-#define DEVICE_MAIN_AREA_SIZE__VALUE 0xffff
-
-#define DEVICE_SPARE_AREA_SIZE 0x180
-#define DEVICE_SPARE_AREA_SIZE__VALUE 0xffff
-
-#define TWO_ROW_ADDR_CYCLES 0x190
-#define TWO_ROW_ADDR_CYCLES__FLAG 0x0001
-
-#define MULTIPLANE_ADDR_RESTRICT 0x1a0
-#define MULTIPLANE_ADDR_RESTRICT__FLAG 0x0001
-
-#define ECC_CORRECTION 0x1b0
-#define ECC_CORRECTION__VALUE 0x001f
-
-#define READ_MODE 0x1c0
-#define READ_MODE__VALUE 0x000f
-
-#define WRITE_MODE 0x1d0
-#define WRITE_MODE__VALUE 0x000f
-
-#define COPYBACK_MODE 0x1e0
-#define COPYBACK_MODE__VALUE 0x000f
-
-#define RDWR_EN_LO_CNT 0x1f0
-#define RDWR_EN_LO_CNT__VALUE 0x001f
-
-#define RDWR_EN_HI_CNT 0x200
-#define RDWR_EN_HI_CNT__VALUE 0x001f
-
-#define MAX_RD_DELAY 0x210
-#define MAX_RD_DELAY__VALUE 0x000f
-
-#define CS_SETUP_CNT 0x220
-#define CS_SETUP_CNT__VALUE 0x001f
-
-#define SPARE_AREA_SKIP_BYTES 0x230
-#define SPARE_AREA_SKIP_BYTES__VALUE 0x003f
-
-#define SPARE_AREA_MARKER 0x240
-#define SPARE_AREA_MARKER__VALUE 0xffff
-
-#define DEVICES_CONNECTED 0x250
-#define DEVICES_CONNECTED__VALUE 0x0007
-
-#define DIE_MASK 0x260
-#define DIE_MASK__VALUE 0x00ff
-
-#define FIRST_BLOCK_OF_NEXT_PLANE 0x270
-#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE 0xffff
-
-#define WRITE_PROTECT 0x280
-#define WRITE_PROTECT__FLAG 0x0001
-
-#define RE_2_RE 0x290
-#define RE_2_RE__VALUE 0x003f
-
-#define MANUFACTURER_ID 0x300
-#define MANUFACTURER_ID__VALUE 0x00ff
-
-#define DEVICE_ID 0x310
-#define DEVICE_ID__VALUE 0x00ff
-
-#define DEVICE_PARAM_0 0x320
-#define DEVICE_PARAM_0__VALUE 0x00ff
-
-#define DEVICE_PARAM_1 0x330
-#define DEVICE_PARAM_1__VALUE 0x00ff
-
-#define DEVICE_PARAM_2 0x340
-#define DEVICE_PARAM_2__VALUE 0x00ff
-
-#define LOGICAL_PAGE_DATA_SIZE 0x350
-#define LOGICAL_PAGE_DATA_SIZE__VALUE 0xffff
-
-#define LOGICAL_PAGE_SPARE_SIZE 0x360
-#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff
-
-#define REVISION 0x370
-#define REVISION__VALUE 0xffff
-
-#define ONFI_DEVICE_FEATURES 0x380
-#define ONFI_DEVICE_FEATURES__VALUE 0x003f
-
-#define ONFI_OPTIONAL_COMMANDS 0x390
-#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f
-
-#define ONFI_TIMING_MODE 0x3a0
-#define ONFI_TIMING_MODE__VALUE 0x003f
-
-#define ONFI_PGM_CACHE_TIMING_MODE 0x3b0
-#define ONFI_PGM_CACHE_TIMING_MODE__VALUE 0x003f
-
-#define ONFI_DEVICE_NO_OF_LUNS 0x3c0
-#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS 0x00ff
-#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE 0x0100
-
-#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L 0x3d0
-#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE 0xffff
-
-#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U 0x3e0
-#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE 0xffff
-
-#define FEATURES 0x3f0
-#define FEATURES__N_BANKS 0x0003
-#define FEATURES__ECC_MAX_ERR 0x003c
-#define FEATURES__DMA 0x0040
-#define FEATURES__CMD_DMA 0x0080
-#define FEATURES__PARTITION 0x0100
-#define FEATURES__XDMA_SIDEBAND 0x0200
-#define FEATURES__GPREG 0x0400
-#define FEATURES__INDEX_ADDR 0x0800
-
-#define TRANSFER_MODE 0x400
-#define TRANSFER_MODE__VALUE 0x0003
-
-#define INTR_STATUS0 0x410
-#define INTR_STATUS0__ECC_TRANSACTION_DONE 0x0001
-#define INTR_STATUS0__ECC_ERR 0x0002
-#define INTR_STATUS0__DMA_CMD_COMP 0x0004
-#define INTR_STATUS0__TIME_OUT 0x0008
-#define INTR_STATUS0__PROGRAM_FAIL 0x0010
-#define INTR_STATUS0__ERASE_FAIL 0x0020
-#define INTR_STATUS0__LOAD_COMP 0x0040
-#define INTR_STATUS0__PROGRAM_COMP 0x0080
-#define INTR_STATUS0__ERASE_COMP 0x0100
-#define INTR_STATUS0__PIPE_CPYBCK_CMD_COMP 0x0200
-#define INTR_STATUS0__LOCKED_BLK 0x0400
-#define INTR_STATUS0__UNSUP_CMD 0x0800
-#define INTR_STATUS0__INT_ACT 0x1000
-#define INTR_STATUS0__RST_COMP 0x2000
-#define INTR_STATUS0__PIPE_CMD_ERR 0x4000
-#define INTR_STATUS0__PAGE_XFER_INC 0x8000
-
-#define INTR_EN0 0x420
-#define INTR_EN0__ECC_TRANSACTION_DONE 0x0001
-#define INTR_EN0__ECC_ERR 0x0002
-#define INTR_EN0__DMA_CMD_COMP 0x0004
-#define INTR_EN0__TIME_OUT 0x0008
-#define INTR_EN0__PROGRAM_FAIL 0x0010
-#define INTR_EN0__ERASE_FAIL 0x0020
-#define INTR_EN0__LOAD_COMP 0x0040
-#define INTR_EN0__PROGRAM_COMP 0x0080
-#define INTR_EN0__ERASE_COMP 0x0100
-#define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200
-#define INTR_EN0__LOCKED_BLK 0x0400
-#define INTR_EN0__UNSUP_CMD 0x0800
-#define INTR_EN0__INT_ACT 0x1000
-#define INTR_EN0__RST_COMP 0x2000
-#define INTR_EN0__PIPE_CMD_ERR 0x4000
-#define INTR_EN0__PAGE_XFER_INC 0x8000
-
-#define PAGE_CNT0 0x430
-#define PAGE_CNT0__VALUE 0x00ff
-
-#define ERR_PAGE_ADDR0 0x440
-#define ERR_PAGE_ADDR0__VALUE 0xffff
-
-#define ERR_BLOCK_ADDR0 0x450
-#define ERR_BLOCK_ADDR0__VALUE 0xffff
-
-#define INTR_STATUS1 0x460
-#define INTR_STATUS1__ECC_TRANSACTION_DONE 0x0001
-#define INTR_STATUS1__ECC_ERR 0x0002
-#define INTR_STATUS1__DMA_CMD_COMP 0x0004
-#define INTR_STATUS1__TIME_OUT 0x0008
-#define INTR_STATUS1__PROGRAM_FAIL 0x0010
-#define INTR_STATUS1__ERASE_FAIL 0x0020
-#define INTR_STATUS1__LOAD_COMP 0x0040
-#define INTR_STATUS1__PROGRAM_COMP 0x0080
-#define INTR_STATUS1__ERASE_COMP 0x0100
-#define INTR_STATUS1__PIPE_CPYBCK_CMD_COMP 0x0200
-#define INTR_STATUS1__LOCKED_BLK 0x0400
-#define INTR_STATUS1__UNSUP_CMD 0x0800
-#define INTR_STATUS1__INT_ACT 0x1000
-#define INTR_STATUS1__RST_COMP 0x2000
-#define INTR_STATUS1__PIPE_CMD_ERR 0x4000
-#define INTR_STATUS1__PAGE_XFER_INC 0x8000
-
-#define INTR_EN1 0x470
-#define INTR_EN1__ECC_TRANSACTION_DONE 0x0001
-#define INTR_EN1__ECC_ERR 0x0002
-#define INTR_EN1__DMA_CMD_COMP 0x0004
-#define INTR_EN1__TIME_OUT 0x0008
-#define INTR_EN1__PROGRAM_FAIL 0x0010
-#define INTR_EN1__ERASE_FAIL 0x0020
-#define INTR_EN1__LOAD_COMP 0x0040
-#define INTR_EN1__PROGRAM_COMP 0x0080
-#define INTR_EN1__ERASE_COMP 0x0100
-#define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200
-#define INTR_EN1__LOCKED_BLK 0x0400
-#define INTR_EN1__UNSUP_CMD 0x0800
-#define INTR_EN1__INT_ACT 0x1000
-#define INTR_EN1__RST_COMP 0x2000
-#define INTR_EN1__PIPE_CMD_ERR 0x4000
-#define INTR_EN1__PAGE_XFER_INC 0x8000
-
-#define PAGE_CNT1 0x480
-#define PAGE_CNT1__VALUE 0x00ff
-
-#define ERR_PAGE_ADDR1 0x490
-#define ERR_PAGE_ADDR1__VALUE 0xffff
-
-#define ERR_BLOCK_ADDR1 0x4a0
-#define ERR_BLOCK_ADDR1__VALUE 0xffff
-
-#define INTR_STATUS2 0x4b0
-#define INTR_STATUS2__ECC_TRANSACTION_DONE 0x0001
-#define INTR_STATUS2__ECC_ERR 0x0002
-#define INTR_STATUS2__DMA_CMD_COMP 0x0004
-#define INTR_STATUS2__TIME_OUT 0x0008
-#define INTR_STATUS2__PROGRAM_FAIL 0x0010
-#define INTR_STATUS2__ERASE_FAIL 0x0020
-#define INTR_STATUS2__LOAD_COMP 0x0040
-#define INTR_STATUS2__PROGRAM_COMP 0x0080
-#define INTR_STATUS2__ERASE_COMP 0x0100
-#define INTR_STATUS2__PIPE_CPYBCK_CMD_COMP 0x0200
-#define INTR_STATUS2__LOCKED_BLK 0x0400
-#define INTR_STATUS2__UNSUP_CMD 0x0800
-#define INTR_STATUS2__INT_ACT 0x1000
-#define INTR_STATUS2__RST_COMP 0x2000
-#define INTR_STATUS2__PIPE_CMD_ERR 0x4000
-#define INTR_STATUS2__PAGE_XFER_INC 0x8000
-
-#define INTR_EN2 0x4c0
-#define INTR_EN2__ECC_TRANSACTION_DONE 0x0001
-#define INTR_EN2__ECC_ERR 0x0002
-#define INTR_EN2__DMA_CMD_COMP 0x0004
-#define INTR_EN2__TIME_OUT 0x0008
-#define INTR_EN2__PROGRAM_FAIL 0x0010
-#define INTR_EN2__ERASE_FAIL 0x0020
-#define INTR_EN2__LOAD_COMP 0x0040
-#define INTR_EN2__PROGRAM_COMP 0x0080
-#define INTR_EN2__ERASE_COMP 0x0100
-#define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200
-#define INTR_EN2__LOCKED_BLK 0x0400
-#define INTR_EN2__UNSUP_CMD 0x0800
-#define INTR_EN2__INT_ACT 0x1000
-#define INTR_EN2__RST_COMP 0x2000
-#define INTR_EN2__PIPE_CMD_ERR 0x4000
-#define INTR_EN2__PAGE_XFER_INC 0x8000
-
-#define PAGE_CNT2 0x4d0
-#define PAGE_CNT2__VALUE 0x00ff
-
-#define ERR_PAGE_ADDR2 0x4e0
-#define ERR_PAGE_ADDR2__VALUE 0xffff
-
-#define ERR_BLOCK_ADDR2 0x4f0
-#define ERR_BLOCK_ADDR2__VALUE 0xffff
-
-#define INTR_STATUS3 0x500
-#define INTR_STATUS3__ECC_TRANSACTION_DONE 0x0001
-#define INTR_STATUS3__ECC_ERR 0x0002
-#define INTR_STATUS3__DMA_CMD_COMP 0x0004
-#define INTR_STATUS3__TIME_OUT 0x0008
-#define INTR_STATUS3__PROGRAM_FAIL 0x0010
-#define INTR_STATUS3__ERASE_FAIL 0x0020
-#define INTR_STATUS3__LOAD_COMP 0x0040
-#define INTR_STATUS3__PROGRAM_COMP 0x0080
-#define INTR_STATUS3__ERASE_COMP 0x0100
-#define INTR_STATUS3__PIPE_CPYBCK_CMD_COMP 0x0200
-#define INTR_STATUS3__LOCKED_BLK 0x0400
-#define INTR_STATUS3__UNSUP_CMD 0x0800
-#define INTR_STATUS3__INT_ACT 0x1000
-#define INTR_STATUS3__RST_COMP 0x2000
-#define INTR_STATUS3__PIPE_CMD_ERR 0x4000
-#define INTR_STATUS3__PAGE_XFER_INC 0x8000
-
-#define INTR_EN3 0x510
-#define INTR_EN3__ECC_TRANSACTION_DONE 0x0001
-#define INTR_EN3__ECC_ERR 0x0002
-#define INTR_EN3__DMA_CMD_COMP 0x0004
-#define INTR_EN3__TIME_OUT 0x0008
-#define INTR_EN3__PROGRAM_FAIL 0x0010
-#define INTR_EN3__ERASE_FAIL 0x0020
-#define INTR_EN3__LOAD_COMP 0x0040
-#define INTR_EN3__PROGRAM_COMP 0x0080
-#define INTR_EN3__ERASE_COMP 0x0100
-#define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200
-#define INTR_EN3__LOCKED_BLK 0x0400
-#define INTR_EN3__UNSUP_CMD 0x0800
-#define INTR_EN3__INT_ACT 0x1000
-#define INTR_EN3__RST_COMP 0x2000
-#define INTR_EN3__PIPE_CMD_ERR 0x4000
-#define INTR_EN3__PAGE_XFER_INC 0x8000
-
-#define PAGE_CNT3 0x520
-#define PAGE_CNT3__VALUE 0x00ff
-
-#define ERR_PAGE_ADDR3 0x530
-#define ERR_PAGE_ADDR3__VALUE 0xffff
-
-#define ERR_BLOCK_ADDR3 0x540
-#define ERR_BLOCK_ADDR3__VALUE 0xffff
-
-#define DATA_INTR 0x550
-#define DATA_INTR__WRITE_SPACE_AV 0x0001
-#define DATA_INTR__READ_DATA_AV 0x0002
-
-#define DATA_INTR_EN 0x560
-#define DATA_INTR_EN__WRITE_SPACE_AV 0x0001
-#define DATA_INTR_EN__READ_DATA_AV 0x0002
-
-#define GPREG_0 0x570
-#define GPREG_0__VALUE 0xffff
-
-#define GPREG_1 0x580
-#define GPREG_1__VALUE 0xffff
-
-#define GPREG_2 0x590
-#define GPREG_2__VALUE 0xffff
-
-#define GPREG_3 0x5a0
-#define GPREG_3__VALUE 0xffff
-
-#define ECC_THRESHOLD 0x600
-#define ECC_THRESHOLD__VALUE 0x03ff
-
-#define ECC_ERROR_BLOCK_ADDRESS 0x610
-#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff
-
-#define ECC_ERROR_PAGE_ADDRESS 0x620
-#define ECC_ERROR_PAGE_ADDRESS__VALUE 0x0fff
-#define ECC_ERROR_PAGE_ADDRESS__BANK 0xf000
-
-#define ECC_ERROR_ADDRESS 0x630
-#define ECC_ERROR_ADDRESS__OFFSET 0x0fff
-#define ECC_ERROR_ADDRESS__SECTOR_NR 0xf000
-
-#define ERR_CORRECTION_INFO 0x640
-#define ERR_CORRECTION_INFO__BYTEMASK 0x00ff
-#define ERR_CORRECTION_INFO__DEVICE_NR 0x0f00
-#define ERR_CORRECTION_INFO__ERROR_TYPE 0x4000
-#define ERR_CORRECTION_INFO__LAST_ERR_INFO 0x8000
-
-#define DMA_ENABLE 0x700
-#define DMA_ENABLE__FLAG 0x0001
-
-#define IGNORE_ECC_DONE 0x710
-#define IGNORE_ECC_DONE__FLAG 0x0001
-
-#define DMA_INTR 0x720
-#define DMA_INTR__TARGET_ERROR 0x0001
-#define DMA_INTR__DESC_COMP_CHANNEL0 0x0002
-#define DMA_INTR__DESC_COMP_CHANNEL1 0x0004
-#define DMA_INTR__DESC_COMP_CHANNEL2 0x0008
-#define DMA_INTR__DESC_COMP_CHANNEL3 0x0010
-#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020
-
-#define DMA_INTR_EN 0x730
-#define DMA_INTR_EN__TARGET_ERROR 0x0001
-#define DMA_INTR_EN__DESC_COMP_CHANNEL0 0x0002
-#define DMA_INTR_EN__DESC_COMP_CHANNEL1 0x0004
-#define DMA_INTR_EN__DESC_COMP_CHANNEL2 0x0008
-#define DMA_INTR_EN__DESC_COMP_CHANNEL3 0x0010
-#define DMA_INTR_EN__MEMCOPY_DESC_COMP 0x0020
-
-#define TARGET_ERR_ADDR_LO 0x740
-#define TARGET_ERR_ADDR_LO__VALUE 0xffff
-
-#define TARGET_ERR_ADDR_HI 0x750
-#define TARGET_ERR_ADDR_HI__VALUE 0xffff
-
-#define CHNL_ACTIVE 0x760
-#define CHNL_ACTIVE__CHANNEL0 0x0001
-#define CHNL_ACTIVE__CHANNEL1 0x0002
-#define CHNL_ACTIVE__CHANNEL2 0x0004
-#define CHNL_ACTIVE__CHANNEL3 0x0008
-
-#define ACTIVE_SRC_ID 0x800
-#define ACTIVE_SRC_ID__VALUE 0x00ff
-
-#define PTN_INTR 0x810
-#define PTN_INTR__CONFIG_ERROR 0x0001
-#define PTN_INTR__ACCESS_ERROR_BANK0 0x0002
-#define PTN_INTR__ACCESS_ERROR_BANK1 0x0004
-#define PTN_INTR__ACCESS_ERROR_BANK2 0x0008
-#define PTN_INTR__ACCESS_ERROR_BANK3 0x0010
-#define PTN_INTR__REG_ACCESS_ERROR 0x0020
-
-#define PTN_INTR_EN 0x820
-#define PTN_INTR_EN__CONFIG_ERROR 0x0001
-#define PTN_INTR_EN__ACCESS_ERROR_BANK0 0x0002
-#define PTN_INTR_EN__ACCESS_ERROR_BANK1 0x0004
-#define PTN_INTR_EN__ACCESS_ERROR_BANK2 0x0008
-#define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010
-#define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020
-
-#define PERM_SRC_ID_0 0x830
-#define PERM_SRC_ID_0__SRCID 0x00ff
-#define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800
-#define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000
-#define PERM_SRC_ID_0__READ_ACTIVE 0x4000
-#define PERM_SRC_ID_0__PARTITION_VALID 0x8000
-
-#define MIN_BLK_ADDR_0 0x840
-#define MIN_BLK_ADDR_0__VALUE 0xffff
-
-#define MAX_BLK_ADDR_0 0x850
-#define MAX_BLK_ADDR_0__VALUE 0xffff
-
-#define MIN_MAX_BANK_0 0x860
-#define MIN_MAX_BANK_0__MIN_VALUE 0x0003
-#define MIN_MAX_BANK_0__MAX_VALUE 0x000c
-
-#define PERM_SRC_ID_1 0x870
-#define PERM_SRC_ID_1__SRCID 0x00ff
-#define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800
-#define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000
-#define PERM_SRC_ID_1__READ_ACTIVE 0x4000
-#define PERM_SRC_ID_1__PARTITION_VALID 0x8000
-
-#define MIN_BLK_ADDR_1 0x880
-#define MIN_BLK_ADDR_1__VALUE 0xffff
-
-#define MAX_BLK_ADDR_1 0x890
-#define MAX_BLK_ADDR_1__VALUE 0xffff
-
-#define MIN_MAX_BANK_1 0x8a0
-#define MIN_MAX_BANK_1__MIN_VALUE 0x0003
-#define MIN_MAX_BANK_1__MAX_VALUE 0x000c
-
-#define PERM_SRC_ID_2 0x8b0
-#define PERM_SRC_ID_2__SRCID 0x00ff
-#define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800
-#define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000
-#define PERM_SRC_ID_2__READ_ACTIVE 0x4000
-#define PERM_SRC_ID_2__PARTITION_VALID 0x8000
-
-#define MIN_BLK_ADDR_2 0x8c0
-#define MIN_BLK_ADDR_2__VALUE 0xffff
-
-#define MAX_BLK_ADDR_2 0x8d0
-#define MAX_BLK_ADDR_2__VALUE 0xffff
-
-#define MIN_MAX_BANK_2 0x8e0
-#define MIN_MAX_BANK_2__MIN_VALUE 0x0003
-#define MIN_MAX_BANK_2__MAX_VALUE 0x000c
-
-#define PERM_SRC_ID_3 0x8f0
-#define PERM_SRC_ID_3__SRCID 0x00ff
-#define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800
-#define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000
-#define PERM_SRC_ID_3__READ_ACTIVE 0x4000
-#define PERM_SRC_ID_3__PARTITION_VALID 0x8000
-
-#define MIN_BLK_ADDR_3 0x900
-#define MIN_BLK_ADDR_3__VALUE 0xffff
-
-#define MAX_BLK_ADDR_3 0x910
-#define MAX_BLK_ADDR_3__VALUE 0xffff
-
-#define MIN_MAX_BANK_3 0x920
-#define MIN_MAX_BANK_3__MIN_VALUE 0x0003
-#define MIN_MAX_BANK_3__MAX_VALUE 0x000c
-
-#define PERM_SRC_ID_4 0x930
-#define PERM_SRC_ID_4__SRCID 0x00ff
-#define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800
-#define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000
-#define PERM_SRC_ID_4__READ_ACTIVE 0x4000
-#define PERM_SRC_ID_4__PARTITION_VALID 0x8000
-
-#define MIN_BLK_ADDR_4 0x940
-#define MIN_BLK_ADDR_4__VALUE 0xffff
-
-#define MAX_BLK_ADDR_4 0x950
-#define MAX_BLK_ADDR_4__VALUE 0xffff
-
-#define MIN_MAX_BANK_4 0x960
-#define MIN_MAX_BANK_4__MIN_VALUE 0x0003
-#define MIN_MAX_BANK_4__MAX_VALUE 0x000c
-
-#define PERM_SRC_ID_5 0x970
-#define PERM_SRC_ID_5__SRCID 0x00ff
-#define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800
-#define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000
-#define PERM_SRC_ID_5__READ_ACTIVE 0x4000
-#define PERM_SRC_ID_5__PARTITION_VALID 0x8000
-
-#define MIN_BLK_ADDR_5 0x980
-#define MIN_BLK_ADDR_5__VALUE 0xffff
-
-#define MAX_BLK_ADDR_5 0x990
-#define MAX_BLK_ADDR_5__VALUE 0xffff
-
-#define MIN_MAX_BANK_5 0x9a0
-#define MIN_MAX_BANK_5__MIN_VALUE 0x0003
-#define MIN_MAX_BANK_5__MAX_VALUE 0x000c
-
-#define PERM_SRC_ID_6 0x9b0
-#define PERM_SRC_ID_6__SRCID 0x00ff
-#define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800
-#define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000
-#define PERM_SRC_ID_6__READ_ACTIVE 0x4000
-#define PERM_SRC_ID_6__PARTITION_VALID 0x8000
-
-#define MIN_BLK_ADDR_6 0x9c0
-#define MIN_BLK_ADDR_6__VALUE 0xffff
-
-#define MAX_BLK_ADDR_6 0x9d0
-#define MAX_BLK_ADDR_6__VALUE 0xffff
-
-#define MIN_MAX_BANK_6 0x9e0
-#define MIN_MAX_BANK_6__MIN_VALUE 0x0003
-#define MIN_MAX_BANK_6__MAX_VALUE 0x000c
-
-#define PERM_SRC_ID_7 0x9f0
-#define PERM_SRC_ID_7__SRCID 0x00ff
-#define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800
-#define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000
-#define PERM_SRC_ID_7__READ_ACTIVE 0x4000
-#define PERM_SRC_ID_7__PARTITION_VALID 0x8000
-
-#define MIN_BLK_ADDR_7 0xa00
-#define MIN_BLK_ADDR_7__VALUE 0xffff
-
-#define MAX_BLK_ADDR_7 0xa10
-#define MAX_BLK_ADDR_7__VALUE 0xffff
-
-#define MIN_MAX_BANK_7 0xa20
-#define MIN_MAX_BANK_7__MIN_VALUE 0x0003
-#define MIN_MAX_BANK_7__MAX_VALUE 0x000c
diff --git a/drivers/staging/spectra/spectraswconfig.h b/drivers/staging/spectra/spectraswconfig.h
deleted file mode 100644
index 17259469e955..000000000000
--- a/drivers/staging/spectra/spectraswconfig.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * NAND Flash Controller Device Driver
- * Copyright (c) 2009, Intel Corporation and its suppliers.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef _SPECTRASWCONFIG_
-#define _SPECTRASWCONFIG_
-
-/* NAND driver version */
-#define GLOB_VERSION "driver version 20100311"
-
-
-/***** Common Parameters *****/
-#define RETRY_TIMES 3
-
-#define READ_BADBLOCK_INFO 1
-#define READBACK_VERIFY 0
-#define AUTO_FORMAT_FLASH 0
-
-/***** Cache Parameters *****/
-#define CACHE_ITEM_NUM 128
-#define BLK_NUM_FOR_L2_CACHE 16
-
-/***** Block Table Parameters *****/
-#define BLOCK_TABLE_INDEX 0
-
-/***** Wear Leveling Parameters *****/
-#define WEAR_LEVELING_GATE 0x10
-#define WEAR_LEVELING_BLOCK_NUM 10
-
-#define DEBUG_BNDRY 0
-
-/***** Product Feature Support *****/
-#define FLASH_EMU defined(CONFIG_SPECTRA_EMU)
-#define FLASH_NAND defined(CONFIG_SPECTRA_MRST_HW)
-#define FLASH_MTD defined(CONFIG_SPECTRA_MTD)
-#define CMD_DMA defined(CONFIG_SPECTRA_MRST_HW_DMA)
-
-#define SPECTRA_PARTITION_ID 0
-
-/* Enable this macro if the number of flash blocks is larger than 16K. */
-#define SUPPORT_LARGE_BLOCKNUM 1
-
-/**** Block Table and Reserved Block Parameters *****/
-#define SPECTRA_START_BLOCK 3
-//#define NUM_FREE_BLOCKS_GATE 30
-#define NUM_FREE_BLOCKS_GATE 60
-
-/**** Hardware Parameters ****/
-#define GLOB_HWCTL_REG_BASE 0xFFA40000
-#define GLOB_HWCTL_REG_SIZE 4096
-
-#define GLOB_HWCTL_MEM_BASE 0xFFA48000
-#define GLOB_HWCTL_MEM_SIZE 4096
-
-/* KBV - Updated to LNW scratch register address */
-#define SCRATCH_REG_ADDR 0xFF108018
-#define SCRATCH_REG_SIZE 64
-
-#define GLOB_HWCTL_DEFAULT_BLKS 2048
-
-#define SUPPORT_15BITECC 1
-#define SUPPORT_8BITECC 1
-
-#define ONFI_BLOOM_TIME 0
-#define MODE5_WORKAROUND 1
-
-#endif /*_SPECTRASWCONFIG_*/
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index 55c0b510889c..03420e25d9c6 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -109,11 +109,6 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
spin_unlock(&sdev->ud.lock);
return -EINVAL;
}
-#if 0
- setnodelay(socket);
- setkeepalive(socket);
- setreuse(socket);
-#endif
sdev->ud.tcp_socket = socket;
spin_unlock(&sdev->ud.lock);
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
index 6b4e3e182de8..27ac363d1cfa 100644
--- a/drivers/staging/usbip/stub_rx.c
+++ b/drivers/staging/usbip/stub_rx.c
@@ -564,7 +564,7 @@ static void stub_rx_pdu(struct usbip_device *ud)
memset(&pdu, 0, sizeof(pdu));
/* 1. receive a pdu header */
- ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0);
+ ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
if (ret != sizeof(pdu)) {
dev_err(dev, "recv a header, %d\n", ret);
usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index 3b7a847f4657..d93e7f1f7973 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -334,9 +334,8 @@ void usbip_dump_header(struct usbip_header *pdu)
}
EXPORT_SYMBOL_GPL(usbip_dump_header);
-/* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */
-int usbip_xmit(int send, struct socket *sock, char *buf, int size,
- int msg_flags)
+/* Receive data over TCP/IP. */
+int usbip_recv(struct socket *sock, void *buf, int size)
{
int result;
struct msghdr msg;
@@ -355,19 +354,6 @@ int usbip_xmit(int send, struct socket *sock, char *buf, int size,
return -EINVAL;
}
- if (usbip_dbg_flag_xmit) {
- if (send) {
- if (!in_interrupt())
- pr_debug("%-10s:", current->comm);
- else
- pr_debug("interrupt :");
-
- pr_debug("sending... , sock %p, buf %p, size %d, "
- "msg_flags %d\n", sock, buf, size, msg_flags);
- usbip_dump_buffer(buf, size);
- }
- }
-
do {
sock->sk->sk_allocation = GFP_NOIO;
iov.iov_base = buf;
@@ -377,42 +363,30 @@ int usbip_xmit(int send, struct socket *sock, char *buf, int size,
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_namelen = 0;
- msg.msg_flags = msg_flags | MSG_NOSIGNAL;
-
- if (send)
- result = kernel_sendmsg(sock, &msg, &iov, 1, size);
- else
- result = kernel_recvmsg(sock, &msg, &iov, 1, size,
- MSG_WAITALL);
+ msg.msg_flags = MSG_NOSIGNAL;
+ result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL);
if (result <= 0) {
- pr_debug("%s sock %p buf %p size %u ret %d total %d\n",
- send ? "send" : "receive", sock, buf, size,
- result, total);
+ pr_debug("receive sock %p buf %p size %u ret %d total %d\n",
+ sock, buf, size, result, total);
goto err;
}
size -= result;
buf += result;
total += result;
-
} while (size > 0);
if (usbip_dbg_flag_xmit) {
- if (!send) {
- if (!in_interrupt())
- pr_debug("%-10s:", current->comm);
- else
- pr_debug("interrupt :");
-
- pr_debug("receiving....\n");
- usbip_dump_buffer(bp, osize);
- pr_debug("received, osize %d ret %d size %d total %d\n",
- osize, result, size, total);
- }
+ if (!in_interrupt())
+ pr_debug("%-10s:", current->comm);
+ else
+ pr_debug("interrupt :");
- if (send)
- pr_debug("send, total %d\n", total);
+ pr_debug("receiving....\n");
+ usbip_dump_buffer(bp, osize);
+ pr_debug("received, osize %d ret %d size %d total %d\n",
+ osize, result, size, total);
}
return total;
@@ -420,7 +394,7 @@ int usbip_xmit(int send, struct socket *sock, char *buf, int size,
err:
return result;
}
-EXPORT_SYMBOL_GPL(usbip_xmit);
+EXPORT_SYMBOL_GPL(usbip_recv);
struct socket *sockfd_to_socket(unsigned int sockfd)
{
@@ -712,7 +686,7 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
if (!buff)
return -ENOMEM;
- ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0);
+ ret = usbip_recv(ud->tcp_socket, buff, size);
if (ret != size) {
dev_err(&urb->dev->dev, "recv iso_frame_descriptor, %d\n",
ret);
@@ -823,8 +797,7 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
if (!(size > 0))
return 0;
- ret = usbip_xmit(0, ud->tcp_socket, (char *)urb->transfer_buffer,
- size, 0);
+ ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size);
if (ret != size) {
dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret);
if (ud->side == USBIP_STUB) {
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index be216175ae87..b8f8c48b8a72 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -292,21 +292,11 @@ struct usbip_device {
} eh_ops;
};
-#if 0
-int usbip_sendmsg(struct socket *, struct msghdr *, int);
-int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss);
-int setnodelay(struct socket *);
-int setquickack(struct socket *);
-int setkeepalive(struct socket *socket);
-void setreuse(struct socket *);
-#endif
-
/* usbip_common.c */
void usbip_dump_urb(struct urb *purb);
void usbip_dump_header(struct usbip_header *pdu);
-int usbip_xmit(int send, struct socket *sock, char *buf, int size,
- int msg_flags);
+int usbip_recv(struct socket *sock, void *buf, int size);
struct socket *sockfd_to_socket(unsigned int sockfd);
void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
@@ -337,9 +327,4 @@ static inline int interface_to_devnum(struct usb_interface *interface)
return udev->devnum;
}
-static inline int interface_to_infnum(struct usb_interface *interface)
-{
- return interface->cur_altsetting->desc.bInterfaceNumber;
-}
-
#endif /* __USBIP_COMMON_H */
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
index 3872b8cccdcf..3f511b47563d 100644
--- a/drivers/staging/usbip/vhci_rx.c
+++ b/drivers/staging/usbip/vhci_rx.c
@@ -206,7 +206,7 @@ static void vhci_rx_pdu(struct usbip_device *ud)
memset(&pdu, 0, sizeof(pdu));
/* 1. receive a pdu header */
- ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0);
+ ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
if (ret < 0) {
if (ret == -ECONNRESET)
pr_info("connection reset by peer\n");
diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO
index 82c222b4a146..79f00333e7ef 100644
--- a/drivers/staging/vme/TODO
+++ b/drivers/staging/vme/TODO
@@ -1,70 +1,5 @@
TODO
====
-API
-===
-
-Master window broadcast select mask
------------------------------------
-
-API currently provides no method to set or get Broadcast Select mask. Suggest
-somthing like:
-
- int vme_master_bmsk_set (struct vme_resource *res, int mask);
- int vme_master_bmsk_get (struct vme_resource *res, int *mask);
-
-
-Interrupt Generation
---------------------
-
-Add optional timeout when waiting for an IACK.
-
-
-CR/CSR Buffer
--------------
-
-The VME API provides no functions to access the buffer mapped into the CR/CSR
-space.
-
-
-Mailboxes
----------
-
-Whilst not part of the VME specification, they are provided by a number of
-chips. They are currently not supported at all by the API.
-
-
-Core
-====
-
-- Improve generic sanity checks (Such as does an offset and size fit within a
- window and parameter checking).
-
-Bridge Support
-==============
-
-Tempe (tsi148)
---------------
-
-- 2eSST Broadcast mode.
-- Mailboxes unsupported.
-- Improve error detection.
-- Control of prefetch size, threshold.
-- Arbiter control
-- Requestor control
-
-Universe II (ca91c142)
-----------------------
-
-- Mailboxes unsupported.
-- Error Detection.
-- Control of prefetch size, threshold.
-- Arbiter control
-- Requestor control
-- Slot detection
-
-Universe I (ca91x042)
----------------------
-
-Currently completely unsupported.
+- Add one or more device drivers which use the VME framework.
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index 0e4feac138eb..515b8b8e32a8 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -338,7 +338,7 @@ static int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level,
static int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled,
unsigned long long vme_base, unsigned long long size,
- dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle)
+ dma_addr_t pci_base, u32 aspace, u32 cycle)
{
unsigned int i, addr = 0, granularity;
unsigned int temp_ctl = 0;
@@ -444,7 +444,7 @@ static int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled,
static int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled,
unsigned long long *vme_base, unsigned long long *size,
- dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle)
+ dma_addr_t *pci_base, u32 *aspace, u32 *cycle)
{
unsigned int i, granularity = 0, ctl = 0;
unsigned long long vme_bound, pci_offset;
@@ -595,8 +595,8 @@ static void ca91cx42_free_resource(struct vme_master_resource *image)
static int ca91cx42_master_set(struct vme_master_resource *image, int enabled,
- unsigned long long vme_base, unsigned long long size,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
+ unsigned long long vme_base, unsigned long long size, u32 aspace,
+ u32 cycle, u32 dwidth)
{
int retval = 0;
unsigned int i, granularity = 0;
@@ -753,7 +753,7 @@ err_window:
static int __ca91cx42_master_get(struct vme_master_resource *image,
int *enabled, unsigned long long *vme_base, unsigned long long *size,
- vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
+ u32 *aspace, u32 *cycle, u32 *dwidth)
{
unsigned int i, ctl;
unsigned long long pci_base, pci_bound, vme_offset;
@@ -839,8 +839,8 @@ static int __ca91cx42_master_get(struct vme_master_resource *image,
}
static int ca91cx42_master_get(struct vme_master_resource *image, int *enabled,
- unsigned long long *vme_base, unsigned long long *size,
- vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
+ unsigned long long *vme_base, unsigned long long *size, u32 *aspace,
+ u32 *cycle, u32 *dwidth)
{
int retval;
@@ -876,13 +876,13 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image,
* maximal configured data cycle is used and splits it
* automatically for non-aligned addresses.
*/
- if ((int)addr & 0x1) {
+ if ((uintptr_t)addr & 0x1) {
*(u8 *)buf = ioread8(addr);
done += 1;
if (done == count)
goto out;
}
- if ((int)addr & 0x2) {
+ if ((uintptr_t)addr & 0x2) {
if ((count - done) < 2) {
*(u8 *)(buf + done) = ioread8(addr + done);
done += 1;
@@ -930,13 +930,13 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image,
/* Here we apply for the same strategy we do in master_read
* function in order to assure D16 cycle when required.
*/
- if ((int)addr & 0x1) {
+ if ((uintptr_t)addr & 0x1) {
iowrite8(*(u8 *)buf, addr);
done += 1;
if (done == count)
goto out;
}
- if ((int)addr & 0x2) {
+ if ((uintptr_t)addr & 0x2) {
if ((count - done) < 2) {
iowrite8(*(u8 *)(buf + done), addr + done);
done += 1;
@@ -973,7 +973,8 @@ static unsigned int ca91cx42_master_rmw(struct vme_master_resource *image,
unsigned int mask, unsigned int compare, unsigned int swap,
loff_t offset)
{
- u32 pci_addr, result;
+ u32 result;
+ uintptr_t pci_addr;
int i;
struct ca91cx42_driver *bridge;
struct device *dev;
@@ -990,7 +991,7 @@ static unsigned int ca91cx42_master_rmw(struct vme_master_resource *image,
/* Lock image */
spin_lock(&image->lock);
- pci_addr = (u32)image->kern_base + offset;
+ pci_addr = (uintptr_t)image->kern_base + offset;
/* Address must be 4-byte aligned */
if (pci_addr & 0x3) {
@@ -1291,7 +1292,7 @@ static int ca91cx42_dma_list_empty(struct vme_dma_list *list)
* callback is attached and disabled when the last callback is removed.
*/
static int ca91cx42_lm_set(struct vme_lm_resource *lm,
- unsigned long long lm_base, vme_address_t aspace, vme_cycle_t cycle)
+ unsigned long long lm_base, u32 aspace, u32 cycle)
{
u32 temp_base, lm_ctl = 0;
int i;
@@ -1359,7 +1360,7 @@ static int ca91cx42_lm_set(struct vme_lm_resource *lm,
* or disabled.
*/
static int ca91cx42_lm_get(struct vme_lm_resource *lm,
- unsigned long long *lm_base, vme_address_t *aspace, vme_cycle_t *cycle)
+ unsigned long long *lm_base, u32 *aspace, u32 *cycle)
{
u32 lm_ctl, enabled = 0;
struct ca91cx42_driver *bridge;
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index 6c1167c2bea9..08a449b4abf9 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -483,7 +483,7 @@ static int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level,
* Find the first error in this address range
*/
static struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge,
- vme_address_t aspace, unsigned long long address, size_t count)
+ u32 aspace, unsigned long long address, size_t count)
{
struct list_head *err_pos;
struct vme_bus_error *vme_err, *valid = NULL;
@@ -517,7 +517,7 @@ static struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge,
* Clear errors in the provided address range.
*/
static void tsi148_clear_errors(struct vme_bridge *tsi148_bridge,
- vme_address_t aspace, unsigned long long address, size_t count)
+ u32 aspace, unsigned long long address, size_t count)
{
struct list_head *err_pos, *temp;
struct vme_bus_error *vme_err;
@@ -551,7 +551,7 @@ static void tsi148_clear_errors(struct vme_bridge *tsi148_bridge,
*/
static int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
unsigned long long vme_base, unsigned long long size,
- dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle)
+ dma_addr_t pci_base, u32 aspace, u32 cycle)
{
unsigned int i, addr = 0, granularity = 0;
unsigned int temp_ctl = 0;
@@ -701,7 +701,7 @@ static int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
*/
static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled,
unsigned long long *vme_base, unsigned long long *size,
- dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle)
+ dma_addr_t *pci_base, u32 *aspace, u32 *cycle)
{
unsigned int i, granularity = 0, ctl = 0;
unsigned int vme_base_low, vme_base_high;
@@ -893,8 +893,8 @@ static void tsi148_free_resource(struct vme_master_resource *image)
* Set the attributes of an outbound window.
*/
static int tsi148_master_set(struct vme_master_resource *image, int enabled,
- unsigned long long vme_base, unsigned long long size,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
+ unsigned long long vme_base, unsigned long long size, u32 aspace,
+ u32 cycle, u32 dwidth)
{
int retval = 0;
unsigned int i;
@@ -1129,8 +1129,8 @@ err_window:
* XXX Not parsing prefetch information.
*/
static int __tsi148_master_get(struct vme_master_resource *image, int *enabled,
- unsigned long long *vme_base, unsigned long long *size,
- vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
+ unsigned long long *vme_base, unsigned long long *size, u32 *aspace,
+ u32 *cycle, u32 *dwidth)
{
unsigned int i, ctl;
unsigned int pci_base_low, pci_base_high;
@@ -1239,8 +1239,8 @@ static int __tsi148_master_get(struct vme_master_resource *image, int *enabled,
static int tsi148_master_get(struct vme_master_resource *image, int *enabled,
- unsigned long long *vme_base, unsigned long long *size,
- vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
+ unsigned long long *vme_base, unsigned long long *size, u32 *aspace,
+ u32 *cycle, u32 *dwidth)
{
int retval;
@@ -1259,9 +1259,7 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
{
int retval, enabled;
unsigned long long vme_base, size;
- vme_address_t aspace;
- vme_cycle_t cycle;
- vme_width_t dwidth;
+ u32 aspace, cycle, dwidth;
struct vme_bus_error *vme_err = NULL;
struct vme_bridge *tsi148_bridge;
@@ -1301,9 +1299,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
{
int retval = 0, enabled;
unsigned long long vme_base, size;
- vme_address_t aspace;
- vme_cycle_t cycle;
- vme_width_t dwidth;
+ u32 aspace, cycle, dwidth;
struct vme_bus_error *vme_err = NULL;
struct vme_bridge *tsi148_bridge;
@@ -1420,7 +1416,7 @@ static unsigned int tsi148_master_rmw(struct vme_master_resource *image,
}
static int tsi148_dma_set_vme_src_attributes(struct device *dev, u32 *attr,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
+ u32 aspace, u32 cycle, u32 dwidth)
{
/* Setup 2eSST speeds */
switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
@@ -1514,7 +1510,7 @@ static int tsi148_dma_set_vme_src_attributes(struct device *dev, u32 *attr,
}
static int tsi148_dma_set_vme_dest_attributes(struct device *dev, u32 *attr,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
+ u32 aspace, u32 cycle, u32 dwidth)
{
/* Setup 2eSST speeds */
switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
@@ -1886,7 +1882,7 @@ static int tsi148_dma_list_empty(struct vme_dma_list *list)
* callback is attached and disabled when the last callback is removed.
*/
static int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
- vme_address_t aspace, vme_cycle_t cycle)
+ u32 aspace, u32 cycle)
{
u32 lm_base_high, lm_base_low, lm_ctl = 0;
int i;
@@ -1953,7 +1949,7 @@ static int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
* or disabled.
*/
static int tsi148_lm_get(struct vme_lm_resource *lm,
- unsigned long long *lm_base, vme_address_t *aspace, vme_cycle_t *cycle)
+ unsigned long long *lm_base, u32 *aspace, u32 *cycle)
{
u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0;
struct tsi148_driver *bridge;
diff --git a/drivers/staging/vme/devices/Kconfig b/drivers/staging/vme/devices/Kconfig
index ca5ba89e2d8c..55ec30cb1fa2 100644
--- a/drivers/staging/vme/devices/Kconfig
+++ b/drivers/staging/vme/devices/Kconfig
@@ -6,3 +6,16 @@ config VME_USER
If you say Y here you want to be able to access a limited number of
VME windows in a manner at least semi-compatible with the interface
provided with the original driver at http://vmelinux.org/.
+
+config VME_PIO2
+ tristate "GE PIO2 VME"
+ depends on GPIOLIB
+ help
+ Say Y here to include support for the GE PIO2. The PIO2 is a 6U VME
+ slave card, implementing 32 solid-state relay switched IO lines, in
+ 4 groups of 8. Each bank of IO lines is built to function as input,
+ output or both depending on the variant of the card.
+
+ To compile this driver as a module, choose M here. The module will
+ be called vme_pio2. If unsure, say N.
+
diff --git a/drivers/staging/vme/devices/Makefile b/drivers/staging/vme/devices/Makefile
index 459742a75283..172512cb5dbf 100644
--- a/drivers/staging/vme/devices/Makefile
+++ b/drivers/staging/vme/devices/Makefile
@@ -3,3 +3,6 @@
#
obj-$(CONFIG_VME_USER) += vme_user.o
+
+vme_pio2-objs := vme_pio2_cntr.o vme_pio2_gpio.o vme_pio2_core.o
+obj-$(CONFIG_VME_PIO2) += vme_pio2.o
diff --git a/drivers/staging/vme/devices/vme_pio2.h b/drivers/staging/vme/devices/vme_pio2.h
new file mode 100644
index 000000000000..3c5931364535
--- /dev/null
+++ b/drivers/staging/vme/devices/vme_pio2.h
@@ -0,0 +1,249 @@
+#ifndef _VME_PIO2_H_
+#define _VME_PIO2_H_
+
+#define PIO2_CARDS_MAX 32
+
+#define PIO2_VARIANT_LENGTH 5
+
+#define PIO2_NUM_CHANNELS 32
+#define PIO2_NUM_IRQS 11
+#define PIO2_NUM_CNTRS 6
+
+#define PIO2_REGS_SIZE 0x40
+
+#define PIO2_REGS_DATA0 0x0
+#define PIO2_REGS_DATA1 0x1
+#define PIO2_REGS_DATA2 0x2
+#define PIO2_REGS_DATA3 0x3
+
+static const int PIO2_REGS_DATA[4] = { PIO2_REGS_DATA0, PIO2_REGS_DATA1,
+ PIO2_REGS_DATA2, PIO2_REGS_DATA3 };
+
+#define PIO2_REGS_INT_STAT0 0x8
+#define PIO2_REGS_INT_STAT1 0x9
+#define PIO2_REGS_INT_STAT2 0xa
+#define PIO2_REGS_INT_STAT3 0xb
+
+static const int PIO2_REGS_INT_STAT[4] = { PIO2_REGS_INT_STAT0,
+ PIO2_REGS_INT_STAT1,
+ PIO2_REGS_INT_STAT2,
+ PIO2_REGS_INT_STAT3 };
+
+#define PIO2_REGS_INT_STAT_CNTR 0xc
+#define PIO2_REGS_INT_MASK0 0x10
+#define PIO2_REGS_INT_MASK1 0x11
+#define PIO2_REGS_INT_MASK2 0x12
+#define PIO2_REGS_INT_MASK3 0x13
+#define PIO2_REGS_INT_MASK4 0x14
+#define PIO2_REGS_INT_MASK5 0x15
+#define PIO2_REGS_INT_MASK6 0x16
+#define PIO2_REGS_INT_MASK7 0x17
+
+static const int PIO2_REGS_INT_MASK[8] = { PIO2_REGS_INT_MASK0,
+ PIO2_REGS_INT_MASK1,
+ PIO2_REGS_INT_MASK2,
+ PIO2_REGS_INT_MASK3,
+ PIO2_REGS_INT_MASK4,
+ PIO2_REGS_INT_MASK5,
+ PIO2_REGS_INT_MASK6,
+ PIO2_REGS_INT_MASK7 };
+
+
+
+#define PIO2_REGS_CTRL 0x18
+#define PIO2_REGS_VME_VECTOR 0x19
+#define PIO2_REGS_CNTR0 0x20
+#define PIO2_REGS_CNTR1 0x22
+#define PIO2_REGS_CNTR2 0x24
+#define PIO2_REGS_CTRL_WRD0 0x26
+#define PIO2_REGS_CNTR3 0x28
+#define PIO2_REGS_CNTR4 0x2a
+#define PIO2_REGS_CNTR5 0x2c
+#define PIO2_REGS_CTRL_WRD1 0x2e
+
+#define PIO2_REGS_ID 0x30
+
+
+/* PIO2_REGS_DATAx (0x0 - 0x3) */
+
+static const int PIO2_CHANNEL_BANK[32] = { 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3 };
+
+#define PIO2_CHANNEL0_BIT (1 << 0)
+#define PIO2_CHANNEL1_BIT (1 << 1)
+#define PIO2_CHANNEL2_BIT (1 << 2)
+#define PIO2_CHANNEL3_BIT (1 << 3)
+#define PIO2_CHANNEL4_BIT (1 << 4)
+#define PIO2_CHANNEL5_BIT (1 << 5)
+#define PIO2_CHANNEL6_BIT (1 << 6)
+#define PIO2_CHANNEL7_BIT (1 << 7)
+#define PIO2_CHANNEL8_BIT (1 << 0)
+#define PIO2_CHANNEL9_BIT (1 << 1)
+#define PIO2_CHANNEL10_BIT (1 << 2)
+#define PIO2_CHANNEL11_BIT (1 << 3)
+#define PIO2_CHANNEL12_BIT (1 << 4)
+#define PIO2_CHANNEL13_BIT (1 << 5)
+#define PIO2_CHANNEL14_BIT (1 << 6)
+#define PIO2_CHANNEL15_BIT (1 << 7)
+#define PIO2_CHANNEL16_BIT (1 << 0)
+#define PIO2_CHANNEL17_BIT (1 << 1)
+#define PIO2_CHANNEL18_BIT (1 << 2)
+#define PIO2_CHANNEL19_BIT (1 << 3)
+#define PIO2_CHANNEL20_BIT (1 << 4)
+#define PIO2_CHANNEL21_BIT (1 << 5)
+#define PIO2_CHANNEL22_BIT (1 << 6)
+#define PIO2_CHANNEL23_BIT (1 << 7)
+#define PIO2_CHANNEL24_BIT (1 << 0)
+#define PIO2_CHANNEL25_BIT (1 << 1)
+#define PIO2_CHANNEL26_BIT (1 << 2)
+#define PIO2_CHANNEL27_BIT (1 << 3)
+#define PIO2_CHANNEL28_BIT (1 << 4)
+#define PIO2_CHANNEL29_BIT (1 << 5)
+#define PIO2_CHANNEL30_BIT (1 << 6)
+#define PIO2_CHANNEL31_BIT (1 << 7)
+
+static const int PIO2_CHANNEL_BIT[32] = { PIO2_CHANNEL0_BIT, PIO2_CHANNEL1_BIT,
+ PIO2_CHANNEL2_BIT, PIO2_CHANNEL3_BIT,
+ PIO2_CHANNEL4_BIT, PIO2_CHANNEL5_BIT,
+ PIO2_CHANNEL6_BIT, PIO2_CHANNEL7_BIT,
+ PIO2_CHANNEL8_BIT, PIO2_CHANNEL9_BIT,
+ PIO2_CHANNEL10_BIT, PIO2_CHANNEL11_BIT,
+ PIO2_CHANNEL12_BIT, PIO2_CHANNEL13_BIT,
+ PIO2_CHANNEL14_BIT, PIO2_CHANNEL15_BIT,
+ PIO2_CHANNEL16_BIT, PIO2_CHANNEL17_BIT,
+ PIO2_CHANNEL18_BIT, PIO2_CHANNEL19_BIT,
+ PIO2_CHANNEL20_BIT, PIO2_CHANNEL21_BIT,
+ PIO2_CHANNEL22_BIT, PIO2_CHANNEL23_BIT,
+ PIO2_CHANNEL24_BIT, PIO2_CHANNEL25_BIT,
+ PIO2_CHANNEL26_BIT, PIO2_CHANNEL27_BIT,
+ PIO2_CHANNEL28_BIT, PIO2_CHANNEL29_BIT,
+ PIO2_CHANNEL30_BIT, PIO2_CHANNEL31_BIT
+ };
+
+/* PIO2_REGS_INT_STAT_CNTR (0xc) */
+#define PIO2_COUNTER0 (1 << 0)
+#define PIO2_COUNTER1 (1 << 1)
+#define PIO2_COUNTER2 (1 << 2)
+#define PIO2_COUNTER3 (1 << 3)
+#define PIO2_COUNTER4 (1 << 4)
+#define PIO2_COUNTER5 (1 << 5)
+
+static const int PIO2_COUNTER[6] = { PIO2_COUNTER0, PIO2_COUNTER1,
+ PIO2_COUNTER2, PIO2_COUNTER3,
+ PIO2_COUNTER4, PIO2_COUNTER5 };
+
+/* PIO2_REGS_CTRL (0x18) */
+#define PIO2_VME_INT_MASK 0x7
+#define PIO2_LED (1 << 6)
+#define PIO2_LOOP (1 << 7)
+
+/* PIO2_REGS_VME_VECTOR (0x19) */
+#define PIO2_VME_VECTOR_SPUR 0x0
+#define PIO2_VME_VECTOR_BANK0 0x1
+#define PIO2_VME_VECTOR_BANK1 0x2
+#define PIO2_VME_VECTOR_BANK2 0x3
+#define PIO2_VME_VECTOR_BANK3 0x4
+#define PIO2_VME_VECTOR_CNTR0 0x5
+#define PIO2_VME_VECTOR_CNTR1 0x6
+#define PIO2_VME_VECTOR_CNTR2 0x7
+#define PIO2_VME_VECTOR_CNTR3 0x8
+#define PIO2_VME_VECTOR_CNTR4 0x9
+#define PIO2_VME_VECTOR_CNTR5 0xa
+
+#define PIO2_VME_VECTOR_MASK 0xf0
+
+static const int PIO2_VECTOR_BANK[4] = { PIO2_VME_VECTOR_BANK0,
+ PIO2_VME_VECTOR_BANK1,
+ PIO2_VME_VECTOR_BANK2,
+ PIO2_VME_VECTOR_BANK3 };
+
+static const int PIO2_VECTOR_CNTR[6] = { PIO2_VME_VECTOR_CNTR0,
+ PIO2_VME_VECTOR_CNTR1,
+ PIO2_VME_VECTOR_CNTR2,
+ PIO2_VME_VECTOR_CNTR3,
+ PIO2_VME_VECTOR_CNTR4,
+ PIO2_VME_VECTOR_CNTR5 };
+
+/* PIO2_REGS_CNTRx (0x20 - 0x24 & 0x28 - 0x2c) */
+
+static const int PIO2_CNTR_DATA[6] = { PIO2_REGS_CNTR0, PIO2_REGS_CNTR1,
+ PIO2_REGS_CNTR2, PIO2_REGS_CNTR3,
+ PIO2_REGS_CNTR4, PIO2_REGS_CNTR5 };
+
+/* PIO2_REGS_CTRL_WRDx (0x26 & 0x2e) */
+
+static const int PIO2_CNTR_CTRL[6] = { PIO2_REGS_CTRL_WRD0,
+ PIO2_REGS_CTRL_WRD0,
+ PIO2_REGS_CTRL_WRD0,
+ PIO2_REGS_CTRL_WRD1,
+ PIO2_REGS_CTRL_WRD1,
+ PIO2_REGS_CTRL_WRD1 };
+
+#define PIO2_CNTR_SC_DEV0 0
+#define PIO2_CNTR_SC_DEV1 (1 << 6)
+#define PIO2_CNTR_SC_DEV2 (2 << 6)
+#define PIO2_CNTR_SC_RDBACK (3 << 6)
+
+static const int PIO2_CNTR_SC_DEV[6] = { PIO2_CNTR_SC_DEV0, PIO2_CNTR_SC_DEV1,
+ PIO2_CNTR_SC_DEV2, PIO2_CNTR_SC_DEV0,
+ PIO2_CNTR_SC_DEV1, PIO2_CNTR_SC_DEV2 };
+
+#define PIO2_CNTR_RW_LATCH 0
+#define PIO2_CNTR_RW_LSB (1 << 4)
+#define PIO2_CNTR_RW_MSB (2 << 4)
+#define PIO2_CNTR_RW_BOTH (3 << 4)
+
+#define PIO2_CNTR_MODE0 0
+#define PIO2_CNTR_MODE1 (1 << 1)
+#define PIO2_CNTR_MODE2 (2 << 1)
+#define PIO2_CNTR_MODE3 (3 << 1)
+#define PIO2_CNTR_MODE4 (4 << 1)
+#define PIO2_CNTR_MODE5 (5 << 1)
+
+#define PIO2_CNTR_BCD 1
+
+
+
+enum pio2_bank_config { NOFIT, INPUT, OUTPUT, BOTH };
+enum pio2_int_config { NONE = 0, LOW2HIGH = 1, HIGH2LOW = 2, EITHER = 4 };
+
+/* Bank configuration structure */
+struct pio2_io_bank {
+ enum pio2_bank_config config;
+ u8 value;
+ enum pio2_int_config irq[8];
+};
+
+/* Counter configuration structure */
+struct pio2_cntr {
+ int mode;
+ int count;
+};
+
+struct pio2_card {
+ int id;
+ int bus;
+ long base;
+ int irq_vector;
+ int irq_level;
+ char variant[6];
+ int led;
+
+ struct vme_dev *vdev;
+ struct vme_resource *window;
+
+ struct gpio_chip gc;
+ struct pio2_io_bank bank[4];
+
+ struct pio2_cntr cntr[6];
+};
+
+int pio2_cntr_reset(struct pio2_card *);
+
+int pio2_gpio_reset(struct pio2_card *);
+int __init pio2_gpio_init(struct pio2_card *);
+void __exit pio2_gpio_exit(struct pio2_card *);
+
+#endif /* _VME_PIO2_H_ */
diff --git a/drivers/staging/vme/devices/vme_pio2_cntr.c b/drivers/staging/vme/devices/vme_pio2_cntr.c
new file mode 100644
index 000000000000..08e0d59806ca
--- /dev/null
+++ b/drivers/staging/vme/devices/vme_pio2_cntr.c
@@ -0,0 +1,71 @@
+/*
+ * GE PIO2 Counter Driver
+ *
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * The PIO-2 has 6 counters, currently this code just disables the interrupts
+ * and leaves them alone.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+
+#include "../vme.h"
+#include "vme_pio2.h"
+
+static int pio2_cntr_irq_set(struct pio2_card *card, int id)
+{
+ int retval;
+ u8 data;
+
+ data = PIO2_CNTR_SC_DEV[id] | PIO2_CNTR_RW_BOTH | card->cntr[id].mode;
+ retval = vme_master_write(card->window, &data, 1, PIO2_CNTR_CTRL[id]);
+ if (retval < 0)
+ return retval;
+
+ data = card->cntr[id].count & 0xFF;
+ retval = vme_master_write(card->window, &data, 1, PIO2_CNTR_DATA[id]);
+ if (retval < 0)
+ return retval;
+
+ data = (card->cntr[id].count >> 8) & 0xFF;
+ retval = vme_master_write(card->window, &data, 1, PIO2_CNTR_DATA[id]);
+ if (retval < 0)
+ return retval;
+
+ return 0;
+}
+
+int pio2_cntr_reset(struct pio2_card *card)
+{
+ int i, retval = 0;
+ u8 reg;
+
+ /* Clear down all timers */
+ for (i = 0; i < 6; i++) {
+ card->cntr[i].mode = PIO2_CNTR_MODE5;
+ card->cntr[i].count = 0;
+ retval = pio2_cntr_irq_set(card, i);
+ if (retval < 0)
+ return retval;
+ }
+
+ /* Ensure all counter interrupts are cleared */
+ do {
+ retval = vme_master_read(card->window, &reg, 1,
+ PIO2_REGS_INT_STAT_CNTR);
+ if (retval < 0)
+ return retval;
+ } while (reg != 0);
+
+ return retval;
+}
+
diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
new file mode 100644
index 000000000000..9fedc442a779
--- /dev/null
+++ b/drivers/staging/vme/devices/vme_pio2_core.c
@@ -0,0 +1,524 @@
+/*
+ * GE PIO2 6U VME I/O Driver
+ *
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include "../vme.h"
+#include "vme_pio2.h"
+
+
+static const char driver_name[] = "pio2";
+
+static int bus[PIO2_CARDS_MAX];
+static int bus_num;
+static long base[PIO2_CARDS_MAX];
+static int base_num;
+static int vector[PIO2_CARDS_MAX];
+static int vector_num;
+static int level[PIO2_CARDS_MAX];
+static int level_num;
+static const char *variant[PIO2_CARDS_MAX];
+static int variant_num;
+
+static int loopback;
+
+static int pio2_match(struct vme_dev *);
+static int __devinit pio2_probe(struct vme_dev *);
+static int __devexit pio2_remove(struct vme_dev *);
+
+static int pio2_get_led(struct pio2_card *card)
+{
+ /* Can't read hardware, state saved in structure */
+ return card->led;
+}
+
+static int pio2_set_led(struct pio2_card *card, int state)
+{
+ u8 reg;
+ int retval;
+
+ reg = card->irq_level;
+
+ /* Register state inverse of led state */
+ if (!state)
+ reg |= PIO2_LED;
+
+ if (loopback)
+ reg |= PIO2_LOOP;
+
+ retval = vme_master_write(card->window, &reg, 1, PIO2_REGS_CTRL);
+ if (retval < 0)
+ return retval;
+
+ card->led = state ? 1 : 0;
+
+ return 0;
+}
+
+static void pio2_int(int level, int vector, void *ptr)
+{
+ int vec, i, channel, retval;
+ u8 reg;
+ struct pio2_card *card = ptr;
+
+ vec = vector & ~PIO2_VME_VECTOR_MASK;
+
+ switch (vec) {
+ case 0:
+ dev_warn(&card->vdev->dev, "Spurious Interrupt\n");
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ /* Channels 0 to 7 */
+ retval = vme_master_read(card->window, &reg, 1,
+ PIO2_REGS_INT_STAT[vec - 1]);
+ if (retval < 0) {
+ dev_err(&card->vdev->dev,
+ "Unable to read IRQ status register\n");
+ return;
+ }
+ for (i = 0; i < 8; i++) {
+ channel = ((vec - 1) * 8) + i;
+ if (reg & PIO2_CHANNEL_BIT[channel])
+ dev_info(&card->vdev->dev,
+ "Interrupt on I/O channel %d\n",
+ channel);
+ }
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ /* Counters are dealt with by their own handler */
+ dev_err(&card->vdev->dev,
+ "Counter interrupt\n");
+ break;
+ }
+}
+
+
+/*
+ * We return whether this has been successful - this is used in the probe to
+ * ensure we have a valid card.
+ */
+static int pio2_reset_card(struct pio2_card *card)
+{
+ int retval = 0;
+ u8 data = 0;
+
+ /* Clear main register*/
+ retval = vme_master_write(card->window, &data, 1, PIO2_REGS_CTRL);
+ if (retval < 0)
+ return retval;
+
+ /* Clear VME vector */
+ retval = vme_master_write(card->window, &data, 1, PIO2_REGS_VME_VECTOR);
+ if (retval < 0)
+ return retval;
+
+ /* Reset GPIO */
+ retval = pio2_gpio_reset(card);
+ if (retval < 0)
+ return retval;
+
+ /* Reset counters */
+ retval = pio2_cntr_reset(card);
+ if (retval < 0)
+ return retval;
+
+ return 0;
+}
+
+static struct vme_driver pio2_driver = {
+ .name = driver_name,
+ .match = pio2_match,
+ .probe = pio2_probe,
+ .remove = __devexit_p(pio2_remove),
+};
+
+
+static int __init pio2_init(void)
+{
+ int retval = 0;
+
+ if (bus_num == 0) {
+ printk(KERN_ERR "%s: No cards, skipping registration\n",
+ driver_name);
+ goto err_nocard;
+ }
+
+ if (bus_num > PIO2_CARDS_MAX) {
+ printk(KERN_ERR
+ "%s: Driver only able to handle %d PIO2 Cards\n",
+ driver_name, PIO2_CARDS_MAX);
+ bus_num = PIO2_CARDS_MAX;
+ }
+
+ /* Register the PIO2 driver */
+ retval = vme_register_driver(&pio2_driver, bus_num);
+ if (retval != 0)
+ goto err_reg;
+
+ return retval;
+
+err_reg:
+err_nocard:
+ return retval;
+}
+
+static int pio2_match(struct vme_dev *vdev)
+{
+
+ if (vdev->num >= bus_num) {
+ dev_err(&vdev->dev,
+ "The enumeration of the VMEbus to which the board is connected must be specified");
+ return 0;
+ }
+
+ if (vdev->num >= base_num) {
+ dev_err(&vdev->dev,
+ "The VME address for the cards registers must be specified");
+ return 0;
+ }
+
+ if (vdev->num >= vector_num) {
+ dev_err(&vdev->dev,
+ "The IRQ vector used by the card must be specified");
+ return 0;
+ }
+
+ if (vdev->num >= level_num) {
+ dev_err(&vdev->dev,
+ "The IRQ level used by the card must be specified");
+ return 0;
+ }
+
+ if (vdev->num >= variant_num) {
+ dev_err(&vdev->dev, "The variant of the card must be specified");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int __devinit pio2_probe(struct vme_dev *vdev)
+{
+ struct pio2_card *card;
+ int retval;
+ int i;
+ u8 reg;
+ int vec;
+
+ card = kzalloc(sizeof(struct pio2_card), GFP_KERNEL);
+ if (card == NULL) {
+ dev_err(&vdev->dev, "Unable to allocate card structure\n");
+ retval = -ENOMEM;
+ goto err_struct;
+ }
+
+ card->id = vdev->num;
+ card->bus = bus[card->id];
+ card->base = base[card->id];
+ card->irq_vector = vector[card->id];
+ card->irq_level = level[card->id] & PIO2_VME_INT_MASK;
+ strncpy(card->variant, variant[card->id], PIO2_VARIANT_LENGTH);
+ card->vdev = vdev;
+
+ for (i = 0; i < PIO2_VARIANT_LENGTH; i++) {
+
+ if (isdigit(card->variant[i]) == 0) {
+ dev_err(&card->vdev->dev, "Variant invalid\n");
+ retval = -EINVAL;
+ goto err_variant;
+ }
+ }
+
+ /*
+ * Bottom 4 bits of VME interrupt vector used to determine source,
+ * provided vector should only use upper 4 bits.
+ */
+ if (card->irq_vector & ~PIO2_VME_VECTOR_MASK) {
+ dev_err(&card->vdev->dev,
+ "Invalid VME IRQ Vector, vector must not use lower 4 bits\n");
+ retval = -EINVAL;
+ goto err_vector;
+ }
+
+ /*
+ * There is no way to determine the build variant or whether each bank
+ * is input, output or both at run time. The inputs are also inverted
+ * if configured as both.
+ *
+ * We pass in the board variant and use that to determine the
+ * configuration of the banks.
+ */
+ for (i = 1; i < PIO2_VARIANT_LENGTH; i++) {
+ switch (card->variant[i]) {
+ case '0':
+ card->bank[i-1].config = NOFIT;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ card->bank[i-1].config = INPUT;
+ break;
+ case '5':
+ card->bank[i-1].config = OUTPUT;
+ break;
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ card->bank[i-1].config = BOTH;
+ break;
+ }
+ }
+
+ /* Get a master window and position over regs */
+ card->window = vme_master_request(vdev, VME_A24, VME_SCT, VME_D16);
+ if (card->window == NULL) {
+ dev_err(&card->vdev->dev,
+ "Unable to assign VME master resource\n");
+ retval = -EIO;
+ goto err_window;
+ }
+
+ retval = vme_master_set(card->window, 1, card->base, 0x10000, VME_A24,
+ (VME_SCT | VME_USER | VME_DATA), VME_D16);
+ if (retval) {
+ dev_err(&card->vdev->dev,
+ "Unable to configure VME master resource\n");
+ goto err_set;
+ }
+
+ /*
+ * There is also no obvious register which we can probe to determine
+ * whether the provided base is valid. If we can read the "ID Register"
+ * offset and the reset function doesn't error, assume we have a valid
+ * location.
+ */
+ retval = vme_master_read(card->window, &reg, 1, PIO2_REGS_ID);
+ if (retval < 0) {
+ dev_err(&card->vdev->dev, "Unable to read from device\n");
+ goto err_read;
+ }
+
+ dev_dbg(&card->vdev->dev, "ID Register:%x\n", reg);
+
+ /*
+ * Ensure all the I/O is cleared. We can't read back the states, so
+ * this is the only method we have to ensure that the I/O is in a known
+ * state.
+ */
+ retval = pio2_reset_card(card);
+ if (retval) {
+ dev_err(&card->vdev->dev,
+ "Failed to reset card, is location valid?");
+ retval = -ENODEV;
+ goto err_reset;
+ }
+
+ /* Configure VME Interrupts */
+ reg = card->irq_level;
+ if (pio2_get_led(card))
+ reg |= PIO2_LED;
+ if (loopback)
+ reg |= PIO2_LOOP;
+ retval = vme_master_write(card->window, &reg, 1, PIO2_REGS_CTRL);
+ if (retval < 0)
+ return retval;
+
+ /* Set VME vector */
+ retval = vme_master_write(card->window, &card->irq_vector, 1,
+ PIO2_REGS_VME_VECTOR);
+ if (retval < 0)
+ return retval;
+
+ /* Attach spurious interrupt handler. */
+ vec = card->irq_vector | PIO2_VME_VECTOR_SPUR;
+
+ retval = vme_irq_request(vdev, card->irq_level, vec,
+ &pio2_int, (void *)card);
+ if (retval < 0) {
+ dev_err(&card->vdev->dev,
+ "Unable to attach VME interrupt vector0x%x, level 0x%x\n",
+ vec, card->irq_level);
+ goto err_irq;
+ }
+
+ /* Attach GPIO interrupt handlers. */
+ for (i = 0; i < 4; i++) {
+ vec = card->irq_vector | PIO2_VECTOR_BANK[i];
+
+ retval = vme_irq_request(vdev, card->irq_level, vec,
+ &pio2_int, (void *)card);
+ if (retval < 0) {
+ dev_err(&card->vdev->dev,
+ "Unable to attach VME interrupt vector0x%x, level 0x%x\n",
+ vec, card->irq_level);
+ goto err_gpio_irq;
+ }
+ }
+
+ /* Attach counter interrupt handlers. */
+ for (i = 0; i < 6; i++) {
+ vec = card->irq_vector | PIO2_VECTOR_CNTR[i];
+
+ retval = vme_irq_request(vdev, card->irq_level, vec,
+ &pio2_int, (void *)card);
+ if (retval < 0) {
+ dev_err(&card->vdev->dev,
+ "Unable to attach VME interrupt vector0x%x, level 0x%x\n",
+ vec, card->irq_level);
+ goto err_cntr_irq;
+ }
+ }
+
+ /* Register IO */
+ retval = pio2_gpio_init(card);
+ if (retval < 0) {
+ dev_err(&card->vdev->dev,
+ "Unable to register with GPIO framework\n");
+ goto err_gpio;
+ }
+
+ /* Set LED - This also sets interrupt level */
+ retval = pio2_set_led(card, 0);
+ if (retval < 0) {
+ dev_err(&card->vdev->dev, "Unable to set LED\n");
+ goto err_led;
+ }
+
+ dev_set_drvdata(&card->vdev->dev, card);
+
+ dev_info(&card->vdev->dev,
+ "PIO2 (variant %s) configured at 0x%lx\n", card->variant,
+ card->base);
+
+ return 0;
+
+err_led:
+ pio2_gpio_exit(card);
+err_gpio:
+ i = 6;
+err_cntr_irq:
+ while (i > 0) {
+ i--;
+ vec = card->irq_vector | PIO2_VECTOR_CNTR[i];
+ vme_irq_free(vdev, card->irq_level, vec);
+ }
+
+ i = 4;
+err_gpio_irq:
+ while (i > 0) {
+ i--;
+ vec = card->irq_vector | PIO2_VECTOR_BANK[i];
+ vme_irq_free(vdev, card->irq_level, vec);
+ }
+
+ vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR;
+ vme_irq_free(vdev, card->irq_level, vec);
+err_irq:
+ pio2_reset_card(card);
+err_reset:
+err_read:
+ vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16);
+err_set:
+ vme_master_free(card->window);
+err_window:
+err_vector:
+err_variant:
+ kfree(card);
+err_struct:
+ return retval;
+}
+
+static int __devexit pio2_remove(struct vme_dev *vdev)
+{
+ int vec;
+ int i;
+
+ struct pio2_card *card = dev_get_drvdata(&vdev->dev);
+
+ pio2_gpio_exit(card);
+
+ for (i = 0; i < 6; i++) {
+ vec = card->irq_vector | PIO2_VECTOR_CNTR[i];
+ vme_irq_free(vdev, card->irq_level, vec);
+ }
+
+ for (i = 0; i < 4; i++) {
+ vec = card->irq_vector | PIO2_VECTOR_BANK[i];
+ vme_irq_free(vdev, card->irq_level, vec);
+ }
+
+ vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR;
+ vme_irq_free(vdev, card->irq_level, vec);
+
+ pio2_reset_card(card);
+
+ vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16);
+
+ vme_master_free(card->window);
+
+ kfree(card);
+
+ return 0;
+}
+
+static void __exit pio2_exit(void)
+{
+ vme_unregister_driver(&pio2_driver);
+}
+
+
+/* These are required for each board */
+MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected");
+module_param_array(bus, int, &bus_num, S_IRUGO);
+
+MODULE_PARM_DESC(base, "Base VME address for PIO2 Registers");
+module_param_array(base, long, &base_num, S_IRUGO);
+
+MODULE_PARM_DESC(vector, "VME IRQ Vector (Lower 4 bits masked)");
+module_param_array(vector, int, &vector_num, S_IRUGO);
+
+MODULE_PARM_DESC(level, "VME IRQ Level");
+module_param_array(level, int, &level_num, S_IRUGO);
+
+MODULE_PARM_DESC(variant, "Last 4 characters of PIO2 board variant");
+module_param_array(variant, charp, &variant_num, S_IRUGO);
+
+/* This is for debugging */
+MODULE_PARM_DESC(loopback, "Enable loopback mode on all cards");
+module_param(loopback, bool, S_IRUGO);
+
+MODULE_DESCRIPTION("GE PIO2 6U VME I/O Driver");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
+MODULE_LICENSE("GPL");
+
+module_init(pio2_init);
+module_exit(pio2_exit);
+
diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c
new file mode 100644
index 000000000000..dc837deb99dd
--- /dev/null
+++ b/drivers/staging/vme/devices/vme_pio2_gpio.c
@@ -0,0 +1,232 @@
+/*
+ * GE PIO2 GPIO Driver
+ *
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include "../vme.h"
+#include "vme_pio2.h"
+
+static const char driver_name[] = "pio2_gpio";
+
+static struct pio2_card *gpio_to_pio2_card(struct gpio_chip *chip)
+{
+ return container_of(chip, struct pio2_card, gc);
+}
+
+static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ u8 reg;
+ int retval;
+ struct pio2_card *card = gpio_to_pio2_card(chip);
+
+ if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
+ (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
+
+ dev_err(&card->vdev->dev, "Channel not available as input\n");
+ return 0;
+ }
+
+ retval = vme_master_read(card->window, &reg, 1,
+ PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
+ if (retval < 0) {
+ dev_err(&card->vdev->dev, "Unable to read from GPIO\n");
+ return 0;
+ }
+
+ /*
+ * Remember, input on channels configured as both input and output
+ * are inverted!
+ */
+ if (reg & PIO2_CHANNEL_BIT[offset]) {
+ if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
+ return 0;
+ else
+ return 1;
+ } else {
+ if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+static void pio2_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ u8 reg;
+ int retval;
+ struct pio2_card *card = gpio_to_pio2_card(chip);
+
+ if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
+ (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
+
+ dev_err(&card->vdev->dev, "Channel not availabe as output\n");
+ return;
+ }
+
+ if (value)
+ reg = card->bank[PIO2_CHANNEL_BANK[offset]].value |
+ PIO2_CHANNEL_BIT[offset];
+ else
+ reg = card->bank[PIO2_CHANNEL_BANK[offset]].value &
+ ~PIO2_CHANNEL_BIT[offset];
+
+ retval = vme_master_write(card->window, &reg, 1,
+ PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
+ if (retval < 0) {
+ dev_err(&card->vdev->dev, "Unable to write to GPIO\n");
+ return;
+ }
+
+ card->bank[PIO2_CHANNEL_BANK[offset]].value = reg;
+}
+
+/* Directionality configured at board build - send appropriate response */
+static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
+{
+ int data;
+ struct pio2_card *card = gpio_to_pio2_card(chip);
+
+ if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
+ (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
+ dev_err(&card->vdev->dev,
+ "Channel directionality not configurable at runtine\n");
+
+ data = -EINVAL;
+ } else {
+ data = 0;
+ }
+
+ return data;
+}
+
+/* Directionality configured at board build - send appropriate response */
+static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+ int data;
+ struct pio2_card *card = gpio_to_pio2_card(chip);
+
+ if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
+ (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
+ dev_err(&card->vdev->dev,
+ "Channel directionality not configurable at runtine\n");
+
+ data = -EINVAL;
+ } else {
+ data = 0;
+ }
+
+ return data;
+}
+
+/*
+ * We return whether this has been successful - this is used in the probe to
+ * ensure we have a valid card.
+ */
+int pio2_gpio_reset(struct pio2_card *card)
+{
+ int retval = 0;
+ int i, j;
+
+ u8 data = 0;
+
+ /* Zero output registers */
+ for (i = 0; i < 4; i++) {
+ retval = vme_master_write(card->window, &data, 1,
+ PIO2_REGS_DATA[i]);
+ if (retval < 0)
+ return retval;
+ card->bank[i].value = 0;
+ }
+
+ /* Set input interrupt masks */
+ for (i = 0; i < 4; i++) {
+ retval = vme_master_write(card->window, &data, 1,
+ PIO2_REGS_INT_MASK[i * 2]);
+ if (retval < 0)
+ return retval;
+
+ retval = vme_master_write(card->window, &data, 1,
+ PIO2_REGS_INT_MASK[(i * 2) + 1]);
+ if (retval < 0)
+ return retval;
+
+ for (j = 0; j < 8; j++)
+ card->bank[i].irq[j] = NONE;
+ }
+
+ /* Ensure all I/O interrupts are cleared */
+ for (i = 0; i < 4; i++) {
+ do {
+ retval = vme_master_read(card->window, &data, 1,
+ PIO2_REGS_INT_STAT[i]);
+ if (retval < 0)
+ return retval;
+ } while (data != 0);
+ }
+
+ return 0;
+}
+
+int __init pio2_gpio_init(struct pio2_card *card)
+{
+ int retval = 0;
+ char *label;
+
+ label = kmalloc(PIO2_NUM_CHANNELS, GFP_KERNEL);
+ if (label == NULL) {
+ dev_err(&card->vdev->dev, "Unable to allocate GPIO label\n");
+ return -ENOMEM;
+ }
+
+ sprintf(label, "%s@%s", driver_name, dev_name(&card->vdev->dev));
+ card->gc.label = label;
+
+ card->gc.ngpio = PIO2_NUM_CHANNELS;
+ /* Dynamic allocation of base */
+ card->gc.base = -1;
+ /* Setup pointers to chip functions */
+ card->gc.direction_input = pio2_gpio_dir_in;
+ card->gc.direction_output = pio2_gpio_dir_out;
+ card->gc.get = pio2_gpio_get;
+ card->gc.set = pio2_gpio_set;
+
+ /* This function adds a memory mapped GPIO chip */
+ retval = gpiochip_add(&(card->gc));
+ if (retval) {
+ dev_err(&card->vdev->dev, "Unable to register GPIO\n");
+ kfree(card->gc.label);
+ }
+
+ return retval;
+};
+
+void __exit pio2_gpio_exit(struct pio2_card *card)
+{
+ const char *label = card->gc.label;
+
+ if (gpiochip_remove(&(card->gc)))
+ dev_err(&card->vdev->dev, "Failed to remove GPIO");
+
+ kfree(label);
+}
+
diff --git a/drivers/staging/vme/devices/vme_user.h b/drivers/staging/vme/devices/vme_user.h
index d85a1e9dbe3a..7d24cd6343e4 100644
--- a/drivers/staging/vme/devices/vme_user.h
+++ b/drivers/staging/vme/devices/vme_user.h
@@ -10,9 +10,9 @@ struct vme_master {
int enable; /* State of Window */
unsigned long long vme_addr; /* Starting Address on the VMEbus */
unsigned long long size; /* Window Size */
- vme_address_t aspace; /* Address Space */
- vme_cycle_t cycle; /* Cycle properties */
- vme_width_t dwidth; /* Maximum Data Width */
+ u32 aspace; /* Address Space */
+ u32 cycle; /* Cycle properties */
+ u32 dwidth; /* Maximum Data Width */
#if 0
char prefetchEnable; /* Prefetch Read Enable State */
int prefetchSize; /* Prefetch Read Size (Cache Lines) */
@@ -34,8 +34,8 @@ struct vme_slave {
int enable; /* State of Window */
unsigned long long vme_addr; /* Starting Address on the VMEbus */
unsigned long long size; /* Window Size */
- vme_address_t aspace; /* Address Space */
- vme_cycle_t cycle; /* Cycle properties */
+ u32 aspace; /* Address Space */
+ u32 cycle; /* Cycle properties */
#if 0
char wrPostEnable; /* Write Post State */
char rmwLock; /* Lock PCI during RMW Cycles */
diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c
index b04b4688f705..70722ae52321 100644
--- a/drivers/staging/vme/vme.c
+++ b/drivers/staging/vme/vme.c
@@ -153,9 +153,7 @@ size_t vme_get_size(struct vme_resource *resource)
int enabled, retval;
unsigned long long base, size;
dma_addr_t buf_base;
- vme_address_t aspace;
- vme_cycle_t cycle;
- vme_width_t dwidth;
+ u32 aspace, cycle, dwidth;
switch (resource->type) {
case VME_MASTER:
@@ -181,7 +179,7 @@ size_t vme_get_size(struct vme_resource *resource)
}
EXPORT_SYMBOL(vme_get_size);
-static int vme_check_window(vme_address_t aspace, unsigned long long vme_base,
+static int vme_check_window(u32 aspace, unsigned long long vme_base,
unsigned long long size)
{
int retval = 0;
@@ -232,8 +230,8 @@ static int vme_check_window(vme_address_t aspace, unsigned long long vme_base,
* Request a slave image with specific attributes, return some unique
* identifier.
*/
-struct vme_resource *vme_slave_request(struct vme_dev *vdev,
- vme_address_t address, vme_cycle_t cycle)
+struct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address,
+ u32 cycle)
{
struct vme_bridge *bridge;
struct list_head *slave_pos = NULL;
@@ -298,7 +296,7 @@ EXPORT_SYMBOL(vme_slave_request);
int vme_slave_set(struct vme_resource *resource, int enabled,
unsigned long long vme_base, unsigned long long size,
- dma_addr_t buf_base, vme_address_t aspace, vme_cycle_t cycle)
+ dma_addr_t buf_base, u32 aspace, u32 cycle)
{
struct vme_bridge *bridge = find_bridge(resource);
struct vme_slave_resource *image;
@@ -333,7 +331,7 @@ EXPORT_SYMBOL(vme_slave_set);
int vme_slave_get(struct vme_resource *resource, int *enabled,
unsigned long long *vme_base, unsigned long long *size,
- dma_addr_t *buf_base, vme_address_t *aspace, vme_cycle_t *cycle)
+ dma_addr_t *buf_base, u32 *aspace, u32 *cycle)
{
struct vme_bridge *bridge = find_bridge(resource);
struct vme_slave_resource *image;
@@ -388,8 +386,8 @@ EXPORT_SYMBOL(vme_slave_free);
* Request a master image with specific attributes, return some unique
* identifier.
*/
-struct vme_resource *vme_master_request(struct vme_dev *vdev,
- vme_address_t address, vme_cycle_t cycle, vme_width_t dwidth)
+struct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address,
+ u32 cycle, u32 dwidth)
{
struct vme_bridge *bridge;
struct list_head *master_pos = NULL;
@@ -456,8 +454,8 @@ err_bus:
EXPORT_SYMBOL(vme_master_request);
int vme_master_set(struct vme_resource *resource, int enabled,
- unsigned long long vme_base, unsigned long long size,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
+ unsigned long long vme_base, unsigned long long size, u32 aspace,
+ u32 cycle, u32 dwidth)
{
struct vme_bridge *bridge = find_bridge(resource);
struct vme_master_resource *image;
@@ -492,8 +490,8 @@ int vme_master_set(struct vme_resource *resource, int enabled,
EXPORT_SYMBOL(vme_master_set);
int vme_master_get(struct vme_resource *resource, int *enabled,
- unsigned long long *vme_base, unsigned long long *size,
- vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
+ unsigned long long *vme_base, unsigned long long *size, u32 *aspace,
+ u32 *cycle, u32 *dwidth)
{
struct vme_bridge *bridge = find_bridge(resource);
struct vme_master_resource *image;
@@ -646,8 +644,7 @@ EXPORT_SYMBOL(vme_master_free);
* Request a DMA controller with specific attributes, return some unique
* identifier.
*/
-struct vme_resource *vme_dma_request(struct vme_dev *vdev,
- vme_dma_route_t route)
+struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route)
{
struct vme_bridge *bridge;
struct list_head *dma_pos = NULL;
@@ -743,8 +740,7 @@ EXPORT_SYMBOL(vme_new_dma_list);
/*
* Create "Pattern" type attributes
*/
-struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern,
- vme_pattern_t type)
+struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type)
{
struct vme_dma_attr *attributes;
struct vme_dma_pattern *pattern_attr;
@@ -822,7 +818,7 @@ EXPORT_SYMBOL(vme_dma_pci_attribute);
* Create "VME" type attributes
*/
struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
+ u32 aspace, u32 cycle, u32 dwidth)
{
struct vme_dma_attr *attributes;
struct vme_dma_vme *vme_attr;
@@ -1173,7 +1169,7 @@ int vme_lm_count(struct vme_resource *resource)
EXPORT_SYMBOL(vme_lm_count);
int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base,
- vme_address_t aspace, vme_cycle_t cycle)
+ u32 aspace, u32 cycle)
{
struct vme_bridge *bridge = find_bridge(resource);
struct vme_lm_resource *lm;
@@ -1195,7 +1191,7 @@ int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base,
EXPORT_SYMBOL(vme_lm_set);
int vme_lm_get(struct vme_resource *resource, unsigned long long *lm_base,
- vme_address_t *aspace, vme_cycle_t *cycle)
+ u32 *aspace, u32 *cycle)
{
struct vme_bridge *bridge = find_bridge(resource);
struct vme_lm_resource *lm;
@@ -1307,7 +1303,12 @@ EXPORT_SYMBOL(vme_slot_get);
/* - Bridge Registration --------------------------------------------------- */
-static int vme_add_bus(struct vme_bridge *bridge)
+static void vme_dev_release(struct device *dev)
+{
+ kfree(dev_to_vme_dev(dev));
+}
+
+int vme_register_bridge(struct vme_bridge *bridge)
{
int i;
int ret = -1;
@@ -1327,8 +1328,9 @@ static int vme_add_bus(struct vme_bridge *bridge)
return ret;
}
+EXPORT_SYMBOL(vme_register_bridge);
-static void vme_remove_bus(struct vme_bridge *bridge)
+void vme_unregister_bridge(struct vme_bridge *bridge)
{
struct vme_dev *vdev;
struct vme_dev *tmp;
@@ -1343,22 +1345,6 @@ static void vme_remove_bus(struct vme_bridge *bridge)
list_del(&bridge->bus_list);
mutex_unlock(&vme_buses_lock);
}
-
-static void vme_dev_release(struct device *dev)
-{
- kfree(dev_to_vme_dev(dev));
-}
-
-int vme_register_bridge(struct vme_bridge *bridge)
-{
- return vme_add_bus(bridge);
-}
-EXPORT_SYMBOL(vme_register_bridge);
-
-void vme_unregister_bridge(struct vme_bridge *bridge)
-{
- vme_remove_bus(bridge);
-}
EXPORT_SYMBOL(vme_unregister_bridge);
/* - Driver Registration --------------------------------------------------- */
@@ -1421,10 +1407,7 @@ static int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs)
* and if the bridge is removed, it will have to go through
* vme_unregister_bridge() to do it (which calls remove() on
* the bridge which in turn tries to acquire vme_buses_lock and
- * will have to wait). The probe() called after device
- * registration in __vme_register_driver below will also fail
- * as the bridge is being removed (since the probe() calls
- * vme_bridge_get()).
+ * will have to wait).
*/
err = __vme_register_driver_bus(drv, bridge, ndevs);
if (err)
diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h
index e3828badca61..9d38ceed60e2 100644
--- a/drivers/staging/vme/vme.h
+++ b/drivers/staging/vme/vme.h
@@ -10,7 +10,6 @@ enum vme_resource_type {
};
/* VME Address Spaces */
-typedef u32 vme_address_t;
#define VME_A16 0x1
#define VME_A24 0x2
#define VME_A32 0x4
@@ -29,7 +28,6 @@ typedef u32 vme_address_t;
/* VME Cycle Types */
-typedef u32 vme_cycle_t;
#define VME_SCT 0x1
#define VME_BLT 0x2
#define VME_MBLT 0x4
@@ -47,28 +45,23 @@ typedef u32 vme_cycle_t;
#define VME_DATA 0x8000
/* VME Data Widths */
-typedef u32 vme_width_t;
#define VME_D8 0x1
#define VME_D16 0x2
#define VME_D32 0x4
#define VME_D64 0x8
/* Arbitration Scheduling Modes */
-typedef u32 vme_arbitration_t;
#define VME_R_ROBIN_MODE 0x1
#define VME_PRIORITY_MODE 0x2
-typedef u32 vme_dma_t;
#define VME_DMA_PATTERN (1<<0)
#define VME_DMA_PCI (1<<1)
#define VME_DMA_VME (1<<2)
-typedef u32 vme_pattern_t;
#define VME_DMA_PATTERN_BYTE (1<<0)
#define VME_DMA_PATTERN_WORD (1<<1)
#define VME_DMA_PATTERN_INCREMENT (1<<2)
-typedef u32 vme_dma_route_t;
#define VME_DMA_VME_TO_MEM (1<<0)
#define VME_DMA_MEM_TO_VME (1<<1)
#define VME_DMA_VME_TO_VME (1<<2)
@@ -77,7 +70,7 @@ typedef u32 vme_dma_route_t;
#define VME_DMA_PATTERN_TO_MEM (1<<5)
struct vme_dma_attr {
- vme_dma_t type;
+ u32 type;
void *private;
};
@@ -97,7 +90,7 @@ extern struct bus_type vme_bus_type;
/**
* Structure representing a VME device
- * @id: The ID of the device (currently the bus and slot number)
+ * @num: The device number
* @bridge: Pointer to the bridge device this device is on
* @dev: Internal device structure
* @drv_list: List of devices (per driver)
@@ -128,32 +121,29 @@ void vme_free_consistent(struct vme_resource *, size_t, void *,
size_t vme_get_size(struct vme_resource *);
-struct vme_resource *vme_slave_request(struct vme_dev *, vme_address_t,
- vme_cycle_t);
+struct vme_resource *vme_slave_request(struct vme_dev *, u32, u32);
int vme_slave_set(struct vme_resource *, int, unsigned long long,
- unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t);
+ unsigned long long, dma_addr_t, u32, u32);
int vme_slave_get(struct vme_resource *, int *, unsigned long long *,
- unsigned long long *, dma_addr_t *, vme_address_t *, vme_cycle_t *);
+ unsigned long long *, dma_addr_t *, u32 *, u32 *);
void vme_slave_free(struct vme_resource *);
-struct vme_resource *vme_master_request(struct vme_dev *, vme_address_t,
- vme_cycle_t, vme_width_t);
+struct vme_resource *vme_master_request(struct vme_dev *, u32, u32, u32);
int vme_master_set(struct vme_resource *, int, unsigned long long,
- unsigned long long, vme_address_t, vme_cycle_t, vme_width_t);
+ unsigned long long, u32, u32, u32);
int vme_master_get(struct vme_resource *, int *, unsigned long long *,
- unsigned long long *, vme_address_t *, vme_cycle_t *, vme_width_t *);
+ unsigned long long *, u32 *, u32 *, u32 *);
ssize_t vme_master_read(struct vme_resource *, void *, size_t, loff_t);
ssize_t vme_master_write(struct vme_resource *, void *, size_t, loff_t);
unsigned int vme_master_rmw(struct vme_resource *, unsigned int, unsigned int,
unsigned int, loff_t);
void vme_master_free(struct vme_resource *);
-struct vme_resource *vme_dma_request(struct vme_dev *, vme_dma_route_t);
+struct vme_resource *vme_dma_request(struct vme_dev *, u32);
struct vme_dma_list *vme_new_dma_list(struct vme_resource *);
-struct vme_dma_attr *vme_dma_pattern_attribute(u32, vme_pattern_t);
+struct vme_dma_attr *vme_dma_pattern_attribute(u32, u32);
struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t);
-struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long, vme_address_t,
- vme_cycle_t, vme_width_t);
+struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long, u32, u32, u32);
void vme_dma_free_attribute(struct vme_dma_attr *);
int vme_dma_list_add(struct vme_dma_list *, struct vme_dma_attr *,
struct vme_dma_attr *, size_t);
@@ -168,10 +158,8 @@ int vme_irq_generate(struct vme_dev *, int, int);
struct vme_resource * vme_lm_request(struct vme_dev *);
int vme_lm_count(struct vme_resource *);
-int vme_lm_set(struct vme_resource *, unsigned long long, vme_address_t,
- vme_cycle_t);
-int vme_lm_get(struct vme_resource *, unsigned long long *, vme_address_t *,
- vme_cycle_t *);
+int vme_lm_set(struct vme_resource *, unsigned long long, u32, u32);
+int vme_lm_get(struct vme_resource *, unsigned long long *, u32 *, u32 *);
int vme_lm_attach(struct vme_resource *, int, void (*callback)(int));
int vme_lm_detach(struct vme_resource *, int);
void vme_lm_free(struct vme_resource *);
diff --git a/drivers/staging/vme/vme_api.txt b/drivers/staging/vme/vme_api.txt
index e8ff2151a487..856efa35f6e3 100644
--- a/drivers/staging/vme/vme_api.txt
+++ b/drivers/staging/vme/vme_api.txt
@@ -86,26 +86,26 @@ driver allows a resource to be assigned based on the required attributes of the
driver in question:
struct vme_resource * vme_master_request(struct vme_dev *dev,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t width);
-
- struct vme_resource * vme_slave_request(struct vme_dev *dev,
- vme_address_t aspace, vme_cycle_t cycle);
-
- struct vme_resource *vme_dma_request(struct vme_dev *dev,
- vme_dma_route_t route);
-
-For slave windows these attributes are split into those of type 'vme_address_t'
-and 'vme_cycle_t'. Master windows add a further set of attributes
-'vme_cycle_t'. These attributes are defined as bitmasks and as such any
-combination of the attributes can be requested for a single window, the core
-will assign a window that meets the requirements, returning a pointer of type
-vme_resource that should be used to identify the allocated resource when it is
-used. For DMA controllers, the request function requires the potential
-direction of any transfers to be provided in the route attributes. This is
-typically VME-to-MEM and/or MEM-to-VME, though some hardware can support
-VME-to-VME and MEM-to-MEM transfers as well as test pattern generation. If an
-unallocated window fitting the requirements can not be found a NULL pointer
-will be returned.
+ u32 aspace, u32 cycle, u32 width);
+
+ struct vme_resource * vme_slave_request(struct vme_dev *dev, u32 aspace,
+ u32 cycle);
+
+ struct vme_resource *vme_dma_request(struct vme_dev *dev, u32 route);
+
+For slave windows these attributes are split into the VME address spaces that
+need to be accessed in 'aspace' and VME bus cycle types required in 'cycle'.
+Master windows add a further set of attributes in 'width' specifying the
+required data transfer widths. These attributes are defined as bitmasks and as
+such any combination of the attributes can be requested for a single window,
+the core will assign a window that meets the requirements, returning a pointer
+of type vme_resource that should be used to identify the allocated resource
+when it is used. For DMA controllers, the request function requires the
+potential direction of any transfers to be provided in the route attributes.
+This is typically VME-to-MEM and/or MEM-to-VME, though some hardware can
+support VME-to-VME and MEM-to-MEM transfers as well as test pattern generation.
+If an unallocated window fitting the requirements can not be found a NULL
+pointer will be returned.
Functions are also provided to free window allocations once they are no longer
required. These functions should be passed the pointer to the resource provided
@@ -133,12 +133,12 @@ Once a master window has been assigned the following functions can be used to
configure it and retrieve the current settings:
int vme_master_set (struct vme_resource *res, int enabled,
- unsigned long long base, unsigned long long size,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t width);
+ unsigned long long base, unsigned long long size, u32 aspace,
+ u32 cycle, u32 width);
int vme_master_get (struct vme_resource *res, int *enabled,
- unsigned long long *base, unsigned long long *size,
- vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *width);
+ unsigned long long *base, unsigned long long *size, u32 *aspace,
+ u32 *cycle, u32 *width);
The address spaces, transfer widths and cycle types are the same as described
under resource management, however some of the options are mutually exclusive.
@@ -189,11 +189,11 @@ configure it and retrieve the current settings:
int vme_slave_set (struct vme_resource *res, int enabled,
unsigned long long base, unsigned long long size,
- dma_addr_t mem, vme_address_t aspace, vme_cycle_t cycle);
+ dma_addr_t mem, u32 aspace, u32 cycle);
int vme_slave_get (struct vme_resource *res, int *enabled,
unsigned long long *base, unsigned long long *size,
- dma_addr_t *mem, vme_address_t *aspace, vme_cycle_t *cycle);
+ dma_addr_t *mem, u32 *aspace, u32 *cycle);
The address spaces, transfer widths and cycle types are the same as described
under resource management, however some of the options are mutually exclusive.
@@ -273,8 +273,7 @@ and pattern sources and destinations (where appropriate):
Pattern source:
- struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern,
- vme_pattern_t type);
+ struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type);
PCI source or destination:
@@ -283,7 +282,7 @@ PCI source or destination:
VME source or destination:
struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long base,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t width);
+ u32 aspace, u32 cycle, u32 width);
The following function should be used to free an attribute:
@@ -366,10 +365,10 @@ Once a bank of location monitors has been allocated, the following functions
are provided to configure the location and mode of the location monitor:
int vme_lm_set(struct vme_resource *res, unsigned long long base,
- vme_address_t aspace, vme_cycle_t cycle);
+ u32 aspace, u32 cycle);
int vme_lm_get(struct vme_resource *res, unsigned long long *base,
- vme_address_t *aspace, vme_cycle_t *cycle);
+ u32 *aspace, u32 *cycle);
Location Monitor Use
diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/staging/vme/vme_bridge.h
index c2deda2c38df..934949abd745 100644
--- a/drivers/staging/vme/vme_bridge.h
+++ b/drivers/staging/vme/vme_bridge.h
@@ -15,9 +15,9 @@ struct vme_master_resource {
spinlock_t lock;
int locked;
int number;
- vme_address_t address_attr;
- vme_cycle_t cycle_attr;
- vme_width_t width_attr;
+ u32 address_attr;
+ u32 cycle_attr;
+ u32 width_attr;
struct resource bus_resource;
void __iomem *kern_base;
};
@@ -28,13 +28,13 @@ struct vme_slave_resource {
struct mutex mtx;
int locked;
int number;
- vme_address_t address_attr;
- vme_cycle_t cycle_attr;
+ u32 address_attr;
+ u32 cycle_attr;
};
struct vme_dma_pattern {
u32 pattern;
- vme_pattern_t type;
+ u32 type;
};
struct vme_dma_pci {
@@ -43,9 +43,9 @@ struct vme_dma_pci {
struct vme_dma_vme {
unsigned long long address;
- vme_address_t aspace;
- vme_cycle_t cycle;
- vme_width_t dwidth;
+ u32 aspace;
+ u32 cycle;
+ u32 dwidth;
};
struct vme_dma_list {
@@ -63,7 +63,7 @@ struct vme_dma_resource {
int number;
struct list_head pending;
struct list_head running;
- vme_dma_route_t route_attr;
+ u32 route_attr;
};
struct vme_lm_resource {
@@ -122,17 +122,16 @@ struct vme_bridge {
/* Slave Functions */
int (*slave_get) (struct vme_slave_resource *, int *,
unsigned long long *, unsigned long long *, dma_addr_t *,
- vme_address_t *, vme_cycle_t *);
+ u32 *, u32 *);
int (*slave_set) (struct vme_slave_resource *, int, unsigned long long,
- unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t);
+ unsigned long long, dma_addr_t, u32, u32);
/* Master Functions */
int (*master_get) (struct vme_master_resource *, int *,
- unsigned long long *, unsigned long long *, vme_address_t *,
- vme_cycle_t *, vme_width_t *);
+ unsigned long long *, unsigned long long *, u32 *, u32 *,
+ u32 *);
int (*master_set) (struct vme_master_resource *, int,
- unsigned long long, unsigned long long, vme_address_t,
- vme_cycle_t, vme_width_t);
+ unsigned long long, unsigned long long, u32, u32, u32);
ssize_t (*master_read) (struct vme_master_resource *, void *, size_t,
loff_t);
ssize_t (*master_write) (struct vme_master_resource *, void *, size_t,
@@ -151,10 +150,9 @@ struct vme_bridge {
int (*irq_generate) (struct vme_bridge *, int, int);
/* Location monitor functions */
- int (*lm_set) (struct vme_lm_resource *, unsigned long long,
- vme_address_t, vme_cycle_t);
- int (*lm_get) (struct vme_lm_resource *, unsigned long long *,
- vme_address_t *, vme_cycle_t *);
+ int (*lm_set) (struct vme_lm_resource *, unsigned long long, u32, u32);
+ int (*lm_get) (struct vme_lm_resource *, unsigned long long *, u32 *,
+ u32 *);
int (*lm_attach) (struct vme_lm_resource *, int, void (*callback)(int));
int (*lm_detach) (struct vme_lm_resource *, int);
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index d8dd7846447d..3e8283c2dc73 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -3153,11 +3153,7 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
break;
case SIOCGIWNWID: //0x8b03 support
- #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
- rc = iwctl_giwnwid(dev, NULL, &(wrq->u.nwid), NULL);
- #else
- rc = -EOPNOTSUPP;
- #endif
+ rc = -EOPNOTSUPP;
break;
// Set frequency/channel
diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c
index 432a20993c6e..7fd5cc5a55f6 100644
--- a/drivers/staging/vt6655/ioctl.c
+++ b/drivers/staging/vt6655/ioctl.c
@@ -300,6 +300,10 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
result = -EFAULT;
break;
}
+ if (sList.uItem > (ULONG_MAX - sizeof(SBSSIDList)) / sizeof(SBSSIDItem)) {
+ result = -EINVAL;
+ break;
+ }
pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), (int)GFP_ATOMIC);
if (pList == NULL) {
result = -ENOMEM;
@@ -571,6 +575,10 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
result = -EFAULT;
break;
}
+ if (sNodeList.uItem > (ULONG_MAX - sizeof(SNodeList)) / sizeof(SNodeItem)) {
+ result = -EINVAL;
+ break;
+ }
pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
if (pNodeList == NULL) {
result = -ENOMEM;
diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c
index 5e425d1476b8..87288db21785 100644
--- a/drivers/staging/vt6655/iwctl.c
+++ b/drivers/staging/vt6655/iwctl.c
@@ -151,18 +151,6 @@ int iwctl_giwname(struct net_device *dev,
return 0;
}
-int iwctl_giwnwid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq,
- char *extra)
-{
- //wrq->value = 0x100;
- //wrq->disabled = 0;
- //wrq->fixed = 1;
- //return 0;
- return -EOPNOTSUPP;
-}
-
/*
* Wireless Handler : set scan
*/
diff --git a/drivers/staging/vt6655/iwctl.h b/drivers/staging/vt6655/iwctl.h
index 3096de0ba1bd..d224f913a624 100644
--- a/drivers/staging/vt6655/iwctl.h
+++ b/drivers/staging/vt6655/iwctl.h
@@ -79,11 +79,6 @@ int iwctl_giwname(struct net_device *dev,
char *wrq,
char *extra);
-int iwctl_giwnwid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq,
- char *extra) ;
-
int iwctl_giwsens(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *wrq,
diff --git a/drivers/staging/vt6656/80211mgr.c b/drivers/staging/vt6656/80211mgr.c
index fceec4999c36..39f98423dc02 100644
--- a/drivers/staging/vt6656/80211mgr.c
+++ b/drivers/staging/vt6656/80211mgr.c
@@ -224,8 +224,6 @@ vMgrDecodeBeacon(
}
pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
}
-
- return;
}
@@ -248,8 +246,6 @@ vMgrEncodeIBSSATIM(
{
pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
pFrame->len = WLAN_HDR_ADDR3_LEN;
-
- return;
}
@@ -270,8 +266,6 @@ vMgrDecodeIBSSATIM(
)
{
pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
- return;
}
@@ -298,8 +292,6 @@ vMgrEncodeDisassociation(
pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+ WLAN_DISASSOC_OFF_REASON);
pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DISASSOC_OFF_REASON + sizeof(*(pFrame->pwReason));
-
- return;
}
@@ -324,8 +316,6 @@ vMgrDecodeDisassociation(
/* Fixed Fields */
pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+ WLAN_DISASSOC_OFF_REASON);
-
- return;
}
/*+
@@ -352,7 +342,6 @@ vMgrEncodeAssocRequest(
pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+ WLAN_ASSOCREQ_OFF_LISTEN_INT);
pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCREQ_OFF_LISTEN_INT + sizeof(*(pFrame->pwListenInterval));
- return;
}
@@ -418,7 +407,6 @@ vMgrDecodeAssocRequest(
}
pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
}
- return;
}
/*+
@@ -448,8 +436,6 @@ vMgrEncodeAssocResponse(
+ WLAN_ASSOCRESP_OFF_AID);
pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCRESP_OFF_AID
+ sizeof(*(pFrame->pwAid));
-
- return;
}
@@ -491,10 +477,8 @@ vMgrDecodeAssocResponse(
if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) {
pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pFrame->pExtSuppRates=[%p].\n", pItem);
- } else {
+ } else
pFrame->pExtSuppRates = NULL;
- }
- return;
}
@@ -524,8 +508,6 @@ vMgrEncodeReassocRequest(
pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+ WLAN_REASSOCREQ_OFF_CURR_AP);
pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCREQ_OFF_CURR_AP + sizeof(*(pFrame->pAddrCurrAP));
-
- return;
}
@@ -578,10 +560,9 @@ vMgrDecodeReassocRequest(
pFrame->pRSN = (PWLAN_IE_RSN)pItem;
break;
case WLAN_EID_RSN_WPA:
- if (pFrame->pRSNWPA == NULL) {
+ if (pFrame->pRSNWPA == NULL)
if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE)
pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem;
- }
break;
case WLAN_EID_EXTSUPP_RATES:
@@ -595,7 +576,6 @@ vMgrDecodeReassocRequest(
}
pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
}
- return;
}
@@ -619,7 +599,6 @@ vMgrEncodeProbeRequest(
{
pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
pFrame->len = WLAN_HDR_ADDR3_LEN;
- return;
}
/*+
@@ -670,7 +649,6 @@ vMgrDecodeProbeRequest(
pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
}
- return;
}
@@ -703,8 +681,6 @@ vMgrEncodeProbeResponse(
pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_PROBERESP_OFF_CAP_INFO +
sizeof(*(pFrame->pwCapInfo));
-
- return;
}
@@ -818,7 +794,6 @@ vMgrDecodeProbeResponse(
pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
}
- return;
}
@@ -848,7 +823,6 @@ vMgrEncodeAuthen(
pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+ WLAN_AUTHEN_OFF_STATUS);
pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_AUTHEN_OFF_STATUS + sizeof(*(pFrame->pwStatus));
- return;
}
@@ -886,7 +860,6 @@ vMgrDecodeAuthen(
if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE))
pFrame->pChallenge = (PWLAN_IE_CHALLENGE)pItem;
- return;
}
@@ -912,7 +885,6 @@ vMgrEncodeDeauthen(
pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+ WLAN_DEAUTHEN_OFF_REASON);
pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DEAUTHEN_OFF_REASON + sizeof(*(pFrame->pwReason));
- return;
}
@@ -937,7 +909,6 @@ vMgrDecodeDeauthen(
/* Fixed Fields */
pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+ WLAN_DEAUTHEN_OFF_REASON);
- return;
}
@@ -968,7 +939,6 @@ vMgrEncodeReassocResponse(
+ WLAN_REASSOCRESP_OFF_AID);
pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCRESP_OFF_AID + sizeof(*(pFrame->pwAid));
- return;
}
@@ -1010,5 +980,4 @@ vMgrDecodeReassocResponse(
if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES))
pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
- return;
}
diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
index 0d11147f91c1..06f27f624db4 100644
--- a/drivers/staging/vt6656/baseband.c
+++ b/drivers/staging/vt6656/baseband.c
@@ -932,30 +932,8 @@ BBvCaculateParameter (
void
BBvSetAntennaMode (PSDevice pDevice, BYTE byAntennaMode)
{
- //{{ RobertYu: 20041124, ABG Mode, VC1/VC2 define, make the ANT_A, ANT_B inverted
- /*if ( (pDevice->byRFType == RF_MAXIM2829) ||
- (pDevice->byRFType == RF_UW2452) ||
- (pDevice->byRFType == RF_AIROHA7230) ) { // RobertYu: 20041210, 20050104
-
- switch (byAntennaMode) {
- case ANT_TXA:
- byAntennaMode = ANT_TXB;
- break;
- case ANT_TXB:
- byAntennaMode = ANT_TXA;
- break;
- case ANT_RXA:
- byAntennaMode = ANT_RXB;
- break;
- case ANT_RXB:
- byAntennaMode = ANT_RXA;
- break;
- }
- }*/
-
switch (byAntennaMode) {
case ANT_TXA:
- break;
case ANT_TXB:
break;
case ANT_RXA:
@@ -1249,8 +1227,7 @@ void BBvLoopbackOff (PSDevice pDevice)
// Set the CR33 Bit2 to disable internal Loopback.
ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x21, &byData);//CR33
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x21, (BYTE)(byData & 0xFE));//CR33
- }
- else { // OFDM
+ } else { /* OFDM */
ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x9A, &byData);//CR154
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x9A, (BYTE)(byData & 0xFE));//CR154
}
@@ -1277,19 +1254,16 @@ BBvSetShortSlotTime (PSDevice pDevice)
{
BYTE byBBVGA=0;
- if (pDevice->bShortSlotTime) {
+ if (pDevice->bShortSlotTime)
pDevice->byBBRxConf &= 0xDF;//1101 1111
- } else {
+ else
pDevice->byBBRxConf |= 0x20;//0010 0000
- }
ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0xE7, &byBBVGA);
- if (byBBVGA == pDevice->abyBBVGA[0]) {
+ if (byBBVGA == pDevice->abyBBVGA[0])
pDevice->byBBRxConf |= 0x20;//0010 0000
- }
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0A, pDevice->byBBRxConf);
-
}
@@ -1299,13 +1273,11 @@ void BBvSetVGAGainOffset(PSDevice pDevice, BYTE byData)
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xE7, byData);
// patch for 3253B0 Baseband with Cardbus module
- if (byData == pDevice->abyBBVGA[0]) {
- pDevice->byBBRxConf |= 0x20;//0010 0000
- } else if (pDevice->bShortSlotTime) {
- pDevice->byBBRxConf &= 0xDF;//1101 1111
- } else {
- pDevice->byBBRxConf |= 0x20;//0010 0000
- }
+ if (pDevice->bShortSlotTime)
+ pDevice->byBBRxConf &= 0xDF; /* 1101 1111 */
+ else
+ pDevice->byBBRxConf |= 0x20; /* 0010 0000 */
+
ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0A, pDevice->byBBRxConf);//CR10
}
@@ -1365,15 +1337,14 @@ static unsigned long s_ulGetLowSQ3(PSDevice pDevice)
unsigned long ulMaxPacket;
ulMaxPacket = pDevice->aulPktNum[RATE_54M];
- if ( pDevice->aulPktNum[RATE_54M] != 0 ) {
+ if (pDevice->aulPktNum[RATE_54M] != 0)
ulSQ3 = pDevice->aulSQ3Val[RATE_54M] / pDevice->aulPktNum[RATE_54M];
- }
- for ( ii=RATE_48M;ii>=RATE_6M;ii-- ) {
- if ( pDevice->aulPktNum[ii] > ulMaxPacket ) {
+
+ for (ii = RATE_48M; ii >= RATE_6M; ii--)
+ if (pDevice->aulPktNum[ii] > ulMaxPacket) {
ulMaxPacket = pDevice->aulPktNum[ii];
ulSQ3 = pDevice->aulSQ3Val[ii] / pDevice->aulPktNum[ii];
}
- }
return ulSQ3;
}
@@ -1392,7 +1363,7 @@ static unsigned long s_ulGetRatio(PSDevice pDevice)
ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
ulRatio += TOP_RATE_54M;
}
- for ( ii=RATE_48M;ii>=RATE_1M;ii-- ) {
+ for (ii = RATE_48M; ii >= RATE_1M; ii--)
if ( pDevice->aulPktNum[ii] > ulMaxPacket ) {
ulPacketNum = 0;
for ( jj=RATE_54M;jj>=ii;jj--)
@@ -1402,8 +1373,6 @@ static unsigned long s_ulGetRatio(PSDevice pDevice)
ulMaxPacket = pDevice->aulPktNum[ii];
}
- }
-
return ulRatio;
}
@@ -1589,7 +1558,6 @@ void TimerSQ3CallBack(void *hDeviceContext)
spin_unlock_irq(&pDevice->lock);
- return;
}
@@ -1637,7 +1605,6 @@ void TimerSQ3Tmax3CallBack(void *hDeviceContext)
add_timer(&pDevice->TimerSQ3Tmax1);
spin_unlock_irq(&pDevice->lock);
- return;
}
void
diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c
index af006df4c8e9..32c67ed8435a 100644
--- a/drivers/staging/vt6656/bssdb.c
+++ b/drivers/staging/vt6656/bssdb.c
@@ -216,26 +216,6 @@ PKnownBSS BSSpSearchBSSList(void *hDeviceContext,
continue;
}
}
-/*
- if (pMgmt->eAuthenMode < WMAC_AUTH_WPA) {
- if (pCurrBSS->bWPAValid == TRUE) {
- // WPA AP will reject connection of station without WPA enable.
- continue;
- }
- } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
- (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)) {
- if (pCurrBSS->bWPAValid == FALSE) {
- // station with WPA enable can't join NonWPA AP.
- continue;
- }
- } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
- (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {
- if (pCurrBSS->bWPA2Valid == FALSE) {
- // station with WPA2 enable can't join NonWPA2 AP.
- continue;
- }
- }
-*/
pMgmt->pSameBSS[jj].uChannel = pCurrBSS->uChannel;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSpSearchBSSList pSelect1[%02X %02X %02X-%02X %02X %02X]\n",*pCurrBSS->abyBSSID,*(pCurrBSS->abyBSSID+1),*(pCurrBSS->abyBSSID+2),*(pCurrBSS->abyBSSID+3),*(pCurrBSS->abyBSSID+4),*(pCurrBSS->abyBSSID+5));
@@ -300,18 +280,11 @@ void BSSvClearBSSList(void *hDeviceContext, BOOL bKeepCurrBSSID)
continue;
}
}
-/*
- if ((pMgmt->sBSSList[ii].bActive) && (pMgmt->sBSSList[ii].uClearCount < BSS_CLEAR_COUNT)) {
- pMgmt->sBSSList[ii].uClearCount ++;
- continue;
- }
-*/
- pMgmt->sBSSList[ii].bActive = FALSE;
+
+ pMgmt->sBSSList[ii].bActive = FALSE;
memset(&pMgmt->sBSSList[ii], 0, sizeof(KnownBSS));
}
BSSvClearAnyBSSJoinRecord(pDevice);
-
- return;
}
@@ -524,46 +497,6 @@ BOOL BSSbInsertToBSSList(void *hDeviceContext,
pBSSList->ldBmAverage[ii] = 0;
}
-/*
- if ((pIE_Country != NULL) &&
- (pMgmt->b11hEnable == TRUE)) {
- CARDvSetCountryInfo(pMgmt->pAdapter,
- pBSSList->eNetworkTypeInUse,
- pIE_Country);
- }
-
- if ((bParsingQuiet == TRUE) && (pIE_Quiet != NULL)) {
- if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) &&
- (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) {
- // valid EID
- if (pQuiet == NULL) {
- pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
- CARDbSetQuiet( pMgmt->pAdapter,
- TRUE,
- pQuiet->byQuietCount,
- pQuiet->byQuietPeriod,
- *((PWORD)pQuiet->abyQuietDuration),
- *((PWORD)pQuiet->abyQuietOffset)
- );
- } else {
- pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
- CARDbSetQuiet( pMgmt->pAdapter,
- FALSE,
- pQuiet->byQuietCount,
- pQuiet->byQuietPeriod,
- *((PWORD)pQuiet->abyQuietDuration),
- *((PWORD)pQuiet->abyQuietOffset)
- );
- }
- }
- }
-
- if ((bParsingQuiet == TRUE) &&
- (pQuiet != NULL)) {
- CARDbStartQuiet(pMgmt->pAdapter);
- }
-*/
-
pBSSList->uIELength = uIELength;
if (pBSSList->uIELength > WLAN_BEACON_FR_MAXLEN)
pBSSList->uIELength = WLAN_BEACON_FR_MAXLEN;
@@ -609,8 +542,6 @@ BOOL BSSbUpdateToBSSList(void *hDeviceContext,
PSRxMgmtPacket pRxPacket = (PSRxMgmtPacket)pRxPacketContext;
signed long ldBm, ldBmSum;
BOOL bParsingQuiet = FALSE;
- // BYTE abyTmpSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-
if (pBSSList == NULL)
return FALSE;
@@ -622,7 +553,6 @@ BOOL BSSbUpdateToBSSList(void *hDeviceContext,
pBSSList->wCapInfo = cpu_to_le16(wCapInfo);
pBSSList->uClearCount = 0;
pBSSList->uChannel = byCurrChannel;
-// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSbUpdateToBSSList: pBSSList->uChannel: %d\n", pBSSList->uChannel);
if (pSSID->len > WLAN_SSID_MAXLEN)
pSSID->len = WLAN_SSID_MAXLEN;
@@ -809,7 +739,6 @@ void BSSvCreateOneNode(void *hDeviceContext, unsigned int *puNodeIndex)
pMgmt->sNodeDBTable[*puNodeIndex].byAuthSequence = 0;
pMgmt->sNodeDBTable[*puNodeIndex].wEnQueueCnt = 0;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create node index = %d\n", ii);
- return;
};
@@ -840,8 +769,6 @@ void BSSvRemoveOneNode(void *hDeviceContext, unsigned int uNodeIndex)
memset(&pMgmt->sNodeDBTable[uNodeIndex], 0, sizeof(KnownNodeDB));
// clear tx bit map
pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[uNodeIndex].wAID >> 3] &= ~byMask[pMgmt->sNodeDBTable[uNodeIndex].wAID & 7];
-
- return;
};
/*+
*
@@ -1054,10 +981,6 @@ if((pMgmt->eCurrState!=WMAC_STATE_ASSOC) &&
// Rate fallback check
if (!pDevice->bFixRate) {
-/*
- if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (ii == 0))
- RATEvTxRateFallBack(pDevice, &(pMgmt->sNodeDBTable[ii]));
-*/
if (ii > 0) {
// ii = 0 for multicast node (AP & Adhoc)
RATEvTxRateFallBack((void *)pDevice,
@@ -1152,7 +1075,6 @@ if((pMgmt->eCurrState!=WMAC_STATE_ASSOC) &&
(pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) {
if (pMgmt->sNodeDBTable[0].bActive) { // Assoc with BSS
- // DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Callback inactive Count = [%d]\n", pMgmt->sNodeDBTable[0].uInActiveCount);
if (pDevice->bUpdateBBVGA) {
/* s_vCheckSensitivity((void *) pDevice); */
@@ -1194,7 +1116,6 @@ if((pMgmt->eCurrState!=WMAC_STATE_ASSOC) &&
pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
}
#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
- // if(pDevice->bWPASuppWextEnabled == TRUE)
{
union iwreq_data wrqu;
memset(&wrqu, 0, sizeof (wrqu));
@@ -1223,7 +1144,6 @@ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bIsRoaming %d, !\n", pDevice->bIsRoaming );
pDevice->uIsroamingTime = 0;
pDevice->bRoaming = FALSE;
-// if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
wpahdr = (viawget_wpa_header *)pDevice->skb->data;
wpahdr->type = VIAWGET_CCKM_ROAM_MSG;
wpahdr->resp_ie_len = 0;
@@ -1237,7 +1157,6 @@ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bIsRoaming %d, !\n", pDevice->bIsRoaming );
netif_rx(pDevice->skb);
pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-// }
}
else if ((pDevice->bRoaming == FALSE)&&(pDevice->bIsRoaming == TRUE)) {
pDevice->uIsroamingTime++;
@@ -1315,7 +1234,6 @@ else {
pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ);
add_timer(&pMgmt->sTimerSecondCallback);
- return;
}
/*+
@@ -1364,7 +1282,6 @@ void BSSvUpdateNodeTxCounter(void *hDeviceContext,
// Only Unicast using support rates
if (wFIFOCtl & FIFOCTL_NEEDACK) {
- //DBG_PRN_GRP21(("Device %08X, wRate %04X, byTSR %02X\n", hDeviceContext, wRate, byTSR));
if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) {
pMgmt->sNodeDBTable[0].uTxAttempts += 1;
if ( !(byTSR & (TSR_TMO | TSR_RETRYTMO))) {
@@ -1475,10 +1392,6 @@ void BSSvUpdateNodeTxCounter(void *hDeviceContext,
}
}
}
-
- return;
-
-
}
/*+
@@ -1519,8 +1432,6 @@ void BSSvClearNodeDBTable(void *hDeviceContext,
memset(&pMgmt->sNodeDBTable[ii], 0, sizeof(KnownNodeDB));
}
}
-
- return;
};
void s_vCheckSensitivity(void *hDeviceContext)
@@ -1584,7 +1495,6 @@ RxOkRatio = (RxCnt < 6) ? 2000:((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt);
//decide link quality
if(pDevice->bLinkPass !=TRUE)
{
- // printk("s_uCalculateLinkQual-->Link disconnect and Poor quality**\n");
pDevice->scStatistic.LinkQuality = 0;
pDevice->scStatistic.SignalStren = 0;
}
@@ -1608,7 +1518,6 @@ else
pDevice->scStatistic.TxFailCount = 0;
pDevice->scStatistic.TxNoRetryOkCount = 0;
pDevice->scStatistic.TxRetryOkCount = 0;
- return;
}
void BSSvClearAnyBSSJoinRecord(void *hDeviceContext)
@@ -1617,10 +1526,8 @@ void BSSvClearAnyBSSJoinRecord(void *hDeviceContext)
PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
unsigned int ii;
- for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+ for (ii = 0; ii < MAX_BSS_NUM; ii++)
pMgmt->sBSSList[ii].bSelected = FALSE;
- }
- return;
}
void s_vCheckPreEDThreshold(void *hDeviceContext)
@@ -1637,6 +1544,5 @@ void s_vCheckPreEDThreshold(void *hDeviceContext)
BBvUpdatePreEDThreshold(pDevice, FALSE);
}
}
- return;
}
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c
index a49053bd7c65..9d09e9fd8e18 100644
--- a/drivers/staging/vt6656/card.c
+++ b/drivers/staging/vt6656/card.c
@@ -91,15 +91,10 @@ const WORD cwRXBCNTSFOff[MAX_RATE] =
* uConnectionChannel - Channel to be set
* Out:
* none
- *
- * Return Value: TRUE if succeeded; FALSE if failed.
- *
*/
-BOOL CARDbSetMediaChannel(void *pDeviceHandler, unsigned int uConnectionChannel)
+void CARDbSetMediaChannel(void *pDeviceHandler, unsigned int uConnectionChannel)
{
PSDevice pDevice = (PSDevice) pDeviceHandler;
-BOOL bResult = TRUE;
-
if (pDevice->byBBType == BB_TYPE_11A) { // 15 ~ 38
if ((uConnectionChannel < (CB_MAX_CHANNEL_24G+1)) || (uConnectionChannel > CB_MAX_CHANNEL))
@@ -140,7 +135,6 @@ BOOL bResult = TRUE;
RFbRawSetPower(pDevice, pDevice->abyCCKPwrTbl[uConnectionChannel-1], RATE_1M);
}
ControlvWriteByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_CHANNEL,(BYTE)(uConnectionChannel|0x80));
- return(bResult);
}
/*
@@ -607,7 +601,7 @@ BYTE ii;
* Return Value: TRUE if succeeded; FALSE if failed.
*
*/
-BOOL CARDbAddBasicRate(void *pDeviceHandler, WORD wRateIdx)
+void CARDbAddBasicRate(void *pDeviceHandler, WORD wRateIdx)
{
PSDevice pDevice = (PSDevice) pDeviceHandler;
WORD wRate = (WORD)(1<<wRateIdx);
@@ -616,8 +610,6 @@ WORD wRate = (WORD)(1<<wRateIdx);
//Determines the highest basic rate.
CARDvUpdateBasicTopRate(pDevice);
-
- return(TRUE);
}
BOOL CARDbIsOFDMinBasicRate(void *pDeviceHandler)
@@ -1090,7 +1082,7 @@ CARDbChannelSwitch (
if (byCount == 0) {
pDevice->sMgmtObj.uCurrChannel = byNewChannel;
- bResult = CARDbSetMediaChannel(pDevice, byNewChannel);
+ CARDbSetMediaChannel(pDevice, byNewChannel);
return bResult;
}
diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h
index 6c91343d0d14..9cf71a3d8801 100644
--- a/drivers/staging/vt6656/card.h
+++ b/drivers/staging/vt6656/card.h
@@ -60,12 +60,12 @@ typedef enum _CARD_OP_MODE {
/*--------------------- Export Functions --------------------------*/
-BOOL CARDbSetMediaChannel(void *pDeviceHandler,
+void CARDbSetMediaChannel(void *pDeviceHandler,
unsigned int uConnectionChannel);
void CARDvSetRSPINF(void *pDeviceHandler, BYTE byBBType);
void vUpdateIFS(void *pDeviceHandler);
void CARDvUpdateBasicTopRate(void *pDeviceHandler);
-BOOL CARDbAddBasicRate(void *pDeviceHandler, WORD wRateIdx);
+void CARDbAddBasicRate(void *pDeviceHandler, WORD wRateIdx);
BOOL CARDbIsOFDMinBasicRate(void *pDeviceHandler);
void CARDvAdjustTSF(void *pDeviceHandler, BYTE byRxRate,
QWORD qwBSSTimestamp, QWORD qwLocalTSF);
diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c
index c95833ac58e0..0a114231145f 100644
--- a/drivers/staging/vt6656/int.c
+++ b/drivers/staging/vt6656/int.c
@@ -92,9 +92,8 @@ void INTvWorkItem(void *Context)
spin_unlock_irq(&pDevice->lock);
}
-int INTnsProcessData(PSDevice pDevice)
+void INTnsProcessData(PSDevice pDevice)
{
- int status = STATUS_SUCCESS;
PSINTData pINTData;
PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
struct net_device_stats *pStats = &pDevice->stats;
@@ -218,6 +217,4 @@ int INTnsProcessData(PSDevice pDevice)
pDevice->scStatistic.ullTxBroadcastBytes;
pStats->tx_errors = pDevice->scStatistic.dwTsrErr;
pStats->tx_dropped = pDevice->scStatistic.dwTsrErr;
-
- return status;
}
diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h
index 3176c8d08d6d..a5d96b968176 100644
--- a/drivers/staging/vt6656/int.h
+++ b/drivers/staging/vt6656/int.h
@@ -68,6 +68,6 @@ SINTData, *PSINTData;
/*--------------------- Export Functions --------------------------*/
void INTvWorkItem(void *Context);
-int INTnsProcessData(PSDevice pDevice);
+void INTnsProcessData(PSDevice pDevice);
#endif /* __INT_H__ */
diff --git a/drivers/staging/vt6656/ioctl.c b/drivers/staging/vt6656/ioctl.c
index 49390026dea3..1463d76895f0 100644
--- a/drivers/staging/vt6656/ioctl.c
+++ b/drivers/staging/vt6656/ioctl.c
@@ -295,6 +295,10 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
result = -EFAULT;
break;
}
+ if (sList.uItem > (ULONG_MAX - sizeof(SBSSIDList)) / sizeof(SBSSIDItem)) {
+ result = -EINVAL;
+ break;
+ }
pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), (int)GFP_ATOMIC);
if (pList == NULL) {
result = -ENOMEM;
@@ -557,6 +561,10 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
result = -EFAULT;
break;
}
+ if (sNodeList.uItem > (ULONG_MAX - sizeof(SNodeList)) / sizeof(SNodeItem)) {
+ result = -ENOMEM;
+ break;
+ }
pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
if (pNodeList == NULL) {
result = -ENOMEM;
diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c
index 2121205a912b..ecfda5272fa1 100644
--- a/drivers/staging/vt6656/iwctl.c
+++ b/drivers/staging/vt6656/iwctl.c
@@ -128,17 +128,6 @@ int iwctl_giwname(struct net_device *dev,
return 0;
}
-int iwctl_giwnwid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq,
- char *extra)
-{
- //wrq->value = 0x100;
- //wrq->disabled = 0;
- //wrq->fixed = 1;
- //return 0;
- return -EOPNOTSUPP;
-}
/*
* Wireless Handler : set scan
*/
@@ -1939,7 +1928,6 @@ static const iw_handler iwctl_handler[] =
(iw_handler) iwctl_commit, // SIOCSIWCOMMIT
(iw_handler) iwctl_giwname, // SIOCGIWNAME
(iw_handler) NULL, // SIOCSIWNWID
- (iw_handler) NULL, // SIOCGIWNWID
(iw_handler) iwctl_siwfreq, // SIOCSIWFREQ
(iw_handler) iwctl_giwfreq, // SIOCGIWFREQ
(iw_handler) iwctl_siwmode, // SIOCSIWMODE
diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h
index cc48954783fc..10a240e65012 100644
--- a/drivers/staging/vt6656/iwctl.h
+++ b/drivers/staging/vt6656/iwctl.h
@@ -77,11 +77,6 @@ int iwctl_giwname(struct net_device *dev,
char *wrq,
char *extra);
-int iwctl_giwnwid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq,
- char *extra) ;
-
int iwctl_giwsens(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *wrq,
diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c
index 26c19d1408c4..af4a29d14775 100644
--- a/drivers/staging/vt6656/mac.c
+++ b/drivers/staging/vt6656/mac.c
@@ -133,10 +133,9 @@ void MACvWriteMultiAddr(PSDevice pDevice, unsigned int uByteIdx, BYTE byData)
* Out:
* none
*
- * Return Value: TRUE if success; otherwise FALSE
*
*/
-BOOL MACbShutdown (PSDevice pDevice)
+void MACbShutdown(PSDevice pDevice)
{
CONTROLnsRequestOutAsyn(pDevice,
MESSAGE_TYPE_MACSHUTDOWN,
@@ -145,7 +144,6 @@ BOOL MACbShutdown (PSDevice pDevice)
0,
NULL
);
- return TRUE;
}
void MACvSetBBType(PSDevice pDevice,BYTE byType)
diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h
index 491ff5ecd04b..147ac50218d3 100644
--- a/drivers/staging/vt6656/mac.h
+++ b/drivers/staging/vt6656/mac.h
@@ -422,7 +422,7 @@
void MACvSetMultiAddrByHash(PSDevice pDevice, BYTE byHashIdx);
void MACvWriteMultiAddr(PSDevice pDevice, unsigned int uByteIdx, BYTE byData);
-BOOL MACbShutdown(PSDevice pDevice);
+void MACbShutdown(PSDevice pDevice);
void MACvSetBBType(PSDevice pDevice, BYTE byType);
void MACvSetMISCFifo(PSDevice pDevice, WORD wOffset, DWORD dwData);
void MACvDisableKeyEntry(PSDevice pDevice, unsigned int uEntryIdx);
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 541f9aa8ef6d..6a708f447651 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -900,7 +900,7 @@ static BOOL device_alloc_bufs(PSDevice pDevice) {
}
// allocate rcb mem
- pDevice->pRCBMem = kmalloc((sizeof(RCB) * pDevice->cbRD), GFP_KERNEL);
+ pDevice->pRCBMem = kzalloc((sizeof(RCB) * pDevice->cbRD), GFP_KERNEL);
if (pDevice->pRCBMem == NULL) {
DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : alloc rx usb context failed\n", pDevice->dev->name);
goto free_tx;
@@ -912,7 +912,6 @@ static BOOL device_alloc_bufs(PSDevice pDevice) {
pDevice->FirstRecvMngList = NULL;
pDevice->LastRecvMngList = NULL;
pDevice->NumRecvFreeList = 0;
- memset(pDevice->pRCBMem, 0, (sizeof(RCB) * pDevice->cbRD));
pRCB = (PRCB) pDevice->pRCBMem;
for (ii = 0; ii < pDevice->cbRD; ii++) {
@@ -1618,15 +1617,8 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
break;
case SIOCSIWNWID:
- rc = -EOPNOTSUPP;
- break;
-
case SIOCGIWNWID: //0x8b03 support
- #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
- rc = iwctl_giwnwid(dev, NULL, &(wrq->u.nwid), NULL);
- #else
- rc = -EOPNOTSUPP;
- #endif
+ rc = -EOPNOTSUPP;
break;
// Set frequency/channel
diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c
index 1f1d98679171..2bd9b84ace8e 100644
--- a/drivers/staging/wlags49_h2/wl_pci.c
+++ b/drivers/staging/wlags49_h2/wl_pci.c
@@ -112,17 +112,10 @@ extern dbg_info_t *DbgInfo;
#endif // DBG
/* define the PCI device Table Cardname and id tables */
-enum hermes_pci_versions {
- CH_Agere_Systems_Mini_PCI_V1 = 0,
-};
-
static struct pci_device_id wl_pci_tbl[] __devinitdata = {
- { PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_0,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 },
- { PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_1,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 },
- { PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_0), },
+ { PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_1), },
+ { PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_2), },
{ } /* Terminating entry */
};
diff --git a/drivers/staging/xgifb/Makefile b/drivers/staging/xgifb/Makefile
index 3c8c7de9eadd..55e519905346 100644
--- a/drivers/staging/xgifb/Makefile
+++ b/drivers/staging/xgifb/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_FB_XGI) += xgifb.o
-xgifb-y := XGI_main_26.o vb_init.o vb_setmode.o vb_util.o vb_ext.o
+xgifb-y := XGI_main_26.o vb_init.o vb_setmode.o vb_util.o
diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
index 71aebe3e84d8..35f7b2a485e1 100644
--- a/drivers/staging/xgifb/XGI_main.h
+++ b/drivers/staging/xgifb/XGI_main.h
@@ -32,14 +32,10 @@
#endif
static DEFINE_PCI_DEVICE_TABLE(xgifb_pci_table) = {
- {PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_20, PCI_ANY_ID, PCI_ANY_ID,
- 0, 0, 0},
- {PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_27, PCI_ANY_ID, PCI_ANY_ID,
- 0, 0, 1},
- {PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_40, PCI_ANY_ID, PCI_ANY_ID,
- 0, 0, 2},
- {PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_42, PCI_ANY_ID, PCI_ANY_ID,
- 0, 0, 3},
+ {PCI_DEVICE(PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_20)},
+ {PCI_DEVICE(PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_27)},
+ {PCI_DEVICE(PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_40)},
+ {PCI_DEVICE(PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_42)},
{0}
};
@@ -128,7 +124,6 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
/* display status */
static int XGIfb_crt1off;
static int XGIfb_forcecrt1 = -1;
-static int XGIfb_userom ;
/* global flags */
static int XGIfb_tvmode;
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index 277e408c39c5..2502c49c9c5b 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -21,7 +21,6 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
-#include <linux/vmalloc.h>
#include <linux/vt_kern.h>
#include <linux/capability.h>
#include <linux/fs.h>
@@ -46,8 +45,7 @@
#define GPIOG_EN (1<<6)
#define GPIOG_READ (1<<1)
-#define XGIFB_ROM_SIZE 65536
-
+static char *forcecrt2type;
static char *mode;
static int vesa = -1;
static unsigned int refresh_rate;
@@ -159,7 +157,6 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
/* unsigned long temp = 0; */
int Clock;
- XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
@@ -199,7 +196,6 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
unsigned char sr_data, cr_data, cr_data2;
unsigned long cr_data3;
int A, B, C, D, E, F, temp, j;
- XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
ModeIdIndex, XGI_Pr);
@@ -387,7 +383,7 @@ static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
/* ------------------ Internal helper routines ----------------- */
-static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
+static int XGIfb_GetXG21DefaultLVDSModeIdx(struct xgifb_video_info *xgifb_info)
{
int found_mode = 0;
@@ -396,11 +392,11 @@ static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
found_mode = 0;
while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
&& (XGIbios_mode[XGIfb_mode_idx].xres
- <= XGI21_LCDCapList[0].LVDSHDE)) {
+ <= xgifb_info->lvds_data.LVDSHDE)) {
if ((XGIbios_mode[XGIfb_mode_idx].xres
- == XGI21_LCDCapList[0].LVDSHDE)
+ == xgifb_info->lvds_data.LVDSHDE)
&& (XGIbios_mode[XGIfb_mode_idx].yres
- == XGI21_LCDCapList[0].LVDSVDE)
+ == xgifb_info->lvds_data.LVDSVDE)
&& (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
found_mode = 1;
break;
@@ -456,51 +452,6 @@ invalid:
printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
}
-static int XGIfb_GetXG21LVDSData(struct xgifb_video_info *xgifb_info)
-{
- u8 tmp;
- void __iomem *data = xgifb_info->mmio_vbase + 0x20000;
- int i, j, k;
-
- tmp = xgifb_reg_get(XGISR, 0x1e);
- xgifb_reg_set(XGISR, 0x1e, tmp | 4);
-
- if ((readb(data) == 0x55) &&
- (readb(data + 1) == 0xAA) &&
- (readb(data + 0x65) & 0x1)) {
- i = readw(data + 0x316);
- j = readb(data + i - 1);
- if (j == 0xff)
- j = 1;
-
- k = 0;
- do {
- XGI21_LCDCapList[k].LVDS_Capability = readw(data + i);
- XGI21_LCDCapList[k].LVDSHT = readw(data + i + 2);
- XGI21_LCDCapList[k].LVDSVT = readw(data + i + 4);
- XGI21_LCDCapList[k].LVDSHDE = readw(data + i + 6);
- XGI21_LCDCapList[k].LVDSVDE = readw(data + i + 8);
- XGI21_LCDCapList[k].LVDSHFP = readw(data + i + 10);
- XGI21_LCDCapList[k].LVDSVFP = readw(data + i + 12);
- XGI21_LCDCapList[k].LVDSHSYNC = readw(data + i + 14);
- XGI21_LCDCapList[k].LVDSVSYNC = readw(data + i + 16);
- XGI21_LCDCapList[k].VCLKData1 = readb(data + i + 18);
- XGI21_LCDCapList[k].VCLKData2 = readb(data + i + 19);
- XGI21_LCDCapList[k].PSC_S1 = readb(data + i + 20);
- XGI21_LCDCapList[k].PSC_S2 = readb(data + i + 21);
- XGI21_LCDCapList[k].PSC_S3 = readb(data + i + 22);
- XGI21_LCDCapList[k].PSC_S4 = readb(data + i + 23);
- XGI21_LCDCapList[k].PSC_S5 = readb(data + i + 24);
- i += 25;
- j--;
- k++;
- } while ((j > 0) && (k < (sizeof(XGI21_LCDCapList)
- / sizeof(struct XGI21_LVDSCapStruct))));
- return 1;
- }
- return 0;
-}
-
static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex)
{
u16 xres, yres;
@@ -508,8 +459,8 @@ static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex)
if (xgifb_info->chip == XG21) {
if (xgifb_info->display2 == XGIFB_DISP_LCD) {
- xres = XGI21_LCDCapList[0].LVDSHDE;
- yres = XGI21_LCDCapList[0].LVDSVDE;
+ xres = xgifb_info->lvds_data.LVDSHDE;
+ yres = xgifb_info->lvds_data.LVDSVDE;
if (XGIbios_mode[myindex].xres > xres)
return -1;
if (XGIbios_mode[myindex].yres > yres)
@@ -1223,7 +1174,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
if (isactive) {
XGIfb_pre_setmode(xgifb_info);
- if (XGISetModeNew(hw_info,
+ if (XGISetModeNew(xgifb_info, hw_info,
XGIbios_mode[xgifb_info->mode_idx].mode_no)
== 0) {
printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n",
@@ -1794,17 +1745,16 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
XGIfb_crt1off = 0;
}
- if (XGIfb_crt2type != -1)
- /* TW: Override with option */
- xgifb_info->display2 = XGIfb_crt2type;
- else if (cr32 & XGI_VB_TV)
- xgifb_info->display2 = XGIFB_DISP_TV;
- else if (cr32 & XGI_VB_LCD)
- xgifb_info->display2 = XGIFB_DISP_LCD;
- else if (cr32 & XGI_VB_CRT2)
- xgifb_info->display2 = XGIFB_DISP_CRT;
- else
- xgifb_info->display2 = XGIFB_DISP_NONE;
+ if (!xgifb_info->display2_force) {
+ if (cr32 & XGI_VB_TV)
+ xgifb_info->display2 = XGIFB_DISP_TV;
+ else if (cr32 & XGI_VB_LCD)
+ xgifb_info->display2 = XGIFB_DISP_LCD;
+ else if (cr32 & XGI_VB_CRT2)
+ xgifb_info->display2 = XGIFB_DISP_CRT;
+ else
+ xgifb_info->display2 = XGIFB_DISP_NONE;
+ }
if (XGIfb_tvplug != -1)
/* PR/TW: Override with option */
@@ -1925,8 +1875,6 @@ static int __init XGIfb_setup(char *options)
XGIfb_crt2type = XGIFB_DISP_LCD;
} else if (!strncmp(this_opt, "noypan", 6)) {
XGIfb_ypan = 0;
- } else if (!strncmp(this_opt, "userom:", 7)) {
- XGIfb_userom = xgifb_optval(this_opt, 7);
} else {
mode = this_opt;
}
@@ -1934,35 +1882,12 @@ static int __init XGIfb_setup(char *options)
return 0;
}
-static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
-{
- void __iomem *rom_address;
- unsigned char *rom_copy;
- size_t rom_size;
-
- rom_address = pci_map_rom(dev, &rom_size);
- if (rom_address == NULL)
- return NULL;
-
- rom_copy = vzalloc(XGIFB_ROM_SIZE);
- if (rom_copy == NULL)
- goto done;
-
- rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
- memcpy_fromio(rom_copy, rom_address, rom_size);
-
-done:
- pci_unmap_rom(dev, rom_address);
- return rom_copy;
-}
-
static int __devinit xgifb_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
u8 reg, reg1;
u8 CR48, CR38;
int ret;
- bool xgi21_drvlcdcaplist = false;
struct fb_info *fb_info;
struct xgifb_video_info *xgifb_info;
struct xgi_hw_device_info *hw_info;
@@ -2001,6 +1926,11 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
goto error;
}
+ if (XGIfb_crt2type != -1) {
+ xgifb_info->display2 = XGIfb_crt2type;
+ xgifb_info->display2_force = true;
+ }
+
XGIRegInit(&xgifb_info->dev_info, (unsigned long)hw_info->pjIOAddress);
xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
@@ -2041,18 +1971,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
printk("XGIfb:chipid = %x\n", xgifb_info->chip);
hw_info->jChipType = xgifb_info->chip;
- if ((xgifb_info->chip == XG21) || (XGIfb_userom)) {
- hw_info->pjVirtualRomBase = xgifb_copy_rom(pdev);
- if (hw_info->pjVirtualRomBase)
- printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",
- hw_info->pjVirtualRomBase);
- else
- printk(KERN_INFO "XGIfb: Video ROM not found\n");
- } else {
- hw_info->pjVirtualRomBase = NULL;
- printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
- }
-
if (XGIfb_get_dram_size(xgifb_info)) {
printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
ret = -ENODEV;
@@ -2117,8 +2035,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
CR38 = xgifb_reg_get(XGICR, 0x38);
if ((CR38&0xE0) == 0xC0) {
xgifb_info->display2 = XGIFB_DISP_LCD;
- if (!XGIfb_GetXG21LVDSData(xgifb_info))
- xgi21_drvlcdcaplist = true;
} else if ((CR38&0xE0) == 0x60) {
xgifb_info->hasVB = HASVB_CHRONTEL;
} else {
@@ -2193,6 +2109,8 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
if (xgifb_info->hasVB != HASVB_NONE)
XGIfb_detect_VB(xgifb_info);
+ else if (xgifb_info->chip != XG21)
+ xgifb_info->display2 = XGIFB_DISP_NONE;
if (xgifb_info->display2 == XGIFB_DISP_LCD) {
if (!enable_dstn) {
@@ -2254,7 +2172,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
if (xgifb_info->display2 == XGIFB_DISP_LCD &&
xgifb_info->chip == XG21)
xgifb_info->mode_idx =
- XGIfb_GetXG21DefaultLVDSModeIdx();
+ XGIfb_GetXG21DefaultLVDSModeIdx(xgifb_info);
else
xgifb_info->mode_idx = DEFAULT_MODE;
}
@@ -2264,21 +2182,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
goto error_1;
}
- if (xgi21_drvlcdcaplist) {
- int m;
-
- for (m = 0; m < ARRAY_SIZE(XGI21_LCDCapList); m++)
- if ((XGI21_LCDCapList[m].LVDSHDE ==
- XGIbios_mode[xgifb_info->mode_idx].xres) &&
- (XGI21_LCDCapList[m].LVDSVDE ==
- XGIbios_mode[xgifb_info->mode_idx].yres)) {
- xgifb_reg_set(xgifb_info->dev_info.P3d4,
- 0x36,
- m);
- break;
- }
- }
-
/* yilin set default refresh rate */
xgifb_info->refresh_rate = refresh_rate;
if (xgifb_info->refresh_rate == 0)
@@ -2418,7 +2321,6 @@ error_1:
error_0:
release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
error:
- vfree(hw_info->pjVirtualRomBase);
framebuffer_release(fb_info);
return ret;
}
@@ -2442,7 +2344,6 @@ static void __devexit xgifb_remove(struct pci_dev *pdev)
iounmap(xgifb_info->video_vbase);
release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
- vfree(xgifb_info->hw_info.pjVirtualRomBase);
framebuffer_release(fb_info);
pci_set_drvdata(pdev, NULL);
}
@@ -2458,6 +2359,8 @@ static int __init xgifb_init(void)
{
char *option = NULL;
+ if (forcecrt2type != NULL)
+ XGIfb_search_crt2type(forcecrt2type);
if (fb_get_options("xgifb", &option))
return -ENODEV;
XGIfb_setup(option);
@@ -2480,6 +2383,11 @@ MODULE_AUTHOR("XGITECH , Others");
module_param(mode, charp, 0);
module_param(vesa, int, 0);
module_param(filter, int, 0);
+module_param(forcecrt2type, charp, 0);
+
+MODULE_PARM_DESC(forcecrt2type,
+ "\nForce the second display output type. Possible values are NONE,\n"
+ "LCD, TV, VGA, SVIDEO or COMPOSITE.\n");
MODULE_PARM_DESC(mode,
"\nSelects the desired default display mode in the format XxYxDepth,\n"
diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
index 7611846a7039..2c866bb65a00 100644
--- a/drivers/staging/xgifb/XGIfb.h
+++ b/drivers/staging/xgifb/XGIfb.h
@@ -86,10 +86,13 @@ struct xgifb_video_info {
unsigned int refresh_rate;
enum xgifb_display_type display2; /* the second display output type */
+ bool display2_force;
unsigned char hasVB;
unsigned char TV_type;
unsigned char TV_plug;
+ struct XGI21_LVDSCapStruct lvds_data;
+
enum XGI_CHIP_TYPE chip;
unsigned char revision_id;
diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
deleted file mode 100644
index b1a25730b7ca..000000000000
--- a/drivers/staging/xgifb/vb_ext.c
+++ /dev/null
@@ -1,444 +0,0 @@
-#include <linux/io.h>
-#include <linux/types.h>
-#include "XGIfb.h"
-
-#include "vb_def.h"
-#include "vgatypes.h"
-#include "vb_struct.h"
-#include "vb_util.h"
-#include "vb_setmode.h"
-#include "vb_ext.h"
-
-/**************************************************************
- *********************** Dynamic Sense ************************
- *************************************************************/
-
-static unsigned char XGINew_Is301B(struct vb_device_info *pVBInfo)
-{
- unsigned short flag;
-
- flag = xgifb_reg_get(pVBInfo->Part4Port, 0x01);
-
- if (flag > 0x0B0)
- return 0; /* 301b */
- else
- return 1;
-}
-
-static unsigned char XGINew_Sense(unsigned short tempbx,
- unsigned short tempcx,
- struct vb_device_info *pVBInfo)
-{
- unsigned short temp, i, tempch;
-
- temp = tempbx & 0xFF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x11, temp);
- temp = (tempbx & 0xFF00) >> 8;
- temp |= (tempcx & 0x00FF);
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
-
- for (i = 0; i < 10; i++)
- XGI_LongWait(pVBInfo);
-
- tempch = (tempcx & 0x7F00) >> 8;
- temp = xgifb_reg_get(pVBInfo->Part4Port, 0x03);
- temp = temp ^ (0x0E);
- temp &= tempch;
-
- if (temp > 0)
- return 1;
- else
- return 0;
-}
-
-static unsigned char
-XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short temp;
-
- /* add lcd sense */
- if (HwDeviceExtension->ulCRT2LCDType == LCD_UNKNOWN) {
- return 0;
- } else {
- temp = (unsigned short) HwDeviceExtension->ulCRT2LCDType;
- switch (HwDeviceExtension->ulCRT2LCDType) {
- case LCD_INVALID:
- case LCD_800x600:
- case LCD_1024x768:
- case LCD_1280x1024:
- break;
-
- case LCD_640x480:
- case LCD_1024x600:
- case LCD_1152x864:
- case LCD_1280x960:
- case LCD_1152x768:
- temp = 0;
- break;
-
- case LCD_1400x1050:
- case LCD_1280x768:
- case LCD_1600x1200:
- break;
-
- case LCD_1920x1440:
- case LCD_2048x1536:
- temp = 0;
- break;
-
- default:
- break;
- }
- xgifb_reg_and_or(pVBInfo->P3d4, 0x36, 0xF0, temp);
- return 1;
- }
-}
-
-static unsigned char XGINew_GetPanelID(struct vb_device_info *pVBInfo)
-{
- unsigned short PanelTypeTable[16] = { SyncNN | PanelRGB18Bit
- | Panel800x600 | _PanelType00, SyncNN | PanelRGB18Bit
- | Panel1024x768 | _PanelType01, SyncNN | PanelRGB18Bit
- | Panel800x600 | _PanelType02, SyncNN | PanelRGB18Bit
- | Panel640x480 | _PanelType03, SyncNN | PanelRGB18Bit
- | Panel1024x768 | _PanelType04, SyncNN | PanelRGB18Bit
- | Panel1024x768 | _PanelType05, SyncNN | PanelRGB18Bit
- | Panel1024x768 | _PanelType06, SyncNN | PanelRGB24Bit
- | Panel1024x768 | _PanelType07, SyncNN | PanelRGB18Bit
- | Panel800x600 | _PanelType08, SyncNN | PanelRGB18Bit
- | Panel1024x768 | _PanelType09, SyncNN | PanelRGB18Bit
- | Panel800x600 | _PanelType0A, SyncNN | PanelRGB18Bit
- | Panel1024x768 | _PanelType0B, SyncNN | PanelRGB18Bit
- | Panel1024x768 | _PanelType0C, SyncNN | PanelRGB24Bit
- | Panel1024x768 | _PanelType0D, SyncNN | PanelRGB18Bit
- | Panel1024x768 | _PanelType0E, SyncNN | PanelRGB18Bit
- | Panel1024x768 | _PanelType0F };
- unsigned short tempax, tempbx, temp;
- /* unsigned short return_flag; */
-
- tempax = xgifb_reg_get(pVBInfo->P3c4, 0x1A);
- tempbx = tempax & 0x1E;
-
- if (tempax == 0)
- return 0;
- else {
- /*
- if (!(tempax & 0x10)) {
- if (pVBInfo->IF_DEF_LVDS == 1) {
- tempbx = 0;
- temp = xgifb_reg_get(pVBInfo->P3c4, 0x38);
- if (temp & 0x40)
- tempbx |= 0x08;
- if (temp & 0x20)
- tempbx |= 0x02;
- if (temp & 0x01)
- tempbx |= 0x01;
-
- temp = xgifb_reg_get(pVBInfo->P3c4, 0x39);
- if (temp & 0x80)
- tempbx |= 0x04;
- } else {
- return(0);
- }
- }
- */
-
- tempbx = tempbx >> 1;
- temp = tempbx & 0x00F;
- xgifb_reg_set(pVBInfo->P3d4, 0x36, temp);
- tempbx--;
- tempbx = PanelTypeTable[tempbx];
-
- temp = (tempbx & 0xFF00) >> 8;
- xgifb_reg_and_or(pVBInfo->P3d4, 0x37, ~(LCDSyncBit
- | LCDRGB18Bit), temp);
- return 1;
- }
-}
-
-static unsigned char
-XGINew_BridgeIsEnable(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short flag;
-
- if (XGI_BridgeIsOn(pVBInfo) == 0) {
- flag = xgifb_reg_get(pVBInfo->Part1Port, 0x0);
-
- if (flag & 0x050)
- return 1;
- else
- return 0;
-
- }
- return 0;
-}
-
-static unsigned char
-XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempbx, tempcx, temp, i, tempch;
-
- tempbx = *pVBInfo->pYCSenseData2;
-
- tempcx = 0x0604;
-
- temp = tempbx & 0xFF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x11, temp);
- temp = (tempbx & 0xFF00) >> 8;
- temp |= (tempcx & 0x00FF);
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
-
- for (i = 0; i < 10; i++)
- XGI_LongWait(pVBInfo);
-
- tempch = (tempcx & 0xFF00) >> 8;
- temp = xgifb_reg_get(pVBInfo->Part4Port, 0x03);
- temp = temp ^ (0x0E);
- temp &= tempch;
-
- if (temp != tempch)
- return 0;
-
- tempbx = *pVBInfo->pVideoSenseData2;
-
- tempcx = 0x0804;
- temp = tempbx & 0xFF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x11, temp);
- temp = (tempbx & 0xFF00) >> 8;
- temp |= (tempcx & 0x00FF);
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
-
- for (i = 0; i < 10; i++)
- XGI_LongWait(pVBInfo);
-
- tempch = (tempcx & 0xFF00) >> 8;
- temp = xgifb_reg_get(pVBInfo->Part4Port, 0x03);
- temp = temp ^ (0x0E);
- temp &= tempch;
-
- if (temp != tempch) {
- return 0;
- } else {
- tempbx = 0x3FF;
- tempcx = 0x0804;
- temp = tempbx & 0xFF;
- xgifb_reg_set(pVBInfo->Part4Port, 0x11, temp);
- temp = (tempbx & 0xFF00) >> 8;
- temp |= (tempcx & 0x00FF);
- xgifb_reg_and_or(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
-
- for (i = 0; i < 10; i++)
- XGI_LongWait(pVBInfo);
-
- tempch = (tempcx & 0xFF00) >> 8;
- temp = xgifb_reg_get(pVBInfo->Part4Port, 0x03);
- temp = temp ^ (0x0E);
- temp &= tempch;
-
- if (temp != tempch)
- return 1;
- else
- return 0;
- }
-}
-
-void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- unsigned short tempax = 0, tempbx, tempcx, temp,
- P2reg0 = 0, SenseModeNo = 0,
- OutputSelect = *pVBInfo->pOutputSelect,
- ModeIdIndex, i;
- pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
-
- if (pVBInfo->IF_DEF_LVDS == 1) {
- /* ynlai 02/27/2002 */
- tempax = xgifb_reg_get(pVBInfo->P3c4, 0x1A);
- tempbx = xgifb_reg_get(pVBInfo->P3c4, 0x1B);
- tempax = ((tempax & 0xFE) >> 1) | (tempbx << 8);
- if (tempax == 0x00) { /* Get Panel id from DDC */
- temp = XGINew_GetLCDDDCInfo(HwDeviceExtension, pVBInfo);
- if (temp == 1) { /* LCD connect */
- /* set CR39 bit0="1" */
- xgifb_reg_and_or(pVBInfo->P3d4,
- 0x39, 0xFF, 0x01);
- /* clean CR37 bit4="0" */
- xgifb_reg_and_or(pVBInfo->P3d4,
- 0x37, 0xEF, 0x00);
- temp = LCDSense;
- } else { /* LCD don't connect */
- temp = 0;
- }
- } else {
- XGINew_GetPanelID(pVBInfo);
- temp = LCDSense;
- }
-
- tempbx = ~(LCDSense | AVIDEOSense | SVIDEOSense);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x32, tempbx, temp);
- } else { /* for 301 */
- if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { /* for HiVision */
- tempax = xgifb_reg_get(pVBInfo->P3c4, 0x38);
- temp = tempax & 0x01;
- tempax = xgifb_reg_get(pVBInfo->P3c4, 0x3A);
- temp = temp | (tempax & 0x02);
- xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xA0, temp);
- } else {
- if (XGI_BridgeIsOn(pVBInfo)) {
- P2reg0 = xgifb_reg_get(pVBInfo->Part2Port,
- 0x00);
- if (!XGINew_BridgeIsEnable(HwDeviceExtension,
- pVBInfo)) {
- SenseModeNo = 0x2e;
- /* xgifb_reg_set(pVBInfo->P3d4, 0x30, 0x41);
- * XGISetModeNew(HwDeviceExtension, 0x2e);
- * // ynlai InitMode */
-
- temp = XGI_SearchModeID(SenseModeNo,
- &ModeIdIndex,
- pVBInfo);
- XGI_GetVGAType(HwDeviceExtension,
- pVBInfo);
- XGI_GetVBType(pVBInfo);
- pVBInfo->SetFlag = 0x00;
- pVBInfo->ModeType = ModeVGA;
- pVBInfo->VBInfo = SetCRT2ToRAMDAC |
- LoadDACFlag |
- SetInSlaveMode;
- XGI_GetLCDInfo(0x2e,
- ModeIdIndex,
- pVBInfo);
- XGI_GetTVInfo(0x2e,
- ModeIdIndex,
- pVBInfo);
- XGI_EnableBridge(HwDeviceExtension,
- pVBInfo);
- XGI_SetCRT2Group301(SenseModeNo,
- HwDeviceExtension,
- pVBInfo);
- XGI_SetCRT2ModeRegs(0x2e,
- HwDeviceExtension,
- pVBInfo);
- /* XGI_DisableBridge(HwDeviceExtension,
- * pVBInfo ) ; */
- /* Display Off 0212 */
- xgifb_reg_and_or(pVBInfo->P3c4,
- 0x01,
- 0xDF,
- 0x20);
- for (i = 0; i < 20; i++)
- XGI_LongWait(pVBInfo);
- }
- xgifb_reg_set(pVBInfo->Part2Port, 0x00, 0x1c);
- tempax = 0;
- tempbx = *pVBInfo->pRGBSenseData;
-
- if (!(XGINew_Is301B(pVBInfo)))
- tempbx = *pVBInfo->pRGBSenseData2;
-
- tempcx = 0x0E08;
- if (XGINew_Sense(tempbx, tempcx, pVBInfo)) {
- if (XGINew_Sense(tempbx,
- tempcx,
- pVBInfo))
- tempax |= Monitor2Sense;
- }
-
- if (pVBInfo->VBType & VB_XGI301C)
- xgifb_reg_or(pVBInfo->Part4Port,
- 0x0d,
- 0x04);
-
- /* add by kuku for Multi-adapter sense HiTV */
- if (XGINew_SenseHiTV(HwDeviceExtension,
- pVBInfo)) {
- tempax |= HiTVSense;
- if ((pVBInfo->VBType & VB_XGI301C))
- tempax ^= (HiTVSense |
- YPbPrSense);
- }
-
- /* start */
- if (!(tempax & (HiTVSense | YPbPrSense))) {
- tempbx = *pVBInfo->pYCSenseData;
- if (!(XGINew_Is301B(pVBInfo)))
- tempbx = *pVBInfo->pYCSenseData2;
- tempcx = 0x0604;
- if (XGINew_Sense(tempbx,
- tempcx,
- pVBInfo)) {
- if (XGINew_Sense(tempbx,
- tempcx,
- pVBInfo))
- tempax |= SVIDEOSense;
- }
-
- if (OutputSelect & BoardTVType) {
- tempbx = *pVBInfo->pVideoSenseData;
-
- if (!(XGINew_Is301B(pVBInfo)))
- tempbx = *pVBInfo->pVideoSenseData2;
-
- tempcx = 0x0804;
- if (XGINew_Sense(tempbx,
- tempcx,
- pVBInfo)) {
- if (XGINew_Sense(tempbx,
- tempcx,
- pVBInfo))
- tempax |= AVIDEOSense;
- }
- } else {
- if (!(tempax & SVIDEOSense)) {
- tempbx = *pVBInfo->pVideoSenseData;
-
- if (!(XGINew_Is301B(pVBInfo)))
- tempbx = *pVBInfo->pVideoSenseData2;
-
- tempcx = 0x0804;
- if (XGINew_Sense(tempbx,
- tempcx,
- pVBInfo)) {
- if (XGINew_Sense(tempbx, tempcx, pVBInfo))
- tempax |= AVIDEOSense;
- }
- }
- }
- }
- } /* end */
- if (!(tempax & Monitor2Sense)) {
- if (XGINew_SenseLCD(HwDeviceExtension, pVBInfo))
- tempax |= LCDSense;
- }
- tempbx = 0;
- tempcx = 0;
- XGINew_Sense(tempbx, tempcx, pVBInfo);
-
- xgifb_reg_and_or(pVBInfo->P3d4, 0x32, ~0xDF, tempax);
- xgifb_reg_set(pVBInfo->Part2Port, 0x00, P2reg0);
-
- if (!(P2reg0 & 0x20)) {
- pVBInfo->VBInfo = DisableCRT2Display;
- /* XGI_SetCRT2Group301(SenseModeNo,
- * HwDeviceExtension,
- * pVBInfo); */
- }
- }
- }
- XGI_DisableBridge(HwDeviceExtension, pVBInfo); /* shampoo 0226 */
-
-}
-
-unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- /* unsigned short SoftSetting ; */
- unsigned short temp;
-
- temp = XGINew_GetLCDDDCInfo(HwDeviceExtension, pVBInfo);
-
- return temp;
-}
diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
deleted file mode 100644
index 0b1f55b4242f..000000000000
--- a/drivers/staging/xgifb/vb_ext.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _VBEXT_
-#define _VBEXT_
-
-extern void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo);
-extern unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *,
- struct vb_device_info *pVBInfo);
-
-#endif
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index 9e890a17fbc2..4ccd988ffd7c 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -1,6 +1,7 @@
#include <linux/types.h>
#include <linux/delay.h> /* udelay */
#include <linux/pci.h>
+#include <linux/vmalloc.h>
#include "vgatypes.h"
#include "XGIfb.h"
@@ -10,7 +11,6 @@
#include "vb_util.h"
#include "vb_setmode.h"
#include "vb_init.h"
-#include "vb_ext.h"
#include <linux/io.h>
@@ -35,6 +35,8 @@ static const unsigned short XGINew_DDRDRAM_TYPE20[12][5] = {
{ 2, 12, 9, 8, 0x35},
{ 2, 12, 8, 4, 0x31} };
+#define XGIFB_ROM_SIZE 65536
+
static unsigned char
XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
@@ -1068,20 +1070,20 @@ static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension,
return 0;
}
-static void XGINew_SetDRAMSize_340(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGINew_SetDRAMSize_340(struct xgifb_video_info *xgifb_info,
+ struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
{
unsigned short data;
- pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
- XGISetModeNew(HwDeviceExtension, 0x2e);
+ XGISetModeNew(xgifb_info, HwDeviceExtension, 0x2e);
data = xgifb_reg_get(pVBInfo->P3c4, 0x21);
/* disable read cache */
xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short) (data & 0xDF));
- XGI_DisplayOff(HwDeviceExtension, pVBInfo);
+ XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
/* data = xgifb_reg_get(pVBInfo->P3c4, 0x1); */
/* data |= 0x20 ; */
@@ -1092,118 +1094,100 @@ static void XGINew_SetDRAMSize_340(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short) (data | 0x20));
}
-static void ReadVBIOSTablData(unsigned char ChipType,
+static u8 *xgifb_copy_rom(struct pci_dev *dev, size_t *rom_size)
+{
+ void __iomem *rom_address;
+ u8 *rom_copy;
+
+ rom_address = pci_map_rom(dev, rom_size);
+ if (rom_address == NULL)
+ return NULL;
+
+ rom_copy = vzalloc(XGIFB_ROM_SIZE);
+ if (rom_copy == NULL)
+ goto done;
+
+ *rom_size = min_t(size_t, *rom_size, XGIFB_ROM_SIZE);
+ memcpy_fromio(rom_copy, rom_address, *rom_size);
+
+done:
+ pci_unmap_rom(dev, rom_address);
+ return rom_copy;
+}
+
+static void xgifb_read_vbios(struct pci_dev *pdev,
struct vb_device_info *pVBInfo)
{
- volatile unsigned char *pVideoMemory =
- (unsigned char *) pVBInfo->ROMAddr;
+ struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
+ u8 *vbios;
unsigned long i;
- unsigned char j, k;
- /* Volari customize data area end */
-
- if (ChipType == XG21) {
- pVBInfo->IF_DEF_LVDS = 0;
- if (pVideoMemory[0x65] & 0x1) {
- pVBInfo->IF_DEF_LVDS = 1;
- i = pVideoMemory[0x316] | (pVideoMemory[0x317] << 8);
- j = pVideoMemory[i - 1];
- if (j != 0xff) {
- k = 0;
- do {
- pVBInfo->XG21_LVDSCapList[k].
- LVDS_Capability
- = pVideoMemory[i] |
- (pVideoMemory[i + 1] << 8);
- pVBInfo->XG21_LVDSCapList[k].LVDSHT
- = pVideoMemory[i + 2] |
- (pVideoMemory[i + 3] << 8);
- pVBInfo->XG21_LVDSCapList[k].LVDSVT
- = pVideoMemory[i + 4] |
- (pVideoMemory[i + 5] << 8);
- pVBInfo->XG21_LVDSCapList[k].LVDSHDE
- = pVideoMemory[i + 6] |
- (pVideoMemory[i + 7] << 8);
- pVBInfo->XG21_LVDSCapList[k].LVDSVDE
- = pVideoMemory[i + 8] |
- (pVideoMemory[i + 9] << 8);
- pVBInfo->XG21_LVDSCapList[k].LVDSHFP
- = pVideoMemory[i + 10] |
- (pVideoMemory[i + 11] << 8);
- pVBInfo->XG21_LVDSCapList[k].LVDSVFP
- = pVideoMemory[i + 12] |
- (pVideoMemory[i + 13] << 8);
- pVBInfo->XG21_LVDSCapList[k].LVDSHSYNC
- = pVideoMemory[i + 14] |
- (pVideoMemory[i + 15] << 8);
- pVBInfo->XG21_LVDSCapList[k].LVDSVSYNC
- = pVideoMemory[i + 16] |
- (pVideoMemory[i + 17] << 8);
- pVBInfo->XG21_LVDSCapList[k].VCLKData1
- = pVideoMemory[i + 18];
- pVBInfo->XG21_LVDSCapList[k].VCLKData2
- = pVideoMemory[i + 19];
- pVBInfo->XG21_LVDSCapList[k].PSC_S1
- = pVideoMemory[i + 20];
- pVBInfo->XG21_LVDSCapList[k].PSC_S2
- = pVideoMemory[i + 21];
- pVBInfo->XG21_LVDSCapList[k].PSC_S3
- = pVideoMemory[i + 22];
- pVBInfo->XG21_LVDSCapList[k].PSC_S4
- = pVideoMemory[i + 23];
- pVBInfo->XG21_LVDSCapList[k].PSC_S5
- = pVideoMemory[i + 24];
- i += 25;
- j--;
- k++;
- } while ((j > 0) &&
- (k < (sizeof(XGI21_LCDCapList) /
- sizeof(struct
- XGI21_LVDSCapStruct))));
- } else {
- pVBInfo->XG21_LVDSCapList[0].LVDS_Capability
- = pVideoMemory[i] |
- (pVideoMemory[i + 1] << 8);
- pVBInfo->XG21_LVDSCapList[0].LVDSHT
- = pVideoMemory[i + 2] |
- (pVideoMemory[i + 3] << 8);
- pVBInfo->XG21_LVDSCapList[0].LVDSVT
- = pVideoMemory[i + 4] |
- (pVideoMemory[i + 5] << 8);
- pVBInfo->XG21_LVDSCapList[0].LVDSHDE
- = pVideoMemory[i + 6] |
- (pVideoMemory[i + 7] << 8);
- pVBInfo->XG21_LVDSCapList[0].LVDSVDE
- = pVideoMemory[i + 8] |
- (pVideoMemory[i + 9] << 8);
- pVBInfo->XG21_LVDSCapList[0].LVDSHFP
- = pVideoMemory[i + 10] |
- (pVideoMemory[i + 11] << 8);
- pVBInfo->XG21_LVDSCapList[0].LVDSVFP
- = pVideoMemory[i + 12] |
- (pVideoMemory[i + 13] << 8);
- pVBInfo->XG21_LVDSCapList[0].LVDSHSYNC
- = pVideoMemory[i + 14] |
- (pVideoMemory[i + 15] << 8);
- pVBInfo->XG21_LVDSCapList[0].LVDSVSYNC
- = pVideoMemory[i + 16] |
- (pVideoMemory[i + 17] << 8);
- pVBInfo->XG21_LVDSCapList[0].VCLKData1
- = pVideoMemory[i + 18];
- pVBInfo->XG21_LVDSCapList[0].VCLKData2
- = pVideoMemory[i + 19];
- pVBInfo->XG21_LVDSCapList[0].PSC_S1
- = pVideoMemory[i + 20];
- pVBInfo->XG21_LVDSCapList[0].PSC_S2
- = pVideoMemory[i + 21];
- pVBInfo->XG21_LVDSCapList[0].PSC_S3
- = pVideoMemory[i + 22];
- pVBInfo->XG21_LVDSCapList[0].PSC_S4
- = pVideoMemory[i + 23];
- pVBInfo->XG21_LVDSCapList[0].PSC_S5
- = pVideoMemory[i + 24];
- }
- }
+ unsigned char j;
+ struct XGI21_LVDSCapStruct *lvds;
+ size_t vbios_size;
+ int entry;
+
+ if (xgifb_info->chip != XG21)
+ return;
+ pVBInfo->IF_DEF_LVDS = 0;
+ vbios = xgifb_copy_rom(pdev, &vbios_size);
+ if (vbios == NULL) {
+ dev_err(&pdev->dev, "video BIOS not available\n");
+ return;
+ }
+ if (vbios_size <= 0x65)
+ goto error;
+ /*
+ * The user can ignore the LVDS bit in the BIOS and force the display
+ * type.
+ */
+ if (!(vbios[0x65] & 0x1) &&
+ (!xgifb_info->display2_force ||
+ xgifb_info->display2 != XGIFB_DISP_LCD)) {
+ vfree(vbios);
+ return;
}
+ if (vbios_size <= 0x317)
+ goto error;
+ i = vbios[0x316] | (vbios[0x317] << 8);
+ if (vbios_size <= i - 1)
+ goto error;
+ j = vbios[i - 1];
+ if (j == 0)
+ goto error;
+ if (j == 0xff)
+ j = 1;
+ /*
+ * Read the LVDS table index scratch register set by the BIOS.
+ */
+ entry = xgifb_reg_get(xgifb_info->dev_info.P3d4, 0x36);
+ if (entry >= j)
+ entry = 0;
+ i += entry * 25;
+ lvds = &xgifb_info->lvds_data;
+ if (vbios_size <= i + 24)
+ goto error;
+ lvds->LVDS_Capability = vbios[i] | (vbios[i + 1] << 8);
+ lvds->LVDSHT = vbios[i + 2] | (vbios[i + 3] << 8);
+ lvds->LVDSVT = vbios[i + 4] | (vbios[i + 5] << 8);
+ lvds->LVDSHDE = vbios[i + 6] | (vbios[i + 7] << 8);
+ lvds->LVDSVDE = vbios[i + 8] | (vbios[i + 9] << 8);
+ lvds->LVDSHFP = vbios[i + 10] | (vbios[i + 11] << 8);
+ lvds->LVDSVFP = vbios[i + 12] | (vbios[i + 13] << 8);
+ lvds->LVDSHSYNC = vbios[i + 14] | (vbios[i + 15] << 8);
+ lvds->LVDSVSYNC = vbios[i + 16] | (vbios[i + 17] << 8);
+ lvds->VCLKData1 = vbios[i + 18];
+ lvds->VCLKData2 = vbios[i + 19];
+ lvds->PSC_S1 = vbios[i + 20];
+ lvds->PSC_S2 = vbios[i + 21];
+ lvds->PSC_S3 = vbios[i + 22];
+ lvds->PSC_S4 = vbios[i + 23];
+ lvds->PSC_S5 = vbios[i + 24];
+ vfree(vbios);
+ pVBInfo->IF_DEF_LVDS = 1;
+ return;
+error:
+ dev_err(&pdev->dev, "video BIOS corrupted\n");
+ vfree(vbios);
}
static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
@@ -1336,18 +1320,57 @@ static void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension,
}
+static unsigned short XGINew_SenseLCD(struct xgi_hw_device_info
+ *HwDeviceExtension,
+ struct vb_device_info *pVBInfo)
+{
+ unsigned short temp;
+
+ /* add lcd sense */
+ if (HwDeviceExtension->ulCRT2LCDType == LCD_UNKNOWN) {
+ return 0;
+ } else {
+ temp = (unsigned short) HwDeviceExtension->ulCRT2LCDType;
+ switch (HwDeviceExtension->ulCRT2LCDType) {
+ case LCD_INVALID:
+ case LCD_800x600:
+ case LCD_1024x768:
+ case LCD_1280x1024:
+ break;
+
+ case LCD_640x480:
+ case LCD_1024x600:
+ case LCD_1152x864:
+ case LCD_1280x960:
+ case LCD_1152x768:
+ temp = 0;
+ break;
+
+ case LCD_1400x1050:
+ case LCD_1280x768:
+ case LCD_1600x1200:
+ break;
+
+ case LCD_1920x1440:
+ case LCD_2048x1536:
+ temp = 0;
+ break;
+
+ default:
+ break;
+ }
+ xgifb_reg_and_or(pVBInfo->P3d4, 0x36, 0xF0, temp);
+ return 1;
+ }
+}
+
static void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
{
unsigned char Temp;
- volatile unsigned char *pVideoMemory =
- (unsigned char *) pVBInfo->ROMAddr;
-
- pVBInfo->IF_DEF_LVDS = 0;
#if 1
- if ((pVideoMemory[0x65] & 0x01)) { /* For XG21 LVDS */
- pVBInfo->IF_DEF_LVDS = 1;
+ if (pVBInfo->IF_DEF_LVDS) { /* For XG21 LVDS */
xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
/* LVDS on chip */
xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0);
@@ -1393,7 +1416,6 @@ static void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3d4, 0x4A, bCR4A);
if (Temp <= 0x02) {
- pVBInfo->IF_DEF_LVDS = 1;
/* LVDS setting */
xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0);
xgifb_reg_set(pVBInfo->P3d4, 0x30, 0x21);
@@ -1451,24 +1473,15 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
struct vb_device_info *pVBInfo = &VBINF;
unsigned char i, temp = 0, temp1;
/* VBIOSVersion[5]; */
- volatile unsigned char *pVideoMemory;
/* unsigned long j, k; */
- pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
-
pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
- pVideoMemory = (unsigned char *) pVBInfo->ROMAddr;
-
/* Newdebugcode(0x99); */
-
- /* if (pVBInfo->ROMAddr == 0) */
- /* return(0); */
-
if (pVBInfo->FBAddr == NULL) {
printk("\n pVBInfo->FBAddr == 0 ");
return 0;
@@ -1516,8 +1529,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
- /* ReadVBIOSData */
- ReadVBIOSTablData(HwDeviceExtension->jChipType, pVBInfo);
+ xgifb_read_vbios(pdev, pVBInfo);
/* 1.Openkey */
xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
@@ -1774,7 +1786,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
pVBInfo);
printk("20");
- XGINew_SetDRAMSize_340(HwDeviceExtension, pVBInfo);
+ XGINew_SetDRAMSize_340(xgifb_info, HwDeviceExtension, pVBInfo);
printk("21");
printk("22");
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index 81c0cc41bb42..67a316c3c108 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -67,11 +67,6 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
pVBInfo->XGINEWUB_CRT1Table
= (struct XGI_CRT1TableStruct *) XGI_CRT1Table;
- /* add for new UNIVGABIOS */
- /* XGINew_UBLCDDataTable =
- * (struct XGI_LCDDataTablStruct *) XGI_LCDDataTable; */
- /* XGINew_UBTVDataTable = (XGI_TVDataTablStruct *) XGI_TVDataTable; */
-
pVBInfo->MCLKData = (struct XGI_MCLKDataStruct *) XGI340New_MCLKData;
pVBInfo->ECLKData = (struct XGI_ECLKDataStruct *) XGI340_ECLKData;
pVBInfo->VCLKData = (struct XGI_VCLKDataStruct *) XGI_VCLKData;
@@ -148,9 +143,6 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
else
pVBInfo->LCDCapList = XGI_LCDCapList;
- if ((ChipType == XG21) || (ChipType == XG27))
- pVBInfo->XG21_LVDSCapList = XGI21_LCDCapList;
-
pVBInfo->XGI_TVDelayList = XGI301TVDelayList;
pVBInfo->XGI_TVDelayList2 = XGI301TVDelayList2;
@@ -236,28 +228,6 @@ static void XGI_SetSeqRegs(unsigned short ModeNo,
}
}
-static void XGI_SetMiscRegs(unsigned short StandTableIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char Miscdata;
-
- /* Get Misc from file */
- Miscdata = pVBInfo->StandTable[StandTableIndex].MISC;
- /*
- if (pVBInfo->VBType & (VB_XGI301B |
- VB_XGI302B |
- VB_XGI301LV |
- VB_XGI302LV |
- VB_XGI301C)) {
- if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
- Miscdata |= 0x0C;
- }
- }
- */
-
- outb(Miscdata, pVBInfo->P3c2); /* Set Misc(3c2) */
-}
-
static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
unsigned short StandTableIndex,
struct vb_device_info *pVBInfo)
@@ -274,16 +244,6 @@ static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
CRTCdata = pVBInfo->StandTable[StandTableIndex].CRTC[i];
xgifb_reg_set(pVBInfo->P3d4, i, CRTCdata); /* Set CRTC(3d4) */
}
- /*
- if ((HwDeviceExtension->jChipType == XGI_630) &&
- (HwDeviceExtension->jChipRevision == 0x30)) {
- if (pVBInfo->VBInfo & SetInSlaveMode) {
- if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
- xgifb_reg_set(pVBInfo->P3d4, 0x18, 0xFE);
- }
- }
- }
- */
}
static void XGI_SetATTRegs(unsigned short ModeNo,
@@ -530,10 +490,6 @@ static void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo,
unsigned char data, data1, pushax;
unsigned short i, j;
- /* xgifb_reg_set(pVBInfo->P3d4, 0x51, 0); */
- /* xgifb_reg_set(pVBInfo->P3d4, 0x56, 0); */
- /* xgifb_reg_and_or(pVBInfo->P3d4, 0x11, 0x7f, 0x00); */
-
/* unlock cr0-7 */
data = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
data &= 0x7F;
@@ -595,10 +551,6 @@ static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
unsigned char data;
unsigned short i, j;
- /* xgifb_reg_set(pVBInfo->P3d4, 0x51, 0); */
- /* xgifb_reg_set(pVBInfo->P3d4, 0x56, 0); */
- /* xgifb_reg_and_or(pVBInfo->P3d4, 0x11, 0x7f, 0x00); */
-
for (i = 0x00; i <= 0x01; i++) {
data = pVBInfo->TimingV[0].data[i];
xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 6), data);
@@ -976,6 +928,20 @@ static void XGI_SetXG27CRTC(unsigned short ModeNo,
}
}
+static void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo)
+{
+ unsigned char temp;
+
+ /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
+ temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
+ temp = (temp & 3) << 6;
+ /* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0xc0, temp & 0x80);
+ /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80);
+
+}
+
static void xgifb_set_lcd(int chip_id,
struct vb_device_info *pVBInfo,
unsigned short RefreshRateTableIndex,
@@ -1088,6 +1054,20 @@ static void XGI_UpdateXG21CRTC(unsigned short ModeNo,
}
}
+static unsigned short XGI_GetResInfo(unsigned short ModeNo,
+ unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+{
+ unsigned short resindex;
+
+ if (ModeNo <= 0x13)
+ /* si+St_ResInfo */
+ resindex = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
+ else
+ /* si+Ext_ResInfo */
+ resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ return resindex;
+}
+
static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
unsigned short ModeNo, unsigned short ModeIdIndex,
unsigned short RefreshRateTableIndex,
@@ -1127,9 +1107,6 @@ static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
tempcx = 8;
- /* if (!(modeflag & Charx8Dot)) */
- /* tempcx = 9; */
-
tempax /= tempcx;
tempax -= 1;
tempbx -= 1;
@@ -1163,20 +1140,6 @@ static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3d4, 0x11, temp);
}
-unsigned short XGI_GetResInfo(unsigned short ModeNo,
- unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
-{
- unsigned short resindex;
-
- if (ModeNo <= 0x13)
- /* si+St_ResInfo */
- resindex = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
- else
- /* si+Ext_ResInfo */
- resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- return resindex;
-}
-
static void XGI_SetCRT1Offset(unsigned short ModeNo,
unsigned short ModeIdIndex,
unsigned short RefreshRateTableIndex,
@@ -1308,77 +1271,55 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
VCLKIndex = LCDXlat2VCLK[CRT2Index];
else
VCLKIndex = LCDXlat1VCLK[CRT2Index];
- } else { /* for TV */
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
- if (pVBInfo->SetFlag & RPLLDIV2XO) {
- VCLKIndex = HiTVVCLKDIV2;
- VCLKIndex += 25;
- } else {
- VCLKIndex = HiTVVCLK;
- VCLKIndex += 25;
- }
-
- if (pVBInfo->SetFlag & TVSimuMode) {
- if (modeflag & Charx8Dot) {
- VCLKIndex =
- HiTVSimuVCLK;
- VCLKIndex += 25;
- } else {
- VCLKIndex =
- HiTVTextVCLK;
- VCLKIndex += 25;
- }
- }
+ } else if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+ if (pVBInfo->SetFlag & RPLLDIV2XO) {
+ VCLKIndex = HiTVVCLKDIV2;
+ VCLKIndex += 25;
+ } else {
+ VCLKIndex = HiTVVCLK;
+ VCLKIndex += 25;
+ }
- /* 301lv */
- if (pVBInfo->VBType & VB_XGI301LV) {
- if (!(pVBInfo->VBExtInfo ==
- VB_YPbPr1080i)) {
- VCLKIndex =
- YPbPr750pVCLK;
- if (!(pVBInfo->VBExtInfo
- ==
- VB_YPbPr750p)) {
- VCLKIndex =
- YPbPr525pVCLK;
- if (!(pVBInfo->VBExtInfo
- == VB_YPbPr525p)) {
- VCLKIndex
- = YPbPr525iVCLK_2;
- if (!(pVBInfo->SetFlag
- & RPLLDIV2XO))
- VCLKIndex
- = YPbPr525iVCLK;
- }
- }
- }
- }
+ if (pVBInfo->SetFlag & TVSimuMode) {
+ if (modeflag & Charx8Dot) {
+ VCLKIndex = HiTVSimuVCLK;
+ VCLKIndex += 25;
} else {
- if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (pVBInfo->SetFlag &
- RPLLDIV2XO) {
- VCLKIndex = TVVCLKDIV2;
- VCLKIndex += 25;
- } else {
- VCLKIndex = TVVCLK;
- VCLKIndex += 25;
- }
- }
+ VCLKIndex = HiTVTextVCLK;
+ VCLKIndex += 25;
}
- } else { /* for CRT2 */
- /* Port 3cch */
- VCLKIndex = (unsigned char) inb(
- (pVBInfo->P3ca + 0x02));
- VCLKIndex = ((VCLKIndex >> 2) & 0x03);
- if (ModeNo > 0x13) {
- /* di+Ext_CRTVCLK */
- VCLKIndex =
- pVBInfo->RefIndex[
+ }
+
+ /* 301lv */
+ if ((pVBInfo->VBType & VB_XGI301LV) &&
+ !(pVBInfo->VBExtInfo == VB_YPbPr1080i)) {
+ if (pVBInfo->VBExtInfo == VB_YPbPr750p)
+ VCLKIndex = YPbPr750pVCLK;
+ else if (pVBInfo->VBExtInfo == VB_YPbPr525p)
+ VCLKIndex = YPbPr525pVCLK;
+ else if (pVBInfo->SetFlag & RPLLDIV2XO)
+ VCLKIndex = YPbPr525iVCLK_2;
+ else
+ VCLKIndex = YPbPr525iVCLK;
+ }
+ } else if (pVBInfo->VBInfo & SetCRT2ToTV) {
+ if (pVBInfo->SetFlag & RPLLDIV2XO) {
+ VCLKIndex = TVVCLKDIV2;
+ VCLKIndex += 25;
+ } else {
+ VCLKIndex = TVVCLK;
+ VCLKIndex += 25;
+ }
+ } else { /* for CRT2 */
+ /* Port 3cch */
+ VCLKIndex = (unsigned char) inb((pVBInfo->P3ca + 0x02));
+ VCLKIndex = ((VCLKIndex >> 2) & 0x03);
+ if (ModeNo > 0x13) {
+ /* di+Ext_CRTVCLK */
+ VCLKIndex = pVBInfo->RefIndex[
RefreshRateTableIndex].
Ext_CRTVCLK;
- VCLKIndex &= IndexMask;
- }
+ VCLKIndex &= IndexMask;
}
}
} else { /* LVDS */
@@ -1397,7 +1338,6 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
else
VCLKIndex = LVDSXlat3VCLK[VCLKIndex];
}
- /* VCLKIndex = VCLKIndex&IndexMask; */
return VCLKIndex;
}
@@ -1461,6 +1401,19 @@ static void XGI_SetCRT1VCLK(unsigned short ModeNo,
}
}
+static void XGI_SetXG21FPBits(struct vb_device_info *pVBInfo)
+{
+ unsigned char temp;
+
+ temp = xgifb_reg_get(pVBInfo->P3d4, 0x37); /* D[0] 1: 18bit */
+ temp = (temp & 1) << 6;
+ /* SR06[6] 18bit Dither */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x40, temp);
+ /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80);
+
+}
+
static void XGI_SetCRT1FIFO(unsigned short ModeNo,
struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
@@ -1532,16 +1485,6 @@ static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_set(pVBInfo->P3c4, 0x1F, data);
}
- /* Jong for Adavantech LCD ripple issue
- if ((VCLK >= 0) && (VCLK < 135))
- data2 = 0x03;
- else if ((VCLK >= 135) && (VCLK < 160))
- data2 = 0x02;
- else if ((VCLK >= 160) && (VCLK < 260))
- data2 = 0x01;
- else if (VCLK > 260)
- data2 = 0x00;
- */
data2 = 0x00;
xgifb_reg_and_or(pVBInfo->P3c4, 0x07, 0xFC, data2);
@@ -1591,7 +1534,6 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
data2 |= 0x20;
xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x3F, data2);
- /* xgifb_reg_set(pVBInfo->P3c4,0x06,data2); */
resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
if (ModeNo <= 0x13)
xres = pVBInfo->StResInfo[resindex].HTotal;
@@ -1636,11 +1578,6 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
XGI_SetVCLKState(HwDeviceExtension, ModeNo, RefreshRateTableIndex,
pVBInfo);
- /* if (modeflag&HalfDCLK) //030305 fix lowresolution bug */
- /* if (XGINew_IF_DEF_NEW_LOWRES) */
- /* XGI_VesaLowResolution(ModeNo, ModeIdIndex);
- * //030305 fix lowresolution bug */
-
data = xgifb_reg_get(pVBInfo->P3d4, 0x31);
if (HwDeviceExtension->jChipType == XG27) {
@@ -1803,11 +1740,6 @@ static void XGI_GetLVDSResInfo(unsigned short ModeNo,
/* si+Ext_ResInfo */
modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- /* if (ModeNo > 0x13) */
- /* modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; */
- /* else */
- /* modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; */
-
if (ModeNo <= 0x13)
/* si+St_ResInfo */
resindex = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
@@ -1815,8 +1747,6 @@ static void XGI_GetLVDSResInfo(unsigned short ModeNo,
/* si+Ext_ResInfo */
resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- /* resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo); */
-
if (ModeNo <= 0x13) {
xres = pVBInfo->StResInfo[resindex].HTotal;
yres = pVBInfo->StResInfo[resindex].VTotal;
@@ -1831,13 +1761,10 @@ static void XGI_GetLVDSResInfo(unsigned short ModeNo,
if (modeflag & DoubleScanMode)
yres = yres << 1;
}
- /* if (modeflag & Charx8Dot) */
- /* { */
if (xres == 720)
xres = 640;
- /* } */
pVBInfo->VGAHDE = xres;
pVBInfo->HDE = xres;
pVBInfo->VGAVDE = yres;
@@ -1890,7 +1817,7 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
tempal = (tempal & 0x0f);
}
- tempcx = LCDLenList[tempbx]; /* mov cl,byte ptr cs:LCDLenList[bx] */
+ tempcx = LCDLenList[tempbx];
if (pVBInfo->LCDInfo & EnableScalingLCD) { /* ScaleLCD */
if ((tempbx == 5) || (tempbx) == 7)
@@ -1898,9 +1825,6 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
else if ((tempbx == 3) || (tempbx == 8))
tempcx = LVDSDesDataLen2;
}
- /* mov di, word ptr cs:LCDDataList[bx] */
- /* tempdi = pVideoMemory[LCDDataList + tempbx * 2] |
- (pVideoMemory[LCDDataList + tempbx * 2 + 1] << 8); */
switch (tempbx) {
case 0:
@@ -2321,10 +2245,10 @@ static void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
switch (tempbx) {
case 0:
- tempdi = NULL; /*EPLCHTVCRT1Ptr_H;*/
+ tempdi = NULL;
break;
case 1:
- tempdi = NULL; /*EPLCHTVCRT1Ptr_V;*/
+ tempdi = NULL;
break;
case 2:
case 6:
@@ -2363,9 +2287,7 @@ static void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
}
/* 07/05/22 */
- if (table == 0x00) {
- } else if (table == 0x01) {
- } else if (table == 0x04) {
+ if (table == 0x04) {
switch (tempdi[i].DATAPTR) {
case 0:
return &XGI_ExtPALData[tempal];
@@ -2429,7 +2351,6 @@ static void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
default:
break;
}
- } else if (table == 0x06) {
}
return NULL;
}
@@ -2741,7 +2662,6 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
else
tempbx = LCDPtr->LCDVRS;
- /* tempbx = tempbx >> 4; */
tempcx = push1;
if (pVBInfo->LCDInfo & EnableScalingLCD)
@@ -2881,7 +2801,6 @@ static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
unsigned short index;
if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- /* index = XGI_GetLCDCapPtr(pVBInfo); */
index = XGI_GetLCDCapPtr1(pVBInfo);
if (pVBInfo->VBInfo & SetCRT2ToLCD) { /* LCDB */
@@ -3105,19 +3024,6 @@ static void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension,
}
}
-void XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *pVBInfo)
-{
- /*
- if ( HwDeviceExtension->jChipType >= XG20 ) {
- pVBInfo->Set_VGAType = XG20;
- } else {
- pVBInfo->Set_VGAType = VGA_XGI340;
- }
- */
- pVBInfo->Set_VGAType = HwDeviceExtension->jChipType;
-}
-
void XGI_GetVBType(struct vb_device_info *pVBInfo)
{
unsigned short flag, tempbx, tempah;
@@ -3160,7 +3066,7 @@ void XGI_GetVBType(struct vb_device_info *pVBInfo)
}
}
-void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
{
@@ -3193,14 +3099,9 @@ void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
if (pVBInfo->IF_DEF_LCDA == 1) {
- if ((pVBInfo->Set_VGAType >= XG20)
- || (pVBInfo->Set_VGAType >= XG40)) {
+ if ((HwDeviceExtension->jChipType >= XG20) ||
+ (HwDeviceExtension->jChipType >= XG40)) {
if (pVBInfo->IF_DEF_LVDS == 0) {
- /* if ((pVBInfo->VBType & VB_XGI302B)
- || (pVBInfo->VBType & VB_XGI301LV)
- || (pVBInfo->VBType & VB_XGI302LV)
- || (pVBInfo->VBType & VB_XGI301C))
- */
if (pVBInfo->VBType &
(VB_XGI302B |
VB_XGI301LV |
@@ -3225,7 +3126,7 @@ void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
((pVBInfo->VBType & VB_XGI301LV) ||
(pVBInfo->VBType & VB_XGI302LV) ||
(pVBInfo->VBType & VB_XGI301C)))) {
- if (temp & SetYPbPr) { /* temp = CR38 */
+ if (temp & SetYPbPr) {
if (pVBInfo->IF_DEF_HiVision == 1) {
/* shampoo add for new
* scratch */
@@ -3242,8 +3143,6 @@ void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
SetCRT2ToYPbPr;
}
}
-
- /* tempbx |= SetCRT2ToYPbPr; */
}
}
}
@@ -3368,7 +3267,7 @@ void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
pVBInfo->VBInfo = tempbx;
}
-void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
unsigned short temp, tempbx = 0, resinfo = 0, modeflag, index1;
@@ -3404,17 +3303,6 @@ void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
tempbx &= (SetCHTVOverScan |
SetNTSCJ |
SetPALTV);
- /*
- if (pVBInfo->IF_DEF_LVDS == 0) {
- //PAL-M/PAL-N Info
- index1 = xgifb_reg_get(pVBInfo->P3d4, 0x38);
- //00:PAL, 01:PAL-M, 10:PAL-N
- temp2 = (index1 & 0xC0) >> 5;
- tempbx |= temp2;
- if (temp2 & 0x02) //PAL-M
- tempbx &= (~SetPALTV);
- }
- */
}
if (pVBInfo->IF_DEF_LVDS == 0) {
@@ -3476,8 +3364,8 @@ void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
pVBInfo->TVInfo = tempbx;
}
-unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
+static unsigned char XGI_GetLCDInfo(unsigned short ModeNo,
+ unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
{
unsigned short temp, tempax, tempbx, modeflag, resinfo = 0, LCDIdIndex;
@@ -3553,15 +3441,8 @@ unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
tempbx |= SetLCDtoNonExpanding;
}
- /*
- if (tempax & LCDBToA) {
- tempbx |= SetLCDBToA;
- }
- */
-
if (pVBInfo->IF_DEF_ExpLink == 1) {
if (modeflag & HalfDCLK) {
- /* if (!(pVBInfo->LCDInfo&LCDNonExpanding)) */
if (!(tempbx & SetLCDtoNonExpanding)) {
tempbx |= EnableLVDSDDA;
} else {
@@ -3604,25 +3485,6 @@ unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
}
}
- /*
- if (pVBInfo->IF_DEF_LVDS == 0) {
- if (tempax & (LockLCDBToA | StLCDBToA)) {
- if (pVBInfo->VBInfo & SetInSlaveMode) {
- if (!((!(tempax & LockLCDBToA)) &&
- (ModeNo > 0x13))) {
- pVBInfo->VBInfo &=
- ~(SetSimuScanMode |
- SetInSlaveMode |
- SetCRT2ToLCD);
- pVBInfo->VBInfo |=
- SetCRT2ToLCDA |
- SetCRT2ToDualEdge;
- }
- }
- }
- }
- */
-
return 1;
}
@@ -3632,10 +3494,6 @@ unsigned char XGI_SearchModeID(unsigned short ModeNo,
if (ModeNo <= 5)
ModeNo |= 1;
if (ModeNo <= 0x13) {
- /* for (*ModeIdIndex=0;
- *ModeIdIndex < sizeof(pVBInfo->SModeIDTable)
- / sizeof(struct XGI_StStruct);
- (*ModeIdIndex)++) */
for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID ==
ModeNo)
@@ -3651,10 +3509,6 @@ unsigned char XGI_SearchModeID(unsigned short ModeNo,
(*ModeIdIndex) += 2; /* 400 lines */
/* else 350 lines */
} else {
- /* for (*ModeIdIndex=0;
- *ModeIdIndex < sizeof(pVBInfo->EModeIDTable)
- / sizeof(struct XGI_ExtStruct);
- (*ModeIdIndex)++) */
for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID ==
ModeNo)
@@ -3675,7 +3529,6 @@ static unsigned char XG21GPIODataTransfer(unsigned char ujDate)
for (i = 0; i < 8; i++) {
ujRet = ujRet << 1;
- /* ujRet |= GETBITS(ujDate >> i, 0:0); */
ujRet |= (ujDate >> i) & 1;
}
@@ -3726,7 +3579,101 @@ static unsigned char XGI_XG27GetPSCValue(struct vb_device_info *pVBInfo)
return temp;
}
-void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE,
+/*----------------------------------------------------------------------------*/
+/* input */
+/* bl[5] : 1;LVDS signal on */
+/* bl[1] : 1;LVDS backlight on */
+/* bl[0] : 1:LVDS VDD on */
+/* bh: 100000b : clear bit 5, to set bit5 */
+/* 000010b : clear bit 1, to set bit1 */
+/* 000001b : clear bit 0, to set bit0 */
+/*----------------------------------------------------------------------------*/
+static void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
+ struct vb_device_info *pVBInfo)
+{
+ unsigned char CR4A, temp;
+
+ CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
+ tempbh &= 0x23;
+ tempbl &= 0x23;
+ xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
+
+ if (tempbh & 0x20) {
+ temp = (tempbl >> 4) & 0x02;
+
+ /* CR B4[1] */
+ xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
+
+ }
+
+ temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
+
+ temp = XG21GPIODataTransfer(temp);
+ temp &= ~tempbh;
+ temp |= tempbl;
+ xgifb_reg_set(pVBInfo->P3d4, 0x48, temp);
+}
+
+static void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
+ struct vb_device_info *pVBInfo)
+{
+ unsigned char CR4A, temp;
+ unsigned short tempbh0, tempbl0;
+
+ tempbh0 = tempbh;
+ tempbl0 = tempbl;
+ tempbh0 &= 0x20;
+ tempbl0 &= 0x20;
+ tempbh0 >>= 3;
+ tempbl0 >>= 3;
+
+ if (tempbh & 0x20) {
+ temp = (tempbl >> 4) & 0x02;
+
+ /* CR B4[1] */
+ xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
+
+ }
+ xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~tempbh0, tempbl0);
+
+ CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
+ tempbh &= 0x03;
+ tempbl &= 0x03;
+ tempbh <<= 2;
+ tempbl <<= 2; /* GPIOC,GPIOD */
+ xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
+ xgifb_reg_and_or(pVBInfo->P3d4, 0x48, ~tempbh, tempbl);
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_XG21SetPanelDelay */
+/* Input : */
+/* Output : */
+/* Description : */
+/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */
+/* : bl : 2 ; T2 : the duration signal on and Vdd on */
+/* : bl : 3 ; T3 : the duration between CPL off and signal off */
+/* : bl : 4 ; T4 : the duration signal off and Vdd off */
+/* --------------------------------------------------------------------- */
+static void XGI_XG21SetPanelDelay(struct xgifb_video_info *xgifb_info,
+ unsigned short tempbl,
+ struct vb_device_info *pVBInfo)
+{
+ if (tempbl == 1)
+ mdelay(xgifb_info->lvds_data.PSC_S1);
+
+ if (tempbl == 2)
+ mdelay(xgifb_info->lvds_data.PSC_S2);
+
+ if (tempbl == 3)
+ mdelay(xgifb_info->lvds_data.PSC_S3);
+
+ if (tempbl == 4)
+ mdelay(xgifb_info->lvds_data.PSC_S4);
+}
+
+static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info,
+ struct xgi_hw_device_info *pXGIHWDE,
struct vb_device_info *pVBInfo)
{
@@ -3736,12 +3683,12 @@ void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE,
if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x1)) {
/* LVDS VDD on */
XGI_XG21BLSignalVDD(0x01, 0x01, pVBInfo);
- XGI_XG21SetPanelDelay(2, pVBInfo);
+ XGI_XG21SetPanelDelay(xgifb_info, 2, pVBInfo);
}
if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x20))
/* LVDS signal on */
XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo);
- XGI_XG21SetPanelDelay(3, pVBInfo);
+ XGI_XG21SetPanelDelay(xgifb_info, 3, pVBInfo);
/* LVDS backlight on */
XGI_XG21BLSignalVDD(0x02, 0x02, pVBInfo);
} else {
@@ -3756,12 +3703,12 @@ void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE,
if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x1)) {
/* LVDS VDD on */
XGI_XG27BLSignalVDD(0x01, 0x01, pVBInfo);
- XGI_XG21SetPanelDelay(2, pVBInfo);
+ XGI_XG21SetPanelDelay(xgifb_info, 2, pVBInfo);
}
if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x20))
/* LVDS signal on */
XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo);
- XGI_XG21SetPanelDelay(3, pVBInfo);
+ XGI_XG21SetPanelDelay(xgifb_info, 3, pVBInfo);
/* LVDS backlight on */
XGI_XG27BLSignalVDD(0x02, 0x02, pVBInfo);
} else {
@@ -3772,7 +3719,8 @@ void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE,
}
}
-void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE,
+void XGI_DisplayOff(struct xgifb_video_info *xgifb_info,
+ struct xgi_hw_device_info *pXGIHWDE,
struct vb_device_info *pVBInfo)
{
@@ -3780,7 +3728,7 @@ void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE,
if (pVBInfo->IF_DEF_LVDS == 1) {
/* LVDS backlight off */
XGI_XG21BLSignalVDD(0x02, 0x00, pVBInfo);
- XGI_XG21SetPanelDelay(3, pVBInfo);
+ XGI_XG21SetPanelDelay(xgifb_info, 3, pVBInfo);
} else {
/* DVO/DVI signal off */
XGI_XG21BLSignalVDD(0x20, 0x00, pVBInfo);
@@ -3791,7 +3739,7 @@ void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE,
if ((XGI_XG27GetPSCValue(pVBInfo) & 0x2)) {
/* LVDS backlight off */
XGI_XG27BLSignalVDD(0x02, 0x00, pVBInfo);
- XGI_XG21SetPanelDelay(3, pVBInfo);
+ XGI_XG21SetPanelDelay(xgifb_info, 3, pVBInfo);
}
if (pVBInfo->IF_DEF_LVDS == 0)
@@ -3838,26 +3786,17 @@ static void XGI_GetCRT2ResInfo(unsigned short ModeNo,
if (ModeNo <= 0x13) {
xres = pVBInfo->StResInfo[resindex].HTotal;
yres = pVBInfo->StResInfo[resindex].VTotal;
- /* si+St_ResInfo */
- /* modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;*/
} else {
xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
/* si+St_ModeFlag */
modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- /*
- if (pVBInfo->IF_DEF_FSTN) {
- xres *= 2;
- yres *= 2;
- } else {
- */
if (modeflag & HalfDCLK)
xres *= 2;
if (modeflag & DoubleScanMode)
yres *= 2;
- /* } */
}
if (pVBInfo->VBInfo & SetCRT2ToLCD) {
@@ -4028,8 +3967,6 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
tempbx = 775;
else if (pVBInfo->VGAVDE == 600)
tempbx = 775;
- /* else if (pVBInfo->VGAVDE==350) tempbx=560; */
- /* else if (pVBInfo->VGAVDE==400) tempbx=640; */
else
tempbx = 768;
} else
@@ -4294,7 +4231,6 @@ static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
HwDeviceExtension, pVBInfo);
XGI_SetCRT2FIFO(pVBInfo);
- /* XGI_SetCRT2Sync(ModeNo,RefreshRateTableIndex); */
for (tempcx = 4; tempcx < 7; tempcx++)
xgifb_reg_set(pVBInfo->Part1Port, tempcx, 0x0);
@@ -4497,9 +4433,6 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
temp = 0xFF; /* set MAX HT */
xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp);
- /* if (modeflag & Charx8Dot) */
- /* tempcx = 0x08; */
- /* else */
tempcx = 0x08;
if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C))
@@ -4565,7 +4498,6 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
}
}
} else {
- /* tempcx = tempbx & 0x00FF ; */
tempbx = (tempbx & 0xFF00) >> 8;
tempcx = (tempcx + tempbx) >> 1;
temp = (tempcx & 0x00FF) + 2;
@@ -4579,36 +4511,23 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
temp -= 6;
}
}
- } else {
- if (!(modeflag & HalfDCLK)) {
- temp -= 4;
- if (pVBInfo->LCDResInfo != Panel1280x960) {
- if (pVBInfo->VGAHDE >= 800) {
- temp -= 7;
- if (pVBInfo->ModeType ==
- ModeEGA) {
- if (pVBInfo->VGAVDE ==
- 1024) {
- temp += 15;
- if (pVBInfo->LCDResInfo != Panel1280x1024) {
- temp +=
- 7;
- }
- }
- }
-
- if (pVBInfo->VGAHDE >= 1280) {
- if (pVBInfo->LCDResInfo
- != Panel1280x960) {
- if (pVBInfo->LCDInfo
- & LCDNonExpanding) {
- temp
- += 28;
- }
- }
- }
- }
+ } else if (!(modeflag & HalfDCLK)) {
+ temp -= 4;
+ if (pVBInfo->LCDResInfo != Panel1280x960 &&
+ pVBInfo->VGAHDE >= 800) {
+ temp -= 7;
+ if (pVBInfo->ModeType == ModeEGA &&
+ pVBInfo->VGAVDE == 1024) {
+ temp += 15;
+ if (pVBInfo->LCDResInfo !=
+ Panel1280x1024)
+ temp += 7;
}
+
+ if (pVBInfo->VGAHDE >= 1280 &&
+ pVBInfo->LCDResInfo != Panel1280x960 &&
+ (pVBInfo->LCDInfo & LCDNonExpanding))
+ temp += 28;
}
}
}
@@ -5297,7 +5216,6 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
tempax--;
xgifb_reg_and(pVBInfo->Part2Port, 0x01, tempax);
- /* if ( !( pVBInfo->VBType & VB_XGI301C ) ) */
xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xEF);
}
@@ -5436,7 +5354,6 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
tempax = pVBInfo->VT;
tempbx = pVBInfo->LCDVRS;
- /* if (SetLCD_Info & EnableScalingLCD) */
tempcx += tempbx;
if (tempcx >= tempax)
tempcx -= tempax;
@@ -5478,12 +5395,10 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
temp = (tempcx & 0xFF00) >> 8;
xgifb_reg_set(pVBInfo->Part2Port, 0x25, temp);
- /* getlcdsync() */
XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
tempcx = tempax;
tempax = pVBInfo->HT;
tempbx = pVBInfo->LCDHRS;
- /* if ( SetLCD_Info & EnableScalingLCD) */
if (XGI_IsLCDDualLink(pVBInfo)) {
tempax = tempax >> 1;
tempbx = tempbx >> 1;
@@ -5801,9 +5716,6 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex,
if (XGI_IsLCDDualLink(pVBInfo))
tempax = tempax >> 1;
- /* if((pVBInfo->VBInfo&(SetCRT2ToLCD)) ||
- ((pVBInfo->TVInfo&SetYPbPrMode525p) ||
- (pVBInfo->TVInfo&SetYPbPrMode750p))) { */
if (pVBInfo->VBInfo & SetCRT2ToLCD) {
if (tempax > 800)
tempax -= 800;
@@ -5817,33 +5729,6 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex,
}
tempax -= 1;
- /*
- if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVisionTV)) {
- if (pVBInfo->VBType & VB_XGI301LV) {
- if (!(pVBInfo->TVInfo &
- (SetYPbPrMode525p |
- SetYPbPrMode750p |
- SetYPbPrMode1080i))) {
- if (pVBInfo->VGAHDE > 800) {
- if (pVBInfo->VGAHDE == 1024)
- tempax =(tempax * 25 /
- 32) - 1;
- else
- tempax = (tempax * 20 /
- 32) - 1;
- }
- }
- } else {
- if (pVBInfo->VGAHDE > 800) {
- if (pVBInfo->VGAHDE == 1024)
- tempax = (tempax * 25 / 32) - 1;
- else
- tempax = (tempax * 20 / 32) - 1;
- }
- }
- }
- */
-
temp = (tempax & 0xFF00) >> 8;
temp = ((temp & 0x0003) << 4);
xgifb_reg_set(pVBInfo->Part4Port, 0x1E, temp);
@@ -5902,7 +5787,6 @@ static void XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex,
if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag
| CRT2DisplayFlag))) {
XGINew_EnableCRT2(pVBInfo);
- /* LoadDAC2(pVBInfo->Part5Port, ModeNo, ModeIdIndex); */
}
}
return;
@@ -5921,118 +5805,11 @@ static void XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_and_or(pVBInfo->P3d4, 0x63, 0xBF, 0x00);
}
-/*----------------------------------------------------------------------------*/
-/* input */
-/* bl[5] : 1;LVDS signal on */
-/* bl[1] : 1;LVDS backlight on */
-/* bl[0] : 1:LVDS VDD on */
-/* bh: 100000b : clear bit 5, to set bit5 */
-/* 000010b : clear bit 1, to set bit1 */
-/* 000001b : clear bit 0, to set bit0 */
-/*----------------------------------------------------------------------------*/
-void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
- struct vb_device_info *pVBInfo)
-{
- unsigned char CR4A, temp;
-
- CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
- tempbh &= 0x23;
- tempbl &= 0x23;
- xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
-
- if (tempbh & 0x20) {
- temp = (tempbl >> 4) & 0x02;
-
- /* CR B4[1] */
- xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
-
- }
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
-
- temp = XG21GPIODataTransfer(temp);
- temp &= ~tempbh;
- temp |= tempbl;
- xgifb_reg_set(pVBInfo->P3d4, 0x48, temp);
-}
-
-void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
- struct vb_device_info *pVBInfo)
-{
- unsigned char CR4A, temp;
- unsigned short tempbh0, tempbl0;
-
- tempbh0 = tempbh;
- tempbl0 = tempbl;
- tempbh0 &= 0x20;
- tempbl0 &= 0x20;
- tempbh0 >>= 3;
- tempbl0 >>= 3;
-
- if (tempbh & 0x20) {
- temp = (tempbl >> 4) & 0x02;
-
- /* CR B4[1] */
- xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
-
- }
- xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~tempbh0, tempbl0);
-
- CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
- tempbh &= 0x03;
- tempbl &= 0x03;
- tempbh <<= 2;
- tempbl <<= 2; /* GPIOC,GPIOD */
- xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
- xgifb_reg_and_or(pVBInfo->P3d4, 0x48, ~tempbh, tempbl);
-}
-
-/* --------------------------------------------------------------------- */
-unsigned short XGI_GetLVDSOEMTableIndex(struct vb_device_info *pVBInfo)
-{
- unsigned short index;
-
- index = xgifb_reg_get(pVBInfo->P3d4, 0x36);
- if (index < sizeof(XGI21_LCDCapList)
- / sizeof(struct XGI21_LVDSCapStruct))
- return index;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-/* Function : XGI_XG21SetPanelDelay */
-/* Input : */
-/* Output : */
-/* Description : */
-/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */
-/* : bl : 2 ; T2 : the duration signal on and Vdd on */
-/* : bl : 3 ; T3 : the duration between CPL off and signal off */
-/* : bl : 4 ; T4 : the duration signal off and Vdd off */
-/* --------------------------------------------------------------------- */
-void XGI_XG21SetPanelDelay(unsigned short tempbl,
+static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
+ unsigned short ModeNo, unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
- unsigned short index;
-
- index = XGI_GetLVDSOEMTableIndex(pVBInfo);
- if (tempbl == 1)
- mdelay(pVBInfo->XG21_LVDSCapList[index].PSC_S1);
-
- if (tempbl == 2)
- mdelay(pVBInfo->XG21_LVDSCapList[index].PSC_S2);
-
- if (tempbl == 3)
- mdelay(pVBInfo->XG21_LVDSCapList[index].PSC_S3);
-
- if (tempbl == 4)
- mdelay(pVBInfo->XG21_LVDSCapList[index].PSC_S4);
-}
-
-unsigned char XGI_XG21CheckLVDSMode(unsigned short ModeNo,
- unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
-{
- unsigned short xres, yres, colordepth, modeflag, resindex,
- lvdstableindex;
+ unsigned short xres, yres, colordepth, modeflag, resindex;
resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
if (ModeNo <= 0x13) {
@@ -6061,18 +5838,15 @@ unsigned char XGI_XG21CheckLVDSMode(unsigned short ModeNo,
}
- lvdstableindex = XGI_GetLVDSOEMTableIndex(pVBInfo);
- if (xres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE))
+ if (xres > xgifb_info->lvds_data.LVDSHDE)
return 0;
- if (yres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE))
+ if (yres > xgifb_info->lvds_data.LVDSVDE)
return 0;
if (ModeNo > 0x13) {
- if ((xres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].
- LVDSHDE)) ||
- (yres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].
- LVDSVDE))) {
+ if (xres != xgifb_info->lvds_data.LVDSHDE ||
+ yres != xgifb_info->lvds_data.LVDSVDE) {
colordepth = XGI_GetColorDepth(ModeNo,
ModeIdIndex,
pVBInfo);
@@ -6084,55 +5858,26 @@ unsigned char XGI_XG21CheckLVDSMode(unsigned short ModeNo,
return 1;
}
-void XGI_SetXG21FPBits(struct vb_device_info *pVBInfo)
-{
- unsigned char temp;
-
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x37); /* D[0] 1: 18bit */
- temp = (temp & 1) << 6;
- /* SR06[6] 18bit Dither */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x40, temp);
- /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80);
-
-}
-
-void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo)
-{
- unsigned char temp;
-
- /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
- temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
- temp = (temp & 3) << 6;
- /* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0xc0, temp & 0x80);
- /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80);
-
-}
-
-static void xgifb_set_lvds(int chip_id,
+static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info,
+ int chip_id,
unsigned short ModeNo,
unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
unsigned char temp, Miscdata;
- unsigned short xres, yres, modeflag, resindex, lvdstableindex;
+ unsigned short xres, yres, modeflag, resindex;
unsigned short LVDSHT, LVDSHBS, LVDSHRS, LVDSHRE, LVDSHBE;
unsigned short LVDSVT, LVDSVBS, LVDSVRS, LVDSVRE, LVDSVBE;
unsigned short value;
- lvdstableindex = XGI_GetLVDSOEMTableIndex(pVBInfo);
- temp = (unsigned char) ((pVBInfo->XG21_LVDSCapList[lvdstableindex].
- LVDS_Capability &
+ temp = (unsigned char) ((xgifb_info->lvds_data.LVDS_Capability &
(LCDPolarity << 8)) >> 8);
temp &= LCDPolarity;
Miscdata = (unsigned char) inb(pVBInfo->P3cc);
outb((Miscdata & 0x3F) | temp, pVBInfo->P3c2);
- temp = (unsigned char) (pVBInfo->XG21_LVDSCapList[lvdstableindex].
- LVDS_Capability & LCDPolarity);
+ temp = xgifb_info->lvds_data.LVDS_Capability & LCDPolarity;
/* SR35[7] FP VSync polarity */
xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x80, temp & 0x80);
/* SR30[5] FP HSync polarity */
@@ -6159,48 +5904,43 @@ static void xgifb_set_lvds(int chip_id,
if (!(modeflag & Charx8Dot))
xres = xres * 8 / 9;
- LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
+ LVDSHT = xgifb_info->lvds_data.LVDSHT;
- LVDSHBS = xres + (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE
- - xres) / 2;
+ LVDSHBS = xres + (xgifb_info->lvds_data.LVDSHDE - xres) / 2;
if ((ModeNo <= 0x13) && (modeflag & HalfDCLK))
LVDSHBS -= xres / 4;
if (LVDSHBS > LVDSHT)
LVDSHBS -= LVDSHT;
- LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP;
+ LVDSHRS = LVDSHBS + xgifb_info->lvds_data.LVDSHFP;
if (LVDSHRS > LVDSHT)
LVDSHRS -= LVDSHT;
- LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC;
+ LVDSHRE = LVDSHRS + xgifb_info->lvds_data.LVDSHSYNC;
if (LVDSHRE > LVDSHT)
LVDSHRE -= LVDSHT;
- LVDSHBE = LVDSHBS + LVDSHT
- - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE;
+ LVDSHBE = LVDSHBS + LVDSHT - xgifb_info->lvds_data.LVDSHDE;
- LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
+ LVDSVT = xgifb_info->lvds_data.LVDSVT;
- LVDSVBS = yres + (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE
- - yres) / 2;
+ LVDSVBS = yres + (xgifb_info->lvds_data.LVDSVDE - yres) / 2;
if ((ModeNo > 0x13) && (modeflag & DoubleScanMode))
LVDSVBS += yres / 2;
if (LVDSVBS > LVDSVT)
LVDSVBS -= LVDSVT;
- LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP;
+ LVDSVRS = LVDSVBS + xgifb_info->lvds_data.LVDSVFP;
if (LVDSVRS > LVDSVT)
LVDSVRS -= LVDSVT;
- LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].
- LVDSVSYNC;
+ LVDSVRE = LVDSVRS + xgifb_info->lvds_data.LVDSVSYNC;
if (LVDSVRE > LVDSVT)
LVDSVRE -= LVDSVT;
- LVDSVBE = LVDSVBS + LVDSVT
- - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE;
+ LVDSVBE = LVDSVBS + LVDSVT - xgifb_info->lvds_data.LVDSVDE;
temp = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
xgifb_reg_set(pVBInfo->P3d4, 0x11, temp & 0x7f); /* Unlock CRTC */
@@ -6300,13 +6040,9 @@ static void xgifb_set_lvds(int chip_id,
xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, value);
xgifb_reg_set(pVBInfo->P3c4,
- 0x2B,
- pVBInfo->XG21_LVDSCapList[lvdstableindex].
- VCLKData1);
+ 0x2B, xgifb_info->lvds_data.VCLKData1);
xgifb_reg_set(pVBInfo->P3c4,
- 0x2C,
- pVBInfo->XG21_LVDSCapList[lvdstableindex].
- VCLKData2);
+ 0x2C, xgifb_info->lvds_data.VCLKData2);
value += 0x10;
}
@@ -6398,7 +6134,8 @@ static unsigned char XGI_EnableChISLCD(struct vb_device_info *pVBInfo)
return 0;
}
-void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info,
+ struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
{
unsigned short tempah = 0;
@@ -6442,7 +6179,7 @@ void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension,
| SetSimuScanMode))) {
if (pVBInfo->SetFlag & GatingCRT)
XGI_EnableGatingCRT(HwDeviceExtension, pVBInfo);
- XGI_DisplayOff(HwDeviceExtension, pVBInfo);
+ XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
}
if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
@@ -6464,7 +6201,6 @@ void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension,
((!(pVBInfo->VBInfo & SetCRT2ToLCDA)) &&
(pVBInfo->VBInfo &
(SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV))))
- /* BScreenOff=1 */
xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80);
if ((pVBInfo->SetFlag & DisableChB) ||
@@ -6484,7 +6220,6 @@ void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension,
}
} else { /* {301} */
if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
- /* BScreenOff=1 */
xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80);
/* Disable CRT2 */
xgifb_reg_and(pVBInfo->Part1Port, 0x1E, 0xDF);
@@ -6494,7 +6229,7 @@ void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension,
if (pVBInfo->VBInfo & (DisableCRT2Display | SetCRT2ToLCDA
| SetSimuScanMode))
- XGI_DisplayOff(HwDeviceExtension, pVBInfo);
+ XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
}
}
@@ -6610,17 +6345,6 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo)
if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
tempbl = tempbl >> 4;
- /*
- if (pVBInfo->VBInfo & SetCRT2ToRAMDAC)
- tempbl = CRT2Delay1; // Get CRT2 Delay
- if (pVBInfo->VBType &
- (VB_XGI301B |
- VB_XGI302B |
- VB_XGI301LV |
- VB_XGI302LV |
- VB_XGI301C))
- tempbl = CRT2Delay2;
- */
if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
/* Get LCD Delay */
index = XGI_GetLCDCapPtr(pVBInfo);
@@ -6680,23 +6404,6 @@ static void XGI_SetLCDCap_A(unsigned short tempcx,
(unsigned short) (0x30 | (tempcx & 0x00C0)));
xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x00);
}
-
- /*
- if (tempcx & EnableLCD24bpp) { // 24bits
- xgifb_reg_and_or(pVBInfo->Part1Port,
- 0x19,
- 0x0F,
- (unsigned short)(0x30 | (tempcx&0x00C0)));
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x00);
- } else {
- xgifb_reg_and_or(pVBInfo->Part1Port,
- 0x19,
- 0x0F,
- // Enable Dither
- (unsigned short)(0x20 | (tempcx&0x00C0)));
- xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x80);
- }
- */
}
/* --------------------------------------------------------------------- */
@@ -6718,6 +6425,25 @@ static void XGI_SetLCDCap_B(unsigned short tempcx,
| 0x18)); /* Enable Dither */
}
+static void XGI_LongWait(struct vb_device_info *pVBInfo)
+{
+ unsigned short i;
+
+ i = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
+
+ if (!(i & 0xC0)) {
+ for (i = 0; i < 0xFFFF; i++) {
+ if (!(inb(pVBInfo->P3da) & 0x08))
+ break;
+ }
+
+ for (i = 0; i < 0xFFFF; i++) {
+ if ((inb(pVBInfo->P3da) & 0x08))
+ break;
+ }
+ }
+}
+
static void SetSpectrum(struct vb_device_info *pVBInfo)
{
unsigned short index;
@@ -6940,14 +6666,12 @@ static void XGI_OEM310Setting(unsigned short ModeNo,
unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
- /* GetPart1IO(); */
XGI_SetDelayComp(pVBInfo);
if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))
XGI_SetLCDCap(pVBInfo);
if (pVBInfo->VBInfo & SetCRT2ToTV) {
- /* GetPart2IO() */
XGI_SetPhaseIncr(pVBInfo);
XGI_SetYFilter(ModeNo, ModeIdIndex, pVBInfo);
XGI_SetAntiFlicker(ModeNo, ModeIdIndex, pVBInfo);
@@ -6963,7 +6687,7 @@ static void XGI_OEM310Setting(unsigned short ModeNo,
/* Output : */
/* Description : Origin code for crt2group */
/* --------------------------------------------------------------------- */
-void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
+static void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
{
@@ -6972,8 +6696,6 @@ void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
unsigned char tempah;
- /* // fix write part1 index 0 BTDRAM bit Bug
- * xgifb_reg_set(pVBInfo->Part1Port, 0x03, 0x00); */
tempah = 0;
if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x00);
@@ -6999,32 +6721,6 @@ void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
}
}
- /* 0210 shampoo
- if (pVBInfo->VBInfo & DisableCRT2Display) {
- tempah = 0;
- }
-
- xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
- if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD)) {
- tempcl = pVBInfo->ModeType;
- if (ModeNo > 0x13) {
- tempcl -= ModeVGA;
- if ((tempcl > 0) || (tempcl == 0)) {
- tempah=(0x008>>tempcl) ;
- if (tempah == 0)
- tempah = 1;
- tempah |= 0x040;
- }
- } else {
- tempah = 0x040;
- }
-
- if (pVBInfo->VBInfo & SetInSlaveMode) {
- tempah = (tempah ^ 0x050);
- }
- }
- */
-
xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
tempah = 0x08;
tempbl = 0xf0;
@@ -7093,14 +6789,11 @@ void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
tempah |= 0x080;
if (pVBInfo->VBInfo & SetCRT2ToTV) {
- /* if (!(pVBInfo->TVInfo &
- (SetYPbPrMode525p | SetYPbPrMode750p))) { */
tempah |= 0x020;
if (ModeNo > 0x13) {
if (pVBInfo->VBInfo & DriverMode)
tempah = tempah ^ 0x20;
}
- /* } */
}
xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D, ~0x0BF, tempah);
@@ -7110,12 +6803,8 @@ void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
tempah |= 0x40;
if (pVBInfo->VBInfo & SetCRT2ToTV) {
- /* if ((!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV)) &&
- (!(pVBInfo->TVInfo &
- (SetYPbPrMode525p | SetYPbPrMode750p)))) { */
if (pVBInfo->TVInfo & RPLLDIV2XO)
tempah |= 0x40;
- /* } */
}
if ((pVBInfo->LCDResInfo == Panel1280x1024)
@@ -7219,57 +6908,6 @@ unsigned char XGI_BridgeIsOn(struct vb_device_info *pVBInfo)
}
}
-void XGI_LongWait(struct vb_device_info *pVBInfo)
-{
- unsigned short i;
-
- i = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
-
- if (!(i & 0xC0)) {
- for (i = 0; i < 0xFFFF; i++) {
- if (!(inb(pVBInfo->P3da) & 0x08))
- break;
- }
-
- for (i = 0; i < 0xFFFF; i++) {
- if ((inb(pVBInfo->P3da) & 0x08))
- break;
- }
- }
-}
-
-static void XGI_VBLongWait(struct vb_device_info *pVBInfo)
-{
- unsigned short tempal, temp, i, j;
- return;
- if (!(pVBInfo->VBInfo & SetCRT2ToTV)) {
- temp = 0;
- for (i = 0; i < 3; i++) {
- for (j = 0; j < 100; j++) {
- tempal = inb(pVBInfo->P3da);
- if (temp & 0x01) { /* VBWaitMode2 */
- if ((tempal & 0x08))
- continue;
-
- if (!(tempal & 0x08))
- break;
-
- } else { /* VBWaitMode1 */
- if (!(tempal & 0x08))
- continue;
-
- if ((tempal & 0x08))
- break;
- }
- }
- temp = temp ^ 0x01;
- }
- } else {
- XGI_LongWait(pVBInfo);
- }
- return;
-}
-
unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
unsigned short ModeNo, unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
@@ -7322,12 +6960,6 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
RefreshRateTableIndex = pVBInfo->EModeIDTable[ModeIdIndex].REFindex;
ModeNo = pVBInfo->RefIndex[RefreshRateTableIndex].ModeID;
if (pXGIHWDE->jChipType >= XG20) { /* for XG20, XG21, XG27 */
- /*
- if (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag &
- XG2xNotSupport) {
- index++;
- }
- */
if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 800) &&
(pVBInfo->RefIndex[RefreshRateTableIndex].YRes == 600)) {
index++;
@@ -7371,7 +7003,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
temp = XGI_AjustCRT2Rate(ModeNo, ModeIdIndex,
RefreshRateTableIndex, &i, pVBInfo);
}
- return RefreshRateTableIndex + i; /* return (0x01 | (temp1<<1)); */
+ return RefreshRateTableIndex + i;
}
static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,
@@ -7379,9 +7011,6 @@ static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
unsigned short RefreshRateTableIndex;
- /* unsigned short temp ; */
-
- /* pVBInfo->SelectCRT2Rate = 0; */
pVBInfo->SetFlag |= ProgrammingCRT2;
RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
@@ -7394,7 +7023,7 @@ static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,
XGI_SetCRT2ECLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
}
-unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
+static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
{
@@ -7499,10 +7128,6 @@ void XGI_SenseCRT1(struct vb_device_info *pVBInfo)
outb((unsigned char) DAC_TEST_PARMS[2], (pVBInfo->P3c8 + 1));
}
- XGI_VBLongWait(pVBInfo);
- XGI_VBLongWait(pVBInfo);
- XGI_VBLongWait(pVBInfo);
-
mdelay(1);
XGI_WaitDisply(pVBInfo);
@@ -7532,7 +7157,8 @@ void XGI_SenseCRT1(struct vb_device_info *pVBInfo)
xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char) SR1F);
}
-void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info,
+ struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *pVBInfo)
{
unsigned short tempah;
@@ -7544,7 +7170,6 @@ void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
/* Power on */
xgifb_reg_set(pVBInfo->Part1Port, 0x1E, 0x20);
} else {
- /* SetCRT2ToLCDA ) */
if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
/* Power on */
xgifb_reg_set(pVBInfo->Part1Port,
@@ -7572,10 +7197,8 @@ void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
pVBInfo->Part1Port, 0x2E);
if (!(tempah & 0x80))
- /* BVBDOENABLE = 1 */
xgifb_reg_or(pVBInfo->Part1Port,
0x2E, 0x80);
- /* BScreenOFF = 0 */
xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F);
}
}
@@ -7638,12 +7261,11 @@ void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
xgifb_reg_or(pVBInfo->Part4Port, 0x1F, tempah);
if (!(pVBInfo->SetFlag & DisableChA)) {
- XGI_VBLongWait(pVBInfo);
if (!(pVBInfo->SetFlag & GatingCRT)) {
XGI_DisableGatingCRT(HwDeviceExtension,
pVBInfo);
- XGI_DisplayOn(HwDeviceExtension, pVBInfo);
- XGI_VBLongWait(pVBInfo);
+ XGI_DisplayOn(xgifb_info, HwDeviceExtension,
+ pVBInfo);
}
}
} /* 301 */
@@ -7656,15 +7278,15 @@ void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
tempah = (unsigned char) xgifb_reg_get(pVBInfo->Part1Port,
0x2E);
if (!(tempah & 0x80))
- /* BVBDOENABLE = 1 */
xgifb_reg_or(pVBInfo->Part1Port, 0x2E, 0x80);
xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F);
- XGI_DisplayOn(HwDeviceExtension, pVBInfo);
+ XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
} /* End of VB */
}
-static void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
+ struct xgi_hw_device_info *HwDeviceExtension,
unsigned short ModeNo, unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
@@ -7672,18 +7294,14 @@ static void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
unsigned short XGINew_P3cc = pVBInfo->P3cc;
- /* XGINew_CRT1Mode = ModeNo; // SaveModeID */
StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
- /* XGI_SetBIOSData(ModeNo, ModeIdIndex); */
- /* XGI_ClearBankRegs(ModeNo, ModeIdIndex); */
XGI_SetSeqRegs(ModeNo, StandTableIndex, ModeIdIndex, pVBInfo);
- XGI_SetMiscRegs(StandTableIndex, pVBInfo);
+ outb(pVBInfo->StandTable[StandTableIndex].MISC, pVBInfo->P3c2);
XGI_SetCRTCRegs(HwDeviceExtension, StandTableIndex, pVBInfo);
XGI_SetATTRegs(ModeNo, StandTableIndex, ModeIdIndex, pVBInfo);
XGI_SetGRCRegs(StandTableIndex, pVBInfo);
XGI_ClearExt1Regs(pVBInfo);
- /* if (pVBInfo->IF_DEF_ExpLink) */
if (HwDeviceExtension->jChipType == XG27) {
if (pVBInfo->IF_DEF_LVDS == 0)
XGI_SetDefaultVCLK(pVBInfo);
@@ -7735,11 +7353,6 @@ static void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
if (temp & 0xA0) {
- /* Enable write GPIOF */
- /* xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x20); */
- /* P. DWN */
- /* xgifb_reg_and(pVBInfo->P3d4, 0x48, ~0x20); */
- /* XG21 CRT1 Timing */
if (HwDeviceExtension->jChipType == XG27)
XGI_SetXG27CRTC(ModeNo, ModeIdIndex,
RefreshRateTableIndex, pVBInfo);
@@ -7754,10 +7367,9 @@ static void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
pVBInfo, RefreshRateTableIndex, ModeNo);
if (pVBInfo->IF_DEF_LVDS == 1)
- xgifb_set_lvds(HwDeviceExtension->jChipType,
+ xgifb_set_lvds(xgifb_info,
+ HwDeviceExtension->jChipType,
ModeNo, ModeIdIndex, pVBInfo);
- /* P. ON */
- /* xgifb_reg_or(pVBInfo->P3d4, 0x48, 0x20); */
}
}
@@ -7765,22 +7377,16 @@ static void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
XGI_SetCRT1FIFO(ModeNo, HwDeviceExtension, pVBInfo);
XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeNo, ModeIdIndex,
RefreshRateTableIndex, pVBInfo);
-
- /* XGI_LoadCharacter(); //dif ifdef TVFont */
-
XGI_LoadDAC(ModeNo, ModeIdIndex, pVBInfo);
- /* XGI_ClearBuffer(HwDeviceExtension, ModeNo, pVBInfo); */
}
-unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
+unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
+ struct xgi_hw_device_info *HwDeviceExtension,
unsigned short ModeNo)
{
unsigned short ModeIdIndex;
- /* unsigned char *pVBInfo->FBAddr =
- HwDeviceExtension->pjVideoMemoryAddress; */
struct vb_device_info VBINF;
struct vb_device_info *pVBInfo = &VBINF;
- pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
pVBInfo->IF_DEF_LVDS = 0;
pVBInfo->IF_DEF_LCDA = 1;
@@ -7831,14 +7437,8 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
XGI_GetVBType(pVBInfo);
InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
- if (ModeNo & 0x80) {
+ if (ModeNo & 0x80)
ModeNo = ModeNo & 0x7F;
- /* XGINew_flag_clearbuffer = 0; */
- }
- /* else {
- XGINew_flag_clearbuffer = 1;
- }
- */
xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 1.Openkey */
@@ -7846,16 +7446,14 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo);
- XGI_GetVGAType(HwDeviceExtension, pVBInfo);
-
if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
XGI_GetVBInfo(ModeNo, ModeIdIndex, HwDeviceExtension, pVBInfo);
XGI_GetTVInfo(ModeNo, ModeIdIndex, pVBInfo);
XGI_GetLCDInfo(ModeNo, ModeIdIndex, pVBInfo);
- XGI_DisableBridge(HwDeviceExtension, pVBInfo);
+ XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
if (pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) {
- XGI_SetCRT1Group(HwDeviceExtension, ModeNo,
+ XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo,
ModeIdIndex, pVBInfo);
if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
@@ -7864,7 +7462,8 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
}
} else {
if (!(pVBInfo->VBInfo & SwitchToCRT2)) {
- XGI_SetCRT1Group(HwDeviceExtension, ModeNo,
+ XGI_SetCRT1Group(xgifb_info,
+ HwDeviceExtension, ModeNo,
ModeIdIndex, pVBInfo);
if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
XGI_SetLCDAGroup(ModeNo, ModeIdIndex,
@@ -7894,11 +7493,11 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
XGI_SetCRT2ModeRegs(ModeNo, HwDeviceExtension, pVBInfo);
XGI_OEM310Setting(ModeNo, ModeIdIndex, pVBInfo); /*0212*/
XGI_CloseCRTC(HwDeviceExtension, pVBInfo);
- XGI_EnableBridge(HwDeviceExtension, pVBInfo);
+ XGI_EnableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
} /* !XG20 */
else {
if (pVBInfo->IF_DEF_LVDS == 1)
- if (!XGI_XG21CheckLVDSMode(ModeNo,
+ if (!XGI_XG21CheckLVDSMode(xgifb_info, ModeNo,
ModeIdIndex,
pVBInfo))
return 0;
@@ -7914,39 +7513,13 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
pVBInfo->SetFlag = 0;
pVBInfo->VBInfo = DisableCRT2Display;
- XGI_DisplayOff(HwDeviceExtension, pVBInfo);
+ XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
- XGI_SetCRT1Group(HwDeviceExtension, ModeNo, ModeIdIndex,
- pVBInfo);
+ XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo,
+ ModeIdIndex, pVBInfo);
- XGI_DisplayOn(HwDeviceExtension, pVBInfo);
- /*
- if (HwDeviceExtension->jChipType == XG21)
- xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0x80, 0x80);
- */
- }
-
- /*
- if (ModeNo <= 0x13) {
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
}
- pVBInfo->ModeType = modeflag&ModeInfoFlag;
- pVBInfo->SetFlag = 0x00;
- pVBInfo->VBInfo = DisableCRT2Display;
- temp = XGINew_CheckMemorySize(HwDeviceExtension,
- ModeNo,
- ModeIdIndex,
- pVBInfo);
-
- if (temp == 0)
- return (0);
-
- XGI_DisplayOff(HwDeviceExtension, pVBInfo) ;
- XGI_SetCRT1Group(HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo);
- XGI_DisplayOn(HwDeviceExtension, pVBInfo);
- */
XGI_UpdateModeInfo(HwDeviceExtension, pVBInfo);
diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
index 1bd8667ff5cf..552482858c1c 100644
--- a/drivers/staging/xgifb/vb_setmode.h
+++ b/drivers/staging/xgifb/vb_setmode.h
@@ -6,66 +6,22 @@ extern void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *);
extern void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
struct vb_device_info *);
-extern void XGI_LongWait(struct vb_device_info *);
-extern void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
- struct xgi_hw_device_info *,
- struct vb_device_info *);
-extern void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *);
-extern void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *);
-extern void XGI_DisplayOff(struct xgi_hw_device_info *,
+extern void XGI_DisplayOff(struct xgifb_video_info *,
+ struct xgi_hw_device_info *,
struct vb_device_info *);
-extern void XGI_DisplayOn(struct xgi_hw_device_info *,
- struct vb_device_info *);
extern void XGI_GetVBType(struct vb_device_info *);
extern void XGI_SenseCRT1(struct vb_device_info *);
-extern void XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *);
-extern void XGI_GetVBInfo(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *);
-extern void XGI_GetTVInfo(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *);
-extern unsigned short XGI_GetResInfo(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo);
-
-extern unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
+extern unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
+ struct xgi_hw_device_info *HwDeviceExtension,
unsigned short ModeNo) ;
extern unsigned char XGI_SearchModeID(unsigned short ModeNo,
unsigned short *ModeIdIndex,
struct vb_device_info *);
-extern unsigned char XGI_GetLCDInfo(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *);
extern unsigned char XGI_BridgeIsOn(struct vb_device_info *);
-
-extern unsigned char
-XGI_SetCRT2Group301(unsigned short ModeNo,
- struct xgi_hw_device_info *HwDeviceExtension,
- struct vb_device_info *);
extern unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
unsigned short ModeNo,
unsigned short ModeIdIndex,
struct vb_device_info *);
-extern void XGI_SetXG21FPBits(struct vb_device_info *pVBInfo);
-extern void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo);
-extern void XGI_XG21BLSignalVDD(unsigned short tempbh,
- unsigned short tempbl,
- struct vb_device_info *pVBInfo);
-extern void XGI_XG27BLSignalVDD(unsigned short tempbh,
- unsigned short tempbl,
- struct vb_device_info *pVBInfo);
-extern void XGI_XG21SetPanelDelay(unsigned short tempbl,
- struct vb_device_info *pVBInfo);
-extern unsigned char XGI_XG21CheckLVDSMode(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo);
-extern unsigned short XGI_GetLVDSOEMTableIndex(struct vb_device_info *pVBInfo);
-
#endif
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
index f9ade6f9f7ee..6556a0d6ff82 100644
--- a/drivers/staging/xgifb/vb_struct.h
+++ b/drivers/staging/xgifb/vb_struct.h
@@ -293,13 +293,12 @@ struct vb_device_info {
unsigned short IF_DEF_ExpLink;
unsigned short IF_DEF_HiVision;
unsigned short LCDResInfo, LCDTypeInfo, VBType;/*301b*/
- unsigned short VBInfo, TVInfo, LCDInfo, Set_VGAType;
+ unsigned short VBInfo, TVInfo, LCDInfo;
unsigned short VBExtInfo;/*301lv*/
unsigned short SetFlag;
unsigned short NewFlickerMode;
unsigned short SelectCRT2Rate;
- unsigned char *ROMAddr;
void __iomem *FBAddr;
unsigned long BaseAddr;
unsigned long RelIO;
@@ -376,7 +375,6 @@ struct vb_device_info {
unsigned char *pXGINew_CR97 ;
struct XGI330_LCDCapStruct *LCDCapList;
- struct XGI21_LVDSCapStruct *XG21_LVDSCapList;
struct XGI_TimingHStruct *TimingH;
struct XGI_TimingVStruct *TimingV;
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
index b81ac7726d1c..e7946f1c1143 100644
--- a/drivers/staging/xgifb/vb_table.h
+++ b/drivers/staging/xgifb/vb_table.h
@@ -2569,33 +2569,6 @@ static struct XGI330_LCDCapStruct XGI_LCDCapList[] = {
0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
};
-struct XGI21_LVDSCapStruct XGI21_LCDCapList[] = {
- {DisableLCD24bpp + LCDPolarity,
- 2160, 1250, 1600, 1200, 64, 1, 192, 3,
- 0x70, 0x24, 0x20, 0x04, 0x0A, 0x02, 0xC8
- },
- {DisableLCD24bpp + LCDPolarity,
- 1688, 1066, 1280, 1024, 48, 1, 112, 3,
- 0x70, 0x44, 0x20, 0x04, 0x0A, 0x02, 0xC8
- },
- {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8),
- 1344, 806, 1024, 768, 24, 3, 136, 6,
- 0x6C, 0x65, 0x20, 0x04, 0x0A, 0x02, 0xC8
- },
- {DisableLCD24bpp + LCDPolarity,
- 1056, 628, 800, 600, 40, 1, 128, 4,
- 0x42, 0xE2, 0x20, 0x14, 0x0A, 0x02, 0x00
- },
- {DisableLCD24bpp + LCDPolarity,
- 928, 525, 800, 480, 40, 13, 48, 3,
- 0x52, 0xC5, 0x20, 0x14, 0x0A, 0x02, 0x00
- },
- {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8),
- 800, 525, 640, 480, 16, 10, 96, 2,
- 0x1B, 0xE1, 0x20, 0x04, 0x0A, 0x02, 0xC8
- }
-};
-
static struct XGI_Ext2Struct XGI330_RefIndex[] = {
{Support32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175,
0x00, 0x10, 0x59, 320, 200},/* 00 */
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
index 9b939b75c309..9e166bbb00c4 100644
--- a/drivers/staging/xgifb/vgatypes.h
+++ b/drivers/staging/xgifb/vgatypes.h
@@ -51,8 +51,6 @@ struct xgi_hw_device_info {
unsigned long ulExternalChip; /* NO VB or other video bridge*/
/* if ujVBChipID = VB_CHIP_UNKNOWN, */
- unsigned char *pjVirtualRomBase; /* ROM image */
-
void __iomem *pjVideoMemoryAddress;/* base virtual memory address */
/* of Linear VGA memory */
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c
index 56c1f9c80dc1..642840c612ac 100644
--- a/drivers/staging/zcache/zcache-main.c
+++ b/drivers/staging/zcache/zcache-main.c
@@ -787,7 +787,7 @@ static ssize_t zv_max_zsize_store(struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- err = strict_strtoul(buf, 10, &val);
+ err = kstrtoul(buf, 10, &val);
if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7))
return -EINVAL;
zv_max_zsize = val;
@@ -819,7 +819,7 @@ static ssize_t zv_max_mean_zsize_store(struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- err = strict_strtoul(buf, 10, &val);
+ err = kstrtoul(buf, 10, &val);
if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7))
return -EINVAL;
zv_max_mean_zsize = val;
@@ -853,7 +853,7 @@ static ssize_t zv_page_count_policy_percent_store(struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- err = strict_strtoul(buf, 10, &val);
+ err = kstrtoul(buf, 10, &val);
if (err || (val == 0) || (val > 150))
return -EINVAL;
zv_page_count_policy_percent = val;
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 09de99fbb7e0..2a2a92d389e6 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -653,7 +653,8 @@ int zram_init_device(struct zram *zram)
goto fail_no_table;
}
- zram->compress_buffer = (void *)__get_free_pages(__GFP_ZERO, 1);
+ zram->compress_buffer =
+ (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
if (!zram->compress_buffer) {
pr_err("Error allocating compressor buffer space\n");
ret = -ENOMEM;
diff --git a/drivers/staging/zram/zram_sysfs.c b/drivers/staging/zram/zram_sysfs.c
index 0ea8ed296a9d..d521122826f6 100644
--- a/drivers/staging/zram/zram_sysfs.c
+++ b/drivers/staging/zram/zram_sysfs.c
@@ -58,7 +58,7 @@ static ssize_t disksize_store(struct device *dev,
u64 disksize;
struct zram *zram = dev_to_zram(dev);
- ret = strict_strtoull(buf, 10, &disksize);
+ ret = kstrtoull(buf, 10, &disksize);
if (ret)
return ret;
@@ -88,7 +88,7 @@ static ssize_t reset_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
int ret;
- unsigned long do_reset;
+ unsigned short do_reset;
struct zram *zram;
struct block_device *bdev;
@@ -99,7 +99,7 @@ static ssize_t reset_store(struct device *dev,
if (bdev->bd_holders)
return -EBUSY;
- ret = strict_strtoul(buf, 10, &do_reset);
+ ret = kstrtou16(buf, 10, &do_reset);
if (ret)
return ret;