Pull staging driver updates from Greg KH: "Here is the big staging driver pull request for 4.5-rc1. Lots of cleanups and fixes here, not as many as some releases, but 800+ isn't that bad. Full details in the shortlog. All of these have been in linux-next for a while" * tag 'staging-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (843 commits) Revert "arm64: dts: Add dts files to enable ION on Hi6220 SoC." staging: gdm724x: constify tty_port_operations structs staging: gdm72xx: add userspace data struct staging: gdm72xx: Replace timeval with ktime_t iio: adc: ina2xx: Fix incorrect report of data endianness to userspace. iio: light: us5182d: Refactor read_raw function iio: light: us5182d: Add interrupt support and events iio: light: us5182d: Fix enable status inconcistency iio: Make IIO value formating function globally available. staging: emxx_udc: use list_first_entry_or_null() staging/emxx_udc: fix 64-bit warnings STAGING: COMEDI: Using kernel types in plx9080.h STAGING: COMEDI: Added spaces around binary operators in plx9080.h STAGING: COMEDI: Fixed format of comments in plx9080.h staging: comedi: comedilib.h: Coding style warning fix for block comments staging: comedi: s526: add macros for counter control reg values staging: comedi: s526: replace counter mode bitfield struct staging: comedi: check for more errors for zero-length write staging: comedi: simplify returned errors for comedi_write() staging: comedi: return error on "write" if no command set up ...
Unified · Split
| @@ -0,0 +1,21 @@ | ||
| 1 | +What: /config/iio | |
| 2 | +Date: October 2015 | |
| 3 | +KernelVersion: 4.4 | |
| 4 | +Contact: linux-iio@vger.kernel.org | |
| 5 | +Description: | |
| 6 | + This represents Industrial IO configuration entry point | |
| 7 | + directory. It contains sub-groups corresponding to IIO | |
| 8 | + objects. | |
| 9 | + | |
| 10 | +What: /config/iio/triggers | |
| 11 | +Date: October 2015 | |
| 12 | +KernelVersion: 4.4 | |
| 13 | +Description: | |
| 14 | + Industrial IO software triggers directory. | |
| 15 | + | |
| 16 | +What: /config/iio/triggers/hrtimers | |
| 17 | +Date: October 2015 | |
| 18 | +KernelVersion: 4.4 | |
| 19 | +Description: | |
| 20 | + High resolution timers directory. Creating a directory here | |
| 21 | + will result in creating a hrtimer trigger in the IIO subsystem. | |
| @@ -0,0 +1,24 @@ | ||
| 1 | +What: /sys/bus/iio/devices/iio:deviceX/in_allow_async_readout | |
| 2 | +Date: December 2015 | |
| 3 | +KernelVersion: 4.4 | |
| 4 | +Contact: linux-iio@vger.kernel.org | |
| 5 | +Description: | |
| 6 | + By default (value '0'), the capture thread checks for the Conversion | |
| 7 | + Ready Flag to being set prior to committing a new value to the sample | |
| 8 | + buffer. This synchronizes the in-chip conversion rate with the | |
| 9 | + in-driver readout rate at the cost of an additional register read. | |
| 10 | + | |
| 11 | + Writing '1' will remove the polling for the Conversion Ready Flags to | |
| 12 | + save the additional i2c transaction, which will improve the bandwidth | |
| 13 | + available for reading data. However, samples can be occasionally skipped | |
| 14 | + or repeated, depending on the beat between the capture and conversion | |
| 15 | + rates. | |
| 16 | + | |
| 17 | +What: /sys/bus/iio/devices/iio:deviceX/in_shunt_resistor | |
| 18 | +Date: December 2015 | |
| 19 | +KernelVersion: 4.4 | |
| 20 | +Contact: linux-iio@vger.kernel.org | |
| 21 | +Description: | |
| 22 | + The value of the shunt resistor may be known only at runtime fom an | |
| 23 | + eeprom content read by a client application. This attribute allows to | |
| 24 | + set its value in ohms. | |
| @@ -20,6 +20,7 @@ adi,adt7476 +/-1C TDM Extended Temp Range I.C · 19 unmodified lines | ||
| 20 | 20 | adi,adt7490 +/-1C TDM Extended Temp Range I.C |
| 21 | 21 | adi,adxl345 Three-Axis Digital Accelerometer |
| 22 | 22 | adi,adxl346 Three-Axis Digital Accelerometer (backward-compatibility value "adi,adxl345" must be listed too) |
| 23 | +ams,iaq-core AMS iAQ-Core VOC Sensor | |
| 23 | 24 | at,24c08 i2c serial eeprom (24cxx) |
| 24 | 25 | atmel,24c00 i2c serial eeprom (24cxx) |
| 25 | 26 | atmel,24c01 i2c serial eeprom (24cxx) |
| @@ -7,13 +7,18 @@ Required properties: · 6 unmodified lines | ||
| 7 | 7 | * "fsl,mma8453" |
| 8 | 8 | * "fsl,mma8652" |
| 9 | 9 | * "fsl,mma8653" |
| 10 | + | |
| 10 | 11 | - reg: the I2C address of the chip |
| 11 | 12 | |
| 12 | 13 | Optional properties: |
| 13 | 14 | |
| 14 | 15 | - interrupt-parent: should be the phandle for the interrupt controller |
| 16 | + | |
| 15 | 17 | - interrupts: interrupt mapping for GPIO IRQ |
| 16 | 18 | |
| 19 | + - interrupt-names: should contain "INT1" and/or "INT2", the accelerometer's | |
| 20 | + interrupt line in use. | |
| 21 | + | |
| 17 | 22 | Example: |
| 18 | 23 | |
| 19 | 24 | mma8453fc@1d { |
| @@ -21,4 +26,5 @@ Example: · 1 unmodified line | ||
| 21 | 26 | reg = <0x1d>; |
| 22 | 27 | interrupt-parent = <&gpio1>; |
| 23 | 28 | interrupts = <5 0>; |
| 29 | + interrupt-names = "INT2"; | |
| 24 | 30 | }; |
| @@ -0,0 +1,22 @@ | ||
| 1 | +Freescale imx7d ADC bindings | |
| 2 | + | |
| 3 | +The devicetree bindings are for the ADC driver written for | |
| 4 | +imx7d SoC. | |
| 5 | + | |
| 6 | +Required properties: | |
| 7 | +- compatible: Should be "fsl,imx7d-adc" | |
| 8 | +- reg: Offset and length of the register set for the ADC device | |
| 9 | +- interrupts: The interrupt number for the ADC device | |
| 10 | +- clocks: The root clock of the ADC controller | |
| 11 | +- clock-names: Must contain "adc", matching entry in the clocks property | |
| 12 | +- vref-supply: The regulator supply ADC reference voltage | |
| 13 | + | |
| 14 | +Example: | |
| 15 | +adc1: adc@30610000 { | |
| 16 | + compatible = "fsl,imx7d-adc"; | |
| 17 | + reg = <0x30610000 0x10000>; | |
| 18 | + interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; | |
| 19 | + clocks = <&clks IMX7D_ADC_ROOT_CLK>; | |
| 20 | + clock-names = "adc"; | |
| 21 | + vref-supply = <®_vcc_3v3_mcu>; | |
| 22 | +}; | |
| @@ -10,16 +10,28 @@ must be specified. · 9 unmodified lines | ||
| 10 | 10 | Required properties: |
| 11 | 11 | - compatible: Must be one of the following, depending on the |
| 12 | 12 | model: |
| 13 | − "mcp3001" | |
| 14 | − "mcp3002" | |
| 15 | − "mcp3004" | |
| 16 | − "mcp3008" | |
| 17 | − "mcp3201" | |
| 18 | − "mcp3202" | |
| 19 | − "mcp3204" | |
| 20 | − "mcp3208" | |
| 21 | − "mcp3301" | |
| 13 | + "mcp3001" (DEPRECATED) | |
| 14 | + "mcp3002" (DEPRECATED) | |
| 15 | + "mcp3004" (DEPRECATED) | |
| 16 | + "mcp3008" (DEPRECATED) | |
| 17 | + "mcp3201" (DEPRECATED) | |
| 18 | + "mcp3202" (DEPRECATED) | |
| 19 | + "mcp3204" (DEPRECATED) | |
| 20 | + "mcp3208" (DEPRECATED) | |
| 21 | + "mcp3301" (DEPRECATED) | |
| 22 | 22 | |
| 23 | + "microchip,mcp3001" | |
| 24 | + "microchip,mcp3002" | |
| 25 | + "microchip,mcp3004" | |
| 26 | + "microchip,mcp3008" | |
| 27 | + "microchip,mcp3201" | |
| 28 | + "microchip,mcp3202" | |
| 29 | + "microchip,mcp3204" | |
| 30 | + "microchip,mcp3208" | |
| 31 | + "microchip,mcp3301" | |
| 32 | + | |
| 33 | + NOTE: The use of the compatibles with no vendor prefix | |
| 34 | + is deprecated and only listed because old DT use them. | |
| 23 | 35 | |
| 24 | 36 | Examples: |
| 25 | 37 | spi_controller { |
| @@ -1,7 +1,8 @@ | ||
| 1 | −* Microchip mcp3422/3/4/6/7/8 chip family (ADC) | |
| 1 | +* Microchip mcp3421/2/3/4/6/7/8 chip family (ADC) | |
| 2 | 2 | |
| 3 | 3 | Required properties: |
| 4 | 4 | - compatible: Should be |
| 5 | + "microchip,mcp3421" or | |
| 5 | 6 | "microchip,mcp3422" or |
| 6 | 7 | "microchip,mcp3423" or |
| 7 | 8 | "microchip,mcp3424" or |
| @@ -0,0 +1,48 @@ | ||
| 1 | +* Palmas general purpose ADC IP block devicetree bindings | |
| 2 | + | |
| 3 | +Channels list: | |
| 4 | + 0 battery type | |
| 5 | + 1 battery temp NTC (optional current source) | |
| 6 | + 2 GP | |
| 7 | + 3 temp (with ext. diode, optional current source) | |
| 8 | + 4 GP | |
| 9 | + 5 GP | |
| 10 | + 6 VBAT_SENSE | |
| 11 | + 7 VCC_SENSE | |
| 12 | + 8 Backup Battery voltage | |
| 13 | + 9 external charger (VCHG) | |
| 14 | + 10 VBUS | |
| 15 | + 11 DC-DC current probe (how does this work?) | |
| 16 | + 12 internal die temp | |
| 17 | + 13 internal die temp | |
| 18 | + 14 USB ID pin voltage | |
| 19 | + 15 test network | |
| 20 | + | |
| 21 | +Required properties: | |
| 22 | +- compatible : Must be "ti,palmas-gpadc". | |
| 23 | +- #io-channel-cells: Should be set to <1>. | |
| 24 | + | |
| 25 | +Optional sub-nodes: | |
| 26 | +ti,channel0-current-microamp: Channel 0 current in uA. | |
| 27 | + Values are rounded to derive 0uA, 5uA, 15uA, 20uA. | |
| 28 | +ti,channel3-current-microamp: Channel 3 current in uA. | |
| 29 | + Values are rounded to derive 0uA, 10uA, 400uA, 800uA. | |
| 30 | +ti,enable-extended-delay: Enable extended delay. | |
| 31 | + | |
| 32 | +Example: | |
| 33 | + | |
| 34 | +pmic { | |
| 35 | + compatible = "ti,twl6035-pmic", "ti,palmas-pmic"; | |
| 36 | + ... | |
| 37 | + gpadc { | |
| 38 | + compatible = "ti,palmas-gpadc"; | |
| 39 | + interrupts = <18 0 | |
| 40 | + 16 0 | |
| 41 | + 17 0>; | |
| 42 | + #io-channel-cells = <1>; | |
| 43 | + ti,channel0-current-microamp = <5>; | |
| 44 | + ti,channel3-current-microamp = <10>; | |
| 45 | + }; | |
| 46 | + }; | |
| 47 | + ... | |
| 48 | +}; | |
| @@ -1,7 +1,7 @@ | ||
| 1 | −* Texas Instruments' ADC128S052 and ADC122S021 ADC chip | |
| 1 | +* Texas Instruments' ADC128S052, ADC122S021 and ADC124S021 ADC chip | |
| 2 | 2 | |
| 3 | 3 | Required properties: |
| 4 | − - compatible: Should be "ti,adc128s052" or "ti,adc122s021" | |
| 4 | + - compatible: Should be "ti,adc128s052", "ti,adc122s021" or "ti,adc124s021" | |
| 5 | 5 | - reg: spi chip select number for the device |
| 6 | 6 | - vref-supply: The regulator supply for ADC reference voltage |
| 7 | 7 | |
| @@ -0,0 +1,20 @@ | ||
| 1 | +* Texas Instruments' ADS8684 and ADS8688 ADC chip | |
| 2 | + | |
| 3 | +Required properties: | |
| 4 | + - compatible: Should be "ti,ads8684" or "ti,ads8688" | |
| 5 | + - reg: spi chip select number for the device | |
| 6 | + | |
| 7 | +Recommended properties: | |
| 8 | + - spi-max-frequency: Definition as per | |
| 9 | + Documentation/devicetree/bindings/spi/spi-bus.txt | |
| 10 | + | |
| 11 | +Optional properties: | |
| 12 | + - vref-supply: The regulator supply for ADC reference voltage | |
| 13 | + | |
| 14 | +Example: | |
| 15 | +adc@0 { | |
| 16 | + compatible = "ti,ads8688"; | |
| 17 | + reg = <0>; | |
| 18 | + vref-supply = <&vdd_supply>; | |
| 19 | + spi-max-frequency = <1000000>; | |
| 20 | +}; | |
| @@ -0,0 +1,21 @@ | ||
| 1 | +Maxim MAX30100 heart rate and pulse oximeter sensor | |
| 2 | + | |
| 3 | +* https://datasheets.maximintegrated.com/en/ds/MAX30100.pdf | |
| 4 | + | |
| 5 | +Required properties: | |
| 6 | + - compatible: must be "maxim,max30100" | |
| 7 | + - reg: the I2C address of the sensor | |
| 8 | + - interrupt-parent: should be the phandle for the interrupt controller | |
| 9 | + - interrupts: the sole interrupt generated by the device | |
| 10 | + | |
| 11 | + Refer to interrupt-controller/interrupts.txt for generic | |
| 12 | + interrupt client node bindings. | |
| 13 | + | |
| 14 | +Example: | |
| 15 | + | |
| 16 | +max30100@057 { | |
| 17 | + compatible = "maxim,max30100"; | |
| 18 | + reg = <57>; | |
| 19 | + interrupt-parent = <&gpio1>; | |
| 20 | + interrupts = <16 2>; | |
| 21 | +}; | |
| @@ -7,13 +7,24 @@ Required properties: · 6 unmodified lines | ||
| 7 | 7 | Optional properties: |
| 8 | 8 | - upisemi,glass-coef: glass attenuation factor - compensation factor of |
| 9 | 9 | resolution 1000 for material transmittance. |
| 10 | + | |
| 10 | 11 | - upisemi,dark-ths: array of 8 elements containing 16-bit thresholds (adc |
| 11 | 12 | counts) corresponding to every scale. |
| 13 | + | |
| 12 | 14 | - upisemi,upper-dark-gain: 8-bit dark gain compensation factor(4 int and 4 |
| 13 | 15 | fractional bits - Q4.4) applied when light > threshold |
| 16 | + | |
| 14 | 17 | - upisemi,lower-dark-gain: 8-bit dark gain compensation factor(4 int and 4 |
| 15 | 18 | fractional bits - Q4.4) applied when light < threshold |
| 16 | 19 | |
| 20 | +- upisemi,continuous: This chip has two power modes: one-shot (chip takes one | |
| 21 | + measurement and then shuts itself down) and continuous ( | |
| 22 | + chip takes continuous measurements). The one-shot mode is | |
| 23 | + more power-friendly but the continuous mode may be more | |
| 24 | + reliable. If this property is specified the continuous | |
| 25 | + mode will be used instead of the default one-shot one for | |
| 26 | + raw reads. | |
| 27 | + | |
| 17 | 28 | If the optional properties are not specified these factors will default to the |
| 18 | 29 | values in the below example. |
| 19 | 30 | The glass-coef defaults to no compensation for the covering material. |
| @@ -36,6 +36,7 @@ Accelerometers: · 35 unmodified lines | ||
| 36 | 36 | - st,lsm303dlm-accel |
| 37 | 37 | - st,lsm330-accel |
| 38 | 38 | - st,lsm303agr-accel |
| 39 | +- st,lis2dh12-accel | |
| 39 | 40 | |
| 40 | 41 | Gyroscopes: |
| 41 | 42 | - st,l3g4200d-gyro |
| @@ -0,0 +1,31 @@ | ||
| 1 | +Hi6220 SoC ION | |
| 2 | +=================================================================== | |
| 3 | +Required properties: | |
| 4 | +- compatible : "hisilicon,hi6220-ion" | |
| 5 | +- list of the ION heaps | |
| 6 | + - heap name : maybe heap_sys_user@0 | |
| 7 | + - heap id : id should be unique in the system. | |
| 8 | + - heap base : base ddr address of the heap,0 means that | |
| 9 | + it is dynamic. | |
| 10 | + - heap size : memory size and 0 means it is dynamic. | |
| 11 | + - heap type : the heap type of the heap, please also | |
| 12 | + see the define in ion.h(drivers/staging/android/uapi/ion.h) | |
| 13 | +------------------------------------------------------------------- | |
| 14 | +Example: | |
| 15 | + hi6220-ion { | |
| 16 | + compatible = "hisilicon,hi6220-ion"; | |
| 17 | + heap_sys_user@0 { | |
| 18 | + heap-name = "sys_user"; | |
| 19 | + heap-id = <0x0>; | |
| 20 | + heap-base = <0x0>; | |
| 21 | + heap-size = <0x0>; | |
| 22 | + heap-type = "ion_system"; | |
| 23 | + }; | |
| 24 | + heap_sys_contig@0 { | |
| 25 | + heap-name = "sys_contig"; | |
| 26 | + heap-id = <0x1>; | |
| 27 | + heap-base = <0x0>; | |
| 28 | + heap-size = <0x0>; | |
| 29 | + heap-type = "ion_system_contig"; | |
| 30 | + }; | |
| 31 | + }; | |
| @@ -0,0 +1,93 @@ | ||
| 1 | +Industrial IIO configfs support | |
| 2 | + | |
| 3 | +1. Overview | |
| 4 | + | |
| 5 | +Configfs is a filesystem-based manager of kernel objects. IIO uses some | |
| 6 | +objects that could be easily configured using configfs (e.g.: devices, | |
| 7 | +triggers). | |
| 8 | + | |
| 9 | +See Documentation/filesystems/configfs/configfs.txt for more information | |
| 10 | +about how configfs works. | |
| 11 | + | |
| 12 | +2. Usage | |
| 13 | + | |
| 14 | +In order to use configfs support in IIO we need to select it at compile | |
| 15 | +time via CONFIG_IIO_CONFIGFS config option. | |
| 16 | + | |
| 17 | +Then, mount the configfs filesystem (usually under /config directory): | |
| 18 | + | |
| 19 | +$ mkdir /config | |
| 20 | +$ mount -t configfs none /config | |
| 21 | + | |
| 22 | +At this point, all default IIO groups will be created and can be accessed | |
| 23 | +under /config/iio. Next chapters will describe available IIO configuration | |
| 24 | +objects. | |
| 25 | + | |
| 26 | +3. Software triggers | |
| 27 | + | |
| 28 | +One of the IIO default configfs groups is the "triggers" group. It is | |
| 29 | +automagically accessible when the configfs is mounted and can be found | |
| 30 | +under /config/iio/triggers. | |
| 31 | + | |
| 32 | +IIO software triggers implementation offers support for creating multiple | |
| 33 | +trigger types. A new trigger type is usually implemented as a separate | |
| 34 | +kernel module following the interface in include/linux/iio/sw_trigger.h: | |
| 35 | + | |
| 36 | +/* | |
| 37 | + * drivers/iio/trigger/iio-trig-sample.c | |
| 38 | + * sample kernel module implementing a new trigger type | |
| 39 | + */ | |
| 40 | +#include <linux/iio/sw_trigger.h> | |
| 41 | + | |
| 42 | + | |
| 43 | +static struct iio_sw_trigger *iio_trig_sample_probe(const char *name) | |
| 44 | +{ | |
| 45 | + /* | |
| 46 | + * This allocates and registers an IIO trigger plus other | |
| 47 | + * trigger type specific initialization. | |
| 48 | + */ | |
| 49 | +} | |
| 50 | + | |
| 51 | +static int iio_trig_hrtimer_remove(struct iio_sw_trigger *swt) | |
| 52 | +{ | |
| 53 | + /* | |
| 54 | + * This undoes the actions in iio_trig_sample_probe | |
| 55 | + */ | |
| 56 | +} | |
| 57 | + | |
| 58 | +static const struct iio_sw_trigger_ops iio_trig_sample_ops = { | |
| 59 | + .probe = iio_trig_sample_probe, | |
| 60 | + .remove = iio_trig_sample_remove, | |
| 61 | +}; | |
| 62 | + | |
| 63 | +static struct iio_sw_trigger_type iio_trig_sample = { | |
| 64 | + .name = "trig-sample", | |
| 65 | + .owner = THIS_MODULE, | |
| 66 | + .ops = &iio_trig_sample_ops, | |
| 67 | +}; | |
| 68 | + | |
| 69 | +module_iio_sw_trigger_driver(iio_trig_sample); | |
| 70 | + | |
| 71 | +Each trigger type has its own directory under /config/iio/triggers. Loading | |
| 72 | +iio-trig-sample module will create 'trig-sample' trigger type directory | |
| 73 | +/config/iio/triggers/trig-sample. | |
| 74 | + | |
| 75 | +We support the following interrupt sources (trigger types): | |
| 76 | + * hrtimer, uses high resolution timers as interrupt source | |
| 77 | + | |
| 78 | +3.1 Hrtimer triggers creation and destruction | |
| 79 | + | |
| 80 | +Loading iio-trig-hrtimer module will register hrtimer trigger types allowing | |
| 81 | +users to create hrtimer triggers under /config/iio/triggers/hrtimer. | |
| 82 | + | |
| 83 | +e.g: | |
| 84 | + | |
| 85 | +$ mkdir /config/triggers/hrtimer/instance1 | |
| 86 | +$ rmdir /config/triggers/hrtimer/instance1 | |
| 87 | + | |
| 88 | +Each trigger can have one or more attributes specific to the trigger type. | |
| 89 | + | |
| 90 | +3.2 "hrtimer" trigger types attributes | |
| 91 | + | |
| 92 | +"hrtimer" trigger type doesn't have any configurable attribute from /config dir. | |
| 93 | +It does introduce the sampling_frequency attribute to trigger directory. | |
| @@ -22,6 +22,14 @@ if IIO_BUFFER · 21 unmodified lines | ||
| 22 | 22 | source "drivers/iio/buffer/Kconfig" |
| 23 | 23 | endif # IIO_BUFFER |
| 24 | 24 | |
| 25 | +config IIO_CONFIGFS | |
| 26 | + tristate "Enable IIO configuration via configfs" | |
| 27 | + select CONFIGFS_FS | |
| 28 | + help | |
| 29 | + This allows configuring various IIO bits through configfs | |
| 30 | + (e.g. software triggers). For more info see | |
| 31 | + Documentation/iio/iio_configfs.txt. | |
| 32 | + | |
| 25 | 33 | config IIO_TRIGGER |
| 26 | 34 | bool "Enable triggered sampling support" |
| 27 | 35 | help |
| @@ -38,6 +46,14 @@ config IIO_CONSUMERS_PER_TRIGGER · 10 unmodified lines | ||
| 38 | 46 | This value controls the maximum number of consumers that a |
| 39 | 47 | given trigger may handle. Default is 2. |
| 40 | 48 | |
| 49 | +config IIO_SW_TRIGGER | |
| 50 | + tristate "Enable software triggers support" | |
| 51 | + select IIO_CONFIGFS | |
| 52 | + help | |
| 53 | + Provides IIO core support for software triggers. A software | |
| 54 | + trigger can be created via configfs or directly by a driver | |
| 55 | + using the API provided. | |
| 56 | + | |
| 41 | 57 | config IIO_TRIGGERED_EVENT |
| 42 | 58 | tristate |
| 43 | 59 | select IIO_TRIGGER |
| @@ -50,8 +66,10 @@ source "drivers/iio/amplifiers/Kconfig" · 6 unmodified lines | ||
| 50 | 66 | source "drivers/iio/chemical/Kconfig" |
| 51 | 67 | source "drivers/iio/common/Kconfig" |
| 52 | 68 | source "drivers/iio/dac/Kconfig" |
| 69 | +source "drivers/iio/dummy/Kconfig" | |
| 53 | 70 | source "drivers/iio/frequency/Kconfig" |
| 54 | 71 | source "drivers/iio/gyro/Kconfig" |
| 72 | +source "drivers/iio/health/Kconfig" | |
| 55 | 73 | source "drivers/iio/humidity/Kconfig" |
| 56 | 74 | source "drivers/iio/imu/Kconfig" |
| 57 | 75 | source "drivers/iio/light/Kconfig" |
| @@ -7,6 +7,8 @@ industrialio-y := industrialio-core.o industrialio-event.o inkern.o · 6 unmodified lines | ||
| 7 | 7 | industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o |
| 8 | 8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o |
| 9 | 9 | |
| 10 | +obj-$(CONFIG_IIO_CONFIGFS) += industrialio-configfs.o | |
| 11 | +obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o | |
| 10 | 12 | obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o |
| 11 | 13 | |
| 12 | 14 | obj-y += accel/ |
| @@ -16,8 +18,10 @@ obj-y += buffer/ · 3 unmodified lines | ||
| 16 | 18 | obj-y += chemical/ |
| 17 | 19 | obj-y += common/ |
| 18 | 20 | obj-y += dac/ |
| 21 | +obj-y += dummy/ | |
| 19 | 22 | obj-y += gyro/ |
| 20 | 23 | obj-y += frequency/ |
| 24 | +obj-y += health/ | |
| 21 | 25 | obj-y += humidity/ |
| 22 | 26 | obj-y += imu/ |
| 23 | 27 | obj-y += light/ |
| @@ -64,7 +64,7 @@ config IIO_ST_ACCEL_3AXIS · 63 unmodified lines | ||
| 64 | 64 | help |
| 65 | 65 | Say yes here to build support for STMicroelectronics accelerometers: |
| 66 | 66 | LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC, |
| 67 | − LIS331DLH, LSM303DL, LSM303DLM, LSM330. | |
| 67 | + LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12. | |
| 68 | 68 | |
| 69 | 69 | This driver can also be built as a module. If so, these modules |
| 70 | 70 | will be created: |
| @@ -107,6 +107,35 @@ config KXCJK1013 · 36 unmodified lines | ||
| 107 | 107 | To compile this driver as a module, choose M here: the module will |
| 108 | 108 | be called kxcjk-1013. |
| 109 | 109 | |
| 110 | +config MMA7455 | |
| 111 | + tristate | |
| 112 | + select IIO_BUFFER | |
| 113 | + select IIO_TRIGGERED_BUFFER | |
| 114 | + | |
| 115 | +config MMA7455_I2C | |
| 116 | + tristate "Freescale MMA7455L/MMA7456L Accelerometer I2C Driver" | |
| 117 | + depends on I2C | |
| 118 | + select MMA7455 | |
| 119 | + select REGMAP_I2C | |
| 120 | + help | |
| 121 | + Say yes here to build support for the Freescale MMA7455L and | |
| 122 | + MMA7456L 3-axis accelerometer. | |
| 123 | + | |
| 124 | + To compile this driver as a module, choose M here: the module | |
| 125 | + will be called mma7455_i2c. | |
| 126 | + | |
| 127 | +config MMA7455_SPI | |
| 128 | + tristate "Freescale MMA7455L/MMA7456L Accelerometer SPI Driver" | |
| 129 | + depends on SPI_MASTER | |
| 130 | + select MMA7455 | |
| 131 | + select REGMAP_SPI | |
| 132 | + help | |
| 133 | + Say yes here to build support for the Freescale MMA7455L and | |
| 134 | + MMA7456L 3-axis accelerometer. | |
| 135 | + | |
| 136 | + To compile this driver as a module, choose M here: the module | |
| 137 | + will be called mma7455_spi. | |
| 138 | + | |
| 110 | 139 | config MMA8452 |
| 111 | 140 | tristate "Freescale MMA8452Q and similar Accelerometers Driver" |
| 112 | 141 | depends on I2C |
| @@ -158,6 +187,17 @@ config MXC4005 · 45 unmodified lines | ||
| 158 | 187 | To compile this driver as a module, choose M. The module will be |
| 159 | 188 | called mxc4005. |
| 160 | 189 | |
| 190 | +config MXC6255 | |
| 191 | + tristate "Memsic MXC6255 Orientation Sensing Accelerometer Driver" | |
| 192 | + depends on I2C | |
| 193 | + select REGMAP_I2C | |
| 194 | + help | |
| 195 | + Say yes here to build support for the Memsic MXC6255 Orientation | |
| 196 | + Sensing Accelerometer Driver. | |
| 197 | + | |
| 198 | + To compile this driver as a module, choose M here: the module will be | |
| 199 | + called mxc6255. | |
| 200 | + | |
| 161 | 201 | config STK8312 |
| 162 | 202 | tristate "Sensortek STK8312 3-Axis Accelerometer Driver" |
| 163 | 203 | depends on I2C |
| @@ -10,6 +10,11 @@ obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o · 9 unmodified lines | ||
| 10 | 10 | obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o |
| 11 | 11 | obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o |
| 12 | 12 | obj-$(CONFIG_KXSD9) += kxsd9.o |
| 13 | + | |
| 14 | +obj-$(CONFIG_MMA7455) += mma7455_core.o | |
| 15 | +obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o | |
| 16 | +obj-$(CONFIG_MMA7455_SPI) += mma7455_spi.o | |
| 17 | + | |
| 13 | 18 | obj-$(CONFIG_MMA8452) += mma8452.o |
| 14 | 19 | |
| 15 | 20 | obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o |
| @@ -17,6 +22,7 @@ obj-$(CONFIG_MMA9551) += mma9551.o · 1 unmodified line | ||
| 17 | 22 | obj-$(CONFIG_MMA9553) += mma9553.o |
| 18 | 23 | |
| 19 | 24 | obj-$(CONFIG_MXC4005) += mxc4005.o |
| 25 | +obj-$(CONFIG_MXC6255) += mxc6255.o | |
| 20 | 26 | |
| 21 | 27 | obj-$(CONFIG_STK8312) += stk8312.o |
| 22 | 28 | obj-$(CONFIG_STK8BA50) += stk8ba50.o |
| @@ -1623,24 +1623,22 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, · 1622 unmodified lines | ||
| 1623 | 1623 | } |
| 1624 | 1624 | } |
| 1625 | 1625 | |
| 1626 | − ret = iio_device_register(indio_dev); | |
| 1627 | − if (ret < 0) { | |
| 1628 | − dev_err(dev, "Unable to register iio device\n"); | |
| 1629 | − goto err_trigger_unregister; | |
| 1630 | − } | |
| 1631 | − | |
| 1632 | 1626 | ret = pm_runtime_set_active(dev); |
| 1633 | 1627 | if (ret) |
| 1634 | − goto err_iio_unregister; | |
| 1628 | + goto err_trigger_unregister; | |
| 1635 | 1629 | |
| 1636 | 1630 | pm_runtime_enable(dev); |
| 1637 | 1631 | pm_runtime_set_autosuspend_delay(dev, BMC150_AUTO_SUSPEND_DELAY_MS); |
| 1638 | 1632 | pm_runtime_use_autosuspend(dev); |
| 1639 | 1633 | |
| 1634 | + ret = iio_device_register(indio_dev); | |
| 1635 | + if (ret < 0) { | |
| 1636 | + dev_err(dev, "Unable to register iio device\n"); | |
| 1637 | + goto err_trigger_unregister; | |
| 1638 | + } | |
| 1639 | + | |
| 1640 | 1640 | return 0; |
| 1641 | 1641 | |
| 1642 | −err_iio_unregister: | |
| 1643 | − iio_device_unregister(indio_dev); | |
| 1644 | 1642 | err_trigger_unregister: |
| 1645 | 1643 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); |
| 1646 | 1644 | err_buffer_cleanup: |
| @@ -1655,12 +1653,12 @@ int bmc150_accel_core_remove(struct device *dev) · 8 unmodified lines | ||
| 1655 | 1653 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
| 1656 | 1654 | struct bmc150_accel_data *data = iio_priv(indio_dev); |
| 1657 | 1655 | |
| 1656 | + iio_device_unregister(indio_dev); | |
| 1657 | + | |
| 1658 | 1658 | pm_runtime_disable(data->dev); |
| 1659 | 1659 | pm_runtime_set_suspended(data->dev); |
| 1660 | 1660 | pm_runtime_put_noidle(data->dev); |
| 1661 | 1661 | |
| 1662 | − iio_device_unregister(indio_dev); | |
| 1663 | − | |
| 1664 | 1662 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); |
| 1665 | 1663 | |
| 1666 | 1664 | iio_triggered_buffer_cleanup(indio_dev); |
| @@ -1264,25 +1264,23 @@ static int kxcjk1013_probe(struct i2c_client *client, · 1263 unmodified lines | ||
| 1264 | 1264 | goto err_trigger_unregister; |
| 1265 | 1265 | } |
| 1266 | 1266 | |
| 1267 | − ret = iio_device_register(indio_dev); | |
| 1268 | − if (ret < 0) { | |
| 1269 | − dev_err(&client->dev, "unable to register iio device\n"); | |
| 1270 | − goto err_buffer_cleanup; | |
| 1271 | − } | |
| 1272 | − | |
| 1273 | 1267 | ret = pm_runtime_set_active(&client->dev); |
| 1274 | 1268 | if (ret) |
| 1275 | − goto err_iio_unregister; | |
| 1269 | + goto err_buffer_cleanup; | |
| 1276 | 1270 | |
| 1277 | 1271 | pm_runtime_enable(&client->dev); |
| 1278 | 1272 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 1279 | 1273 | KXCJK1013_SLEEP_DELAY_MS); |
| 1280 | 1274 | pm_runtime_use_autosuspend(&client->dev); |
| 1281 | 1275 | |
| 1276 | + ret = iio_device_register(indio_dev); | |
| 1277 | + if (ret < 0) { | |
| 1278 | + dev_err(&client->dev, "unable to register iio device\n"); | |
| 1279 | + goto err_buffer_cleanup; | |
| 1280 | + } | |
| 1281 | + | |
| 1282 | 1282 | return 0; |
| 1283 | 1283 | |
| 1284 | −err_iio_unregister: | |
| 1285 | − iio_device_unregister(indio_dev); | |
| 1286 | 1284 | err_buffer_cleanup: |
| 1287 | 1285 | if (data->dready_trig) |
| 1288 | 1286 | iio_triggered_buffer_cleanup(indio_dev); |
| @@ -1302,12 +1300,12 @@ static int kxcjk1013_remove(struct i2c_client *client) · 13 unmodified lines | ||
| 1302 | 1300 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 1303 | 1301 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1304 | 1302 | |
| 1303 | + iio_device_unregister(indio_dev); | |
| 1304 | + | |
| 1305 | 1305 | pm_runtime_disable(&client->dev); |
| 1306 | 1306 | pm_runtime_set_suspended(&client->dev); |
| 1307 | 1307 | pm_runtime_put_noidle(&client->dev); |
| 1308 | 1308 | |
| 1309 | − iio_device_unregister(indio_dev); | |
| 1310 | − | |
| 1311 | 1309 | if (data->dready_trig) { |
| 1312 | 1310 | iio_triggered_buffer_cleanup(indio_dev); |
| 1313 | 1311 | iio_trigger_unregister(data->dready_trig); |
| @@ -0,0 +1,19 @@ | ||
| 1 | +/* | |
| 2 | + * IIO accel driver for Freescale MMA7455L 3-axis 10-bit accelerometer | |
| 3 | + * Copyright 2015 Joachim Eastwood <manabian@gmail.com> | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify | |
| 6 | + * it under the terms of the GNU General Public License version 2 as | |
| 7 | + * published by the Free Software Foundation. | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#ifndef __MMA7455_H | |
| 11 | +#define __MMA7455_H | |
| 12 | + | |
| 13 | +extern const struct regmap_config mma7455_core_regmap; | |
| 14 | + | |
| 15 | +int mma7455_core_probe(struct device *dev, struct regmap *regmap, | |
| 16 | + const char *name); | |
| 17 | +int mma7455_core_remove(struct device *dev); | |
| 18 | + | |
| 19 | +#endif | |
| @@ -0,0 +1,311 @@ | ||
| 1 | +/* | |
| 2 | + * IIO accel core driver for Freescale MMA7455L 3-axis 10-bit accelerometer | |
| 3 | + * Copyright 2015 Joachim Eastwood <manabian@gmail.com> | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify | |
| 6 | + * it under the terms of the GNU General Public License version 2 as | |
| 7 | + * published by the Free Software Foundation. | |
| 8 | + * | |
| 9 | + * UNSUPPORTED hardware features: | |
| 10 | + * - 8-bit mode with different scales | |
| 11 | + * - INT1/INT2 interrupts | |
| 12 | + * - Offset calibration | |
| 13 | + * - Events | |
| 14 | + */ | |
| 15 | + | |
| 16 | +#include <linux/delay.h> | |
| 17 | +#include <linux/iio/iio.h> | |
| 18 | +#include <linux/iio/sysfs.h> | |
| 19 | +#include <linux/iio/buffer.h> | |
| 20 | +#include <linux/iio/trigger.h> | |
| 21 | +#include <linux/iio/trigger_consumer.h> | |
| 22 | +#include <linux/iio/triggered_buffer.h> | |
| 23 | +#include <linux/module.h> | |
| 24 | +#include <linux/regmap.h> | |
| 25 | + | |
| 26 | +#include "mma7455.h" | |
| 27 | + | |
| 28 | +#define MMA7455_REG_XOUTL 0x00 | |
| 29 | +#define MMA7455_REG_XOUTH 0x01 | |
| 30 | +#define MMA7455_REG_YOUTL 0x02 | |
| 31 | +#define MMA7455_REG_YOUTH 0x03 | |
| 32 | +#define MMA7455_REG_ZOUTL 0x04 | |
| 33 | +#define MMA7455_REG_ZOUTH 0x05 | |
| 34 | +#define MMA7455_REG_STATUS 0x09 | |
| 35 | +#define MMA7455_STATUS_DRDY BIT(0) | |
| 36 | +#define MMA7455_REG_WHOAMI 0x0f | |
| 37 | +#define MMA7455_WHOAMI_ID 0x55 | |
| 38 | +#define MMA7455_REG_MCTL 0x16 | |
| 39 | +#define MMA7455_MCTL_MODE_STANDBY 0x00 | |
| 40 | +#define MMA7455_MCTL_MODE_MEASURE 0x01 | |
| 41 | +#define MMA7455_REG_CTL1 0x18 | |
| 42 | +#define MMA7455_CTL1_DFBW_MASK BIT(7) | |
| 43 | +#define MMA7455_CTL1_DFBW_125HZ BIT(7) | |
| 44 | +#define MMA7455_CTL1_DFBW_62_5HZ 0 | |
| 45 | +#define MMA7455_REG_TW 0x1e | |
| 46 | + | |
| 47 | +/* | |
| 48 | + * When MMA7455 is used in 10-bit it has a fullscale of -8g | |
| 49 | + * corresponding to raw value -512. The userspace interface | |
| 50 | + * uses m/s^2 and we declare micro units. | |
| 51 | + * So scale factor is given by: | |
| 52 | + * g * 8 * 1e6 / 512 = 153228.90625, with g = 9.80665 | |
| 53 | + */ | |
| 54 | +#define MMA7455_10BIT_SCALE 153229 | |
| 55 | + | |
| 56 | +struct mma7455_data { | |
| 57 | + struct regmap *regmap; | |
| 58 | + struct device *dev; | |
| 59 | +}; | |
| 60 | + | |
| 61 | +static int mma7455_drdy(struct mma7455_data *mma7455) | |
| 62 | +{ | |
| 63 | + unsigned int reg; | |
| 64 | + int tries = 3; | |
| 65 | + int ret; | |
| 66 | + | |
| 67 | + while (tries-- > 0) { | |
| 68 | + ret = regmap_read(mma7455->regmap, MMA7455_REG_STATUS, ®); | |
| 69 | + if (ret) | |
| 70 | + return ret; | |
| 71 | + | |
| 72 | + if (reg & MMA7455_STATUS_DRDY) | |
| 73 | + return 0; | |
| 74 | + | |
| 75 | + msleep(20); | |
| 76 | + } | |
| 77 | + | |
| 78 | + dev_warn(mma7455->dev, "data not ready\n"); | |
| 79 | + | |
| 80 | + return -EIO; | |
| 81 | +} | |
| 82 | + | |
| 83 | +static irqreturn_t mma7455_trigger_handler(int irq, void *p) | |
| 84 | +{ | |
| 85 | + struct iio_poll_func *pf = p; | |
| 86 | + struct iio_dev *indio_dev = pf->indio_dev; | |
| 87 | + struct mma7455_data *mma7455 = iio_priv(indio_dev); | |
| 88 | + u8 buf[16]; /* 3 x 16-bit channels + padding + ts */ | |
| 89 | + int ret; | |
| 90 | + | |
| 91 | + ret = mma7455_drdy(mma7455); | |
| 92 | + if (ret) | |
| 93 | + goto done; | |
| 94 | + | |
| 95 | + ret = regmap_bulk_read(mma7455->regmap, MMA7455_REG_XOUTL, buf, | |
| 96 | + sizeof(__le16) * 3); | |
| 97 | + if (ret) | |
| 98 | + goto done; | |
| 99 | + | |
| 100 | + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); | |
| 101 | + | |
| 102 | +done: | |
| 103 | + iio_trigger_notify_done(indio_dev->trig); | |
| 104 | + | |
| 105 | + return IRQ_HANDLED; | |
| 106 | +} | |
| 107 | + | |
| 108 | +static int mma7455_read_raw(struct iio_dev *indio_dev, | |
| 109 | + struct iio_chan_spec const *chan, | |
| 110 | + int *val, int *val2, long mask) | |
| 111 | +{ | |
| 112 | + struct mma7455_data *mma7455 = iio_priv(indio_dev); | |
| 113 | + unsigned int reg; | |
| 114 | + __le16 data; | |
| 115 | + int ret; | |
| 116 | + | |
| 117 | + switch (mask) { | |
| 118 | + case IIO_CHAN_INFO_RAW: | |
| 119 | + if (iio_buffer_enabled(indio_dev)) | |
| 120 | + return -EBUSY; | |
| 121 | + | |
| 122 | + ret = mma7455_drdy(mma7455); | |
| 123 | + if (ret) | |
| 124 | + return ret; | |
| 125 | + | |
| 126 | + ret = regmap_bulk_read(mma7455->regmap, chan->address, &data, | |
| 127 | + sizeof(data)); | |
| 128 | + if (ret) | |
| 129 | + return ret; | |
| 130 | + | |
| 131 | + *val = sign_extend32(le16_to_cpu(data), 9); | |
| 132 | + | |
| 133 | + return IIO_VAL_INT; | |
| 134 | + | |
| 135 | + case IIO_CHAN_INFO_SCALE: | |
| 136 | + *val = 0; | |
| 137 | + *val2 = MMA7455_10BIT_SCALE; | |
| 138 | + | |
| 139 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 140 | + | |
| 141 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 142 | + ret = regmap_read(mma7455->regmap, MMA7455_REG_CTL1, ®); | |
| 143 | + if (ret) | |
| 144 | + return ret; | |
| 145 | + | |
| 146 | + if (reg & MMA7455_CTL1_DFBW_MASK) | |
| 147 | + *val = 250; | |
| 148 | + else | |
| 149 | + *val = 125; | |
| 150 | + | |
| 151 | + return IIO_VAL_INT; | |
| 152 | + } | |
| 153 | + | |
| 154 | + return -EINVAL; | |
| 155 | +} | |
| 156 | + | |
| 157 | +static int mma7455_write_raw(struct iio_dev *indio_dev, | |
| 158 | + struct iio_chan_spec const *chan, | |
| 159 | + int val, int val2, long mask) | |
| 160 | +{ | |
| 161 | + struct mma7455_data *mma7455 = iio_priv(indio_dev); | |
| 162 | + int i; | |
| 163 | + | |
| 164 | + switch (mask) { | |
| 165 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 166 | + if (val == 250 && val2 == 0) | |
| 167 | + i = MMA7455_CTL1_DFBW_125HZ; | |
| 168 | + else if (val == 125 && val2 == 0) | |
| 169 | + i = MMA7455_CTL1_DFBW_62_5HZ; | |
| 170 | + else | |
| 171 | + return -EINVAL; | |
| 172 | + | |
| 173 | + return regmap_update_bits(mma7455->regmap, MMA7455_REG_CTL1, | |
| 174 | + MMA7455_CTL1_DFBW_MASK, i); | |
| 175 | + | |
| 176 | + case IIO_CHAN_INFO_SCALE: | |
| 177 | + /* In 10-bit mode there is only one scale available */ | |
| 178 | + if (val == 0 && val2 == MMA7455_10BIT_SCALE) | |
| 179 | + return 0; | |
| 180 | + break; | |
| 181 | + } | |
| 182 | + | |
| 183 | + return -EINVAL; | |
| 184 | +} | |
| 185 | + | |
| 186 | +static IIO_CONST_ATTR(sampling_frequency_available, "125 250"); | |
| 187 | + | |
| 188 | +static struct attribute *mma7455_attributes[] = { | |
| 189 | + &iio_const_attr_sampling_frequency_available.dev_attr.attr, | |
| 190 | + NULL | |
| 191 | +}; | |
| 192 | + | |
| 193 | +static const struct attribute_group mma7455_group = { | |
| 194 | + .attrs = mma7455_attributes, | |
| 195 | +}; | |
| 196 | + | |
| 197 | +static const struct iio_info mma7455_info = { | |
| 198 | + .attrs = &mma7455_group, | |
| 199 | + .read_raw = mma7455_read_raw, | |
| 200 | + .write_raw = mma7455_write_raw, | |
| 201 | + .driver_module = THIS_MODULE, | |
| 202 | +}; | |
| 203 | + | |
| 204 | +#define MMA7455_CHANNEL(axis, idx) { \ | |
| 205 | + .type = IIO_ACCEL, \ | |
| 206 | + .modified = 1, \ | |
| 207 | + .address = MMA7455_REG_##axis##OUTL,\ | |
| 208 | + .channel2 = IIO_MOD_##axis, \ | |
| 209 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 210 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | |
| 211 | + BIT(IIO_CHAN_INFO_SCALE), \ | |
| 212 | + .scan_index = idx, \ | |
| 213 | + .scan_type = { \ | |
| 214 | + .sign = 's', \ | |
| 215 | + .realbits = 10, \ | |
| 216 | + .storagebits = 16, \ | |
| 217 | + .endianness = IIO_LE, \ | |
| 218 | + }, \ | |
| 219 | +} | |
| 220 | + | |
| 221 | +static const struct iio_chan_spec mma7455_channels[] = { | |
| 222 | + MMA7455_CHANNEL(X, 0), | |
| 223 | + MMA7455_CHANNEL(Y, 1), | |
| 224 | + MMA7455_CHANNEL(Z, 2), | |
| 225 | + IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 226 | +}; | |
| 227 | + | |
| 228 | +static const unsigned long mma7455_scan_masks[] = {0x7, 0}; | |
| 229 | + | |
| 230 | +const struct regmap_config mma7455_core_regmap = { | |
| 231 | + .reg_bits = 8, | |
| 232 | + .val_bits = 8, | |
| 233 | + .max_register = MMA7455_REG_TW, | |
| 234 | +}; | |
| 235 | +EXPORT_SYMBOL_GPL(mma7455_core_regmap); | |
| 236 | + | |
| 237 | +int mma7455_core_probe(struct device *dev, struct regmap *regmap, | |
| 238 | + const char *name) | |
| 239 | +{ | |
| 240 | + struct mma7455_data *mma7455; | |
| 241 | + struct iio_dev *indio_dev; | |
| 242 | + unsigned int reg; | |
| 243 | + int ret; | |
| 244 | + | |
| 245 | + ret = regmap_read(regmap, MMA7455_REG_WHOAMI, ®); | |
| 246 | + if (ret) { | |
| 247 | + dev_err(dev, "unable to read reg\n"); | |
| 248 | + return ret; | |
| 249 | + } | |
| 250 | + | |
| 251 | + if (reg != MMA7455_WHOAMI_ID) { | |
| 252 | + dev_err(dev, "device id mismatch\n"); | |
| 253 | + return -ENODEV; | |
| 254 | + } | |
| 255 | + | |
| 256 | + indio_dev = devm_iio_device_alloc(dev, sizeof(*mma7455)); | |
| 257 | + if (!indio_dev) | |
| 258 | + return -ENOMEM; | |
| 259 | + | |
| 260 | + dev_set_drvdata(dev, indio_dev); | |
| 261 | + mma7455 = iio_priv(indio_dev); | |
| 262 | + mma7455->regmap = regmap; | |
| 263 | + mma7455->dev = dev; | |
| 264 | + | |
| 265 | + indio_dev->info = &mma7455_info; | |
| 266 | + indio_dev->name = name; | |
| 267 | + indio_dev->dev.parent = dev; | |
| 268 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 269 | + indio_dev->channels = mma7455_channels; | |
| 270 | + indio_dev->num_channels = ARRAY_SIZE(mma7455_channels); | |
| 271 | + indio_dev->available_scan_masks = mma7455_scan_masks; | |
| 272 | + | |
| 273 | + regmap_write(mma7455->regmap, MMA7455_REG_MCTL, | |
| 274 | + MMA7455_MCTL_MODE_MEASURE); | |
| 275 | + | |
| 276 | + ret = iio_triggered_buffer_setup(indio_dev, NULL, | |
| 277 | + mma7455_trigger_handler, NULL); | |
| 278 | + if (ret) { | |
| 279 | + dev_err(dev, "unable to setup triggered buffer\n"); | |
| 280 | + return ret; | |
| 281 | + } | |
| 282 | + | |
| 283 | + ret = iio_device_register(indio_dev); | |
| 284 | + if (ret) { | |
| 285 | + dev_err(dev, "unable to register device\n"); | |
| 286 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 287 | + return ret; | |
| 288 | + } | |
| 289 | + | |
| 290 | + return 0; | |
| 291 | +} | |
| 292 | +EXPORT_SYMBOL_GPL(mma7455_core_probe); | |
| 293 | + | |
| 294 | +int mma7455_core_remove(struct device *dev) | |
| 295 | +{ | |
| 296 | + struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
| 297 | + struct mma7455_data *mma7455 = iio_priv(indio_dev); | |
| 298 | + | |
| 299 | + iio_device_unregister(indio_dev); | |
| 300 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 301 | + | |
| 302 | + regmap_write(mma7455->regmap, MMA7455_REG_MCTL, | |
| 303 | + MMA7455_MCTL_MODE_STANDBY); | |
| 304 | + | |
| 305 | + return 0; | |
| 306 | +} | |
| 307 | +EXPORT_SYMBOL_GPL(mma7455_core_remove); | |
| 308 | + | |
| 309 | +MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>"); | |
| 310 | +MODULE_DESCRIPTION("Freescale MMA7455L core accelerometer driver"); | |
| 311 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,56 @@ | ||
| 1 | +/* | |
| 2 | + * IIO accel I2C driver for Freescale MMA7455L 3-axis 10-bit accelerometer | |
| 3 | + * Copyright 2015 Joachim Eastwood <manabian@gmail.com> | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify | |
| 6 | + * it under the terms of the GNU General Public License version 2 as | |
| 7 | + * published by the Free Software Foundation. | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#include <linux/i2c.h> | |
| 11 | +#include <linux/module.h> | |
| 12 | +#include <linux/regmap.h> | |
| 13 | + | |
| 14 | +#include "mma7455.h" | |
| 15 | + | |
| 16 | +static int mma7455_i2c_probe(struct i2c_client *i2c, | |
| 17 | + const struct i2c_device_id *id) | |
| 18 | +{ | |
| 19 | + struct regmap *regmap; | |
| 20 | + const char *name = NULL; | |
| 21 | + | |
| 22 | + regmap = devm_regmap_init_i2c(i2c, &mma7455_core_regmap); | |
| 23 | + if (IS_ERR(regmap)) | |
| 24 | + return PTR_ERR(regmap); | |
| 25 | + | |
| 26 | + if (id) | |
| 27 | + name = id->name; | |
| 28 | + | |
| 29 | + return mma7455_core_probe(&i2c->dev, regmap, name); | |
| 30 | +} | |
| 31 | + | |
| 32 | +static int mma7455_i2c_remove(struct i2c_client *i2c) | |
| 33 | +{ | |
| 34 | + return mma7455_core_remove(&i2c->dev); | |
| 35 | +} | |
| 36 | + | |
| 37 | +static const struct i2c_device_id mma7455_i2c_ids[] = { | |
| 38 | + { "mma7455", 0 }, | |
| 39 | + { "mma7456", 0 }, | |
| 40 | + { } | |
| 41 | +}; | |
| 42 | +MODULE_DEVICE_TABLE(i2c, mma7455_i2c_ids); | |
| 43 | + | |
| 44 | +static struct i2c_driver mma7455_i2c_driver = { | |
| 45 | + .probe = mma7455_i2c_probe, | |
| 46 | + .remove = mma7455_i2c_remove, | |
| 47 | + .id_table = mma7455_i2c_ids, | |
| 48 | + .driver = { | |
| 49 | + .name = "mma7455-i2c", | |
| 50 | + }, | |
| 51 | +}; | |
| 52 | +module_i2c_driver(mma7455_i2c_driver); | |
| 53 | + | |
| 54 | +MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>"); | |
| 55 | +MODULE_DESCRIPTION("Freescale MMA7455L I2C accelerometer driver"); | |
| 56 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,52 @@ | ||
| 1 | +/* | |
| 2 | + * IIO accel SPI driver for Freescale MMA7455L 3-axis 10-bit accelerometer | |
| 3 | + * Copyright 2015 Joachim Eastwood <manabian@gmail.com> | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify | |
| 6 | + * it under the terms of the GNU General Public License version 2 as | |
| 7 | + * published by the Free Software Foundation. | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#include <linux/module.h> | |
| 11 | +#include <linux/regmap.h> | |
| 12 | +#include <linux/spi/spi.h> | |
| 13 | + | |
| 14 | +#include "mma7455.h" | |
| 15 | + | |
| 16 | +static int mma7455_spi_probe(struct spi_device *spi) | |
| 17 | +{ | |
| 18 | + const struct spi_device_id *id = spi_get_device_id(spi); | |
| 19 | + struct regmap *regmap; | |
| 20 | + | |
| 21 | + regmap = devm_regmap_init_spi(spi, &mma7455_core_regmap); | |
| 22 | + if (IS_ERR(regmap)) | |
| 23 | + return PTR_ERR(regmap); | |
| 24 | + | |
| 25 | + return mma7455_core_probe(&spi->dev, regmap, id->name); | |
| 26 | +} | |
| 27 | + | |
| 28 | +static int mma7455_spi_remove(struct spi_device *spi) | |
| 29 | +{ | |
| 30 | + return mma7455_core_remove(&spi->dev); | |
| 31 | +} | |
| 32 | + | |
| 33 | +static const struct spi_device_id mma7455_spi_ids[] = { | |
| 34 | + { "mma7455", 0 }, | |
| 35 | + { "mma7456", 0 }, | |
| 36 | + { } | |
| 37 | +}; | |
| 38 | +MODULE_DEVICE_TABLE(spi, mma7455_spi_ids); | |
| 39 | + | |
| 40 | +static struct spi_driver mma7455_spi_driver = { | |
| 41 | + .probe = mma7455_spi_probe, | |
| 42 | + .remove = mma7455_spi_remove, | |
| 43 | + .id_table = mma7455_spi_ids, | |
| 44 | + .driver = { | |
| 45 | + .name = "mma7455-spi", | |
| 46 | + }, | |
| 47 | +}; | |
| 48 | +module_spi_driver(mma7455_spi_driver); | |
| 49 | + | |
| 50 | +MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>"); | |
| 51 | +MODULE_DESCRIPTION("Freescale MMA7455L SPI accelerometer driver"); | |
| 52 | +MODULE_LICENSE("GPL v2"); | |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/iio/events.h> |
| 30 | 30 | #include <linux/delay.h> |
| 31 | 31 | #include <linux/of_device.h> |
| 32 | +#include <linux/of_irq.h> | |
| 32 | 33 | |
| 33 | 34 | #define MMA8452_STATUS 0x00 |
| 34 | 35 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) |
| @@ -57,7 +58,6 @@ · 22 unmodified lines | ||
| 57 | 58 | #define MMA8452_FF_MT_COUNT 0x18 |
| 58 | 59 | #define MMA8452_TRANSIENT_CFG 0x1d |
| 59 | 60 | #define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0) |
| 60 | −#define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1) | |
| 61 | 61 | #define MMA8452_TRANSIENT_CFG_ELE BIT(4) |
| 62 | 62 | #define MMA8452_TRANSIENT_SRC 0x1e |
| 63 | 63 | #define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1) |
| @@ -143,6 +143,13 @@ struct mma_chip_info { · 79 unmodified lines | ||
| 143 | 143 | u8 ev_count; |
| 144 | 144 | }; |
| 145 | 145 | |
| 146 | +enum { | |
| 147 | + idx_x, | |
| 148 | + idx_y, | |
| 149 | + idx_z, | |
| 150 | + idx_ts, | |
| 151 | +}; | |
| 152 | + | |
| 146 | 153 | static int mma8452_drdy(struct mma8452_data *data) |
| 147 | 154 | { |
| 148 | 155 | int tries = 150; |
| @@ -816,31 +823,31 @@ static struct attribute_group mma8452_event_attribute_group = { · 667 unmodified lines | ||
| 816 | 823 | } |
| 817 | 824 | |
| 818 | 825 | static const struct iio_chan_spec mma8452_channels[] = { |
| 819 | − MMA8452_CHANNEL(X, 0, 12), | |
| 820 | − MMA8452_CHANNEL(Y, 1, 12), | |
| 821 | − MMA8452_CHANNEL(Z, 2, 12), | |
| 822 | − IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 826 | + MMA8452_CHANNEL(X, idx_x, 12), | |
| 827 | + MMA8452_CHANNEL(Y, idx_y, 12), | |
| 828 | + MMA8452_CHANNEL(Z, idx_z, 12), | |
| 829 | + IIO_CHAN_SOFT_TIMESTAMP(idx_ts), | |
| 823 | 830 | }; |
| 824 | 831 | |
| 825 | 832 | static const struct iio_chan_spec mma8453_channels[] = { |
| 826 | − MMA8452_CHANNEL(X, 0, 10), | |
| 827 | − MMA8452_CHANNEL(Y, 1, 10), | |
| 828 | − MMA8452_CHANNEL(Z, 2, 10), | |
| 829 | − IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 833 | + MMA8452_CHANNEL(X, idx_x, 10), | |
| 834 | + MMA8452_CHANNEL(Y, idx_y, 10), | |
| 835 | + MMA8452_CHANNEL(Z, idx_z, 10), | |
| 836 | + IIO_CHAN_SOFT_TIMESTAMP(idx_ts), | |
| 830 | 837 | }; |
| 831 | 838 | |
| 832 | 839 | static const struct iio_chan_spec mma8652_channels[] = { |
| 833 | − MMA8652_CHANNEL(X, 0, 12), | |
| 834 | − MMA8652_CHANNEL(Y, 1, 12), | |
| 835 | − MMA8652_CHANNEL(Z, 2, 12), | |
| 836 | − IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 840 | + MMA8652_CHANNEL(X, idx_x, 12), | |
| 841 | + MMA8652_CHANNEL(Y, idx_y, 12), | |
| 842 | + MMA8652_CHANNEL(Z, idx_z, 12), | |
| 843 | + IIO_CHAN_SOFT_TIMESTAMP(idx_ts), | |
| 837 | 844 | }; |
| 838 | 845 | |
| 839 | 846 | static const struct iio_chan_spec mma8653_channels[] = { |
| 840 | − MMA8652_CHANNEL(X, 0, 10), | |
| 841 | − MMA8652_CHANNEL(Y, 1, 10), | |
| 842 | − MMA8652_CHANNEL(Z, 2, 10), | |
| 843 | − IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 847 | + MMA8652_CHANNEL(X, idx_x, 10), | |
| 848 | + MMA8652_CHANNEL(Y, idx_y, 10), | |
| 849 | + MMA8652_CHANNEL(Z, idx_z, 10), | |
| 850 | + IIO_CHAN_SOFT_TIMESTAMP(idx_ts), | |
| 844 | 851 | }; |
| 845 | 852 | |
| 846 | 853 | enum { |
| @@ -1130,13 +1137,21 @@ static int mma8452_probe(struct i2c_client *client, · 283 unmodified lines | ||
| 1130 | 1137 | MMA8452_INT_FF_MT; |
| 1131 | 1138 | int enabled_interrupts = MMA8452_INT_TRANS | |
| 1132 | 1139 | MMA8452_INT_FF_MT; |
| 1140 | + int irq2; | |
| 1133 | 1141 | |
| 1134 | − /* Assume wired to INT1 pin */ | |
| 1135 | − ret = i2c_smbus_write_byte_data(client, | |
| 1136 | − MMA8452_CTRL_REG5, | |
| 1137 | − supported_interrupts); | |
| 1138 | − if (ret < 0) | |
| 1139 | − return ret; | |
| 1142 | + irq2 = of_irq_get_byname(client->dev.of_node, "INT2"); | |
| 1143 | + | |
| 1144 | + if (irq2 == client->irq) { | |
| 1145 | + dev_dbg(&client->dev, "using interrupt line INT2\n"); | |
| 1146 | + } else { | |
| 1147 | + ret = i2c_smbus_write_byte_data(client, | |
| 1148 | + MMA8452_CTRL_REG5, | |
| 1149 | + supported_interrupts); | |
| 1150 | + if (ret < 0) | |
| 1151 | + return ret; | |
| 1152 | + | |
| 1153 | + dev_dbg(&client->dev, "using interrupt line INT1\n"); | |
| 1154 | + } | |
| 1140 | 1155 | |
| 1141 | 1156 | ret = i2c_smbus_write_byte_data(client, |
| 1142 | 1157 | MMA8452_CTRL_REG4, |
| @@ -495,25 +495,23 @@ static int mma9551_probe(struct i2c_client *client, · 494 unmodified lines | ||
| 495 | 495 | if (ret < 0) |
| 496 | 496 | goto out_poweroff; |
| 497 | 497 | |
| 498 | − ret = iio_device_register(indio_dev); | |
| 499 | − if (ret < 0) { | |
| 500 | − dev_err(&client->dev, "unable to register iio device\n"); | |
| 501 | − goto out_poweroff; | |
| 502 | − } | |
| 503 | − | |
| 504 | 498 | ret = pm_runtime_set_active(&client->dev); |
| 505 | 499 | if (ret < 0) |
| 506 | − goto out_iio_unregister; | |
| 500 | + goto out_poweroff; | |
| 507 | 501 | |
| 508 | 502 | pm_runtime_enable(&client->dev); |
| 509 | 503 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 510 | 504 | MMA9551_AUTO_SUSPEND_DELAY_MS); |
| 511 | 505 | pm_runtime_use_autosuspend(&client->dev); |
| 512 | 506 | |
| 507 | + ret = iio_device_register(indio_dev); | |
| 508 | + if (ret < 0) { | |
| 509 | + dev_err(&client->dev, "unable to register iio device\n"); | |
| 510 | + goto out_poweroff; | |
| 511 | + } | |
| 512 | + | |
| 513 | 513 | return 0; |
| 514 | 514 | |
| 515 | −out_iio_unregister: | |
| 516 | − iio_device_unregister(indio_dev); | |
| 517 | 515 | out_poweroff: |
| 518 | 516 | mma9551_set_device_state(client, false); |
| 519 | 517 | |
| @@ -525,11 +523,12 @@ static int mma9551_remove(struct i2c_client *client) · 5 unmodified lines | ||
| 525 | 523 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 526 | 524 | struct mma9551_data *data = iio_priv(indio_dev); |
| 527 | 525 | |
| 526 | + iio_device_unregister(indio_dev); | |
| 527 | + | |
| 528 | 528 | pm_runtime_disable(&client->dev); |
| 529 | 529 | pm_runtime_set_suspended(&client->dev); |
| 530 | 530 | pm_runtime_put_noidle(&client->dev); |
| 531 | 531 | |
| 532 | − iio_device_unregister(indio_dev); | |
| 533 | 532 | mutex_lock(&data->mutex); |
| 534 | 533 | mma9551_set_device_state(data->client, false); |
| 535 | 534 | mutex_unlock(&data->mutex); |
| @@ -1133,27 +1133,24 @@ static int mma9553_probe(struct i2c_client *client, · 1132 unmodified lines | ||
| 1133 | 1133 | } |
| 1134 | 1134 | } |
| 1135 | 1135 | |
| 1136 | − ret = iio_device_register(indio_dev); | |
| 1137 | − if (ret < 0) { | |
| 1138 | − dev_err(&client->dev, "unable to register iio device\n"); | |
| 1139 | − goto out_poweroff; | |
| 1140 | − } | |
| 1141 | − | |
| 1142 | 1136 | ret = pm_runtime_set_active(&client->dev); |
| 1143 | 1137 | if (ret < 0) |
| 1144 | − goto out_iio_unregister; | |
| 1138 | + goto out_poweroff; | |
| 1145 | 1139 | |
| 1146 | 1140 | pm_runtime_enable(&client->dev); |
| 1147 | 1141 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 1148 | 1142 | MMA9551_AUTO_SUSPEND_DELAY_MS); |
| 1149 | 1143 | pm_runtime_use_autosuspend(&client->dev); |
| 1150 | 1144 | |
| 1151 | − dev_dbg(&indio_dev->dev, "Registered device %s\n", name); | |
| 1145 | + ret = iio_device_register(indio_dev); | |
| 1146 | + if (ret < 0) { | |
| 1147 | + dev_err(&client->dev, "unable to register iio device\n"); | |
| 1148 | + goto out_poweroff; | |
| 1149 | + } | |
| 1152 | 1150 | |
| 1151 | + dev_dbg(&indio_dev->dev, "Registered device %s\n", name); | |
| 1153 | 1152 | return 0; |
| 1154 | 1153 | |
| 1155 | −out_iio_unregister: | |
| 1156 | − iio_device_unregister(indio_dev); | |
| 1157 | 1154 | out_poweroff: |
| 1158 | 1155 | mma9551_set_device_state(client, false); |
| 1159 | 1156 | return ret; |
| @@ -1164,11 +1161,12 @@ static int mma9553_remove(struct i2c_client *client) · 4 unmodified lines | ||
| 1164 | 1161 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 1165 | 1162 | struct mma9553_data *data = iio_priv(indio_dev); |
| 1166 | 1163 | |
| 1164 | + iio_device_unregister(indio_dev); | |
| 1165 | + | |
| 1167 | 1166 | pm_runtime_disable(&client->dev); |
| 1168 | 1167 | pm_runtime_set_suspended(&client->dev); |
| 1169 | 1168 | pm_runtime_put_noidle(&client->dev); |
| 1170 | 1169 | |
| 1171 | − iio_device_unregister(indio_dev); | |
| 1172 | 1170 | mutex_lock(&data->mutex); |
| 1173 | 1171 | mma9551_set_device_state(data->client, false); |
| 1174 | 1172 | mutex_unlock(&data->mutex); |
| @@ -0,0 +1,198 @@ | ||
| 1 | +/* | |
| 2 | + * MXC6255 - MEMSIC orientation sensing accelerometer | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015, Intel Corporation. | |
| 5 | + * | |
| 6 | + * This file is subject to the terms and conditions of version 2 of | |
| 7 | + * the GNU General Public License. See the file COPYING in the main | |
| 8 | + * directory of this archive for more details. | |
| 9 | + * | |
| 10 | + * IIO driver for MXC6255 (7-bit I2C slave address 0x15). | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/module.h> | |
| 14 | +#include <linux/i2c.h> | |
| 15 | +#include <linux/init.h> | |
| 16 | +#include <linux/iio/iio.h> | |
| 17 | +#include <linux/delay.h> | |
| 18 | +#include <linux/acpi.h> | |
| 19 | +#include <linux/regmap.h> | |
| 20 | +#include <linux/iio/sysfs.h> | |
| 21 | + | |
| 22 | +#define MXC6255_DRV_NAME "mxc6255" | |
| 23 | +#define MXC6255_REGMAP_NAME "mxc6255_regmap" | |
| 24 | + | |
| 25 | +#define MXC6255_REG_XOUT 0x00 | |
| 26 | +#define MXC6255_REG_YOUT 0x01 | |
| 27 | +#define MXC6255_REG_CHIP_ID 0x08 | |
| 28 | + | |
| 29 | +#define MXC6255_CHIP_ID 0x05 | |
| 30 | + | |
| 31 | +/* | |
| 32 | + * MXC6255 has only one measurement range: +/- 2G. | |
| 33 | + * The acceleration output is an 8-bit value. | |
| 34 | + * | |
| 35 | + * Scale is calculated as follows: | |
| 36 | + * (2 + 2) * 9.80665 / (2^8 - 1) = 0.153829 | |
| 37 | + * | |
| 38 | + * Scale value for +/- 2G measurement range | |
| 39 | + */ | |
| 40 | +#define MXC6255_SCALE 153829 | |
| 41 | + | |
| 42 | +enum mxc6255_axis { | |
| 43 | + AXIS_X, | |
| 44 | + AXIS_Y, | |
| 45 | +}; | |
| 46 | + | |
| 47 | +struct mxc6255_data { | |
| 48 | + struct i2c_client *client; | |
| 49 | + struct regmap *regmap; | |
| 50 | +}; | |
| 51 | + | |
| 52 | +static int mxc6255_read_raw(struct iio_dev *indio_dev, | |
| 53 | + struct iio_chan_spec const *chan, | |
| 54 | + int *val, int *val2, long mask) | |
| 55 | +{ | |
| 56 | + struct mxc6255_data *data = iio_priv(indio_dev); | |
| 57 | + unsigned int reg; | |
| 58 | + int ret; | |
| 59 | + | |
| 60 | + switch (mask) { | |
| 61 | + case IIO_CHAN_INFO_RAW: | |
| 62 | + ret = regmap_read(data->regmap, chan->address, ®); | |
| 63 | + if (ret < 0) { | |
| 64 | + dev_err(&data->client->dev, | |
| 65 | + "Error reading reg %lu\n", chan->address); | |
| 66 | + return ret; | |
| 67 | + } | |
| 68 | + | |
| 69 | + *val = sign_extend32(reg, 7); | |
| 70 | + return IIO_VAL_INT; | |
| 71 | + case IIO_CHAN_INFO_SCALE: | |
| 72 | + *val = 0; | |
| 73 | + *val2 = MXC6255_SCALE; | |
| 74 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 75 | + default: | |
| 76 | + return -EINVAL; | |
| 77 | + } | |
| 78 | +} | |
| 79 | + | |
| 80 | +static const struct iio_info mxc6255_info = { | |
| 81 | + .driver_module = THIS_MODULE, | |
| 82 | + .read_raw = mxc6255_read_raw, | |
| 83 | +}; | |
| 84 | + | |
| 85 | +#define MXC6255_CHANNEL(_axis, reg) { \ | |
| 86 | + .type = IIO_ACCEL, \ | |
| 87 | + .modified = 1, \ | |
| 88 | + .channel2 = IIO_MOD_##_axis, \ | |
| 89 | + .address = reg, \ | |
| 90 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 91 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
| 92 | +} | |
| 93 | + | |
| 94 | +static const struct iio_chan_spec mxc6255_channels[] = { | |
| 95 | + MXC6255_CHANNEL(X, MXC6255_REG_XOUT), | |
| 96 | + MXC6255_CHANNEL(Y, MXC6255_REG_YOUT), | |
| 97 | +}; | |
| 98 | + | |
| 99 | +static bool mxc6255_is_readable_reg(struct device *dev, unsigned int reg) | |
| 100 | +{ | |
| 101 | + switch (reg) { | |
| 102 | + case MXC6255_REG_XOUT: | |
| 103 | + case MXC6255_REG_YOUT: | |
| 104 | + case MXC6255_REG_CHIP_ID: | |
| 105 | + return true; | |
| 106 | + default: | |
| 107 | + return false; | |
| 108 | + } | |
| 109 | +} | |
| 110 | + | |
| 111 | +static const struct regmap_config mxc6255_regmap_config = { | |
| 112 | + .name = MXC6255_REGMAP_NAME, | |
| 113 | + | |
| 114 | + .reg_bits = 8, | |
| 115 | + .val_bits = 8, | |
| 116 | + | |
| 117 | + .readable_reg = mxc6255_is_readable_reg, | |
| 118 | +}; | |
| 119 | + | |
| 120 | +static int mxc6255_probe(struct i2c_client *client, | |
| 121 | + const struct i2c_device_id *id) | |
| 122 | +{ | |
| 123 | + struct mxc6255_data *data; | |
| 124 | + struct iio_dev *indio_dev; | |
| 125 | + struct regmap *regmap; | |
| 126 | + unsigned int chip_id; | |
| 127 | + int ret; | |
| 128 | + | |
| 129 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 130 | + if (!indio_dev) | |
| 131 | + return -ENOMEM; | |
| 132 | + | |
| 133 | + regmap = devm_regmap_init_i2c(client, &mxc6255_regmap_config); | |
| 134 | + if (IS_ERR(regmap)) { | |
| 135 | + dev_err(&client->dev, "Error initializing regmap\n"); | |
| 136 | + return PTR_ERR(regmap); | |
| 137 | + } | |
| 138 | + | |
| 139 | + data = iio_priv(indio_dev); | |
| 140 | + i2c_set_clientdata(client, indio_dev); | |
| 141 | + data->client = client; | |
| 142 | + data->regmap = regmap; | |
| 143 | + | |
| 144 | + indio_dev->name = MXC6255_DRV_NAME; | |
| 145 | + indio_dev->dev.parent = &client->dev; | |
| 146 | + indio_dev->channels = mxc6255_channels; | |
| 147 | + indio_dev->num_channels = ARRAY_SIZE(mxc6255_channels); | |
| 148 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 149 | + indio_dev->info = &mxc6255_info; | |
| 150 | + | |
| 151 | + ret = regmap_read(data->regmap, MXC6255_REG_CHIP_ID, &chip_id); | |
| 152 | + if (ret < 0) { | |
| 153 | + dev_err(&client->dev, "Error reading chip id %d\n", ret); | |
| 154 | + return ret; | |
| 155 | + } | |
| 156 | + | |
| 157 | + if (chip_id != MXC6255_CHIP_ID) { | |
| 158 | + dev_err(&client->dev, "Invalid chip id %x\n", chip_id); | |
| 159 | + return -ENODEV; | |
| 160 | + } | |
| 161 | + | |
| 162 | + dev_dbg(&client->dev, "Chip id %x\n", chip_id); | |
| 163 | + | |
| 164 | + ret = devm_iio_device_register(&client->dev, indio_dev); | |
| 165 | + if (ret < 0) { | |
| 166 | + dev_err(&client->dev, "Could not register IIO device\n"); | |
| 167 | + return ret; | |
| 168 | + } | |
| 169 | + | |
| 170 | + return 0; | |
| 171 | +} | |
| 172 | + | |
| 173 | +static const struct acpi_device_id mxc6255_acpi_match[] = { | |
| 174 | + {"MXC6255", 0}, | |
| 175 | + { } | |
| 176 | +}; | |
| 177 | +MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match); | |
| 178 | + | |
| 179 | +static const struct i2c_device_id mxc6255_id[] = { | |
| 180 | + {"mxc6255", 0}, | |
| 181 | + { } | |
| 182 | +}; | |
| 183 | +MODULE_DEVICE_TABLE(i2c, mxc6255_id); | |
| 184 | + | |
| 185 | +static struct i2c_driver mxc6255_driver = { | |
| 186 | + .driver = { | |
| 187 | + .name = MXC6255_DRV_NAME, | |
| 188 | + .acpi_match_table = ACPI_PTR(mxc6255_acpi_match), | |
| 189 | + }, | |
| 190 | + .probe = mxc6255_probe, | |
| 191 | + .id_table = mxc6255_id, | |
| 192 | +}; | |
| 193 | + | |
| 194 | +module_i2c_driver(mxc6255_driver); | |
| 195 | + | |
| 196 | +MODULE_AUTHOR("Teodora Baluta <teodora.baluta@intel.com>"); | |
| 197 | +MODULE_DESCRIPTION("MEMSIC MXC6255 orientation sensing accelerometer driver"); | |
| 198 | +MODULE_LICENSE("GPL v2"); | |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #define LSM303DLM_ACCEL_DEV_NAME "lsm303dlm_accel" |
| 28 | 28 | #define LSM330_ACCEL_DEV_NAME "lsm330_accel" |
| 29 | 29 | #define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel" |
| 30 | +#define LIS2DH12_ACCEL_DEV_NAME "lis2dh12_accel" | |
| 30 | 31 | |
| 31 | 32 | /** |
| 32 | 33 | * struct st_sensors_platform_data - default accel platform data |
| @@ -232,6 +232,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { · 231 unmodified lines | ||
| 232 | 232 | [3] = LSM330DL_ACCEL_DEV_NAME, |
| 233 | 233 | [4] = LSM330DLC_ACCEL_DEV_NAME, |
| 234 | 234 | [5] = LSM303AGR_ACCEL_DEV_NAME, |
| 235 | + [6] = LIS2DH12_ACCEL_DEV_NAME, | |
| 235 | 236 | }, |
| 236 | 237 | .ch = (struct iio_chan_spec *)st_accel_12bit_channels, |
| 237 | 238 | .odr = { |
| @@ -72,6 +72,10 @@ static const struct of_device_id st_accel_of_match[] = { · 71 unmodified lines | ||
| 72 | 72 | .compatible = "st,lsm303agr-accel", |
| 73 | 73 | .data = LSM303AGR_ACCEL_DEV_NAME, |
| 74 | 74 | }, |
| 75 | + { | |
| 76 | + .compatible = "st,lis2dh12-accel", | |
| 77 | + .data = LIS2DH12_ACCEL_DEV_NAME, | |
| 78 | + }, | |
| 75 | 79 | {}, |
| 76 | 80 | }; |
| 77 | 81 | MODULE_DEVICE_TABLE(of, st_accel_of_match); |
| @@ -121,6 +125,7 @@ static const struct i2c_device_id st_accel_id_table[] = { · 43 unmodified lines | ||
| 121 | 125 | { LSM303DLM_ACCEL_DEV_NAME }, |
| 122 | 126 | { LSM330_ACCEL_DEV_NAME }, |
| 123 | 127 | { LSM303AGR_ACCEL_DEV_NAME }, |
| 128 | + { LIS2DH12_ACCEL_DEV_NAME }, | |
| 124 | 129 | {}, |
| 125 | 130 | }; |
| 126 | 131 | MODULE_DEVICE_TABLE(i2c, st_accel_id_table); |
| @@ -58,6 +58,7 @@ static const struct spi_device_id st_accel_id_table[] = { · 57 unmodified lines | ||
| 58 | 58 | { LSM303DLM_ACCEL_DEV_NAME }, |
| 59 | 59 | { LSM330_ACCEL_DEV_NAME }, |
| 60 | 60 | { LSM303AGR_ACCEL_DEV_NAME }, |
| 61 | + { LIS2DH12_ACCEL_DEV_NAME }, | |
| 61 | 62 | {}, |
| 62 | 63 | }; |
| 63 | 64 | MODULE_DEVICE_TABLE(spi, st_accel_id_table); |
| @@ -194,6 +194,25 @@ config HI8435 · 193 unmodified lines | ||
| 194 | 194 | This driver can also be built as a module. If so, the module will be |
| 195 | 195 | called hi8435. |
| 196 | 196 | |
| 197 | +config INA2XX_ADC | |
| 198 | + tristate "Texas Instruments INA2xx Power Monitors IIO driver" | |
| 199 | + depends on I2C && !SENSORS_INA2XX | |
| 200 | + select REGMAP_I2C | |
| 201 | + select IIO_BUFFER | |
| 202 | + select IIO_KFIFO_BUF | |
| 203 | + help | |
| 204 | + Say yes here to build support for TI INA2xx family of Power Monitors. | |
| 205 | + This driver is mutually exclusive with the HWMON version. | |
| 206 | + | |
| 207 | +config IMX7D_ADC | |
| 208 | + tristate "IMX7D ADC driver" | |
| 209 | + depends on ARCH_MXC || COMPILE_TEST | |
| 210 | + help | |
| 211 | + Say yes here to build support for IMX7D ADC. | |
| 212 | + | |
| 213 | + This driver can also be built as a module. If so, the module will be | |
| 214 | + called imx7d_adc. | |
| 215 | + | |
| 197 | 216 | config LP8788_ADC |
| 198 | 217 | tristate "LP8788 ADC driver" |
| 199 | 218 | depends on MFD_LP8788 |
| @@ -275,6 +294,14 @@ config NAU7802 · 75 unmodified lines | ||
| 275 | 294 | To compile this driver as a module, choose M here: the |
| 276 | 295 | module will be called nau7802. |
| 277 | 296 | |
| 297 | +config PALMAS_GPADC | |
| 298 | + tristate "TI Palmas General Purpose ADC" | |
| 299 | + depends on MFD_PALMAS | |
| 300 | + help | |
| 301 | + Palmas series pmic chip by Texas Instruments (twl6035/6037) | |
| 302 | + is used in smartphones and tablets and supports a 16 channel | |
| 303 | + general purpose ADC. | |
| 304 | + | |
| 278 | 305 | config QCOM_SPMI_IADC |
| 279 | 306 | tristate "Qualcomm SPMI PMIC current ADC" |
| 280 | 307 | depends on SPMI |
| @@ -324,15 +351,25 @@ config TI_ADC081C · 43 unmodified lines | ||
| 324 | 351 | called ti-adc081c. |
| 325 | 352 | |
| 326 | 353 | config TI_ADC128S052 |
| 327 | − tristate "Texas Instruments ADC128S052/ADC122S021" | |
| 354 | + tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021" | |
| 328 | 355 | depends on SPI |
| 329 | 356 | help |
| 330 | − If you say yes here you get support for Texas Instruments ADC128S052 | |
| 331 | − and ADC122S021 chips. | |
| 357 | + If you say yes here you get support for Texas Instruments ADC128S052, | |
| 358 | + ADC122S021 and ADC124S021 chips. | |
| 332 | 359 | |
| 333 | 360 | This driver can also be built as a module. If so, the module will be |
| 334 | 361 | called ti-adc128s052. |
| 335 | 362 | |
| 363 | +config TI_ADS8688 | |
| 364 | + tristate "Texas Instruments ADS8688" | |
| 365 | + depends on SPI && OF | |
| 366 | + help | |
| 367 | + If you say yes here you get support for Texas Instruments ADS8684 and | |
| 368 | + and ADS8688 ADC chips | |
| 369 | + | |
| 370 | + This driver can also be built as a module. If so, the module will be | |
| 371 | + called ti-ads8688. | |
| 372 | + | |
| 336 | 373 | config TI_AM335X_ADC |
| 337 | 374 | tristate "TI's AM335X ADC driver" |
| 338 | 375 | depends on MFD_TI_AM335X_TSCADC |
| @@ -20,6 +20,8 @@ obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o · 19 unmodified lines | ||
| 20 | 20 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o |
| 21 | 21 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o |
| 22 | 22 | obj-$(CONFIG_HI8435) += hi8435.o |
| 23 | +obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o | |
| 24 | +obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o | |
| 23 | 25 | obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o |
| 24 | 26 | obj-$(CONFIG_MAX1027) += max1027.o |
| 25 | 27 | obj-$(CONFIG_MAX1363) += max1363.o |
| @@ -27,11 +29,13 @@ obj-$(CONFIG_MCP320X) += mcp320x.o · 1 unmodified line | ||
| 27 | 29 | obj-$(CONFIG_MCP3422) += mcp3422.o |
| 28 | 30 | obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o |
| 29 | 31 | obj-$(CONFIG_NAU7802) += nau7802.o |
| 32 | +obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o | |
| 30 | 33 | obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o |
| 31 | 34 | obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o |
| 32 | 35 | obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o |
| 33 | 36 | obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o |
| 34 | 37 | obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o |
| 38 | +obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o | |
| 35 | 39 | obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o |
| 36 | 40 | obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o |
| 37 | 41 | obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o |
| @@ -478,10 +478,9 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, · 477 unmodified lines | ||
| 478 | 478 | *val2 = st-> |
| 479 | 479 | scale_avail[(st->conf >> 8) & 0x7][1]; |
| 480 | 480 | return IIO_VAL_INT_PLUS_NANO; |
| 481 | − } else { | |
| 482 | − /* 1170mV / 2^23 * 6 */ | |
| 483 | − scale_uv = (1170ULL * 1000000000ULL * 6ULL); | |
| 484 | 481 | } |
| 482 | + /* 1170mV / 2^23 * 6 */ | |
| 483 | + scale_uv = (1170ULL * 1000000000ULL * 6ULL); | |
| 485 | 484 | break; |
| 486 | 485 | case IIO_TEMP: |
| 487 | 486 | /* 1170mV / 0.81 mV/C / 2^23 */ |
| @@ -742,7 +742,7 @@ static int at91_adc_of_get_resolution(struct at91_adc_state *st, · 741 unmodified lines | ||
| 742 | 742 | return count; |
| 743 | 743 | } |
| 744 | 744 | |
| 745 | − resolutions = kmalloc(count * sizeof(*resolutions), GFP_KERNEL); | |
| 745 | + resolutions = kmalloc_array(count, sizeof(*resolutions), GFP_KERNEL); | |
| 746 | 746 | if (!resolutions) |
| 747 | 747 | return -ENOMEM; |
| 748 | 748 | |
| @@ -0,0 +1,609 @@ | ||
| 1 | +/* | |
| 2 | + * Freescale i.MX7D ADC driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2015 Freescale Semiconductor, Inc. | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + */ | |
| 11 | + | |
| 12 | +#include <linux/clk.h> | |
| 13 | +#include <linux/completion.h> | |
| 14 | +#include <linux/err.h> | |
| 15 | +#include <linux/interrupt.h> | |
| 16 | +#include <linux/io.h> | |
| 17 | +#include <linux/kernel.h> | |
| 18 | +#include <linux/module.h> | |
| 19 | +#include <linux/platform_device.h> | |
| 20 | +#include <linux/regulator/consumer.h> | |
| 21 | + | |
| 22 | +#include <linux/iio/iio.h> | |
| 23 | +#include <linux/iio/driver.h> | |
| 24 | +#include <linux/iio/sysfs.h> | |
| 25 | + | |
| 26 | +/* ADC register */ | |
| 27 | +#define IMX7D_REG_ADC_CH_A_CFG1 0x00 | |
| 28 | +#define IMX7D_REG_ADC_CH_A_CFG2 0x10 | |
| 29 | +#define IMX7D_REG_ADC_CH_B_CFG1 0x20 | |
| 30 | +#define IMX7D_REG_ADC_CH_B_CFG2 0x30 | |
| 31 | +#define IMX7D_REG_ADC_CH_C_CFG1 0x40 | |
| 32 | +#define IMX7D_REG_ADC_CH_C_CFG2 0x50 | |
| 33 | +#define IMX7D_REG_ADC_CH_D_CFG1 0x60 | |
| 34 | +#define IMX7D_REG_ADC_CH_D_CFG2 0x70 | |
| 35 | +#define IMX7D_REG_ADC_CH_SW_CFG 0x80 | |
| 36 | +#define IMX7D_REG_ADC_TIMER_UNIT 0x90 | |
| 37 | +#define IMX7D_REG_ADC_DMA_FIFO 0xa0 | |
| 38 | +#define IMX7D_REG_ADC_FIFO_STATUS 0xb0 | |
| 39 | +#define IMX7D_REG_ADC_INT_SIG_EN 0xc0 | |
| 40 | +#define IMX7D_REG_ADC_INT_EN 0xd0 | |
| 41 | +#define IMX7D_REG_ADC_INT_STATUS 0xe0 | |
| 42 | +#define IMX7D_REG_ADC_CHA_B_CNV_RSLT 0xf0 | |
| 43 | +#define IMX7D_REG_ADC_CHC_D_CNV_RSLT 0x100 | |
| 44 | +#define IMX7D_REG_ADC_CH_SW_CNV_RSLT 0x110 | |
| 45 | +#define IMX7D_REG_ADC_DMA_FIFO_DAT 0x120 | |
| 46 | +#define IMX7D_REG_ADC_ADC_CFG 0x130 | |
| 47 | + | |
| 48 | +#define IMX7D_REG_ADC_CHANNEL_CFG2_BASE 0x10 | |
| 49 | +#define IMX7D_EACH_CHANNEL_REG_OFFSET 0x20 | |
| 50 | + | |
| 51 | +#define IMX7D_REG_ADC_CH_CFG1_CHANNEL_EN (0x1 << 31) | |
| 52 | +#define IMX7D_REG_ADC_CH_CFG1_CHANNEL_SINGLE BIT(30) | |
| 53 | +#define IMX7D_REG_ADC_CH_CFG1_CHANNEL_AVG_EN BIT(29) | |
| 54 | +#define IMX7D_REG_ADC_CH_CFG1_CHANNEL_SEL(x) ((x) << 24) | |
| 55 | + | |
| 56 | +#define IMX7D_REG_ADC_CH_CFG2_AVG_NUM_4 (0x0 << 12) | |
| 57 | +#define IMX7D_REG_ADC_CH_CFG2_AVG_NUM_8 (0x1 << 12) | |
| 58 | +#define IMX7D_REG_ADC_CH_CFG2_AVG_NUM_16 (0x2 << 12) | |
| 59 | +#define IMX7D_REG_ADC_CH_CFG2_AVG_NUM_32 (0x3 << 12) | |
| 60 | + | |
| 61 | +#define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_4 (0x0 << 29) | |
| 62 | +#define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_8 (0x1 << 29) | |
| 63 | +#define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_16 (0x2 << 29) | |
| 64 | +#define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_32 (0x3 << 29) | |
| 65 | +#define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_64 (0x4 << 29) | |
| 66 | +#define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_128 (0x5 << 29) | |
| 67 | + | |
| 68 | +#define IMX7D_REG_ADC_ADC_CFG_ADC_CLK_DOWN BIT(31) | |
| 69 | +#define IMX7D_REG_ADC_ADC_CFG_ADC_POWER_DOWN BIT(1) | |
| 70 | +#define IMX7D_REG_ADC_ADC_CFG_ADC_EN BIT(0) | |
| 71 | + | |
| 72 | +#define IMX7D_REG_ADC_INT_CHA_COV_INT_EN BIT(8) | |
| 73 | +#define IMX7D_REG_ADC_INT_CHB_COV_INT_EN BIT(9) | |
| 74 | +#define IMX7D_REG_ADC_INT_CHC_COV_INT_EN BIT(10) | |
| 75 | +#define IMX7D_REG_ADC_INT_CHD_COV_INT_EN BIT(11) | |
| 76 | +#define IMX7D_REG_ADC_INT_CHANNEL_INT_EN \ | |
| 77 | + (IMX7D_REG_ADC_INT_CHA_COV_INT_EN | \ | |
| 78 | + IMX7D_REG_ADC_INT_CHB_COV_INT_EN | \ | |
| 79 | + IMX7D_REG_ADC_INT_CHC_COV_INT_EN | \ | |
| 80 | + IMX7D_REG_ADC_INT_CHD_COV_INT_EN) | |
| 81 | +#define IMX7D_REG_ADC_INT_STATUS_CHANNEL_INT_STATUS 0xf00 | |
| 82 | +#define IMX7D_REG_ADC_INT_STATUS_CHANNEL_CONV_TIME_OUT 0xf0000 | |
| 83 | + | |
| 84 | +#define IMX7D_ADC_TIMEOUT msecs_to_jiffies(100) | |
| 85 | + | |
| 86 | +enum imx7d_adc_clk_pre_div { | |
| 87 | + IMX7D_ADC_ANALOG_CLK_PRE_DIV_4, | |
| 88 | + IMX7D_ADC_ANALOG_CLK_PRE_DIV_8, | |
| 89 | + IMX7D_ADC_ANALOG_CLK_PRE_DIV_16, | |
| 90 | + IMX7D_ADC_ANALOG_CLK_PRE_DIV_32, | |
| 91 | + IMX7D_ADC_ANALOG_CLK_PRE_DIV_64, | |
| 92 | + IMX7D_ADC_ANALOG_CLK_PRE_DIV_128, | |
| 93 | +}; | |
| 94 | + | |
| 95 | +enum imx7d_adc_average_num { | |
| 96 | + IMX7D_ADC_AVERAGE_NUM_4, | |
| 97 | + IMX7D_ADC_AVERAGE_NUM_8, | |
| 98 | + IMX7D_ADC_AVERAGE_NUM_16, | |
| 99 | + IMX7D_ADC_AVERAGE_NUM_32, | |
| 100 | +}; | |
| 101 | + | |
| 102 | +struct imx7d_adc_feature { | |
| 103 | + enum imx7d_adc_clk_pre_div clk_pre_div; | |
| 104 | + enum imx7d_adc_average_num avg_num; | |
| 105 | + | |
| 106 | + u32 core_time_unit; /* impact the sample rate */ | |
| 107 | + | |
| 108 | + bool average_en; | |
| 109 | +}; | |
| 110 | + | |
| 111 | +struct imx7d_adc { | |
| 112 | + struct device *dev; | |
| 113 | + void __iomem *regs; | |
| 114 | + struct clk *clk; | |
| 115 | + | |
| 116 | + u32 vref_uv; | |
| 117 | + u32 value; | |
| 118 | + u32 channel; | |
| 119 | + u32 pre_div_num; | |
| 120 | + | |
| 121 | + struct regulator *vref; | |
| 122 | + struct imx7d_adc_feature adc_feature; | |
| 123 | + | |
| 124 | + struct completion completion; | |
| 125 | +}; | |
| 126 | + | |
| 127 | +struct imx7d_adc_analogue_core_clk { | |
| 128 | + u32 pre_div; | |
| 129 | + u32 reg_config; | |
| 130 | +}; | |
| 131 | + | |
| 132 | +#define IMX7D_ADC_ANALOGUE_CLK_CONFIG(_pre_div, _reg_conf) { \ | |
| 133 | + .pre_div = (_pre_div), \ | |
| 134 | + .reg_config = (_reg_conf), \ | |
| 135 | +} | |
| 136 | + | |
| 137 | +static const struct imx7d_adc_analogue_core_clk imx7d_adc_analogue_clk[] = { | |
| 138 | + IMX7D_ADC_ANALOGUE_CLK_CONFIG(4, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_4), | |
| 139 | + IMX7D_ADC_ANALOGUE_CLK_CONFIG(8, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_8), | |
| 140 | + IMX7D_ADC_ANALOGUE_CLK_CONFIG(16, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_16), | |
| 141 | + IMX7D_ADC_ANALOGUE_CLK_CONFIG(32, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_32), | |
| 142 | + IMX7D_ADC_ANALOGUE_CLK_CONFIG(64, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_64), | |
| 143 | + IMX7D_ADC_ANALOGUE_CLK_CONFIG(128, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_128), | |
| 144 | +}; | |
| 145 | + | |
| 146 | +#define IMX7D_ADC_CHAN(_idx) { \ | |
| 147 | + .type = IIO_VOLTAGE, \ | |
| 148 | + .indexed = 1, \ | |
| 149 | + .channel = (_idx), \ | |
| 150 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 151 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | |
| 152 | + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | |
| 153 | +} | |
| 154 | + | |
| 155 | +static const struct iio_chan_spec imx7d_adc_iio_channels[] = { | |
| 156 | + IMX7D_ADC_CHAN(0), | |
| 157 | + IMX7D_ADC_CHAN(1), | |
| 158 | + IMX7D_ADC_CHAN(2), | |
| 159 | + IMX7D_ADC_CHAN(3), | |
| 160 | + IMX7D_ADC_CHAN(4), | |
| 161 | + IMX7D_ADC_CHAN(5), | |
| 162 | + IMX7D_ADC_CHAN(6), | |
| 163 | + IMX7D_ADC_CHAN(7), | |
| 164 | + IMX7D_ADC_CHAN(8), | |
| 165 | + IMX7D_ADC_CHAN(9), | |
| 166 | + IMX7D_ADC_CHAN(10), | |
| 167 | + IMX7D_ADC_CHAN(11), | |
| 168 | + IMX7D_ADC_CHAN(12), | |
| 169 | + IMX7D_ADC_CHAN(13), | |
| 170 | + IMX7D_ADC_CHAN(14), | |
| 171 | + IMX7D_ADC_CHAN(15), | |
| 172 | +}; | |
| 173 | + | |
| 174 | +static const u32 imx7d_adc_average_num[] = { | |
| 175 | + IMX7D_REG_ADC_CH_CFG2_AVG_NUM_4, | |
| 176 | + IMX7D_REG_ADC_CH_CFG2_AVG_NUM_8, | |
| 177 | + IMX7D_REG_ADC_CH_CFG2_AVG_NUM_16, | |
| 178 | + IMX7D_REG_ADC_CH_CFG2_AVG_NUM_32, | |
| 179 | +}; | |
| 180 | + | |
| 181 | +static void imx7d_adc_feature_config(struct imx7d_adc *info) | |
| 182 | +{ | |
| 183 | + info->adc_feature.clk_pre_div = IMX7D_ADC_ANALOG_CLK_PRE_DIV_4; | |
| 184 | + info->adc_feature.avg_num = IMX7D_ADC_AVERAGE_NUM_32; | |
| 185 | + info->adc_feature.core_time_unit = 1; | |
| 186 | + info->adc_feature.average_en = true; | |
| 187 | +} | |
| 188 | + | |
| 189 | +static void imx7d_adc_sample_rate_set(struct imx7d_adc *info) | |
| 190 | +{ | |
| 191 | + struct imx7d_adc_feature *adc_feature = &info->adc_feature; | |
| 192 | + struct imx7d_adc_analogue_core_clk adc_analogure_clk; | |
| 193 | + u32 i; | |
| 194 | + u32 tmp_cfg1; | |
| 195 | + u32 sample_rate = 0; | |
| 196 | + | |
| 197 | + /* | |
| 198 | + * Before sample set, disable channel A,B,C,D. Here we | |
| 199 | + * clear the bit 31 of register REG_ADC_CH_A\B\C\D_CFG1. | |
| 200 | + */ | |
| 201 | + for (i = 0; i < 4; i++) { | |
| 202 | + tmp_cfg1 = | |
| 203 | + readl(info->regs + i * IMX7D_EACH_CHANNEL_REG_OFFSET); | |
| 204 | + tmp_cfg1 &= ~IMX7D_REG_ADC_CH_CFG1_CHANNEL_EN; | |
| 205 | + writel(tmp_cfg1, | |
| 206 | + info->regs + i * IMX7D_EACH_CHANNEL_REG_OFFSET); | |
| 207 | + } | |
| 208 | + | |
| 209 | + adc_analogure_clk = imx7d_adc_analogue_clk[adc_feature->clk_pre_div]; | |
| 210 | + sample_rate |= adc_analogure_clk.reg_config; | |
| 211 | + info->pre_div_num = adc_analogure_clk.pre_div; | |
| 212 | + | |
| 213 | + sample_rate |= adc_feature->core_time_unit; | |
| 214 | + writel(sample_rate, info->regs + IMX7D_REG_ADC_TIMER_UNIT); | |
| 215 | +} | |
| 216 | + | |
| 217 | +static void imx7d_adc_hw_init(struct imx7d_adc *info) | |
| 218 | +{ | |
| 219 | + u32 cfg; | |
| 220 | + | |
| 221 | + /* power up and enable adc analogue core */ | |
| 222 | + cfg = readl(info->regs + IMX7D_REG_ADC_ADC_CFG); | |
| 223 | + cfg &= ~(IMX7D_REG_ADC_ADC_CFG_ADC_CLK_DOWN | | |
| 224 | + IMX7D_REG_ADC_ADC_CFG_ADC_POWER_DOWN); | |
| 225 | + cfg |= IMX7D_REG_ADC_ADC_CFG_ADC_EN; | |
| 226 | + writel(cfg, info->regs + IMX7D_REG_ADC_ADC_CFG); | |
| 227 | + | |
| 228 | + /* enable channel A,B,C,D interrupt */ | |
| 229 | + writel(IMX7D_REG_ADC_INT_CHANNEL_INT_EN, | |
| 230 | + info->regs + IMX7D_REG_ADC_INT_SIG_EN); | |
| 231 | + writel(IMX7D_REG_ADC_INT_CHANNEL_INT_EN, | |
| 232 | + info->regs + IMX7D_REG_ADC_INT_EN); | |
| 233 | + | |
| 234 | + imx7d_adc_sample_rate_set(info); | |
| 235 | +} | |
| 236 | + | |
| 237 | +static void imx7d_adc_channel_set(struct imx7d_adc *info) | |
| 238 | +{ | |
| 239 | + u32 cfg1 = 0; | |
| 240 | + u32 cfg2; | |
| 241 | + u32 channel; | |
| 242 | + | |
| 243 | + channel = info->channel; | |
| 244 | + | |
| 245 | + /* the channel choose single conversion, and enable average mode */ | |
| 246 | + cfg1 |= (IMX7D_REG_ADC_CH_CFG1_CHANNEL_EN | | |
| 247 | + IMX7D_REG_ADC_CH_CFG1_CHANNEL_SINGLE); | |
| 248 | + if (info->adc_feature.average_en) | |
| 249 | + cfg1 |= IMX7D_REG_ADC_CH_CFG1_CHANNEL_AVG_EN; | |
| 250 | + | |
| 251 | + /* | |
| 252 | + * physical channel 0 chose logical channel A | |
| 253 | + * physical channel 1 chose logical channel B | |
| 254 | + * physical channel 2 chose logical channel C | |
| 255 | + * physical channel 3 chose logical channel D | |
| 256 | + */ | |
| 257 | + cfg1 |= IMX7D_REG_ADC_CH_CFG1_CHANNEL_SEL(channel); | |
| 258 | + | |
| 259 | + /* | |
| 260 | + * read register REG_ADC_CH_A\B\C\D_CFG2, according to the | |
| 261 | + * channel chosen | |
| 262 | + */ | |
| 263 | + cfg2 = readl(info->regs + IMX7D_EACH_CHANNEL_REG_OFFSET * channel + | |
| 264 | + IMX7D_REG_ADC_CHANNEL_CFG2_BASE); | |
| 265 | + | |
| 266 | + cfg2 |= imx7d_adc_average_num[info->adc_feature.avg_num]; | |
| 267 | + | |
| 268 | + /* | |
| 269 | + * write the register REG_ADC_CH_A\B\C\D_CFG2, according to | |
| 270 | + * the channel chosen | |
| 271 | + */ | |
| 272 | + writel(cfg2, info->regs + IMX7D_EACH_CHANNEL_REG_OFFSET * channel + | |
| 273 | + IMX7D_REG_ADC_CHANNEL_CFG2_BASE); | |
| 274 | + writel(cfg1, info->regs + IMX7D_EACH_CHANNEL_REG_OFFSET * channel); | |
| 275 | +} | |
| 276 | + | |
| 277 | +static u32 imx7d_adc_get_sample_rate(struct imx7d_adc *info) | |
| 278 | +{ | |
| 279 | + /* input clock is always 24MHz */ | |
| 280 | + u32 input_clk = 24000000; | |
| 281 | + u32 analogue_core_clk; | |
| 282 | + u32 core_time_unit = info->adc_feature.core_time_unit; | |
| 283 | + u32 tmp; | |
| 284 | + | |
| 285 | + analogue_core_clk = input_clk / info->pre_div_num; | |
| 286 | + tmp = (core_time_unit + 1) * 6; | |
| 287 | + | |
| 288 | + return analogue_core_clk / tmp; | |
| 289 | +} | |
| 290 | + | |
| 291 | +static int imx7d_adc_read_raw(struct iio_dev *indio_dev, | |
| 292 | + struct iio_chan_spec const *chan, | |
| 293 | + int *val, | |
| 294 | + int *val2, | |
| 295 | + long mask) | |
| 296 | +{ | |
| 297 | + struct imx7d_adc *info = iio_priv(indio_dev); | |
| 298 | + | |
| 299 | + u32 channel; | |
| 300 | + long ret; | |
| 301 | + | |
| 302 | + switch (mask) { | |
| 303 | + case IIO_CHAN_INFO_RAW: | |
| 304 | + mutex_lock(&indio_dev->mlock); | |
| 305 | + reinit_completion(&info->completion); | |
| 306 | + | |
| 307 | + channel = chan->channel & 0x03; | |
| 308 | + info->channel = channel; | |
| 309 | + imx7d_adc_channel_set(info); | |
| 310 | + | |
| 311 | + ret = wait_for_completion_interruptible_timeout | |
| 312 | + (&info->completion, IMX7D_ADC_TIMEOUT); | |
| 313 | + if (ret == 0) { | |
| 314 | + mutex_unlock(&indio_dev->mlock); | |
| 315 | + return -ETIMEDOUT; | |
| 316 | + } | |
| 317 | + if (ret < 0) { | |
| 318 | + mutex_unlock(&indio_dev->mlock); | |
| 319 | + return ret; | |
| 320 | + } | |
| 321 | + | |
| 322 | + *val = info->value; | |
| 323 | + mutex_unlock(&indio_dev->mlock); | |
| 324 | + return IIO_VAL_INT; | |
| 325 | + | |
| 326 | + case IIO_CHAN_INFO_SCALE: | |
| 327 | + info->vref_uv = regulator_get_voltage(info->vref); | |
| 328 | + *val = info->vref_uv / 1000; | |
| 329 | + *val2 = 12; | |
| 330 | + return IIO_VAL_FRACTIONAL_LOG2; | |
| 331 | + | |
| 332 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 333 | + *val = imx7d_adc_get_sample_rate(info); | |
| 334 | + return IIO_VAL_INT; | |
| 335 | + | |
| 336 | + default: | |
| 337 | + return -EINVAL; | |
| 338 | + } | |
| 339 | +} | |
| 340 | + | |
| 341 | +static int imx7d_adc_read_data(struct imx7d_adc *info) | |
| 342 | +{ | |
| 343 | + u32 channel; | |
| 344 | + u32 value; | |
| 345 | + | |
| 346 | + channel = info->channel & 0x03; | |
| 347 | + | |
| 348 | + /* | |
| 349 | + * channel A and B conversion result share one register, | |
| 350 | + * bit[27~16] is the channel B conversion result, | |
| 351 | + * bit[11~0] is the channel A conversion result. | |
| 352 | + * channel C and D is the same. | |
| 353 | + */ | |
| 354 | + if (channel < 2) | |
| 355 | + value = readl(info->regs + IMX7D_REG_ADC_CHA_B_CNV_RSLT); | |
| 356 | + else | |
| 357 | + value = readl(info->regs + IMX7D_REG_ADC_CHC_D_CNV_RSLT); | |
| 358 | + if (channel & 0x1) /* channel B or D */ | |
| 359 | + value = (value >> 16) & 0xFFF; | |
| 360 | + else /* channel A or C */ | |
| 361 | + value &= 0xFFF; | |
| 362 | + | |
| 363 | + return value; | |
| 364 | +} | |
| 365 | + | |
| 366 | +static irqreturn_t imx7d_adc_isr(int irq, void *dev_id) | |
| 367 | +{ | |
| 368 | + struct imx7d_adc *info = (struct imx7d_adc *)dev_id; | |
| 369 | + int status; | |
| 370 | + | |
| 371 | + status = readl(info->regs + IMX7D_REG_ADC_INT_STATUS); | |
| 372 | + if (status & IMX7D_REG_ADC_INT_STATUS_CHANNEL_INT_STATUS) { | |
| 373 | + info->value = imx7d_adc_read_data(info); | |
| 374 | + complete(&info->completion); | |
| 375 | + | |
| 376 | + /* | |
| 377 | + * The register IMX7D_REG_ADC_INT_STATUS can't clear | |
| 378 | + * itself after read operation, need software to write | |
| 379 | + * 0 to the related bit. Here we clear the channel A/B/C/D | |
| 380 | + * conversion finished flag. | |
| 381 | + */ | |
| 382 | + status &= ~IMX7D_REG_ADC_INT_STATUS_CHANNEL_INT_STATUS; | |
| 383 | + writel(status, info->regs + IMX7D_REG_ADC_INT_STATUS); | |
| 384 | + } | |
| 385 | + | |
| 386 | + /* | |
| 387 | + * If the channel A/B/C/D conversion timeout, report it and clear these | |
| 388 | + * timeout flags. | |
| 389 | + */ | |
| 390 | + if (status & IMX7D_REG_ADC_INT_STATUS_CHANNEL_CONV_TIME_OUT) { | |
| 391 | + pr_err("%s: ADC got conversion time out interrupt: 0x%08x\n", | |
| 392 | + dev_name(info->dev), status); | |
| 393 | + status &= ~IMX7D_REG_ADC_INT_STATUS_CHANNEL_CONV_TIME_OUT; | |
| 394 | + writel(status, info->regs + IMX7D_REG_ADC_INT_STATUS); | |
| 395 | + } | |
| 396 | + | |
| 397 | + return IRQ_HANDLED; | |
| 398 | +} | |
| 399 | + | |
| 400 | +static int imx7d_adc_reg_access(struct iio_dev *indio_dev, | |
| 401 | + unsigned reg, unsigned writeval, | |
| 402 | + unsigned *readval) | |
| 403 | +{ | |
| 404 | + struct imx7d_adc *info = iio_priv(indio_dev); | |
| 405 | + | |
| 406 | + if (!readval || reg % 4 || reg > IMX7D_REG_ADC_ADC_CFG) | |
| 407 | + return -EINVAL; | |
| 408 | + | |
| 409 | + *readval = readl(info->regs + reg); | |
| 410 | + | |
| 411 | + return 0; | |
| 412 | +} | |
| 413 | + | |
| 414 | +static const struct iio_info imx7d_adc_iio_info = { | |
| 415 | + .driver_module = THIS_MODULE, | |
| 416 | + .read_raw = &imx7d_adc_read_raw, | |
| 417 | + .debugfs_reg_access = &imx7d_adc_reg_access, | |
| 418 | +}; | |
| 419 | + | |
| 420 | +static const struct of_device_id imx7d_adc_match[] = { | |
| 421 | + { .compatible = "fsl,imx7d-adc", }, | |
| 422 | + { /* sentinel */ } | |
| 423 | +}; | |
| 424 | +MODULE_DEVICE_TABLE(of, imx7d_adc_match); | |
| 425 | + | |
| 426 | +static void imx7d_adc_power_down(struct imx7d_adc *info) | |
| 427 | +{ | |
| 428 | + u32 adc_cfg; | |
| 429 | + | |
| 430 | + adc_cfg = readl(info->regs + IMX7D_REG_ADC_ADC_CFG); | |
| 431 | + adc_cfg |= IMX7D_REG_ADC_ADC_CFG_ADC_CLK_DOWN | | |
| 432 | + IMX7D_REG_ADC_ADC_CFG_ADC_POWER_DOWN; | |
| 433 | + adc_cfg &= ~IMX7D_REG_ADC_ADC_CFG_ADC_EN; | |
| 434 | + writel(adc_cfg, info->regs + IMX7D_REG_ADC_ADC_CFG); | |
| 435 | +} | |
| 436 | + | |
| 437 | +static int imx7d_adc_probe(struct platform_device *pdev) | |
| 438 | +{ | |
| 439 | + struct imx7d_adc *info; | |
| 440 | + struct iio_dev *indio_dev; | |
| 441 | + struct resource *mem; | |
| 442 | + int irq; | |
| 443 | + int ret; | |
| 444 | + | |
| 445 | + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); | |
| 446 | + if (!indio_dev) { | |
| 447 | + dev_err(&pdev->dev, "Failed allocating iio device\n"); | |
| 448 | + return -ENOMEM; | |
| 449 | + } | |
| 450 | + | |
| 451 | + info = iio_priv(indio_dev); | |
| 452 | + info->dev = &pdev->dev; | |
| 453 | + | |
| 454 | + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 455 | + info->regs = devm_ioremap_resource(&pdev->dev, mem); | |
| 456 | + if (IS_ERR(info->regs)) { | |
| 457 | + ret = PTR_ERR(info->regs); | |
| 458 | + dev_err(&pdev->dev, | |
| 459 | + "Failed to remap adc memory, err = %d\n", ret); | |
| 460 | + return ret; | |
| 461 | + } | |
| 462 | + | |
| 463 | + irq = platform_get_irq(pdev, 0); | |
| 464 | + if (irq < 0) { | |
| 465 | + dev_err(&pdev->dev, "No irq resource?\n"); | |
| 466 | + return irq; | |
| 467 | + } | |
| 468 | + | |
| 469 | + info->clk = devm_clk_get(&pdev->dev, "adc"); | |
| 470 | + if (IS_ERR(info->clk)) { | |
| 471 | + ret = PTR_ERR(info->clk); | |
| 472 | + dev_err(&pdev->dev, "Failed getting clock, err = %d\n", ret); | |
| 473 | + return ret; | |
| 474 | + } | |
| 475 | + | |
| 476 | + info->vref = devm_regulator_get(&pdev->dev, "vref"); | |
| 477 | + if (IS_ERR(info->vref)) { | |
| 478 | + ret = PTR_ERR(info->vref); | |
| 479 | + dev_err(&pdev->dev, | |
| 480 | + "Failed getting reference voltage, err = %d\n", ret); | |
| 481 | + return ret; | |
| 482 | + } | |
| 483 | + | |
| 484 | + ret = regulator_enable(info->vref); | |
| 485 | + if (ret) { | |
| 486 | + dev_err(&pdev->dev, | |
| 487 | + "Can't enable adc reference top voltage, err = %d\n", | |
| 488 | + ret); | |
| 489 | + return ret; | |
| 490 | + } | |
| 491 | + | |
| 492 | + platform_set_drvdata(pdev, indio_dev); | |
| 493 | + | |
| 494 | + init_completion(&info->completion); | |
| 495 | + | |
| 496 | + indio_dev->name = dev_name(&pdev->dev); | |
| 497 | + indio_dev->dev.parent = &pdev->dev; | |
| 498 | + indio_dev->info = &imx7d_adc_iio_info; | |
| 499 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 500 | + indio_dev->channels = imx7d_adc_iio_channels; | |
| 501 | + indio_dev->num_channels = ARRAY_SIZE(imx7d_adc_iio_channels); | |
| 502 | + | |
| 503 | + ret = clk_prepare_enable(info->clk); | |
| 504 | + if (ret) { | |
| 505 | + dev_err(&pdev->dev, | |
| 506 | + "Could not prepare or enable the clock.\n"); | |
| 507 | + goto error_adc_clk_enable; | |
| 508 | + } | |
| 509 | + | |
| 510 | + ret = devm_request_irq(info->dev, irq, | |
| 511 | + imx7d_adc_isr, 0, | |
| 512 | + dev_name(&pdev->dev), info); | |
| 513 | + if (ret < 0) { | |
| 514 | + dev_err(&pdev->dev, "Failed requesting irq, irq = %d\n", irq); | |
| 515 | + goto error_iio_device_register; | |
| 516 | + } | |
| 517 | + | |
| 518 | + imx7d_adc_feature_config(info); | |
| 519 | + imx7d_adc_hw_init(info); | |
| 520 | + | |
| 521 | + ret = iio_device_register(indio_dev); | |
| 522 | + if (ret) { | |
| 523 | + imx7d_adc_power_down(info); | |
| 524 | + dev_err(&pdev->dev, "Couldn't register the device.\n"); | |
| 525 | + goto error_iio_device_register; | |
| 526 | + } | |
| 527 | + | |
| 528 | + return 0; | |
| 529 | + | |
| 530 | +error_iio_device_register: | |
| 531 | + clk_disable_unprepare(info->clk); | |
| 532 | +error_adc_clk_enable: | |
| 533 | + regulator_disable(info->vref); | |
| 534 | + | |
| 535 | + return ret; | |
| 536 | +} | |
| 537 | + | |
| 538 | +static int imx7d_adc_remove(struct platform_device *pdev) | |
| 539 | +{ | |
| 540 | + struct iio_dev *indio_dev = platform_get_drvdata(pdev); | |
| 541 | + struct imx7d_adc *info = iio_priv(indio_dev); | |
| 542 | + | |
| 543 | + iio_device_unregister(indio_dev); | |
| 544 | + | |
| 545 | + imx7d_adc_power_down(info); | |
| 546 | + | |
| 547 | + clk_disable_unprepare(info->clk); | |
| 548 | + regulator_disable(info->vref); | |
| 549 | + | |
| 550 | + return 0; | |
| 551 | +} | |
| 552 | + | |
| 553 | +static int __maybe_unused imx7d_adc_suspend(struct device *dev) | |
| 554 | +{ | |
| 555 | + struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
| 556 | + struct imx7d_adc *info = iio_priv(indio_dev); | |
| 557 | + | |
| 558 | + imx7d_adc_power_down(info); | |
| 559 | + | |
| 560 | + clk_disable_unprepare(info->clk); | |
| 561 | + regulator_disable(info->vref); | |
| 562 | + | |
| 563 | + return 0; | |
| 564 | +} | |
| 565 | + | |
| 566 | +static int __maybe_unused imx7d_adc_resume(struct device *dev) | |
| 567 | +{ | |
| 568 | + struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
| 569 | + struct imx7d_adc *info = iio_priv(indio_dev); | |
| 570 | + int ret; | |
| 571 | + | |
| 572 | + ret = regulator_enable(info->vref); | |
| 573 | + if (ret) { | |
| 574 | + dev_err(info->dev, | |
| 575 | + "Can't enable adc reference top voltage, err = %d\n", | |
| 576 | + ret); | |
| 577 | + return ret; | |
| 578 | + } | |
| 579 | + | |
| 580 | + ret = clk_prepare_enable(info->clk); | |
| 581 | + if (ret) { | |
| 582 | + dev_err(info->dev, | |
| 583 | + "Could not prepare or enable clock.\n"); | |
| 584 | + regulator_disable(info->vref); | |
| 585 | + return ret; | |
| 586 | + } | |
| 587 | + | |
| 588 | + imx7d_adc_hw_init(info); | |
| 589 | + | |
| 590 | + return 0; | |
| 591 | +} | |
| 592 | + | |
| 593 | +static SIMPLE_DEV_PM_OPS(imx7d_adc_pm_ops, imx7d_adc_suspend, imx7d_adc_resume); | |
| 594 | + | |
| 595 | +static struct platform_driver imx7d_adc_driver = { | |
| 596 | + .probe = imx7d_adc_probe, | |
| 597 | + .remove = imx7d_adc_remove, | |
| 598 | + .driver = { | |
| 599 | + .name = "imx7d_adc", | |
| 600 | + .of_match_table = imx7d_adc_match, | |
| 601 | + .pm = &imx7d_adc_pm_ops, | |
| 602 | + }, | |
| 603 | +}; | |
| 604 | + | |
| 605 | +module_platform_driver(imx7d_adc_driver); | |
| 606 | + | |
| 607 | +MODULE_AUTHOR("Haibo Chen <haibo.chen@freescale.com>"); | |
| 608 | +MODULE_DESCRIPTION("Freeacale IMX7D ADC driver"); | |
| 609 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,745 @@ | ||
| 1 | +/* | |
| 2 | + * INA2XX Current and Power Monitors | |
| 3 | + * | |
| 4 | + * Copyright 2015 Baylibre SAS. | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License version 2 as | |
| 8 | + * published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * Based on linux/drivers/iio/adc/ad7291.c | |
| 11 | + * Copyright 2010-2011 Analog Devices Inc. | |
| 12 | + * | |
| 13 | + * Based on linux/drivers/hwmon/ina2xx.c | |
| 14 | + * Copyright 2012 Lothar Felten <l-felten@ti.com> | |
| 15 | + * | |
| 16 | + * Licensed under the GPL-2 or later. | |
| 17 | + * | |
| 18 | + * IIO driver for INA219-220-226-230-231 | |
| 19 | + * | |
| 20 | + * Configurable 7-bit I2C slave address from 0x40 to 0x4F | |
| 21 | + */ | |
| 22 | +#include <linux/module.h> | |
| 23 | +#include <linux/kthread.h> | |
| 24 | +#include <linux/delay.h> | |
| 25 | +#include <linux/iio/kfifo_buf.h> | |
| 26 | +#include <linux/iio/sysfs.h> | |
| 27 | +#include <linux/i2c.h> | |
| 28 | +#include <linux/regmap.h> | |
| 29 | +#include <linux/platform_data/ina2xx.h> | |
| 30 | + | |
| 31 | +#include <linux/util_macros.h> | |
| 32 | + | |
| 33 | +/* INA2XX registers definition */ | |
| 34 | +#define INA2XX_CONFIG 0x00 | |
| 35 | +#define INA2XX_SHUNT_VOLTAGE 0x01 /* readonly */ | |
| 36 | +#define INA2XX_BUS_VOLTAGE 0x02 /* readonly */ | |
| 37 | +#define INA2XX_POWER 0x03 /* readonly */ | |
| 38 | +#define INA2XX_CURRENT 0x04 /* readonly */ | |
| 39 | +#define INA2XX_CALIBRATION 0x05 | |
| 40 | + | |
| 41 | +#define INA226_ALERT_MASK 0x06 | |
| 42 | +#define INA266_CVRF BIT(3) | |
| 43 | + | |
| 44 | +#define INA2XX_MAX_REGISTERS 8 | |
| 45 | + | |
| 46 | +/* settings - depend on use case */ | |
| 47 | +#define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */ | |
| 48 | +#define INA226_CONFIG_DEFAULT 0x4327 | |
| 49 | +#define INA226_DEFAULT_AVG 4 | |
| 50 | +#define INA226_DEFAULT_IT 1110 | |
| 51 | + | |
| 52 | +#define INA2XX_RSHUNT_DEFAULT 10000 | |
| 53 | + | |
| 54 | +/* | |
| 55 | + * bit mask for reading the averaging setting in the configuration register | |
| 56 | + * FIXME: use regmap_fields. | |
| 57 | + */ | |
| 58 | +#define INA2XX_MODE_MASK GENMASK(3, 0) | |
| 59 | + | |
| 60 | +#define INA226_AVG_MASK GENMASK(11, 9) | |
| 61 | +#define INA226_SHIFT_AVG(val) ((val) << 9) | |
| 62 | + | |
| 63 | +/* Integration time for VBus */ | |
| 64 | +#define INA226_ITB_MASK GENMASK(8, 6) | |
| 65 | +#define INA226_SHIFT_ITB(val) ((val) << 6) | |
| 66 | + | |
| 67 | +/* Integration time for VShunt */ | |
| 68 | +#define INA226_ITS_MASK GENMASK(5, 3) | |
| 69 | +#define INA226_SHIFT_ITS(val) ((val) << 3) | |
| 70 | + | |
| 71 | +/* Cosmetic macro giving the sampling period for a full P=UxI cycle */ | |
| 72 | +#define SAMPLING_PERIOD(c) ((c->int_time_vbus + c->int_time_vshunt) \ | |
| 73 | + * c->avg) | |
| 74 | + | |
| 75 | +static bool ina2xx_is_writeable_reg(struct device *dev, unsigned int reg) | |
| 76 | +{ | |
| 77 | + return (reg == INA2XX_CONFIG) || (reg > INA2XX_CURRENT); | |
| 78 | +} | |
| 79 | + | |
| 80 | +static bool ina2xx_is_volatile_reg(struct device *dev, unsigned int reg) | |
| 81 | +{ | |
| 82 | + return (reg != INA2XX_CONFIG); | |
| 83 | +} | |
| 84 | + | |
| 85 | +static inline bool is_signed_reg(unsigned int reg) | |
| 86 | +{ | |
| 87 | + return (reg == INA2XX_SHUNT_VOLTAGE) || (reg == INA2XX_CURRENT); | |
| 88 | +} | |
| 89 | + | |
| 90 | +static const struct regmap_config ina2xx_regmap_config = { | |
| 91 | + .reg_bits = 8, | |
| 92 | + .val_bits = 16, | |
| 93 | + .max_register = INA2XX_MAX_REGISTERS, | |
| 94 | + .writeable_reg = ina2xx_is_writeable_reg, | |
| 95 | + .volatile_reg = ina2xx_is_volatile_reg, | |
| 96 | +}; | |
| 97 | + | |
| 98 | +enum ina2xx_ids { ina219, ina226 }; | |
| 99 | + | |
| 100 | +struct ina2xx_config { | |
| 101 | + u16 config_default; | |
| 102 | + int calibration_factor; | |
| 103 | + int shunt_div; | |
| 104 | + int bus_voltage_shift; | |
| 105 | + int bus_voltage_lsb; /* uV */ | |
| 106 | + int power_lsb; /* uW */ | |
| 107 | +}; | |
| 108 | + | |
| 109 | +struct ina2xx_chip_info { | |
| 110 | + struct regmap *regmap; | |
| 111 | + struct task_struct *task; | |
| 112 | + const struct ina2xx_config *config; | |
| 113 | + struct mutex state_lock; | |
| 114 | + unsigned int shunt_resistor; | |
| 115 | + int avg; | |
| 116 | + s64 prev_ns; /* track buffer capture time, check for underruns*/ | |
| 117 | + int int_time_vbus; /* Bus voltage integration time uS */ | |
| 118 | + int int_time_vshunt; /* Shunt voltage integration time uS */ | |
| 119 | + bool allow_async_readout; | |
| 120 | +}; | |
| 121 | + | |
| 122 | +static const struct ina2xx_config ina2xx_config[] = { | |
| 123 | + [ina219] = { | |
| 124 | + .config_default = INA219_CONFIG_DEFAULT, | |
| 125 | + .calibration_factor = 40960000, | |
| 126 | + .shunt_div = 100, | |
| 127 | + .bus_voltage_shift = 3, | |
| 128 | + .bus_voltage_lsb = 4000, | |
| 129 | + .power_lsb = 20000, | |
| 130 | + }, | |
| 131 | + [ina226] = { | |
| 132 | + .config_default = INA226_CONFIG_DEFAULT, | |
| 133 | + .calibration_factor = 5120000, | |
| 134 | + .shunt_div = 400, | |
| 135 | + .bus_voltage_shift = 0, | |
| 136 | + .bus_voltage_lsb = 1250, | |
| 137 | + .power_lsb = 25000, | |
| 138 | + }, | |
| 139 | +}; | |
| 140 | + | |
| 141 | +static int ina2xx_read_raw(struct iio_dev *indio_dev, | |
| 142 | + struct iio_chan_spec const *chan, | |
| 143 | + int *val, int *val2, long mask) | |
| 144 | +{ | |
| 145 | + int ret; | |
| 146 | + struct ina2xx_chip_info *chip = iio_priv(indio_dev); | |
| 147 | + unsigned int regval; | |
| 148 | + | |
| 149 | + switch (mask) { | |
| 150 | + case IIO_CHAN_INFO_RAW: | |
| 151 | + ret = regmap_read(chip->regmap, chan->address, ®val); | |
| 152 | + if (ret < 0) | |
| 153 | + return ret; | |
| 154 | + | |
| 155 | + if (is_signed_reg(chan->address)) | |
| 156 | + *val = (s16) regval; | |
| 157 | + else | |
| 158 | + *val = regval; | |
| 159 | + | |
| 160 | + return IIO_VAL_INT; | |
| 161 | + | |
| 162 | + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | |
| 163 | + *val = chip->avg; | |
| 164 | + return IIO_VAL_INT; | |
| 165 | + | |
| 166 | + case IIO_CHAN_INFO_INT_TIME: | |
| 167 | + *val = 0; | |
| 168 | + if (chan->address == INA2XX_SHUNT_VOLTAGE) | |
| 169 | + *val2 = chip->int_time_vshunt; | |
| 170 | + else | |
| 171 | + *val2 = chip->int_time_vbus; | |
| 172 | + | |
| 173 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 174 | + | |
| 175 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 176 | + /* | |
| 177 | + * Sample freq is read only, it is a consequence of | |
| 178 | + * 1/AVG*(CT_bus+CT_shunt). | |
| 179 | + */ | |
| 180 | + *val = DIV_ROUND_CLOSEST(1000000, SAMPLING_PERIOD(chip)); | |
| 181 | + | |
| 182 | + return IIO_VAL_INT; | |
| 183 | + | |
| 184 | + case IIO_CHAN_INFO_SCALE: | |
| 185 | + switch (chan->address) { | |
| 186 | + case INA2XX_SHUNT_VOLTAGE: | |
| 187 | + /* processed (mV) = raw*1000/shunt_div */ | |
| 188 | + *val2 = chip->config->shunt_div; | |
| 189 | + *val = 1000; | |
| 190 | + return IIO_VAL_FRACTIONAL; | |
| 191 | + | |
| 192 | + case INA2XX_BUS_VOLTAGE: | |
| 193 | + /* processed (mV) = raw*lsb (uV) / (1000 << shift) */ | |
| 194 | + *val = chip->config->bus_voltage_lsb; | |
| 195 | + *val2 = 1000 << chip->config->bus_voltage_shift; | |
| 196 | + return IIO_VAL_FRACTIONAL; | |
| 197 | + | |
| 198 | + case INA2XX_POWER: | |
| 199 | + /* processed (mW) = raw*lsb (uW) / 1000 */ | |
| 200 | + *val = chip->config->power_lsb; | |
| 201 | + *val2 = 1000; | |
| 202 | + return IIO_VAL_FRACTIONAL; | |
| 203 | + | |
| 204 | + case INA2XX_CURRENT: | |
| 205 | + /* processed (mA) = raw (mA) */ | |
| 206 | + *val = 1; | |
| 207 | + return IIO_VAL_INT; | |
| 208 | + } | |
| 209 | + } | |
| 210 | + | |
| 211 | + return -EINVAL; | |
| 212 | +} | |
| 213 | + | |
| 214 | +/* | |
| 215 | + * Available averaging rates for ina226. The indices correspond with | |
| 216 | + * the bit values expected by the chip (according to the ina226 datasheet, | |
| 217 | + * table 3 AVG bit settings, found at | |
| 218 | + * http://www.ti.com/lit/ds/symlink/ina226.pdf. | |
| 219 | + */ | |
| 220 | +static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 }; | |
| 221 | + | |
| 222 | +static int ina226_set_average(struct ina2xx_chip_info *chip, unsigned int val, | |
| 223 | + unsigned int *config) | |
| 224 | +{ | |
| 225 | + int bits; | |
| 226 | + | |
| 227 | + if (val > 1024 || val < 1) | |
| 228 | + return -EINVAL; | |
| 229 | + | |
| 230 | + bits = find_closest(val, ina226_avg_tab, | |
| 231 | + ARRAY_SIZE(ina226_avg_tab)); | |
| 232 | + | |
| 233 | + chip->avg = ina226_avg_tab[bits]; | |
| 234 | + | |
| 235 | + *config &= ~INA226_AVG_MASK; | |
| 236 | + *config |= INA226_SHIFT_AVG(bits) & INA226_AVG_MASK; | |
| 237 | + | |
| 238 | + return 0; | |
| 239 | +} | |
| 240 | + | |
| 241 | +/* Conversion times in uS */ | |
| 242 | +static const int ina226_conv_time_tab[] = { 140, 204, 332, 588, 1100, | |
| 243 | + 2116, 4156, 8244 }; | |
| 244 | + | |
| 245 | +static int ina226_set_int_time_vbus(struct ina2xx_chip_info *chip, | |
| 246 | + unsigned int val_us, unsigned int *config) | |
| 247 | +{ | |
| 248 | + int bits; | |
| 249 | + | |
| 250 | + if (val_us > 8244 || val_us < 140) | |
| 251 | + return -EINVAL; | |
| 252 | + | |
| 253 | + bits = find_closest(val_us, ina226_conv_time_tab, | |
| 254 | + ARRAY_SIZE(ina226_conv_time_tab)); | |
| 255 | + | |
| 256 | + chip->int_time_vbus = ina226_conv_time_tab[bits]; | |
| 257 | + | |
| 258 | + *config &= ~INA226_ITB_MASK; | |
| 259 | + *config |= INA226_SHIFT_ITB(bits) & INA226_ITB_MASK; | |
| 260 | + | |
| 261 | + return 0; | |
| 262 | +} | |
| 263 | + | |
| 264 | +static int ina226_set_int_time_vshunt(struct ina2xx_chip_info *chip, | |
| 265 | + unsigned int val_us, unsigned int *config) | |
| 266 | +{ | |
| 267 | + int bits; | |
| 268 | + | |
| 269 | + if (val_us > 8244 || val_us < 140) | |
| 270 | + return -EINVAL; | |
| 271 | + | |
| 272 | + bits = find_closest(val_us, ina226_conv_time_tab, | |
| 273 | + ARRAY_SIZE(ina226_conv_time_tab)); | |
| 274 | + | |
| 275 | + chip->int_time_vshunt = ina226_conv_time_tab[bits]; | |
| 276 | + | |
| 277 | + *config &= ~INA226_ITS_MASK; | |
| 278 | + *config |= INA226_SHIFT_ITS(bits) & INA226_ITS_MASK; | |
| 279 | + | |
| 280 | + return 0; | |
| 281 | +} | |
| 282 | + | |
| 283 | +static int ina2xx_write_raw(struct iio_dev *indio_dev, | |
| 284 | + struct iio_chan_spec const *chan, | |
| 285 | + int val, int val2, long mask) | |
| 286 | +{ | |
| 287 | + struct ina2xx_chip_info *chip = iio_priv(indio_dev); | |
| 288 | + int ret; | |
| 289 | + unsigned int config, tmp; | |
| 290 | + | |
| 291 | + if (iio_buffer_enabled(indio_dev)) | |
| 292 | + return -EBUSY; | |
| 293 | + | |
| 294 | + mutex_lock(&chip->state_lock); | |
| 295 | + | |
| 296 | + ret = regmap_read(chip->regmap, INA2XX_CONFIG, &config); | |
| 297 | + if (ret < 0) | |
| 298 | + goto _err; | |
| 299 | + | |
| 300 | + tmp = config; | |
| 301 | + | |
| 302 | + switch (mask) { | |
| 303 | + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | |
| 304 | + ret = ina226_set_average(chip, val, &tmp); | |
| 305 | + break; | |
| 306 | + | |
| 307 | + case IIO_CHAN_INFO_INT_TIME: | |
| 308 | + if (chan->address == INA2XX_SHUNT_VOLTAGE) | |
| 309 | + ret = ina226_set_int_time_vshunt(chip, val2, &tmp); | |
| 310 | + else | |
| 311 | + ret = ina226_set_int_time_vbus(chip, val2, &tmp); | |
| 312 | + break; | |
| 313 | + default: | |
| 314 | + ret = -EINVAL; | |
| 315 | + } | |
| 316 | + | |
| 317 | + if (!ret && (tmp != config)) | |
| 318 | + ret = regmap_write(chip->regmap, INA2XX_CONFIG, tmp); | |
| 319 | +_err: | |
| 320 | + mutex_unlock(&chip->state_lock); | |
| 321 | + | |
| 322 | + return ret; | |
| 323 | +} | |
| 324 | + | |
| 325 | + | |
| 326 | +static ssize_t ina2xx_allow_async_readout_show(struct device *dev, | |
| 327 | + struct device_attribute *attr, | |
| 328 | + char *buf) | |
| 329 | +{ | |
| 330 | + struct ina2xx_chip_info *chip = iio_priv(dev_to_iio_dev(dev)); | |
| 331 | + | |
| 332 | + return sprintf(buf, "%d\n", chip->allow_async_readout); | |
| 333 | +} | |
| 334 | + | |
| 335 | +static ssize_t ina2xx_allow_async_readout_store(struct device *dev, | |
| 336 | + struct device_attribute *attr, | |
| 337 | + const char *buf, size_t len) | |
| 338 | +{ | |
| 339 | + struct ina2xx_chip_info *chip = iio_priv(dev_to_iio_dev(dev)); | |
| 340 | + bool val; | |
| 341 | + int ret; | |
| 342 | + | |
| 343 | + ret = strtobool((const char *) buf, &val); | |
| 344 | + if (ret) | |
| 345 | + return ret; | |
| 346 | + | |
| 347 | + chip->allow_async_readout = val; | |
| 348 | + | |
| 349 | + return len; | |
| 350 | +} | |
| 351 | + | |
| 352 | +static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val) | |
| 353 | +{ | |
| 354 | + if (val <= 0 || val > chip->config->calibration_factor) | |
| 355 | + return -EINVAL; | |
| 356 | + | |
| 357 | + chip->shunt_resistor = val; | |
| 358 | + return 0; | |
| 359 | +} | |
| 360 | + | |
| 361 | +static ssize_t ina2xx_shunt_resistor_show(struct device *dev, | |
| 362 | + struct device_attribute *attr, | |
| 363 | + char *buf) | |
| 364 | +{ | |
| 365 | + struct ina2xx_chip_info *chip = iio_priv(dev_to_iio_dev(dev)); | |
| 366 | + | |
| 367 | + return sprintf(buf, "%d\n", chip->shunt_resistor); | |
| 368 | +} | |
| 369 | + | |
| 370 | +static ssize_t ina2xx_shunt_resistor_store(struct device *dev, | |
| 371 | + struct device_attribute *attr, | |
| 372 | + const char *buf, size_t len) | |
| 373 | +{ | |
| 374 | + struct ina2xx_chip_info *chip = iio_priv(dev_to_iio_dev(dev)); | |
| 375 | + unsigned long val; | |
| 376 | + int ret; | |
| 377 | + | |
| 378 | + ret = kstrtoul((const char *) buf, 10, &val); | |
| 379 | + if (ret) | |
| 380 | + return ret; | |
| 381 | + | |
| 382 | + ret = set_shunt_resistor(chip, val); | |
| 383 | + if (ret) | |
| 384 | + return ret; | |
| 385 | + | |
| 386 | + return len; | |
| 387 | +} | |
| 388 | + | |
| 389 | +#define INA2XX_CHAN(_type, _index, _address) { \ | |
| 390 | + .type = (_type), \ | |
| 391 | + .address = (_address), \ | |
| 392 | + .indexed = 1, \ | |
| 393 | + .channel = (_index), \ | |
| 394 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ | |
| 395 | + | BIT(IIO_CHAN_INFO_SCALE), \ | |
| 396 | + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | |
| 397 | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ | |
| 398 | + .scan_index = (_index), \ | |
| 399 | + .scan_type = { \ | |
| 400 | + .sign = 'u', \ | |
| 401 | + .realbits = 16, \ | |
| 402 | + .storagebits = 16, \ | |
| 403 | + .endianness = IIO_CPU, \ | |
| 404 | + } \ | |
| 405 | +} | |
| 406 | + | |
| 407 | +/* | |
| 408 | + * Sampling Freq is a consequence of the integration times of | |
| 409 | + * the Voltage channels. | |
| 410 | + */ | |
| 411 | +#define INA2XX_CHAN_VOLTAGE(_index, _address) { \ | |
| 412 | + .type = IIO_VOLTAGE, \ | |
| 413 | + .address = (_address), \ | |
| 414 | + .indexed = 1, \ | |
| 415 | + .channel = (_index), \ | |
| 416 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
| 417 | + BIT(IIO_CHAN_INFO_SCALE) | \ | |
| 418 | + BIT(IIO_CHAN_INFO_INT_TIME), \ | |
| 419 | + .scan_index = (_index), \ | |
| 420 | + .scan_type = { \ | |
| 421 | + .sign = 'u', \ | |
| 422 | + .realbits = 16, \ | |
| 423 | + .storagebits = 16, \ | |
| 424 | + .endianness = IIO_LE, \ | |
| 425 | + } \ | |
| 426 | +} | |
| 427 | + | |
| 428 | +static const struct iio_chan_spec ina2xx_channels[] = { | |
| 429 | + INA2XX_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), | |
| 430 | + INA2XX_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), | |
| 431 | + INA2XX_CHAN(IIO_POWER, 2, INA2XX_POWER), | |
| 432 | + INA2XX_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT), | |
| 433 | + IIO_CHAN_SOFT_TIMESTAMP(4), | |
| 434 | +}; | |
| 435 | + | |
| 436 | +static int ina2xx_work_buffer(struct iio_dev *indio_dev) | |
| 437 | +{ | |
| 438 | + struct ina2xx_chip_info *chip = iio_priv(indio_dev); | |
| 439 | + unsigned short data[8]; | |
| 440 | + int bit, ret, i = 0; | |
| 441 | + unsigned long buffer_us, elapsed_us; | |
| 442 | + s64 time_a, time_b; | |
| 443 | + unsigned int alert; | |
| 444 | + | |
| 445 | + time_a = iio_get_time_ns(); | |
| 446 | + | |
| 447 | + /* | |
| 448 | + * Because the timer thread and the chip conversion clock | |
| 449 | + * are asynchronous, the period difference will eventually | |
| 450 | + * result in reading V[k-1] again, or skip V[k] at time Tk. | |
| 451 | + * In order to resync the timer with the conversion process | |
| 452 | + * we check the ConVersionReadyFlag. | |
| 453 | + * On hardware that supports using the ALERT pin to toggle a | |
| 454 | + * GPIO a triggered buffer could be used instead. | |
| 455 | + * For now, we pay for that extra read of the ALERT register | |
| 456 | + */ | |
| 457 | + if (!chip->allow_async_readout) | |
| 458 | + do { | |
| 459 | + ret = regmap_read(chip->regmap, INA226_ALERT_MASK, | |
| 460 | + &alert); | |
| 461 | + if (ret < 0) | |
| 462 | + return ret; | |
| 463 | + | |
| 464 | + alert &= INA266_CVRF; | |
| 465 | + trace_printk("Conversion ready: %d\n", !!alert); | |
| 466 | + | |
| 467 | + } while (!alert); | |
| 468 | + | |
| 469 | + /* | |
| 470 | + * Single register reads: bulk_read will not work with ina226 | |
| 471 | + * as there is no auto-increment of the address register for | |
| 472 | + * data length longer than 16bits. | |
| 473 | + */ | |
| 474 | + for_each_set_bit(bit, indio_dev->active_scan_mask, | |
| 475 | + indio_dev->masklength) { | |
| 476 | + unsigned int val; | |
| 477 | + | |
| 478 | + ret = regmap_read(chip->regmap, | |
| 479 | + INA2XX_SHUNT_VOLTAGE + bit, &val); | |
| 480 | + if (ret < 0) | |
| 481 | + return ret; | |
| 482 | + | |
| 483 | + data[i++] = val; | |
| 484 | + } | |
| 485 | + | |
| 486 | + time_b = iio_get_time_ns(); | |
| 487 | + | |
| 488 | + iio_push_to_buffers_with_timestamp(indio_dev, | |
| 489 | + (unsigned int *)data, time_a); | |
| 490 | + | |
| 491 | + buffer_us = (unsigned long)(time_b - time_a) / 1000; | |
| 492 | + elapsed_us = (unsigned long)(time_a - chip->prev_ns) / 1000; | |
| 493 | + | |
| 494 | + trace_printk("uS: elapsed: %lu, buf: %lu\n", elapsed_us, buffer_us); | |
| 495 | + | |
| 496 | + chip->prev_ns = time_a; | |
| 497 | + | |
| 498 | + return buffer_us; | |
| 499 | +}; | |
| 500 | + | |
| 501 | +static int ina2xx_capture_thread(void *data) | |
| 502 | +{ | |
| 503 | + struct iio_dev *indio_dev = (struct iio_dev *)data; | |
| 504 | + struct ina2xx_chip_info *chip = iio_priv(indio_dev); | |
| 505 | + unsigned int sampling_us = SAMPLING_PERIOD(chip); | |
| 506 | + int buffer_us; | |
| 507 | + | |
| 508 | + /* | |
| 509 | + * Poll a bit faster than the chip internal Fs, in case | |
| 510 | + * we wish to sync with the conversion ready flag. | |
| 511 | + */ | |
| 512 | + if (!chip->allow_async_readout) | |
| 513 | + sampling_us -= 200; | |
| 514 | + | |
| 515 | + do { | |
| 516 | + buffer_us = ina2xx_work_buffer(indio_dev); | |
| 517 | + if (buffer_us < 0) | |
| 518 | + return buffer_us; | |
| 519 | + | |
| 520 | + if (sampling_us > buffer_us) | |
| 521 | + udelay(sampling_us - buffer_us); | |
| 522 | + | |
| 523 | + } while (!kthread_should_stop()); | |
| 524 | + | |
| 525 | + return 0; | |
| 526 | +} | |
| 527 | + | |
| 528 | +static int ina2xx_buffer_enable(struct iio_dev *indio_dev) | |
| 529 | +{ | |
| 530 | + struct ina2xx_chip_info *chip = iio_priv(indio_dev); | |
| 531 | + unsigned int sampling_us = SAMPLING_PERIOD(chip); | |
| 532 | + | |
| 533 | + trace_printk("Enabling buffer w/ scan_mask %02x, freq = %d, avg =%u\n", | |
| 534 | + (unsigned int)(*indio_dev->active_scan_mask), | |
| 535 | + 1000000/sampling_us, chip->avg); | |
| 536 | + | |
| 537 | + trace_printk("Expected work period: %u us\n", sampling_us); | |
| 538 | + trace_printk("Async readout mode: %d\n", chip->allow_async_readout); | |
| 539 | + | |
| 540 | + chip->prev_ns = iio_get_time_ns(); | |
| 541 | + | |
| 542 | + chip->task = kthread_run(ina2xx_capture_thread, (void *)indio_dev, | |
| 543 | + "%s:%d-%uus", indio_dev->name, indio_dev->id, | |
| 544 | + sampling_us); | |
| 545 | + | |
| 546 | + return PTR_ERR_OR_ZERO(chip->task); | |
| 547 | +} | |
| 548 | + | |
| 549 | +static int ina2xx_buffer_disable(struct iio_dev *indio_dev) | |
| 550 | +{ | |
| 551 | + struct ina2xx_chip_info *chip = iio_priv(indio_dev); | |
| 552 | + | |
| 553 | + if (chip->task) { | |
| 554 | + kthread_stop(chip->task); | |
| 555 | + chip->task = NULL; | |
| 556 | + } | |
| 557 | + | |
| 558 | + return 0; | |
| 559 | +} | |
| 560 | + | |
| 561 | +static const struct iio_buffer_setup_ops ina2xx_setup_ops = { | |
| 562 | + .postenable = &ina2xx_buffer_enable, | |
| 563 | + .predisable = &ina2xx_buffer_disable, | |
| 564 | +}; | |
| 565 | + | |
| 566 | +static int ina2xx_debug_reg(struct iio_dev *indio_dev, | |
| 567 | + unsigned reg, unsigned writeval, unsigned *readval) | |
| 568 | +{ | |
| 569 | + struct ina2xx_chip_info *chip = iio_priv(indio_dev); | |
| 570 | + | |
| 571 | + if (!readval) | |
| 572 | + return regmap_write(chip->regmap, reg, writeval); | |
| 573 | + | |
| 574 | + return regmap_read(chip->regmap, reg, readval); | |
| 575 | +} | |
| 576 | + | |
| 577 | +/* Possible integration times for vshunt and vbus */ | |
| 578 | +static IIO_CONST_ATTR_INT_TIME_AVAIL \ | |
| 579 | + ("0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244"); | |
| 580 | + | |
| 581 | +static IIO_DEVICE_ATTR(in_allow_async_readout, S_IRUGO | S_IWUSR, | |
| 582 | + ina2xx_allow_async_readout_show, | |
| 583 | + ina2xx_allow_async_readout_store, 0); | |
| 584 | + | |
| 585 | +static IIO_DEVICE_ATTR(in_shunt_resistor, S_IRUGO | S_IWUSR, | |
| 586 | + ina2xx_shunt_resistor_show, | |
| 587 | + ina2xx_shunt_resistor_store, 0); | |
| 588 | + | |
| 589 | +static struct attribute *ina2xx_attributes[] = { | |
| 590 | + &iio_dev_attr_in_allow_async_readout.dev_attr.attr, | |
| 591 | + &iio_const_attr_integration_time_available.dev_attr.attr, | |
| 592 | + &iio_dev_attr_in_shunt_resistor.dev_attr.attr, | |
| 593 | + NULL, | |
| 594 | +}; | |
| 595 | + | |
| 596 | +static const struct attribute_group ina2xx_attribute_group = { | |
| 597 | + .attrs = ina2xx_attributes, | |
| 598 | +}; | |
| 599 | + | |
| 600 | +static const struct iio_info ina2xx_info = { | |
| 601 | + .debugfs_reg_access = &ina2xx_debug_reg, | |
| 602 | + .read_raw = &ina2xx_read_raw, | |
| 603 | + .write_raw = &ina2xx_write_raw, | |
| 604 | + .attrs = &ina2xx_attribute_group, | |
| 605 | + .driver_module = THIS_MODULE, | |
| 606 | +}; | |
| 607 | + | |
| 608 | +/* Initialize the configuration and calibration registers. */ | |
| 609 | +static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config) | |
| 610 | +{ | |
| 611 | + u16 regval; | |
| 612 | + int ret = regmap_write(chip->regmap, INA2XX_CONFIG, config); | |
| 613 | + | |
| 614 | + if (ret < 0) | |
| 615 | + return ret; | |
| 616 | + /* | |
| 617 | + * Set current LSB to 1mA, shunt is in uOhms | |
| 618 | + * (equation 13 in datasheet). We hardcode a Current_LSB | |
| 619 | + * of 1.0 x10-6. The only remaining parameter is RShunt. | |
| 620 | + * There is no need to expose the CALIBRATION register | |
| 621 | + * to the user for now. | |
| 622 | + */ | |
| 623 | + regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor, | |
| 624 | + chip->shunt_resistor); | |
| 625 | + | |
| 626 | + return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval); | |
| 627 | +} | |
| 628 | + | |
| 629 | +static int ina2xx_probe(struct i2c_client *client, | |
| 630 | + const struct i2c_device_id *id) | |
| 631 | +{ | |
| 632 | + struct ina2xx_chip_info *chip; | |
| 633 | + struct iio_dev *indio_dev; | |
| 634 | + struct iio_buffer *buffer; | |
| 635 | + int ret; | |
| 636 | + unsigned int val; | |
| 637 | + | |
| 638 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); | |
| 639 | + if (!indio_dev) | |
| 640 | + return -ENOMEM; | |
| 641 | + | |
| 642 | + chip = iio_priv(indio_dev); | |
| 643 | + | |
| 644 | + chip->config = &ina2xx_config[id->driver_data]; | |
| 645 | + | |
| 646 | + if (of_property_read_u32(client->dev.of_node, | |
| 647 | + "shunt-resistor", &val) < 0) { | |
| 648 | + struct ina2xx_platform_data *pdata = | |
| 649 | + dev_get_platdata(&client->dev); | |
| 650 | + | |
| 651 | + if (pdata) | |
| 652 | + val = pdata->shunt_uohms; | |
| 653 | + else | |
| 654 | + val = INA2XX_RSHUNT_DEFAULT; | |
| 655 | + } | |
| 656 | + | |
| 657 | + ret = set_shunt_resistor(chip, val); | |
| 658 | + if (ret) | |
| 659 | + return ret; | |
| 660 | + | |
| 661 | + mutex_init(&chip->state_lock); | |
| 662 | + | |
| 663 | + /* This is only used for device removal purposes. */ | |
| 664 | + i2c_set_clientdata(client, indio_dev); | |
| 665 | + | |
| 666 | + indio_dev->name = id->name; | |
| 667 | + indio_dev->channels = ina2xx_channels; | |
| 668 | + indio_dev->num_channels = ARRAY_SIZE(ina2xx_channels); | |
| 669 | + | |
| 670 | + indio_dev->dev.parent = &client->dev; | |
| 671 | + indio_dev->info = &ina2xx_info; | |
| 672 | + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; | |
| 673 | + | |
| 674 | + chip->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config); | |
| 675 | + if (IS_ERR(chip->regmap)) { | |
| 676 | + dev_err(&client->dev, "failed to allocate register map\n"); | |
| 677 | + return PTR_ERR(chip->regmap); | |
| 678 | + } | |
| 679 | + | |
| 680 | + /* Patch the current config register with default. */ | |
| 681 | + val = chip->config->config_default; | |
| 682 | + | |
| 683 | + if (id->driver_data == ina226) { | |
| 684 | + ina226_set_average(chip, INA226_DEFAULT_AVG, &val); | |
| 685 | + ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val); | |
| 686 | + ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val); | |
| 687 | + } | |
| 688 | + | |
| 689 | + ret = ina2xx_init(chip, val); | |
| 690 | + if (ret < 0) { | |
| 691 | + dev_err(&client->dev, "error configuring the device: %d\n", | |
| 692 | + ret); | |
| 693 | + return -ENODEV; | |
| 694 | + } | |
| 695 | + | |
| 696 | + buffer = devm_iio_kfifo_allocate(&indio_dev->dev); | |
| 697 | + if (!buffer) | |
| 698 | + return -ENOMEM; | |
| 699 | + | |
| 700 | + indio_dev->setup_ops = &ina2xx_setup_ops; | |
| 701 | + | |
| 702 | + iio_device_attach_buffer(indio_dev, buffer); | |
| 703 | + | |
| 704 | + return iio_device_register(indio_dev); | |
| 705 | +} | |
| 706 | + | |
| 707 | + | |
| 708 | +static int ina2xx_remove(struct i2c_client *client) | |
| 709 | +{ | |
| 710 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 711 | + struct ina2xx_chip_info *chip = iio_priv(indio_dev); | |
| 712 | + | |
| 713 | + iio_device_unregister(indio_dev); | |
| 714 | + | |
| 715 | + /* Powerdown */ | |
| 716 | + return regmap_update_bits(chip->regmap, INA2XX_CONFIG, | |
| 717 | + INA2XX_MODE_MASK, 0); | |
| 718 | +} | |
| 719 | + | |
| 720 | + | |
| 721 | +static const struct i2c_device_id ina2xx_id[] = { | |
| 722 | + {"ina219", ina219}, | |
| 723 | + {"ina220", ina219}, | |
| 724 | + {"ina226", ina226}, | |
| 725 | + {"ina230", ina226}, | |
| 726 | + {"ina231", ina226}, | |
| 727 | + {} | |
| 728 | +}; | |
| 729 | + | |
| 730 | +MODULE_DEVICE_TABLE(i2c, ina2xx_id); | |
| 731 | + | |
| 732 | +static struct i2c_driver ina2xx_driver = { | |
| 733 | + .driver = { | |
| 734 | + .name = KBUILD_MODNAME, | |
| 735 | + }, | |
| 736 | + .probe = ina2xx_probe, | |
| 737 | + .remove = ina2xx_remove, | |
| 738 | + .id_table = ina2xx_id, | |
| 739 | +}; | |
| 740 | + | |
| 741 | +module_i2c_driver(ina2xx_driver); | |
| 742 | + | |
| 743 | +MODULE_AUTHOR("Marc Titinger <marc.titinger@baylibre.com>"); | |
| 744 | +MODULE_DESCRIPTION("Texas Instruments INA2XX ADC driver"); | |
| 745 | +MODULE_LICENSE("GPL v2"); | |
| @@ -354,6 +354,7 @@ static int mcp320x_remove(struct spi_device *spi) · 353 unmodified lines | ||
| 354 | 354 | |
| 355 | 355 | #if defined(CONFIG_OF) |
| 356 | 356 | static const struct of_device_id mcp320x_dt_ids[] = { |
| 357 | + /* NOTE: The use of compatibles with no vendor prefix is deprecated. */ | |
| 357 | 358 | { |
| 358 | 359 | .compatible = "mcp3001", |
| 359 | 360 | .data = &mcp320x_chip_infos[mcp3001], |
| @@ -381,6 +382,33 @@ static const struct of_device_id mcp320x_dt_ids[] = { · 21 unmodified lines | ||
| 381 | 382 | }, { |
| 382 | 383 | .compatible = "mcp3301", |
| 383 | 384 | .data = &mcp320x_chip_infos[mcp3301], |
| 385 | + }, { | |
| 386 | + .compatible = "microchip,mcp3001", | |
| 387 | + .data = &mcp320x_chip_infos[mcp3001], | |
| 388 | + }, { | |
| 389 | + .compatible = "microchip,mcp3002", | |
| 390 | + .data = &mcp320x_chip_infos[mcp3002], | |
| 391 | + }, { | |
| 392 | + .compatible = "microchip,mcp3004", | |
| 393 | + .data = &mcp320x_chip_infos[mcp3004], | |
| 394 | + }, { | |
| 395 | + .compatible = "microchip,mcp3008", | |
| 396 | + .data = &mcp320x_chip_infos[mcp3008], | |
| 397 | + }, { | |
| 398 | + .compatible = "microchip,mcp3201", | |
| 399 | + .data = &mcp320x_chip_infos[mcp3201], | |
| 400 | + }, { | |
| 401 | + .compatible = "microchip,mcp3202", | |
| 402 | + .data = &mcp320x_chip_infos[mcp3202], | |
| 403 | + }, { | |
| 404 | + .compatible = "microchip,mcp3204", | |
| 405 | + .data = &mcp320x_chip_infos[mcp3204], | |
| 406 | + }, { | |
| 407 | + .compatible = "microchip,mcp3208", | |
| 408 | + .data = &mcp320x_chip_infos[mcp3208], | |
| 409 | + }, { | |
| 410 | + .compatible = "microchip,mcp3301", | |
| 411 | + .data = &mcp320x_chip_infos[mcp3301], | |
| 384 | 412 | }, { |
| 385 | 413 | } |
| 386 | 414 | }; |
| @@ -305,6 +305,10 @@ static const struct attribute_group mcp3422_attribute_group = { · 304 unmodified lines | ||
| 305 | 305 | .attrs = mcp3422_attributes, |
| 306 | 306 | }; |
| 307 | 307 | |
| 308 | +static const struct iio_chan_spec mcp3421_channels[] = { | |
| 309 | + MCP3422_CHAN(0), | |
| 310 | +}; | |
| 311 | + | |
| 308 | 312 | static const struct iio_chan_spec mcp3422_channels[] = { |
| 309 | 313 | MCP3422_CHAN(0), |
| 310 | 314 | MCP3422_CHAN(1), |
| @@ -352,6 +356,10 @@ static int mcp3422_probe(struct i2c_client *client, · 41 unmodified lines | ||
| 352 | 356 | indio_dev->info = &mcp3422_info; |
| 353 | 357 | |
| 354 | 358 | switch (adc->id) { |
| 359 | + case 1: | |
| 360 | + indio_dev->channels = mcp3421_channels; | |
| 361 | + indio_dev->num_channels = ARRAY_SIZE(mcp3421_channels); | |
| 362 | + break; | |
| 355 | 363 | case 2: |
| 356 | 364 | case 3: |
| 357 | 365 | case 6: |
| @@ -383,6 +391,7 @@ static int mcp3422_probe(struct i2c_client *client, · 25 unmodified lines | ||
| 383 | 391 | } |
| 384 | 392 | |
| 385 | 393 | static const struct i2c_device_id mcp3422_id[] = { |
| 394 | + { "mcp3421", 1 }, | |
| 386 | 395 | { "mcp3422", 2 }, |
| 387 | 396 | { "mcp3423", 3 }, |
| 388 | 397 | { "mcp3424", 4 }, |
| @@ -0,0 +1,859 @@ | ||
| 1 | +/* | |
| 2 | + * palmas-adc.c -- TI PALMAS GPADC. | |
| 3 | + * | |
| 4 | + * Copyright (c) 2013, NVIDIA Corporation. All rights reserved. | |
| 5 | + * | |
| 6 | + * Author: Pradeep Goudagunta <pgoudagunta@nvidia.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or | |
| 9 | + * modify it under the terms of the GNU General Public License as | |
| 10 | + * published by the Free Software Foundation version 2. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/module.h> | |
| 14 | +#include <linux/err.h> | |
| 15 | +#include <linux/irq.h> | |
| 16 | +#include <linux/interrupt.h> | |
| 17 | +#include <linux/platform_device.h> | |
| 18 | +#include <linux/slab.h> | |
| 19 | +#include <linux/delay.h> | |
| 20 | +#include <linux/i2c.h> | |
| 21 | +#include <linux/pm.h> | |
| 22 | +#include <linux/mfd/palmas.h> | |
| 23 | +#include <linux/completion.h> | |
| 24 | +#include <linux/of.h> | |
| 25 | +#include <linux/of_device.h> | |
| 26 | +#include <linux/iio/iio.h> | |
| 27 | +#include <linux/iio/machine.h> | |
| 28 | +#include <linux/iio/driver.h> | |
| 29 | + | |
| 30 | +#define MOD_NAME "palmas-gpadc" | |
| 31 | +#define PALMAS_ADC_CONVERSION_TIMEOUT (msecs_to_jiffies(5000)) | |
| 32 | +#define PALMAS_TO_BE_CALCULATED 0 | |
| 33 | +#define PALMAS_GPADC_TRIMINVALID -1 | |
| 34 | + | |
| 35 | +struct palmas_gpadc_info { | |
| 36 | +/* calibration codes and regs */ | |
| 37 | + int x1; /* lower ideal code */ | |
| 38 | + int x2; /* higher ideal code */ | |
| 39 | + int v1; /* expected lower volt reading */ | |
| 40 | + int v2; /* expected higher volt reading */ | |
| 41 | + u8 trim1_reg; /* register number for lower trim */ | |
| 42 | + u8 trim2_reg; /* register number for upper trim */ | |
| 43 | + int gain; /* calculated from above (after reading trim regs) */ | |
| 44 | + int offset; /* calculated from above (after reading trim regs) */ | |
| 45 | + int gain_error; /* calculated from above (after reading trim regs) */ | |
| 46 | + bool is_uncalibrated; /* if channel has calibration data */ | |
| 47 | +}; | |
| 48 | + | |
| 49 | +#define PALMAS_ADC_INFO(_chan, _x1, _x2, _v1, _v2, _t1, _t2, _is_uncalibrated) \ | |
| 50 | + [PALMAS_ADC_CH_##_chan] = { \ | |
| 51 | + .x1 = _x1, \ | |
| 52 | + .x2 = _x2, \ | |
| 53 | + .v1 = _v1, \ | |
| 54 | + .v2 = _v2, \ | |
| 55 | + .gain = PALMAS_TO_BE_CALCULATED, \ | |
| 56 | + .offset = PALMAS_TO_BE_CALCULATED, \ | |
| 57 | + .gain_error = PALMAS_TO_BE_CALCULATED, \ | |
| 58 | + .trim1_reg = PALMAS_GPADC_TRIM##_t1, \ | |
| 59 | + .trim2_reg = PALMAS_GPADC_TRIM##_t2, \ | |
| 60 | + .is_uncalibrated = _is_uncalibrated \ | |
| 61 | + } | |
| 62 | + | |
| 63 | +static struct palmas_gpadc_info palmas_gpadc_info[] = { | |
| 64 | + PALMAS_ADC_INFO(IN0, 2064, 3112, 630, 950, 1, 2, false), | |
| 65 | + PALMAS_ADC_INFO(IN1, 2064, 3112, 630, 950, 1, 2, false), | |
| 66 | + PALMAS_ADC_INFO(IN2, 2064, 3112, 1260, 1900, 3, 4, false), | |
| 67 | + PALMAS_ADC_INFO(IN3, 2064, 3112, 630, 950, 1, 2, false), | |
| 68 | + PALMAS_ADC_INFO(IN4, 2064, 3112, 630, 950, 1, 2, false), | |
| 69 | + PALMAS_ADC_INFO(IN5, 2064, 3112, 630, 950, 1, 2, false), | |
| 70 | + PALMAS_ADC_INFO(IN6, 2064, 3112, 2520, 3800, 5, 6, false), | |
| 71 | + PALMAS_ADC_INFO(IN7, 2064, 3112, 2520, 3800, 7, 8, false), | |
| 72 | + PALMAS_ADC_INFO(IN8, 2064, 3112, 3150, 4750, 9, 10, false), | |
| 73 | + PALMAS_ADC_INFO(IN9, 2064, 3112, 5670, 8550, 11, 12, false), | |
| 74 | + PALMAS_ADC_INFO(IN10, 2064, 3112, 3465, 5225, 13, 14, false), | |
| 75 | + PALMAS_ADC_INFO(IN11, 0, 0, 0, 0, INVALID, INVALID, true), | |
| 76 | + PALMAS_ADC_INFO(IN12, 0, 0, 0, 0, INVALID, INVALID, true), | |
| 77 | + PALMAS_ADC_INFO(IN13, 0, 0, 0, 0, INVALID, INVALID, true), | |
| 78 | + PALMAS_ADC_INFO(IN14, 2064, 3112, 3645, 5225, 15, 16, false), | |
| 79 | + PALMAS_ADC_INFO(IN15, 0, 0, 0, 0, INVALID, INVALID, true), | |
| 80 | +}; | |
| 81 | + | |
| 82 | +/** | |
| 83 | + * struct palmas_gpadc - the palmas_gpadc structure | |
| 84 | + * @ch0_current: channel 0 current source setting | |
| 85 | + * 0: 0 uA | |
| 86 | + * 1: 5 uA | |
| 87 | + * 2: 15 uA | |
| 88 | + * 3: 20 uA | |
| 89 | + * @ch3_current: channel 0 current source setting | |
| 90 | + * 0: 0 uA | |
| 91 | + * 1: 10 uA | |
| 92 | + * 2: 400 uA | |
| 93 | + * 3: 800 uA | |
| 94 | + * @extended_delay: enable the gpadc extended delay mode | |
| 95 | + * @auto_conversion_period: define the auto_conversion_period | |
| 96 | + * | |
| 97 | + * This is the palmas_gpadc structure to store run-time information | |
| 98 | + * and pointers for this driver instance. | |
| 99 | + */ | |
| 100 | + | |
| 101 | +struct palmas_gpadc { | |
| 102 | + struct device *dev; | |
| 103 | + struct palmas *palmas; | |
| 104 | + u8 ch0_current; | |
| 105 | + u8 ch3_current; | |
| 106 | + bool extended_delay; | |
| 107 | + int irq; | |
| 108 | + int irq_auto_0; | |
| 109 | + int irq_auto_1; | |
| 110 | + struct palmas_gpadc_info *adc_info; | |
| 111 | + struct completion conv_completion; | |
| 112 | + struct palmas_adc_wakeup_property wakeup1_data; | |
| 113 | + struct palmas_adc_wakeup_property wakeup2_data; | |
| 114 | + bool wakeup1_enable; | |
| 115 | + bool wakeup2_enable; | |
| 116 | + int auto_conversion_period; | |
| 117 | +}; | |
| 118 | + | |
| 119 | +/* | |
| 120 | + * GPADC lock issue in AUTO mode. | |
| 121 | + * Impact: In AUTO mode, GPADC conversion can be locked after disabling AUTO | |
| 122 | + * mode feature. | |
| 123 | + * Details: | |
| 124 | + * When the AUTO mode is the only conversion mode enabled, if the AUTO | |
| 125 | + * mode feature is disabled with bit GPADC_AUTO_CTRL. AUTO_CONV1_EN = 0 | |
| 126 | + * or bit GPADC_AUTO_CTRL. AUTO_CONV0_EN = 0 during a conversion, the | |
| 127 | + * conversion mechanism can be seen as locked meaning that all following | |
| 128 | + * conversion will give 0 as a result. Bit GPADC_STATUS.GPADC_AVAILABLE | |
| 129 | + * will stay at 0 meaning that GPADC is busy. An RT conversion can unlock | |
| 130 | + * the GPADC. | |
| 131 | + * | |
| 132 | + * Workaround(s): | |
| 133 | + * To avoid the lock mechanism, the workaround to follow before any stop | |
| 134 | + * conversion request is: | |
| 135 | + * Force the GPADC state machine to be ON by using the GPADC_CTRL1. | |
| 136 | + * GPADC_FORCE bit = 1 | |
| 137 | + * Shutdown the GPADC AUTO conversion using | |
| 138 | + * GPADC_AUTO_CTRL.SHUTDOWN_CONV[01] = 0. | |
| 139 | + * After 100us, force the GPADC state machine to be OFF by using the | |
| 140 | + * GPADC_CTRL1. GPADC_FORCE bit = 0 | |
| 141 | + */ | |
| 142 | + | |
| 143 | +static int palmas_disable_auto_conversion(struct palmas_gpadc *adc) | |
| 144 | +{ | |
| 145 | + int ret; | |
| 146 | + | |
| 147 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 148 | + PALMAS_GPADC_CTRL1, | |
| 149 | + PALMAS_GPADC_CTRL1_GPADC_FORCE, | |
| 150 | + PALMAS_GPADC_CTRL1_GPADC_FORCE); | |
| 151 | + if (ret < 0) { | |
| 152 | + dev_err(adc->dev, "GPADC_CTRL1 update failed: %d\n", ret); | |
| 153 | + return ret; | |
| 154 | + } | |
| 155 | + | |
| 156 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 157 | + PALMAS_GPADC_AUTO_CTRL, | |
| 158 | + PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV1 | | |
| 159 | + PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV0, | |
| 160 | + 0); | |
| 161 | + if (ret < 0) { | |
| 162 | + dev_err(adc->dev, "AUTO_CTRL update failed: %d\n", ret); | |
| 163 | + return ret; | |
| 164 | + } | |
| 165 | + | |
| 166 | + udelay(100); | |
| 167 | + | |
| 168 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 169 | + PALMAS_GPADC_CTRL1, | |
| 170 | + PALMAS_GPADC_CTRL1_GPADC_FORCE, 0); | |
| 171 | + if (ret < 0) | |
| 172 | + dev_err(adc->dev, "GPADC_CTRL1 update failed: %d\n", ret); | |
| 173 | + | |
| 174 | + return ret; | |
| 175 | +} | |
| 176 | + | |
| 177 | +static irqreturn_t palmas_gpadc_irq(int irq, void *data) | |
| 178 | +{ | |
| 179 | + struct palmas_gpadc *adc = data; | |
| 180 | + | |
| 181 | + complete(&adc->conv_completion); | |
| 182 | + | |
| 183 | + return IRQ_HANDLED; | |
| 184 | +} | |
| 185 | + | |
| 186 | +static irqreturn_t palmas_gpadc_irq_auto(int irq, void *data) | |
| 187 | +{ | |
| 188 | + struct palmas_gpadc *adc = data; | |
| 189 | + | |
| 190 | + dev_dbg(adc->dev, "Threshold interrupt %d occurs\n", irq); | |
| 191 | + palmas_disable_auto_conversion(adc); | |
| 192 | + | |
| 193 | + return IRQ_HANDLED; | |
| 194 | +} | |
| 195 | + | |
| 196 | +static int palmas_gpadc_start_mask_interrupt(struct palmas_gpadc *adc, | |
| 197 | + bool mask) | |
| 198 | +{ | |
| 199 | + int ret; | |
| 200 | + | |
| 201 | + if (!mask) | |
| 202 | + ret = palmas_update_bits(adc->palmas, PALMAS_INTERRUPT_BASE, | |
| 203 | + PALMAS_INT3_MASK, | |
| 204 | + PALMAS_INT3_MASK_GPADC_EOC_SW, 0); | |
| 205 | + else | |
| 206 | + ret = palmas_update_bits(adc->palmas, PALMAS_INTERRUPT_BASE, | |
| 207 | + PALMAS_INT3_MASK, | |
| 208 | + PALMAS_INT3_MASK_GPADC_EOC_SW, | |
| 209 | + PALMAS_INT3_MASK_GPADC_EOC_SW); | |
| 210 | + if (ret < 0) | |
| 211 | + dev_err(adc->dev, "GPADC INT MASK update failed: %d\n", ret); | |
| 212 | + | |
| 213 | + return ret; | |
| 214 | +} | |
| 215 | + | |
| 216 | +static int palmas_gpadc_enable(struct palmas_gpadc *adc, int adc_chan, | |
| 217 | + int enable) | |
| 218 | +{ | |
| 219 | + unsigned int mask, val; | |
| 220 | + int ret; | |
| 221 | + | |
| 222 | + if (enable) { | |
| 223 | + val = (adc->extended_delay | |
| 224 | + << PALMAS_GPADC_RT_CTRL_EXTEND_DELAY_SHIFT); | |
| 225 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 226 | + PALMAS_GPADC_RT_CTRL, | |
| 227 | + PALMAS_GPADC_RT_CTRL_EXTEND_DELAY, val); | |
| 228 | + if (ret < 0) { | |
| 229 | + dev_err(adc->dev, "RT_CTRL update failed: %d\n", ret); | |
| 230 | + return ret; | |
| 231 | + } | |
| 232 | + | |
| 233 | + mask = (PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_MASK | | |
| 234 | + PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_MASK | | |
| 235 | + PALMAS_GPADC_CTRL1_GPADC_FORCE); | |
| 236 | + val = (adc->ch0_current | |
| 237 | + << PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_SHIFT); | |
| 238 | + val |= (adc->ch3_current | |
| 239 | + << PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_SHIFT); | |
| 240 | + val |= PALMAS_GPADC_CTRL1_GPADC_FORCE; | |
| 241 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 242 | + PALMAS_GPADC_CTRL1, mask, val); | |
| 243 | + if (ret < 0) { | |
| 244 | + dev_err(adc->dev, | |
| 245 | + "Failed to update current setting: %d\n", ret); | |
| 246 | + return ret; | |
| 247 | + } | |
| 248 | + | |
| 249 | + mask = (PALMAS_GPADC_SW_SELECT_SW_CONV0_SEL_MASK | | |
| 250 | + PALMAS_GPADC_SW_SELECT_SW_CONV_EN); | |
| 251 | + val = (adc_chan | PALMAS_GPADC_SW_SELECT_SW_CONV_EN); | |
| 252 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 253 | + PALMAS_GPADC_SW_SELECT, mask, val); | |
| 254 | + if (ret < 0) { | |
| 255 | + dev_err(adc->dev, "SW_SELECT update failed: %d\n", ret); | |
| 256 | + return ret; | |
| 257 | + } | |
| 258 | + } else { | |
| 259 | + ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | |
| 260 | + PALMAS_GPADC_SW_SELECT, 0); | |
| 261 | + if (ret < 0) | |
| 262 | + dev_err(adc->dev, "SW_SELECT write failed: %d\n", ret); | |
| 263 | + | |
| 264 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 265 | + PALMAS_GPADC_CTRL1, | |
| 266 | + PALMAS_GPADC_CTRL1_GPADC_FORCE, 0); | |
| 267 | + if (ret < 0) { | |
| 268 | + dev_err(adc->dev, "CTRL1 update failed: %d\n", ret); | |
| 269 | + return ret; | |
| 270 | + } | |
| 271 | + } | |
| 272 | + | |
| 273 | + return ret; | |
| 274 | +} | |
| 275 | + | |
| 276 | +static int palmas_gpadc_read_prepare(struct palmas_gpadc *adc, int adc_chan) | |
| 277 | +{ | |
| 278 | + int ret; | |
| 279 | + | |
| 280 | + ret = palmas_gpadc_enable(adc, adc_chan, true); | |
| 281 | + if (ret < 0) | |
| 282 | + return ret; | |
| 283 | + | |
| 284 | + return palmas_gpadc_start_mask_interrupt(adc, 0); | |
| 285 | +} | |
| 286 | + | |
| 287 | +static void palmas_gpadc_read_done(struct palmas_gpadc *adc, int adc_chan) | |
| 288 | +{ | |
| 289 | + palmas_gpadc_start_mask_interrupt(adc, 1); | |
| 290 | + palmas_gpadc_enable(adc, adc_chan, false); | |
| 291 | +} | |
| 292 | + | |
| 293 | +static int palmas_gpadc_calibrate(struct palmas_gpadc *adc, int adc_chan) | |
| 294 | +{ | |
| 295 | + int k; | |
| 296 | + int d1; | |
| 297 | + int d2; | |
| 298 | + int ret; | |
| 299 | + int gain; | |
| 300 | + int x1 = adc->adc_info[adc_chan].x1; | |
| 301 | + int x2 = adc->adc_info[adc_chan].x2; | |
| 302 | + int v1 = adc->adc_info[adc_chan].v1; | |
| 303 | + int v2 = adc->adc_info[adc_chan].v2; | |
| 304 | + | |
| 305 | + ret = palmas_read(adc->palmas, PALMAS_TRIM_GPADC_BASE, | |
| 306 | + adc->adc_info[adc_chan].trim1_reg, &d1); | |
| 307 | + if (ret < 0) { | |
| 308 | + dev_err(adc->dev, "TRIM read failed: %d\n", ret); | |
| 309 | + goto scrub; | |
| 310 | + } | |
| 311 | + | |
| 312 | + ret = palmas_read(adc->palmas, PALMAS_TRIM_GPADC_BASE, | |
| 313 | + adc->adc_info[adc_chan].trim2_reg, &d2); | |
| 314 | + if (ret < 0) { | |
| 315 | + dev_err(adc->dev, "TRIM read failed: %d\n", ret); | |
| 316 | + goto scrub; | |
| 317 | + } | |
| 318 | + | |
| 319 | + /* gain error calculation */ | |
| 320 | + k = (1000 + (1000 * (d2 - d1)) / (x2 - x1)); | |
| 321 | + | |
| 322 | + /* gain calculation */ | |
| 323 | + gain = ((v2 - v1) * 1000) / (x2 - x1); | |
| 324 | + | |
| 325 | + adc->adc_info[adc_chan].gain_error = k; | |
| 326 | + adc->adc_info[adc_chan].gain = gain; | |
| 327 | + /* offset Calculation */ | |
| 328 | + adc->adc_info[adc_chan].offset = (d1 * 1000) - ((k - 1000) * x1); | |
| 329 | + | |
| 330 | +scrub: | |
| 331 | + return ret; | |
| 332 | +} | |
| 333 | + | |
| 334 | +static int palmas_gpadc_start_conversion(struct palmas_gpadc *adc, int adc_chan) | |
| 335 | +{ | |
| 336 | + unsigned int val; | |
| 337 | + int ret; | |
| 338 | + | |
| 339 | + init_completion(&adc->conv_completion); | |
| 340 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 341 | + PALMAS_GPADC_SW_SELECT, | |
| 342 | + PALMAS_GPADC_SW_SELECT_SW_START_CONV0, | |
| 343 | + PALMAS_GPADC_SW_SELECT_SW_START_CONV0); | |
| 344 | + if (ret < 0) { | |
| 345 | + dev_err(adc->dev, "SELECT_SW_START write failed: %d\n", ret); | |
| 346 | + return ret; | |
| 347 | + } | |
| 348 | + | |
| 349 | + ret = wait_for_completion_timeout(&adc->conv_completion, | |
| 350 | + PALMAS_ADC_CONVERSION_TIMEOUT); | |
| 351 | + if (ret == 0) { | |
| 352 | + dev_err(adc->dev, "conversion not completed\n"); | |
| 353 | + return -ETIMEDOUT; | |
| 354 | + } | |
| 355 | + | |
| 356 | + ret = palmas_bulk_read(adc->palmas, PALMAS_GPADC_BASE, | |
| 357 | + PALMAS_GPADC_SW_CONV0_LSB, &val, 2); | |
| 358 | + if (ret < 0) { | |
| 359 | + dev_err(adc->dev, "SW_CONV0_LSB read failed: %d\n", ret); | |
| 360 | + return ret; | |
| 361 | + } | |
| 362 | + | |
| 363 | + ret = val & 0xFFF; | |
| 364 | + | |
| 365 | + return ret; | |
| 366 | +} | |
| 367 | + | |
| 368 | +static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc, | |
| 369 | + int adc_chan, int val) | |
| 370 | +{ | |
| 371 | + if (!adc->adc_info[adc_chan].is_uncalibrated) | |
| 372 | + val = (val*1000 - adc->adc_info[adc_chan].offset) / | |
| 373 | + adc->adc_info[adc_chan].gain_error; | |
| 374 | + | |
| 375 | + if (val < 0) { | |
| 376 | + dev_err(adc->dev, "Mismatch with calibration\n"); | |
| 377 | + return 0; | |
| 378 | + } | |
| 379 | + | |
| 380 | + val = (val * adc->adc_info[adc_chan].gain) / 1000; | |
| 381 | + | |
| 382 | + return val; | |
| 383 | +} | |
| 384 | + | |
| 385 | +static int palmas_gpadc_read_raw(struct iio_dev *indio_dev, | |
| 386 | + struct iio_chan_spec const *chan, int *val, int *val2, long mask) | |
| 387 | +{ | |
| 388 | + struct palmas_gpadc *adc = iio_priv(indio_dev); | |
| 389 | + int adc_chan = chan->channel; | |
| 390 | + int ret = 0; | |
| 391 | + | |
| 392 | + if (adc_chan > PALMAS_ADC_CH_MAX) | |
| 393 | + return -EINVAL; | |
| 394 | + | |
| 395 | + mutex_lock(&indio_dev->mlock); | |
| 396 | + | |
| 397 | + switch (mask) { | |
| 398 | + case IIO_CHAN_INFO_RAW: | |
| 399 | + case IIO_CHAN_INFO_PROCESSED: | |
| 400 | + ret = palmas_gpadc_read_prepare(adc, adc_chan); | |
| 401 | + if (ret < 0) | |
| 402 | + goto out; | |
| 403 | + | |
| 404 | + ret = palmas_gpadc_start_conversion(adc, adc_chan); | |
| 405 | + if (ret < 0) { | |
| 406 | + dev_err(adc->dev, | |
| 407 | + "ADC start conversion failed\n"); | |
| 408 | + goto out; | |
| 409 | + } | |
| 410 | + | |
| 411 | + if (mask == IIO_CHAN_INFO_PROCESSED) | |
| 412 | + ret = palmas_gpadc_get_calibrated_code( | |
| 413 | + adc, adc_chan, ret); | |
| 414 | + | |
| 415 | + *val = ret; | |
| 416 | + | |
| 417 | + ret = IIO_VAL_INT; | |
| 418 | + goto out; | |
| 419 | + } | |
| 420 | + | |
| 421 | + mutex_unlock(&indio_dev->mlock); | |
| 422 | + return ret; | |
| 423 | + | |
| 424 | +out: | |
| 425 | + palmas_gpadc_read_done(adc, adc_chan); | |
| 426 | + mutex_unlock(&indio_dev->mlock); | |
| 427 | + | |
| 428 | + return ret; | |
| 429 | +} | |
| 430 | + | |
| 431 | +static const struct iio_info palmas_gpadc_iio_info = { | |
| 432 | + .read_raw = palmas_gpadc_read_raw, | |
| 433 | + .driver_module = THIS_MODULE, | |
| 434 | +}; | |
| 435 | + | |
| 436 | +#define PALMAS_ADC_CHAN_IIO(chan, _type, chan_info) \ | |
| 437 | +{ \ | |
| 438 | + .datasheet_name = PALMAS_DATASHEET_NAME(chan), \ | |
| 439 | + .type = _type, \ | |
| 440 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
| 441 | + BIT(chan_info), \ | |
| 442 | + .indexed = 1, \ | |
| 443 | + .channel = PALMAS_ADC_CH_##chan, \ | |
| 444 | +} | |
| 445 | + | |
| 446 | +static const struct iio_chan_spec palmas_gpadc_iio_channel[] = { | |
| 447 | + PALMAS_ADC_CHAN_IIO(IN0, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 448 | + PALMAS_ADC_CHAN_IIO(IN1, IIO_TEMP, IIO_CHAN_INFO_RAW), | |
| 449 | + PALMAS_ADC_CHAN_IIO(IN2, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 450 | + PALMAS_ADC_CHAN_IIO(IN3, IIO_TEMP, IIO_CHAN_INFO_RAW), | |
| 451 | + PALMAS_ADC_CHAN_IIO(IN4, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 452 | + PALMAS_ADC_CHAN_IIO(IN5, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 453 | + PALMAS_ADC_CHAN_IIO(IN6, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 454 | + PALMAS_ADC_CHAN_IIO(IN7, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 455 | + PALMAS_ADC_CHAN_IIO(IN8, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 456 | + PALMAS_ADC_CHAN_IIO(IN9, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 457 | + PALMAS_ADC_CHAN_IIO(IN10, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 458 | + PALMAS_ADC_CHAN_IIO(IN11, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 459 | + PALMAS_ADC_CHAN_IIO(IN12, IIO_TEMP, IIO_CHAN_INFO_RAW), | |
| 460 | + PALMAS_ADC_CHAN_IIO(IN13, IIO_TEMP, IIO_CHAN_INFO_RAW), | |
| 461 | + PALMAS_ADC_CHAN_IIO(IN14, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 462 | + PALMAS_ADC_CHAN_IIO(IN15, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | |
| 463 | +}; | |
| 464 | + | |
| 465 | +static int palmas_gpadc_get_adc_dt_data(struct platform_device *pdev, | |
| 466 | + struct palmas_gpadc_platform_data **gpadc_pdata) | |
| 467 | +{ | |
| 468 | + struct device_node *np = pdev->dev.of_node; | |
| 469 | + struct palmas_gpadc_platform_data *gp_data; | |
| 470 | + int ret; | |
| 471 | + u32 pval; | |
| 472 | + | |
| 473 | + gp_data = devm_kzalloc(&pdev->dev, sizeof(*gp_data), GFP_KERNEL); | |
| 474 | + if (!gp_data) | |
| 475 | + return -ENOMEM; | |
| 476 | + | |
| 477 | + ret = of_property_read_u32(np, "ti,channel0-current-microamp", &pval); | |
| 478 | + if (!ret) | |
| 479 | + gp_data->ch0_current = pval; | |
| 480 | + | |
| 481 | + ret = of_property_read_u32(np, "ti,channel3-current-microamp", &pval); | |
| 482 | + if (!ret) | |
| 483 | + gp_data->ch3_current = pval; | |
| 484 | + | |
| 485 | + gp_data->extended_delay = of_property_read_bool(np, | |
| 486 | + "ti,enable-extended-delay"); | |
| 487 | + | |
| 488 | + *gpadc_pdata = gp_data; | |
| 489 | + | |
| 490 | + return 0; | |
| 491 | +} | |
| 492 | + | |
| 493 | +static int palmas_gpadc_probe(struct platform_device *pdev) | |
| 494 | +{ | |
| 495 | + struct palmas_gpadc *adc; | |
| 496 | + struct palmas_platform_data *pdata; | |
| 497 | + struct palmas_gpadc_platform_data *gpadc_pdata = NULL; | |
| 498 | + struct iio_dev *indio_dev; | |
| 499 | + int ret, i; | |
| 500 | + | |
| 501 | + pdata = dev_get_platdata(pdev->dev.parent); | |
| 502 | + | |
| 503 | + if (pdata && pdata->gpadc_pdata) | |
| 504 | + gpadc_pdata = pdata->gpadc_pdata; | |
| 505 | + | |
| 506 | + if (!gpadc_pdata && pdev->dev.of_node) { | |
| 507 | + ret = palmas_gpadc_get_adc_dt_data(pdev, &gpadc_pdata); | |
| 508 | + if (ret < 0) | |
| 509 | + return ret; | |
| 510 | + } | |
| 511 | + if (!gpadc_pdata) | |
| 512 | + return -EINVAL; | |
| 513 | + | |
| 514 | + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc)); | |
| 515 | + if (!indio_dev) { | |
| 516 | + dev_err(&pdev->dev, "iio_device_alloc failed\n"); | |
| 517 | + return -ENOMEM; | |
| 518 | + } | |
| 519 | + | |
| 520 | + adc = iio_priv(indio_dev); | |
| 521 | + adc->dev = &pdev->dev; | |
| 522 | + adc->palmas = dev_get_drvdata(pdev->dev.parent); | |
| 523 | + adc->adc_info = palmas_gpadc_info; | |
| 524 | + init_completion(&adc->conv_completion); | |
| 525 | + dev_set_drvdata(&pdev->dev, indio_dev); | |
| 526 | + | |
| 527 | + adc->auto_conversion_period = gpadc_pdata->auto_conversion_period_ms; | |
| 528 | + adc->irq = palmas_irq_get_virq(adc->palmas, PALMAS_GPADC_EOC_SW_IRQ); | |
| 529 | + if (adc->irq < 0) { | |
| 530 | + dev_err(adc->dev, | |
| 531 | + "get virq failed: %d\n", adc->irq); | |
| 532 | + ret = adc->irq; | |
| 533 | + goto out; | |
| 534 | + } | |
| 535 | + ret = request_threaded_irq(adc->irq, NULL, | |
| 536 | + palmas_gpadc_irq, | |
| 537 | + IRQF_ONESHOT | IRQF_EARLY_RESUME, dev_name(adc->dev), | |
| 538 | + adc); | |
| 539 | + if (ret < 0) { | |
| 540 | + dev_err(adc->dev, | |
| 541 | + "request irq %d failed: %d\n", adc->irq, ret); | |
| 542 | + goto out; | |
| 543 | + } | |
| 544 | + | |
| 545 | + if (gpadc_pdata->adc_wakeup1_data) { | |
| 546 | + memcpy(&adc->wakeup1_data, gpadc_pdata->adc_wakeup1_data, | |
| 547 | + sizeof(adc->wakeup1_data)); | |
| 548 | + adc->wakeup1_enable = true; | |
| 549 | + adc->irq_auto_0 = platform_get_irq(pdev, 1); | |
| 550 | + ret = request_threaded_irq(adc->irq_auto_0, NULL, | |
| 551 | + palmas_gpadc_irq_auto, | |
| 552 | + IRQF_ONESHOT | IRQF_EARLY_RESUME, | |
| 553 | + "palmas-adc-auto-0", adc); | |
| 554 | + if (ret < 0) { | |
| 555 | + dev_err(adc->dev, "request auto0 irq %d failed: %d\n", | |
| 556 | + adc->irq_auto_0, ret); | |
| 557 | + goto out_irq_free; | |
| 558 | + } | |
| 559 | + } | |
| 560 | + | |
| 561 | + if (gpadc_pdata->adc_wakeup2_data) { | |
| 562 | + memcpy(&adc->wakeup2_data, gpadc_pdata->adc_wakeup2_data, | |
| 563 | + sizeof(adc->wakeup2_data)); | |
| 564 | + adc->wakeup2_enable = true; | |
| 565 | + adc->irq_auto_1 = platform_get_irq(pdev, 2); | |
| 566 | + ret = request_threaded_irq(adc->irq_auto_1, NULL, | |
| 567 | + palmas_gpadc_irq_auto, | |
| 568 | + IRQF_ONESHOT | IRQF_EARLY_RESUME, | |
| 569 | + "palmas-adc-auto-1", adc); | |
| 570 | + if (ret < 0) { | |
| 571 | + dev_err(adc->dev, "request auto1 irq %d failed: %d\n", | |
| 572 | + adc->irq_auto_1, ret); | |
| 573 | + goto out_irq_auto0_free; | |
| 574 | + } | |
| 575 | + } | |
| 576 | + | |
| 577 | + /* set the current source 0 (value 0/5/15/20 uA => 0..3) */ | |
| 578 | + if (gpadc_pdata->ch0_current <= 1) | |
| 579 | + adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_0; | |
| 580 | + else if (gpadc_pdata->ch0_current <= 5) | |
| 581 | + adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_5; | |
| 582 | + else if (gpadc_pdata->ch0_current <= 15) | |
| 583 | + adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_15; | |
| 584 | + else | |
| 585 | + adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_20; | |
| 586 | + | |
| 587 | + /* set the current source 3 (value 0/10/400/800 uA => 0..3) */ | |
| 588 | + if (gpadc_pdata->ch3_current <= 1) | |
| 589 | + adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_0; | |
| 590 | + else if (gpadc_pdata->ch3_current <= 10) | |
| 591 | + adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_10; | |
| 592 | + else if (gpadc_pdata->ch3_current <= 400) | |
| 593 | + adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_400; | |
| 594 | + else | |
| 595 | + adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_800; | |
| 596 | + | |
| 597 | + adc->extended_delay = gpadc_pdata->extended_delay; | |
| 598 | + | |
| 599 | + indio_dev->name = MOD_NAME; | |
| 600 | + indio_dev->dev.parent = &pdev->dev; | |
| 601 | + indio_dev->info = &palmas_gpadc_iio_info; | |
| 602 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 603 | + indio_dev->channels = palmas_gpadc_iio_channel; | |
| 604 | + indio_dev->num_channels = ARRAY_SIZE(palmas_gpadc_iio_channel); | |
| 605 | + | |
| 606 | + ret = iio_device_register(indio_dev); | |
| 607 | + if (ret < 0) { | |
| 608 | + dev_err(adc->dev, "iio_device_register() failed: %d\n", ret); | |
| 609 | + goto out_irq_auto1_free; | |
| 610 | + } | |
| 611 | + | |
| 612 | + device_set_wakeup_capable(&pdev->dev, 1); | |
| 613 | + for (i = 0; i < PALMAS_ADC_CH_MAX; i++) { | |
| 614 | + if (!(adc->adc_info[i].is_uncalibrated)) | |
| 615 | + palmas_gpadc_calibrate(adc, i); | |
| 616 | + } | |
| 617 | + | |
| 618 | + if (adc->wakeup1_enable || adc->wakeup2_enable) | |
| 619 | + device_wakeup_enable(&pdev->dev); | |
| 620 | + | |
| 621 | + return 0; | |
| 622 | + | |
| 623 | +out_irq_auto1_free: | |
| 624 | + if (gpadc_pdata->adc_wakeup2_data) | |
| 625 | + free_irq(adc->irq_auto_1, adc); | |
| 626 | +out_irq_auto0_free: | |
| 627 | + if (gpadc_pdata->adc_wakeup1_data) | |
| 628 | + free_irq(adc->irq_auto_0, adc); | |
| 629 | +out_irq_free: | |
| 630 | + free_irq(adc->irq, adc); | |
| 631 | +out: | |
| 632 | + return ret; | |
| 633 | +} | |
| 634 | + | |
| 635 | +static int palmas_gpadc_remove(struct platform_device *pdev) | |
| 636 | +{ | |
| 637 | + struct iio_dev *indio_dev = dev_to_iio_dev(&pdev->dev); | |
| 638 | + struct palmas_gpadc *adc = iio_priv(indio_dev); | |
| 639 | + | |
| 640 | + if (adc->wakeup1_enable || adc->wakeup2_enable) | |
| 641 | + device_wakeup_disable(&pdev->dev); | |
| 642 | + iio_device_unregister(indio_dev); | |
| 643 | + free_irq(adc->irq, adc); | |
| 644 | + if (adc->wakeup1_enable) | |
| 645 | + free_irq(adc->irq_auto_0, adc); | |
| 646 | + if (adc->wakeup2_enable) | |
| 647 | + free_irq(adc->irq_auto_1, adc); | |
| 648 | + | |
| 649 | + return 0; | |
| 650 | +} | |
| 651 | + | |
| 652 | +#ifdef CONFIG_PM_SLEEP | |
| 653 | +static int palmas_adc_wakeup_configure(struct palmas_gpadc *adc) | |
| 654 | +{ | |
| 655 | + int adc_period, conv; | |
| 656 | + int i; | |
| 657 | + int ch0 = 0, ch1 = 0; | |
| 658 | + int thres; | |
| 659 | + int ret; | |
| 660 | + | |
| 661 | + adc_period = adc->auto_conversion_period; | |
| 662 | + for (i = 0; i < 16; ++i) { | |
| 663 | + if (((1000 * (1 << i)) / 32) < adc_period) | |
| 664 | + continue; | |
| 665 | + } | |
| 666 | + if (i > 0) | |
| 667 | + i--; | |
| 668 | + adc_period = i; | |
| 669 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 670 | + PALMAS_GPADC_AUTO_CTRL, | |
| 671 | + PALMAS_GPADC_AUTO_CTRL_COUNTER_CONV_MASK, | |
| 672 | + adc_period); | |
| 673 | + if (ret < 0) { | |
| 674 | + dev_err(adc->dev, "AUTO_CTRL write failed: %d\n", ret); | |
| 675 | + return ret; | |
| 676 | + } | |
| 677 | + | |
| 678 | + conv = 0; | |
| 679 | + if (adc->wakeup1_enable) { | |
| 680 | + int polarity; | |
| 681 | + | |
| 682 | + ch0 = adc->wakeup1_data.adc_channel_number; | |
| 683 | + conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN; | |
| 684 | + if (adc->wakeup1_data.adc_high_threshold > 0) { | |
| 685 | + thres = adc->wakeup1_data.adc_high_threshold; | |
| 686 | + polarity = 0; | |
| 687 | + } else { | |
| 688 | + thres = adc->wakeup1_data.adc_low_threshold; | |
| 689 | + polarity = PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL; | |
| 690 | + } | |
| 691 | + | |
| 692 | + ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | |
| 693 | + PALMAS_GPADC_THRES_CONV0_LSB, thres & 0xFF); | |
| 694 | + if (ret < 0) { | |
| 695 | + dev_err(adc->dev, | |
| 696 | + "THRES_CONV0_LSB write failed: %d\n", ret); | |
| 697 | + return ret; | |
| 698 | + } | |
| 699 | + | |
| 700 | + ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | |
| 701 | + PALMAS_GPADC_THRES_CONV0_MSB, | |
| 702 | + ((thres >> 8) & 0xF) | polarity); | |
| 703 | + if (ret < 0) { | |
| 704 | + dev_err(adc->dev, | |
| 705 | + "THRES_CONV0_MSB write failed: %d\n", ret); | |
| 706 | + return ret; | |
| 707 | + } | |
| 708 | + } | |
| 709 | + | |
| 710 | + if (adc->wakeup2_enable) { | |
| 711 | + int polarity; | |
| 712 | + | |
| 713 | + ch1 = adc->wakeup2_data.adc_channel_number; | |
| 714 | + conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN; | |
| 715 | + if (adc->wakeup2_data.adc_high_threshold > 0) { | |
| 716 | + thres = adc->wakeup2_data.adc_high_threshold; | |
| 717 | + polarity = 0; | |
| 718 | + } else { | |
| 719 | + thres = adc->wakeup2_data.adc_low_threshold; | |
| 720 | + polarity = PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL; | |
| 721 | + } | |
| 722 | + | |
| 723 | + ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | |
| 724 | + PALMAS_GPADC_THRES_CONV1_LSB, thres & 0xFF); | |
| 725 | + if (ret < 0) { | |
| 726 | + dev_err(adc->dev, | |
| 727 | + "THRES_CONV1_LSB write failed: %d\n", ret); | |
| 728 | + return ret; | |
| 729 | + } | |
| 730 | + | |
| 731 | + ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | |
| 732 | + PALMAS_GPADC_THRES_CONV1_MSB, | |
| 733 | + ((thres >> 8) & 0xF) | polarity); | |
| 734 | + if (ret < 0) { | |
| 735 | + dev_err(adc->dev, | |
| 736 | + "THRES_CONV1_MSB write failed: %d\n", ret); | |
| 737 | + return ret; | |
| 738 | + } | |
| 739 | + } | |
| 740 | + | |
| 741 | + ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | |
| 742 | + PALMAS_GPADC_AUTO_SELECT, (ch1 << 4) | ch0); | |
| 743 | + if (ret < 0) { | |
| 744 | + dev_err(adc->dev, "AUTO_SELECT write failed: %d\n", ret); | |
| 745 | + return ret; | |
| 746 | + } | |
| 747 | + | |
| 748 | + ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | |
| 749 | + PALMAS_GPADC_AUTO_CTRL, | |
| 750 | + PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN | | |
| 751 | + PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN, conv); | |
| 752 | + if (ret < 0) | |
| 753 | + dev_err(adc->dev, "AUTO_CTRL write failed: %d\n", ret); | |
| 754 | + | |
| 755 | + return ret; | |
| 756 | +} | |
| 757 | + | |
| 758 | +static int palmas_adc_wakeup_reset(struct palmas_gpadc *adc) | |
| 759 | +{ | |
| 760 | + int ret; | |
| 761 | + | |
| 762 | + ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | |
| 763 | + PALMAS_GPADC_AUTO_SELECT, 0); | |
| 764 | + if (ret < 0) { | |
| 765 | + dev_err(adc->dev, "AUTO_SELECT write failed: %d\n", ret); | |
| 766 | + return ret; | |
| 767 | + } | |
| 768 | + | |
| 769 | + ret = palmas_disable_auto_conversion(adc); | |
| 770 | + if (ret < 0) | |
| 771 | + dev_err(adc->dev, "Disable auto conversion failed: %d\n", ret); | |
| 772 | + | |
| 773 | + return ret; | |
| 774 | +} | |
| 775 | + | |
| 776 | +static int palmas_gpadc_suspend(struct device *dev) | |
| 777 | +{ | |
| 778 | + struct iio_dev *indio_dev = dev_to_iio_dev(dev); | |
| 779 | + struct palmas_gpadc *adc = iio_priv(indio_dev); | |
| 780 | + int wakeup = adc->wakeup1_enable || adc->wakeup2_enable; | |
| 781 | + int ret; | |
| 782 | + | |
| 783 | + if (!device_may_wakeup(dev) || !wakeup) | |
| 784 | + return 0; | |
| 785 | + | |
| 786 | + ret = palmas_adc_wakeup_configure(adc); | |
| 787 | + if (ret < 0) | |
| 788 | + return ret; | |
| 789 | + | |
| 790 | + if (adc->wakeup1_enable) | |
| 791 | + enable_irq_wake(adc->irq_auto_0); | |
| 792 | + | |
| 793 | + if (adc->wakeup2_enable) | |
| 794 | + enable_irq_wake(adc->irq_auto_1); | |
| 795 | + | |
| 796 | + return 0; | |
| 797 | +} | |
| 798 | + | |
| 799 | +static int palmas_gpadc_resume(struct device *dev) | |
| 800 | +{ | |
| 801 | + struct iio_dev *indio_dev = dev_to_iio_dev(dev); | |
| 802 | + struct palmas_gpadc *adc = iio_priv(indio_dev); | |
| 803 | + int wakeup = adc->wakeup1_enable || adc->wakeup2_enable; | |
| 804 | + int ret; | |
| 805 | + | |
| 806 | + if (!device_may_wakeup(dev) || !wakeup) | |
| 807 | + return 0; | |
| 808 | + | |
| 809 | + ret = palmas_adc_wakeup_reset(adc); | |
| 810 | + if (ret < 0) | |
| 811 | + return ret; | |
| 812 | + | |
| 813 | + if (adc->wakeup1_enable) | |
| 814 | + disable_irq_wake(adc->irq_auto_0); | |
| 815 | + | |
| 816 | + if (adc->wakeup2_enable) | |
| 817 | + disable_irq_wake(adc->irq_auto_1); | |
| 818 | + | |
| 819 | + return 0; | |
| 820 | +}; | |
| 821 | +#endif | |
| 822 | + | |
| 823 | +static const struct dev_pm_ops palmas_pm_ops = { | |
| 824 | + SET_SYSTEM_SLEEP_PM_OPS(palmas_gpadc_suspend, | |
| 825 | + palmas_gpadc_resume) | |
| 826 | +}; | |
| 827 | + | |
| 828 | +static const struct of_device_id of_palmas_gpadc_match_tbl[] = { | |
| 829 | + { .compatible = "ti,palmas-gpadc", }, | |
| 830 | + { /* end */ } | |
| 831 | +}; | |
| 832 | +MODULE_DEVICE_TABLE(of, of_palmas_gpadc_match_tbl); | |
| 833 | + | |
| 834 | +static struct platform_driver palmas_gpadc_driver = { | |
| 835 | + .probe = palmas_gpadc_probe, | |
| 836 | + .remove = palmas_gpadc_remove, | |
| 837 | + .driver = { | |
| 838 | + .name = MOD_NAME, | |
| 839 | + .pm = &palmas_pm_ops, | |
| 840 | + .of_match_table = of_palmas_gpadc_match_tbl, | |
| 841 | + }, | |
| 842 | +}; | |
| 843 | + | |
| 844 | +static int __init palmas_gpadc_init(void) | |
| 845 | +{ | |
| 846 | + return platform_driver_register(&palmas_gpadc_driver); | |
| 847 | +} | |
| 848 | +module_init(palmas_gpadc_init); | |
| 849 | + | |
| 850 | +static void __exit palmas_gpadc_exit(void) | |
| 851 | +{ | |
| 852 | + platform_driver_unregister(&palmas_gpadc_driver); | |
| 853 | +} | |
| 854 | +module_exit(palmas_gpadc_exit); | |
| 855 | + | |
| 856 | +MODULE_DESCRIPTION("palmas GPADC driver"); | |
| 857 | +MODULE_AUTHOR("Pradeep Goudagunta<pgoudagunta@nvidia.com>"); | |
| 858 | +MODULE_ALIAS("platform:palmas-gpadc"); | |
| 859 | +MODULE_LICENSE("GPL v2"); | |
| @@ -1,10 +1,11 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * Copyright (C) 2014 Angelo Compagnucci <angelo.compagnucci@gmail.com> |
| 3 | 3 | * |
| 4 | − * Driver for Texas Instruments' ADC128S052 and ADC122S021 ADC chip. | |
| 4 | + * Driver for Texas Instruments' ADC128S052, ADC122S021 and ADC124S021 ADC chip. | |
| 5 | 5 | * Datasheets can be found here: |
| 6 | 6 | * http://www.ti.com/lit/ds/symlink/adc128s052.pdf |
| 7 | 7 | * http://www.ti.com/lit/ds/symlink/adc122s021.pdf |
| 8 | + * http://www.ti.com/lit/ds/symlink/adc124s021.pdf | |
| 8 | 9 | * |
| 9 | 10 | * This program is free software; you can redistribute it and/or modify |
| 10 | 11 | * it under the terms of the GNU General Public License version 2 as |
| @@ -114,9 +115,17 @@ static const struct iio_chan_spec adc122s021_channels[] = { · 103 unmodified lines | ||
| 114 | 115 | ADC128_VOLTAGE_CHANNEL(1), |
| 115 | 116 | }; |
| 116 | 117 | |
| 118 | +static const struct iio_chan_spec adc124s021_channels[] = { | |
| 119 | + ADC128_VOLTAGE_CHANNEL(0), | |
| 120 | + ADC128_VOLTAGE_CHANNEL(1), | |
| 121 | + ADC128_VOLTAGE_CHANNEL(2), | |
| 122 | + ADC128_VOLTAGE_CHANNEL(3), | |
| 123 | +}; | |
| 124 | + | |
| 117 | 125 | static const struct adc128_configuration adc128_config[] = { |
| 118 | 126 | { adc128s052_channels, ARRAY_SIZE(adc128s052_channels) }, |
| 119 | 127 | { adc122s021_channels, ARRAY_SIZE(adc122s021_channels) }, |
| 128 | + { adc124s021_channels, ARRAY_SIZE(adc124s021_channels) }, | |
| 120 | 129 | }; |
| 121 | 130 | |
| 122 | 131 | static const struct iio_info adc128_info = { |
| @@ -177,6 +186,7 @@ static int adc128_remove(struct spi_device *spi) · 54 unmodified lines | ||
| 177 | 186 | static const struct of_device_id adc128_of_match[] = { |
| 178 | 187 | { .compatible = "ti,adc128s052", }, |
| 179 | 188 | { .compatible = "ti,adc122s021", }, |
| 189 | + { .compatible = "ti,adc124s021", }, | |
| 180 | 190 | { /* sentinel */ }, |
| 181 | 191 | }; |
| 182 | 192 | MODULE_DEVICE_TABLE(of, adc128_of_match); |
| @@ -184,6 +194,7 @@ MODULE_DEVICE_TABLE(of, adc128_of_match); · 1 unmodified line | ||
| 184 | 194 | static const struct spi_device_id adc128_id[] = { |
| 185 | 195 | { "adc128s052", 0}, /* index into adc128_config */ |
| 186 | 196 | { "adc122s021", 1}, |
| 197 | + { "adc124s021", 2}, | |
| 187 | 198 | { } |
| 188 | 199 | }; |
| 189 | 200 | MODULE_DEVICE_TABLE(spi, adc128_id); |
| @@ -0,0 +1,486 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2015 Prevas A/S | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify | |
| 5 | + * it under the terms of the GNU General Public License version 2 as | |
| 6 | + * published by the Free Software Foundation. | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#include <linux/device.h> | |
| 10 | +#include <linux/kernel.h> | |
| 11 | +#include <linux/slab.h> | |
| 12 | +#include <linux/sysfs.h> | |
| 13 | +#include <linux/spi/spi.h> | |
| 14 | +#include <linux/regulator/consumer.h> | |
| 15 | +#include <linux/err.h> | |
| 16 | +#include <linux/module.h> | |
| 17 | +#include <linux/of.h> | |
| 18 | + | |
| 19 | +#include <linux/iio/iio.h> | |
| 20 | +#include <linux/iio/sysfs.h> | |
| 21 | + | |
| 22 | +#define ADS8688_CMD_REG(x) (x << 8) | |
| 23 | +#define ADS8688_CMD_REG_NOOP 0x00 | |
| 24 | +#define ADS8688_CMD_REG_RST 0x85 | |
| 25 | +#define ADS8688_CMD_REG_MAN_CH(chan) (0xC0 | (4 * chan)) | |
| 26 | +#define ADS8688_CMD_DONT_CARE_BITS 16 | |
| 27 | + | |
| 28 | +#define ADS8688_PROG_REG(x) (x << 9) | |
| 29 | +#define ADS8688_PROG_REG_RANGE_CH(chan) (0x05 + chan) | |
| 30 | +#define ADS8688_PROG_WR_BIT BIT(8) | |
| 31 | +#define ADS8688_PROG_DONT_CARE_BITS 8 | |
| 32 | + | |
| 33 | +#define ADS8688_REG_PLUSMINUS25VREF 0 | |
| 34 | +#define ADS8688_REG_PLUSMINUS125VREF 1 | |
| 35 | +#define ADS8688_REG_PLUSMINUS0625VREF 2 | |
| 36 | +#define ADS8688_REG_PLUS25VREF 5 | |
| 37 | +#define ADS8688_REG_PLUS125VREF 6 | |
| 38 | + | |
| 39 | +#define ADS8688_VREF_MV 4096 | |
| 40 | +#define ADS8688_REALBITS 16 | |
| 41 | + | |
| 42 | +/* | |
| 43 | + * enum ads8688_range - ADS8688 reference voltage range | |
| 44 | + * @ADS8688_PLUSMINUS25VREF: Device is configured for input range ±2.5 * VREF | |
| 45 | + * @ADS8688_PLUSMINUS125VREF: Device is configured for input range ±1.25 * VREF | |
| 46 | + * @ADS8688_PLUSMINUS0625VREF: Device is configured for input range ±0.625 * VREF | |
| 47 | + * @ADS8688_PLUS25VREF: Device is configured for input range 0 - 2.5 * VREF | |
| 48 | + * @ADS8688_PLUS125VREF: Device is configured for input range 0 - 1.25 * VREF | |
| 49 | + */ | |
| 50 | +enum ads8688_range { | |
| 51 | + ADS8688_PLUSMINUS25VREF, | |
| 52 | + ADS8688_PLUSMINUS125VREF, | |
| 53 | + ADS8688_PLUSMINUS0625VREF, | |
| 54 | + ADS8688_PLUS25VREF, | |
| 55 | + ADS8688_PLUS125VREF, | |
| 56 | +}; | |
| 57 | + | |
| 58 | +struct ads8688_chip_info { | |
| 59 | + const struct iio_chan_spec *channels; | |
| 60 | + unsigned int num_channels; | |
| 61 | +}; | |
| 62 | + | |
| 63 | +struct ads8688_state { | |
| 64 | + struct mutex lock; | |
| 65 | + const struct ads8688_chip_info *chip_info; | |
| 66 | + struct spi_device *spi; | |
| 67 | + struct regulator *reg; | |
| 68 | + unsigned int vref_mv; | |
| 69 | + enum ads8688_range range[8]; | |
| 70 | + union { | |
| 71 | + __be32 d32; | |
| 72 | + u8 d8[4]; | |
| 73 | + } data[2] ____cacheline_aligned; | |
| 74 | +}; | |
| 75 | + | |
| 76 | +enum ads8688_id { | |
| 77 | + ID_ADS8684, | |
| 78 | + ID_ADS8688, | |
| 79 | +}; | |
| 80 | + | |
| 81 | +struct ads8688_ranges { | |
| 82 | + enum ads8688_range range; | |
| 83 | + unsigned int scale; | |
| 84 | + int offset; | |
| 85 | + u8 reg; | |
| 86 | +}; | |
| 87 | + | |
| 88 | +static const struct ads8688_ranges ads8688_range_def[5] = { | |
| 89 | + { | |
| 90 | + .range = ADS8688_PLUSMINUS25VREF, | |
| 91 | + .scale = 76295, | |
| 92 | + .offset = -(1 << (ADS8688_REALBITS - 1)), | |
| 93 | + .reg = ADS8688_REG_PLUSMINUS25VREF, | |
| 94 | + }, { | |
| 95 | + .range = ADS8688_PLUSMINUS125VREF, | |
| 96 | + .scale = 38148, | |
| 97 | + .offset = -(1 << (ADS8688_REALBITS - 1)), | |
| 98 | + .reg = ADS8688_REG_PLUSMINUS125VREF, | |
| 99 | + }, { | |
| 100 | + .range = ADS8688_PLUSMINUS0625VREF, | |
| 101 | + .scale = 19074, | |
| 102 | + .offset = -(1 << (ADS8688_REALBITS - 1)), | |
| 103 | + .reg = ADS8688_REG_PLUSMINUS0625VREF, | |
| 104 | + }, { | |
| 105 | + .range = ADS8688_PLUS25VREF, | |
| 106 | + .scale = 38148, | |
| 107 | + .offset = 0, | |
| 108 | + .reg = ADS8688_REG_PLUS25VREF, | |
| 109 | + }, { | |
| 110 | + .range = ADS8688_PLUS125VREF, | |
| 111 | + .scale = 19074, | |
| 112 | + .offset = 0, | |
| 113 | + .reg = ADS8688_REG_PLUS125VREF, | |
| 114 | + } | |
| 115 | +}; | |
| 116 | + | |
| 117 | +static ssize_t ads8688_show_scales(struct device *dev, | |
| 118 | + struct device_attribute *attr, char *buf) | |
| 119 | +{ | |
| 120 | + struct ads8688_state *st = iio_priv(dev_to_iio_dev(dev)); | |
| 121 | + | |
| 122 | + return sprintf(buf, "0.%09u 0.%09u 0.%09u\n", | |
| 123 | + ads8688_range_def[0].scale * st->vref_mv, | |
| 124 | + ads8688_range_def[1].scale * st->vref_mv, | |
| 125 | + ads8688_range_def[2].scale * st->vref_mv); | |
| 126 | +} | |
| 127 | + | |
| 128 | +static ssize_t ads8688_show_offsets(struct device *dev, | |
| 129 | + struct device_attribute *attr, char *buf) | |
| 130 | +{ | |
| 131 | + return sprintf(buf, "%d %d\n", ads8688_range_def[0].offset, | |
| 132 | + ads8688_range_def[3].offset); | |
| 133 | +} | |
| 134 | + | |
| 135 | +static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, | |
| 136 | + ads8688_show_scales, NULL, 0); | |
| 137 | +static IIO_DEVICE_ATTR(in_voltage_offset_available, S_IRUGO, | |
| 138 | + ads8688_show_offsets, NULL, 0); | |
| 139 | + | |
| 140 | +static struct attribute *ads8688_attributes[] = { | |
| 141 | + &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, | |
| 142 | + &iio_dev_attr_in_voltage_offset_available.dev_attr.attr, | |
| 143 | + NULL, | |
| 144 | +}; | |
| 145 | + | |
| 146 | +static const struct attribute_group ads8688_attribute_group = { | |
| 147 | + .attrs = ads8688_attributes, | |
| 148 | +}; | |
| 149 | + | |
| 150 | +#define ADS8688_CHAN(index) \ | |
| 151 | +{ \ | |
| 152 | + .type = IIO_VOLTAGE, \ | |
| 153 | + .indexed = 1, \ | |
| 154 | + .channel = index, \ | |
| 155 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ | |
| 156 | + | BIT(IIO_CHAN_INFO_SCALE) \ | |
| 157 | + | BIT(IIO_CHAN_INFO_OFFSET), \ | |
| 158 | +} | |
| 159 | + | |
| 160 | +static const struct iio_chan_spec ads8684_channels[] = { | |
| 161 | + ADS8688_CHAN(0), | |
| 162 | + ADS8688_CHAN(1), | |
| 163 | + ADS8688_CHAN(2), | |
| 164 | + ADS8688_CHAN(3), | |
| 165 | +}; | |
| 166 | + | |
| 167 | +static const struct iio_chan_spec ads8688_channels[] = { | |
| 168 | + ADS8688_CHAN(0), | |
| 169 | + ADS8688_CHAN(1), | |
| 170 | + ADS8688_CHAN(2), | |
| 171 | + ADS8688_CHAN(3), | |
| 172 | + ADS8688_CHAN(4), | |
| 173 | + ADS8688_CHAN(5), | |
| 174 | + ADS8688_CHAN(6), | |
| 175 | + ADS8688_CHAN(7), | |
| 176 | +}; | |
| 177 | + | |
| 178 | +static int ads8688_prog_write(struct iio_dev *indio_dev, unsigned int addr, | |
| 179 | + unsigned int val) | |
| 180 | +{ | |
| 181 | + struct ads8688_state *st = iio_priv(indio_dev); | |
| 182 | + u32 tmp; | |
| 183 | + | |
| 184 | + tmp = ADS8688_PROG_REG(addr) | ADS8688_PROG_WR_BIT | val; | |
| 185 | + tmp <<= ADS8688_PROG_DONT_CARE_BITS; | |
| 186 | + st->data[0].d32 = cpu_to_be32(tmp); | |
| 187 | + | |
| 188 | + return spi_write(st->spi, &st->data[0].d8[1], 3); | |
| 189 | +} | |
| 190 | + | |
| 191 | +static int ads8688_reset(struct iio_dev *indio_dev) | |
| 192 | +{ | |
| 193 | + struct ads8688_state *st = iio_priv(indio_dev); | |
| 194 | + u32 tmp; | |
| 195 | + | |
| 196 | + tmp = ADS8688_CMD_REG(ADS8688_CMD_REG_RST); | |
| 197 | + tmp <<= ADS8688_CMD_DONT_CARE_BITS; | |
| 198 | + st->data[0].d32 = cpu_to_be32(tmp); | |
| 199 | + | |
| 200 | + return spi_write(st->spi, &st->data[0].d8[0], 4); | |
| 201 | +} | |
| 202 | + | |
| 203 | +static int ads8688_read(struct iio_dev *indio_dev, unsigned int chan) | |
| 204 | +{ | |
| 205 | + struct ads8688_state *st = iio_priv(indio_dev); | |
| 206 | + int ret; | |
| 207 | + u32 tmp; | |
| 208 | + struct spi_transfer t[] = { | |
| 209 | + { | |
| 210 | + .tx_buf = &st->data[0].d8[0], | |
| 211 | + .len = 4, | |
| 212 | + .cs_change = 1, | |
| 213 | + }, { | |
| 214 | + .tx_buf = &st->data[1].d8[0], | |
| 215 | + .rx_buf = &st->data[1].d8[0], | |
| 216 | + .len = 4, | |
| 217 | + }, | |
| 218 | + }; | |
| 219 | + | |
| 220 | + tmp = ADS8688_CMD_REG(ADS8688_CMD_REG_MAN_CH(chan)); | |
| 221 | + tmp <<= ADS8688_CMD_DONT_CARE_BITS; | |
| 222 | + st->data[0].d32 = cpu_to_be32(tmp); | |
| 223 | + | |
| 224 | + tmp = ADS8688_CMD_REG(ADS8688_CMD_REG_NOOP); | |
| 225 | + tmp <<= ADS8688_CMD_DONT_CARE_BITS; | |
| 226 | + st->data[1].d32 = cpu_to_be32(tmp); | |
| 227 | + | |
| 228 | + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); | |
| 229 | + if (ret < 0) | |
| 230 | + return ret; | |
| 231 | + | |
| 232 | + return be32_to_cpu(st->data[1].d32) & 0xffff; | |
| 233 | +} | |
| 234 | + | |
| 235 | +static int ads8688_read_raw(struct iio_dev *indio_dev, | |
| 236 | + struct iio_chan_spec const *chan, | |
| 237 | + int *val, int *val2, long m) | |
| 238 | +{ | |
| 239 | + int ret, offset; | |
| 240 | + unsigned long scale_mv; | |
| 241 | + | |
| 242 | + struct ads8688_state *st = iio_priv(indio_dev); | |
| 243 | + | |
| 244 | + mutex_lock(&st->lock); | |
| 245 | + switch (m) { | |
| 246 | + case IIO_CHAN_INFO_RAW: | |
| 247 | + ret = ads8688_read(indio_dev, chan->channel); | |
| 248 | + mutex_unlock(&st->lock); | |
| 249 | + if (ret < 0) | |
| 250 | + return ret; | |
| 251 | + *val = ret; | |
| 252 | + return IIO_VAL_INT; | |
| 253 | + case IIO_CHAN_INFO_SCALE: | |
| 254 | + scale_mv = st->vref_mv; | |
| 255 | + scale_mv *= ads8688_range_def[st->range[chan->channel]].scale; | |
| 256 | + *val = 0; | |
| 257 | + *val2 = scale_mv; | |
| 258 | + mutex_unlock(&st->lock); | |
| 259 | + return IIO_VAL_INT_PLUS_NANO; | |
| 260 | + case IIO_CHAN_INFO_OFFSET: | |
| 261 | + offset = ads8688_range_def[st->range[chan->channel]].offset; | |
| 262 | + *val = offset; | |
| 263 | + mutex_unlock(&st->lock); | |
| 264 | + return IIO_VAL_INT; | |
| 265 | + } | |
| 266 | + mutex_unlock(&st->lock); | |
| 267 | + | |
| 268 | + return -EINVAL; | |
| 269 | +} | |
| 270 | + | |
| 271 | +static int ads8688_write_reg_range(struct iio_dev *indio_dev, | |
| 272 | + struct iio_chan_spec const *chan, | |
| 273 | + enum ads8688_range range) | |
| 274 | +{ | |
| 275 | + unsigned int tmp; | |
| 276 | + int ret; | |
| 277 | + | |
| 278 | + tmp = ADS8688_PROG_REG_RANGE_CH(chan->channel); | |
| 279 | + ret = ads8688_prog_write(indio_dev, tmp, range); | |
| 280 | + | |
| 281 | + return ret; | |
| 282 | +} | |
| 283 | + | |
| 284 | +static int ads8688_write_raw(struct iio_dev *indio_dev, | |
| 285 | + struct iio_chan_spec const *chan, | |
| 286 | + int val, int val2, long mask) | |
| 287 | +{ | |
| 288 | + struct ads8688_state *st = iio_priv(indio_dev); | |
| 289 | + unsigned int scale = 0; | |
| 290 | + int ret = -EINVAL, i, offset = 0; | |
| 291 | + | |
| 292 | + mutex_lock(&st->lock); | |
| 293 | + switch (mask) { | |
| 294 | + case IIO_CHAN_INFO_SCALE: | |
| 295 | + /* If the offset is 0 the ±2.5 * VREF mode is not available */ | |
| 296 | + offset = ads8688_range_def[st->range[chan->channel]].offset; | |
| 297 | + if (offset == 0 && val2 == ads8688_range_def[0].scale * st->vref_mv) { | |
| 298 | + mutex_unlock(&st->lock); | |
| 299 | + return -EINVAL; | |
| 300 | + } | |
| 301 | + | |
| 302 | + /* Lookup new mode */ | |
| 303 | + for (i = 0; i < ARRAY_SIZE(ads8688_range_def); i++) | |
| 304 | + if (val2 == ads8688_range_def[i].scale * st->vref_mv && | |
| 305 | + offset == ads8688_range_def[i].offset) { | |
| 306 | + ret = ads8688_write_reg_range(indio_dev, chan, | |
| 307 | + ads8688_range_def[i].reg); | |
| 308 | + break; | |
| 309 | + } | |
| 310 | + break; | |
| 311 | + case IIO_CHAN_INFO_OFFSET: | |
| 312 | + /* | |
| 313 | + * There are only two available offsets: | |
| 314 | + * 0 and -(1 << (ADS8688_REALBITS - 1)) | |
| 315 | + */ | |
| 316 | + if (!(ads8688_range_def[0].offset == val || | |
| 317 | + ads8688_range_def[3].offset == val)) { | |
| 318 | + mutex_unlock(&st->lock); | |
| 319 | + return -EINVAL; | |
| 320 | + } | |
| 321 | + | |
| 322 | + /* | |
| 323 | + * If the device are in ±2.5 * VREF mode, it's not allowed to | |
| 324 | + * switch to a mode where the offset is 0 | |
| 325 | + */ | |
| 326 | + if (val == 0 && | |
| 327 | + st->range[chan->channel] == ADS8688_PLUSMINUS25VREF) { | |
| 328 | + mutex_unlock(&st->lock); | |
| 329 | + return -EINVAL; | |
| 330 | + } | |
| 331 | + | |
| 332 | + scale = ads8688_range_def[st->range[chan->channel]].scale; | |
| 333 | + | |
| 334 | + /* Lookup new mode */ | |
| 335 | + for (i = 0; i < ARRAY_SIZE(ads8688_range_def); i++) | |
| 336 | + if (val == ads8688_range_def[i].offset && | |
| 337 | + scale == ads8688_range_def[i].scale) { | |
| 338 | + ret = ads8688_write_reg_range(indio_dev, chan, | |
| 339 | + ads8688_range_def[i].reg); | |
| 340 | + break; | |
| 341 | + } | |
| 342 | + break; | |
| 343 | + } | |
| 344 | + | |
| 345 | + if (!ret) | |
| 346 | + st->range[chan->channel] = ads8688_range_def[i].range; | |
| 347 | + | |
| 348 | + mutex_unlock(&st->lock); | |
| 349 | + | |
| 350 | + return ret; | |
| 351 | +} | |
| 352 | + | |
| 353 | +static int ads8688_write_raw_get_fmt(struct iio_dev *indio_dev, | |
| 354 | + struct iio_chan_spec const *chan, | |
| 355 | + long mask) | |
| 356 | +{ | |
| 357 | + switch (mask) { | |
| 358 | + case IIO_CHAN_INFO_SCALE: | |
| 359 | + return IIO_VAL_INT_PLUS_NANO; | |
| 360 | + case IIO_CHAN_INFO_OFFSET: | |
| 361 | + return IIO_VAL_INT; | |
| 362 | + } | |
| 363 | + | |
| 364 | + return -EINVAL; | |
| 365 | +} | |
| 366 | + | |
| 367 | +static const struct iio_info ads8688_info = { | |
| 368 | + .read_raw = &ads8688_read_raw, | |
| 369 | + .write_raw = &ads8688_write_raw, | |
| 370 | + .write_raw_get_fmt = &ads8688_write_raw_get_fmt, | |
| 371 | + .attrs = &ads8688_attribute_group, | |
| 372 | + .driver_module = THIS_MODULE, | |
| 373 | +}; | |
| 374 | + | |
| 375 | +static const struct ads8688_chip_info ads8688_chip_info_tbl[] = { | |
| 376 | + [ID_ADS8684] = { | |
| 377 | + .channels = ads8684_channels, | |
| 378 | + .num_channels = ARRAY_SIZE(ads8684_channels), | |
| 379 | + }, | |
| 380 | + [ID_ADS8688] = { | |
| 381 | + .channels = ads8688_channels, | |
| 382 | + .num_channels = ARRAY_SIZE(ads8688_channels), | |
| 383 | + }, | |
| 384 | +}; | |
| 385 | + | |
| 386 | +static int ads8688_probe(struct spi_device *spi) | |
| 387 | +{ | |
| 388 | + struct ads8688_state *st; | |
| 389 | + struct iio_dev *indio_dev; | |
| 390 | + int ret; | |
| 391 | + | |
| 392 | + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); | |
| 393 | + if (indio_dev == NULL) | |
| 394 | + return -ENOMEM; | |
| 395 | + | |
| 396 | + st = iio_priv(indio_dev); | |
| 397 | + | |
| 398 | + st->reg = devm_regulator_get_optional(&spi->dev, "vref"); | |
| 399 | + if (!IS_ERR(st->reg)) { | |
| 400 | + ret = regulator_enable(st->reg); | |
| 401 | + if (ret) | |
| 402 | + return ret; | |
| 403 | + | |
| 404 | + ret = regulator_get_voltage(st->reg); | |
| 405 | + if (ret < 0) | |
| 406 | + goto error_out; | |
| 407 | + | |
| 408 | + st->vref_mv = ret / 1000; | |
| 409 | + } else { | |
| 410 | + /* Use internal reference */ | |
| 411 | + st->vref_mv = ADS8688_VREF_MV; | |
| 412 | + } | |
| 413 | + | |
| 414 | + st->chip_info = &ads8688_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | |
| 415 | + | |
| 416 | + spi->mode = SPI_MODE_1; | |
| 417 | + | |
| 418 | + spi_set_drvdata(spi, indio_dev); | |
| 419 | + | |
| 420 | + st->spi = spi; | |
| 421 | + | |
| 422 | + indio_dev->name = spi_get_device_id(spi)->name; | |
| 423 | + indio_dev->dev.parent = &spi->dev; | |
| 424 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 425 | + indio_dev->channels = st->chip_info->channels; | |
| 426 | + indio_dev->num_channels = st->chip_info->num_channels; | |
| 427 | + indio_dev->info = &ads8688_info; | |
| 428 | + | |
| 429 | + ads8688_reset(indio_dev); | |
| 430 | + | |
| 431 | + mutex_init(&st->lock); | |
| 432 | + | |
| 433 | + ret = iio_device_register(indio_dev); | |
| 434 | + if (ret) | |
| 435 | + goto error_out; | |
| 436 | + | |
| 437 | + return 0; | |
| 438 | + | |
| 439 | +error_out: | |
| 440 | + if (!IS_ERR_OR_NULL(st->reg)) | |
| 441 | + regulator_disable(st->reg); | |
| 442 | + | |
| 443 | + return ret; | |
| 444 | +} | |
| 445 | + | |
| 446 | +static int ads8688_remove(struct spi_device *spi) | |
| 447 | +{ | |
| 448 | + struct iio_dev *indio_dev = spi_get_drvdata(spi); | |
| 449 | + struct ads8688_state *st = iio_priv(indio_dev); | |
| 450 | + | |
| 451 | + iio_device_unregister(indio_dev); | |
| 452 | + | |
| 453 | + if (!IS_ERR_OR_NULL(st->reg)) | |
| 454 | + regulator_disable(st->reg); | |
| 455 | + | |
| 456 | + return 0; | |
| 457 | +} | |
| 458 | + | |
| 459 | +static const struct spi_device_id ads8688_id[] = { | |
| 460 | + {"ads8684", ID_ADS8684}, | |
| 461 | + {"ads8688", ID_ADS8688}, | |
| 462 | + {} | |
| 463 | +}; | |
| 464 | +MODULE_DEVICE_TABLE(spi, ads8688_id); | |
| 465 | + | |
| 466 | +static const struct of_device_id ads8688_of_match[] = { | |
| 467 | + { .compatible = "ti,ads8684" }, | |
| 468 | + { .compatible = "ti,ads8688" }, | |
| 469 | + { } | |
| 470 | +}; | |
| 471 | +MODULE_DEVICE_TABLE(of, ads8688_of_match); | |
| 472 | + | |
| 473 | +static struct spi_driver ads8688_driver = { | |
| 474 | + .driver = { | |
| 475 | + .name = "ads8688", | |
| 476 | + .owner = THIS_MODULE, | |
| 477 | + }, | |
| 478 | + .probe = ads8688_probe, | |
| 479 | + .remove = ads8688_remove, | |
| 480 | + .id_table = ads8688_id, | |
| 481 | +}; | |
| 482 | +module_spi_driver(ads8688_driver); | |
| 483 | + | |
| 484 | +MODULE_AUTHOR("Sean Nyekjaer <sean.nyekjaer@prevas.dk>"); | |
| 485 | +MODULE_DESCRIPTION("Texas Instruments ADS8688 driver"); | |
| 486 | +MODULE_LICENSE("GPL v2"); | |
| @@ -803,7 +803,7 @@ err: · 802 unmodified lines | ||
| 803 | 803 | return ret; |
| 804 | 804 | } |
| 805 | 805 | |
| 806 | −static struct iio_buffer_setup_ops xadc_buffer_ops = { | |
| 806 | +static const struct iio_buffer_setup_ops xadc_buffer_ops = { | |
| 807 | 807 | .preenable = &xadc_preenable, |
| 808 | 808 | .postenable = &iio_triggered_buffer_postenable, |
| 809 | 809 | .predisable = &iio_triggered_buffer_predisable, |
| @@ -9,6 +9,26 @@ config IIO_BUFFER_CB · 8 unmodified lines | ||
| 9 | 9 | Should be selected by any drivers that do in-kernel push |
| 10 | 10 | usage. That is, those where the data is pushed to the consumer. |
| 11 | 11 | |
| 12 | +config IIO_BUFFER_DMA | |
| 13 | + tristate | |
| 14 | + help | |
| 15 | + Provides the generic IIO DMA buffer infrastructure that can be used by | |
| 16 | + drivers for devices with DMA support to implement the IIO buffer. | |
| 17 | + | |
| 18 | + Should be selected by drivers that want to use the generic DMA buffer | |
| 19 | + infrastructure. | |
| 20 | + | |
| 21 | +config IIO_BUFFER_DMAENGINE | |
| 22 | + tristate | |
| 23 | + select IIO_BUFFER_DMA | |
| 24 | + help | |
| 25 | + Provides a bonding of the generic IIO DMA buffer infrastructure with the | |
| 26 | + DMAengine framework. This can be used by converter drivers with a DMA port | |
| 27 | + connected to an external DMA controller which is supported by the | |
| 28 | + DMAengine framework. | |
| 29 | + | |
| 30 | + Should be selected by drivers that want to use this functionality. | |
| 31 | + | |
| 12 | 32 | config IIO_KFIFO_BUF |
| 13 | 33 | tristate "Industrial I/O buffering based on kfifo" |
| 14 | 34 | help |
| @@ -4,5 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | # When adding new entries keep the list in alphabetical order |
| 6 | 6 | obj-$(CONFIG_IIO_BUFFER_CB) += industrialio-buffer-cb.o |
| 7 | +obj-$(CONFIG_IIO_BUFFER_DMA) += industrialio-buffer-dma.o | |
| 8 | +obj-$(CONFIG_IIO_BUFFER_DMAENGINE) += industrialio-buffer-dmaengine.o | |
| 7 | 9 | obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o |
| 8 | 10 | obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o |
| @@ -0,0 +1,683 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2013-2015 Analog Devices Inc. | |
| 3 | + * Author: Lars-Peter Clausen <lars@metafoo.de> | |
| 4 | + * | |
| 5 | + * Licensed under the GPL-2. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#include <linux/slab.h> | |
| 9 | +#include <linux/kernel.h> | |
| 10 | +#include <linux/module.h> | |
| 11 | +#include <linux/device.h> | |
| 12 | +#include <linux/workqueue.h> | |
| 13 | +#include <linux/mutex.h> | |
| 14 | +#include <linux/sched.h> | |
| 15 | +#include <linux/poll.h> | |
| 16 | +#include <linux/iio/buffer.h> | |
| 17 | +#include <linux/iio/buffer-dma.h> | |
| 18 | +#include <linux/dma-mapping.h> | |
| 19 | +#include <linux/sizes.h> | |
| 20 | + | |
| 21 | +/* | |
| 22 | + * For DMA buffers the storage is sub-divided into so called blocks. Each block | |
| 23 | + * has its own memory buffer. The size of the block is the granularity at which | |
| 24 | + * memory is exchanged between the hardware and the application. Increasing the | |
| 25 | + * basic unit of data exchange from one sample to one block decreases the | |
| 26 | + * management overhead that is associated with each sample. E.g. if we say the | |
| 27 | + * management overhead for one exchange is x and the unit of exchange is one | |
| 28 | + * sample the overhead will be x for each sample. Whereas when using a block | |
| 29 | + * which contains n samples the overhead per sample is reduced to x/n. This | |
| 30 | + * allows to achieve much higher samplerates than what can be sustained with | |
| 31 | + * the one sample approach. | |
| 32 | + * | |
| 33 | + * Blocks are exchanged between the DMA controller and the application via the | |
| 34 | + * means of two queues. The incoming queue and the outgoing queue. Blocks on the | |
| 35 | + * incoming queue are waiting for the DMA controller to pick them up and fill | |
| 36 | + * them with data. Block on the outgoing queue have been filled with data and | |
| 37 | + * are waiting for the application to dequeue them and read the data. | |
| 38 | + * | |
| 39 | + * A block can be in one of the following states: | |
| 40 | + * * Owned by the application. In this state the application can read data from | |
| 41 | + * the block. | |
| 42 | + * * On the incoming list: Blocks on the incoming list are queued up to be | |
| 43 | + * processed by the DMA controller. | |
| 44 | + * * Owned by the DMA controller: The DMA controller is processing the block | |
| 45 | + * and filling it with data. | |
| 46 | + * * On the outgoing list: Blocks on the outgoing list have been successfully | |
| 47 | + * processed by the DMA controller and contain data. They can be dequeued by | |
| 48 | + * the application. | |
| 49 | + * * Dead: A block that is dead has been marked as to be freed. It might still | |
| 50 | + * be owned by either the application or the DMA controller at the moment. | |
| 51 | + * But once they are done processing it instead of going to either the | |
| 52 | + * incoming or outgoing queue the block will be freed. | |
| 53 | + * | |
| 54 | + * In addition to this blocks are reference counted and the memory associated | |
| 55 | + * with both the block structure as well as the storage memory for the block | |
| 56 | + * will be freed when the last reference to the block is dropped. This means a | |
| 57 | + * block must not be accessed without holding a reference. | |
| 58 | + * | |
| 59 | + * The iio_dma_buffer implementation provides a generic infrastructure for | |
| 60 | + * managing the blocks. | |
| 61 | + * | |
| 62 | + * A driver for a specific piece of hardware that has DMA capabilities need to | |
| 63 | + * implement the submit() callback from the iio_dma_buffer_ops structure. This | |
| 64 | + * callback is supposed to initiate the DMA transfer copying data from the | |
| 65 | + * converter to the memory region of the block. Once the DMA transfer has been | |
| 66 | + * completed the driver must call iio_dma_buffer_block_done() for the completed | |
| 67 | + * block. | |
| 68 | + * | |
| 69 | + * Prior to this it must set the bytes_used field of the block contains | |
| 70 | + * the actual number of bytes in the buffer. Typically this will be equal to the | |
| 71 | + * size of the block, but if the DMA hardware has certain alignment requirements | |
| 72 | + * for the transfer length it might choose to use less than the full size. In | |
| 73 | + * either case it is expected that bytes_used is a multiple of the bytes per | |
| 74 | + * datum, i.e. the block must not contain partial samples. | |
| 75 | + * | |
| 76 | + * The driver must call iio_dma_buffer_block_done() for each block it has | |
| 77 | + * received through its submit_block() callback, even if it does not actually | |
| 78 | + * perform a DMA transfer for the block, e.g. because the buffer was disabled | |
| 79 | + * before the block transfer was started. In this case it should set bytes_used | |
| 80 | + * to 0. | |
| 81 | + * | |
| 82 | + * In addition it is recommended that a driver implements the abort() callback. | |
| 83 | + * It will be called when the buffer is disabled and can be used to cancel | |
| 84 | + * pending and stop active transfers. | |
| 85 | + * | |
| 86 | + * The specific driver implementation should use the default callback | |
| 87 | + * implementations provided by this module for the iio_buffer_access_funcs | |
| 88 | + * struct. It may overload some callbacks with custom variants if the hardware | |
| 89 | + * has special requirements that are not handled by the generic functions. If a | |
| 90 | + * driver chooses to overload a callback it has to ensure that the generic | |
| 91 | + * callback is called from within the custom callback. | |
| 92 | + */ | |
| 93 | + | |
| 94 | +static void iio_buffer_block_release(struct kref *kref) | |
| 95 | +{ | |
| 96 | + struct iio_dma_buffer_block *block = container_of(kref, | |
| 97 | + struct iio_dma_buffer_block, kref); | |
| 98 | + | |
| 99 | + WARN_ON(block->state != IIO_BLOCK_STATE_DEAD); | |
| 100 | + | |
| 101 | + dma_free_coherent(block->queue->dev, PAGE_ALIGN(block->size), | |
| 102 | + block->vaddr, block->phys_addr); | |
| 103 | + | |
| 104 | + iio_buffer_put(&block->queue->buffer); | |
| 105 | + kfree(block); | |
| 106 | +} | |
| 107 | + | |
| 108 | +static void iio_buffer_block_get(struct iio_dma_buffer_block *block) | |
| 109 | +{ | |
| 110 | + kref_get(&block->kref); | |
| 111 | +} | |
| 112 | + | |
| 113 | +static void iio_buffer_block_put(struct iio_dma_buffer_block *block) | |
| 114 | +{ | |
| 115 | + kref_put(&block->kref, iio_buffer_block_release); | |
| 116 | +} | |
| 117 | + | |
| 118 | +/* | |
| 119 | + * dma_free_coherent can sleep, hence we need to take some special care to be | |
| 120 | + * able to drop a reference from an atomic context. | |
| 121 | + */ | |
| 122 | +static LIST_HEAD(iio_dma_buffer_dead_blocks); | |
| 123 | +static DEFINE_SPINLOCK(iio_dma_buffer_dead_blocks_lock); | |
| 124 | + | |
| 125 | +static void iio_dma_buffer_cleanup_worker(struct work_struct *work) | |
| 126 | +{ | |
| 127 | + struct iio_dma_buffer_block *block, *_block; | |
| 128 | + LIST_HEAD(block_list); | |
| 129 | + | |
| 130 | + spin_lock_irq(&iio_dma_buffer_dead_blocks_lock); | |
| 131 | + list_splice_tail_init(&iio_dma_buffer_dead_blocks, &block_list); | |
| 132 | + spin_unlock_irq(&iio_dma_buffer_dead_blocks_lock); | |
| 133 | + | |
| 134 | + list_for_each_entry_safe(block, _block, &block_list, head) | |
| 135 | + iio_buffer_block_release(&block->kref); | |
| 136 | +} | |
| 137 | +static DECLARE_WORK(iio_dma_buffer_cleanup_work, iio_dma_buffer_cleanup_worker); | |
| 138 | + | |
| 139 | +static void iio_buffer_block_release_atomic(struct kref *kref) | |
| 140 | +{ | |
| 141 | + struct iio_dma_buffer_block *block; | |
| 142 | + unsigned long flags; | |
| 143 | + | |
| 144 | + block = container_of(kref, struct iio_dma_buffer_block, kref); | |
| 145 | + | |
| 146 | + spin_lock_irqsave(&iio_dma_buffer_dead_blocks_lock, flags); | |
| 147 | + list_add_tail(&block->head, &iio_dma_buffer_dead_blocks); | |
| 148 | + spin_unlock_irqrestore(&iio_dma_buffer_dead_blocks_lock, flags); | |
| 149 | + | |
| 150 | + schedule_work(&iio_dma_buffer_cleanup_work); | |
| 151 | +} | |
| 152 | + | |
| 153 | +/* | |
| 154 | + * Version of iio_buffer_block_put() that can be called from atomic context | |
| 155 | + */ | |
| 156 | +static void iio_buffer_block_put_atomic(struct iio_dma_buffer_block *block) | |
| 157 | +{ | |
| 158 | + kref_put(&block->kref, iio_buffer_block_release_atomic); | |
| 159 | +} | |
| 160 | + | |
| 161 | +static struct iio_dma_buffer_queue *iio_buffer_to_queue(struct iio_buffer *buf) | |
| 162 | +{ | |
| 163 | + return container_of(buf, struct iio_dma_buffer_queue, buffer); | |
| 164 | +} | |
| 165 | + | |
| 166 | +static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block( | |
| 167 | + struct iio_dma_buffer_queue *queue, size_t size) | |
| 168 | +{ | |
| 169 | + struct iio_dma_buffer_block *block; | |
| 170 | + | |
| 171 | + block = kzalloc(sizeof(*block), GFP_KERNEL); | |
| 172 | + if (!block) | |
| 173 | + return NULL; | |
| 174 | + | |
| 175 | + block->vaddr = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size), | |
| 176 | + &block->phys_addr, GFP_KERNEL); | |
| 177 | + if (!block->vaddr) { | |
| 178 | + kfree(block); | |
| 179 | + return NULL; | |
| 180 | + } | |
| 181 | + | |
| 182 | + block->size = size; | |
| 183 | + block->state = IIO_BLOCK_STATE_DEQUEUED; | |
| 184 | + block->queue = queue; | |
| 185 | + INIT_LIST_HEAD(&block->head); | |
| 186 | + kref_init(&block->kref); | |
| 187 | + | |
| 188 | + iio_buffer_get(&queue->buffer); | |
| 189 | + | |
| 190 | + return block; | |
| 191 | +} | |
| 192 | + | |
| 193 | +static void _iio_dma_buffer_block_done(struct iio_dma_buffer_block *block) | |
| 194 | +{ | |
| 195 | + struct iio_dma_buffer_queue *queue = block->queue; | |
| 196 | + | |
| 197 | + /* | |
| 198 | + * The buffer has already been freed by the application, just drop the | |
| 199 | + * reference. | |
| 200 | + */ | |
| 201 | + if (block->state != IIO_BLOCK_STATE_DEAD) { | |
| 202 | + block->state = IIO_BLOCK_STATE_DONE; | |
| 203 | + list_add_tail(&block->head, &queue->outgoing); | |
| 204 | + } | |
| 205 | +} | |
| 206 | + | |
| 207 | +/** | |
| 208 | + * iio_dma_buffer_block_done() - Indicate that a block has been completed | |
| 209 | + * @block: The completed block | |
| 210 | + * | |
| 211 | + * Should be called when the DMA controller has finished handling the block to | |
| 212 | + * pass back ownership of the block to the queue. | |
| 213 | + */ | |
| 214 | +void iio_dma_buffer_block_done(struct iio_dma_buffer_block *block) | |
| 215 | +{ | |
| 216 | + struct iio_dma_buffer_queue *queue = block->queue; | |
| 217 | + unsigned long flags; | |
| 218 | + | |
| 219 | + spin_lock_irqsave(&queue->list_lock, flags); | |
| 220 | + _iio_dma_buffer_block_done(block); | |
| 221 | + spin_unlock_irqrestore(&queue->list_lock, flags); | |
| 222 | + | |
| 223 | + iio_buffer_block_put_atomic(block); | |
| 224 | + wake_up_interruptible_poll(&queue->buffer.pollq, POLLIN | POLLRDNORM); | |
| 225 | +} | |
| 226 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_block_done); | |
| 227 | + | |
| 228 | +/** | |
| 229 | + * iio_dma_buffer_block_list_abort() - Indicate that a list block has been | |
| 230 | + * aborted | |
| 231 | + * @queue: Queue for which to complete blocks. | |
| 232 | + * @list: List of aborted blocks. All blocks in this list must be from @queue. | |
| 233 | + * | |
| 234 | + * Typically called from the abort() callback after the DMA controller has been | |
| 235 | + * stopped. This will set bytes_used to 0 for each block in the list and then | |
| 236 | + * hand the blocks back to the queue. | |
| 237 | + */ | |
| 238 | +void iio_dma_buffer_block_list_abort(struct iio_dma_buffer_queue *queue, | |
| 239 | + struct list_head *list) | |
| 240 | +{ | |
| 241 | + struct iio_dma_buffer_block *block, *_block; | |
| 242 | + unsigned long flags; | |
| 243 | + | |
| 244 | + spin_lock_irqsave(&queue->list_lock, flags); | |
| 245 | + list_for_each_entry_safe(block, _block, list, head) { | |
| 246 | + list_del(&block->head); | |
| 247 | + block->bytes_used = 0; | |
| 248 | + _iio_dma_buffer_block_done(block); | |
| 249 | + iio_buffer_block_put_atomic(block); | |
| 250 | + } | |
| 251 | + spin_unlock_irqrestore(&queue->list_lock, flags); | |
| 252 | + | |
| 253 | + wake_up_interruptible_poll(&queue->buffer.pollq, POLLIN | POLLRDNORM); | |
| 254 | +} | |
| 255 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_block_list_abort); | |
| 256 | + | |
| 257 | +static bool iio_dma_block_reusable(struct iio_dma_buffer_block *block) | |
| 258 | +{ | |
| 259 | + /* | |
| 260 | + * If the core owns the block it can be re-used. This should be the | |
| 261 | + * default case when enabling the buffer, unless the DMA controller does | |
| 262 | + * not support abort and has not given back the block yet. | |
| 263 | + */ | |
| 264 | + switch (block->state) { | |
| 265 | + case IIO_BLOCK_STATE_DEQUEUED: | |
| 266 | + case IIO_BLOCK_STATE_QUEUED: | |
| 267 | + case IIO_BLOCK_STATE_DONE: | |
| 268 | + return true; | |
| 269 | + default: | |
| 270 | + return false; | |
| 271 | + } | |
| 272 | +} | |
| 273 | + | |
| 274 | +/** | |
| 275 | + * iio_dma_buffer_request_update() - DMA buffer request_update callback | |
| 276 | + * @buffer: The buffer which to request an update | |
| 277 | + * | |
| 278 | + * Should be used as the iio_dma_buffer_request_update() callback for | |
| 279 | + * iio_buffer_access_ops struct for DMA buffers. | |
| 280 | + */ | |
| 281 | +int iio_dma_buffer_request_update(struct iio_buffer *buffer) | |
| 282 | +{ | |
| 283 | + struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); | |
| 284 | + struct iio_dma_buffer_block *block; | |
| 285 | + bool try_reuse = false; | |
| 286 | + size_t size; | |
| 287 | + int ret = 0; | |
| 288 | + int i; | |
| 289 | + | |
| 290 | + /* | |
| 291 | + * Split the buffer into two even parts. This is used as a double | |
| 292 | + * buffering scheme with usually one block at a time being used by the | |
| 293 | + * DMA and the other one by the application. | |
| 294 | + */ | |
| 295 | + size = DIV_ROUND_UP(queue->buffer.bytes_per_datum * | |
| 296 | + queue->buffer.length, 2); | |
| 297 | + | |
| 298 | + mutex_lock(&queue->lock); | |
| 299 | + | |
| 300 | + /* Allocations are page aligned */ | |
| 301 | + if (PAGE_ALIGN(queue->fileio.block_size) == PAGE_ALIGN(size)) | |
| 302 | + try_reuse = true; | |
| 303 | + | |
| 304 | + queue->fileio.block_size = size; | |
| 305 | + queue->fileio.active_block = NULL; | |
| 306 | + | |
| 307 | + spin_lock_irq(&queue->list_lock); | |
| 308 | + for (i = 0; i < 2; i++) { | |
| 309 | + block = queue->fileio.blocks[i]; | |
| 310 | + | |
| 311 | + /* If we can't re-use it free it */ | |
| 312 | + if (block && (!iio_dma_block_reusable(block) || !try_reuse)) | |
| 313 | + block->state = IIO_BLOCK_STATE_DEAD; | |
| 314 | + } | |
| 315 | + | |
| 316 | + /* | |
| 317 | + * At this point all blocks are either owned by the core or marked as | |
| 318 | + * dead. This means we can reset the lists without having to fear | |
| 319 | + * corrution. | |
| 320 | + */ | |
| 321 | + INIT_LIST_HEAD(&queue->outgoing); | |
| 322 | + spin_unlock_irq(&queue->list_lock); | |
| 323 | + | |
| 324 | + INIT_LIST_HEAD(&queue->incoming); | |
| 325 | + | |
| 326 | + for (i = 0; i < 2; i++) { | |
| 327 | + if (queue->fileio.blocks[i]) { | |
| 328 | + block = queue->fileio.blocks[i]; | |
| 329 | + if (block->state == IIO_BLOCK_STATE_DEAD) { | |
| 330 | + /* Could not reuse it */ | |
| 331 | + iio_buffer_block_put(block); | |
| 332 | + block = NULL; | |
| 333 | + } else { | |
| 334 | + block->size = size; | |
| 335 | + } | |
| 336 | + } else { | |
| 337 | + block = NULL; | |
| 338 | + } | |
| 339 | + | |
| 340 | + if (!block) { | |
| 341 | + block = iio_dma_buffer_alloc_block(queue, size); | |
| 342 | + if (!block) { | |
| 343 | + ret = -ENOMEM; | |
| 344 | + goto out_unlock; | |
| 345 | + } | |
| 346 | + queue->fileio.blocks[i] = block; | |
| 347 | + } | |
| 348 | + | |
| 349 | + block->state = IIO_BLOCK_STATE_QUEUED; | |
| 350 | + list_add_tail(&block->head, &queue->incoming); | |
| 351 | + } | |
| 352 | + | |
| 353 | +out_unlock: | |
| 354 | + mutex_unlock(&queue->lock); | |
| 355 | + | |
| 356 | + return ret; | |
| 357 | +} | |
| 358 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_request_update); | |
| 359 | + | |
| 360 | +static void iio_dma_buffer_submit_block(struct iio_dma_buffer_queue *queue, | |
| 361 | + struct iio_dma_buffer_block *block) | |
| 362 | +{ | |
| 363 | + int ret; | |
| 364 | + | |
| 365 | + /* | |
| 366 | + * If the hardware has already been removed we put the block into | |
| 367 | + * limbo. It will neither be on the incoming nor outgoing list, nor will | |
| 368 | + * it ever complete. It will just wait to be freed eventually. | |
| 369 | + */ | |
| 370 | + if (!queue->ops) | |
| 371 | + return; | |
| 372 | + | |
| 373 | + block->state = IIO_BLOCK_STATE_ACTIVE; | |
| 374 | + iio_buffer_block_get(block); | |
| 375 | + ret = queue->ops->submit(queue, block); | |
| 376 | + if (ret) { | |
| 377 | + /* | |
| 378 | + * This is a bit of a problem and there is not much we can do | |
| 379 | + * other then wait for the buffer to be disabled and re-enabled | |
| 380 | + * and try again. But it should not really happen unless we run | |
| 381 | + * out of memory or something similar. | |
| 382 | + * | |
| 383 | + * TODO: Implement support in the IIO core to allow buffers to | |
| 384 | + * notify consumers that something went wrong and the buffer | |
| 385 | + * should be disabled. | |
| 386 | + */ | |
| 387 | + iio_buffer_block_put(block); | |
| 388 | + } | |
| 389 | +} | |
| 390 | + | |
| 391 | +/** | |
| 392 | + * iio_dma_buffer_enable() - Enable DMA buffer | |
| 393 | + * @buffer: IIO buffer to enable | |
| 394 | + * @indio_dev: IIO device the buffer is attached to | |
| 395 | + * | |
| 396 | + * Needs to be called when the device that the buffer is attached to starts | |
| 397 | + * sampling. Typically should be the iio_buffer_access_ops enable callback. | |
| 398 | + * | |
| 399 | + * This will allocate the DMA buffers and start the DMA transfers. | |
| 400 | + */ | |
| 401 | +int iio_dma_buffer_enable(struct iio_buffer *buffer, | |
| 402 | + struct iio_dev *indio_dev) | |
| 403 | +{ | |
| 404 | + struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); | |
| 405 | + struct iio_dma_buffer_block *block, *_block; | |
| 406 | + | |
| 407 | + mutex_lock(&queue->lock); | |
| 408 | + queue->active = true; | |
| 409 | + list_for_each_entry_safe(block, _block, &queue->incoming, head) { | |
| 410 | + list_del(&block->head); | |
| 411 | + iio_dma_buffer_submit_block(queue, block); | |
| 412 | + } | |
| 413 | + mutex_unlock(&queue->lock); | |
| 414 | + | |
| 415 | + return 0; | |
| 416 | +} | |
| 417 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_enable); | |
| 418 | + | |
| 419 | +/** | |
| 420 | + * iio_dma_buffer_disable() - Disable DMA buffer | |
| 421 | + * @buffer: IIO DMA buffer to disable | |
| 422 | + * @indio_dev: IIO device the buffer is attached to | |
| 423 | + * | |
| 424 | + * Needs to be called when the device that the buffer is attached to stops | |
| 425 | + * sampling. Typically should be the iio_buffer_access_ops disable callback. | |
| 426 | + */ | |
| 427 | +int iio_dma_buffer_disable(struct iio_buffer *buffer, | |
| 428 | + struct iio_dev *indio_dev) | |
| 429 | +{ | |
| 430 | + struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); | |
| 431 | + | |
| 432 | + mutex_lock(&queue->lock); | |
| 433 | + queue->active = false; | |
| 434 | + | |
| 435 | + if (queue->ops && queue->ops->abort) | |
| 436 | + queue->ops->abort(queue); | |
| 437 | + mutex_unlock(&queue->lock); | |
| 438 | + | |
| 439 | + return 0; | |
| 440 | +} | |
| 441 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_disable); | |
| 442 | + | |
| 443 | +static void iio_dma_buffer_enqueue(struct iio_dma_buffer_queue *queue, | |
| 444 | + struct iio_dma_buffer_block *block) | |
| 445 | +{ | |
| 446 | + if (block->state == IIO_BLOCK_STATE_DEAD) { | |
| 447 | + iio_buffer_block_put(block); | |
| 448 | + } else if (queue->active) { | |
| 449 | + iio_dma_buffer_submit_block(queue, block); | |
| 450 | + } else { | |
| 451 | + block->state = IIO_BLOCK_STATE_QUEUED; | |
| 452 | + list_add_tail(&block->head, &queue->incoming); | |
| 453 | + } | |
| 454 | +} | |
| 455 | + | |
| 456 | +static struct iio_dma_buffer_block *iio_dma_buffer_dequeue( | |
| 457 | + struct iio_dma_buffer_queue *queue) | |
| 458 | +{ | |
| 459 | + struct iio_dma_buffer_block *block; | |
| 460 | + | |
| 461 | + spin_lock_irq(&queue->list_lock); | |
| 462 | + block = list_first_entry_or_null(&queue->outgoing, struct | |
| 463 | + iio_dma_buffer_block, head); | |
| 464 | + if (block != NULL) { | |
| 465 | + list_del(&block->head); | |
| 466 | + block->state = IIO_BLOCK_STATE_DEQUEUED; | |
| 467 | + } | |
| 468 | + spin_unlock_irq(&queue->list_lock); | |
| 469 | + | |
| 470 | + return block; | |
| 471 | +} | |
| 472 | + | |
| 473 | +/** | |
| 474 | + * iio_dma_buffer_read() - DMA buffer read callback | |
| 475 | + * @buffer: Buffer to read form | |
| 476 | + * @n: Number of bytes to read | |
| 477 | + * @user_buffer: Userspace buffer to copy the data to | |
| 478 | + * | |
| 479 | + * Should be used as the read_first_n callback for iio_buffer_access_ops | |
| 480 | + * struct for DMA buffers. | |
| 481 | + */ | |
| 482 | +int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, | |
| 483 | + char __user *user_buffer) | |
| 484 | +{ | |
| 485 | + struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); | |
| 486 | + struct iio_dma_buffer_block *block; | |
| 487 | + int ret; | |
| 488 | + | |
| 489 | + if (n < buffer->bytes_per_datum) | |
| 490 | + return -EINVAL; | |
| 491 | + | |
| 492 | + mutex_lock(&queue->lock); | |
| 493 | + | |
| 494 | + if (!queue->fileio.active_block) { | |
| 495 | + block = iio_dma_buffer_dequeue(queue); | |
| 496 | + if (block == NULL) { | |
| 497 | + ret = 0; | |
| 498 | + goto out_unlock; | |
| 499 | + } | |
| 500 | + queue->fileio.pos = 0; | |
| 501 | + queue->fileio.active_block = block; | |
| 502 | + } else { | |
| 503 | + block = queue->fileio.active_block; | |
| 504 | + } | |
| 505 | + | |
| 506 | + n = rounddown(n, buffer->bytes_per_datum); | |
| 507 | + if (n > block->bytes_used - queue->fileio.pos) | |
| 508 | + n = block->bytes_used - queue->fileio.pos; | |
| 509 | + | |
| 510 | + if (copy_to_user(user_buffer, block->vaddr + queue->fileio.pos, n)) { | |
| 511 | + ret = -EFAULT; | |
| 512 | + goto out_unlock; | |
| 513 | + } | |
| 514 | + | |
| 515 | + queue->fileio.pos += n; | |
| 516 | + | |
| 517 | + if (queue->fileio.pos == block->bytes_used) { | |
| 518 | + queue->fileio.active_block = NULL; | |
| 519 | + iio_dma_buffer_enqueue(queue, block); | |
| 520 | + } | |
| 521 | + | |
| 522 | + ret = n; | |
| 523 | + | |
| 524 | +out_unlock: | |
| 525 | + mutex_unlock(&queue->lock); | |
| 526 | + | |
| 527 | + return ret; | |
| 528 | +} | |
| 529 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_read); | |
| 530 | + | |
| 531 | +/** | |
| 532 | + * iio_dma_buffer_data_available() - DMA buffer data_available callback | |
| 533 | + * @buf: Buffer to check for data availability | |
| 534 | + * | |
| 535 | + * Should be used as the data_available callback for iio_buffer_access_ops | |
| 536 | + * struct for DMA buffers. | |
| 537 | + */ | |
| 538 | +size_t iio_dma_buffer_data_available(struct iio_buffer *buf) | |
| 539 | +{ | |
| 540 | + struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buf); | |
| 541 | + struct iio_dma_buffer_block *block; | |
| 542 | + size_t data_available = 0; | |
| 543 | + | |
| 544 | + /* | |
| 545 | + * For counting the available bytes we'll use the size of the block not | |
| 546 | + * the number of actual bytes available in the block. Otherwise it is | |
| 547 | + * possible that we end up with a value that is lower than the watermark | |
| 548 | + * but won't increase since all blocks are in use. | |
| 549 | + */ | |
| 550 | + | |
| 551 | + mutex_lock(&queue->lock); | |
| 552 | + if (queue->fileio.active_block) | |
| 553 | + data_available += queue->fileio.active_block->size; | |
| 554 | + | |
| 555 | + spin_lock_irq(&queue->list_lock); | |
| 556 | + list_for_each_entry(block, &queue->outgoing, head) | |
| 557 | + data_available += block->size; | |
| 558 | + spin_unlock_irq(&queue->list_lock); | |
| 559 | + mutex_unlock(&queue->lock); | |
| 560 | + | |
| 561 | + return data_available; | |
| 562 | +} | |
| 563 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_data_available); | |
| 564 | + | |
| 565 | +/** | |
| 566 | + * iio_dma_buffer_set_bytes_per_datum() - DMA buffer set_bytes_per_datum callback | |
| 567 | + * @buffer: Buffer to set the bytes-per-datum for | |
| 568 | + * @bpd: The new bytes-per-datum value | |
| 569 | + * | |
| 570 | + * Should be used as the set_bytes_per_datum callback for iio_buffer_access_ops | |
| 571 | + * struct for DMA buffers. | |
| 572 | + */ | |
| 573 | +int iio_dma_buffer_set_bytes_per_datum(struct iio_buffer *buffer, size_t bpd) | |
| 574 | +{ | |
| 575 | + buffer->bytes_per_datum = bpd; | |
| 576 | + | |
| 577 | + return 0; | |
| 578 | +} | |
| 579 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_set_bytes_per_datum); | |
| 580 | + | |
| 581 | +/** | |
| 582 | + * iio_dma_buffer_set_length - DMA buffer set_length callback | |
| 583 | + * @buffer: Buffer to set the length for | |
| 584 | + * @length: The new buffer length | |
| 585 | + * | |
| 586 | + * Should be used as the set_length callback for iio_buffer_access_ops | |
| 587 | + * struct for DMA buffers. | |
| 588 | + */ | |
| 589 | +int iio_dma_buffer_set_length(struct iio_buffer *buffer, int length) | |
| 590 | +{ | |
| 591 | + /* Avoid an invalid state */ | |
| 592 | + if (length < 2) | |
| 593 | + length = 2; | |
| 594 | + buffer->length = length; | |
| 595 | + buffer->watermark = length / 2; | |
| 596 | + | |
| 597 | + return 0; | |
| 598 | +} | |
| 599 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_set_length); | |
| 600 | + | |
| 601 | +/** | |
| 602 | + * iio_dma_buffer_init() - Initialize DMA buffer queue | |
| 603 | + * @queue: Buffer to initialize | |
| 604 | + * @dev: DMA device | |
| 605 | + * @ops: DMA buffer queue callback operations | |
| 606 | + * | |
| 607 | + * The DMA device will be used by the queue to do DMA memory allocations. So it | |
| 608 | + * should refer to the device that will perform the DMA to ensure that | |
| 609 | + * allocations are done from a memory region that can be accessed by the device. | |
| 610 | + */ | |
| 611 | +int iio_dma_buffer_init(struct iio_dma_buffer_queue *queue, | |
| 612 | + struct device *dev, const struct iio_dma_buffer_ops *ops) | |
| 613 | +{ | |
| 614 | + iio_buffer_init(&queue->buffer); | |
| 615 | + queue->buffer.length = PAGE_SIZE; | |
| 616 | + queue->buffer.watermark = queue->buffer.length / 2; | |
| 617 | + queue->dev = dev; | |
| 618 | + queue->ops = ops; | |
| 619 | + | |
| 620 | + INIT_LIST_HEAD(&queue->incoming); | |
| 621 | + INIT_LIST_HEAD(&queue->outgoing); | |
| 622 | + | |
| 623 | + mutex_init(&queue->lock); | |
| 624 | + spin_lock_init(&queue->list_lock); | |
| 625 | + | |
| 626 | + return 0; | |
| 627 | +} | |
| 628 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_init); | |
| 629 | + | |
| 630 | +/** | |
| 631 | + * iio_dma_buffer_exit() - Cleanup DMA buffer queue | |
| 632 | + * @queue: Buffer to cleanup | |
| 633 | + * | |
| 634 | + * After this function has completed it is safe to free any resources that are | |
| 635 | + * associated with the buffer and are accessed inside the callback operations. | |
| 636 | + */ | |
| 637 | +void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue) | |
| 638 | +{ | |
| 639 | + unsigned int i; | |
| 640 | + | |
| 641 | + mutex_lock(&queue->lock); | |
| 642 | + | |
| 643 | + spin_lock_irq(&queue->list_lock); | |
| 644 | + for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) { | |
| 645 | + if (!queue->fileio.blocks[i]) | |
| 646 | + continue; | |
| 647 | + queue->fileio.blocks[i]->state = IIO_BLOCK_STATE_DEAD; | |
| 648 | + } | |
| 649 | + INIT_LIST_HEAD(&queue->outgoing); | |
| 650 | + spin_unlock_irq(&queue->list_lock); | |
| 651 | + | |
| 652 | + INIT_LIST_HEAD(&queue->incoming); | |
| 653 | + | |
| 654 | + for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) { | |
| 655 | + if (!queue->fileio.blocks[i]) | |
| 656 | + continue; | |
| 657 | + iio_buffer_block_put(queue->fileio.blocks[i]); | |
| 658 | + queue->fileio.blocks[i] = NULL; | |
| 659 | + } | |
| 660 | + queue->fileio.active_block = NULL; | |
| 661 | + queue->ops = NULL; | |
| 662 | + | |
| 663 | + mutex_unlock(&queue->lock); | |
| 664 | +} | |
| 665 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_exit); | |
| 666 | + | |
| 667 | +/** | |
| 668 | + * iio_dma_buffer_release() - Release final buffer resources | |
| 669 | + * @queue: Buffer to release | |
| 670 | + * | |
| 671 | + * Frees resources that can't yet be freed in iio_dma_buffer_exit(). Should be | |
| 672 | + * called in the buffers release callback implementation right before freeing | |
| 673 | + * the memory associated with the buffer. | |
| 674 | + */ | |
| 675 | +void iio_dma_buffer_release(struct iio_dma_buffer_queue *queue) | |
| 676 | +{ | |
| 677 | + mutex_destroy(&queue->lock); | |
| 678 | +} | |
| 679 | +EXPORT_SYMBOL_GPL(iio_dma_buffer_release); | |
| 680 | + | |
| 681 | +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | |
| 682 | +MODULE_DESCRIPTION("DMA buffer for the IIO framework"); | |
| 683 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,213 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2014-2015 Analog Devices Inc. | |
| 3 | + * Author: Lars-Peter Clausen <lars@metafoo.de> | |
| 4 | + * | |
| 5 | + * Licensed under the GPL-2 or later. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#include <linux/slab.h> | |
| 9 | +#include <linux/kernel.h> | |
| 10 | +#include <linux/dmaengine.h> | |
| 11 | +#include <linux/dma-mapping.h> | |
| 12 | +#include <linux/spinlock.h> | |
| 13 | +#include <linux/err.h> | |
| 14 | + | |
| 15 | +#include <linux/iio/iio.h> | |
| 16 | +#include <linux/iio/buffer.h> | |
| 17 | +#include <linux/iio/buffer-dma.h> | |
| 18 | +#include <linux/iio/buffer-dmaengine.h> | |
| 19 | + | |
| 20 | +/* | |
| 21 | + * The IIO DMAengine buffer combines the generic IIO DMA buffer infrastructure | |
| 22 | + * with the DMAengine framework. The generic IIO DMA buffer infrastructure is | |
| 23 | + * used to manage the buffer memory and implement the IIO buffer operations | |
| 24 | + * while the DMAengine framework is used to perform the DMA transfers. Combined | |
| 25 | + * this results in a device independent fully functional DMA buffer | |
| 26 | + * implementation that can be used by device drivers for peripherals which are | |
| 27 | + * connected to a DMA controller which has a DMAengine driver implementation. | |
| 28 | + */ | |
| 29 | + | |
| 30 | +struct dmaengine_buffer { | |
| 31 | + struct iio_dma_buffer_queue queue; | |
| 32 | + | |
| 33 | + struct dma_chan *chan; | |
| 34 | + struct list_head active; | |
| 35 | + | |
| 36 | + size_t align; | |
| 37 | + size_t max_size; | |
| 38 | +}; | |
| 39 | + | |
| 40 | +static struct dmaengine_buffer *iio_buffer_to_dmaengine_buffer( | |
| 41 | + struct iio_buffer *buffer) | |
| 42 | +{ | |
| 43 | + return container_of(buffer, struct dmaengine_buffer, queue.buffer); | |
| 44 | +} | |
| 45 | + | |
| 46 | +static void iio_dmaengine_buffer_block_done(void *data) | |
| 47 | +{ | |
| 48 | + struct iio_dma_buffer_block *block = data; | |
| 49 | + unsigned long flags; | |
| 50 | + | |
| 51 | + spin_lock_irqsave(&block->queue->list_lock, flags); | |
| 52 | + list_del(&block->head); | |
| 53 | + spin_unlock_irqrestore(&block->queue->list_lock, flags); | |
| 54 | + iio_dma_buffer_block_done(block); | |
| 55 | +} | |
| 56 | + | |
| 57 | +static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue, | |
| 58 | + struct iio_dma_buffer_block *block) | |
| 59 | +{ | |
| 60 | + struct dmaengine_buffer *dmaengine_buffer = | |
| 61 | + iio_buffer_to_dmaengine_buffer(&queue->buffer); | |
| 62 | + struct dma_async_tx_descriptor *desc; | |
| 63 | + dma_cookie_t cookie; | |
| 64 | + | |
| 65 | + block->bytes_used = min(block->size, dmaengine_buffer->max_size); | |
| 66 | + block->bytes_used = rounddown(block->bytes_used, | |
| 67 | + dmaengine_buffer->align); | |
| 68 | + | |
| 69 | + desc = dmaengine_prep_slave_single(dmaengine_buffer->chan, | |
| 70 | + block->phys_addr, block->bytes_used, DMA_DEV_TO_MEM, | |
| 71 | + DMA_PREP_INTERRUPT); | |
| 72 | + if (!desc) | |
| 73 | + return -ENOMEM; | |
| 74 | + | |
| 75 | + desc->callback = iio_dmaengine_buffer_block_done; | |
| 76 | + desc->callback_param = block; | |
| 77 | + | |
| 78 | + cookie = dmaengine_submit(desc); | |
| 79 | + if (dma_submit_error(cookie)) | |
| 80 | + return dma_submit_error(cookie); | |
| 81 | + | |
| 82 | + spin_lock_irq(&dmaengine_buffer->queue.list_lock); | |
| 83 | + list_add_tail(&block->head, &dmaengine_buffer->active); | |
| 84 | + spin_unlock_irq(&dmaengine_buffer->queue.list_lock); | |
| 85 | + | |
| 86 | + dma_async_issue_pending(dmaengine_buffer->chan); | |
| 87 | + | |
| 88 | + return 0; | |
| 89 | +} | |
| 90 | + | |
| 91 | +static void iio_dmaengine_buffer_abort(struct iio_dma_buffer_queue *queue) | |
| 92 | +{ | |
| 93 | + struct dmaengine_buffer *dmaengine_buffer = | |
| 94 | + iio_buffer_to_dmaengine_buffer(&queue->buffer); | |
| 95 | + | |
| 96 | + dmaengine_terminate_all(dmaengine_buffer->chan); | |
| 97 | + /* FIXME: There is a slight chance of a race condition here. | |
| 98 | + * dmaengine_terminate_all() does not guarantee that all transfer | |
| 99 | + * callbacks have finished running. Need to introduce a | |
| 100 | + * dmaengine_terminate_all_sync(). | |
| 101 | + */ | |
| 102 | + iio_dma_buffer_block_list_abort(queue, &dmaengine_buffer->active); | |
| 103 | +} | |
| 104 | + | |
| 105 | +static void iio_dmaengine_buffer_release(struct iio_buffer *buf) | |
| 106 | +{ | |
| 107 | + struct dmaengine_buffer *dmaengine_buffer = | |
| 108 | + iio_buffer_to_dmaengine_buffer(buf); | |
| 109 | + | |
| 110 | + iio_dma_buffer_release(&dmaengine_buffer->queue); | |
| 111 | + kfree(dmaengine_buffer); | |
| 112 | +} | |
| 113 | + | |
| 114 | +static const struct iio_buffer_access_funcs iio_dmaengine_buffer_ops = { | |
| 115 | + .read_first_n = iio_dma_buffer_read, | |
| 116 | + .set_bytes_per_datum = iio_dma_buffer_set_bytes_per_datum, | |
| 117 | + .set_length = iio_dma_buffer_set_length, | |
| 118 | + .request_update = iio_dma_buffer_request_update, | |
| 119 | + .enable = iio_dma_buffer_enable, | |
| 120 | + .disable = iio_dma_buffer_disable, | |
| 121 | + .data_available = iio_dma_buffer_data_available, | |
| 122 | + .release = iio_dmaengine_buffer_release, | |
| 123 | + | |
| 124 | + .modes = INDIO_BUFFER_HARDWARE, | |
| 125 | + .flags = INDIO_BUFFER_FLAG_FIXED_WATERMARK, | |
| 126 | +}; | |
| 127 | + | |
| 128 | +static const struct iio_dma_buffer_ops iio_dmaengine_default_ops = { | |
| 129 | + .submit = iio_dmaengine_buffer_submit_block, | |
| 130 | + .abort = iio_dmaengine_buffer_abort, | |
| 131 | +}; | |
| 132 | + | |
| 133 | +/** | |
| 134 | + * iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine | |
| 135 | + * @dev: Parent device for the buffer | |
| 136 | + * @channel: DMA channel name, typically "rx". | |
| 137 | + * | |
| 138 | + * This allocates a new IIO buffer which internally uses the DMAengine framework | |
| 139 | + * to perform its transfers. The parent device will be used to request the DMA | |
| 140 | + * channel. | |
| 141 | + * | |
| 142 | + * Once done using the buffer iio_dmaengine_buffer_free() should be used to | |
| 143 | + * release it. | |
| 144 | + */ | |
| 145 | +struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, | |
| 146 | + const char *channel) | |
| 147 | +{ | |
| 148 | + struct dmaengine_buffer *dmaengine_buffer; | |
| 149 | + unsigned int width, src_width, dest_width; | |
| 150 | + struct dma_slave_caps caps; | |
| 151 | + struct dma_chan *chan; | |
| 152 | + int ret; | |
| 153 | + | |
| 154 | + dmaengine_buffer = kzalloc(sizeof(*dmaengine_buffer), GFP_KERNEL); | |
| 155 | + if (!dmaengine_buffer) | |
| 156 | + return ERR_PTR(-ENOMEM); | |
| 157 | + | |
| 158 | + chan = dma_request_slave_channel_reason(dev, channel); | |
| 159 | + if (IS_ERR(chan)) { | |
| 160 | + ret = PTR_ERR(chan); | |
| 161 | + goto err_free; | |
| 162 | + } | |
| 163 | + | |
| 164 | + ret = dma_get_slave_caps(chan, &caps); | |
| 165 | + if (ret < 0) | |
| 166 | + goto err_free; | |
| 167 | + | |
| 168 | + /* Needs to be aligned to the maximum of the minimums */ | |
| 169 | + if (caps.src_addr_widths) | |
| 170 | + src_width = __ffs(caps.src_addr_widths); | |
| 171 | + else | |
| 172 | + src_width = 1; | |
| 173 | + if (caps.dst_addr_widths) | |
| 174 | + dest_width = __ffs(caps.dst_addr_widths); | |
| 175 | + else | |
| 176 | + dest_width = 1; | |
| 177 | + width = max(src_width, dest_width); | |
| 178 | + | |
| 179 | + INIT_LIST_HEAD(&dmaengine_buffer->active); | |
| 180 | + dmaengine_buffer->chan = chan; | |
| 181 | + dmaengine_buffer->align = width; | |
| 182 | + dmaengine_buffer->max_size = dma_get_max_seg_size(chan->device->dev); | |
| 183 | + | |
| 184 | + iio_dma_buffer_init(&dmaengine_buffer->queue, chan->device->dev, | |
| 185 | + &iio_dmaengine_default_ops); | |
| 186 | + | |
| 187 | + dmaengine_buffer->queue.buffer.access = &iio_dmaengine_buffer_ops; | |
| 188 | + | |
| 189 | + return &dmaengine_buffer->queue.buffer; | |
| 190 | + | |
| 191 | +err_free: | |
| 192 | + kfree(dmaengine_buffer); | |
| 193 | + return ERR_PTR(ret); | |
| 194 | +} | |
| 195 | +EXPORT_SYMBOL(iio_dmaengine_buffer_alloc); | |
| 196 | + | |
| 197 | +/** | |
| 198 | + * iio_dmaengine_buffer_free() - Free dmaengine buffer | |
| 199 | + * @buffer: Buffer to free | |
| 200 | + * | |
| 201 | + * Frees a buffer previously allocated with iio_dmaengine_buffer_alloc(). | |
| 202 | + */ | |
| 203 | +void iio_dmaengine_buffer_free(struct iio_buffer *buffer) | |
| 204 | +{ | |
| 205 | + struct dmaengine_buffer *dmaengine_buffer = | |
| 206 | + iio_buffer_to_dmaengine_buffer(buffer); | |
| 207 | + | |
| 208 | + iio_dma_buffer_exit(&dmaengine_buffer->queue); | |
| 209 | + dma_release_channel(dmaengine_buffer->chan); | |
| 210 | + | |
| 211 | + iio_buffer_put(buffer); | |
| 212 | +} | |
| 213 | +EXPORT_SYMBOL_GPL(iio_dmaengine_buffer_free); | |
| @@ -4,6 +4,14 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | menu "Chemical Sensors" |
| 6 | 6 | |
| 7 | +config IAQCORE | |
| 8 | + tristate "AMS iAQ-Core VOC sensors" | |
| 9 | + depends on I2C | |
| 10 | + help | |
| 11 | + Say Y here to build I2C interface support for the AMS | |
| 12 | + iAQ-Core Continuous/Pulsed VOC (Volatile Organic Compounds) | |
| 13 | + sensors | |
| 14 | + | |
| 7 | 15 | config VZ89X |
| 8 | 16 | tristate "SGX Sensortech MiCS VZ89X VOC sensor" |
| 9 | 17 | depends on I2C |
| @@ -3,4 +3,5 @@ · 2 unmodified lines | ||
| 3 | 3 | # |
| 4 | 4 | |
| 5 | 5 | # When adding new entries keep the list in alphabetical order |
| 6 | +obj-$(CONFIG_IAQCORE) += ams-iaq-core.o | |
| 6 | 7 | obj-$(CONFIG_VZ89X) += vz89x.o |
| @@ -0,0 +1,200 @@ | ||
| 1 | +/* | |
| 2 | + * ams-iaq-core.c - Support for AMS iAQ-Core VOC sensors | |
| 3 | + * | |
| 4 | + * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + */ | |
| 17 | + | |
| 18 | +#include <linux/module.h> | |
| 19 | +#include <linux/mutex.h> | |
| 20 | +#include <linux/init.h> | |
| 21 | +#include <linux/i2c.h> | |
| 22 | +#include <linux/iio/iio.h> | |
| 23 | + | |
| 24 | +#define AMS_IAQCORE_DATA_SIZE 9 | |
| 25 | + | |
| 26 | +#define AMS_IAQCORE_VOC_CO2_IDX 0 | |
| 27 | +#define AMS_IAQCORE_VOC_RESISTANCE_IDX 1 | |
| 28 | +#define AMS_IAQCORE_VOC_TVOC_IDX 2 | |
| 29 | + | |
| 30 | +struct ams_iaqcore_reading { | |
| 31 | + __be16 co2_ppm; | |
| 32 | + u8 status; | |
| 33 | + __be32 resistance; | |
| 34 | + __be16 voc_ppb; | |
| 35 | +} __attribute__((__packed__)); | |
| 36 | + | |
| 37 | +struct ams_iaqcore_data { | |
| 38 | + struct i2c_client *client; | |
| 39 | + struct mutex lock; | |
| 40 | + unsigned long last_update; | |
| 41 | + | |
| 42 | + struct ams_iaqcore_reading buffer; | |
| 43 | +}; | |
| 44 | + | |
| 45 | +static const struct iio_chan_spec ams_iaqcore_channels[] = { | |
| 46 | + { | |
| 47 | + .type = IIO_CONCENTRATION, | |
| 48 | + .channel2 = IIO_MOD_CO2, | |
| 49 | + .modified = 1, | |
| 50 | + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | |
| 51 | + .address = AMS_IAQCORE_VOC_CO2_IDX, | |
| 52 | + }, | |
| 53 | + { | |
| 54 | + .type = IIO_RESISTANCE, | |
| 55 | + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | |
| 56 | + .address = AMS_IAQCORE_VOC_RESISTANCE_IDX, | |
| 57 | + }, | |
| 58 | + { | |
| 59 | + .type = IIO_CONCENTRATION, | |
| 60 | + .channel2 = IIO_MOD_VOC, | |
| 61 | + .modified = 1, | |
| 62 | + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | |
| 63 | + .address = AMS_IAQCORE_VOC_TVOC_IDX, | |
| 64 | + }, | |
| 65 | +}; | |
| 66 | + | |
| 67 | +static int ams_iaqcore_read_measurement(struct ams_iaqcore_data *data) | |
| 68 | +{ | |
| 69 | + struct i2c_client *client = data->client; | |
| 70 | + int ret; | |
| 71 | + | |
| 72 | + struct i2c_msg msg = { | |
| 73 | + .addr = client->addr, | |
| 74 | + .flags = client->flags | I2C_M_RD, | |
| 75 | + .len = AMS_IAQCORE_DATA_SIZE, | |
| 76 | + .buf = (char *) &data->buffer, | |
| 77 | + }; | |
| 78 | + | |
| 79 | + ret = i2c_transfer(client->adapter, &msg, 1); | |
| 80 | + | |
| 81 | + return (ret == AMS_IAQCORE_DATA_SIZE) ? 0 : ret; | |
| 82 | +} | |
| 83 | + | |
| 84 | +static int ams_iaqcore_get_measurement(struct ams_iaqcore_data *data) | |
| 85 | +{ | |
| 86 | + int ret; | |
| 87 | + | |
| 88 | + /* sensor can only be polled once a second max per datasheet */ | |
| 89 | + if (!time_after(jiffies, data->last_update + HZ)) | |
| 90 | + return 0; | |
| 91 | + | |
| 92 | + ret = ams_iaqcore_read_measurement(data); | |
| 93 | + if (ret < 0) | |
| 94 | + return ret; | |
| 95 | + | |
| 96 | + data->last_update = jiffies; | |
| 97 | + | |
| 98 | + return 0; | |
| 99 | +} | |
| 100 | + | |
| 101 | +static int ams_iaqcore_read_raw(struct iio_dev *indio_dev, | |
| 102 | + struct iio_chan_spec const *chan, int *val, | |
| 103 | + int *val2, long mask) | |
| 104 | +{ | |
| 105 | + struct ams_iaqcore_data *data = iio_priv(indio_dev); | |
| 106 | + int ret; | |
| 107 | + | |
| 108 | + if (mask != IIO_CHAN_INFO_PROCESSED) | |
| 109 | + return -EINVAL; | |
| 110 | + | |
| 111 | + mutex_lock(&data->lock); | |
| 112 | + ret = ams_iaqcore_get_measurement(data); | |
| 113 | + | |
| 114 | + if (ret) | |
| 115 | + goto err_out; | |
| 116 | + | |
| 117 | + switch (chan->address) { | |
| 118 | + case AMS_IAQCORE_VOC_CO2_IDX: | |
| 119 | + *val = 0; | |
| 120 | + *val2 = be16_to_cpu(data->buffer.co2_ppm); | |
| 121 | + ret = IIO_VAL_INT_PLUS_MICRO; | |
| 122 | + break; | |
| 123 | + case AMS_IAQCORE_VOC_RESISTANCE_IDX: | |
| 124 | + *val = be32_to_cpu(data->buffer.resistance); | |
| 125 | + ret = IIO_VAL_INT; | |
| 126 | + break; | |
| 127 | + case AMS_IAQCORE_VOC_TVOC_IDX: | |
| 128 | + *val = 0; | |
| 129 | + *val2 = be16_to_cpu(data->buffer.voc_ppb); | |
| 130 | + ret = IIO_VAL_INT_PLUS_NANO; | |
| 131 | + break; | |
| 132 | + default: | |
| 133 | + ret = -EINVAL; | |
| 134 | + } | |
| 135 | + | |
| 136 | +err_out: | |
| 137 | + mutex_unlock(&data->lock); | |
| 138 | + | |
| 139 | + return ret; | |
| 140 | +} | |
| 141 | + | |
| 142 | +static const struct iio_info ams_iaqcore_info = { | |
| 143 | + .read_raw = ams_iaqcore_read_raw, | |
| 144 | + .driver_module = THIS_MODULE, | |
| 145 | +}; | |
| 146 | + | |
| 147 | +static int ams_iaqcore_probe(struct i2c_client *client, | |
| 148 | + const struct i2c_device_id *id) | |
| 149 | +{ | |
| 150 | + struct iio_dev *indio_dev; | |
| 151 | + struct ams_iaqcore_data *data; | |
| 152 | + | |
| 153 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 154 | + if (!indio_dev) | |
| 155 | + return -ENOMEM; | |
| 156 | + | |
| 157 | + data = iio_priv(indio_dev); | |
| 158 | + i2c_set_clientdata(client, indio_dev); | |
| 159 | + data->client = client; | |
| 160 | + | |
| 161 | + /* so initial reading will complete */ | |
| 162 | + data->last_update = jiffies - HZ; | |
| 163 | + mutex_init(&data->lock); | |
| 164 | + | |
| 165 | + indio_dev->dev.parent = &client->dev; | |
| 166 | + indio_dev->info = &ams_iaqcore_info, | |
| 167 | + indio_dev->name = dev_name(&client->dev); | |
| 168 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 169 | + | |
| 170 | + indio_dev->channels = ams_iaqcore_channels; | |
| 171 | + indio_dev->num_channels = ARRAY_SIZE(ams_iaqcore_channels); | |
| 172 | + | |
| 173 | + return devm_iio_device_register(&client->dev, indio_dev); | |
| 174 | +} | |
| 175 | + | |
| 176 | +static const struct i2c_device_id ams_iaqcore_id[] = { | |
| 177 | + { "ams-iaq-core", 0 }, | |
| 178 | + { } | |
| 179 | +}; | |
| 180 | +MODULE_DEVICE_TABLE(i2c, ams_iaqcore_id); | |
| 181 | + | |
| 182 | +static const struct of_device_id ams_iaqcore_dt_ids[] = { | |
| 183 | + { .compatible = "ams,iaq-core" }, | |
| 184 | + { } | |
| 185 | +}; | |
| 186 | +MODULE_DEVICE_TABLE(of, ams_iaqcore_dt_ids); | |
| 187 | + | |
| 188 | +static struct i2c_driver ams_iaqcore_driver = { | |
| 189 | + .driver = { | |
| 190 | + .name = "ams-iaq-core", | |
| 191 | + .of_match_table = of_match_ptr(ams_iaqcore_dt_ids), | |
| 192 | + }, | |
| 193 | + .probe = ams_iaqcore_probe, | |
| 194 | + .id_table = ams_iaqcore_id, | |
| 195 | +}; | |
| 196 | +module_i2c_driver(ams_iaqcore_driver); | |
| 197 | + | |
| 198 | +MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); | |
| 199 | +MODULE_DESCRIPTION("AMS iAQ-Core VOC sensors"); | |
| 200 | +MODULE_LICENSE("GPL v2"); | |
| @@ -34,8 +34,9 @@ · 33 unmodified lines | ||
| 34 | 34 | struct vz89x_data { |
| 35 | 35 | struct i2c_client *client; |
| 36 | 36 | struct mutex lock; |
| 37 | − unsigned long last_update; | |
| 37 | + int (*xfer)(struct vz89x_data *data, u8 cmd); | |
| 38 | 38 | |
| 39 | + unsigned long last_update; | |
| 39 | 40 | u8 buffer[VZ89X_REG_MEASUREMENT_SIZE]; |
| 40 | 41 | }; |
| 41 | 42 | |
| @@ -100,27 +101,60 @@ static int vz89x_measurement_is_valid(struct vz89x_data *data) · 58 unmodified lines | ||
| 100 | 101 | return !!(data->buffer[VZ89X_REG_MEASUREMENT_SIZE - 1] > 0); |
| 101 | 102 | } |
| 102 | 103 | |
| 103 | −static int vz89x_get_measurement(struct vz89x_data *data) | |
| 104 | +static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd) | |
| 104 | 105 | { |
| 106 | + struct i2c_client *client = data->client; | |
| 107 | + struct i2c_msg msg[2]; | |
| 105 | 108 | int ret; |
| 106 | − int i; | |
| 109 | + u8 buf[3] = { cmd, 0, 0}; | |
| 107 | 110 | |
| 108 | − /* sensor can only be polled once a second max per datasheet */ | |
| 109 | − if (!time_after(jiffies, data->last_update + HZ)) | |
| 110 | − return 0; | |
| 111 | + msg[0].addr = client->addr; | |
| 112 | + msg[0].flags = client->flags; | |
| 113 | + msg[0].len = 3; | |
| 114 | + msg[0].buf = (char *) &buf; | |
| 115 | + | |
| 116 | + msg[1].addr = client->addr; | |
| 117 | + msg[1].flags = client->flags | I2C_M_RD; | |
| 118 | + msg[1].len = VZ89X_REG_MEASUREMENT_SIZE; | |
| 119 | + msg[1].buf = (char *) &data->buffer; | |
| 120 | + | |
| 121 | + ret = i2c_transfer(client->adapter, msg, 2); | |
| 111 | 122 | |
| 112 | − ret = i2c_smbus_write_word_data(data->client, | |
| 113 | − VZ89X_REG_MEASUREMENT, 0); | |
| 123 | + return (ret == 2) ? 0 : ret; | |
| 124 | +} | |
| 125 | + | |
| 126 | +static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd) | |
| 127 | +{ | |
| 128 | + struct i2c_client *client = data->client; | |
| 129 | + int ret; | |
| 130 | + int i; | |
| 131 | + | |
| 132 | + ret = i2c_smbus_write_word_data(client, cmd, 0); | |
| 114 | 133 | if (ret < 0) |
| 115 | 134 | return ret; |
| 116 | 135 | |
| 117 | 136 | for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) { |
| 118 | − ret = i2c_smbus_read_byte(data->client); | |
| 137 | + ret = i2c_smbus_read_byte(client); | |
| 119 | 138 | if (ret < 0) |
| 120 | 139 | return ret; |
| 121 | 140 | data->buffer[i] = ret; |
| 122 | 141 | } |
| 123 | 142 | |
| 143 | + return 0; | |
| 144 | +} | |
| 145 | + | |
| 146 | +static int vz89x_get_measurement(struct vz89x_data *data) | |
| 147 | +{ | |
| 148 | + int ret; | |
| 149 | + | |
| 150 | + /* sensor can only be polled once a second max per datasheet */ | |
| 151 | + if (!time_after(jiffies, data->last_update + HZ)) | |
| 152 | + return 0; | |
| 153 | + | |
| 154 | + ret = data->xfer(data, VZ89X_REG_MEASUREMENT); | |
| 155 | + if (ret < 0) | |
| 156 | + return ret; | |
| 157 | + | |
| 124 | 158 | ret = vz89x_measurement_is_valid(data); |
| 125 | 159 | if (ret) |
| 126 | 160 | return -EAGAIN; |
| @@ -204,15 +238,19 @@ static int vz89x_probe(struct i2c_client *client, · 77 unmodified lines | ||
| 204 | 238 | struct iio_dev *indio_dev; |
| 205 | 239 | struct vz89x_data *data; |
| 206 | 240 | |
| 207 | − if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA | | |
| 208 | − I2C_FUNC_SMBUS_BYTE)) | |
| 209 | − return -ENODEV; | |
| 210 | − | |
| 211 | 241 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
| 212 | 242 | if (!indio_dev) |
| 213 | 243 | return -ENOMEM; |
| 214 | − | |
| 215 | 244 | data = iio_priv(indio_dev); |
| 245 | + | |
| 246 | + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | |
| 247 | + data->xfer = vz89x_i2c_xfer; | |
| 248 | + else if (i2c_check_functionality(client->adapter, | |
| 249 | + I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE)) | |
| 250 | + data->xfer = vz89x_smbus_xfer; | |
| 251 | + else | |
| 252 | + return -ENOTSUPP; | |
| 253 | + | |
| 216 | 254 | i2c_set_clientdata(client, indio_dev); |
| 217 | 255 | data->client = client; |
| 218 | 256 | data->last_update = jiffies - HZ; |
| @@ -18,9 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <asm/unaligned.h> |
| 19 | 19 | #include <linux/iio/common/st_sensors.h> |
| 20 | 20 | |
| 21 | − | |
| 22 | −#define ST_SENSORS_WAI_ADDRESS 0x0f | |
| 23 | − | |
| 24 | 21 | static inline u32 st_sensors_get_unaligned_le24(const u8 *p) |
| 25 | 22 | { |
| 26 | 23 | return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8; |
| @@ -0,0 +1,36 @@ | ||
| 1 | +# | |
| 2 | +# Industrial I/O subsystem Dummy Driver configuration | |
| 3 | +# | |
| 4 | +menu "IIO dummy driver" | |
| 5 | + depends on IIO | |
| 6 | + | |
| 7 | +config IIO_DUMMY_EVGEN | |
| 8 | + select IRQ_WORK | |
| 9 | + tristate | |
| 10 | + | |
| 11 | +config IIO_SIMPLE_DUMMY | |
| 12 | + tristate "An example driver with no hardware requirements" | |
| 13 | + help | |
| 14 | + Driver intended mainly as documentation for how to write | |
| 15 | + a driver. May also be useful for testing userspace code | |
| 16 | + without hardware. | |
| 17 | + | |
| 18 | +if IIO_SIMPLE_DUMMY | |
| 19 | + | |
| 20 | +config IIO_SIMPLE_DUMMY_EVENTS | |
| 21 | + bool "Event generation support" | |
| 22 | + select IIO_DUMMY_EVGEN | |
| 23 | + help | |
| 24 | + Add some dummy events to the simple dummy driver. | |
| 25 | + | |
| 26 | +config IIO_SIMPLE_DUMMY_BUFFER | |
| 27 | + bool "Buffered capture support" | |
| 28 | + select IIO_BUFFER | |
| 29 | + select IIO_TRIGGER | |
| 30 | + select IIO_KFIFO_BUF | |
| 31 | + help | |
| 32 | + Add buffered data capture to the simple dummy driver. | |
| 33 | + | |
| 34 | +endif # IIO_SIMPLE_DUMMY | |
| 35 | + | |
| 36 | +endmenu | |
| @@ -0,0 +1,10 @@ | ||
| 1 | +# | |
| 2 | +# Makefile for the IIO Dummy Driver | |
| 3 | +# | |
| 4 | + | |
| 5 | +obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o | |
| 6 | +iio_dummy-y := iio_simple_dummy.o | |
| 7 | +iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_EVENTS) += iio_simple_dummy_events.o | |
| 8 | +iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o | |
| 9 | + | |
| 10 | +obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o | |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
| @@ -435,7 +435,9 @@ static int adis16136_initial_setup(struct iio_dev *indio_dev) · 434 unmodified lines | ||
| 435 | 435 | if (ret) |
| 436 | 436 | return ret; |
| 437 | 437 | |
| 438 | − sscanf(indio_dev->name, "adis%u\n", &device_id); | |
| 438 | + ret = sscanf(indio_dev->name, "adis%u\n", &device_id); | |
| 439 | + if (ret != 1) | |
| 440 | + return -EINVAL; | |
| 439 | 441 | |
| 440 | 442 | if (prod_id != device_id) |
| 441 | 443 | dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", |
| @@ -1077,25 +1077,23 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, · 1076 unmodified lines | ||
| 1077 | 1077 | goto err_trigger_unregister; |
| 1078 | 1078 | } |
| 1079 | 1079 | |
| 1080 | − ret = iio_device_register(indio_dev); | |
| 1081 | − if (ret < 0) { | |
| 1082 | − dev_err(dev, "unable to register iio device\n"); | |
| 1083 | − goto err_buffer_cleanup; | |
| 1084 | − } | |
| 1085 | − | |
| 1086 | 1080 | ret = pm_runtime_set_active(dev); |
| 1087 | 1081 | if (ret) |
| 1088 | − goto err_iio_unregister; | |
| 1082 | + goto err_buffer_cleanup; | |
| 1089 | 1083 | |
| 1090 | 1084 | pm_runtime_enable(dev); |
| 1091 | 1085 | pm_runtime_set_autosuspend_delay(dev, |
| 1092 | 1086 | BMG160_AUTO_SUSPEND_DELAY_MS); |
| 1093 | 1087 | pm_runtime_use_autosuspend(dev); |
| 1094 | 1088 | |
| 1089 | + ret = iio_device_register(indio_dev); | |
| 1090 | + if (ret < 0) { | |
| 1091 | + dev_err(dev, "unable to register iio device\n"); | |
| 1092 | + goto err_buffer_cleanup; | |
| 1093 | + } | |
| 1094 | + | |
| 1095 | 1095 | return 0; |
| 1096 | 1096 | |
| 1097 | −err_iio_unregister: | |
| 1098 | − iio_device_unregister(indio_dev); | |
| 1099 | 1097 | err_buffer_cleanup: |
| 1100 | 1098 | iio_triggered_buffer_cleanup(indio_dev); |
| 1101 | 1099 | err_trigger_unregister: |
| @@ -1113,11 +1111,12 @@ void bmg160_core_remove(struct device *dev) · 11 unmodified lines | ||
| 1113 | 1111 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
| 1114 | 1112 | struct bmg160_data *data = iio_priv(indio_dev); |
| 1115 | 1113 | |
| 1114 | + iio_device_unregister(indio_dev); | |
| 1115 | + | |
| 1116 | 1116 | pm_runtime_disable(dev); |
| 1117 | 1117 | pm_runtime_set_suspended(dev); |
| 1118 | 1118 | pm_runtime_put_noidle(dev); |
| 1119 | 1119 | |
| 1120 | − iio_device_unregister(indio_dev); | |
| 1121 | 1120 | iio_triggered_buffer_cleanup(indio_dev); |
| 1122 | 1121 | |
| 1123 | 1122 | if (data->dready_trig) { |
| @@ -0,0 +1,21 @@ | ||
| 1 | +# | |
| 2 | +# Health sensors | |
| 3 | +# | |
| 4 | +# When adding new entries keep the list in alphabetical order | |
| 5 | + | |
| 6 | +menu "Health sensors" | |
| 7 | + | |
| 8 | +config MAX30100 | |
| 9 | + tristate "MAX30100 heart rate and pulse oximeter sensor" | |
| 10 | + depends on I2C | |
| 11 | + select REGMAP_I2C | |
| 12 | + select IIO_BUFFER | |
| 13 | + select IIO_KFIFO_BUF | |
| 14 | + help | |
| 15 | + Say Y here to build I2C interface support for the Maxim | |
| 16 | + MAX30100 heart rate, and pulse oximeter sensor. | |
| 17 | + | |
| 18 | + To compile this driver as a module, choose M here: the | |
| 19 | + module will be called max30100. | |
| 20 | + | |
| 21 | +endmenu | |
| @@ -0,0 +1,7 @@ | ||
| 1 | +# | |
| 2 | +# Makefile for IIO Health sensors | |
| 3 | +# | |
| 4 | + | |
| 5 | +# When adding new entries keep the list in alphabetical order | |
| 6 | + | |
| 7 | +obj-$(CONFIG_MAX30100) += max30100.o | |
| @@ -0,0 +1,453 @@ | ||
| 1 | +/* | |
| 2 | + * max30100.c - Support for MAX30100 heart rate and pulse oximeter sensor | |
| 3 | + * | |
| 4 | + * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * TODO: allow LED current and pulse length controls via device tree properties | |
| 17 | + */ | |
| 18 | + | |
| 19 | +#include <linux/module.h> | |
| 20 | +#include <linux/init.h> | |
| 21 | +#include <linux/interrupt.h> | |
| 22 | +#include <linux/delay.h> | |
| 23 | +#include <linux/err.h> | |
| 24 | +#include <linux/irq.h> | |
| 25 | +#include <linux/i2c.h> | |
| 26 | +#include <linux/mutex.h> | |
| 27 | +#include <linux/regmap.h> | |
| 28 | +#include <linux/iio/iio.h> | |
| 29 | +#include <linux/iio/buffer.h> | |
| 30 | +#include <linux/iio/kfifo_buf.h> | |
| 31 | + | |
| 32 | +#define MAX30100_REGMAP_NAME "max30100_regmap" | |
| 33 | +#define MAX30100_DRV_NAME "max30100" | |
| 34 | + | |
| 35 | +#define MAX30100_REG_INT_STATUS 0x00 | |
| 36 | +#define MAX30100_REG_INT_STATUS_PWR_RDY BIT(0) | |
| 37 | +#define MAX30100_REG_INT_STATUS_SPO2_RDY BIT(4) | |
| 38 | +#define MAX30100_REG_INT_STATUS_HR_RDY BIT(5) | |
| 39 | +#define MAX30100_REG_INT_STATUS_FIFO_RDY BIT(7) | |
| 40 | + | |
| 41 | +#define MAX30100_REG_INT_ENABLE 0x01 | |
| 42 | +#define MAX30100_REG_INT_ENABLE_SPO2_EN BIT(0) | |
| 43 | +#define MAX30100_REG_INT_ENABLE_HR_EN BIT(1) | |
| 44 | +#define MAX30100_REG_INT_ENABLE_FIFO_EN BIT(3) | |
| 45 | +#define MAX30100_REG_INT_ENABLE_MASK 0xf0 | |
| 46 | +#define MAX30100_REG_INT_ENABLE_MASK_SHIFT 4 | |
| 47 | + | |
| 48 | +#define MAX30100_REG_FIFO_WR_PTR 0x02 | |
| 49 | +#define MAX30100_REG_FIFO_OVR_CTR 0x03 | |
| 50 | +#define MAX30100_REG_FIFO_RD_PTR 0x04 | |
| 51 | +#define MAX30100_REG_FIFO_DATA 0x05 | |
| 52 | +#define MAX30100_REG_FIFO_DATA_ENTRY_COUNT 16 | |
| 53 | +#define MAX30100_REG_FIFO_DATA_ENTRY_LEN 4 | |
| 54 | + | |
| 55 | +#define MAX30100_REG_MODE_CONFIG 0x06 | |
| 56 | +#define MAX30100_REG_MODE_CONFIG_MODE_SPO2_EN BIT(0) | |
| 57 | +#define MAX30100_REG_MODE_CONFIG_MODE_HR_EN BIT(1) | |
| 58 | +#define MAX30100_REG_MODE_CONFIG_MODE_MASK 0x03 | |
| 59 | +#define MAX30100_REG_MODE_CONFIG_TEMP_EN BIT(3) | |
| 60 | +#define MAX30100_REG_MODE_CONFIG_PWR BIT(7) | |
| 61 | + | |
| 62 | +#define MAX30100_REG_SPO2_CONFIG 0x07 | |
| 63 | +#define MAX30100_REG_SPO2_CONFIG_100HZ BIT(2) | |
| 64 | +#define MAX30100_REG_SPO2_CONFIG_HI_RES_EN BIT(6) | |
| 65 | +#define MAX30100_REG_SPO2_CONFIG_1600US 0x3 | |
| 66 | + | |
| 67 | +#define MAX30100_REG_LED_CONFIG 0x09 | |
| 68 | +#define MAX30100_REG_LED_CONFIG_RED_LED_SHIFT 4 | |
| 69 | + | |
| 70 | +#define MAX30100_REG_LED_CONFIG_24MA 0x07 | |
| 71 | +#define MAX30100_REG_LED_CONFIG_50MA 0x0f | |
| 72 | + | |
| 73 | +#define MAX30100_REG_TEMP_INTEGER 0x16 | |
| 74 | +#define MAX30100_REG_TEMP_FRACTION 0x17 | |
| 75 | + | |
| 76 | +struct max30100_data { | |
| 77 | + struct i2c_client *client; | |
| 78 | + struct iio_dev *indio_dev; | |
| 79 | + struct mutex lock; | |
| 80 | + struct regmap *regmap; | |
| 81 | + | |
| 82 | + __be16 buffer[2]; /* 2 16-bit channels */ | |
| 83 | +}; | |
| 84 | + | |
| 85 | +static bool max30100_is_volatile_reg(struct device *dev, unsigned int reg) | |
| 86 | +{ | |
| 87 | + switch (reg) { | |
| 88 | + case MAX30100_REG_INT_STATUS: | |
| 89 | + case MAX30100_REG_MODE_CONFIG: | |
| 90 | + case MAX30100_REG_FIFO_WR_PTR: | |
| 91 | + case MAX30100_REG_FIFO_OVR_CTR: | |
| 92 | + case MAX30100_REG_FIFO_RD_PTR: | |
| 93 | + case MAX30100_REG_FIFO_DATA: | |
| 94 | + case MAX30100_REG_TEMP_INTEGER: | |
| 95 | + case MAX30100_REG_TEMP_FRACTION: | |
| 96 | + return true; | |
| 97 | + default: | |
| 98 | + return false; | |
| 99 | + } | |
| 100 | +} | |
| 101 | + | |
| 102 | +static const struct regmap_config max30100_regmap_config = { | |
| 103 | + .name = MAX30100_REGMAP_NAME, | |
| 104 | + | |
| 105 | + .reg_bits = 8, | |
| 106 | + .val_bits = 8, | |
| 107 | + | |
| 108 | + .max_register = MAX30100_REG_TEMP_FRACTION, | |
| 109 | + .cache_type = REGCACHE_FLAT, | |
| 110 | + | |
| 111 | + .volatile_reg = max30100_is_volatile_reg, | |
| 112 | +}; | |
| 113 | + | |
| 114 | +static const unsigned long max30100_scan_masks[] = {0x3, 0}; | |
| 115 | + | |
| 116 | +static const struct iio_chan_spec max30100_channels[] = { | |
| 117 | + { | |
| 118 | + .type = IIO_INTENSITY, | |
| 119 | + .channel2 = IIO_MOD_LIGHT_IR, | |
| 120 | + .modified = 1, | |
| 121 | + | |
| 122 | + .scan_index = 0, | |
| 123 | + .scan_type = { | |
| 124 | + .sign = 'u', | |
| 125 | + .realbits = 16, | |
| 126 | + .storagebits = 16, | |
| 127 | + .endianness = IIO_BE, | |
| 128 | + }, | |
| 129 | + }, | |
| 130 | + { | |
| 131 | + .type = IIO_INTENSITY, | |
| 132 | + .channel2 = IIO_MOD_LIGHT_RED, | |
| 133 | + .modified = 1, | |
| 134 | + | |
| 135 | + .scan_index = 1, | |
| 136 | + .scan_type = { | |
| 137 | + .sign = 'u', | |
| 138 | + .realbits = 16, | |
| 139 | + .storagebits = 16, | |
| 140 | + .endianness = IIO_BE, | |
| 141 | + }, | |
| 142 | + }, | |
| 143 | + { | |
| 144 | + .type = IIO_TEMP, | |
| 145 | + .info_mask_separate = | |
| 146 | + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | |
| 147 | + .scan_index = -1, | |
| 148 | + }, | |
| 149 | +}; | |
| 150 | + | |
| 151 | +static int max30100_set_powermode(struct max30100_data *data, bool state) | |
| 152 | +{ | |
| 153 | + return regmap_update_bits(data->regmap, MAX30100_REG_MODE_CONFIG, | |
| 154 | + MAX30100_REG_MODE_CONFIG_PWR, | |
| 155 | + state ? 0 : MAX30100_REG_MODE_CONFIG_PWR); | |
| 156 | +} | |
| 157 | + | |
| 158 | +static int max30100_clear_fifo(struct max30100_data *data) | |
| 159 | +{ | |
| 160 | + int ret; | |
| 161 | + | |
| 162 | + ret = regmap_write(data->regmap, MAX30100_REG_FIFO_WR_PTR, 0); | |
| 163 | + if (ret) | |
| 164 | + return ret; | |
| 165 | + | |
| 166 | + ret = regmap_write(data->regmap, MAX30100_REG_FIFO_OVR_CTR, 0); | |
| 167 | + if (ret) | |
| 168 | + return ret; | |
| 169 | + | |
| 170 | + return regmap_write(data->regmap, MAX30100_REG_FIFO_RD_PTR, 0); | |
| 171 | +} | |
| 172 | + | |
| 173 | +static int max30100_buffer_postenable(struct iio_dev *indio_dev) | |
| 174 | +{ | |
| 175 | + struct max30100_data *data = iio_priv(indio_dev); | |
| 176 | + int ret; | |
| 177 | + | |
| 178 | + ret = max30100_set_powermode(data, true); | |
| 179 | + if (ret) | |
| 180 | + return ret; | |
| 181 | + | |
| 182 | + return max30100_clear_fifo(data); | |
| 183 | +} | |
| 184 | + | |
| 185 | +static int max30100_buffer_predisable(struct iio_dev *indio_dev) | |
| 186 | +{ | |
| 187 | + struct max30100_data *data = iio_priv(indio_dev); | |
| 188 | + | |
| 189 | + return max30100_set_powermode(data, false); | |
| 190 | +} | |
| 191 | + | |
| 192 | +static const struct iio_buffer_setup_ops max30100_buffer_setup_ops = { | |
| 193 | + .postenable = max30100_buffer_postenable, | |
| 194 | + .predisable = max30100_buffer_predisable, | |
| 195 | +}; | |
| 196 | + | |
| 197 | +static inline int max30100_fifo_count(struct max30100_data *data) | |
| 198 | +{ | |
| 199 | + unsigned int val; | |
| 200 | + int ret; | |
| 201 | + | |
| 202 | + ret = regmap_read(data->regmap, MAX30100_REG_INT_STATUS, &val); | |
| 203 | + if (ret) | |
| 204 | + return ret; | |
| 205 | + | |
| 206 | + /* FIFO is almost full */ | |
| 207 | + if (val & MAX30100_REG_INT_STATUS_FIFO_RDY) | |
| 208 | + return MAX30100_REG_FIFO_DATA_ENTRY_COUNT - 1; | |
| 209 | + | |
| 210 | + return 0; | |
| 211 | +} | |
| 212 | + | |
| 213 | +static int max30100_read_measurement(struct max30100_data *data) | |
| 214 | +{ | |
| 215 | + int ret; | |
| 216 | + | |
| 217 | + ret = i2c_smbus_read_i2c_block_data(data->client, | |
| 218 | + MAX30100_REG_FIFO_DATA, | |
| 219 | + MAX30100_REG_FIFO_DATA_ENTRY_LEN, | |
| 220 | + (u8 *) &data->buffer); | |
| 221 | + | |
| 222 | + return (ret == MAX30100_REG_FIFO_DATA_ENTRY_LEN) ? 0 : ret; | |
| 223 | +} | |
| 224 | + | |
| 225 | +static irqreturn_t max30100_interrupt_handler(int irq, void *private) | |
| 226 | +{ | |
| 227 | + struct iio_dev *indio_dev = private; | |
| 228 | + struct max30100_data *data = iio_priv(indio_dev); | |
| 229 | + int ret, cnt = 0; | |
| 230 | + | |
| 231 | + mutex_lock(&data->lock); | |
| 232 | + | |
| 233 | + while (cnt-- || (cnt = max30100_fifo_count(data) > 0)) { | |
| 234 | + ret = max30100_read_measurement(data); | |
| 235 | + if (ret) | |
| 236 | + break; | |
| 237 | + | |
| 238 | + iio_push_to_buffers(data->indio_dev, data->buffer); | |
| 239 | + } | |
| 240 | + | |
| 241 | + mutex_unlock(&data->lock); | |
| 242 | + | |
| 243 | + return IRQ_HANDLED; | |
| 244 | +} | |
| 245 | + | |
| 246 | +static int max30100_chip_init(struct max30100_data *data) | |
| 247 | +{ | |
| 248 | + int ret; | |
| 249 | + | |
| 250 | + /* RED IR LED = 24mA, IR LED = 50mA */ | |
| 251 | + ret = regmap_write(data->regmap, MAX30100_REG_LED_CONFIG, | |
| 252 | + (MAX30100_REG_LED_CONFIG_24MA << | |
| 253 | + MAX30100_REG_LED_CONFIG_RED_LED_SHIFT) | | |
| 254 | + MAX30100_REG_LED_CONFIG_50MA); | |
| 255 | + if (ret) | |
| 256 | + return ret; | |
| 257 | + | |
| 258 | + /* enable hi-res SPO2 readings at 100Hz */ | |
| 259 | + ret = regmap_write(data->regmap, MAX30100_REG_SPO2_CONFIG, | |
| 260 | + MAX30100_REG_SPO2_CONFIG_HI_RES_EN | | |
| 261 | + MAX30100_REG_SPO2_CONFIG_100HZ); | |
| 262 | + if (ret) | |
| 263 | + return ret; | |
| 264 | + | |
| 265 | + /* enable SPO2 mode */ | |
| 266 | + ret = regmap_update_bits(data->regmap, MAX30100_REG_MODE_CONFIG, | |
| 267 | + MAX30100_REG_MODE_CONFIG_MODE_MASK, | |
| 268 | + MAX30100_REG_MODE_CONFIG_MODE_HR_EN | | |
| 269 | + MAX30100_REG_MODE_CONFIG_MODE_SPO2_EN); | |
| 270 | + if (ret) | |
| 271 | + return ret; | |
| 272 | + | |
| 273 | + /* enable FIFO interrupt */ | |
| 274 | + return regmap_update_bits(data->regmap, MAX30100_REG_INT_ENABLE, | |
| 275 | + MAX30100_REG_INT_ENABLE_MASK, | |
| 276 | + MAX30100_REG_INT_ENABLE_FIFO_EN | |
| 277 | + << MAX30100_REG_INT_ENABLE_MASK_SHIFT); | |
| 278 | +} | |
| 279 | + | |
| 280 | +static int max30100_read_temp(struct max30100_data *data, int *val) | |
| 281 | +{ | |
| 282 | + int ret; | |
| 283 | + unsigned int reg; | |
| 284 | + | |
| 285 | + ret = regmap_read(data->regmap, MAX30100_REG_TEMP_INTEGER, ®); | |
| 286 | + if (ret < 0) | |
| 287 | + return ret; | |
| 288 | + *val = reg << 4; | |
| 289 | + | |
| 290 | + ret = regmap_read(data->regmap, MAX30100_REG_TEMP_FRACTION, ®); | |
| 291 | + if (ret < 0) | |
| 292 | + return ret; | |
| 293 | + | |
| 294 | + *val |= reg & 0xf; | |
| 295 | + *val = sign_extend32(*val, 11); | |
| 296 | + | |
| 297 | + return 0; | |
| 298 | +} | |
| 299 | + | |
| 300 | +static int max30100_get_temp(struct max30100_data *data, int *val) | |
| 301 | +{ | |
| 302 | + int ret; | |
| 303 | + | |
| 304 | + /* start acquisition */ | |
| 305 | + ret = regmap_update_bits(data->regmap, MAX30100_REG_MODE_CONFIG, | |
| 306 | + MAX30100_REG_MODE_CONFIG_TEMP_EN, | |
| 307 | + MAX30100_REG_MODE_CONFIG_TEMP_EN); | |
| 308 | + if (ret) | |
| 309 | + return ret; | |
| 310 | + | |
| 311 | + usleep_range(35000, 50000); | |
| 312 | + | |
| 313 | + return max30100_read_temp(data, val); | |
| 314 | +} | |
| 315 | + | |
| 316 | +static int max30100_read_raw(struct iio_dev *indio_dev, | |
| 317 | + struct iio_chan_spec const *chan, | |
| 318 | + int *val, int *val2, long mask) | |
| 319 | +{ | |
| 320 | + struct max30100_data *data = iio_priv(indio_dev); | |
| 321 | + int ret = -EINVAL; | |
| 322 | + | |
| 323 | + switch (mask) { | |
| 324 | + case IIO_CHAN_INFO_RAW: | |
| 325 | + /* | |
| 326 | + * Temperature reading can only be acquired while engine | |
| 327 | + * is running | |
| 328 | + */ | |
| 329 | + mutex_lock(&indio_dev->mlock); | |
| 330 | + | |
| 331 | + if (!iio_buffer_enabled(indio_dev)) | |
| 332 | + ret = -EAGAIN; | |
| 333 | + else { | |
| 334 | + ret = max30100_get_temp(data, val); | |
| 335 | + if (!ret) | |
| 336 | + ret = IIO_VAL_INT; | |
| 337 | + | |
| 338 | + } | |
| 339 | + | |
| 340 | + mutex_unlock(&indio_dev->mlock); | |
| 341 | + break; | |
| 342 | + case IIO_CHAN_INFO_SCALE: | |
| 343 | + *val = 1; /* 0.0625 */ | |
| 344 | + *val2 = 16; | |
| 345 | + ret = IIO_VAL_FRACTIONAL; | |
| 346 | + break; | |
| 347 | + } | |
| 348 | + | |
| 349 | + return ret; | |
| 350 | +} | |
| 351 | + | |
| 352 | +static const struct iio_info max30100_info = { | |
| 353 | + .driver_module = THIS_MODULE, | |
| 354 | + .read_raw = max30100_read_raw, | |
| 355 | +}; | |
| 356 | + | |
| 357 | +static int max30100_probe(struct i2c_client *client, | |
| 358 | + const struct i2c_device_id *id) | |
| 359 | +{ | |
| 360 | + struct max30100_data *data; | |
| 361 | + struct iio_buffer *buffer; | |
| 362 | + struct iio_dev *indio_dev; | |
| 363 | + int ret; | |
| 364 | + | |
| 365 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 366 | + if (!indio_dev) | |
| 367 | + return -ENOMEM; | |
| 368 | + | |
| 369 | + buffer = devm_iio_kfifo_allocate(&client->dev); | |
| 370 | + if (!buffer) | |
| 371 | + return -ENOMEM; | |
| 372 | + | |
| 373 | + iio_device_attach_buffer(indio_dev, buffer); | |
| 374 | + | |
| 375 | + indio_dev->name = MAX30100_DRV_NAME; | |
| 376 | + indio_dev->channels = max30100_channels; | |
| 377 | + indio_dev->info = &max30100_info; | |
| 378 | + indio_dev->num_channels = ARRAY_SIZE(max30100_channels); | |
| 379 | + indio_dev->available_scan_masks = max30100_scan_masks; | |
| 380 | + indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); | |
| 381 | + indio_dev->setup_ops = &max30100_buffer_setup_ops; | |
| 382 | + | |
| 383 | + data = iio_priv(indio_dev); | |
| 384 | + data->indio_dev = indio_dev; | |
| 385 | + data->client = client; | |
| 386 | + | |
| 387 | + mutex_init(&data->lock); | |
| 388 | + i2c_set_clientdata(client, indio_dev); | |
| 389 | + | |
| 390 | + data->regmap = devm_regmap_init_i2c(client, &max30100_regmap_config); | |
| 391 | + if (IS_ERR(data->regmap)) { | |
| 392 | + dev_err(&client->dev, "regmap initialization failed.\n"); | |
| 393 | + return PTR_ERR(data->regmap); | |
| 394 | + } | |
| 395 | + max30100_set_powermode(data, false); | |
| 396 | + | |
| 397 | + ret = max30100_chip_init(data); | |
| 398 | + if (ret) | |
| 399 | + return ret; | |
| 400 | + | |
| 401 | + if (client->irq <= 0) { | |
| 402 | + dev_err(&client->dev, "no valid irq defined\n"); | |
| 403 | + return -EINVAL; | |
| 404 | + } | |
| 405 | + ret = devm_request_threaded_irq(&client->dev, client->irq, | |
| 406 | + NULL, max30100_interrupt_handler, | |
| 407 | + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | |
| 408 | + "max30100_irq", indio_dev); | |
| 409 | + if (ret) { | |
| 410 | + dev_err(&client->dev, "request irq (%d) failed\n", client->irq); | |
| 411 | + return ret; | |
| 412 | + } | |
| 413 | + | |
| 414 | + return iio_device_register(indio_dev); | |
| 415 | +} | |
| 416 | + | |
| 417 | +static int max30100_remove(struct i2c_client *client) | |
| 418 | +{ | |
| 419 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 420 | + struct max30100_data *data = iio_priv(indio_dev); | |
| 421 | + | |
| 422 | + iio_device_unregister(indio_dev); | |
| 423 | + max30100_set_powermode(data, false); | |
| 424 | + | |
| 425 | + return 0; | |
| 426 | +} | |
| 427 | + | |
| 428 | +static const struct i2c_device_id max30100_id[] = { | |
| 429 | + { "max30100", 0 }, | |
| 430 | + {} | |
| 431 | +}; | |
| 432 | +MODULE_DEVICE_TABLE(i2c, max30100_id); | |
| 433 | + | |
| 434 | +static const struct of_device_id max30100_dt_ids[] = { | |
| 435 | + { .compatible = "maxim,max30100" }, | |
| 436 | + { } | |
| 437 | +}; | |
| 438 | +MODULE_DEVICE_TABLE(of, max30100_dt_ids); | |
| 439 | + | |
| 440 | +static struct i2c_driver max30100_driver = { | |
| 441 | + .driver = { | |
| 442 | + .name = MAX30100_DRV_NAME, | |
| 443 | + .of_match_table = of_match_ptr(max30100_dt_ids), | |
| 444 | + }, | |
| 445 | + .probe = max30100_probe, | |
| 446 | + .remove = max30100_remove, | |
| 447 | + .id_table = max30100_id, | |
| 448 | +}; | |
| 449 | +module_i2c_driver(max30100_driver); | |
| 450 | + | |
| 451 | +MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); | |
| 452 | +MODULE_DESCRIPTION("MAX30100 heart rate and pulse oximeter sensor"); | |
| 453 | +MODULE_LICENSE("GPL"); | |
| @@ -288,7 +288,11 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev) · 287 unmodified lines | ||
| 288 | 288 | if (ret) |
| 289 | 289 | goto err_ret; |
| 290 | 290 | |
| 291 | − sscanf(indio_dev->name, "adis%u\n", &device_id); | |
| 291 | + ret = sscanf(indio_dev->name, "adis%u\n", &device_id); | |
| 292 | + if (ret != 1) { | |
| 293 | + ret = -EINVAL; | |
| 294 | + goto err_ret; | |
| 295 | + } | |
| 292 | 296 | |
| 293 | 297 | if (prod_id != device_id) |
| 294 | 298 | dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", |
| @@ -765,7 +765,9 @@ static int adis16480_initial_setup(struct iio_dev *indio_dev) · 764 unmodified lines | ||
| 765 | 765 | if (ret) |
| 766 | 766 | return ret; |
| 767 | 767 | |
| 768 | − sscanf(indio_dev->name, "adis%u\n", &device_id); | |
| 768 | + ret = sscanf(indio_dev->name, "adis%u\n", &device_id); | |
| 769 | + if (ret != 1) | |
| 770 | + return -EINVAL; | |
| 769 | 771 | |
| 770 | 772 | if (prod_id != device_id) |
| 771 | 773 | dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", |
| @@ -1390,6 +1390,14 @@ static int kmx61_probe(struct i2c_client *client, · 1389 unmodified lines | ||
| 1390 | 1390 | } |
| 1391 | 1391 | } |
| 1392 | 1392 | |
| 1393 | + ret = pm_runtime_set_active(&client->dev); | |
| 1394 | + if (ret < 0) | |
| 1395 | + goto err_buffer_cleanup_mag; | |
| 1396 | + | |
| 1397 | + pm_runtime_enable(&client->dev); | |
| 1398 | + pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS); | |
| 1399 | + pm_runtime_use_autosuspend(&client->dev); | |
| 1400 | + | |
| 1393 | 1401 | ret = iio_device_register(data->acc_indio_dev); |
| 1394 | 1402 | if (ret < 0) { |
| 1395 | 1403 | dev_err(&client->dev, "Failed to register acc iio device\n"); |
| @@ -1402,18 +1410,8 @@ static int kmx61_probe(struct i2c_client *client, · 6 unmodified lines | ||
| 1402 | 1410 | goto err_iio_unregister_acc; |
| 1403 | 1411 | } |
| 1404 | 1412 | |
| 1405 | − ret = pm_runtime_set_active(&client->dev); | |
| 1406 | − if (ret < 0) | |
| 1407 | − goto err_iio_unregister_mag; | |
| 1408 | − | |
| 1409 | − pm_runtime_enable(&client->dev); | |
| 1410 | − pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS); | |
| 1411 | − pm_runtime_use_autosuspend(&client->dev); | |
| 1412 | − | |
| 1413 | 1413 | return 0; |
| 1414 | 1414 | |
| 1415 | −err_iio_unregister_mag: | |
| 1416 | − iio_device_unregister(data->mag_indio_dev); | |
| 1417 | 1415 | err_iio_unregister_acc: |
| 1418 | 1416 | iio_device_unregister(data->acc_indio_dev); |
| 1419 | 1417 | err_buffer_cleanup_mag: |
| @@ -1437,13 +1435,13 @@ static int kmx61_remove(struct i2c_client *client) · 17 unmodified lines | ||
| 1437 | 1435 | { |
| 1438 | 1436 | struct kmx61_data *data = i2c_get_clientdata(client); |
| 1439 | 1437 | |
| 1438 | + iio_device_unregister(data->acc_indio_dev); | |
| 1439 | + iio_device_unregister(data->mag_indio_dev); | |
| 1440 | + | |
| 1440 | 1441 | pm_runtime_disable(&client->dev); |
| 1441 | 1442 | pm_runtime_set_suspended(&client->dev); |
| 1442 | 1443 | pm_runtime_put_noidle(&client->dev); |
| 1443 | 1444 | |
| 1444 | − iio_device_unregister(data->acc_indio_dev); | |
| 1445 | − iio_device_unregister(data->mag_indio_dev); | |
| 1446 | − | |
| 1447 | 1445 | if (client->irq > 0) { |
| 1448 | 1446 | iio_triggered_buffer_cleanup(data->acc_indio_dev); |
| 1449 | 1447 | iio_triggered_buffer_cleanup(data->mag_indio_dev); |
| @@ -193,7 +193,8 @@ void iio_buffer_init(struct iio_buffer *buffer) · 192 unmodified lines | ||
| 193 | 193 | INIT_LIST_HEAD(&buffer->buffer_list); |
| 194 | 194 | init_waitqueue_head(&buffer->pollq); |
| 195 | 195 | kref_init(&buffer->ref); |
| 196 | − buffer->watermark = 1; | |
| 196 | + if (!buffer->watermark) | |
| 197 | + buffer->watermark = 1; | |
| 197 | 198 | } |
| 198 | 199 | EXPORT_SYMBOL(iio_buffer_init); |
| 199 | 200 | |
| @@ -567,6 +568,22 @@ static void iio_buffer_deactivate_all(struct iio_dev *indio_dev) · 367 unmodified lines | ||
| 567 | 568 | iio_buffer_deactivate(buffer); |
| 568 | 569 | } |
| 569 | 570 | |
| 571 | +static int iio_buffer_enable(struct iio_buffer *buffer, | |
| 572 | + struct iio_dev *indio_dev) | |
| 573 | +{ | |
| 574 | + if (!buffer->access->enable) | |
| 575 | + return 0; | |
| 576 | + return buffer->access->enable(buffer, indio_dev); | |
| 577 | +} | |
| 578 | + | |
| 579 | +static int iio_buffer_disable(struct iio_buffer *buffer, | |
| 580 | + struct iio_dev *indio_dev) | |
| 581 | +{ | |
| 582 | + if (!buffer->access->disable) | |
| 583 | + return 0; | |
| 584 | + return buffer->access->disable(buffer, indio_dev); | |
| 585 | +} | |
| 586 | + | |
| 570 | 587 | static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, |
| 571 | 588 | struct iio_buffer *buffer) |
| 572 | 589 | { |
| @@ -610,6 +627,7 @@ static void iio_free_scan_mask(struct iio_dev *indio_dev, · 37 unmodified lines | ||
| 610 | 627 | |
| 611 | 628 | struct iio_device_config { |
| 612 | 629 | unsigned int mode; |
| 630 | + unsigned int watermark; | |
| 613 | 631 | const unsigned long *scan_mask; |
| 614 | 632 | unsigned int scan_bytes; |
| 615 | 633 | bool scan_timestamp; |
| @@ -642,10 +660,14 @@ static int iio_verify_update(struct iio_dev *indio_dev, · 26 unmodified lines | ||
| 642 | 660 | if (buffer == remove_buffer) |
| 643 | 661 | continue; |
| 644 | 662 | modes &= buffer->access->modes; |
| 663 | + config->watermark = min(config->watermark, buffer->watermark); | |
| 645 | 664 | } |
| 646 | 665 | |
| 647 | − if (insert_buffer) | |
| 666 | + if (insert_buffer) { | |
| 648 | 667 | modes &= insert_buffer->access->modes; |
| 668 | + config->watermark = min(config->watermark, | |
| 669 | + insert_buffer->watermark); | |
| 670 | + } | |
| 649 | 671 | |
| 650 | 672 | /* Definitely possible for devices to support both of these. */ |
| 651 | 673 | if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) { |
| @@ -713,6 +735,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, · 61 unmodified lines | ||
| 713 | 735 | static int iio_enable_buffers(struct iio_dev *indio_dev, |
| 714 | 736 | struct iio_device_config *config) |
| 715 | 737 | { |
| 738 | + struct iio_buffer *buffer; | |
| 716 | 739 | int ret; |
| 717 | 740 | |
| 718 | 741 | indio_dev->active_scan_mask = config->scan_mask; |
| @@ -743,6 +766,16 @@ static int iio_enable_buffers(struct iio_dev *indio_dev, · 24 unmodified lines | ||
| 743 | 766 | } |
| 744 | 767 | } |
| 745 | 768 | |
| 769 | + if (indio_dev->info->hwfifo_set_watermark) | |
| 770 | + indio_dev->info->hwfifo_set_watermark(indio_dev, | |
| 771 | + config->watermark); | |
| 772 | + | |
| 773 | + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { | |
| 774 | + ret = iio_buffer_enable(buffer, indio_dev); | |
| 775 | + if (ret) | |
| 776 | + goto err_disable_buffers; | |
| 777 | + } | |
| 778 | + | |
| 746 | 779 | indio_dev->currentmode = config->mode; |
| 747 | 780 | |
| 748 | 781 | if (indio_dev->setup_ops->postenable) { |
| @@ -750,12 +783,16 @@ static int iio_enable_buffers(struct iio_dev *indio_dev, · 1 unmodified line | ||
| 750 | 783 | if (ret) { |
| 751 | 784 | dev_dbg(&indio_dev->dev, |
| 752 | 785 | "Buffer not started: postenable failed (%d)\n", ret); |
| 753 | − goto err_run_postdisable; | |
| 786 | + goto err_disable_buffers; | |
| 754 | 787 | } |
| 755 | 788 | } |
| 756 | 789 | |
| 757 | 790 | return 0; |
| 758 | 791 | |
| 792 | +err_disable_buffers: | |
| 793 | + list_for_each_entry_continue_reverse(buffer, &indio_dev->buffer_list, | |
| 794 | + buffer_list) | |
| 795 | + iio_buffer_disable(buffer, indio_dev); | |
| 759 | 796 | err_run_postdisable: |
| 760 | 797 | indio_dev->currentmode = INDIO_DIRECT_MODE; |
| 761 | 798 | if (indio_dev->setup_ops->postdisable) |
| @@ -768,6 +805,7 @@ err_undo_config: · 6 unmodified lines | ||
| 768 | 805 | |
| 769 | 806 | static int iio_disable_buffers(struct iio_dev *indio_dev) |
| 770 | 807 | { |
| 808 | + struct iio_buffer *buffer; | |
| 771 | 809 | int ret = 0; |
| 772 | 810 | int ret2; |
| 773 | 811 | |
| @@ -788,6 +826,12 @@ static int iio_disable_buffers(struct iio_dev *indio_dev) · 14 unmodified lines | ||
| 788 | 826 | ret = ret2; |
| 789 | 827 | } |
| 790 | 828 | |
| 829 | + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { | |
| 830 | + ret2 = iio_buffer_disable(buffer, indio_dev); | |
| 831 | + if (ret2 && !ret) | |
| 832 | + ret = ret2; | |
| 833 | + } | |
| 834 | + | |
| 791 | 835 | indio_dev->currentmode = INDIO_DIRECT_MODE; |
| 792 | 836 | |
| 793 | 837 | if (indio_dev->setup_ops->postdisable) { |
| @@ -974,9 +1018,6 @@ static ssize_t iio_buffer_store_watermark(struct device *dev, · 180 unmodified lines | ||
| 974 | 1018 | } |
| 975 | 1019 | |
| 976 | 1020 | buffer->watermark = val; |
| 977 | − | |
| 978 | − if (indio_dev->info->hwfifo_set_watermark) | |
| 979 | − indio_dev->info->hwfifo_set_watermark(indio_dev, val); | |
| 980 | 1021 | out: |
| 981 | 1022 | mutex_unlock(&indio_dev->mlock); |
| 982 | 1023 | |
| @@ -991,6 +1032,8 @@ static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, · 8 unmodified lines | ||
| 991 | 1032 | iio_buffer_show_enable, iio_buffer_store_enable); |
| 992 | 1033 | static DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR, |
| 993 | 1034 | iio_buffer_show_watermark, iio_buffer_store_watermark); |
| 1035 | +static struct device_attribute dev_attr_watermark_ro = __ATTR(watermark, | |
| 1036 | + S_IRUGO, iio_buffer_show_watermark, NULL); | |
| 994 | 1037 | |
| 995 | 1038 | static struct attribute *iio_buffer_attrs[] = { |
| 996 | 1039 | &dev_attr_length.attr, |
| @@ -1033,6 +1076,9 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) · 36 unmodified lines | ||
| 1033 | 1076 | if (!buffer->access->set_length) |
| 1034 | 1077 | attr[0] = &dev_attr_length_ro.attr; |
| 1035 | 1078 | |
| 1079 | + if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK) | |
| 1080 | + attr[2] = &dev_attr_watermark_ro.attr; | |
| 1081 | + | |
| 1036 | 1082 | if (buffer->attrs) |
| 1037 | 1083 | memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs, |
| 1038 | 1084 | sizeof(struct attribute *) * attrcount); |
| @@ -0,0 +1,51 @@ | ||
| 1 | +/* | |
| 2 | + * Industrial I/O configfs bits | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015 Intel Corporation | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify it | |
| 7 | + * under the terms of the GNU General Public License version 2 as published by | |
| 8 | + * the Free Software Foundation. | |
| 9 | + */ | |
| 10 | + | |
| 11 | +#include <linux/configfs.h> | |
| 12 | +#include <linux/module.h> | |
| 13 | +#include <linux/init.h> | |
| 14 | +#include <linux/kmod.h> | |
| 15 | +#include <linux/slab.h> | |
| 16 | + | |
| 17 | +#include <linux/iio/iio.h> | |
| 18 | +#include <linux/iio/configfs.h> | |
| 19 | + | |
| 20 | +static struct config_item_type iio_root_group_type = { | |
| 21 | + .ct_owner = THIS_MODULE, | |
| 22 | +}; | |
| 23 | + | |
| 24 | +struct configfs_subsystem iio_configfs_subsys = { | |
| 25 | + .su_group = { | |
| 26 | + .cg_item = { | |
| 27 | + .ci_namebuf = "iio", | |
| 28 | + .ci_type = &iio_root_group_type, | |
| 29 | + }, | |
| 30 | + }, | |
| 31 | + .su_mutex = __MUTEX_INITIALIZER(iio_configfs_subsys.su_mutex), | |
| 32 | +}; | |
| 33 | +EXPORT_SYMBOL(iio_configfs_subsys); | |
| 34 | + | |
| 35 | +static int __init iio_configfs_init(void) | |
| 36 | +{ | |
| 37 | + config_group_init(&iio_configfs_subsys.su_group); | |
| 38 | + | |
| 39 | + return configfs_register_subsystem(&iio_configfs_subsys); | |
| 40 | +} | |
| 41 | +module_init(iio_configfs_init); | |
| 42 | + | |
| 43 | +static void __exit iio_configfs_exit(void) | |
| 44 | +{ | |
| 45 | + configfs_unregister_subsystem(&iio_configfs_subsys); | |
| 46 | +} | |
| 47 | +module_exit(iio_configfs_exit); | |
| 48 | + | |
| 49 | +MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); | |
| 50 | +MODULE_DESCRIPTION("Industrial I/O configfs support"); | |
| 51 | +MODULE_LICENSE("GPL v2"); | |
| @@ -470,6 +470,7 @@ ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals) · 469 unmodified lines | ||
| 470 | 470 | return 0; |
| 471 | 471 | } |
| 472 | 472 | } |
| 473 | +EXPORT_SYMBOL_GPL(iio_format_value); | |
| 473 | 474 | |
| 474 | 475 | static ssize_t iio_read_channel_info(struct device *dev, |
| 475 | 476 | struct device_attribute *attr, |
| @@ -512,6 +513,12 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, · 36 unmodified lines | ||
| 512 | 513 | int i = 0, f = 0; |
| 513 | 514 | bool integer_part = true, negative = false; |
| 514 | 515 | |
| 516 | + if (fract_mult == 0) { | |
| 517 | + *fract = 0; | |
| 518 | + | |
| 519 | + return kstrtoint(str, 0, integer); | |
| 520 | + } | |
| 521 | + | |
| 515 | 522 | if (str[0] == '-') { |
| 516 | 523 | negative = true; |
| 517 | 524 | str++; |
| @@ -571,6 +578,9 @@ static ssize_t iio_write_channel_info(struct device *dev, · 53 unmodified lines | ||
| 571 | 578 | if (indio_dev->info->write_raw_get_fmt) |
| 572 | 579 | switch (indio_dev->info->write_raw_get_fmt(indio_dev, |
| 573 | 580 | this_attr->c, this_attr->address)) { |
| 581 | + case IIO_VAL_INT: | |
| 582 | + fract_mult = 0; | |
| 583 | + break; | |
| 574 | 584 | case IIO_VAL_INT_PLUS_MICRO: |
| 575 | 585 | fract_mult = 100000; |
| 576 | 586 | break; |
| @@ -0,0 +1,184 @@ | ||
| 1 | +/* | |
| 2 | + * The Industrial I/O core, software trigger functions | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015 Intel Corporation | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify it | |
| 7 | + * under the terms of the GNU General Public License version 2 as published by | |
| 8 | + * the Free Software Foundation. | |
| 9 | + */ | |
| 10 | + | |
| 11 | +#include <linux/module.h> | |
| 12 | +#include <linux/init.h> | |
| 13 | +#include <linux/kmod.h> | |
| 14 | +#include <linux/list.h> | |
| 15 | +#include <linux/slab.h> | |
| 16 | + | |
| 17 | +#include <linux/iio/sw_trigger.h> | |
| 18 | +#include <linux/iio/configfs.h> | |
| 19 | +#include <linux/configfs.h> | |
| 20 | + | |
| 21 | +static struct config_group *iio_triggers_group; | |
| 22 | +static struct config_item_type iio_trigger_type_group_type; | |
| 23 | + | |
| 24 | +static struct config_item_type iio_triggers_group_type = { | |
| 25 | + .ct_owner = THIS_MODULE, | |
| 26 | +}; | |
| 27 | + | |
| 28 | +static LIST_HEAD(iio_trigger_types_list); | |
| 29 | +static DEFINE_MUTEX(iio_trigger_types_lock); | |
| 30 | + | |
| 31 | +static | |
| 32 | +struct iio_sw_trigger_type *__iio_find_sw_trigger_type(const char *name, | |
| 33 | + unsigned len) | |
| 34 | +{ | |
| 35 | + struct iio_sw_trigger_type *t = NULL, *iter; | |
| 36 | + | |
| 37 | + list_for_each_entry(iter, &iio_trigger_types_list, list) | |
| 38 | + if (!strcmp(iter->name, name)) { | |
| 39 | + t = iter; | |
| 40 | + break; | |
| 41 | + } | |
| 42 | + | |
| 43 | + return t; | |
| 44 | +} | |
| 45 | + | |
| 46 | +int iio_register_sw_trigger_type(struct iio_sw_trigger_type *t) | |
| 47 | +{ | |
| 48 | + struct iio_sw_trigger_type *iter; | |
| 49 | + int ret = 0; | |
| 50 | + | |
| 51 | + mutex_lock(&iio_trigger_types_lock); | |
| 52 | + iter = __iio_find_sw_trigger_type(t->name, strlen(t->name)); | |
| 53 | + if (iter) | |
| 54 | + ret = -EBUSY; | |
| 55 | + else | |
| 56 | + list_add_tail(&t->list, &iio_trigger_types_list); | |
| 57 | + mutex_unlock(&iio_trigger_types_lock); | |
| 58 | + | |
| 59 | + if (ret) | |
| 60 | + return ret; | |
| 61 | + | |
| 62 | + t->group = configfs_register_default_group(iio_triggers_group, t->name, | |
| 63 | + &iio_trigger_type_group_type); | |
| 64 | + if (IS_ERR(t->group)) | |
| 65 | + ret = PTR_ERR(t->group); | |
| 66 | + | |
| 67 | + return ret; | |
| 68 | +} | |
| 69 | +EXPORT_SYMBOL(iio_register_sw_trigger_type); | |
| 70 | + | |
| 71 | +void iio_unregister_sw_trigger_type(struct iio_sw_trigger_type *t) | |
| 72 | +{ | |
| 73 | + struct iio_sw_trigger_type *iter; | |
| 74 | + | |
| 75 | + mutex_lock(&iio_trigger_types_lock); | |
| 76 | + iter = __iio_find_sw_trigger_type(t->name, strlen(t->name)); | |
| 77 | + if (iter) | |
| 78 | + list_del(&t->list); | |
| 79 | + mutex_unlock(&iio_trigger_types_lock); | |
| 80 | + | |
| 81 | + configfs_unregister_default_group(t->group); | |
| 82 | +} | |
| 83 | +EXPORT_SYMBOL(iio_unregister_sw_trigger_type); | |
| 84 | + | |
| 85 | +static | |
| 86 | +struct iio_sw_trigger_type *iio_get_sw_trigger_type(const char *name) | |
| 87 | +{ | |
| 88 | + struct iio_sw_trigger_type *t; | |
| 89 | + | |
| 90 | + mutex_lock(&iio_trigger_types_lock); | |
| 91 | + t = __iio_find_sw_trigger_type(name, strlen(name)); | |
| 92 | + if (t && !try_module_get(t->owner)) | |
| 93 | + t = NULL; | |
| 94 | + mutex_unlock(&iio_trigger_types_lock); | |
| 95 | + | |
| 96 | + return t; | |
| 97 | +} | |
| 98 | + | |
| 99 | +struct iio_sw_trigger *iio_sw_trigger_create(const char *type, const char *name) | |
| 100 | +{ | |
| 101 | + struct iio_sw_trigger *t; | |
| 102 | + struct iio_sw_trigger_type *tt; | |
| 103 | + | |
| 104 | + tt = iio_get_sw_trigger_type(type); | |
| 105 | + if (!tt) { | |
| 106 | + pr_err("Invalid trigger type: %s\n", type); | |
| 107 | + return ERR_PTR(-EINVAL); | |
| 108 | + } | |
| 109 | + t = tt->ops->probe(name); | |
| 110 | + if (IS_ERR(t)) | |
| 111 | + goto out_module_put; | |
| 112 | + | |
| 113 | + t->trigger_type = tt; | |
| 114 | + | |
| 115 | + return t; | |
| 116 | +out_module_put: | |
| 117 | + module_put(tt->owner); | |
| 118 | + return t; | |
| 119 | +} | |
| 120 | +EXPORT_SYMBOL(iio_sw_trigger_create); | |
| 121 | + | |
| 122 | +void iio_sw_trigger_destroy(struct iio_sw_trigger *t) | |
| 123 | +{ | |
| 124 | + struct iio_sw_trigger_type *tt = t->trigger_type; | |
| 125 | + | |
| 126 | + tt->ops->remove(t); | |
| 127 | + module_put(tt->owner); | |
| 128 | +} | |
| 129 | +EXPORT_SYMBOL(iio_sw_trigger_destroy); | |
| 130 | + | |
| 131 | +static struct config_group *trigger_make_group(struct config_group *group, | |
| 132 | + const char *name) | |
| 133 | +{ | |
| 134 | + struct iio_sw_trigger *t; | |
| 135 | + | |
| 136 | + t = iio_sw_trigger_create(group->cg_item.ci_name, name); | |
| 137 | + if (IS_ERR(t)) | |
| 138 | + return ERR_CAST(t); | |
| 139 | + | |
| 140 | + config_item_set_name(&t->group.cg_item, "%s", name); | |
| 141 | + | |
| 142 | + return &t->group; | |
| 143 | +} | |
| 144 | + | |
| 145 | +static void trigger_drop_group(struct config_group *group, | |
| 146 | + struct config_item *item) | |
| 147 | +{ | |
| 148 | + struct iio_sw_trigger *t = to_iio_sw_trigger(item); | |
| 149 | + | |
| 150 | + iio_sw_trigger_destroy(t); | |
| 151 | + config_item_put(item); | |
| 152 | +} | |
| 153 | + | |
| 154 | +static struct configfs_group_operations trigger_ops = { | |
| 155 | + .make_group = &trigger_make_group, | |
| 156 | + .drop_item = &trigger_drop_group, | |
| 157 | +}; | |
| 158 | + | |
| 159 | +static struct config_item_type iio_trigger_type_group_type = { | |
| 160 | + .ct_group_ops = &trigger_ops, | |
| 161 | + .ct_owner = THIS_MODULE, | |
| 162 | +}; | |
| 163 | + | |
| 164 | +static int __init iio_sw_trigger_init(void) | |
| 165 | +{ | |
| 166 | + iio_triggers_group = | |
| 167 | + configfs_register_default_group(&iio_configfs_subsys.su_group, | |
| 168 | + "triggers", | |
| 169 | + &iio_triggers_group_type); | |
| 170 | + if (IS_ERR(iio_triggers_group)) | |
| 171 | + return PTR_ERR(iio_triggers_group); | |
| 172 | + return 0; | |
| 173 | +} | |
| 174 | +module_init(iio_sw_trigger_init); | |
| 175 | + | |
| 176 | +static void __exit iio_sw_trigger_exit(void) | |
| 177 | +{ | |
| 178 | + configfs_unregister_default_group(iio_triggers_group); | |
| 179 | +} | |
| 180 | +module_exit(iio_sw_trigger_exit); | |
| 181 | + | |
| 182 | +MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); | |
| 183 | +MODULE_DESCRIPTION("Industrial I/O software triggers support"); | |
| 184 | +MODULE_LICENSE("GPL v2"); | |
| @@ -61,12 +61,10 @@ EXPORT_SYMBOL_GPL(iio_map_array_register); · 60 unmodified lines | ||
| 61 | 61 | int iio_map_array_unregister(struct iio_dev *indio_dev) |
| 62 | 62 | { |
| 63 | 63 | int ret = -ENODEV; |
| 64 | − struct iio_map_internal *mapi; | |
| 65 | − struct list_head *pos, *tmp; | |
| 64 | + struct iio_map_internal *mapi, *next; | |
| 66 | 65 | |
| 67 | 66 | mutex_lock(&iio_map_list_lock); |
| 68 | − list_for_each_safe(pos, tmp, &iio_map_list) { | |
| 69 | − mapi = list_entry(pos, struct iio_map_internal, l); | |
| 67 | + list_for_each_entry_safe(mapi, next, &iio_map_list, l) { | |
| 70 | 68 | if (indio_dev == mapi->indio_dev) { |
| 71 | 69 | list_del(&mapi->l); |
| 72 | 70 | kfree(mapi); |
| @@ -743,8 +743,10 @@ static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val) · 742 unmodified lines | ||
| 743 | 743 | { |
| 744 | 744 | int ret; |
| 745 | 745 | |
| 746 | − if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX) | |
| 746 | + if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX) { | |
| 747 | + dev_err(&als->pdev->dev, "invalid resistor value\n"); | |
| 747 | 748 | return -EINVAL; |
| 749 | + }; | |
| 748 | 750 | |
| 749 | 751 | ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val); |
| 750 | 752 | if (ret) { |
| @@ -381,17 +381,23 @@ static int pa12203001_probe(struct i2c_client *client, · 380 unmodified lines | ||
| 381 | 381 | return ret; |
| 382 | 382 | |
| 383 | 383 | ret = pm_runtime_set_active(&client->dev); |
| 384 | − if (ret < 0) { | |
| 385 | − pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE); | |
| 386 | − return ret; | |
| 387 | − } | |
| 384 | + if (ret < 0) | |
| 385 | + goto out_err; | |
| 388 | 386 | |
| 389 | 387 | pm_runtime_enable(&client->dev); |
| 390 | 388 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 391 | 389 | PA12203001_SLEEP_DELAY_MS); |
| 392 | 390 | pm_runtime_use_autosuspend(&client->dev); |
| 393 | 391 | |
| 394 | − return iio_device_register(indio_dev); | |
| 392 | + ret = iio_device_register(indio_dev); | |
| 393 | + if (ret < 0) | |
| 394 | + goto out_err; | |
| 395 | + | |
| 396 | + return 0; | |
| 397 | + | |
| 398 | +out_err: | |
| 399 | + pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE); | |
| 400 | + return ret; | |
| 395 | 401 | } |
| 396 | 402 | |
| 397 | 403 | static int pa12203001_remove(struct i2c_client *client) |
| @@ -507,34 +507,28 @@ static int rpr0521_probe(struct i2c_client *client, · 506 unmodified lines | ||
| 507 | 507 | dev_err(&client->dev, "rpr0521 chip init failed\n"); |
| 508 | 508 | return ret; |
| 509 | 509 | } |
| 510 | − ret = iio_device_register(indio_dev); | |
| 511 | − if (ret < 0) | |
| 512 | − return ret; | |
| 513 | 510 | |
| 514 | 511 | ret = pm_runtime_set_active(&client->dev); |
| 515 | 512 | if (ret < 0) |
| 516 | − goto err_iio_unregister; | |
| 513 | + return ret; | |
| 517 | 514 | |
| 518 | 515 | pm_runtime_enable(&client->dev); |
| 519 | 516 | pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS); |
| 520 | 517 | pm_runtime_use_autosuspend(&client->dev); |
| 521 | 518 | |
| 522 | − return 0; | |
| 523 | − | |
| 524 | −err_iio_unregister: | |
| 525 | − iio_device_unregister(indio_dev); | |
| 526 | − return ret; | |
| 519 | + return iio_device_register(indio_dev); | |
| 527 | 520 | } |
| 528 | 521 | |
| 529 | 522 | static int rpr0521_remove(struct i2c_client *client) |
| 530 | 523 | { |
| 531 | 524 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 532 | 525 | |
| 526 | + iio_device_unregister(indio_dev); | |
| 527 | + | |
| 533 | 528 | pm_runtime_disable(&client->dev); |
| 534 | 529 | pm_runtime_set_suspended(&client->dev); |
| 535 | 530 | pm_runtime_put_noidle(&client->dev); |
| 536 | 531 | |
| 537 | − iio_device_unregister(indio_dev); | |
| 538 | 532 | rpr0521_poweroff(iio_priv(indio_dev)); |
| 539 | 533 | |
| 540 | 534 | return 0; |
| @@ -20,14 +20,21 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/acpi.h> |
| 21 | 21 | #include <linux/delay.h> |
| 22 | 22 | #include <linux/i2c.h> |
| 23 | +#include <linux/iio/events.h> | |
| 23 | 24 | #include <linux/iio/iio.h> |
| 25 | +#include <linux/interrupt.h> | |
| 26 | +#include <linux/irq.h> | |
| 24 | 27 | #include <linux/iio/sysfs.h> |
| 25 | 28 | #include <linux/mutex.h> |
| 29 | +#include <linux/pm.h> | |
| 30 | +#include <linux/pm_runtime.h> | |
| 26 | 31 | |
| 27 | 32 | #define US5182D_REG_CFG0 0x00 |
| 28 | 33 | #define US5182D_CFG0_ONESHOT_EN BIT(6) |
| 29 | 34 | #define US5182D_CFG0_SHUTDOWN_EN BIT(7) |
| 30 | 35 | #define US5182D_CFG0_WORD_ENABLE BIT(0) |
| 36 | +#define US5182D_CFG0_PROX BIT(3) | |
| 37 | +#define US5182D_CFG0_PX_IRQ BIT(2) | |
| 31 | 38 | |
| 32 | 39 | #define US5182D_REG_CFG1 0x01 |
| 33 | 40 | #define US5182D_CFG1_ALS_RES16 BIT(4) |
| @@ -39,6 +46,7 @@ · 5 unmodified lines | ||
| 39 | 46 | |
| 40 | 47 | #define US5182D_REG_CFG3 0x03 |
| 41 | 48 | #define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5)) |
| 49 | +#define US5182D_CFG3_INT_SOURCE_PX BIT(3) | |
| 42 | 50 | |
| 43 | 51 | #define US5182D_REG_CFG4 0x10 |
| 44 | 52 | |
| @@ -53,6 +61,13 @@ · 8 unmodified lines | ||
| 53 | 61 | #define US5182D_REG_AUTO_LDARK_GAIN 0x29 |
| 54 | 62 | #define US5182D_REG_AUTO_HDARK_GAIN 0x2a |
| 55 | 63 | |
| 64 | +/* Thresholds for events: px low (0x08-l, 0x09-h), px high (0x0a-l 0x0b-h) */ | |
| 65 | +#define US5182D_REG_PXL_TH 0x08 | |
| 66 | +#define US5182D_REG_PXH_TH 0x0a | |
| 67 | + | |
| 68 | +#define US5182D_REG_PXL_TH_DEFAULT 1000 | |
| 69 | +#define US5182D_REG_PXH_TH_DEFAULT 30000 | |
| 70 | + | |
| 56 | 71 | #define US5182D_OPMODE_ALS 0x01 |
| 57 | 72 | #define US5182D_OPMODE_PX 0x02 |
| 58 | 73 | #define US5182D_OPMODE_SHIFT 4 |
| @@ -81,6 +96,9 @@ · 22 unmodified lines | ||
| 81 | 96 | #define US5182D_READ_BYTE 1 |
| 82 | 97 | #define US5182D_READ_WORD 2 |
| 83 | 98 | #define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */ |
| 99 | +#define US5182D_SLEEP_MS 3000 /* ms */ | |
| 100 | +#define US5182D_PXH_TH_DISABLE 0xffff | |
| 101 | +#define US5182D_PXL_TH_DISABLE 0x0000 | |
| 84 | 102 | |
| 85 | 103 | /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */ |
| 86 | 104 | static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600, |
| @@ -99,6 +117,11 @@ enum mode { · 12 unmodified lines | ||
| 99 | 117 | US5182D_PX_ONLY |
| 100 | 118 | }; |
| 101 | 119 | |
| 120 | +enum pmode { | |
| 121 | + US5182D_CONTINUOUS, | |
| 122 | + US5182D_ONESHOT | |
| 123 | +}; | |
| 124 | + | |
| 102 | 125 | struct us5182d_data { |
| 103 | 126 | struct i2c_client *client; |
| 104 | 127 | struct mutex lock; |
| @@ -111,7 +134,19 @@ struct us5182d_data { · 6 unmodified lines | ||
| 111 | 134 | u8 upper_dark_gain; |
| 112 | 135 | u16 *us5182d_dark_ths; |
| 113 | 136 | |
| 137 | + u16 px_low_th; | |
| 138 | + u16 px_high_th; | |
| 139 | + | |
| 140 | + int rising_en; | |
| 141 | + int falling_en; | |
| 142 | + | |
| 114 | 143 | u8 opmode; |
| 144 | + u8 power_mode; | |
| 145 | + | |
| 146 | + bool als_enabled; | |
| 147 | + bool px_enabled; | |
| 148 | + | |
| 149 | + bool default_continuous; | |
| 115 | 150 | }; |
| 116 | 151 | |
| 117 | 152 | static IIO_CONST_ATTR(in_illuminance_scale_available, |
| @@ -130,16 +165,30 @@ static const struct { · 12 unmodified lines | ||
| 130 | 165 | u8 reg; |
| 131 | 166 | u8 val; |
| 132 | 167 | } us5182d_regvals[] = { |
| 133 | − {US5182D_REG_CFG0, (US5182D_CFG0_SHUTDOWN_EN | | |
| 134 | − US5182D_CFG0_WORD_ENABLE)}, | |
| 168 | + {US5182D_REG_CFG0, US5182D_CFG0_WORD_ENABLE}, | |
| 135 | 169 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, |
| 136 | 170 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | |
| 137 | 171 | US5182D_CFG2_PXGAIN_DEFAULT)}, |
| 138 | − {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100}, | |
| 139 | − {US5182D_REG_MODE_STORE, US5182D_STORE_MODE}, | |
| 172 | + {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100 | | |
| 173 | + US5182D_CFG3_INT_SOURCE_PX}, | |
| 140 | 174 | {US5182D_REG_CFG4, 0x00}, |
| 141 | 175 | }; |
| 142 | 176 | |
| 177 | +static const struct iio_event_spec us5182d_events[] = { | |
| 178 | + { | |
| 179 | + .type = IIO_EV_TYPE_THRESH, | |
| 180 | + .dir = IIO_EV_DIR_RISING, | |
| 181 | + .mask_separate = BIT(IIO_EV_INFO_VALUE) | | |
| 182 | + BIT(IIO_EV_INFO_ENABLE), | |
| 183 | + }, | |
| 184 | + { | |
| 185 | + .type = IIO_EV_TYPE_THRESH, | |
| 186 | + .dir = IIO_EV_DIR_FALLING, | |
| 187 | + .mask_separate = BIT(IIO_EV_INFO_VALUE) | | |
| 188 | + BIT(IIO_EV_INFO_ENABLE), | |
| 189 | + }, | |
| 190 | +}; | |
| 191 | + | |
| 143 | 192 | static const struct iio_chan_spec us5182d_channels[] = { |
| 144 | 193 | { |
| 145 | 194 | .type = IIO_LIGHT, |
| @@ -149,40 +198,39 @@ static const struct iio_chan_spec us5182d_channels[] = { · 3 unmodified lines | ||
| 149 | 198 | { |
| 150 | 199 | .type = IIO_PROXIMITY, |
| 151 | 200 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), |
| 201 | + .event_spec = us5182d_events, | |
| 202 | + .num_event_specs = ARRAY_SIZE(us5182d_events), | |
| 152 | 203 | } |
| 153 | 204 | }; |
| 154 | 205 | |
| 155 | −static int us5182d_get_als(struct us5182d_data *data) | |
| 206 | +static int us5182d_oneshot_en(struct us5182d_data *data) | |
| 156 | 207 | { |
| 157 | 208 | int ret; |
| 158 | − unsigned long result; | |
| 159 | 209 | |
| 160 | − ret = i2c_smbus_read_word_data(data->client, | |
| 161 | − US5182D_REG_ADL); | |
| 210 | + ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | |
| 162 | 211 | if (ret < 0) |
| 163 | 212 | return ret; |
| 164 | 213 | |
| 165 | − result = ret * data->ga / US5182D_GA_RESOLUTION; | |
| 166 | − if (result > 0xffff) | |
| 167 | − result = 0xffff; | |
| 214 | + /* | |
| 215 | + * In oneshot mode the chip will power itself down after taking the | |
| 216 | + * required measurement. | |
| 217 | + */ | |
| 218 | + ret = ret | US5182D_CFG0_ONESHOT_EN; | |
| 168 | 219 | |
| 169 | − return result; | |
| 220 | + return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret); | |
| 170 | 221 | } |
| 171 | 222 | |
| 172 | 223 | static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) |
| 173 | 224 | { |
| 174 | 225 | int ret; |
| 175 | 226 | |
| 227 | + if (mode == data->opmode) | |
| 228 | + return 0; | |
| 229 | + | |
| 176 | 230 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); |
| 177 | 231 | if (ret < 0) |
| 178 | 232 | return ret; |
| 179 | 233 | |
| 180 | − /* | |
| 181 | − * In oneshot mode the chip will power itself down after taking the | |
| 182 | − * required measurement. | |
| 183 | − */ | |
| 184 | − ret = ret | US5182D_CFG0_ONESHOT_EN; | |
| 185 | − | |
| 186 | 234 | /* update mode */ |
| 187 | 235 | ret = ret & ~US5182D_OPMODE_MASK; |
| 188 | 236 | ret = ret | (mode << US5182D_OPMODE_SHIFT); |
| @@ -196,9 +244,6 @@ static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) · 7 unmodified lines | ||
| 196 | 244 | if (ret < 0) |
| 197 | 245 | return ret; |
| 198 | 246 | |
| 199 | − if (mode == data->opmode) | |
| 200 | − return 0; | |
| 201 | − | |
| 202 | 247 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE, |
| 203 | 248 | US5182D_STORE_MODE); |
| 204 | 249 | if (ret < 0) |
| @@ -210,6 +255,177 @@ static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) · 5 unmodified lines | ||
| 210 | 255 | return 0; |
| 211 | 256 | } |
| 212 | 257 | |
| 258 | +static int us5182d_als_enable(struct us5182d_data *data) | |
| 259 | +{ | |
| 260 | + int ret; | |
| 261 | + u8 mode; | |
| 262 | + | |
| 263 | + if (data->power_mode == US5182D_ONESHOT) { | |
| 264 | + ret = us5182d_set_opmode(data, US5182D_ALS_ONLY); | |
| 265 | + if (ret < 0) | |
| 266 | + return ret; | |
| 267 | + data->px_enabled = false; | |
| 268 | + } | |
| 269 | + | |
| 270 | + if (data->als_enabled) | |
| 271 | + return 0; | |
| 272 | + | |
| 273 | + mode = data->px_enabled ? US5182D_ALS_PX : US5182D_ALS_ONLY; | |
| 274 | + | |
| 275 | + ret = us5182d_set_opmode(data, mode); | |
| 276 | + if (ret < 0) | |
| 277 | + return ret; | |
| 278 | + | |
| 279 | + data->als_enabled = true; | |
| 280 | + | |
| 281 | + return 0; | |
| 282 | +} | |
| 283 | + | |
| 284 | +static int us5182d_px_enable(struct us5182d_data *data) | |
| 285 | +{ | |
| 286 | + int ret; | |
| 287 | + u8 mode; | |
| 288 | + | |
| 289 | + if (data->power_mode == US5182D_ONESHOT) { | |
| 290 | + ret = us5182d_set_opmode(data, US5182D_PX_ONLY); | |
| 291 | + if (ret < 0) | |
| 292 | + return ret; | |
| 293 | + data->als_enabled = false; | |
| 294 | + } | |
| 295 | + | |
| 296 | + if (data->px_enabled) | |
| 297 | + return 0; | |
| 298 | + | |
| 299 | + mode = data->als_enabled ? US5182D_ALS_PX : US5182D_PX_ONLY; | |
| 300 | + | |
| 301 | + ret = us5182d_set_opmode(data, mode); | |
| 302 | + if (ret < 0) | |
| 303 | + return ret; | |
| 304 | + | |
| 305 | + data->px_enabled = true; | |
| 306 | + | |
| 307 | + return 0; | |
| 308 | +} | |
| 309 | + | |
| 310 | +static int us5182d_get_als(struct us5182d_data *data) | |
| 311 | +{ | |
| 312 | + int ret; | |
| 313 | + unsigned long result; | |
| 314 | + | |
| 315 | + ret = us5182d_als_enable(data); | |
| 316 | + if (ret < 0) | |
| 317 | + return ret; | |
| 318 | + | |
| 319 | + ret = i2c_smbus_read_word_data(data->client, | |
| 320 | + US5182D_REG_ADL); | |
| 321 | + if (ret < 0) | |
| 322 | + return ret; | |
| 323 | + | |
| 324 | + result = ret * data->ga / US5182D_GA_RESOLUTION; | |
| 325 | + if (result > 0xffff) | |
| 326 | + result = 0xffff; | |
| 327 | + | |
| 328 | + return result; | |
| 329 | +} | |
| 330 | + | |
| 331 | +static int us5182d_get_px(struct us5182d_data *data) | |
| 332 | +{ | |
| 333 | + int ret; | |
| 334 | + | |
| 335 | + ret = us5182d_px_enable(data); | |
| 336 | + if (ret < 0) | |
| 337 | + return ret; | |
| 338 | + | |
| 339 | + return i2c_smbus_read_word_data(data->client, | |
| 340 | + US5182D_REG_PDL); | |
| 341 | +} | |
| 342 | + | |
| 343 | +static int us5182d_shutdown_en(struct us5182d_data *data, u8 state) | |
| 344 | +{ | |
| 345 | + int ret; | |
| 346 | + | |
| 347 | + if (data->power_mode == US5182D_ONESHOT) | |
| 348 | + return 0; | |
| 349 | + | |
| 350 | + ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | |
| 351 | + if (ret < 0) | |
| 352 | + return ret; | |
| 353 | + | |
| 354 | + ret = ret & ~US5182D_CFG0_SHUTDOWN_EN; | |
| 355 | + ret = ret | state; | |
| 356 | + | |
| 357 | + ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret); | |
| 358 | + if (ret < 0) | |
| 359 | + return ret; | |
| 360 | + | |
| 361 | + if (state & US5182D_CFG0_SHUTDOWN_EN) { | |
| 362 | + data->als_enabled = false; | |
| 363 | + data->px_enabled = false; | |
| 364 | + } | |
| 365 | + | |
| 366 | + return ret; | |
| 367 | +} | |
| 368 | + | |
| 369 | + | |
| 370 | +static int us5182d_set_power_state(struct us5182d_data *data, bool on) | |
| 371 | +{ | |
| 372 | + int ret; | |
| 373 | + | |
| 374 | + if (data->power_mode == US5182D_ONESHOT) | |
| 375 | + return 0; | |
| 376 | + | |
| 377 | + if (on) { | |
| 378 | + ret = pm_runtime_get_sync(&data->client->dev); | |
| 379 | + if (ret < 0) | |
| 380 | + pm_runtime_put_noidle(&data->client->dev); | |
| 381 | + } else { | |
| 382 | + pm_runtime_mark_last_busy(&data->client->dev); | |
| 383 | + ret = pm_runtime_put_autosuspend(&data->client->dev); | |
| 384 | + } | |
| 385 | + | |
| 386 | + return ret; | |
| 387 | +} | |
| 388 | + | |
| 389 | +static int us5182d_read_value(struct us5182d_data *data, | |
| 390 | + struct iio_chan_spec const *chan) | |
| 391 | +{ | |
| 392 | + int ret, value; | |
| 393 | + | |
| 394 | + mutex_lock(&data->lock); | |
| 395 | + | |
| 396 | + if (data->power_mode == US5182D_ONESHOT) { | |
| 397 | + ret = us5182d_oneshot_en(data); | |
| 398 | + if (ret < 0) | |
| 399 | + goto out_err; | |
| 400 | + } | |
| 401 | + | |
| 402 | + ret = us5182d_set_power_state(data, true); | |
| 403 | + if (ret < 0) | |
| 404 | + goto out_err; | |
| 405 | + | |
| 406 | + if (chan->type == IIO_LIGHT) | |
| 407 | + ret = us5182d_get_als(data); | |
| 408 | + else | |
| 409 | + ret = us5182d_get_px(data); | |
| 410 | + if (ret < 0) | |
| 411 | + goto out_poweroff; | |
| 412 | + | |
| 413 | + value = ret; | |
| 414 | + | |
| 415 | + ret = us5182d_set_power_state(data, false); | |
| 416 | + if (ret < 0) | |
| 417 | + goto out_err; | |
| 418 | + | |
| 419 | + mutex_unlock(&data->lock); | |
| 420 | + return value; | |
| 421 | + | |
| 422 | +out_poweroff: | |
| 423 | + us5182d_set_power_state(data, false); | |
| 424 | +out_err: | |
| 425 | + mutex_unlock(&data->lock); | |
| 426 | + return ret; | |
| 427 | +} | |
| 428 | + | |
| 213 | 429 | static int us5182d_read_raw(struct iio_dev *indio_dev, |
| 214 | 430 | struct iio_chan_spec const *chan, int *val, |
| 215 | 431 | int *val2, long mask) |
| @@ -219,53 +435,21 @@ static int us5182d_read_raw(struct iio_dev *indio_dev, · 3 unmodified lines | ||
| 219 | 435 | |
| 220 | 436 | switch (mask) { |
| 221 | 437 | case IIO_CHAN_INFO_RAW: |
| 222 | − switch (chan->type) { | |
| 223 | − case IIO_LIGHT: | |
| 224 | − mutex_lock(&data->lock); | |
| 225 | − ret = us5182d_set_opmode(data, US5182D_OPMODE_ALS); | |
| 226 | − if (ret < 0) | |
| 227 | − goto out_err; | |
| 228 | − | |
| 229 | − ret = us5182d_get_als(data); | |
| 230 | − if (ret < 0) | |
| 231 | − goto out_err; | |
| 232 | − mutex_unlock(&data->lock); | |
| 233 | − *val = ret; | |
| 234 | − return IIO_VAL_INT; | |
| 235 | − case IIO_PROXIMITY: | |
| 236 | − mutex_lock(&data->lock); | |
| 237 | − ret = us5182d_set_opmode(data, US5182D_OPMODE_PX); | |
| 238 | − if (ret < 0) | |
| 239 | − goto out_err; | |
| 240 | − | |
| 241 | − ret = i2c_smbus_read_word_data(data->client, | |
| 242 | − US5182D_REG_PDL); | |
| 243 | − if (ret < 0) | |
| 244 | − goto out_err; | |
| 245 | − mutex_unlock(&data->lock); | |
| 246 | − *val = ret; | |
| 247 | − return IIO_VAL_INT; | |
| 248 | − default: | |
| 249 | − return -EINVAL; | |
| 250 | − } | |
| 251 | − | |
| 438 | + ret = us5182d_read_value(data, chan); | |
| 439 | + if (ret < 0) | |
| 440 | + return ret; | |
| 441 | + *val = ret; | |
| 442 | + return IIO_VAL_INT; | |
| 252 | 443 | case IIO_CHAN_INFO_SCALE: |
| 253 | 444 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); |
| 254 | 445 | if (ret < 0) |
| 255 | 446 | return ret; |
| 256 | − | |
| 257 | 447 | *val = 0; |
| 258 | 448 | *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK]; |
| 259 | − | |
| 260 | 449 | return IIO_VAL_INT_PLUS_MICRO; |
| 261 | 450 | default: |
| 262 | 451 | return -EINVAL; |
| 263 | 452 | } |
| 264 | − | |
| 265 | − return -EINVAL; | |
| 266 | −out_err: | |
| 267 | − mutex_unlock(&data->lock); | |
| 268 | − return ret; | |
| 269 | 453 | } |
| 270 | 454 | |
| 271 | 455 | /** |
| @@ -343,11 +527,201 @@ static int us5182d_write_raw(struct iio_dev *indio_dev, · 71 unmodified lines | ||
| 343 | 527 | return -EINVAL; |
| 344 | 528 | } |
| 345 | 529 | |
| 530 | +static int us5182d_setup_prox(struct iio_dev *indio_dev, | |
| 531 | + enum iio_event_direction dir, u16 val) | |
| 532 | +{ | |
| 533 | + struct us5182d_data *data = iio_priv(indio_dev); | |
| 534 | + | |
| 535 | + if (dir == IIO_EV_DIR_FALLING) | |
| 536 | + return i2c_smbus_write_word_data(data->client, | |
| 537 | + US5182D_REG_PXL_TH, val); | |
| 538 | + else if (dir == IIO_EV_DIR_RISING) | |
| 539 | + return i2c_smbus_write_word_data(data->client, | |
| 540 | + US5182D_REG_PXH_TH, val); | |
| 541 | + | |
| 542 | + return 0; | |
| 543 | +} | |
| 544 | + | |
| 545 | +static int us5182d_read_thresh(struct iio_dev *indio_dev, | |
| 546 | + const struct iio_chan_spec *chan, enum iio_event_type type, | |
| 547 | + enum iio_event_direction dir, enum iio_event_info info, int *val, | |
| 548 | + int *val2) | |
| 549 | +{ | |
| 550 | + struct us5182d_data *data = iio_priv(indio_dev); | |
| 551 | + | |
| 552 | + switch (dir) { | |
| 553 | + case IIO_EV_DIR_RISING: | |
| 554 | + mutex_lock(&data->lock); | |
| 555 | + *val = data->px_high_th; | |
| 556 | + mutex_unlock(&data->lock); | |
| 557 | + break; | |
| 558 | + case IIO_EV_DIR_FALLING: | |
| 559 | + mutex_lock(&data->lock); | |
| 560 | + *val = data->px_low_th; | |
| 561 | + mutex_unlock(&data->lock); | |
| 562 | + break; | |
| 563 | + default: | |
| 564 | + return -EINVAL; | |
| 565 | + } | |
| 566 | + | |
| 567 | + return IIO_VAL_INT; | |
| 568 | +} | |
| 569 | + | |
| 570 | +static int us5182d_write_thresh(struct iio_dev *indio_dev, | |
| 571 | + const struct iio_chan_spec *chan, enum iio_event_type type, | |
| 572 | + enum iio_event_direction dir, enum iio_event_info info, int val, | |
| 573 | + int val2) | |
| 574 | +{ | |
| 575 | + struct us5182d_data *data = iio_priv(indio_dev); | |
| 576 | + int ret; | |
| 577 | + | |
| 578 | + if (val < 0 || val > USHRT_MAX || val2 != 0) | |
| 579 | + return -EINVAL; | |
| 580 | + | |
| 581 | + switch (dir) { | |
| 582 | + case IIO_EV_DIR_RISING: | |
| 583 | + mutex_lock(&data->lock); | |
| 584 | + if (data->rising_en) { | |
| 585 | + ret = us5182d_setup_prox(indio_dev, dir, val); | |
| 586 | + if (ret < 0) | |
| 587 | + goto err; | |
| 588 | + } | |
| 589 | + data->px_high_th = val; | |
| 590 | + mutex_unlock(&data->lock); | |
| 591 | + break; | |
| 592 | + case IIO_EV_DIR_FALLING: | |
| 593 | + mutex_lock(&data->lock); | |
| 594 | + if (data->falling_en) { | |
| 595 | + ret = us5182d_setup_prox(indio_dev, dir, val); | |
| 596 | + if (ret < 0) | |
| 597 | + goto err; | |
| 598 | + } | |
| 599 | + data->px_low_th = val; | |
| 600 | + mutex_unlock(&data->lock); | |
| 601 | + break; | |
| 602 | + default: | |
| 603 | + return -EINVAL; | |
| 604 | + } | |
| 605 | + | |
| 606 | + return 0; | |
| 607 | +err: | |
| 608 | + mutex_unlock(&data->lock); | |
| 609 | + return ret; | |
| 610 | +} | |
| 611 | + | |
| 612 | +static int us5182d_read_event_config(struct iio_dev *indio_dev, | |
| 613 | + const struct iio_chan_spec *chan, enum iio_event_type type, | |
| 614 | + enum iio_event_direction dir) | |
| 615 | +{ | |
| 616 | + struct us5182d_data *data = iio_priv(indio_dev); | |
| 617 | + int ret; | |
| 618 | + | |
| 619 | + switch (dir) { | |
| 620 | + case IIO_EV_DIR_RISING: | |
| 621 | + mutex_lock(&data->lock); | |
| 622 | + ret = data->rising_en; | |
| 623 | + mutex_unlock(&data->lock); | |
| 624 | + break; | |
| 625 | + case IIO_EV_DIR_FALLING: | |
| 626 | + mutex_lock(&data->lock); | |
| 627 | + ret = data->falling_en; | |
| 628 | + mutex_unlock(&data->lock); | |
| 629 | + break; | |
| 630 | + default: | |
| 631 | + ret = -EINVAL; | |
| 632 | + break; | |
| 633 | + } | |
| 634 | + | |
| 635 | + return ret; | |
| 636 | +} | |
| 637 | + | |
| 638 | +static int us5182d_write_event_config(struct iio_dev *indio_dev, | |
| 639 | + const struct iio_chan_spec *chan, enum iio_event_type type, | |
| 640 | + enum iio_event_direction dir, int state) | |
| 641 | +{ | |
| 642 | + struct us5182d_data *data = iio_priv(indio_dev); | |
| 643 | + int ret; | |
| 644 | + u16 new_th; | |
| 645 | + | |
| 646 | + mutex_lock(&data->lock); | |
| 647 | + | |
| 648 | + switch (dir) { | |
| 649 | + case IIO_EV_DIR_RISING: | |
| 650 | + if (data->rising_en == state) { | |
| 651 | + mutex_unlock(&data->lock); | |
| 652 | + return 0; | |
| 653 | + } | |
| 654 | + new_th = US5182D_PXH_TH_DISABLE; | |
| 655 | + if (state) { | |
| 656 | + data->power_mode = US5182D_CONTINUOUS; | |
| 657 | + ret = us5182d_set_power_state(data, true); | |
| 658 | + if (ret < 0) | |
| 659 | + goto err; | |
| 660 | + ret = us5182d_px_enable(data); | |
| 661 | + if (ret < 0) | |
| 662 | + goto err_poweroff; | |
| 663 | + new_th = data->px_high_th; | |
| 664 | + } | |
| 665 | + ret = us5182d_setup_prox(indio_dev, dir, new_th); | |
| 666 | + if (ret < 0) | |
| 667 | + goto err_poweroff; | |
| 668 | + data->rising_en = state; | |
| 669 | + break; | |
| 670 | + case IIO_EV_DIR_FALLING: | |
| 671 | + if (data->falling_en == state) { | |
| 672 | + mutex_unlock(&data->lock); | |
| 673 | + return 0; | |
| 674 | + } | |
| 675 | + new_th = US5182D_PXL_TH_DISABLE; | |
| 676 | + if (state) { | |
| 677 | + data->power_mode = US5182D_CONTINUOUS; | |
| 678 | + ret = us5182d_set_power_state(data, true); | |
| 679 | + if (ret < 0) | |
| 680 | + goto err; | |
| 681 | + ret = us5182d_px_enable(data); | |
| 682 | + if (ret < 0) | |
| 683 | + goto err_poweroff; | |
| 684 | + new_th = data->px_low_th; | |
| 685 | + } | |
| 686 | + ret = us5182d_setup_prox(indio_dev, dir, new_th); | |
| 687 | + if (ret < 0) | |
| 688 | + goto err_poweroff; | |
| 689 | + data->falling_en = state; | |
| 690 | + break; | |
| 691 | + default: | |
| 692 | + ret = -EINVAL; | |
| 693 | + goto err; | |
| 694 | + } | |
| 695 | + | |
| 696 | + if (!state) { | |
| 697 | + ret = us5182d_set_power_state(data, false); | |
| 698 | + if (ret < 0) | |
| 699 | + goto err; | |
| 700 | + } | |
| 701 | + | |
| 702 | + if (!data->falling_en && !data->rising_en && !data->default_continuous) | |
| 703 | + data->power_mode = US5182D_ONESHOT; | |
| 704 | + | |
| 705 | + mutex_unlock(&data->lock); | |
| 706 | + return 0; | |
| 707 | + | |
| 708 | +err_poweroff: | |
| 709 | + if (state) | |
| 710 | + us5182d_set_power_state(data, false); | |
| 711 | +err: | |
| 712 | + mutex_unlock(&data->lock); | |
| 713 | + return ret; | |
| 714 | +} | |
| 715 | + | |
| 346 | 716 | static const struct iio_info us5182d_info = { |
| 347 | 717 | .driver_module = THIS_MODULE, |
| 348 | 718 | .read_raw = us5182d_read_raw, |
| 349 | 719 | .write_raw = us5182d_write_raw, |
| 350 | 720 | .attrs = &us5182d_attr_group, |
| 721 | + .read_event_value = &us5182d_read_thresh, | |
| 722 | + .write_event_value = &us5182d_write_thresh, | |
| 723 | + .read_event_config = &us5182d_read_event_config, | |
| 724 | + .write_event_config = &us5182d_write_event_config, | |
| 351 | 725 | }; |
| 352 | 726 | |
| 353 | 727 | static int us5182d_reset(struct iio_dev *indio_dev) |
| @@ -368,6 +742,10 @@ static int us5182d_init(struct iio_dev *indio_dev) · 14 unmodified lines | ||
| 368 | 742 | return ret; |
| 369 | 743 | |
| 370 | 744 | data->opmode = 0; |
| 745 | + data->power_mode = US5182D_CONTINUOUS; | |
| 746 | + data->px_low_th = US5182D_REG_PXL_TH_DEFAULT; | |
| 747 | + data->px_high_th = US5182D_REG_PXH_TH_DEFAULT; | |
| 748 | + | |
| 371 | 749 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { |
| 372 | 750 | ret = i2c_smbus_write_byte_data(data->client, |
| 373 | 751 | us5182d_regvals[i].reg, |
| @@ -376,7 +754,17 @@ static int us5182d_init(struct iio_dev *indio_dev) · 2 unmodified lines | ||
| 376 | 754 | return ret; |
| 377 | 755 | } |
| 378 | 756 | |
| 379 | − return 0; | |
| 757 | + data->als_enabled = true; | |
| 758 | + data->px_enabled = true; | |
| 759 | + | |
| 760 | + if (!data->default_continuous) { | |
| 761 | + ret = us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN); | |
| 762 | + if (ret < 0) | |
| 763 | + return ret; | |
| 764 | + data->power_mode = US5182D_ONESHOT; | |
| 765 | + } | |
| 766 | + | |
| 767 | + return ret; | |
| 380 | 768 | } |
| 381 | 769 | |
| 382 | 770 | static void us5182d_get_platform_data(struct iio_dev *indio_dev) |
| @@ -399,6 +787,8 @@ static void us5182d_get_platform_data(struct iio_dev *indio_dev) · 16 unmodified lines | ||
| 399 | 787 | "upisemi,lower-dark-gain", |
| 400 | 788 | &data->lower_dark_gain)) |
| 401 | 789 | data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT; |
| 790 | + data->default_continuous = device_property_read_bool(&data->client->dev, | |
| 791 | + "upisemi,continuous"); | |
| 402 | 792 | } |
| 403 | 793 | |
| 404 | 794 | static int us5182d_dark_gain_config(struct iio_dev *indio_dev) |
| @@ -426,6 +816,33 @@ static int us5182d_dark_gain_config(struct iio_dev *indio_dev) · 21 unmodified lines | ||
| 426 | 816 | US5182D_REG_DARK_AUTO_EN_DEFAULT); |
| 427 | 817 | } |
| 428 | 818 | |
| 819 | +static irqreturn_t us5182d_irq_thread_handler(int irq, void *private) | |
| 820 | +{ | |
| 821 | + struct iio_dev *indio_dev = private; | |
| 822 | + struct us5182d_data *data = iio_priv(indio_dev); | |
| 823 | + enum iio_event_direction dir; | |
| 824 | + int ret; | |
| 825 | + u64 ev; | |
| 826 | + | |
| 827 | + ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | |
| 828 | + if (ret < 0) { | |
| 829 | + dev_err(&data->client->dev, "i2c transfer error in irq\n"); | |
| 830 | + return IRQ_HANDLED; | |
| 831 | + } | |
| 832 | + | |
| 833 | + dir = ret & US5182D_CFG0_PROX ? IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING; | |
| 834 | + ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, IIO_EV_TYPE_THRESH, dir); | |
| 835 | + | |
| 836 | + iio_push_event(indio_dev, ev, iio_get_time_ns()); | |
| 837 | + | |
| 838 | + ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, | |
| 839 | + ret & ~US5182D_CFG0_PX_IRQ); | |
| 840 | + if (ret < 0) | |
| 841 | + dev_err(&data->client->dev, "i2c transfer error in irq\n"); | |
| 842 | + | |
| 843 | + return IRQ_HANDLED; | |
| 844 | +} | |
| 845 | + | |
| 429 | 846 | static int us5182d_probe(struct i2c_client *client, |
| 430 | 847 | const struct i2c_device_id *id) |
| 431 | 848 | { |
| @@ -457,6 +874,16 @@ static int us5182d_probe(struct i2c_client *client, · 25 unmodified lines | ||
| 457 | 874 | return (ret < 0) ? ret : -ENODEV; |
| 458 | 875 | } |
| 459 | 876 | |
| 877 | + if (client->irq > 0) { | |
| 878 | + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, | |
| 879 | + us5182d_irq_thread_handler, | |
| 880 | + IRQF_TRIGGER_LOW | IRQF_ONESHOT, | |
| 881 | + "us5182d-irq", indio_dev); | |
| 882 | + if (ret < 0) | |
| 883 | + return ret; | |
| 884 | + } else | |
| 885 | + dev_warn(&client->dev, "no valid irq found\n"); | |
| 886 | + | |
| 460 | 887 | us5182d_get_platform_data(indio_dev); |
| 461 | 888 | ret = us5182d_init(indio_dev); |
| 462 | 889 | if (ret < 0) |
| @@ -464,18 +891,73 @@ static int us5182d_probe(struct i2c_client *client, · 1 unmodified line | ||
| 464 | 891 | |
| 465 | 892 | ret = us5182d_dark_gain_config(indio_dev); |
| 466 | 893 | if (ret < 0) |
| 467 | − return ret; | |
| 894 | + goto out_err; | |
| 895 | + | |
| 896 | + if (data->default_continuous) { | |
| 897 | + pm_runtime_set_active(&client->dev); | |
| 898 | + if (ret < 0) | |
| 899 | + goto out_err; | |
| 900 | + } | |
| 901 | + | |
| 902 | + pm_runtime_enable(&client->dev); | |
| 903 | + pm_runtime_set_autosuspend_delay(&client->dev, | |
| 904 | + US5182D_SLEEP_MS); | |
| 905 | + pm_runtime_use_autosuspend(&client->dev); | |
| 906 | + | |
| 907 | + ret = iio_device_register(indio_dev); | |
| 908 | + if (ret < 0) | |
| 909 | + goto out_err; | |
| 910 | + | |
| 911 | + return 0; | |
| 912 | + | |
| 913 | +out_err: | |
| 914 | + us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN); | |
| 915 | + return ret; | |
| 468 | 916 | |
| 469 | − return iio_device_register(indio_dev); | |
| 470 | 917 | } |
| 471 | 918 | |
| 472 | 919 | static int us5182d_remove(struct i2c_client *client) |
| 473 | 920 | { |
| 921 | + struct us5182d_data *data = iio_priv(i2c_get_clientdata(client)); | |
| 922 | + | |
| 474 | 923 | iio_device_unregister(i2c_get_clientdata(client)); |
| 475 | − return i2c_smbus_write_byte_data(client, US5182D_REG_CFG0, | |
| 476 | − US5182D_CFG0_SHUTDOWN_EN); | |
| 924 | + | |
| 925 | + pm_runtime_disable(&client->dev); | |
| 926 | + pm_runtime_set_suspended(&client->dev); | |
| 927 | + | |
| 928 | + return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN); | |
| 929 | +} | |
| 930 | + | |
| 931 | +#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM) | |
| 932 | +static int us5182d_suspend(struct device *dev) | |
| 933 | +{ | |
| 934 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 935 | + struct us5182d_data *data = iio_priv(indio_dev); | |
| 936 | + | |
| 937 | + if (data->power_mode == US5182D_CONTINUOUS) | |
| 938 | + return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN); | |
| 939 | + | |
| 940 | + return 0; | |
| 477 | 941 | } |
| 478 | 942 | |
| 943 | +static int us5182d_resume(struct device *dev) | |
| 944 | +{ | |
| 945 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 946 | + struct us5182d_data *data = iio_priv(indio_dev); | |
| 947 | + | |
| 948 | + if (data->power_mode == US5182D_CONTINUOUS) | |
| 949 | + return us5182d_shutdown_en(data, | |
| 950 | + ~US5182D_CFG0_SHUTDOWN_EN & 0xff); | |
| 951 | + | |
| 952 | + return 0; | |
| 953 | +} | |
| 954 | +#endif | |
| 955 | + | |
| 956 | +static const struct dev_pm_ops us5182d_pm_ops = { | |
| 957 | + SET_SYSTEM_SLEEP_PM_OPS(us5182d_suspend, us5182d_resume) | |
| 958 | + SET_RUNTIME_PM_OPS(us5182d_suspend, us5182d_resume, NULL) | |
| 959 | +}; | |
| 960 | + | |
| 479 | 961 | static const struct acpi_device_id us5182d_acpi_match[] = { |
| 480 | 962 | { "USD5182", 0}, |
| 481 | 963 | {} |
| @@ -493,6 +975,7 @@ MODULE_DEVICE_TABLE(i2c, us5182d_id); · 11 unmodified lines | ||
| 493 | 975 | static struct i2c_driver us5182d_driver = { |
| 494 | 976 | .driver = { |
| 495 | 977 | .name = US5182D_DRV_NAME, |
| 978 | + .pm = &us5182d_pm_ops, | |
| 496 | 979 | .acpi_match_table = ACPI_PTR(us5182d_acpi_match), |
| 497 | 980 | }, |
| 498 | 981 | .probe = us5182d_probe, |
| @@ -928,27 +928,24 @@ static int bmc150_magn_probe(struct i2c_client *client, · 927 unmodified lines | ||
| 928 | 928 | goto err_free_irq; |
| 929 | 929 | } |
| 930 | 930 | |
| 931 | − ret = iio_device_register(indio_dev); | |
| 932 | − if (ret < 0) { | |
| 933 | − dev_err(&client->dev, "unable to register iio device\n"); | |
| 934 | − goto err_buffer_cleanup; | |
| 935 | − } | |
| 936 | − | |
| 937 | 931 | ret = pm_runtime_set_active(&client->dev); |
| 938 | 932 | if (ret) |
| 939 | − goto err_iio_unregister; | |
| 933 | + goto err_buffer_cleanup; | |
| 940 | 934 | |
| 941 | 935 | pm_runtime_enable(&client->dev); |
| 942 | 936 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 943 | 937 | BMC150_MAGN_AUTO_SUSPEND_DELAY_MS); |
| 944 | 938 | pm_runtime_use_autosuspend(&client->dev); |
| 945 | 939 | |
| 946 | − dev_dbg(&indio_dev->dev, "Registered device %s\n", name); | |
| 940 | + ret = iio_device_register(indio_dev); | |
| 941 | + if (ret < 0) { | |
| 942 | + dev_err(&client->dev, "unable to register iio device\n"); | |
| 943 | + goto err_buffer_cleanup; | |
| 944 | + } | |
| 947 | 945 | |
| 946 | + dev_dbg(&indio_dev->dev, "Registered device %s\n", name); | |
| 948 | 947 | return 0; |
| 949 | 948 | |
| 950 | −err_iio_unregister: | |
| 951 | − iio_device_unregister(indio_dev); | |
| 952 | 949 | err_buffer_cleanup: |
| 953 | 950 | iio_triggered_buffer_cleanup(indio_dev); |
| 954 | 951 | err_free_irq: |
| @@ -967,11 +964,12 @@ static int bmc150_magn_remove(struct i2c_client *client) · 12 unmodified lines | ||
| 967 | 964 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 968 | 965 | struct bmc150_magn_data *data = iio_priv(indio_dev); |
| 969 | 966 | |
| 967 | + iio_device_unregister(indio_dev); | |
| 968 | + | |
| 970 | 969 | pm_runtime_disable(&client->dev); |
| 971 | 970 | pm_runtime_set_suspended(&client->dev); |
| 972 | 971 | pm_runtime_put_noidle(&client->dev); |
| 973 | 972 | |
| 974 | − iio_device_unregister(indio_dev); | |
| 975 | 973 | iio_triggered_buffer_cleanup(indio_dev); |
| 976 | 974 | |
| 977 | 975 | if (client->irq > 0) |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | 14 | * GNU General Public License for more details. |
| 15 | 15 | * |
| 16 | − * TODO: runtime pm, interrupt mode, and signal strength reporting | |
| 16 | + * TODO: interrupt mode, and signal strength reporting | |
| 17 | 17 | */ |
| 18 | 18 | |
| 19 | 19 | #include <linux/err.h> |
| @@ -21,6 +21,7 @@ · 1 unmodified line | ||
| 21 | 21 | #include <linux/i2c.h> |
| 22 | 22 | #include <linux/delay.h> |
| 23 | 23 | #include <linux/module.h> |
| 24 | +#include <linux/pm_runtime.h> | |
| 24 | 25 | #include <linux/iio/iio.h> |
| 25 | 26 | #include <linux/iio/sysfs.h> |
| 26 | 27 | #include <linux/iio/buffer.h> |
| @@ -35,8 +36,11 @@ · 8 unmodified lines | ||
| 35 | 36 | #define LIDAR_REG_STATUS_INVALID BIT(3) |
| 36 | 37 | #define LIDAR_REG_STATUS_READY BIT(0) |
| 37 | 38 | |
| 38 | −#define LIDAR_REG_DATA_HBYTE 0x0f | |
| 39 | −#define LIDAR_REG_DATA_LBYTE 0x10 | |
| 39 | +#define LIDAR_REG_DATA_HBYTE 0x0f | |
| 40 | +#define LIDAR_REG_DATA_LBYTE 0x10 | |
| 41 | +#define LIDAR_REG_DATA_WORD_READ BIT(7) | |
| 42 | + | |
| 43 | +#define LIDAR_REG_PWR_CONTROL 0x65 | |
| 40 | 44 | |
| 41 | 45 | #define LIDAR_DRV_NAME "lidar" |
| 42 | 46 | |
| @@ -44,6 +48,9 @@ struct lidar_data { · 1 unmodified line | ||
| 44 | 48 | struct iio_dev *indio_dev; |
| 45 | 49 | struct i2c_client *client; |
| 46 | 50 | |
| 51 | + int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len); | |
| 52 | + int i2c_enabled; | |
| 53 | + | |
| 47 | 54 | u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */ |
| 48 | 55 | }; |
| 49 | 56 | |
| @@ -62,7 +69,28 @@ static const struct iio_chan_spec lidar_channels[] = { · 12 unmodified lines | ||
| 62 | 69 | IIO_CHAN_SOFT_TIMESTAMP(1), |
| 63 | 70 | }; |
| 64 | 71 | |
| 65 | −static int lidar_read_byte(struct lidar_data *data, int reg) | |
| 72 | +static int lidar_i2c_xfer(struct lidar_data *data, u8 reg, u8 *val, int len) | |
| 73 | +{ | |
| 74 | + struct i2c_client *client = data->client; | |
| 75 | + struct i2c_msg msg[2]; | |
| 76 | + int ret; | |
| 77 | + | |
| 78 | + msg[0].addr = client->addr; | |
| 79 | + msg[0].flags = client->flags | I2C_M_STOP; | |
| 80 | + msg[0].len = 1; | |
| 81 | + msg[0].buf = (char *) ® | |
| 82 | + | |
| 83 | + msg[1].addr = client->addr; | |
| 84 | + msg[1].flags = client->flags | I2C_M_RD; | |
| 85 | + msg[1].len = len; | |
| 86 | + msg[1].buf = (char *) val; | |
| 87 | + | |
| 88 | + ret = i2c_transfer(client->adapter, msg, 2); | |
| 89 | + | |
| 90 | + return (ret == 2) ? 0 : ret; | |
| 91 | +} | |
| 92 | + | |
| 93 | +static int lidar_smbus_xfer(struct lidar_data *data, u8 reg, u8 *val, int len) | |
| 66 | 94 | { |
| 67 | 95 | struct i2c_client *client = data->client; |
| 68 | 96 | int ret; |
| @@ -72,17 +100,35 @@ static int lidar_read_byte(struct lidar_data *data, int reg) · 3 unmodified lines | ||
| 72 | 100 | * so in turn i2c_smbus_read_byte_data cannot be used |
| 73 | 101 | */ |
| 74 | 102 | |
| 75 | − ret = i2c_smbus_write_byte(client, reg); | |
| 76 | − if (ret < 0) { | |
| 77 | − dev_err(&client->dev, "cannot write addr value"); | |
| 78 | − return ret; | |
| 103 | + while (len--) { | |
| 104 | + ret = i2c_smbus_write_byte(client, reg++); | |
| 105 | + if (ret < 0) { | |
| 106 | + dev_err(&client->dev, "cannot write addr value"); | |
| 107 | + return ret; | |
| 108 | + } | |
| 109 | + | |
| 110 | + ret = i2c_smbus_read_byte(client); | |
| 111 | + if (ret < 0) { | |
| 112 | + dev_err(&client->dev, "cannot read data value"); | |
| 113 | + return ret; | |
| 114 | + } | |
| 115 | + | |
| 116 | + *(val++) = ret; | |
| 79 | 117 | } |
| 80 | 118 | |
| 81 | − ret = i2c_smbus_read_byte(client); | |
| 119 | + return 0; | |
| 120 | +} | |
| 121 | + | |
| 122 | +static int lidar_read_byte(struct lidar_data *data, u8 reg) | |
| 123 | +{ | |
| 124 | + int ret; | |
| 125 | + u8 val; | |
| 126 | + | |
| 127 | + ret = data->xfer(data, reg, &val, 1); | |
| 82 | 128 | if (ret < 0) |
| 83 | − dev_err(&client->dev, "cannot read data value"); | |
| 129 | + return ret; | |
| 84 | 130 | |
| 85 | − return ret; | |
| 131 | + return val; | |
| 86 | 132 | } |
| 87 | 133 | |
| 88 | 134 | static inline int lidar_write_control(struct lidar_data *data, int val) |
| @@ -90,24 +136,22 @@ static inline int lidar_write_control(struct lidar_data *data, int val) · 1 unmodified line | ||
| 90 | 136 | return i2c_smbus_write_byte_data(data->client, LIDAR_REG_CONTROL, val); |
| 91 | 137 | } |
| 92 | 138 | |
| 93 | −static int lidar_read_measurement(struct lidar_data *data, u16 *reg) | |
| 139 | +static inline int lidar_write_power(struct lidar_data *data, int val) | |
| 94 | 140 | { |
| 95 | − int ret; | |
| 96 | − int val; | |
| 97 | − | |
| 98 | − ret = lidar_read_byte(data, LIDAR_REG_DATA_HBYTE); | |
| 99 | − if (ret < 0) | |
| 100 | − return ret; | |
| 101 | − val = ret << 8; | |
| 141 | + return i2c_smbus_write_byte_data(data->client, | |
| 142 | + LIDAR_REG_PWR_CONTROL, val); | |
| 143 | +} | |
| 102 | 144 | |
| 103 | − ret = lidar_read_byte(data, LIDAR_REG_DATA_LBYTE); | |
| 104 | − if (ret < 0) | |
| 105 | − return ret; | |
| 145 | +static int lidar_read_measurement(struct lidar_data *data, u16 *reg) | |
| 146 | +{ | |
| 147 | + int ret = data->xfer(data, LIDAR_REG_DATA_HBYTE | | |
| 148 | + (data->i2c_enabled ? LIDAR_REG_DATA_WORD_READ : 0), | |
| 149 | + (u8 *) reg, 2); | |
| 106 | 150 | |
| 107 | − val |= ret; | |
| 108 | − *reg = val; | |
| 151 | + if (!ret) | |
| 152 | + *reg = be16_to_cpu(*reg); | |
| 109 | 153 | |
| 110 | − return 0; | |
| 154 | + return ret; | |
| 111 | 155 | } |
| 112 | 156 | |
| 113 | 157 | static int lidar_get_measurement(struct lidar_data *data, u16 *reg) |
| @@ -116,6 +160,8 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg) · 2 unmodified lines | ||
| 116 | 160 | int tries = 10; |
| 117 | 161 | int ret; |
| 118 | 162 | |
| 163 | + pm_runtime_get_sync(&client->dev); | |
| 164 | + | |
| 119 | 165 | /* start sample */ |
| 120 | 166 | ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); |
| 121 | 167 | if (ret < 0) { |
| @@ -144,6 +190,8 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg) · 22 unmodified lines | ||
| 144 | 190 | } |
| 145 | 191 | ret = -EIO; |
| 146 | 192 | } |
| 193 | + pm_runtime_mark_last_busy(&client->dev); | |
| 194 | + pm_runtime_put_autosuspend(&client->dev); | |
| 147 | 195 | |
| 148 | 196 | return ret; |
| 149 | 197 | } |
| @@ -221,6 +269,16 @@ static int lidar_probe(struct i2c_client *client, · 71 unmodified lines | ||
| 221 | 269 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
| 222 | 270 | if (!indio_dev) |
| 223 | 271 | return -ENOMEM; |
| 272 | + data = iio_priv(indio_dev); | |
| 273 | + | |
| 274 | + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | |
| 275 | + data->xfer = lidar_i2c_xfer; | |
| 276 | + data->i2c_enabled = 1; | |
| 277 | + } else if (i2c_check_functionality(client->adapter, | |
| 278 | + I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE)) | |
| 279 | + data->xfer = lidar_smbus_xfer; | |
| 280 | + else | |
| 281 | + return -ENOTSUPP; | |
| 224 | 282 | |
| 225 | 283 | indio_dev->info = &lidar_info; |
| 226 | 284 | indio_dev->name = LIDAR_DRV_NAME; |
| @@ -228,7 +286,6 @@ static int lidar_probe(struct i2c_client *client, · 1 unmodified line | ||
| 228 | 286 | indio_dev->num_channels = ARRAY_SIZE(lidar_channels); |
| 229 | 287 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 230 | 288 | |
| 231 | − data = iio_priv(indio_dev); | |
| 232 | 289 | i2c_set_clientdata(client, indio_dev); |
| 233 | 290 | |
| 234 | 291 | data->client = client; |
| @@ -243,6 +300,17 @@ static int lidar_probe(struct i2c_client *client, · 8 unmodified lines | ||
| 243 | 300 | if (ret) |
| 244 | 301 | goto error_unreg_buffer; |
| 245 | 302 | |
| 303 | + pm_runtime_set_autosuspend_delay(&client->dev, 1000); | |
| 304 | + pm_runtime_use_autosuspend(&client->dev); | |
| 305 | + | |
| 306 | + ret = pm_runtime_set_active(&client->dev); | |
| 307 | + if (ret) | |
| 308 | + goto error_unreg_buffer; | |
| 309 | + pm_runtime_enable(&client->dev); | |
| 310 | + | |
| 311 | + pm_runtime_mark_last_busy(&client->dev); | |
| 312 | + pm_runtime_idle(&client->dev); | |
| 313 | + | |
| 246 | 314 | return 0; |
| 247 | 315 | |
| 248 | 316 | error_unreg_buffer: |
| @@ -258,6 +326,9 @@ static int lidar_remove(struct i2c_client *client) · 9 unmodified lines | ||
| 258 | 326 | iio_device_unregister(indio_dev); |
| 259 | 327 | iio_triggered_buffer_cleanup(indio_dev); |
| 260 | 328 | |
| 329 | + pm_runtime_disable(&client->dev); | |
| 330 | + pm_runtime_set_suspended(&client->dev); | |
| 331 | + | |
| 261 | 332 | return 0; |
| 262 | 333 | } |
| 263 | 334 | |
| @@ -273,10 +344,38 @@ static const struct of_device_id lidar_dt_ids[] = { · 9 unmodified lines | ||
| 273 | 344 | }; |
| 274 | 345 | MODULE_DEVICE_TABLE(of, lidar_dt_ids); |
| 275 | 346 | |
| 347 | +#ifdef CONFIG_PM | |
| 348 | +static int lidar_pm_runtime_suspend(struct device *dev) | |
| 349 | +{ | |
| 350 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 351 | + struct lidar_data *data = iio_priv(indio_dev); | |
| 352 | + | |
| 353 | + return lidar_write_power(data, 0x0f); | |
| 354 | +} | |
| 355 | + | |
| 356 | +static int lidar_pm_runtime_resume(struct device *dev) | |
| 357 | +{ | |
| 358 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 359 | + struct lidar_data *data = iio_priv(indio_dev); | |
| 360 | + int ret = lidar_write_power(data, 0); | |
| 361 | + | |
| 362 | + /* regulator and FPGA needs settling time */ | |
| 363 | + usleep_range(15000, 20000); | |
| 364 | + | |
| 365 | + return ret; | |
| 366 | +} | |
| 367 | +#endif | |
| 368 | + | |
| 369 | +static const struct dev_pm_ops lidar_pm_ops = { | |
| 370 | + SET_RUNTIME_PM_OPS(lidar_pm_runtime_suspend, | |
| 371 | + lidar_pm_runtime_resume, NULL) | |
| 372 | +}; | |
| 373 | + | |
| 276 | 374 | static struct i2c_driver lidar_driver = { |
| 277 | 375 | .driver = { |
| 278 | 376 | .name = LIDAR_DRV_NAME, |
| 279 | 377 | .of_match_table = of_match_ptr(lidar_dt_ids), |
| 378 | + .pm = &lidar_pm_ops, | |
| 280 | 379 | }, |
| 281 | 380 | .probe = lidar_probe, |
| 282 | 381 | .remove = lidar_remove, |
| @@ -5,6 +5,16 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | menu "Triggers - standalone" |
| 7 | 7 | |
| 8 | +config IIO_HRTIMER_TRIGGER | |
| 9 | + tristate "High resolution timer trigger" | |
| 10 | + depends on IIO_SW_TRIGGER | |
| 11 | + help | |
| 12 | + Provides a frequency based IIO trigger using high resolution | |
| 13 | + timers as interrupt source. | |
| 14 | + | |
| 15 | + To compile this driver as a module, choose M here: the | |
| 16 | + module will be called iio-trig-hrtimer. | |
| 17 | + | |
| 8 | 18 | config IIO_INTERRUPT_TRIGGER |
| 9 | 19 | tristate "Generic interrupt trigger" |
| 10 | 20 | help |
| @@ -3,5 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | # |
| 4 | 4 | |
| 5 | 5 | # When adding new entries keep the list in alphabetical order |
| 6 | + | |
| 7 | +obj-$(CONFIG_IIO_HRTIMER_TRIGGER) += iio-trig-hrtimer.o | |
| 6 | 8 | obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o |
| 7 | 9 | obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o |
| @@ -0,0 +1,193 @@ | ||
| 1 | +/** | |
| 2 | + * The industrial I/O periodic hrtimer trigger driver | |
| 3 | + * | |
| 4 | + * Copyright (C) Intuitive Aerial AB | |
| 5 | + * Written by Marten Svanfeldt, marten@intuitiveaerial.com | |
| 6 | + * Copyright (C) 2012, Analog Device Inc. | |
| 7 | + * Author: Lars-Peter Clausen <lars@metafoo.de> | |
| 8 | + * Copyright (C) 2015, Intel Corporation | |
| 9 | + * | |
| 10 | + * This program is free software; you can redistribute it and/or modify it | |
| 11 | + * under the terms of the GNU General Public License version 2 as published by | |
| 12 | + * the Free Software Foundation. | |
| 13 | + * | |
| 14 | + */ | |
| 15 | +#include <linux/kernel.h> | |
| 16 | +#include <linux/slab.h> | |
| 17 | +#include <linux/hrtimer.h> | |
| 18 | + | |
| 19 | +#include <linux/iio/iio.h> | |
| 20 | +#include <linux/iio/trigger.h> | |
| 21 | +#include <linux/iio/sw_trigger.h> | |
| 22 | + | |
| 23 | +/* default sampling frequency - 100Hz */ | |
| 24 | +#define HRTIMER_DEFAULT_SAMPLING_FREQUENCY 100 | |
| 25 | + | |
| 26 | +struct iio_hrtimer_info { | |
| 27 | + struct iio_sw_trigger swt; | |
| 28 | + struct hrtimer timer; | |
| 29 | + unsigned long sampling_frequency; | |
| 30 | + ktime_t period; | |
| 31 | +}; | |
| 32 | + | |
| 33 | +static struct config_item_type iio_hrtimer_type = { | |
| 34 | + .ct_owner = THIS_MODULE, | |
| 35 | +}; | |
| 36 | + | |
| 37 | +static | |
| 38 | +ssize_t iio_hrtimer_show_sampling_frequency(struct device *dev, | |
| 39 | + struct device_attribute *attr, | |
| 40 | + char *buf) | |
| 41 | +{ | |
| 42 | + struct iio_trigger *trig = to_iio_trigger(dev); | |
| 43 | + struct iio_hrtimer_info *info = iio_trigger_get_drvdata(trig); | |
| 44 | + | |
| 45 | + return snprintf(buf, PAGE_SIZE, "%lu\n", info->sampling_frequency); | |
| 46 | +} | |
| 47 | + | |
| 48 | +static | |
| 49 | +ssize_t iio_hrtimer_store_sampling_frequency(struct device *dev, | |
| 50 | + struct device_attribute *attr, | |
| 51 | + const char *buf, size_t len) | |
| 52 | +{ | |
| 53 | + struct iio_trigger *trig = to_iio_trigger(dev); | |
| 54 | + struct iio_hrtimer_info *info = iio_trigger_get_drvdata(trig); | |
| 55 | + unsigned long val; | |
| 56 | + int ret; | |
| 57 | + | |
| 58 | + ret = kstrtoul(buf, 10, &val); | |
| 59 | + if (ret) | |
| 60 | + return ret; | |
| 61 | + | |
| 62 | + if (!val || val > NSEC_PER_SEC) | |
| 63 | + return -EINVAL; | |
| 64 | + | |
| 65 | + info->sampling_frequency = val; | |
| 66 | + info->period = ktime_set(0, NSEC_PER_SEC / val); | |
| 67 | + | |
| 68 | + return len; | |
| 69 | +} | |
| 70 | + | |
| 71 | +static DEVICE_ATTR(sampling_frequency, S_IRUGO | S_IWUSR, | |
| 72 | + iio_hrtimer_show_sampling_frequency, | |
| 73 | + iio_hrtimer_store_sampling_frequency); | |
| 74 | + | |
| 75 | +static struct attribute *iio_hrtimer_attrs[] = { | |
| 76 | + &dev_attr_sampling_frequency.attr, | |
| 77 | + NULL | |
| 78 | +}; | |
| 79 | + | |
| 80 | +static const struct attribute_group iio_hrtimer_attr_group = { | |
| 81 | + .attrs = iio_hrtimer_attrs, | |
| 82 | +}; | |
| 83 | + | |
| 84 | +static const struct attribute_group *iio_hrtimer_attr_groups[] = { | |
| 85 | + &iio_hrtimer_attr_group, | |
| 86 | + NULL | |
| 87 | +}; | |
| 88 | + | |
| 89 | +static enum hrtimer_restart iio_hrtimer_trig_handler(struct hrtimer *timer) | |
| 90 | +{ | |
| 91 | + struct iio_hrtimer_info *info; | |
| 92 | + | |
| 93 | + info = container_of(timer, struct iio_hrtimer_info, timer); | |
| 94 | + | |
| 95 | + hrtimer_forward_now(timer, info->period); | |
| 96 | + iio_trigger_poll(info->swt.trigger); | |
| 97 | + | |
| 98 | + return HRTIMER_RESTART; | |
| 99 | +} | |
| 100 | + | |
| 101 | +static int iio_trig_hrtimer_set_state(struct iio_trigger *trig, bool state) | |
| 102 | +{ | |
| 103 | + struct iio_hrtimer_info *trig_info; | |
| 104 | + | |
| 105 | + trig_info = iio_trigger_get_drvdata(trig); | |
| 106 | + | |
| 107 | + if (state) | |
| 108 | + hrtimer_start(&trig_info->timer, trig_info->period, | |
| 109 | + HRTIMER_MODE_REL); | |
| 110 | + else | |
| 111 | + hrtimer_cancel(&trig_info->timer); | |
| 112 | + | |
| 113 | + return 0; | |
| 114 | +} | |
| 115 | + | |
| 116 | +static const struct iio_trigger_ops iio_hrtimer_trigger_ops = { | |
| 117 | + .owner = THIS_MODULE, | |
| 118 | + .set_trigger_state = iio_trig_hrtimer_set_state, | |
| 119 | +}; | |
| 120 | + | |
| 121 | +static struct iio_sw_trigger *iio_trig_hrtimer_probe(const char *name) | |
| 122 | +{ | |
| 123 | + struct iio_hrtimer_info *trig_info; | |
| 124 | + int ret; | |
| 125 | + | |
| 126 | + trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL); | |
| 127 | + if (!trig_info) | |
| 128 | + return ERR_PTR(-ENOMEM); | |
| 129 | + | |
| 130 | + trig_info->swt.trigger = iio_trigger_alloc("%s", name); | |
| 131 | + if (!trig_info->swt.trigger) { | |
| 132 | + ret = -ENOMEM; | |
| 133 | + goto err_free_trig_info; | |
| 134 | + } | |
| 135 | + | |
| 136 | + iio_trigger_set_drvdata(trig_info->swt.trigger, trig_info); | |
| 137 | + trig_info->swt.trigger->ops = &iio_hrtimer_trigger_ops; | |
| 138 | + trig_info->swt.trigger->dev.groups = iio_hrtimer_attr_groups; | |
| 139 | + | |
| 140 | + hrtimer_init(&trig_info->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | |
| 141 | + trig_info->timer.function = iio_hrtimer_trig_handler; | |
| 142 | + | |
| 143 | + trig_info->sampling_frequency = HRTIMER_DEFAULT_SAMPLING_FREQUENCY; | |
| 144 | + trig_info->period = ktime_set(0, NSEC_PER_SEC / | |
| 145 | + trig_info->sampling_frequency); | |
| 146 | + | |
| 147 | + ret = iio_trigger_register(trig_info->swt.trigger); | |
| 148 | + if (ret) | |
| 149 | + goto err_free_trigger; | |
| 150 | + | |
| 151 | + iio_swt_group_init_type_name(&trig_info->swt, name, &iio_hrtimer_type); | |
| 152 | + return &trig_info->swt; | |
| 153 | +err_free_trigger: | |
| 154 | + iio_trigger_free(trig_info->swt.trigger); | |
| 155 | +err_free_trig_info: | |
| 156 | + kfree(trig_info); | |
| 157 | + | |
| 158 | + return ERR_PTR(ret); | |
| 159 | +} | |
| 160 | + | |
| 161 | +static int iio_trig_hrtimer_remove(struct iio_sw_trigger *swt) | |
| 162 | +{ | |
| 163 | + struct iio_hrtimer_info *trig_info; | |
| 164 | + | |
| 165 | + trig_info = iio_trigger_get_drvdata(swt->trigger); | |
| 166 | + | |
| 167 | + iio_trigger_unregister(swt->trigger); | |
| 168 | + | |
| 169 | + /* cancel the timer after unreg to make sure no one rearms it */ | |
| 170 | + hrtimer_cancel(&trig_info->timer); | |
| 171 | + iio_trigger_free(swt->trigger); | |
| 172 | + kfree(trig_info); | |
| 173 | + | |
| 174 | + return 0; | |
| 175 | +} | |
| 176 | + | |
| 177 | +static const struct iio_sw_trigger_ops iio_trig_hrtimer_ops = { | |
| 178 | + .probe = iio_trig_hrtimer_probe, | |
| 179 | + .remove = iio_trig_hrtimer_remove, | |
| 180 | +}; | |
| 181 | + | |
| 182 | +static struct iio_sw_trigger_type iio_trig_hrtimer = { | |
| 183 | + .name = "hrtimer", | |
| 184 | + .owner = THIS_MODULE, | |
| 185 | + .ops = &iio_trig_hrtimer_ops, | |
| 186 | +}; | |
| 187 | + | |
| 188 | +module_iio_sw_trigger_driver(iio_trig_hrtimer); | |
| 189 | + | |
| 190 | +MODULE_AUTHOR("Marten Svanfeldt <marten@intuitiveaerial.com>"); | |
| 191 | +MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); | |
| 192 | +MODULE_DESCRIPTION("Periodic hrtimer trigger for the IIO subsystem"); | |
| 193 | +MODULE_LICENSE("GPL v2"); | |
| @@ -25,5 +25,13 @@ ion/ · 24 unmodified lines | ||
| 25 | 25 | exposes existing cma regions and doesn't reserve unecessarily memory when |
| 26 | 26 | booting a system which doesn't use ion. |
| 27 | 27 | |
| 28 | +sync framework: | |
| 29 | + - remove CONFIG_SW_SYNC_USER, it is used only for testing/debugging and | |
| 30 | + should not be upstreamed. | |
| 31 | + - port CONFIG_SW_SYNC_USER tests interfaces to use debugfs somehow | |
| 32 | + - port libsync tests to kselftest | |
| 33 | + - clean up and ABI check for security issues | |
| 34 | + - move it to drivers/base/dma-buf | |
| 35 | + | |
| 28 | 36 | Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc: |
| 29 | 37 | Arve Hjønnevåg <arve@android.com> and Riley Andrews <riandrews@android.com> |
| @@ -831,14 +831,14 @@ static struct miscdevice ashmem_misc = { · 830 unmodified lines | ||
| 831 | 831 | |
| 832 | 832 | static int __init ashmem_init(void) |
| 833 | 833 | { |
| 834 | − int ret; | |
| 834 | + int ret = -ENOMEM; | |
| 835 | 835 | |
| 836 | 836 | ashmem_area_cachep = kmem_cache_create("ashmem_area_cache", |
| 837 | 837 | sizeof(struct ashmem_area), |
| 838 | 838 | 0, 0, NULL); |
| 839 | 839 | if (unlikely(!ashmem_area_cachep)) { |
| 840 | 840 | pr_err("failed to create slab cache\n"); |
| 841 | − return -ENOMEM; | |
| 841 | + goto out; | |
| 842 | 842 | } |
| 843 | 843 | |
| 844 | 844 | ashmem_range_cachep = kmem_cache_create("ashmem_range_cache", |
| @@ -846,13 +846,13 @@ static int __init ashmem_init(void) · 1 unmodified line | ||
| 846 | 846 | 0, 0, NULL); |
| 847 | 847 | if (unlikely(!ashmem_range_cachep)) { |
| 848 | 848 | pr_err("failed to create slab cache\n"); |
| 849 | − return -ENOMEM; | |
| 849 | + goto out_free1; | |
| 850 | 850 | } |
| 851 | 851 | |
| 852 | 852 | ret = misc_register(&ashmem_misc); |
| 853 | 853 | if (unlikely(ret)) { |
| 854 | 854 | pr_err("failed to register misc device!\n"); |
| 855 | − return ret; | |
| 855 | + goto out_free2; | |
| 856 | 856 | } |
| 857 | 857 | |
| 858 | 858 | register_shrinker(&ashmem_shrinker); |
| @@ -860,5 +860,12 @@ static int __init ashmem_init(void) · 1 unmodified line | ||
| 860 | 860 | pr_info("initialized\n"); |
| 861 | 861 | |
| 862 | 862 | return 0; |
| 863 | + | |
| 864 | +out_free2: | |
| 865 | + kmem_cache_destroy(ashmem_range_cachep); | |
| 866 | +out_free1: | |
| 867 | + kmem_cache_destroy(ashmem_area_cachep); | |
| 868 | +out: | |
| 869 | + return ret; | |
| 863 | 870 | } |
| 864 | 871 | device_initcall(ashmem_init); |
| @@ -33,3 +33,10 @@ config ION_TEGRA · 32 unmodified lines | ||
| 33 | 33 | help |
| 34 | 34 | Choose this option if you wish to use ion on an nVidia Tegra. |
| 35 | 35 | |
| 36 | +config ION_HISI | |
| 37 | + tristate "Ion for Hisilicon" | |
| 38 | + depends on ARCH_HISI && ION | |
| 39 | + help | |
| 40 | + Choose this option if you wish to use ion on Hisilicon Platform. | |
| 41 | + | |
| 42 | +source "drivers/staging/android/ion/hisilicon/Kconfig" | |
| @@ -7,4 +7,5 @@ endif · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o |
| 9 | 9 | obj-$(CONFIG_ION_TEGRA) += tegra/ |
| 10 | +obj-$(CONFIG_ION_HISI) += hisilicon/ | |
| 10 | 11 | |
| @@ -137,7 +137,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) · 136 unmodified lines | ||
| 137 | 137 | |
| 138 | 138 | data32 = compat_ptr(arg); |
| 139 | 139 | data = compat_alloc_user_space(sizeof(*data)); |
| 140 | − if (data == NULL) | |
| 140 | + if (!data) | |
| 141 | 141 | return -EFAULT; |
| 142 | 142 | |
| 143 | 143 | err = compat_get_ion_allocation_data(data32, data); |
| @@ -156,7 +156,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) · 12 unmodified lines | ||
| 156 | 156 | |
| 157 | 157 | data32 = compat_ptr(arg); |
| 158 | 158 | data = compat_alloc_user_space(sizeof(*data)); |
| 159 | − if (data == NULL) | |
| 159 | + if (!data) | |
| 160 | 160 | return -EFAULT; |
| 161 | 161 | |
| 162 | 162 | err = compat_get_ion_handle_data(data32, data); |
| @@ -173,7 +173,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) · 10 unmodified lines | ||
| 173 | 173 | |
| 174 | 174 | data32 = compat_ptr(arg); |
| 175 | 175 | data = compat_alloc_user_space(sizeof(*data)); |
| 176 | − if (data == NULL) | |
| 176 | + if (!data) | |
| 177 | 177 | return -EFAULT; |
| 178 | 178 | |
| 179 | 179 | err = compat_get_ion_custom_data(data32, data); |
| @@ -0,0 +1,5 @@ | ||
| 1 | +config HI6220_ION | |
| 2 | + bool "Hi6220 ION Driver" | |
| 3 | + depends on ARCH_HISI && ION | |
| 4 | + help | |
| 5 | + Build the Hisilicon Hi6220 ion driver. | |
| @@ -0,0 +1 @@ | ||
| 1 | +obj-$(CONFIG_HI6220_ION) += hi6220_ion.o | |
| @@ -0,0 +1,223 @@ | ||
| 1 | +/* | |
| 2 | + * Hisilicon Hi6220 ION Driver | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015 Hisilicon Limited. | |
| 5 | + * | |
| 6 | + * Author: Chen Feng <puck.chen@hisilicon.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License version 2 as | |
| 10 | + * published by the Free Software Foundation. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#define pr_fmt(fmt) "Ion: " fmt | |
| 14 | + | |
| 15 | +#include <linux/err.h> | |
| 16 | +#include <linux/platform_device.h> | |
| 17 | +#include <linux/slab.h> | |
| 18 | +#include <linux/of.h> | |
| 19 | +#include <linux/mm.h> | |
| 20 | +#include "../ion_priv.h" | |
| 21 | +#include "../ion.h" | |
| 22 | + | |
| 23 | +struct hi6220_ion_type_table { | |
| 24 | + const char *name; | |
| 25 | + enum ion_heap_type type; | |
| 26 | +}; | |
| 27 | + | |
| 28 | +static struct hi6220_ion_type_table ion_type_table[] = { | |
| 29 | + {"ion_system", ION_HEAP_TYPE_SYSTEM}, | |
| 30 | + {"ion_system_contig", ION_HEAP_TYPE_SYSTEM_CONTIG}, | |
| 31 | + {"ion_carveout", ION_HEAP_TYPE_CARVEOUT}, | |
| 32 | + {"ion_chunk", ION_HEAP_TYPE_CHUNK}, | |
| 33 | + {"ion_dma", ION_HEAP_TYPE_DMA}, | |
| 34 | + {"ion_custom", ION_HEAP_TYPE_CUSTOM}, | |
| 35 | +}; | |
| 36 | + | |
| 37 | +static struct ion_device *idev; | |
| 38 | +static int num_heaps; | |
| 39 | +static struct ion_heap **heaps; | |
| 40 | +static struct ion_platform_heap **heaps_data; | |
| 41 | + | |
| 42 | +static int get_type_by_name(const char *name, enum ion_heap_type *type) | |
| 43 | +{ | |
| 44 | + int i; | |
| 45 | + | |
| 46 | + for (i = 0; i < ARRAY_SIZE(ion_type_table); i++) { | |
| 47 | + if (strncmp(name, ion_type_table[i].name, strlen(name))) | |
| 48 | + continue; | |
| 49 | + | |
| 50 | + *type = ion_type_table[i].type; | |
| 51 | + return 0; | |
| 52 | + } | |
| 53 | + | |
| 54 | + return -EINVAL; | |
| 55 | +} | |
| 56 | + | |
| 57 | +static int hi6220_set_platform_data(struct platform_device *pdev) | |
| 58 | +{ | |
| 59 | + unsigned int base; | |
| 60 | + unsigned int size; | |
| 61 | + unsigned int id; | |
| 62 | + const char *heap_name; | |
| 63 | + const char *type_name; | |
| 64 | + enum ion_heap_type type; | |
| 65 | + int ret; | |
| 66 | + struct device_node *np; | |
| 67 | + struct ion_platform_heap *p_data; | |
| 68 | + const struct device_node *dt_node = pdev->dev.of_node; | |
| 69 | + int index = 0; | |
| 70 | + | |
| 71 | + for_each_child_of_node(dt_node, np) | |
| 72 | + num_heaps++; | |
| 73 | + | |
| 74 | + heaps_data = devm_kzalloc(&pdev->dev, | |
| 75 | + sizeof(struct ion_platform_heap *) * | |
| 76 | + num_heaps, | |
| 77 | + GFP_KERNEL); | |
| 78 | + if (!heaps_data) | |
| 79 | + return -ENOMEM; | |
| 80 | + | |
| 81 | + for_each_child_of_node(dt_node, np) { | |
| 82 | + ret = of_property_read_string(np, "heap-name", &heap_name); | |
| 83 | + if (ret < 0) { | |
| 84 | + pr_err("check the name of node %s\n", np->name); | |
| 85 | + continue; | |
| 86 | + } | |
| 87 | + | |
| 88 | + ret = of_property_read_u32(np, "heap-id", &id); | |
| 89 | + if (ret < 0) { | |
| 90 | + pr_err("check the id %s\n", np->name); | |
| 91 | + continue; | |
| 92 | + } | |
| 93 | + | |
| 94 | + ret = of_property_read_u32(np, "heap-base", &base); | |
| 95 | + if (ret < 0) { | |
| 96 | + pr_err("check the base of node %s\n", np->name); | |
| 97 | + continue; | |
| 98 | + } | |
| 99 | + | |
| 100 | + ret = of_property_read_u32(np, "heap-size", &size); | |
| 101 | + if (ret < 0) { | |
| 102 | + pr_err("check the size of node %s\n", np->name); | |
| 103 | + continue; | |
| 104 | + } | |
| 105 | + | |
| 106 | + ret = of_property_read_string(np, "heap-type", &type_name); | |
| 107 | + if (ret < 0) { | |
| 108 | + pr_err("check the type of node %s\n", np->name); | |
| 109 | + continue; | |
| 110 | + } | |
| 111 | + | |
| 112 | + ret = get_type_by_name(type_name, &type); | |
| 113 | + if (ret < 0) { | |
| 114 | + pr_err("type name error %s!\n", type_name); | |
| 115 | + continue; | |
| 116 | + } | |
| 117 | + pr_info("heap index %d : name %s base 0x%x size 0x%x id %d type %d\n", | |
| 118 | + index, heap_name, base, size, id, type); | |
| 119 | + | |
| 120 | + p_data = devm_kzalloc(&pdev->dev, | |
| 121 | + sizeof(struct ion_platform_heap), | |
| 122 | + GFP_KERNEL); | |
| 123 | + if (!p_data) | |
| 124 | + return -ENOMEM; | |
| 125 | + | |
| 126 | + p_data->name = heap_name; | |
| 127 | + p_data->base = base; | |
| 128 | + p_data->size = size; | |
| 129 | + p_data->id = id; | |
| 130 | + p_data->type = type; | |
| 131 | + | |
| 132 | + heaps_data[index] = p_data; | |
| 133 | + index++; | |
| 134 | + } | |
| 135 | + return 0; | |
| 136 | +} | |
| 137 | + | |
| 138 | +static int hi6220_ion_probe(struct platform_device *pdev) | |
| 139 | +{ | |
| 140 | + int i; | |
| 141 | + int err; | |
| 142 | + static struct ion_platform_heap *p_heap; | |
| 143 | + | |
| 144 | + idev = ion_device_create(NULL); | |
| 145 | + err = hi6220_set_platform_data(pdev); | |
| 146 | + if (err) { | |
| 147 | + pr_err("ion set platform data error!\n"); | |
| 148 | + goto err_free_idev; | |
| 149 | + } | |
| 150 | + heaps = devm_kzalloc(&pdev->dev, | |
| 151 | + sizeof(struct ion_heap *) * num_heaps, | |
| 152 | + GFP_KERNEL); | |
| 153 | + if (!heaps) { | |
| 154 | + err = -ENOMEM; | |
| 155 | + goto err_free_idev; | |
| 156 | + } | |
| 157 | + | |
| 158 | + /* | |
| 159 | + * create the heaps as specified in the dts file | |
| 160 | + */ | |
| 161 | + for (i = 0; i < num_heaps; i++) { | |
| 162 | + p_heap = heaps_data[i]; | |
| 163 | + heaps[i] = ion_heap_create(p_heap); | |
| 164 | + if (IS_ERR_OR_NULL(heaps[i])) { | |
| 165 | + err = PTR_ERR(heaps[i]); | |
| 166 | + goto err_free_heaps; | |
| 167 | + } | |
| 168 | + | |
| 169 | + ion_device_add_heap(idev, heaps[i]); | |
| 170 | + | |
| 171 | + pr_info("%s: adding heap %s of type %d with %lx@%lx\n", | |
| 172 | + __func__, p_heap->name, p_heap->type, | |
| 173 | + p_heap->base, (unsigned long)p_heap->size); | |
| 174 | + } | |
| 175 | + return err; | |
| 176 | + | |
| 177 | +err_free_heaps: | |
| 178 | + for (i = 0; i < num_heaps; ++i) { | |
| 179 | + ion_heap_destroy(heaps[i]); | |
| 180 | + heaps[i] = NULL; | |
| 181 | + } | |
| 182 | +err_free_idev: | |
| 183 | + ion_device_destroy(idev); | |
| 184 | + | |
| 185 | + return err; | |
| 186 | +} | |
| 187 | + | |
| 188 | +static int hi6220_ion_remove(struct platform_device *pdev) | |
| 189 | +{ | |
| 190 | + int i; | |
| 191 | + | |
| 192 | + for (i = 0; i < num_heaps; i++) { | |
| 193 | + ion_heap_destroy(heaps[i]); | |
| 194 | + heaps[i] = NULL; | |
| 195 | + } | |
| 196 | + ion_device_destroy(idev); | |
| 197 | + | |
| 198 | + return 0; | |
| 199 | +} | |
| 200 | + | |
| 201 | +static const struct of_device_id hi6220_ion_match_table[] = { | |
| 202 | + {.compatible = "hisilicon,hi6220-ion"}, | |
| 203 | + {}, | |
| 204 | +}; | |
| 205 | + | |
| 206 | +static struct platform_driver hi6220_ion_driver = { | |
| 207 | + .probe = hi6220_ion_probe, | |
| 208 | + .remove = hi6220_ion_remove, | |
| 209 | + .driver = { | |
| 210 | + .name = "ion-hi6220", | |
| 211 | + .of_match_table = hi6220_ion_match_table, | |
| 212 | + }, | |
| 213 | +}; | |
| 214 | + | |
| 215 | +static int __init hi6220_ion_init(void) | |
| 216 | +{ | |
| 217 | + int ret; | |
| 218 | + | |
| 219 | + ret = platform_driver_register(&hi6220_ion_driver); | |
| 220 | + return ret; | |
| 221 | +} | |
| 222 | + | |
| 223 | +subsys_initcall(hi6220_ion_init); | |
| @@ -43,7 +43,7 @@ · 42 unmodified lines | ||
| 43 | 43 | #include <linux/profile.h> |
| 44 | 44 | #include <linux/notifier.h> |
| 45 | 45 | |
| 46 | −static uint32_t lowmem_debug_level = 1; | |
| 46 | +static u32 lowmem_debug_level = 1; | |
| 47 | 47 | static short lowmem_adj[6] = { |
| 48 | 48 | 0, |
| 49 | 49 | 1, |
| @@ -105,8 +105,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) · 55 unmodified lines | ||
| 105 | 105 | } |
| 106 | 106 | |
| 107 | 107 | lowmem_print(3, "lowmem_scan %lu, %x, ofree %d %d, ma %hd\n", |
| 108 | − sc->nr_to_scan, sc->gfp_mask, other_free, | |
| 109 | − other_file, min_score_adj); | |
| 108 | + sc->nr_to_scan, sc->gfp_mask, other_free, | |
| 109 | + other_file, min_score_adj); | |
| 110 | 110 | |
| 111 | 111 | if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) { |
| 112 | 112 | lowmem_print(5, "lowmem_scan %lu, %x, return 0\n", |
| @@ -43,7 +43,7 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, · 42 unmodified lines | ||
| 43 | 43 | return NULL; |
| 44 | 44 | |
| 45 | 45 | obj = kzalloc(size, GFP_KERNEL); |
| 46 | − if (obj == NULL) | |
| 46 | + if (!obj) | |
| 47 | 47 | return NULL; |
| 48 | 48 | |
| 49 | 49 | kref_init(&obj->kref); |
| @@ -130,7 +130,7 @@ struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size) · 80 unmodified lines | ||
| 130 | 130 | return NULL; |
| 131 | 131 | |
| 132 | 132 | pt = kzalloc(size, GFP_KERNEL); |
| 133 | − if (pt == NULL) | |
| 133 | + if (!pt) | |
| 134 | 134 | return NULL; |
| 135 | 135 | |
| 136 | 136 | spin_lock_irqsave(&obj->child_list_lock, flags); |
| @@ -155,7 +155,7 @@ static struct sync_fence *sync_fence_alloc(int size, const char *name) · 18 unmodified lines | ||
| 155 | 155 | struct sync_fence *fence; |
| 156 | 156 | |
| 157 | 157 | fence = kzalloc(size, GFP_KERNEL); |
| 158 | − if (fence == NULL) | |
| 158 | + if (!fence) | |
| 159 | 159 | return NULL; |
| 160 | 160 | |
| 161 | 161 | fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops, |
| @@ -188,34 +188,39 @@ static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) · 26 unmodified lines | ||
| 188 | 188 | } |
| 189 | 189 | |
| 190 | 190 | /* TODO: implement a create which takes more that one sync_pt */ |
| 191 | −struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt) | |
| 191 | +struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt) | |
| 192 | 192 | { |
| 193 | 193 | struct sync_fence *fence; |
| 194 | 194 | |
| 195 | 195 | fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name); |
| 196 | − if (fence == NULL) | |
| 196 | + if (!fence) | |
| 197 | 197 | return NULL; |
| 198 | 198 | |
| 199 | 199 | fence->num_fences = 1; |
| 200 | 200 | atomic_set(&fence->status, 1); |
| 201 | 201 | |
| 202 | − fence->cbs[0].sync_pt = &pt->base; | |
| 202 | + fence->cbs[0].sync_pt = pt; | |
| 203 | 203 | fence->cbs[0].fence = fence; |
| 204 | − if (fence_add_callback(&pt->base, &fence->cbs[0].cb, | |
| 205 | − fence_check_cb_func)) | |
| 204 | + if (fence_add_callback(pt, &fence->cbs[0].cb, fence_check_cb_func)) | |
| 206 | 205 | atomic_dec(&fence->status); |
| 207 | 206 | |
| 208 | 207 | sync_fence_debug_add(fence); |
| 209 | 208 | |
| 210 | 209 | return fence; |
| 211 | 210 | } |
| 211 | +EXPORT_SYMBOL(sync_fence_create_dma); | |
| 212 | + | |
| 213 | +struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt) | |
| 214 | +{ | |
| 215 | + return sync_fence_create_dma(name, &pt->base); | |
| 216 | +} | |
| 212 | 217 | EXPORT_SYMBOL(sync_fence_create); |
| 213 | 218 | |
| 214 | 219 | struct sync_fence *sync_fence_fdget(int fd) |
| 215 | 220 | { |
| 216 | 221 | struct file *file = fget(fd); |
| 217 | 222 | |
| 218 | − if (file == NULL) | |
| 223 | + if (!file) | |
| 219 | 224 | return NULL; |
| 220 | 225 | |
| 221 | 226 | if (file->f_op != &sync_fence_fops) |
| @@ -262,7 +267,7 @@ struct sync_fence *sync_fence_merge(const char *name, · 40 unmodified lines | ||
| 262 | 267 | unsigned long size = offsetof(struct sync_fence, cbs[num_fences]); |
| 263 | 268 | |
| 264 | 269 | fence = sync_fence_alloc(size, name); |
| 265 | − if (fence == NULL) | |
| 270 | + if (!fence) | |
| 266 | 271 | return NULL; |
| 267 | 272 | |
| 268 | 273 | atomic_set(&fence->status, num_fences); |
| @@ -313,7 +318,7 @@ struct sync_fence *sync_fence_merge(const char *name, · 44 unmodified lines | ||
| 313 | 318 | EXPORT_SYMBOL(sync_fence_merge); |
| 314 | 319 | |
| 315 | 320 | int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode, |
| 316 | − int wake_flags, void *key) | |
| 321 | + int wake_flags, void *key) | |
| 317 | 322 | { |
| 318 | 323 | struct sync_fence_waiter *wait; |
| 319 | 324 | |
| @@ -353,7 +358,7 @@ int sync_fence_wait_async(struct sync_fence *fence, · 33 unmodified lines | ||
| 353 | 358 | EXPORT_SYMBOL(sync_fence_wait_async); |
| 354 | 359 | |
| 355 | 360 | int sync_fence_cancel_async(struct sync_fence *fence, |
| 356 | − struct sync_fence_waiter *waiter) | |
| 361 | + struct sync_fence_waiter *waiter) | |
| 357 | 362 | { |
| 358 | 363 | unsigned long flags; |
| 359 | 364 | int ret = 0; |
| @@ -519,12 +524,10 @@ static const struct fence_ops android_fence_ops = { · 159 unmodified lines | ||
| 519 | 524 | static void sync_fence_free(struct kref *kref) |
| 520 | 525 | { |
| 521 | 526 | struct sync_fence *fence = container_of(kref, struct sync_fence, kref); |
| 522 | − int i, status = atomic_read(&fence->status); | |
| 527 | + int i; | |
| 523 | 528 | |
| 524 | 529 | for (i = 0; i < fence->num_fences; ++i) { |
| 525 | − if (status) | |
| 526 | − fence_remove_callback(fence->cbs[i].sync_pt, | |
| 527 | − &fence->cbs[i].cb); | |
| 530 | + fence_remove_callback(fence->cbs[i].sync_pt, &fence->cbs[i].cb); | |
| 528 | 531 | fence_put(fence->cbs[i].sync_pt); |
| 529 | 532 | } |
| 530 | 533 | |
| @@ -583,14 +586,14 @@ static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg) · 52 unmodified lines | ||
| 583 | 586 | } |
| 584 | 587 | |
| 585 | 588 | fence2 = sync_fence_fdget(data.fd2); |
| 586 | − if (fence2 == NULL) { | |
| 589 | + if (!fence2) { | |
| 587 | 590 | err = -ENOENT; |
| 588 | 591 | goto err_put_fd; |
| 589 | 592 | } |
| 590 | 593 | |
| 591 | 594 | data.name[sizeof(data.name) - 1] = '\0'; |
| 592 | 595 | fence3 = sync_fence_merge(data.name, fence, fence2); |
| 593 | − if (fence3 == NULL) { | |
| 596 | + if (!fence3) { | |
| 594 | 597 | err = -ENOMEM; |
| 595 | 598 | goto err_put_fence2; |
| 596 | 599 | } |
| @@ -666,7 +669,7 @@ static long sync_fence_ioctl_fence_info(struct sync_fence *fence, · 69 unmodified lines | ||
| 666 | 669 | size = 4096; |
| 667 | 670 | |
| 668 | 671 | data = kzalloc(size, GFP_KERNEL); |
| 669 | − if (data == NULL) | |
| 672 | + if (!data) | |
| 670 | 673 | return -ENOMEM; |
| 671 | 674 | |
| 672 | 675 | strlcpy(data->name, fence->name, sizeof(data->name)); |
| @@ -254,6 +254,16 @@ void sync_pt_free(struct sync_pt *pt); · 253 unmodified lines | ||
| 254 | 254 | */ |
| 255 | 255 | struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt); |
| 256 | 256 | |
| 257 | +/** | |
| 258 | + * sync_fence_create_dma() - creates a sync fence from dma-fence | |
| 259 | + * @name: name of fence to create | |
| 260 | + * @pt: dma-fence to add to the fence | |
| 261 | + * | |
| 262 | + * Creates a fence containg @pt. Once this is called, the fence takes | |
| 263 | + * ownership of @pt. | |
| 264 | + */ | |
| 265 | +struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt); | |
| 266 | + | |
| 257 | 267 | /* |
| 258 | 268 | * API for sync_fence consumers |
| 259 | 269 | */ |
| @@ -82,36 +82,42 @@ static const char *sync_status_str(int status) · 81 unmodified lines | ||
| 82 | 82 | return "error"; |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | −static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence) | |
| 85 | +static void sync_print_pt(struct seq_file *s, struct fence *pt, bool fence) | |
| 86 | 86 | { |
| 87 | 87 | int status = 1; |
| 88 | − struct sync_timeline *parent = sync_pt_parent(pt); | |
| 89 | 88 | |
| 90 | − if (fence_is_signaled_locked(&pt->base)) | |
| 91 | − status = pt->base.status; | |
| 89 | + if (fence_is_signaled_locked(pt)) | |
| 90 | + status = pt->status; | |
| 92 | 91 | |
| 93 | 92 | seq_printf(s, " %s%spt %s", |
| 94 | − fence ? parent->name : "", | |
| 93 | + fence && pt->ops->get_timeline_name ? | |
| 94 | + pt->ops->get_timeline_name(pt) : "", | |
| 95 | 95 | fence ? "_" : "", |
| 96 | 96 | sync_status_str(status)); |
| 97 | 97 | |
| 98 | 98 | if (status <= 0) { |
| 99 | 99 | struct timespec64 ts64 = |
| 100 | − ktime_to_timespec64(pt->base.timestamp); | |
| 100 | + ktime_to_timespec64(pt->timestamp); | |
| 101 | 101 | |
| 102 | 102 | seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | − if (parent->ops->timeline_value_str && | |
| 106 | − parent->ops->pt_value_str) { | |
| 105 | + if ((!fence || pt->ops->timeline_value_str) && | |
| 106 | + pt->ops->fence_value_str) { | |
| 107 | 107 | char value[64]; |
| 108 | + bool success; | |
| 108 | 109 | |
| 109 | − parent->ops->pt_value_str(pt, value, sizeof(value)); | |
| 110 | − seq_printf(s, ": %s", value); | |
| 111 | − if (fence) { | |
| 112 | − parent->ops->timeline_value_str(parent, value, | |
| 113 | − sizeof(value)); | |
| 114 | − seq_printf(s, " / %s", value); | |
| 110 | + pt->ops->fence_value_str(pt, value, sizeof(value)); | |
| 111 | + success = strlen(value); | |
| 112 | + | |
| 113 | + if (success) | |
| 114 | + seq_printf(s, ": %s", value); | |
| 115 | + | |
| 116 | + if (success && fence) { | |
| 117 | + pt->ops->timeline_value_str(pt, value, sizeof(value)); | |
| 118 | + | |
| 119 | + if (strlen(value)) | |
| 120 | + seq_printf(s, " / %s", value); | |
| 115 | 121 | } |
| 116 | 122 | } |
| 117 | 123 | |
| @@ -138,7 +144,7 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) · 20 unmodified lines | ||
| 138 | 144 | list_for_each(pos, &obj->child_list_head) { |
| 139 | 145 | struct sync_pt *pt = |
| 140 | 146 | container_of(pos, struct sync_pt, child_list); |
| 141 | − sync_print_pt(s, pt, false); | |
| 147 | + sync_print_pt(s, &pt->base, false); | |
| 142 | 148 | } |
| 143 | 149 | spin_unlock_irqrestore(&obj->child_list_lock, flags); |
| 144 | 150 | } |
| @@ -153,11 +159,7 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) · 8 unmodified lines | ||
| 153 | 159 | sync_status_str(atomic_read(&fence->status))); |
| 154 | 160 | |
| 155 | 161 | for (i = 0; i < fence->num_fences; ++i) { |
| 156 | − struct sync_pt *pt = | |
| 157 | − container_of(fence->cbs[i].sync_pt, | |
| 158 | − struct sync_pt, base); | |
| 159 | − | |
| 160 | − sync_print_pt(s, pt, true); | |
| 162 | + sync_print_pt(s, fence->cbs[i].sync_pt, true); | |
| 161 | 163 | } |
| 162 | 164 | |
| 163 | 165 | spin_lock_irqsave(&fence->wq.lock, flags); |
| @@ -25,7 +25,6 @@ · 24 unmodified lines | ||
| 25 | 25 | #include "timed_output.h" |
| 26 | 26 | #include "timed_gpio.h" |
| 27 | 27 | |
| 28 | − | |
| 29 | 28 | struct timed_gpio_data { |
| 30 | 29 | struct timed_output_dev dev; |
| 31 | 30 | struct hrtimer timer; |
| @@ -76,8 +75,8 @@ static void gpio_enable(struct timed_output_dev *dev, int value) · 44 unmodified lines | ||
| 76 | 75 | value = data->max_timeout; |
| 77 | 76 | |
| 78 | 77 | hrtimer_start(&data->timer, |
| 79 | − ktime_set(value / 1000, (value % 1000) * 1000000), | |
| 80 | − HRTIMER_MODE_REL); | |
| 78 | + ktime_set(value / 1000, (value % 1000) * 1000000), | |
| 79 | + HRTIMER_MODE_REL); | |
| 81 | 80 | } |
| 82 | 81 | |
| 83 | 82 | spin_unlock_irqrestore(&data->lock, flags); |
| @@ -94,8 +93,8 @@ static int timed_gpio_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 94 | 93 | return -EBUSY; |
| 95 | 94 | |
| 96 | 95 | gpio_data = devm_kzalloc(&pdev->dev, |
| 97 | − sizeof(struct timed_gpio_data) * pdata->num_gpios, | |
| 98 | − GFP_KERNEL); | |
| 96 | + sizeof(*gpio_data) * pdata->num_gpios, | |
| 97 | + GFP_KERNEL); | |
| 99 | 98 | if (!gpio_data) |
| 100 | 99 | return -ENOMEM; |
| 101 | 100 | |
| @@ -104,7 +103,7 @@ static int timed_gpio_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 104 | 103 | gpio_dat = &gpio_data[i]; |
| 105 | 104 | |
| 106 | 105 | hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, |
| 107 | − HRTIMER_MODE_REL); | |
| 106 | + HRTIMER_MODE_REL); | |
| 108 | 107 | gpio_dat->timer.function = gpio_timer_func; |
| 109 | 108 | spin_lock_init(&gpio_dat->lock); |
| 110 | 109 | |
| @@ -737,15 +737,23 @@ config COMEDI_ADL_PCI9118 · 736 unmodified lines | ||
| 737 | 737 | called adl_pci9118. |
| 738 | 738 | |
| 739 | 739 | config COMEDI_ADV_PCI1710 |
| 740 | − tristate "Advantech PCI-171x, PCI-1720 and PCI-1731 support" | |
| 740 | + tristate "Advantech PCI-171x and PCI-1731 support" | |
| 741 | 741 | select COMEDI_8254 |
| 742 | 742 | ---help--- |
| 743 | 743 | Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711, |
| 744 | − PCI-1713, PCI-1720 and PCI-1731 | |
| 744 | + PCI-1713 and PCI-1731 | |
| 745 | 745 | |
| 746 | 746 | To compile this driver as a module, choose M here: the module will be |
| 747 | 747 | called adv_pci1710. |
| 748 | 748 | |
| 749 | +config COMEDI_ADV_PCI1720 | |
| 750 | + tristate "Advantech PCI-1720 support" | |
| 751 | + ---help--- | |
| 752 | + Enable support for Advantech PCI-1720 Analog Output board. | |
| 753 | + | |
| 754 | + To compile this driver as a module, choose M here: the module will be | |
| 755 | + called adv_pci1720. | |
| 756 | + | |
| 749 | 757 | config COMEDI_ADV_PCI1723 |
| 750 | 758 | tristate "Advantech PCI-1723 support" |
| 751 | 759 | ---help--- |
| @@ -764,6 +772,14 @@ config COMEDI_ADV_PCI1724 · 12 unmodified lines | ||
| 764 | 772 | To compile this driver as a module, choose M here: the module will be |
| 765 | 773 | called adv_pci1724. |
| 766 | 774 | |
| 775 | +config COMEDI_ADV_PCI1760 | |
| 776 | + tristate "Advantech PCI-1760 support" | |
| 777 | + ---help--- | |
| 778 | + Enable support for Advantech PCI-1760 board. | |
| 779 | + | |
| 780 | + To compile this driver as a module, choose M here: the module will be | |
| 781 | + called adv_pci1760. | |
| 782 | + | |
| 767 | 783 | config COMEDI_ADV_PCI_DIO |
| 768 | 784 | tristate "Advantech PCI DIO card support" |
| 769 | 785 | select COMEDI_8254 |
| @@ -771,8 +787,8 @@ config COMEDI_ADV_PCI_DIO · 1 unmodified line | ||
| 771 | 787 | ---help--- |
| 772 | 788 | Enable support for Advantech PCI DIO cards |
| 773 | 789 | PCI-1730, PCI-1733, PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, |
| 774 | − PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754, PCI-1756, | |
| 775 | − PCI-1760 and PCI-1762 | |
| 790 | + PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754, PCI-1756 and | |
| 791 | + PCI-1762 | |
| 776 | 792 | |
| 777 | 793 | To compile this driver as a module, choose M here: the module will be |
| 778 | 794 | called adv_pci_dio. |
| @@ -1,20 +1,20 @@ | ||
| 1 | 1 | /* |
| 2 | − include/comedi.h (installed as /usr/include/comedi.h) | |
| 3 | − header file for comedi | |
| 4 | − | |
| 5 | − COMEDI - Linux Control and Measurement Device Interface | |
| 6 | − Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> | |
| 7 | − | |
| 8 | − This program is free software; you can redistribute it and/or modify | |
| 9 | − it under the terms of the GNU Lesser General Public License as published by | |
| 10 | − the Free Software Foundation; either version 2 of the License, or | |
| 11 | − (at your option) any later version. | |
| 12 | − | |
| 13 | − This program is distributed in the hope that it will be useful, | |
| 14 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − GNU General Public License for more details. | |
| 17 | −*/ | |
| 2 | + * include/comedi.h (installed as /usr/include/comedi.h) | |
| 3 | + * header file for comedi | |
| 4 | + * | |
| 5 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 6 | + * Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU Lesser General Public License as published by | |
| 10 | + * the Free Software Foundation; either version 2 of the License, or | |
| 11 | + * (at your option) any later version. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | + */ | |
| 18 | 18 | |
| 19 | 19 | #ifndef _COMEDI_H |
| 20 | 20 | #define _COMEDI_H |
| @@ -28,9 +28,9 @@ · 7 unmodified lines | ||
| 28 | 28 | #define COMEDI_MAJOR 98 |
| 29 | 29 | |
| 30 | 30 | /* |
| 31 | − maximum number of minor devices. This can be increased, although | |
| 32 | − kernel structures are currently statically allocated, thus you | |
| 33 | − don't want this to be much more than you actually use. | |
| 31 | + * maximum number of minor devices. This can be increased, although | |
| 32 | + * kernel structures are currently statically allocated, thus you | |
| 33 | + * don't want this to be much more than you actually use. | |
| 34 | 34 | */ |
| 35 | 35 | #define COMEDI_NDEVICES 16 |
| 36 | 36 | |
| @@ -63,21 +63,21 @@ · 26 unmodified lines | ||
| 63 | 63 | /* packs and unpacks a channel/range number */ |
| 64 | 64 | |
| 65 | 65 | #define CR_PACK(chan, rng, aref) \ |
| 66 | − ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan)) | |
| 66 | + ((((aref) & 0x3) << 24) | (((rng) & 0xff) << 16) | (chan)) | |
| 67 | 67 | #define CR_PACK_FLAGS(chan, range, aref, flags) \ |
| 68 | 68 | (CR_PACK(chan, range, aref) | ((flags) & CR_FLAGS_MASK)) |
| 69 | 69 | |
| 70 | −#define CR_CHAN(a) ((a)&0xffff) | |
| 71 | −#define CR_RANGE(a) (((a)>>16)&0xff) | |
| 72 | −#define CR_AREF(a) (((a)>>24)&0x03) | |
| 70 | +#define CR_CHAN(a) ((a) & 0xffff) | |
| 71 | +#define CR_RANGE(a) (((a) >> 16) & 0xff) | |
| 72 | +#define CR_AREF(a) (((a) >> 24) & 0x03) | |
| 73 | 73 | |
| 74 | 74 | #define CR_FLAGS_MASK 0xfc000000 |
| 75 | −#define CR_ALT_FILTER (1<<26) | |
| 75 | +#define CR_ALT_FILTER (1 << 26) | |
| 76 | 76 | #define CR_DITHER CR_ALT_FILTER |
| 77 | 77 | #define CR_DEGLITCH CR_ALT_FILTER |
| 78 | −#define CR_ALT_SOURCE (1<<27) | |
| 79 | −#define CR_EDGE (1<<30) | |
| 80 | −#define CR_INVERT (1<<31) | |
| 78 | +#define CR_ALT_SOURCE (1 << 27) | |
| 79 | +#define CR_EDGE (1 << 30) | |
| 80 | +#define CR_INVERT (1 << 31) | |
| 81 | 81 | |
| 82 | 82 | #define AREF_GROUND 0x00 /* analog ref = analog ground */ |
| 83 | 83 | #define AREF_COMMON 0x01 /* analog ref = analog common */ |
| @@ -114,11 +114,11 @@ · 30 unmodified lines | ||
| 114 | 114 | |
| 115 | 115 | #define INSN_READ (0 | INSN_MASK_READ) |
| 116 | 116 | #define INSN_WRITE (1 | INSN_MASK_WRITE) |
| 117 | −#define INSN_BITS (2 | INSN_MASK_READ|INSN_MASK_WRITE) | |
| 118 | −#define INSN_CONFIG (3 | INSN_MASK_READ|INSN_MASK_WRITE) | |
| 119 | −#define INSN_GTOD (4 | INSN_MASK_READ|INSN_MASK_SPECIAL) | |
| 120 | −#define INSN_WAIT (5 | INSN_MASK_WRITE|INSN_MASK_SPECIAL) | |
| 121 | −#define INSN_INTTRIG (6 | INSN_MASK_WRITE|INSN_MASK_SPECIAL) | |
| 117 | +#define INSN_BITS (2 | INSN_MASK_READ | INSN_MASK_WRITE) | |
| 118 | +#define INSN_CONFIG (3 | INSN_MASK_READ | INSN_MASK_WRITE) | |
| 119 | +#define INSN_GTOD (4 | INSN_MASK_READ | INSN_MASK_SPECIAL) | |
| 120 | +#define INSN_WAIT (5 | INSN_MASK_WRITE | INSN_MASK_SPECIAL) | |
| 121 | +#define INSN_INTTRIG (6 | INSN_MASK_WRITE | INSN_MASK_SPECIAL) | |
| 122 | 122 | |
| 123 | 123 | /* trigger flags */ |
| 124 | 124 | /* These flags are used in comedi_trig structures */ |
| @@ -279,7 +279,8 @@ enum configuration_ids { · 154 unmodified lines | ||
| 279 | 279 | INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ |
| 280 | 280 | /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ |
| 281 | 281 | /* Get size in bytes of subdevice's on-board fifos used during |
| 282 | − * streaming input/output */ | |
| 282 | + * streaming input/output | |
| 283 | + */ | |
| 283 | 284 | INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, |
| 284 | 285 | INSN_CONFIG_SET_COUNTER_MODE = 4097, |
| 285 | 286 | /* INSN_CONFIG_8254_SET_MODE is deprecated */ |
| @@ -292,7 +293,8 @@ enum configuration_ids { · 6 unmodified lines | ||
| 292 | 293 | INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ |
| 293 | 294 | INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ |
| 294 | 295 | /* sets H bridge: duty cycle and sign bit for a relay at the |
| 295 | − * same time */ | |
| 296 | + * same time | |
| 297 | + */ | |
| 296 | 298 | INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, |
| 297 | 299 | /* gets H bridge data: duty cycle and the sign bit */ |
| 298 | 300 | INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 |
| @@ -502,13 +504,13 @@ struct comedi_bufinfo { · 203 unmodified lines | ||
| 502 | 504 | |
| 503 | 505 | /* range stuff */ |
| 504 | 506 | |
| 505 | −#define __RANGE(a, b) ((((a)&0xffff)<<16)|((b)&0xffff)) | |
| 507 | +#define __RANGE(a, b) ((((a) & 0xffff) << 16) | ((b) & 0xffff)) | |
| 506 | 508 | |
| 507 | −#define RANGE_OFFSET(a) (((a)>>16)&0xffff) | |
| 508 | −#define RANGE_LENGTH(b) ((b)&0xffff) | |
| 509 | +#define RANGE_OFFSET(a) (((a) >> 16) & 0xffff) | |
| 510 | +#define RANGE_LENGTH(b) ((b) & 0xffff) | |
| 509 | 511 | |
| 510 | −#define RF_UNIT(flags) ((flags)&0xff) | |
| 511 | −#define RF_EXTERNAL (1<<8) | |
| 512 | +#define RF_UNIT(flags) ((flags) & 0xff) | |
| 513 | +#define RF_EXTERNAL (1 << 8) | |
| 512 | 514 | |
| 513 | 515 | #define UNIT_volt 0 |
| 514 | 516 | #define UNIT_mA 1 |
| @@ -521,23 +523,22 @@ struct comedi_bufinfo { · 6 unmodified lines | ||
| 521 | 523 | /**********************************************************/ |
| 522 | 524 | |
| 523 | 525 | /* |
| 524 | − 8254 specific configuration. | |
| 525 | − | |
| 526 | − It supports two config commands: | |
| 527 | − | |
| 528 | − 0 ID: INSN_CONFIG_SET_COUNTER_MODE | |
| 529 | − 1 8254 Mode | |
| 530 | − I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 | |
| 531 | − OR'ed with: | |
| 532 | − I8254_BCD, I8254_BINARY | |
| 533 | − | |
| 534 | − 0 ID: INSN_CONFIG_8254_READ_STATUS | |
| 535 | − 1 <-- Status byte returned here. | |
| 536 | − B7 = Output | |
| 537 | − B6 = NULL Count | |
| 538 | − B5 - B0 Current mode. | |
| 539 | − | |
| 540 | −*/ | |
| 526 | + * 8254 specific configuration. | |
| 527 | + * | |
| 528 | + * It supports two config commands: | |
| 529 | + * | |
| 530 | + * 0 ID: INSN_CONFIG_SET_COUNTER_MODE | |
| 531 | + * 1 8254 Mode | |
| 532 | + * I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 | |
| 533 | + * OR'ed with: | |
| 534 | + * I8254_BCD, I8254_BINARY | |
| 535 | + * | |
| 536 | + * 0 ID: INSN_CONFIG_8254_READ_STATUS | |
| 537 | + * 1 <-- Status byte returned here. | |
| 538 | + * B7 = Output | |
| 539 | + * B6 = NULL Count | |
| 540 | + * B5 - B0 Current mode. | |
| 541 | + */ | |
| 541 | 542 | |
| 542 | 543 | enum i8254_mode { |
| 543 | 544 | I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ |
| @@ -545,18 +546,20 @@ enum i8254_mode { · 1 unmodified line | ||
| 545 | 546 | I8254_MODE2 = (2 << 1), /* Rate generator */ |
| 546 | 547 | I8254_MODE3 = (3 << 1), /* Square wave mode */ |
| 547 | 548 | I8254_MODE4 = (4 << 1), /* Software triggered strobe */ |
| 548 | − I8254_MODE5 = (5 << 1), /* Hardware triggered strobe | |
| 549 | − * (retriggerable) */ | |
| 550 | − I8254_BCD = 1, /* use binary-coded decimal instead of binary | |
| 551 | − * (pretty useless) */ | |
| 549 | + /* Hardware triggered strobe (retriggerable) */ | |
| 550 | + I8254_MODE5 = (5 << 1), | |
| 551 | + /* Use binary-coded decimal instead of binary (pretty useless) */ | |
| 552 | + I8254_BCD = 1, | |
| 552 | 553 | I8254_BINARY = 0 |
| 553 | 554 | }; |
| 554 | 555 | |
| 555 | 556 | #define NI_USUAL_PFI_SELECT(x) (((x) < 10) ? (0x1 + (x)) : (0xb + (x))) |
| 556 | 557 | #define NI_USUAL_RTSI_SELECT(x) (((x) < 7) ? (0xb + (x)) : 0x1b) |
| 557 | 558 | |
| 558 | −/* mode bits for NI general-purpose counters, set with | |
| 559 | − * INSN_CONFIG_SET_COUNTER_MODE */ | |
| 559 | +/* | |
| 560 | + * mode bits for NI general-purpose counters, set with | |
| 561 | + * INSN_CONFIG_SET_COUNTER_MODE | |
| 562 | + */ | |
| 560 | 563 | #define NI_GPCT_COUNTING_MODE_SHIFT 16 |
| 561 | 564 | #define NI_GPCT_INDEX_PHASE_BITSHIFT 20 |
| 562 | 565 | #define NI_GPCT_COUNTING_DIRECTION_SHIFT 24 |
| @@ -624,8 +627,10 @@ enum ni_gpct_mode_bits { · 61 unmodified lines | ||
| 624 | 627 | NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 |
| 625 | 628 | }; |
| 626 | 629 | |
| 627 | −/* Bits for setting a clock source with | |
| 628 | − * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. */ | |
| 630 | +/* | |
| 631 | + * Bits for setting a clock source with | |
| 632 | + * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. | |
| 633 | + */ | |
| 629 | 634 | enum ni_gpct_clock_source_bits { |
| 630 | 635 | NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, |
| 631 | 636 | NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, |
| @@ -656,9 +661,11 @@ enum ni_gpct_clock_source_bits { · 24 unmodified lines | ||
| 656 | 661 | /* no pfi on NI 660x */ |
| 657 | 662 | #define NI_GPCT_PFI_CLOCK_SRC_BITS(x) (0x20 + (x)) |
| 658 | 663 | |
| 659 | −/* Possibilities for setting a gate source with | |
| 660 | −INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. | |
| 661 | −May be bitwise-or'd with CR_EDGE or CR_INVERT. */ | |
| 664 | +/* | |
| 665 | + * Possibilities for setting a gate source with | |
| 666 | + * INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. | |
| 667 | + * May be bitwise-or'd with CR_EDGE or CR_INVERT. | |
| 668 | + */ | |
| 662 | 669 | enum ni_gpct_gate_select { |
| 663 | 670 | /* m-series gates */ |
| 664 | 671 | NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, |
| @@ -675,9 +682,11 @@ enum ni_gpct_gate_select { · 10 unmodified lines | ||
| 675 | 682 | /* more gates for 660x "second gate" */ |
| 676 | 683 | NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, |
| 677 | 684 | NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e, |
| 678 | − /* m-series "second gate" sources are unknown, | |
| 685 | + /* | |
| 686 | + * m-series "second gate" sources are unknown, | |
| 679 | 687 | * we should add them here with an offset of 0x300 when |
| 680 | − * known. */ | |
| 688 | + * known. | |
| 689 | + */ | |
| 681 | 690 | NI_GPCT_DISABLED_GATE_SELECT = 0x8000, |
| 682 | 691 | }; |
| 683 | 692 | |
| @@ -686,8 +695,10 @@ enum ni_gpct_gate_select { · 2 unmodified lines | ||
| 686 | 695 | #define NI_GPCT_PFI_GATE_SELECT(x) NI_USUAL_PFI_SELECT(x) |
| 687 | 696 | #define NI_GPCT_UP_DOWN_PIN_GATE_SELECT(x) (0x202 + (x)) |
| 688 | 697 | |
| 689 | −/* Possibilities for setting a source with | |
| 690 | −INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */ | |
| 698 | +/* | |
| 699 | + * Possibilities for setting a source with | |
| 700 | + * INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. | |
| 701 | + */ | |
| 691 | 702 | enum ni_gpct_other_index { |
| 692 | 703 | NI_GPCT_SOURCE_ENCODER_A, |
| 693 | 704 | NI_GPCT_SOURCE_ENCODER_B, |
| @@ -702,18 +713,24 @@ enum ni_gpct_other_select { · 8 unmodified lines | ||
| 702 | 713 | |
| 703 | 714 | #define NI_GPCT_PFI_OTHER_SELECT(x) NI_USUAL_PFI_SELECT(x) |
| 704 | 715 | |
| 705 | −/* start sources for ni general-purpose counters for use with | |
| 706 | −INSN_CONFIG_ARM */ | |
| 716 | +/* | |
| 717 | + * start sources for ni general-purpose counters for use with | |
| 718 | + * INSN_CONFIG_ARM | |
| 719 | + */ | |
| 707 | 720 | enum ni_gpct_arm_source { |
| 708 | 721 | NI_GPCT_ARM_IMMEDIATE = 0x0, |
| 709 | − NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter | |
| 710 | − * and the adjacent paired | |
| 711 | − * counter simultaneously */ | |
| 712 | − /* NI doesn't document bits for selecting hardware arm triggers. | |
| 722 | + /* | |
| 723 | + * Start both the counter and the adjacent pared | |
| 724 | + * counter simultaneously | |
| 725 | + */ | |
| 726 | + NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, | |
| 727 | + /* | |
| 728 | + * NI doesn't document bits for selecting hardware arm triggers. | |
| 713 | 729 | * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least |
| 714 | 730 | * significant bits (3 bits for 660x or 5 bits for m-series) |
| 715 | 731 | * through to the hardware. This will at least allow someone to |
| 716 | − * figure out what the bits do later. */ | |
| 732 | + * figure out what the bits do later. | |
| 733 | + */ | |
| 717 | 734 | NI_GPCT_ARM_UNKNOWN = 0x1000, |
| 718 | 735 | }; |
| 719 | 736 | |
| @@ -728,8 +745,10 @@ enum ni_gpct_filter_select { · 8 unmodified lines | ||
| 728 | 745 | NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 |
| 729 | 746 | }; |
| 730 | 747 | |
| 731 | −/* PFI digital filtering options for ni m-series for use with | |
| 732 | − * INSN_CONFIG_FILTER. */ | |
| 748 | +/* | |
| 749 | + * PFI digital filtering options for ni m-series for use with | |
| 750 | + * INSN_CONFIG_FILTER. | |
| 751 | + */ | |
| 733 | 752 | enum ni_pfi_filter_select { |
| 734 | 753 | NI_PFI_FILTER_OFF = 0x0, |
| 735 | 754 | NI_PFI_FILTER_125ns = 0x1, |
| @@ -740,9 +759,11 @@ enum ni_pfi_filter_select { · 4 unmodified lines | ||
| 740 | 759 | /* master clock sources for ni mio boards and INSN_CONFIG_SET_CLOCK_SRC */ |
| 741 | 760 | enum ni_mio_clock_source { |
| 742 | 761 | NI_MIO_INTERNAL_CLOCK = 0, |
| 743 | − NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use | |
| 744 | − NI_MIO_PLL_RTSI_CLOCK() */ | |
| 745 | − /* the NI_MIO_PLL_* sources are m-series only */ | |
| 762 | + /* | |
| 763 | + * Doesn't work for m-series, use NI_MIO_PLL_RTSI_CLOCK() | |
| 764 | + * the NI_MIO_PLL_* sources are m-series only | |
| 765 | + */ | |
| 766 | + NI_MIO_RTSI_CLOCK = 1, | |
| 746 | 767 | NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, |
| 747 | 768 | NI_MIO_PLL_PXI10_CLOCK = 3, |
| 748 | 769 | NI_MIO_PLL_RTSI0_CLOCK = 4 |
| @@ -750,9 +771,11 @@ enum ni_mio_clock_source { · 1 unmodified line | ||
| 750 | 771 | |
| 751 | 772 | #define NI_MIO_PLL_RTSI_CLOCK(x) (NI_MIO_PLL_RTSI0_CLOCK + (x)) |
| 752 | 773 | |
| 753 | −/* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. | |
| 754 | − The numbers assigned are not arbitrary, they correspond to the bits required | |
| 755 | − to program the board. */ | |
| 774 | +/* | |
| 775 | + * Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. | |
| 776 | + * The numbers assigned are not arbitrary, they correspond to the bits required | |
| 777 | + * to program the board. | |
| 778 | + */ | |
| 756 | 779 | enum ni_rtsi_routing { |
| 757 | 780 | NI_RTSI_OUTPUT_ADR_START1 = 0, |
| 758 | 781 | NI_RTSI_OUTPUT_ADR_START2 = 1, |
| @@ -763,17 +786,19 @@ enum ni_rtsi_routing { · 4 unmodified lines | ||
| 763 | 786 | NI_RTSI_OUTPUT_G_GATE0 = 6, |
| 764 | 787 | NI_RTSI_OUTPUT_RGOUT0 = 7, |
| 765 | 788 | NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, |
| 766 | − NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI | |
| 767 | − * clock on line 7 */ | |
| 789 | + /* Pre-m-series always have RTSI clock on line 7 */ | |
| 790 | + NI_RTSI_OUTPUT_RTSI_OSC = 12 | |
| 768 | 791 | }; |
| 769 | 792 | |
| 770 | 793 | #define NI_RTSI_OUTPUT_RTSI_BRD(x) (NI_RTSI_OUTPUT_RTSI_BRD_0 + (x)) |
| 771 | 794 | |
| 772 | −/* Signals which can be routed to an NI PFI pin on an m-series board with | |
| 795 | +/* | |
| 796 | + * Signals which can be routed to an NI PFI pin on an m-series board with | |
| 773 | 797 | * INSN_CONFIG_SET_ROUTING. These numbers are also returned by |
| 774 | 798 | * INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though their routing |
| 775 | 799 | * cannot be changed. The numbers assigned are not arbitrary, they correspond |
| 776 | − * to the bits required to program the board. */ | |
| 800 | + * to the bits required to program the board. | |
| 801 | + */ | |
| 777 | 802 | enum ni_pfi_routing { |
| 778 | 803 | NI_PFI_OUTPUT_PFI_DEFAULT = 0, |
| 779 | 804 | NI_PFI_OUTPUT_AI_START1 = 1, |
| @@ -803,20 +828,24 @@ enum ni_pfi_routing { · 23 unmodified lines | ||
| 803 | 828 | |
| 804 | 829 | #define NI_PFI_OUTPUT_RTSI(x) (NI_PFI_OUTPUT_RTSI0 + (x)) |
| 805 | 830 | |
| 806 | −/* Signals which can be routed to output on a NI PFI pin on a 660x board | |
| 807 | − with INSN_CONFIG_SET_ROUTING. The numbers assigned are | |
| 808 | − not arbitrary, they correspond to the bits required | |
| 809 | − to program the board. Lines 0 to 7 can only be set to | |
| 810 | − NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to | |
| 811 | − NI_660X_PFI_OUTPUT_COUNTER. */ | |
| 831 | +/* | |
| 832 | + * Signals which can be routed to output on a NI PFI pin on a 660x board | |
| 833 | + * with INSN_CONFIG_SET_ROUTING. The numbers assigned are | |
| 834 | + * not arbitrary, they correspond to the bits required | |
| 835 | + * to program the board. Lines 0 to 7 can only be set to | |
| 836 | + * NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to | |
| 837 | + * NI_660X_PFI_OUTPUT_COUNTER. | |
| 838 | + */ | |
| 812 | 839 | enum ni_660x_pfi_routing { |
| 813 | 840 | NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ |
| 814 | 841 | NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */ |
| 815 | 842 | }; |
| 816 | 843 | |
| 817 | −/* NI External Trigger lines. These values are not arbitrary, but are related | |
| 844 | +/* | |
| 845 | + * NI External Trigger lines. These values are not arbitrary, but are related | |
| 818 | 846 | * to the bits required to program the board (offset by 1 for historical |
| 819 | − * reasons). */ | |
| 847 | + * reasons). | |
| 848 | + */ | |
| 820 | 849 | #define NI_EXT_PFI(x) (NI_USUAL_PFI_SELECT(x) - 1) |
| 821 | 850 | #define NI_EXT_RTSI(x) (NI_USUAL_RTSI_SELECT(x) - 1) |
| 822 | 851 | |
| @@ -827,9 +856,11 @@ enum comedi_counter_status_flags { · 4 unmodified lines | ||
| 827 | 856 | COMEDI_COUNTER_TERMINAL_COUNT = 0x4, |
| 828 | 857 | }; |
| 829 | 858 | |
| 830 | −/* Clock sources for CDIO subdevice on NI m-series boards. Used as the | |
| 859 | +/* | |
| 860 | + * Clock sources for CDIO subdevice on NI m-series boards. Used as the | |
| 831 | 861 | * scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd |
| 832 | − * with CR_INVERT to change polarity. */ | |
| 862 | + * with CR_INVERT to change polarity. | |
| 863 | + */ | |
| 833 | 864 | enum ni_m_series_cdio_scan_begin_src { |
| 834 | 865 | NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, |
| 835 | 866 | NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18, |
| @@ -846,38 +877,50 @@ enum ni_m_series_cdio_scan_begin_src { · 10 unmodified lines | ||
| 846 | 877 | #define NI_CDIO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) |
| 847 | 878 | #define NI_CDIO_SCAN_BEGIN_SRC_RTSI(x) NI_USUAL_RTSI_SELECT(x) |
| 848 | 879 | |
| 849 | −/* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI | |
| 880 | +/* | |
| 881 | + * scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI | |
| 850 | 882 | * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to |
| 851 | − * change polarity. */ | |
| 883 | + * change polarity. | |
| 884 | + */ | |
| 852 | 885 | #define NI_AO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) |
| 853 | 886 | #define NI_AO_SCAN_BEGIN_SRC_RTSI(x) NI_USUAL_RTSI_SELECT(x) |
| 854 | 887 | |
| 855 | −/* Bits for setting a clock source with | |
| 856 | − * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */ | |
| 888 | +/* | |
| 889 | + * Bits for setting a clock source with | |
| 890 | + * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. | |
| 891 | + */ | |
| 857 | 892 | enum ni_freq_out_clock_source_bits { |
| 858 | 893 | NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ |
| 859 | 894 | NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */ |
| 860 | 895 | }; |
| 861 | 896 | |
| 862 | −/* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for | |
| 863 | − * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ | |
| 897 | +/* | |
| 898 | + * Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for | |
| 899 | + * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). | |
| 900 | + */ | |
| 864 | 901 | enum amplc_dio_clock_source { |
| 865 | − AMPLC_DIO_CLK_CLKN, /* per channel external clock | |
| 866 | − input/output pin (pin is only an | |
| 867 | − input when clock source set to this | |
| 868 | − value, otherwise it is an output) */ | |
| 902 | + /* | |
| 903 | + * Per channel external clock | |
| 904 | + * input/output pin (pin is only an | |
| 905 | + * input when clock source set to this value, | |
| 906 | + * otherwise it is an output) | |
| 907 | + */ | |
| 908 | + AMPLC_DIO_CLK_CLKN, | |
| 869 | 909 | AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ |
| 870 | 910 | AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ |
| 871 | 911 | AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ |
| 872 | 912 | AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ |
| 873 | 913 | AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ |
| 874 | − AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel | |
| 875 | − (for channel 0, preceding counter | |
| 876 | − channel is channel 2 on preceding | |
| 877 | − counter subdevice, for first counter | |
| 878 | − subdevice, preceding counter | |
| 879 | − subdevice is the last counter | |
| 880 | − subdevice) */ | |
| 914 | + /* | |
| 915 | + * Output of preceding counter channel | |
| 916 | + * (for channel 0, preceding counter | |
| 917 | + * channel is channel 2 on preceding | |
| 918 | + * counter subdevice, for first counter | |
| 919 | + * subdevice, preceding counter | |
| 920 | + * subdevice is the last counter | |
| 921 | + * subdevice) | |
| 922 | + */ | |
| 923 | + AMPLC_DIO_CLK_OUTNM1, | |
| 881 | 924 | AMPLC_DIO_CLK_EXT, /* per chip external input pin */ |
| 882 | 925 | /* the following are "enhanced" clock sources for PCIe models */ |
| 883 | 926 | AMPLC_DIO_CLK_VCC, /* clock input HIGH */ |
| @@ -886,35 +929,39 @@ enum amplc_dio_clock_source { · 2 unmodified lines | ||
| 886 | 929 | AMPLC_DIO_CLK_20MHZ /* 20 MHz internal clock */ |
| 887 | 930 | }; |
| 888 | 931 | |
| 889 | −/* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for | |
| 890 | − * timer subdevice on some Amplicon DIO PCIe boards (amplc_dio200 driver). */ | |
| 932 | +/* | |
| 933 | + * Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for | |
| 934 | + * timer subdevice on some Amplicon DIO PCIe boards (amplc_dio200 driver). | |
| 935 | + */ | |
| 891 | 936 | enum amplc_dio_ts_clock_src { |
| 892 | 937 | AMPLC_DIO_TS_CLK_1GHZ, /* 1 ns period with 20 ns granularity */ |
| 893 | 938 | AMPLC_DIO_TS_CLK_1MHZ, /* 1 us period */ |
| 894 | 939 | AMPLC_DIO_TS_CLK_1KHZ /* 1 ms period */ |
| 895 | 940 | }; |
| 896 | 941 | |
| 897 | −/* Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for | |
| 898 | − * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ | |
| 942 | +/* | |
| 943 | + * Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for | |
| 944 | + * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). | |
| 945 | + */ | |
| 899 | 946 | enum amplc_dio_gate_source { |
| 900 | 947 | AMPLC_DIO_GAT_VCC, /* internal high logic level */ |
| 901 | 948 | AMPLC_DIO_GAT_GND, /* internal low logic level */ |
| 902 | 949 | AMPLC_DIO_GAT_GATN, /* per channel external gate input */ |
| 903 | − AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel | |
| 904 | − minus 2 (for channels 0 or 1, | |
| 905 | − channel minus 2 is channel 1 or 2 on | |
| 906 | − the preceding counter subdevice, for | |
| 907 | − the first counter subdevice the | |
| 908 | − preceding counter subdevice is the | |
| 909 | − last counter subdevice) */ | |
| 950 | + /* | |
| 951 | + * negated output of counter channel minus 2 | |
| 952 | + * (for channels 0 or 1, channel minus 2 is channel 1 or 2 on | |
| 953 | + * the preceding counter subdevice, for the first counter subdevice | |
| 954 | + * the preceding counter subdevice is the last counter subdevice) | |
| 955 | + */ | |
| 956 | + AMPLC_DIO_GAT_NOUTNM2, | |
| 910 | 957 | AMPLC_DIO_GAT_RESERVED4, |
| 911 | 958 | AMPLC_DIO_GAT_RESERVED5, |
| 912 | 959 | AMPLC_DIO_GAT_RESERVED6, |
| 913 | 960 | AMPLC_DIO_GAT_RESERVED7, |
| 914 | 961 | /* the following are "enhanced" gate sources for PCIe models */ |
| 915 | 962 | AMPLC_DIO_GAT_NGATN = 6, /* negated per channel gate input */ |
| 916 | − AMPLC_DIO_GAT_OUTNM2, /* non-negated output of counter | |
| 917 | − channel minus 2 */ | |
| 963 | + /* non-negated output of counter channel minus 2 */ | |
| 964 | + AMPLC_DIO_GAT_OUTNM2, | |
| 918 | 965 | AMPLC_DIO_GAT_PAT_PRESENT, /* "pattern present" signal */ |
| 919 | 966 | AMPLC_DIO_GAT_PAT_OCCURRED, /* "pattern occurred" latched */ |
| 920 | 967 | AMPLC_DIO_GAT_PAT_GONE, /* "pattern gone away" latched */ |
| @@ -2303,11 +2303,13 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, · 2302 unmodified lines | ||
| 2303 | 2303 | { |
| 2304 | 2304 | struct comedi_subdevice *s; |
| 2305 | 2305 | struct comedi_async *async; |
| 2306 | − int n, m, count = 0, retval = 0; | |
| 2306 | + unsigned int n, m; | |
| 2307 | + ssize_t count = 0; | |
| 2308 | + int retval = 0; | |
| 2307 | 2309 | DECLARE_WAITQUEUE(wait, current); |
| 2308 | 2310 | struct comedi_file *cfp = file->private_data; |
| 2309 | 2311 | struct comedi_device *dev = cfp->dev; |
| 2310 | − bool on_wait_queue = false; | |
| 2312 | + bool become_nonbusy = false; | |
| 2311 | 2313 | bool attach_locked; |
| 2312 | 2314 | unsigned int old_detach_count; |
| 2313 | 2315 | |
| @@ -2329,74 +2331,33 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, · 15 unmodified lines | ||
| 2329 | 2331 | } |
| 2330 | 2332 | |
| 2331 | 2333 | async = s->async; |
| 2332 | − | |
| 2333 | − if (!s->busy || !nbytes) | |
| 2334 | − goto out; | |
| 2335 | − if (s->busy != file) { | |
| 2336 | − retval = -EACCES; | |
| 2337 | − goto out; | |
| 2338 | − } | |
| 2339 | − if (!(async->cmd.flags & CMDF_WRITE)) { | |
| 2334 | + if (s->busy != file || !(async->cmd.flags & CMDF_WRITE)) { | |
| 2340 | 2335 | retval = -EINVAL; |
| 2341 | 2336 | goto out; |
| 2342 | 2337 | } |
| 2343 | 2338 | |
| 2344 | 2339 | add_wait_queue(&async->wait_head, &wait); |
| 2345 | − on_wait_queue = true; | |
| 2346 | − while (nbytes > 0 && !retval) { | |
| 2340 | + while (count == 0 && !retval) { | |
| 2347 | 2341 | unsigned runflags; |
| 2342 | + unsigned int wp, n1, n2; | |
| 2348 | 2343 | |
| 2349 | 2344 | set_current_state(TASK_INTERRUPTIBLE); |
| 2350 | 2345 | |
| 2351 | 2346 | runflags = comedi_get_subdevice_runflags(s); |
| 2352 | 2347 | if (!comedi_is_runflags_running(runflags)) { |
| 2353 | − if (count == 0) { | |
| 2354 | − struct comedi_subdevice *new_s; | |
| 2355 | − | |
| 2356 | − if (comedi_is_runflags_in_error(runflags)) | |
| 2357 | − retval = -EPIPE; | |
| 2358 | − else | |
| 2359 | − retval = 0; | |
| 2360 | − /* | |
| 2361 | − * To avoid deadlock, cannot acquire dev->mutex | |
| 2362 | − * while dev->attach_lock is held. Need to | |
| 2363 | − * remove task from the async wait queue before | |
| 2364 | − * releasing dev->attach_lock, as it might not | |
| 2365 | − * be valid afterwards. | |
| 2366 | − */ | |
| 2367 | − remove_wait_queue(&async->wait_head, &wait); | |
| 2368 | − on_wait_queue = false; | |
| 2369 | − up_read(&dev->attach_lock); | |
| 2370 | − attach_locked = false; | |
| 2371 | − mutex_lock(&dev->mutex); | |
| 2372 | − /* | |
| 2373 | − * Become non-busy unless things have changed | |
| 2374 | − * behind our back. Checking dev->detach_count | |
| 2375 | − * is unchanged ought to be sufficient (unless | |
| 2376 | − * there have been 2**32 detaches in the | |
| 2377 | − * meantime!), but check the subdevice pointer | |
| 2378 | − * as well just in case. | |
| 2379 | − */ | |
| 2380 | − new_s = comedi_file_write_subdevice(file); | |
| 2381 | − if (dev->attached && | |
| 2382 | − old_detach_count == dev->detach_count && | |
| 2383 | − s == new_s && new_s->async == async) | |
| 2384 | − do_become_nonbusy(dev, s); | |
| 2385 | − mutex_unlock(&dev->mutex); | |
| 2386 | − } | |
| 2348 | + if (comedi_is_runflags_in_error(runflags)) | |
| 2349 | + retval = -EPIPE; | |
| 2350 | + if (retval || nbytes) | |
| 2351 | + become_nonbusy = true; | |
| 2387 | 2352 | break; |
| 2388 | 2353 | } |
| 2354 | + if (nbytes == 0) | |
| 2355 | + break; | |
| 2389 | 2356 | |
| 2390 | − n = nbytes; | |
| 2391 | − | |
| 2392 | − m = n; | |
| 2393 | − if (async->buf_write_ptr + m > async->prealloc_bufsz) | |
| 2394 | − m = async->prealloc_bufsz - async->buf_write_ptr; | |
| 2357 | + /* Allocate all free buffer space. */ | |
| 2395 | 2358 | comedi_buf_write_alloc(s, async->prealloc_bufsz); |
| 2396 | − if (m > comedi_buf_write_n_allocated(s)) | |
| 2397 | − m = comedi_buf_write_n_allocated(s); | |
| 2398 | − if (m < n) | |
| 2399 | − n = m; | |
| 2359 | + m = comedi_buf_write_n_allocated(s); | |
| 2360 | + n = min_t(size_t, m, nbytes); | |
| 2400 | 2361 | |
| 2401 | 2362 | if (n == 0) { |
| 2402 | 2363 | if (file->f_flags & O_NONBLOCK) { |
| @@ -2408,21 +2369,22 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, · 5 unmodified lines | ||
| 2408 | 2369 | retval = -ERESTARTSYS; |
| 2409 | 2370 | break; |
| 2410 | 2371 | } |
| 2411 | − if (!s->busy) | |
| 2412 | − break; | |
| 2413 | − if (s->busy != file) { | |
| 2414 | − retval = -EACCES; | |
| 2415 | − break; | |
| 2416 | − } | |
| 2417 | − if (!(async->cmd.flags & CMDF_WRITE)) { | |
| 2372 | + if (s->busy != file || | |
| 2373 | + !(async->cmd.flags & CMDF_WRITE)) { | |
| 2418 | 2374 | retval = -EINVAL; |
| 2419 | 2375 | break; |
| 2420 | 2376 | } |
| 2421 | 2377 | continue; |
| 2422 | 2378 | } |
| 2423 | 2379 | |
| 2424 | − m = copy_from_user(async->prealloc_buf + async->buf_write_ptr, | |
| 2425 | − buf, n); | |
| 2380 | + wp = async->buf_write_ptr; | |
| 2381 | + n1 = min(n, async->prealloc_bufsz - wp); | |
| 2382 | + n2 = n - n1; | |
| 2383 | + m = copy_from_user(async->prealloc_buf + wp, buf, n1); | |
| 2384 | + if (m) | |
| 2385 | + m += n2; | |
| 2386 | + else if (n2) | |
| 2387 | + m = copy_from_user(async->prealloc_buf, buf + n1, n2); | |
| 2426 | 2388 | if (m) { |
| 2427 | 2389 | n -= m; |
| 2428 | 2390 | retval = -EFAULT; |
| @@ -2433,12 +2395,38 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, · 4 unmodified lines | ||
| 2433 | 2395 | nbytes -= n; |
| 2434 | 2396 | |
| 2435 | 2397 | buf += n; |
| 2436 | − break; /* makes device work like a pipe */ | |
| 2437 | 2398 | } |
| 2438 | −out: | |
| 2439 | − if (on_wait_queue) | |
| 2440 | − remove_wait_queue(&async->wait_head, &wait); | |
| 2399 | + remove_wait_queue(&async->wait_head, &wait); | |
| 2441 | 2400 | set_current_state(TASK_RUNNING); |
| 2401 | + if (become_nonbusy && count == 0) { | |
| 2402 | + struct comedi_subdevice *new_s; | |
| 2403 | + | |
| 2404 | + /* | |
| 2405 | + * To avoid deadlock, cannot acquire dev->mutex | |
| 2406 | + * while dev->attach_lock is held. | |
| 2407 | + */ | |
| 2408 | + up_read(&dev->attach_lock); | |
| 2409 | + attach_locked = false; | |
| 2410 | + mutex_lock(&dev->mutex); | |
| 2411 | + /* | |
| 2412 | + * Check device hasn't become detached behind our back. | |
| 2413 | + * Checking dev->detach_count is unchanged ought to be | |
| 2414 | + * sufficient (unless there have been 2**32 detaches in the | |
| 2415 | + * meantime!), but check the subdevice pointer as well just in | |
| 2416 | + * case. | |
| 2417 | + * | |
| 2418 | + * Also check the subdevice is still in a suitable state to | |
| 2419 | + * become non-busy in case it changed behind our back. | |
| 2420 | + */ | |
| 2421 | + new_s = comedi_file_write_subdevice(file); | |
| 2422 | + if (dev->attached && old_detach_count == dev->detach_count && | |
| 2423 | + s == new_s && new_s->async == async && s->busy == file && | |
| 2424 | + (async->cmd.flags & CMDF_WRITE) && | |
| 2425 | + !comedi_is_subdevice_running(s)) | |
| 2426 | + do_become_nonbusy(dev, s); | |
| 2427 | + mutex_unlock(&dev->mutex); | |
| 2428 | + } | |
| 2429 | +out: | |
| 2442 | 2430 | if (attach_locked) |
| 2443 | 2431 | up_read(&dev->attach_lock); |
| 2444 | 2432 | |
| @@ -1,20 +1,20 @@ | ||
| 1 | 1 | /* |
| 2 | − linux/include/comedilib.h | |
| 3 | − header file for kcomedilib | |
| 4 | − | |
| 5 | − COMEDI - Linux Control and Measurement Device Interface | |
| 6 | − Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> | |
| 7 | − | |
| 8 | − This program is free software; you can redistribute it and/or modify | |
| 9 | − it under the terms of the GNU General Public License as published by | |
| 10 | − the Free Software Foundation; either version 2 of the License, or | |
| 11 | − (at your option) any later version. | |
| 12 | − | |
| 13 | − This program is distributed in the hope that it will be useful, | |
| 14 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − GNU General Public License for more details. | |
| 17 | −*/ | |
| 2 | + * comedilib.h | |
| 3 | + * Header file for kcomedilib | |
| 4 | + * | |
| 5 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 6 | + * Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License as published by | |
| 10 | + * the Free Software Foundation; either version 2 of the License, or | |
| 11 | + * (at your option) any later version. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | + */ | |
| 18 | 18 | |
| 19 | 19 | #ifndef _LINUX_COMEDILIB_H |
| 20 | 20 | #define _LINUX_COMEDILIB_H |
| @@ -78,8 +78,10 @@ obj-$(CONFIG_COMEDI_ADL_PCI8164) += adl_pci8164.o · 77 unmodified lines | ||
| 78 | 78 | obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o |
| 79 | 79 | obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o |
| 80 | 80 | obj-$(CONFIG_COMEDI_ADV_PCI1710) += adv_pci1710.o |
| 81 | +obj-$(CONFIG_COMEDI_ADV_PCI1720) += adv_pci1720.o | |
| 81 | 82 | obj-$(CONFIG_COMEDI_ADV_PCI1723) += adv_pci1723.o |
| 82 | 83 | obj-$(CONFIG_COMEDI_ADV_PCI1724) += adv_pci1724.o |
| 84 | +obj-$(CONFIG_COMEDI_ADV_PCI1760) += adv_pci1760.o | |
| 83 | 85 | obj-$(CONFIG_COMEDI_ADV_PCI_DIO) += adv_pci_dio.o |
| 84 | 86 | obj-$(CONFIG_COMEDI_AMPLC_DIO200_PCI) += amplc_dio200_pci.o |
| 85 | 87 | obj-$(CONFIG_COMEDI_AMPLC_PC236_PCI) += amplc_pci236.o |
| @@ -603,10 +603,11 @@ static void pci9118_ai_munge(struct comedi_device *dev, · 602 unmodified lines | ||
| 603 | 603 | unsigned short *array = data; |
| 604 | 604 | unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes); |
| 605 | 605 | unsigned int i; |
| 606 | + __be16 *barray = data; | |
| 606 | 607 | |
| 607 | 608 | for (i = 0; i < num_samples; i++) { |
| 608 | 609 | if (devpriv->usedma) |
| 609 | − array[i] = be16_to_cpu(array[i]); | |
| 610 | + array[i] = be16_to_cpu(barray[i]); | |
| 610 | 611 | if (s->maxdata == 0xffff) |
| 611 | 612 | array[i] ^= 0x8000; |
| 612 | 613 | else |
| @@ -11,8 +11,9 @@ · 10 unmodified lines | ||
| 11 | 11 | * Driver: adv_pci1710 |
| 12 | 12 | * Description: Comedi driver for Advantech PCI-1710 series boards |
| 13 | 13 | * Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG, PCI-1711, |
| 14 | − * PCI-1713, PCI-1720, PCI-1731 | |
| 14 | + * PCI-1713, PCI-1731 | |
| 15 | 15 | * Author: Michal Dobes <dobes@tesnet.cz> |
| 16 | + * Updated: Fri, 29 Oct 2015 17:19:35 -0700 | |
| 16 | 17 | * Status: works |
| 17 | 18 | * |
| 18 | 19 | * Configuration options: not applicable, uses PCI auto config |
| @@ -40,7 +41,13 @@ · 21 unmodified lines | ||
| 40 | 41 | #define PCI171X_AD_DATA_REG 0x00 /* R: A/D data */ |
| 41 | 42 | #define PCI171X_SOFTTRG_REG 0x00 /* W: soft trigger for A/D */ |
| 42 | 43 | #define PCI171X_RANGE_REG 0x02 /* W: A/D gain/range register */ |
| 44 | +#define PCI171X_RANGE_DIFF BIT(5) | |
| 45 | +#define PCI171X_RANGE_UNI BIT(4) | |
| 46 | +#define PCI171X_RANGE_GAIN(x) (((x) & 0x7) << 0) | |
| 43 | 47 | #define PCI171X_MUX_REG 0x04 /* W: A/D multiplexor control */ |
| 48 | +#define PCI171X_MUX_CHANH(x) (((x) & 0xf) << 8) | |
| 49 | +#define PCI171X_MUX_CHANL(x) (((x) & 0xf) << 0) | |
| 50 | +#define PCI171X_MUX_CHAN(x) (PCI171X_MUX_CHANH(x) | PCI171X_MUX_CHANL(x)) | |
| 44 | 51 | #define PCI171X_STATUS_REG 0x06 /* R: status register */ |
| 45 | 52 | #define PCI171X_STATUS_IRQ BIT(11) /* 1=IRQ occurred */ |
| 46 | 53 | #define PCI171X_STATUS_FF BIT(10) /* 1=FIFO is full, fatal error */ |
| @@ -58,83 +65,58 @@ · 11 unmodified lines | ||
| 58 | 65 | #define PCI171X_CLRFIFO_REG 0x09 /* W: clear FIFO */ |
| 59 | 66 | #define PCI171X_DA_REG(x) (0x0a + ((x) * 2)) /* W: D/A register */ |
| 60 | 67 | #define PCI171X_DAREF_REG 0x0e /* W: D/A reference control */ |
| 68 | +#define PCI171X_DAREF(c, r) (((r) & 0x3) << ((c) * 2)) | |
| 69 | +#define PCI171X_DAREF_MASK(c) PCI171X_DAREF((c), 0x3) | |
| 61 | 70 | #define PCI171X_DI_REG 0x10 /* R: digital inputs */ |
| 62 | 71 | #define PCI171X_DO_REG 0x10 /* W: digital outputs */ |
| 63 | 72 | #define PCI171X_TIMER_BASE 0x18 /* R/W: 8254 timer */ |
| 64 | 73 | |
| 65 | −/* | |
| 66 | − * PCI-1720 only has analog outputs and has a different | |
| 67 | − * register map (dev->iobase) | |
| 68 | − */ | |
| 69 | −#define PCI1720_DA_REG(x) (0x00 + ((x) * 2)) /* W: D/A registers */ | |
| 70 | −#define PCI1720_RANGE_REG 0x08 /* R/W: D/A range register */ | |
| 71 | −#define PCI1720_SYNC_REG 0x09 /* W: D/A synchronized output */ | |
| 72 | −#define PCI1720_SYNC_CTRL_REG 0x0f /* R/W: D/A synchronized control */ | |
| 73 | −#define PCI1720_SYNC_CTRL_SC0 BIT(0) /* set synchronous output mode */ | |
| 74 | − | |
| 75 | −static const struct comedi_lrange range_pci1710_3 = { | |
| 74 | +static const struct comedi_lrange pci1710_ai_range = { | |
| 76 | 75 | 9, { |
| 77 | − BIP_RANGE(5), | |
| 78 | − BIP_RANGE(2.5), | |
| 79 | − BIP_RANGE(1.25), | |
| 80 | − BIP_RANGE(0.625), | |
| 81 | − BIP_RANGE(10), | |
| 82 | − UNI_RANGE(10), | |
| 83 | − UNI_RANGE(5), | |
| 84 | − UNI_RANGE(2.5), | |
| 85 | − UNI_RANGE(1.25) | |
| 76 | + BIP_RANGE(5), /* gain 1 (0x00) */ | |
| 77 | + BIP_RANGE(2.5), /* gain 2 (0x01) */ | |
| 78 | + BIP_RANGE(1.25), /* gain 4 (0x02) */ | |
| 79 | + BIP_RANGE(0.625), /* gain 8 (0x03) */ | |
| 80 | + BIP_RANGE(10), /* gain 0.5 (0x04) */ | |
| 81 | + UNI_RANGE(10), /* gain 1 (0x00 | UNI) */ | |
| 82 | + UNI_RANGE(5), /* gain 2 (0x01 | UNI) */ | |
| 83 | + UNI_RANGE(2.5), /* gain 4 (0x02 | UNI) */ | |
| 84 | + UNI_RANGE(1.25) /* gain 8 (0x03 | UNI) */ | |
| 86 | 85 | } |
| 87 | 86 | }; |
| 88 | 87 | |
| 89 | −static const char range_codes_pci1710_3[] = { 0x00, 0x01, 0x02, 0x03, 0x04, | |
| 90 | − 0x10, 0x11, 0x12, 0x13 }; | |
| 91 | − | |
| 92 | −static const struct comedi_lrange range_pci1710hg = { | |
| 88 | +static const struct comedi_lrange pci1710hg_ai_range = { | |
| 93 | 89 | 12, { |
| 94 | − BIP_RANGE(5), | |
| 95 | − BIP_RANGE(0.5), | |
| 96 | − BIP_RANGE(0.05), | |
| 97 | − BIP_RANGE(0.005), | |
| 98 | − BIP_RANGE(10), | |
| 99 | − BIP_RANGE(1), | |
| 100 | − BIP_RANGE(0.1), | |
| 101 | − BIP_RANGE(0.01), | |
| 102 | − UNI_RANGE(10), | |
| 103 | − UNI_RANGE(1), | |
| 104 | − UNI_RANGE(0.1), | |
| 105 | − UNI_RANGE(0.01) | |
| 90 | + BIP_RANGE(5), /* gain 1 (0x00) */ | |
| 91 | + BIP_RANGE(0.5), /* gain 10 (0x01) */ | |
| 92 | + BIP_RANGE(0.05), /* gain 100 (0x02) */ | |
| 93 | + BIP_RANGE(0.005), /* gain 1000 (0x03) */ | |
| 94 | + BIP_RANGE(10), /* gain 0.5 (0x04) */ | |
| 95 | + BIP_RANGE(1), /* gain 5 (0x05) */ | |
| 96 | + BIP_RANGE(0.1), /* gain 50 (0x06) */ | |
| 97 | + BIP_RANGE(0.01), /* gain 500 (0x07) */ | |
| 98 | + UNI_RANGE(10), /* gain 1 (0x00 | UNI) */ | |
| 99 | + UNI_RANGE(1), /* gain 10 (0x01 | UNI) */ | |
| 100 | + UNI_RANGE(0.1), /* gain 100 (0x02 | UNI) */ | |
| 101 | + UNI_RANGE(0.01) /* gain 1000 (0x03 | UNI) */ | |
| 106 | 102 | } |
| 107 | 103 | }; |
| 108 | 104 | |
| 109 | −static const char range_codes_pci1710hg[] = { 0x00, 0x01, 0x02, 0x03, 0x04, | |
| 110 | − 0x05, 0x06, 0x07, 0x10, 0x11, | |
| 111 | − 0x12, 0x13 }; | |
| 112 | − | |
| 113 | −static const struct comedi_lrange range_pci17x1 = { | |
| 105 | +static const struct comedi_lrange pci1711_ai_range = { | |
| 114 | 106 | 5, { |
| 115 | − BIP_RANGE(10), | |
| 116 | − BIP_RANGE(5), | |
| 117 | − BIP_RANGE(2.5), | |
| 118 | − BIP_RANGE(1.25), | |
| 119 | − BIP_RANGE(0.625) | |
| 120 | − } | |
| 121 | −}; | |
| 122 | − | |
| 123 | −static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; | |
| 124 | − | |
| 125 | −static const struct comedi_lrange pci1720_ao_range = { | |
| 126 | − 4, { | |
| 127 | − UNI_RANGE(5), | |
| 128 | − UNI_RANGE(10), | |
| 129 | − BIP_RANGE(5), | |
| 130 | − BIP_RANGE(10) | |
| 107 | + BIP_RANGE(10), /* gain 1 (0x00) */ | |
| 108 | + BIP_RANGE(5), /* gain 2 (0x01) */ | |
| 109 | + BIP_RANGE(2.5), /* gain 4 (0x02) */ | |
| 110 | + BIP_RANGE(1.25), /* gain 8 (0x03) */ | |
| 111 | + BIP_RANGE(0.625) /* gain 16 (0x04) */ | |
| 131 | 112 | } |
| 132 | 113 | }; |
| 133 | 114 | |
| 134 | 115 | static const struct comedi_lrange pci171x_ao_range = { |
| 135 | − 2, { | |
| 136 | − UNI_RANGE(5), | |
| 137 | − UNI_RANGE(10) | |
| 116 | + 3, { | |
| 117 | + UNI_RANGE(5), /* internal -5V ref */ | |
| 118 | + UNI_RANGE(10), /* internal -10V ref */ | |
| 119 | + RANGE_ext(0, 1) /* external -Vref (+/-10V max) */ | |
| 138 | 120 | } |
| 139 | 121 | }; |
| 140 | 122 | |
| @@ -143,82 +125,43 @@ enum pci1710_boardid { · 2 unmodified lines | ||
| 143 | 125 | BOARD_PCI1710HG, |
| 144 | 126 | BOARD_PCI1711, |
| 145 | 127 | BOARD_PCI1713, |
| 146 | − BOARD_PCI1720, | |
| 147 | 128 | BOARD_PCI1731, |
| 148 | 129 | }; |
| 149 | 130 | |
| 150 | 131 | struct boardtype { |
| 151 | − const char *name; /* board name */ | |
| 152 | − int n_aichan; /* num of A/D chans */ | |
| 153 | − const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ | |
| 154 | − const char *rangecode_ai; /* range codes for programming */ | |
| 132 | + const char *name; | |
| 133 | + const struct comedi_lrange *ai_range; | |
| 134 | + unsigned int is_pci1711:1; | |
| 155 | 135 | unsigned int is_pci1713:1; |
| 156 | − unsigned int is_pci1720:1; | |
| 157 | − unsigned int has_irq:1; | |
| 158 | − unsigned int has_large_fifo:1; /* 4K or 1K FIFO */ | |
| 159 | − unsigned int has_diff_ai:1; | |
| 160 | 136 | unsigned int has_ao:1; |
| 161 | − unsigned int has_di_do:1; | |
| 162 | − unsigned int has_counter:1; | |
| 163 | 137 | }; |
| 164 | 138 | |
| 165 | 139 | static const struct boardtype boardtypes[] = { |
| 166 | 140 | [BOARD_PCI1710] = { |
| 167 | 141 | .name = "pci1710", |
| 168 | − .n_aichan = 16, | |
| 169 | − .rangelist_ai = &range_pci1710_3, | |
| 170 | − .rangecode_ai = range_codes_pci1710_3, | |
| 171 | − .has_irq = 1, | |
| 172 | − .has_large_fifo = 1, | |
| 173 | − .has_diff_ai = 1, | |
| 142 | + .ai_range = &pci1710_ai_range, | |
| 174 | 143 | .has_ao = 1, |
| 175 | − .has_di_do = 1, | |
| 176 | − .has_counter = 1, | |
| 177 | 144 | }, |
| 178 | 145 | [BOARD_PCI1710HG] = { |
| 179 | 146 | .name = "pci1710hg", |
| 180 | − .n_aichan = 16, | |
| 181 | − .rangelist_ai = &range_pci1710hg, | |
| 182 | − .rangecode_ai = range_codes_pci1710hg, | |
| 183 | − .has_irq = 1, | |
| 184 | − .has_large_fifo = 1, | |
| 185 | − .has_diff_ai = 1, | |
| 147 | + .ai_range = &pci1710hg_ai_range, | |
| 186 | 148 | .has_ao = 1, |
| 187 | − .has_di_do = 1, | |
| 188 | − .has_counter = 1, | |
| 189 | 149 | }, |
| 190 | 150 | [BOARD_PCI1711] = { |
| 191 | 151 | .name = "pci1711", |
| 192 | − .n_aichan = 16, | |
| 193 | − .rangelist_ai = &range_pci17x1, | |
| 194 | − .rangecode_ai = range_codes_pci17x1, | |
| 195 | − .has_irq = 1, | |
| 152 | + .ai_range = &pci1711_ai_range, | |
| 153 | + .is_pci1711 = 1, | |
| 196 | 154 | .has_ao = 1, |
| 197 | − .has_di_do = 1, | |
| 198 | − .has_counter = 1, | |
| 199 | 155 | }, |
| 200 | 156 | [BOARD_PCI1713] = { |
| 201 | 157 | .name = "pci1713", |
| 202 | − .n_aichan = 32, | |
| 203 | − .rangelist_ai = &range_pci1710_3, | |
| 204 | − .rangecode_ai = range_codes_pci1710_3, | |
| 158 | + .ai_range = &pci1710_ai_range, | |
| 205 | 159 | .is_pci1713 = 1, |
| 206 | − .has_irq = 1, | |
| 207 | − .has_large_fifo = 1, | |
| 208 | − .has_diff_ai = 1, | |
| 209 | − }, | |
| 210 | − [BOARD_PCI1720] = { | |
| 211 | − .name = "pci1720", | |
| 212 | − .is_pci1720 = 1, | |
| 213 | − .has_ao = 1, | |
| 214 | 160 | }, |
| 215 | 161 | [BOARD_PCI1731] = { |
| 216 | 162 | .name = "pci1731", |
| 217 | − .n_aichan = 16, | |
| 218 | − .rangelist_ai = &range_pci17x1, | |
| 219 | − .rangecode_ai = range_codes_pci17x1, | |
| 220 | − .has_irq = 1, | |
| 221 | − .has_di_do = 1, | |
| 163 | + .ai_range = &pci1711_ai_range, | |
| 164 | + .is_pci1711 = 1, | |
| 222 | 165 | }, |
| 223 | 166 | }; |
| 224 | 167 | |
| @@ -226,14 +169,15 @@ struct pci1710_private { · 1 unmodified line | ||
| 226 | 169 | unsigned int max_samples; |
| 227 | 170 | unsigned int ctrl; /* control register value */ |
| 228 | 171 | unsigned int ctrl_ext; /* used to switch from TRIG_EXT to TRIG_xxx */ |
| 229 | − unsigned int mux_ext; /* used to set the channel interval to scan */ | |
| 172 | + unsigned int mux_scan; /* used to set the channel interval to scan */ | |
| 230 | 173 | unsigned char ai_et; |
| 231 | 174 | unsigned int act_chanlist[32]; /* list of scanned channel */ |
| 232 | 175 | unsigned char saved_seglen; /* len of the non-repeating chanlist */ |
| 233 | 176 | unsigned char da_ranges; /* copy of D/A outpit range register */ |
| 177 | + unsigned char unipolar_gain; /* adjust for unipolar gain codes */ | |
| 234 | 178 | }; |
| 235 | 179 | |
| 236 | −static int pci171x_ai_check_chanlist(struct comedi_device *dev, | |
| 180 | +static int pci1710_ai_check_chanlist(struct comedi_device *dev, | |
| 237 | 181 | struct comedi_subdevice *s, |
| 238 | 182 | struct comedi_cmd *cmd) |
| 239 | 183 | { |
| @@ -299,13 +243,12 @@ static int pci171x_ai_check_chanlist(struct comedi_device *dev, · 59 unmodified lines | ||
| 299 | 243 | return 0; |
| 300 | 244 | } |
| 301 | 245 | |
| 302 | −static void pci171x_ai_setup_chanlist(struct comedi_device *dev, | |
| 246 | +static void pci1710_ai_setup_chanlist(struct comedi_device *dev, | |
| 303 | 247 | struct comedi_subdevice *s, |
| 304 | 248 | unsigned int *chanlist, |
| 305 | 249 | unsigned int n_chan, |
| 306 | 250 | unsigned int seglen) |
| 307 | 251 | { |
| 308 | − const struct boardtype *board = dev->board_ptr; | |
| 309 | 252 | struct pci1710_private *devpriv = dev->private; |
| 310 | 253 | unsigned int first_chan = CR_CHAN(chanlist[0]); |
| 311 | 254 | unsigned int last_chan = CR_CHAN(chanlist[seglen - 1]); |
| @@ -315,14 +258,18 @@ static void pci171x_ai_setup_chanlist(struct comedi_device *dev, · 3 unmodified lines | ||
| 315 | 258 | unsigned int chan = CR_CHAN(chanlist[i]); |
| 316 | 259 | unsigned int range = CR_RANGE(chanlist[i]); |
| 317 | 260 | unsigned int aref = CR_AREF(chanlist[i]); |
| 318 | − unsigned int rangeval; | |
| 261 | + unsigned int rangeval = 0; | |
| 319 | 262 | |
| 320 | − rangeval = board->rangecode_ai[range]; | |
| 321 | 263 | if (aref == AREF_DIFF) |
| 322 | − rangeval |= 0x0020; | |
| 264 | + rangeval |= PCI171X_RANGE_DIFF; | |
| 265 | + if (comedi_range_is_unipolar(s, range)) { | |
| 266 | + rangeval |= PCI171X_RANGE_UNI; | |
| 267 | + range -= devpriv->unipolar_gain; | |
| 268 | + } | |
| 269 | + rangeval |= PCI171X_RANGE_GAIN(range); | |
| 323 | 270 | |
| 324 | 271 | /* select channel and set range */ |
| 325 | − outw(chan | (chan << 8), dev->iobase + PCI171X_MUX_REG); | |
| 272 | + outw(PCI171X_MUX_CHAN(chan), dev->iobase + PCI171X_MUX_REG); | |
| 326 | 273 | outw(rangeval, dev->iobase + PCI171X_RANGE_REG); |
| 327 | 274 | |
| 328 | 275 | devpriv->act_chanlist[i] = chan; |
| @@ -331,11 +278,12 @@ static void pci171x_ai_setup_chanlist(struct comedi_device *dev, · 2 unmodified lines | ||
| 331 | 278 | devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); |
| 332 | 279 | |
| 333 | 280 | /* select channel interval to scan */ |
| 334 | − devpriv->mux_ext = first_chan | (last_chan << 8); | |
| 335 | − outw(devpriv->mux_ext, dev->iobase + PCI171X_MUX_REG); | |
| 281 | + devpriv->mux_scan = PCI171X_MUX_CHANL(first_chan) | | |
| 282 | + PCI171X_MUX_CHANH(last_chan); | |
| 283 | + outw(devpriv->mux_scan, dev->iobase + PCI171X_MUX_REG); | |
| 336 | 284 | } |
| 337 | 285 | |
| 338 | −static int pci171x_ai_eoc(struct comedi_device *dev, | |
| 286 | +static int pci1710_ai_eoc(struct comedi_device *dev, | |
| 339 | 287 | struct comedi_subdevice *s, |
| 340 | 288 | struct comedi_insn *insn, |
| 341 | 289 | unsigned long context) |
| @@ -348,7 +296,7 @@ static int pci171x_ai_eoc(struct comedi_device *dev, · 6 unmodified lines | ||
| 348 | 296 | return -EBUSY; |
| 349 | 297 | } |
| 350 | 298 | |
| 351 | −static int pci171x_ai_read_sample(struct comedi_device *dev, | |
| 299 | +static int pci1710_ai_read_sample(struct comedi_device *dev, | |
| 352 | 300 | struct comedi_subdevice *s, |
| 353 | 301 | unsigned int cur_chan, |
| 354 | 302 | unsigned int *val) |
| @@ -377,7 +325,7 @@ static int pci171x_ai_read_sample(struct comedi_device *dev, · 22 unmodified lines | ||
| 377 | 325 | return 0; |
| 378 | 326 | } |
| 379 | 327 | |
| 380 | −static int pci171x_ai_insn_read(struct comedi_device *dev, | |
| 328 | +static int pci1710_ai_insn_read(struct comedi_device *dev, | |
| 381 | 329 | struct comedi_subdevice *s, |
| 382 | 330 | struct comedi_insn *insn, |
| 383 | 331 | unsigned int *data) |
| @@ -386,13 +334,14 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, · 2 unmodified lines | ||
| 386 | 334 | int ret = 0; |
| 387 | 335 | int i; |
| 388 | 336 | |
| 389 | − devpriv->ctrl &= PCI171X_CTRL_CNT0; | |
| 390 | − devpriv->ctrl |= PCI171X_CTRL_SW; /* set software trigger */ | |
| 337 | + /* enable software trigger */ | |
| 338 | + devpriv->ctrl |= PCI171X_CTRL_SW; | |
| 391 | 339 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); |
| 340 | + | |
| 392 | 341 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 393 | 342 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 394 | 343 | |
| 395 | − pci171x_ai_setup_chanlist(dev, s, &insn->chanspec, 1, 1); | |
| 344 | + pci1710_ai_setup_chanlist(dev, s, &insn->chanspec, 1, 1); | |
| 396 | 345 | |
| 397 | 346 | for (i = 0; i < insn->n; i++) { |
| 398 | 347 | unsigned int val; |
| @@ -400,111 +349,40 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, · 1 unmodified line | ||
| 400 | 349 | /* start conversion */ |
| 401 | 350 | outw(0, dev->iobase + PCI171X_SOFTTRG_REG); |
| 402 | 351 | |
| 403 | − ret = comedi_timeout(dev, s, insn, pci171x_ai_eoc, 0); | |
| 352 | + ret = comedi_timeout(dev, s, insn, pci1710_ai_eoc, 0); | |
| 404 | 353 | if (ret) |
| 405 | 354 | break; |
| 406 | 355 | |
| 407 | − ret = pci171x_ai_read_sample(dev, s, 0, &val); | |
| 356 | + ret = pci1710_ai_read_sample(dev, s, 0, &val); | |
| 408 | 357 | if (ret) |
| 409 | 358 | break; |
| 410 | 359 | |
| 411 | 360 | data[i] = val; |
| 412 | 361 | } |
| 413 | 362 | |
| 363 | + /* disable software trigger */ | |
| 364 | + devpriv->ctrl &= ~PCI171X_CTRL_SW; | |
| 365 | + outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); | |
| 366 | + | |
| 414 | 367 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 415 | 368 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 416 | 369 | |
| 417 | 370 | return ret ? ret : insn->n; |
| 418 | 371 | } |
| 419 | 372 | |
| 420 | −static int pci171x_ao_insn_write(struct comedi_device *dev, | |
| 421 | − struct comedi_subdevice *s, | |
| 422 | − struct comedi_insn *insn, | |
| 423 | − unsigned int *data) | |
| 424 | −{ | |
| 425 | − struct pci1710_private *devpriv = dev->private; | |
| 426 | − unsigned int chan = CR_CHAN(insn->chanspec); | |
| 427 | − unsigned int range = CR_RANGE(insn->chanspec); | |
| 428 | − unsigned int val = s->readback[chan]; | |
| 429 | − int i; | |
| 430 | − | |
| 431 | − devpriv->da_ranges &= ~(1 << (chan << 1)); | |
| 432 | − devpriv->da_ranges |= (range << (chan << 1)); | |
| 433 | − outw(devpriv->da_ranges, dev->iobase + PCI171X_DAREF_REG); | |
| 434 | − | |
| 435 | − for (i = 0; i < insn->n; i++) { | |
| 436 | − val = data[i]; | |
| 437 | − outw(val, dev->iobase + PCI171X_DA_REG(chan)); | |
| 438 | − } | |
| 439 | − | |
| 440 | − s->readback[chan] = val; | |
| 441 | − | |
| 442 | − return insn->n; | |
| 443 | −} | |
| 444 | − | |
| 445 | −static int pci171x_di_insn_bits(struct comedi_device *dev, | |
| 446 | − struct comedi_subdevice *s, | |
| 447 | − struct comedi_insn *insn, | |
| 448 | − unsigned int *data) | |
| 449 | −{ | |
| 450 | − data[1] = inw(dev->iobase + PCI171X_DI_REG); | |
| 451 | − | |
| 452 | − return insn->n; | |
| 453 | −} | |
| 454 | − | |
| 455 | −static int pci171x_do_insn_bits(struct comedi_device *dev, | |
| 456 | − struct comedi_subdevice *s, | |
| 457 | − struct comedi_insn *insn, | |
| 458 | − unsigned int *data) | |
| 459 | −{ | |
| 460 | − if (comedi_dio_update_state(s, data)) | |
| 461 | − outw(s->state, dev->iobase + PCI171X_DO_REG); | |
| 462 | − | |
| 463 | − data[1] = s->state; | |
| 464 | − | |
| 465 | − return insn->n; | |
| 466 | −} | |
| 467 | − | |
| 468 | −static int pci1720_ao_insn_write(struct comedi_device *dev, | |
| 469 | − struct comedi_subdevice *s, | |
| 470 | − struct comedi_insn *insn, | |
| 471 | − unsigned int *data) | |
| 472 | −{ | |
| 473 | − struct pci1710_private *devpriv = dev->private; | |
| 474 | − unsigned int chan = CR_CHAN(insn->chanspec); | |
| 475 | − unsigned int range = CR_RANGE(insn->chanspec); | |
| 476 | − unsigned int val; | |
| 477 | − int i; | |
| 478 | − | |
| 479 | − val = devpriv->da_ranges & (~(0x03 << (chan << 1))); | |
| 480 | − val |= (range << (chan << 1)); | |
| 481 | − if (val != devpriv->da_ranges) { | |
| 482 | − outb(val, dev->iobase + PCI1720_RANGE_REG); | |
| 483 | − devpriv->da_ranges = val; | |
| 484 | − } | |
| 485 | − | |
| 486 | − val = s->readback[chan]; | |
| 487 | − for (i = 0; i < insn->n; i++) { | |
| 488 | − val = data[i]; | |
| 489 | − outw(val, dev->iobase + PCI1720_DA_REG(chan)); | |
| 490 | − outb(0, dev->iobase + PCI1720_SYNC_REG); /* update outputs */ | |
| 491 | − } | |
| 492 | − | |
| 493 | − s->readback[chan] = val; | |
| 494 | − | |
| 495 | − return insn->n; | |
| 496 | −} | |
| 497 | − | |
| 498 | −static int pci171x_ai_cancel(struct comedi_device *dev, | |
| 373 | +static int pci1710_ai_cancel(struct comedi_device *dev, | |
| 499 | 374 | struct comedi_subdevice *s) |
| 500 | 375 | { |
| 501 | 376 | struct pci1710_private *devpriv = dev->private; |
| 502 | 377 | |
| 503 | − devpriv->ctrl &= PCI171X_CTRL_CNT0; | |
| 504 | − devpriv->ctrl |= PCI171X_CTRL_SW; | |
| 505 | − /* reset any operations */ | |
| 378 | + /* disable A/D triggers and interrupt sources */ | |
| 379 | + devpriv->ctrl &= PCI171X_CTRL_CNT0; /* preserve counter 0 clk src */ | |
| 506 | 380 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); |
| 381 | + | |
| 382 | + /* disable pacer */ | |
| 507 | 383 | comedi_8254_pacer_enable(dev->pacer, 1, 2, false); |
| 384 | + | |
| 385 | + /* clear A/D FIFO and any pending interrutps */ | |
| 508 | 386 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 509 | 387 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 510 | 388 | |
| @@ -535,7 +413,7 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, · 24 unmodified lines | ||
| 535 | 413 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 536 | 414 | |
| 537 | 415 | for (; !(inw(dev->iobase + PCI171X_STATUS_REG) & PCI171X_STATUS_FE);) { |
| 538 | − ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); | |
| 416 | + ret = pci1710_ai_read_sample(dev, s, s->async->cur_chan, &val); | |
| 539 | 417 | if (ret) { |
| 540 | 418 | s->async->events |= COMEDI_CB_ERROR; |
| 541 | 419 | break; |
| @@ -579,7 +457,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev, · 37 unmodified lines | ||
| 579 | 457 | unsigned int val; |
| 580 | 458 | int ret; |
| 581 | 459 | |
| 582 | − ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); | |
| 460 | + ret = pci1710_ai_read_sample(dev, s, s->async->cur_chan, &val); | |
| 583 | 461 | if (ret) { |
| 584 | 462 | s->async->events |= COMEDI_CB_ERROR; |
| 585 | 463 | break; |
| @@ -598,7 +476,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev, · 12 unmodified lines | ||
| 598 | 476 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 599 | 477 | } |
| 600 | 478 | |
| 601 | −static irqreturn_t interrupt_service_pci1710(int irq, void *d) | |
| 479 | +static irqreturn_t pci1710_irq_handler(int irq, void *d) | |
| 602 | 480 | { |
| 603 | 481 | struct comedi_device *dev = d; |
| 604 | 482 | struct pci1710_private *devpriv = dev->private; |
| @@ -624,7 +502,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) · 19 unmodified lines | ||
| 624 | 502 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 625 | 503 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 626 | 504 | /* no sample on this interrupt; reset the channel interval */ |
| 627 | − outw(devpriv->mux_ext, dev->iobase + PCI171X_MUX_REG); | |
| 505 | + outw(devpriv->mux_scan, dev->iobase + PCI171X_MUX_REG); | |
| 628 | 506 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); |
| 629 | 507 | comedi_8254_pacer_enable(dev->pacer, 1, 2, true); |
| 630 | 508 | return IRQ_HANDLED; |
| @@ -640,12 +518,12 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) · 9 unmodified lines | ||
| 640 | 518 | return IRQ_HANDLED; |
| 641 | 519 | } |
| 642 | 520 | |
| 643 | −static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) | |
| 521 | +static int pci1710_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) | |
| 644 | 522 | { |
| 645 | 523 | struct pci1710_private *devpriv = dev->private; |
| 646 | 524 | struct comedi_cmd *cmd = &s->async->cmd; |
| 647 | 525 | |
| 648 | − pci171x_ai_setup_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, | |
| 526 | + pci1710_ai_setup_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, | |
| 649 | 527 | devpriv->saved_seglen); |
| 650 | 528 | |
| 651 | 529 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| @@ -681,7 +559,7 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 29 unmodified lines | ||
| 681 | 559 | return 0; |
| 682 | 560 | } |
| 683 | 561 | |
| 684 | −static int pci171x_ai_cmdtest(struct comedi_device *dev, | |
| 562 | +static int pci1710_ai_cmdtest(struct comedi_device *dev, | |
| 685 | 563 | struct comedi_subdevice *s, |
| 686 | 564 | struct comedi_cmd *cmd) |
| 687 | 565 | { |
| @@ -745,7 +623,7 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, · 57 unmodified lines | ||
| 745 | 623 | |
| 746 | 624 | /* Step 5: check channel list */ |
| 747 | 625 | |
| 748 | − err |= pci171x_ai_check_chanlist(dev, s, cmd); | |
| 626 | + err |= pci1710_ai_check_chanlist(dev, s, cmd); | |
| 749 | 627 | |
| 750 | 628 | if (err) |
| 751 | 629 | return 5; |
| @@ -753,7 +631,55 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, · 1 unmodified line | ||
| 753 | 631 | return 0; |
| 754 | 632 | } |
| 755 | 633 | |
| 756 | −static int pci171x_insn_counter_config(struct comedi_device *dev, | |
| 634 | +static int pci1710_ao_insn_write(struct comedi_device *dev, | |
| 635 | + struct comedi_subdevice *s, | |
| 636 | + struct comedi_insn *insn, | |
| 637 | + unsigned int *data) | |
| 638 | +{ | |
| 639 | + struct pci1710_private *devpriv = dev->private; | |
| 640 | + unsigned int chan = CR_CHAN(insn->chanspec); | |
| 641 | + unsigned int range = CR_RANGE(insn->chanspec); | |
| 642 | + unsigned int val = s->readback[chan]; | |
| 643 | + int i; | |
| 644 | + | |
| 645 | + devpriv->da_ranges &= ~PCI171X_DAREF_MASK(chan); | |
| 646 | + devpriv->da_ranges |= PCI171X_DAREF(chan, range); | |
| 647 | + outw(devpriv->da_ranges, dev->iobase + PCI171X_DAREF_REG); | |
| 648 | + | |
| 649 | + for (i = 0; i < insn->n; i++) { | |
| 650 | + val = data[i]; | |
| 651 | + outw(val, dev->iobase + PCI171X_DA_REG(chan)); | |
| 652 | + } | |
| 653 | + | |
| 654 | + s->readback[chan] = val; | |
| 655 | + | |
| 656 | + return insn->n; | |
| 657 | +} | |
| 658 | + | |
| 659 | +static int pci1710_di_insn_bits(struct comedi_device *dev, | |
| 660 | + struct comedi_subdevice *s, | |
| 661 | + struct comedi_insn *insn, | |
| 662 | + unsigned int *data) | |
| 663 | +{ | |
| 664 | + data[1] = inw(dev->iobase + PCI171X_DI_REG); | |
| 665 | + | |
| 666 | + return insn->n; | |
| 667 | +} | |
| 668 | + | |
| 669 | +static int pci1710_do_insn_bits(struct comedi_device *dev, | |
| 670 | + struct comedi_subdevice *s, | |
| 671 | + struct comedi_insn *insn, | |
| 672 | + unsigned int *data) | |
| 673 | +{ | |
| 674 | + if (comedi_dio_update_state(s, data)) | |
| 675 | + outw(s->state, dev->iobase + PCI171X_DO_REG); | |
| 676 | + | |
| 677 | + data[1] = s->state; | |
| 678 | + | |
| 679 | + return insn->n; | |
| 680 | +} | |
| 681 | + | |
| 682 | +static int pci1710_counter_insn_config(struct comedi_device *dev, | |
| 757 | 683 | struct comedi_subdevice *s, |
| 758 | 684 | struct comedi_insn *insn, |
| 759 | 685 | unsigned int *data) |
| @@ -780,7 +706,7 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, · 20 unmodified lines | ||
| 780 | 706 | data[2] = 0; |
| 781 | 707 | } else { |
| 782 | 708 | data[1] = 0; |
| 783 | − data[2] = I8254_OSC_BASE_10MHZ; | |
| 709 | + data[2] = I8254_OSC_BASE_1MHZ; | |
| 784 | 710 | } |
| 785 | 711 | break; |
| 786 | 712 | default: |
| @@ -790,56 +716,29 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, · 3 unmodified lines | ||
| 790 | 716 | return insn->n; |
| 791 | 717 | } |
| 792 | 718 | |
| 793 | −static int pci171x_reset(struct comedi_device *dev) | |
| 719 | +static void pci1710_reset(struct comedi_device *dev) | |
| 794 | 720 | { |
| 795 | 721 | const struct boardtype *board = dev->board_ptr; |
| 796 | − struct pci1710_private *devpriv = dev->private; | |
| 797 | 722 | |
| 798 | − /* Software trigger, CNT0=external */ | |
| 799 | − devpriv->ctrl = PCI171X_CTRL_SW | PCI171X_CTRL_CNT0; | |
| 800 | − /* reset any operations */ | |
| 801 | − outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); | |
| 723 | + /* | |
| 724 | + * Disable A/D triggers and interrupt sources, set counter 0 | |
| 725 | + * to use internal 1 MHz clock. | |
| 726 | + */ | |
| 727 | + outw(0, dev->iobase + PCI171X_CTRL_REG); | |
| 728 | + | |
| 729 | + /* clear A/D FIFO and any pending interrutps */ | |
| 802 | 730 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 803 | 731 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 804 | − devpriv->da_ranges = 0; | |
| 732 | + | |
| 805 | 733 | if (board->has_ao) { |
| 806 | 734 | /* set DACs to 0..5V and outputs to 0V */ |
| 807 | − outb(devpriv->da_ranges, dev->iobase + PCI171X_DAREF_REG); | |
| 735 | + outb(0, dev->iobase + PCI171X_DAREF_REG); | |
| 808 | 736 | outw(0, dev->iobase + PCI171X_DA_REG(0)); |
| 809 | 737 | outw(0, dev->iobase + PCI171X_DA_REG(1)); |
| 810 | 738 | } |
| 811 | − outw(0, dev->iobase + PCI171X_DO_REG); /* digital outputs to 0 */ | |
| 812 | − outb(0, dev->iobase + PCI171X_CLRFIFO_REG); | |
| 813 | − outb(0, dev->iobase + PCI171X_CLRINT_REG); | |
| 814 | 739 | |
| 815 | − return 0; | |
| 816 | −} | |
| 817 | − | |
| 818 | −static int pci1720_reset(struct comedi_device *dev) | |
| 819 | −{ | |
| 820 | − struct pci1710_private *devpriv = dev->private; | |
| 821 | − /* set synchronous output mode */ | |
| 822 | − outb(PCI1720_SYNC_CTRL_SC0, dev->iobase + PCI1720_SYNC_CTRL_REG); | |
| 823 | − devpriv->da_ranges = 0xAA; | |
| 824 | − /* set all ranges to +/-5V and outputs to 0V */ | |
| 825 | − outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE_REG); | |
| 826 | − outw(0x0800, dev->iobase + PCI1720_DA_REG(0)); | |
| 827 | − outw(0x0800, dev->iobase + PCI1720_DA_REG(1)); | |
| 828 | − outw(0x0800, dev->iobase + PCI1720_DA_REG(2)); | |
| 829 | − outw(0x0800, dev->iobase + PCI1720_DA_REG(3)); | |
| 830 | − outb(0, dev->iobase + PCI1720_SYNC_REG); /* update outputs */ | |
| 831 | − | |
| 832 | − return 0; | |
| 833 | −} | |
| 834 | − | |
| 835 | −static int pci1710_reset(struct comedi_device *dev) | |
| 836 | −{ | |
| 837 | − const struct boardtype *board = dev->board_ptr; | |
| 838 | − | |
| 839 | − if (board->is_pci1720) | |
| 840 | − return pci1720_reset(dev); | |
| 841 | − | |
| 842 | − return pci171x_reset(dev); | |
| 740 | + /* set digital outputs to 0 */ | |
| 741 | + outw(0, dev->iobase + PCI171X_DO_REG); | |
| 843 | 742 | } |
| 844 | 743 | |
| 845 | 744 | static int pci1710_auto_attach(struct comedi_device *dev, |
| @@ -850,6 +749,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, · 4 unmodified lines | ||
| 850 | 749 | struct pci1710_private *devpriv; |
| 851 | 750 | struct comedi_subdevice *s; |
| 852 | 751 | int ret, subdev, n_subdevices; |
| 752 | + int i; | |
| 853 | 753 | |
| 854 | 754 | if (context < ARRAY_SIZE(boardtypes)) |
| 855 | 755 | board = &boardtypes[context]; |
| @@ -872,15 +772,16 @@ static int pci1710_auto_attach(struct comedi_device *dev, · 16 unmodified lines | ||
| 872 | 772 | if (!dev->pacer) |
| 873 | 773 | return -ENOMEM; |
| 874 | 774 | |
| 875 | − n_subdevices = 0; | |
| 876 | − if (board->n_aichan) | |
| 877 | − n_subdevices++; | |
| 775 | + n_subdevices = 1; /* all boards have analog inputs */ | |
| 878 | 776 | if (board->has_ao) |
| 879 | 777 | n_subdevices++; |
| 880 | − if (board->has_di_do) | |
| 881 | − n_subdevices += 2; | |
| 882 | − if (board->has_counter) | |
| 883 | − n_subdevices++; | |
| 778 | + if (!board->is_pci1713) { | |
| 779 | + /* | |
| 780 | + * All other boards have digital inputs and outputs as | |
| 781 | + * well as a user counter. | |
| 782 | + */ | |
| 783 | + n_subdevices += 3; | |
| 784 | + } | |
| 884 | 785 | |
| 885 | 786 | ret = comedi_alloc_subdevices(dev, n_subdevices); |
| 886 | 787 | if (ret) |
| @@ -888,8 +789,8 @@ static int pci1710_auto_attach(struct comedi_device *dev, · 1 unmodified line | ||
| 888 | 789 | |
| 889 | 790 | pci1710_reset(dev); |
| 890 | 791 | |
| 891 | − if (board->has_irq && pcidev->irq) { | |
| 892 | − ret = request_irq(pcidev->irq, interrupt_service_pci1710, | |
| 792 | + if (pcidev->irq) { | |
| 793 | + ret = request_irq(pcidev->irq, pci1710_irq_handler, | |
| 893 | 794 | IRQF_SHARED, dev->board_name, dev); |
| 894 | 795 | if (ret == 0) |
| 895 | 796 | dev->irq = pcidev->irq; |
| @@ -897,109 +798,89 @@ static int pci1710_auto_attach(struct comedi_device *dev, · 1 unmodified line | ||
| 897 | 798 | |
| 898 | 799 | subdev = 0; |
| 899 | 800 | |
| 900 | − if (board->n_aichan) { | |
| 901 | − s = &dev->subdevices[subdev]; | |
| 902 | − s->type = COMEDI_SUBD_AI; | |
| 903 | − s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; | |
| 904 | − if (board->has_diff_ai) | |
| 905 | − s->subdev_flags |= SDF_DIFF; | |
| 906 | − s->n_chan = board->n_aichan; | |
| 907 | − s->maxdata = 0x0fff; | |
| 908 | − s->range_table = board->rangelist_ai; | |
| 909 | − s->insn_read = pci171x_ai_insn_read; | |
| 910 | − if (dev->irq) { | |
| 911 | − dev->read_subdev = s; | |
| 912 | − s->subdev_flags |= SDF_CMD_READ; | |
| 913 | − s->len_chanlist = s->n_chan; | |
| 914 | − s->do_cmdtest = pci171x_ai_cmdtest; | |
| 915 | − s->do_cmd = pci171x_ai_cmd; | |
| 916 | − s->cancel = pci171x_ai_cancel; | |
| 801 | + /* Analog Input subdevice */ | |
| 802 | + s = &dev->subdevices[subdev++]; | |
| 803 | + s->type = COMEDI_SUBD_AI; | |
| 804 | + s->subdev_flags = SDF_READABLE | SDF_GROUND; | |
| 805 | + if (!board->is_pci1711) | |
| 806 | + s->subdev_flags |= SDF_DIFF; | |
| 807 | + s->n_chan = board->is_pci1713 ? 32 : 16; | |
| 808 | + s->maxdata = 0x0fff; | |
| 809 | + s->range_table = board->ai_range; | |
| 810 | + s->insn_read = pci1710_ai_insn_read; | |
| 811 | + if (dev->irq) { | |
| 812 | + dev->read_subdev = s; | |
| 813 | + s->subdev_flags |= SDF_CMD_READ; | |
| 814 | + s->len_chanlist = s->n_chan; | |
| 815 | + s->do_cmdtest = pci1710_ai_cmdtest; | |
| 816 | + s->do_cmd = pci1710_ai_cmd; | |
| 817 | + s->cancel = pci1710_ai_cancel; | |
| 818 | + } | |
| 819 | + | |
| 820 | + /* find the value needed to adjust for unipolar gain codes */ | |
| 821 | + for (i = 0; i < s->range_table->length; i++) { | |
| 822 | + if (comedi_range_is_unipolar(s, i)) { | |
| 823 | + devpriv->unipolar_gain = i; | |
| 824 | + break; | |
| 917 | 825 | } |
| 918 | − subdev++; | |
| 919 | 826 | } |
| 920 | 827 | |
| 921 | 828 | if (board->has_ao) { |
| 922 | − s = &dev->subdevices[subdev]; | |
| 829 | + /* Analog Output subdevice */ | |
| 830 | + s = &dev->subdevices[subdev++]; | |
| 923 | 831 | s->type = COMEDI_SUBD_AO; |
| 924 | − s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; | |
| 832 | + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; | |
| 833 | + s->n_chan = 2; | |
| 925 | 834 | s->maxdata = 0x0fff; |
| 926 | − if (board->is_pci1720) { | |
| 927 | − s->n_chan = 4; | |
| 928 | − s->range_table = &pci1720_ao_range; | |
| 929 | − s->insn_write = pci1720_ao_insn_write; | |
| 930 | − } else { | |
| 931 | − s->n_chan = 2; | |
| 932 | − s->range_table = &pci171x_ao_range; | |
| 933 | − s->insn_write = pci171x_ao_insn_write; | |
| 934 | − } | |
| 835 | + s->range_table = &pci171x_ao_range; | |
| 836 | + s->insn_write = pci1710_ao_insn_write; | |
| 935 | 837 | |
| 936 | 838 | ret = comedi_alloc_subdev_readback(s); |
| 937 | 839 | if (ret) |
| 938 | 840 | return ret; |
| 939 | − | |
| 940 | − /* initialize the readback values to match the board reset */ | |
| 941 | − if (board->is_pci1720) { | |
| 942 | − int i; | |
| 943 | − | |
| 944 | − for (i = 0; i < s->n_chan; i++) | |
| 945 | − s->readback[i] = 0x0800; | |
| 946 | − } | |
| 947 | − | |
| 948 | − subdev++; | |
| 949 | 841 | } |
| 950 | 842 | |
| 951 | − if (board->has_di_do) { | |
| 952 | − s = &dev->subdevices[subdev]; | |
| 843 | + if (!board->is_pci1713) { | |
| 844 | + /* Digital Input subdevice */ | |
| 845 | + s = &dev->subdevices[subdev++]; | |
| 953 | 846 | s->type = COMEDI_SUBD_DI; |
| 954 | 847 | s->subdev_flags = SDF_READABLE; |
| 955 | 848 | s->n_chan = 16; |
| 956 | 849 | s->maxdata = 1; |
| 957 | 850 | s->range_table = &range_digital; |
| 958 | − s->insn_bits = pci171x_di_insn_bits; | |
| 959 | − subdev++; | |
| 851 | + s->insn_bits = pci1710_di_insn_bits; | |
| 960 | 852 | |
| 961 | − s = &dev->subdevices[subdev]; | |
| 853 | + /* Digital Output subdevice */ | |
| 854 | + s = &dev->subdevices[subdev++]; | |
| 962 | 855 | s->type = COMEDI_SUBD_DO; |
| 963 | 856 | s->subdev_flags = SDF_WRITABLE; |
| 964 | 857 | s->n_chan = 16; |
| 965 | 858 | s->maxdata = 1; |
| 966 | 859 | s->range_table = &range_digital; |
| 967 | − s->insn_bits = pci171x_do_insn_bits; | |
| 968 | − subdev++; | |
| 969 | − } | |
| 860 | + s->insn_bits = pci1710_do_insn_bits; | |
| 970 | 861 | |
| 971 | − /* Counter subdevice (8254) */ | |
| 972 | − if (board->has_counter) { | |
| 973 | − s = &dev->subdevices[subdev]; | |
| 862 | + /* Counter subdevice (8254) */ | |
| 863 | + s = &dev->subdevices[subdev++]; | |
| 974 | 864 | comedi_8254_subdevice_init(s, dev->pacer); |
| 975 | 865 | |
| 976 | − dev->pacer->insn_config = pci171x_insn_counter_config; | |
| 866 | + dev->pacer->insn_config = pci1710_counter_insn_config; | |
| 977 | 867 | |
| 978 | 868 | /* counters 1 and 2 are used internally for the pacer */ |
| 979 | 869 | comedi_8254_set_busy(dev->pacer, 1, true); |
| 980 | 870 | comedi_8254_set_busy(dev->pacer, 2, true); |
| 981 | − | |
| 982 | − subdev++; | |
| 983 | 871 | } |
| 984 | 872 | |
| 985 | 873 | /* max_samples is half the FIFO size (2 bytes/sample) */ |
| 986 | − devpriv->max_samples = (board->has_large_fifo) ? 2048 : 512; | |
| 874 | + devpriv->max_samples = (board->is_pci1711) ? 512 : 2048; | |
| 987 | 875 | |
| 988 | 876 | return 0; |
| 989 | 877 | } |
| 990 | 878 | |
| 991 | −static void pci1710_detach(struct comedi_device *dev) | |
| 992 | −{ | |
| 993 | − if (dev->iobase) | |
| 994 | − pci1710_reset(dev); | |
| 995 | − comedi_pci_detach(dev); | |
| 996 | −} | |
| 997 | − | |
| 998 | 879 | static struct comedi_driver adv_pci1710_driver = { |
| 999 | 880 | .driver_name = "adv_pci1710", |
| 1000 | 881 | .module = THIS_MODULE, |
| 1001 | 882 | .auto_attach = pci1710_auto_attach, |
| 1002 | − .detach = pci1710_detach, | |
| 883 | + .detach = comedi_pci_detach, | |
| 1003 | 884 | }; |
| 1004 | 885 | |
| 1005 | 886 | static int adv_pci1710_pci_probe(struct pci_dev *dev, |
| @@ -1063,7 +944,6 @@ static const struct pci_device_id adv_pci1710_pci_table[] = { · 57 unmodified lines | ||
| 1063 | 944 | }, |
| 1064 | 945 | { PCI_VDEVICE(ADVANTECH, 0x1711), BOARD_PCI1711 }, |
| 1065 | 946 | { PCI_VDEVICE(ADVANTECH, 0x1713), BOARD_PCI1713 }, |
| 1066 | − { PCI_VDEVICE(ADVANTECH, 0x1720), BOARD_PCI1720 }, | |
| 1067 | 947 | { PCI_VDEVICE(ADVANTECH, 0x1731), BOARD_PCI1731 }, |
| 1068 | 948 | { 0 } |
| 1069 | 949 | }; |
| @@ -0,0 +1,195 @@ | ||
| 1 | +/* | |
| 2 | + * COMEDI driver for Advantech PCI-1720U | |
| 3 | + * Copyright (c) 2015 H Hartley Sweeten <hsweeten@visionengravers.com> | |
| 4 | + * | |
| 5 | + * Separated from the adv_pci1710 driver written by: | |
| 6 | + * Michal Dobes <dobes@tesnet.cz> | |
| 7 | + * | |
| 8 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 9 | + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> | |
| 10 | + * | |
| 11 | + * This program is free software; you can redistribute it and/or modify | |
| 12 | + * it under the terms of the GNU General Public License as published by | |
| 13 | + * the Free Software Foundation; either version 2 of the License, or | |
| 14 | + * (at your option) any later version. | |
| 15 | + * | |
| 16 | + * This program is distributed in the hope that it will be useful, | |
| 17 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 | + * GNU General Public License for more details. | |
| 20 | + */ | |
| 21 | + | |
| 22 | +/* | |
| 23 | + * Driver: adv_pci1720 | |
| 24 | + * Description: 4-channel Isolated D/A Output board | |
| 25 | + * Devices: [Advantech] PCI-7120U (adv_pci1720) | |
| 26 | + * Author: H Hartley Sweeten <hsweeten@visionengravers.com> | |
| 27 | + * Updated: Fri, 29 Oct 2015 17:19:35 -0700 | |
| 28 | + * Status: untested | |
| 29 | + * | |
| 30 | + * Configuration options: not applicable, uses PCI auto config | |
| 31 | + * | |
| 32 | + * The PCI-1720 has 4 isolated 12-bit analog output channels with multiple | |
| 33 | + * output ranges. It also has a BoardID switch to allow differentiating | |
| 34 | + * multiple boards in the system. | |
| 35 | + * | |
| 36 | + * The analog outputs can operate in two modes, immediate and synchronized. | |
| 37 | + * This driver currently does not support the synchronized output mode. | |
| 38 | + * | |
| 39 | + * Jumpers JP1 to JP4 are used to set the current sink ranges for each | |
| 40 | + * analog output channel. In order to use the current sink ranges, the | |
| 41 | + * unipolar 5V range must be used. The voltage output and sink output for | |
| 42 | + * each channel is available on the connector as separate pins. | |
| 43 | + * | |
| 44 | + * Jumper JP5 controls the "hot" reset state of the analog outputs. | |
| 45 | + * Depending on its setting, the analog outputs will either keep the | |
| 46 | + * last settings and output values or reset to the default state after | |
| 47 | + * a "hot" reset. The default state for all channels is uniploar 5V range | |
| 48 | + * and all the output values are 0V. To allow this feature to work, the | |
| 49 | + * analog outputs are not "reset" when the driver attaches. | |
| 50 | + */ | |
| 51 | + | |
| 52 | +#include <linux/module.h> | |
| 53 | +#include <linux/delay.h> | |
| 54 | + | |
| 55 | +#include "../comedi_pci.h" | |
| 56 | + | |
| 57 | +/* | |
| 58 | + * PCI BAR2 Register map (dev->iobase) | |
| 59 | + */ | |
| 60 | +#define PCI1720_AO_LSB_REG(x) (0x00 + ((x) * 2)) | |
| 61 | +#define PCI1720_AO_MSB_REG(x) (0x01 + ((x) * 2)) | |
| 62 | +#define PCI1720_AO_RANGE_REG 0x08 | |
| 63 | +#define PCI1720_AO_RANGE(c, r) (((r) & 0x3) << ((c) * 2)) | |
| 64 | +#define PCI1720_AO_RANGE_MASK(c) PCI1720_AO_RANGE((c), 0x3) | |
| 65 | +#define PCI1720_SYNC_REG 0x09 | |
| 66 | +#define PCI1720_SYNC_CTRL_REG 0x0f | |
| 67 | +#define PCI1720_SYNC_CTRL_SC0 BIT(0) | |
| 68 | +#define PCI1720_BOARDID_REG 0x14 | |
| 69 | + | |
| 70 | +static const struct comedi_lrange pci1720_ao_range = { | |
| 71 | + 4, { | |
| 72 | + UNI_RANGE(5), | |
| 73 | + UNI_RANGE(10), | |
| 74 | + BIP_RANGE(5), | |
| 75 | + BIP_RANGE(10) | |
| 76 | + } | |
| 77 | +}; | |
| 78 | + | |
| 79 | +static int pci1720_ao_insn_write(struct comedi_device *dev, | |
| 80 | + struct comedi_subdevice *s, | |
| 81 | + struct comedi_insn *insn, | |
| 82 | + unsigned int *data) | |
| 83 | +{ | |
| 84 | + unsigned int chan = CR_CHAN(insn->chanspec); | |
| 85 | + unsigned int range = CR_RANGE(insn->chanspec); | |
| 86 | + unsigned int val; | |
| 87 | + int i; | |
| 88 | + | |
| 89 | + /* set the channel range and polarity */ | |
| 90 | + val = inb(dev->iobase + PCI1720_AO_RANGE_REG); | |
| 91 | + val &= ~PCI1720_AO_RANGE_MASK(chan); | |
| 92 | + val |= PCI1720_AO_RANGE(chan, range); | |
| 93 | + outb(val, dev->iobase + PCI1720_AO_RANGE_REG); | |
| 94 | + | |
| 95 | + val = s->readback[chan]; | |
| 96 | + for (i = 0; i < insn->n; i++) { | |
| 97 | + val = data[i]; | |
| 98 | + | |
| 99 | + outb(val & 0xff, dev->iobase + PCI1720_AO_LSB_REG(chan)); | |
| 100 | + outb((val >> 8) & 0xff, dev->iobase + PCI1720_AO_MSB_REG(chan)); | |
| 101 | + | |
| 102 | + /* conversion time is 2us (500 kHz throughput) */ | |
| 103 | + usleep_range(2, 100); | |
| 104 | + } | |
| 105 | + | |
| 106 | + s->readback[chan] = val; | |
| 107 | + | |
| 108 | + return insn->n; | |
| 109 | +} | |
| 110 | + | |
| 111 | +static int pci1720_di_insn_bits(struct comedi_device *dev, | |
| 112 | + struct comedi_subdevice *s, | |
| 113 | + struct comedi_insn *insn, | |
| 114 | + unsigned int *data) | |
| 115 | +{ | |
| 116 | + data[1] = inb(dev->iobase + PCI1720_BOARDID_REG); | |
| 117 | + | |
| 118 | + return insn->n; | |
| 119 | +} | |
| 120 | + | |
| 121 | +static int pci1720_auto_attach(struct comedi_device *dev, | |
| 122 | + unsigned long context) | |
| 123 | +{ | |
| 124 | + struct pci_dev *pcidev = comedi_to_pci_dev(dev); | |
| 125 | + struct comedi_subdevice *s; | |
| 126 | + int ret; | |
| 127 | + | |
| 128 | + ret = comedi_pci_enable(dev); | |
| 129 | + if (ret) | |
| 130 | + return ret; | |
| 131 | + dev->iobase = pci_resource_start(pcidev, 2); | |
| 132 | + | |
| 133 | + ret = comedi_alloc_subdevices(dev, 2); | |
| 134 | + if (ret) | |
| 135 | + return ret; | |
| 136 | + | |
| 137 | + /* Analog Output subdevice */ | |
| 138 | + s = &dev->subdevices[0]; | |
| 139 | + s->type = COMEDI_SUBD_AO; | |
| 140 | + s->subdev_flags = SDF_WRITABLE; | |
| 141 | + s->n_chan = 4; | |
| 142 | + s->maxdata = 0x0fff; | |
| 143 | + s->range_table = &pci1720_ao_range; | |
| 144 | + s->insn_write = pci1720_ao_insn_write; | |
| 145 | + | |
| 146 | + ret = comedi_alloc_subdev_readback(s); | |
| 147 | + if (ret) | |
| 148 | + return ret; | |
| 149 | + | |
| 150 | + /* Digital Input subdevice (BoardID SW1) */ | |
| 151 | + s = &dev->subdevices[1]; | |
| 152 | + s->type = COMEDI_SUBD_DI; | |
| 153 | + s->subdev_flags = SDF_READABLE; | |
| 154 | + s->n_chan = 4; | |
| 155 | + s->maxdata = 1; | |
| 156 | + s->range_table = &range_digital; | |
| 157 | + s->insn_bits = pci1720_di_insn_bits; | |
| 158 | + | |
| 159 | + /* disable synchronized output, channels update when written */ | |
| 160 | + outb(0, dev->iobase + PCI1720_SYNC_CTRL_REG); | |
| 161 | + | |
| 162 | + return 0; | |
| 163 | +} | |
| 164 | + | |
| 165 | +static struct comedi_driver adv_pci1720_driver = { | |
| 166 | + .driver_name = "adv_pci1720", | |
| 167 | + .module = THIS_MODULE, | |
| 168 | + .auto_attach = pci1720_auto_attach, | |
| 169 | + .detach = comedi_pci_detach, | |
| 170 | +}; | |
| 171 | + | |
| 172 | +static int adv_pci1720_pci_probe(struct pci_dev *dev, | |
| 173 | + const struct pci_device_id *id) | |
| 174 | +{ | |
| 175 | + return comedi_pci_auto_config(dev, &adv_pci1720_driver, | |
| 176 | + id->driver_data); | |
| 177 | +} | |
| 178 | + | |
| 179 | +static const struct pci_device_id adv_pci1720_pci_table[] = { | |
| 180 | + { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) }, | |
| 181 | + { 0 } | |
| 182 | +}; | |
| 183 | +MODULE_DEVICE_TABLE(pci, adv_pci1720_pci_table); | |
| 184 | + | |
| 185 | +static struct pci_driver adv_pci1720_pci_driver = { | |
| 186 | + .name = "adv_pci1720", | |
| 187 | + .id_table = adv_pci1720_pci_table, | |
| 188 | + .probe = adv_pci1720_pci_probe, | |
| 189 | + .remove = comedi_pci_auto_unconfig, | |
| 190 | +}; | |
| 191 | +module_comedi_pci_driver(adv_pci1720_driver, adv_pci1720_pci_driver); | |
| 192 | + | |
| 193 | +MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); | |
| 194 | +MODULE_DESCRIPTION("Comedi driver for Advantech PCI-1720 Analog Output board"); | |
| 195 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,432 @@ | ||
| 1 | +/* | |
| 2 | + * COMEDI driver for the Advantech PCI-1760 | |
| 3 | + * Copyright (C) 2015 H Hartley Sweeten <hsweeten@visionengravers.com> | |
| 4 | + * | |
| 5 | + * Based on the pci1760 support in the adv_pci_dio driver written by: | |
| 6 | + * Michal Dobes <dobes@tesnet.cz> | |
| 7 | + * | |
| 8 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 9 | + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> | |
| 10 | + * | |
| 11 | + * This program is free software; you can redistribute it and/or modify | |
| 12 | + * it under the terms of the GNU General Public License as published by | |
| 13 | + * the Free Software Foundation; either version 2 of the License, or | |
| 14 | + * (at your option) any later version. | |
| 15 | + * | |
| 16 | + * This program is distributed in the hope that it will be useful, | |
| 17 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 | + * GNU General Public License for more details. | |
| 20 | + */ | |
| 21 | + | |
| 22 | +/* | |
| 23 | + * Driver: adv_pci1760 | |
| 24 | + * Description: Advantech PCI-1760 Relay & Isolated Digital Input Card | |
| 25 | + * Devices: [Advantech] PCI-1760 (adv_pci1760) | |
| 26 | + * Author: H Hartley Sweeten <hsweeten@visionengravers.com> | |
| 27 | + * Updated: Fri, 13 Nov 2015 12:34:00 -0700 | |
| 28 | + * Status: untested | |
| 29 | + * | |
| 30 | + * Configuration Options: not applicable, uses PCI auto config | |
| 31 | + */ | |
| 32 | + | |
| 33 | +#include <linux/module.h> | |
| 34 | + | |
| 35 | +#include "../comedi_pci.h" | |
| 36 | + | |
| 37 | +/* | |
| 38 | + * PCI-1760 Register Map | |
| 39 | + * | |
| 40 | + * Outgoing Mailbox Bytes | |
| 41 | + * OMB3: Not used (must be 0) | |
| 42 | + * OMB2: The command code to the PCI-1760 | |
| 43 | + * OMB1: The hi byte of the parameter for the command in OMB2 | |
| 44 | + * OMB0: The lo byte of the parameter for the command in OMB2 | |
| 45 | + * | |
| 46 | + * Incoming Mailbox Bytes | |
| 47 | + * IMB3: The Isolated Digital Input status (updated every 100us) | |
| 48 | + * IMB2: The current command (matches OMB2 when command is successful) | |
| 49 | + * IMB1: The hi byte of the feedback data for the command in OMB2 | |
| 50 | + * IMB0: The lo byte of the feedback data for the command in OMB2 | |
| 51 | + * | |
| 52 | + * Interrupt Control/Status | |
| 53 | + * INTCSR3: Not used (must be 0) | |
| 54 | + * INTCSR2: The interrupt status (read only) | |
| 55 | + * INTCSR1: Interrupt enable/disable | |
| 56 | + * INTCSR0: Not used (must be 0) | |
| 57 | + */ | |
| 58 | +#define PCI1760_OMB_REG(x) (0x0c + (x)) | |
| 59 | +#define PCI1760_IMB_REG(x) (0x1c + (x)) | |
| 60 | +#define PCI1760_INTCSR_REG(x) (0x38 + (x)) | |
| 61 | +#define PCI1760_INTCSR1_IRQ_ENA BIT(5) | |
| 62 | +#define PCI1760_INTCSR2_OMB_IRQ BIT(0) | |
| 63 | +#define PCI1760_INTCSR2_IMB_IRQ BIT(1) | |
| 64 | +#define PCI1760_INTCSR2_IRQ_STATUS BIT(6) | |
| 65 | +#define PCI1760_INTCSR2_IRQ_ASSERTED BIT(7) | |
| 66 | + | |
| 67 | +/* PCI-1760 command codes */ | |
| 68 | +#define PCI1760_CMD_CLR_IMB2 0x00 /* Clears IMB2 */ | |
| 69 | +#define PCI1760_CMD_SET_DO 0x01 /* Set output state */ | |
| 70 | +#define PCI1760_CMD_GET_DO 0x02 /* Read output status */ | |
| 71 | +#define PCI1760_CMD_GET_STATUS 0x03 /* Read current status */ | |
| 72 | +#define PCI1760_CMD_GET_FW_VER 0x0e /* Read firware version */ | |
| 73 | +#define PCI1760_CMD_GET_HW_VER 0x0f /* Read hardware version */ | |
| 74 | +#define PCI1760_CMD_SET_PWM_HI(x) (0x10 + (x) * 2) /* Set "hi" period */ | |
| 75 | +#define PCI1760_CMD_SET_PWM_LO(x) (0x11 + (x) * 2) /* Set "lo" period */ | |
| 76 | +#define PCI1760_CMD_SET_PWM_CNT(x) (0x14 + (x)) /* Set burst count */ | |
| 77 | +#define PCI1760_CMD_ENA_PWM 0x1f /* Enable PWM outputs */ | |
| 78 | +#define PCI1760_CMD_ENA_FILT 0x20 /* Enable input filter */ | |
| 79 | +#define PCI1760_CMD_ENA_PAT_MATCH 0x21 /* Enable input pattern match */ | |
| 80 | +#define PCI1760_CMD_SET_PAT_MATCH 0x22 /* Set input pattern match */ | |
| 81 | +#define PCI1760_CMD_ENA_RISE_EDGE 0x23 /* Enable input rising edge */ | |
| 82 | +#define PCI1760_CMD_ENA_FALL_EDGE 0x24 /* Enable input falling edge */ | |
| 83 | +#define PCI1760_CMD_ENA_CNT 0x28 /* Enable counter */ | |
| 84 | +#define PCI1760_CMD_RST_CNT 0x29 /* Reset counter */ | |
| 85 | +#define PCI1760_CMD_ENA_CNT_OFLOW 0x2a /* Enable counter overflow */ | |
| 86 | +#define PCI1760_CMD_ENA_CNT_MATCH 0x2b /* Enable counter match */ | |
| 87 | +#define PCI1760_CMD_SET_CNT_EDGE 0x2c /* Set counter edge */ | |
| 88 | +#define PCI1760_CMD_GET_CNT 0x2f /* Reads counter value */ | |
| 89 | +#define PCI1760_CMD_SET_HI_SAMP(x) (0x30 + (x)) /* Set "hi" sample time */ | |
| 90 | +#define PCI1760_CMD_SET_LO_SAMP(x) (0x38 + (x)) /* Set "lo" sample time */ | |
| 91 | +#define PCI1760_CMD_SET_CNT(x) (0x40 + (x)) /* Set counter reset val */ | |
| 92 | +#define PCI1760_CMD_SET_CNT_MATCH(x) (0x48 + (x)) /* Set counter match val */ | |
| 93 | +#define PCI1760_CMD_GET_INT_FLAGS 0x60 /* Read interrupt flags */ | |
| 94 | +#define PCI1760_CMD_GET_INT_FLAGS_MATCH BIT(0) | |
| 95 | +#define PCI1760_CMD_GET_INT_FLAGS_COS BIT(1) | |
| 96 | +#define PCI1760_CMD_GET_INT_FLAGS_OFLOW BIT(2) | |
| 97 | +#define PCI1760_CMD_GET_OS 0x61 /* Read edge change flags */ | |
| 98 | +#define PCI1760_CMD_GET_CNT_STATUS 0x62 /* Read counter oflow/match */ | |
| 99 | + | |
| 100 | +#define PCI1760_CMD_TIMEOUT 250 /* 250 usec timeout */ | |
| 101 | +#define PCI1760_CMD_RETRIES 3 /* limit number of retries */ | |
| 102 | + | |
| 103 | +#define PCI1760_PWM_TIMEBASE 100000 /* 1 unit = 100 usec */ | |
| 104 | + | |
| 105 | +static int pci1760_send_cmd(struct comedi_device *dev, | |
| 106 | + unsigned char cmd, unsigned short val) | |
| 107 | +{ | |
| 108 | + unsigned long timeout; | |
| 109 | + | |
| 110 | + /* send the command and parameter */ | |
| 111 | + outb(val & 0xff, dev->iobase + PCI1760_OMB_REG(0)); | |
| 112 | + outb((val >> 8) & 0xff, dev->iobase + PCI1760_OMB_REG(1)); | |
| 113 | + outb(cmd, dev->iobase + PCI1760_OMB_REG(2)); | |
| 114 | + outb(0, dev->iobase + PCI1760_OMB_REG(3)); | |
| 115 | + | |
| 116 | + /* datasheet says to allow up to 250 usec for the command to complete */ | |
| 117 | + timeout = jiffies + usecs_to_jiffies(PCI1760_CMD_TIMEOUT); | |
| 118 | + do { | |
| 119 | + if (inb(dev->iobase + PCI1760_IMB_REG(2)) == cmd) { | |
| 120 | + /* command success; return the feedback data */ | |
| 121 | + return inb(dev->iobase + PCI1760_IMB_REG(0)) | | |
| 122 | + (inb(dev->iobase + PCI1760_IMB_REG(1)) << 8); | |
| 123 | + } | |
| 124 | + cpu_relax(); | |
| 125 | + } while (time_before(jiffies, timeout)); | |
| 126 | + | |
| 127 | + return -EBUSY; | |
| 128 | +} | |
| 129 | + | |
| 130 | +static int pci1760_cmd(struct comedi_device *dev, | |
| 131 | + unsigned char cmd, unsigned short val) | |
| 132 | +{ | |
| 133 | + int repeats; | |
| 134 | + int ret; | |
| 135 | + | |
| 136 | + /* send PCI1760_CMD_CLR_IMB2 between identical commands */ | |
| 137 | + if (inb(dev->iobase + PCI1760_IMB_REG(2)) == cmd) { | |
| 138 | + ret = pci1760_send_cmd(dev, PCI1760_CMD_CLR_IMB2, 0); | |
| 139 | + if (ret < 0) { | |
| 140 | + /* timeout? try it once more */ | |
| 141 | + ret = pci1760_send_cmd(dev, PCI1760_CMD_CLR_IMB2, 0); | |
| 142 | + if (ret < 0) | |
| 143 | + return -ETIMEDOUT; | |
| 144 | + } | |
| 145 | + } | |
| 146 | + | |
| 147 | + /* datasheet says to keep retrying the command */ | |
| 148 | + for (repeats = 0; repeats < PCI1760_CMD_RETRIES; repeats++) { | |
| 149 | + ret = pci1760_send_cmd(dev, cmd, val); | |
| 150 | + if (ret >= 0) | |
| 151 | + return ret; | |
| 152 | + } | |
| 153 | + | |
| 154 | + /* command failed! */ | |
| 155 | + return -ETIMEDOUT; | |
| 156 | +} | |
| 157 | + | |
| 158 | +static int pci1760_di_insn_bits(struct comedi_device *dev, | |
| 159 | + struct comedi_subdevice *s, | |
| 160 | + struct comedi_insn *insn, | |
| 161 | + unsigned int *data) | |
| 162 | +{ | |
| 163 | + data[1] = inb(dev->iobase + PCI1760_IMB_REG(3)); | |
| 164 | + | |
| 165 | + return insn->n; | |
| 166 | +} | |
| 167 | + | |
| 168 | +static int pci1760_do_insn_bits(struct comedi_device *dev, | |
| 169 | + struct comedi_subdevice *s, | |
| 170 | + struct comedi_insn *insn, | |
| 171 | + unsigned int *data) | |
| 172 | +{ | |
| 173 | + int ret; | |
| 174 | + | |
| 175 | + if (comedi_dio_update_state(s, data)) { | |
| 176 | + ret = pci1760_cmd(dev, PCI1760_CMD_SET_DO, s->state); | |
| 177 | + if (ret < 0) | |
| 178 | + return ret; | |
| 179 | + } | |
| 180 | + | |
| 181 | + data[1] = s->state; | |
| 182 | + | |
| 183 | + return insn->n; | |
| 184 | +} | |
| 185 | + | |
| 186 | +static int pci1760_pwm_ns_to_div(unsigned int flags, unsigned int ns) | |
| 187 | +{ | |
| 188 | + unsigned int divisor; | |
| 189 | + | |
| 190 | + switch (flags) { | |
| 191 | + case CMDF_ROUND_NEAREST: | |
| 192 | + divisor = DIV_ROUND_CLOSEST(ns, PCI1760_PWM_TIMEBASE); | |
| 193 | + break; | |
| 194 | + case CMDF_ROUND_UP: | |
| 195 | + divisor = DIV_ROUND_UP(ns, PCI1760_PWM_TIMEBASE); | |
| 196 | + break; | |
| 197 | + case CMDF_ROUND_DOWN: | |
| 198 | + divisor = ns / PCI1760_PWM_TIMEBASE; | |
| 199 | + default: | |
| 200 | + return -EINVAL; | |
| 201 | + } | |
| 202 | + | |
| 203 | + if (divisor < 1) | |
| 204 | + divisor = 1; | |
| 205 | + if (divisor > 0xffff) | |
| 206 | + divisor = 0xffff; | |
| 207 | + | |
| 208 | + return divisor; | |
| 209 | +} | |
| 210 | + | |
| 211 | +static int pci1760_pwm_enable(struct comedi_device *dev, | |
| 212 | + unsigned int chan, bool enable) | |
| 213 | +{ | |
| 214 | + int ret; | |
| 215 | + | |
| 216 | + ret = pci1760_cmd(dev, PCI1760_CMD_GET_STATUS, PCI1760_CMD_ENA_PWM); | |
| 217 | + if (ret < 0) | |
| 218 | + return ret; | |
| 219 | + | |
| 220 | + if (enable) | |
| 221 | + ret |= BIT(chan); | |
| 222 | + else | |
| 223 | + ret &= ~BIT(chan); | |
| 224 | + | |
| 225 | + return pci1760_cmd(dev, PCI1760_CMD_ENA_PWM, ret); | |
| 226 | +} | |
| 227 | + | |
| 228 | +static int pci1760_pwm_insn_config(struct comedi_device *dev, | |
| 229 | + struct comedi_subdevice *s, | |
| 230 | + struct comedi_insn *insn, | |
| 231 | + unsigned int *data) | |
| 232 | +{ | |
| 233 | + unsigned int chan = CR_CHAN(insn->chanspec); | |
| 234 | + int hi_div; | |
| 235 | + int lo_div; | |
| 236 | + int ret; | |
| 237 | + | |
| 238 | + switch (data[0]) { | |
| 239 | + case INSN_CONFIG_ARM: | |
| 240 | + ret = pci1760_pwm_enable(dev, chan, false); | |
| 241 | + if (ret < 0) | |
| 242 | + return ret; | |
| 243 | + | |
| 244 | + if (data[1] > 0xffff) | |
| 245 | + return -EINVAL; | |
| 246 | + ret = pci1760_cmd(dev, PCI1760_CMD_SET_PWM_CNT(chan), data[1]); | |
| 247 | + if (ret < 0) | |
| 248 | + return ret; | |
| 249 | + | |
| 250 | + ret = pci1760_pwm_enable(dev, chan, true); | |
| 251 | + if (ret < 0) | |
| 252 | + return ret; | |
| 253 | + break; | |
| 254 | + case INSN_CONFIG_DISARM: | |
| 255 | + ret = pci1760_pwm_enable(dev, chan, false); | |
| 256 | + if (ret < 0) | |
| 257 | + return ret; | |
| 258 | + break; | |
| 259 | + case INSN_CONFIG_PWM_OUTPUT: | |
| 260 | + ret = pci1760_pwm_enable(dev, chan, false); | |
| 261 | + if (ret < 0) | |
| 262 | + return ret; | |
| 263 | + | |
| 264 | + hi_div = pci1760_pwm_ns_to_div(data[1], data[2]); | |
| 265 | + lo_div = pci1760_pwm_ns_to_div(data[3], data[4]); | |
| 266 | + if (hi_div < 0 || lo_div < 0) | |
| 267 | + return -EINVAL; | |
| 268 | + if ((hi_div * PCI1760_PWM_TIMEBASE) != data[2] || | |
| 269 | + (lo_div * PCI1760_PWM_TIMEBASE) != data[4]) { | |
| 270 | + data[2] = hi_div * PCI1760_PWM_TIMEBASE; | |
| 271 | + data[4] = lo_div * PCI1760_PWM_TIMEBASE; | |
| 272 | + return -EAGAIN; | |
| 273 | + } | |
| 274 | + ret = pci1760_cmd(dev, PCI1760_CMD_SET_PWM_HI(chan), hi_div); | |
| 275 | + if (ret < 0) | |
| 276 | + return ret; | |
| 277 | + ret = pci1760_cmd(dev, PCI1760_CMD_SET_PWM_LO(chan), lo_div); | |
| 278 | + if (ret < 0) | |
| 279 | + return ret; | |
| 280 | + break; | |
| 281 | + case INSN_CONFIG_GET_PWM_OUTPUT: | |
| 282 | + hi_div = pci1760_cmd(dev, PCI1760_CMD_GET_STATUS, | |
| 283 | + PCI1760_CMD_SET_PWM_HI(chan)); | |
| 284 | + lo_div = pci1760_cmd(dev, PCI1760_CMD_GET_STATUS, | |
| 285 | + PCI1760_CMD_SET_PWM_LO(chan)); | |
| 286 | + if (hi_div < 0 || lo_div < 0) | |
| 287 | + return -ETIMEDOUT; | |
| 288 | + | |
| 289 | + data[1] = hi_div * PCI1760_PWM_TIMEBASE; | |
| 290 | + data[2] = lo_div * PCI1760_PWM_TIMEBASE; | |
| 291 | + break; | |
| 292 | + case INSN_CONFIG_GET_PWM_STATUS: | |
| 293 | + ret = pci1760_cmd(dev, PCI1760_CMD_GET_STATUS, | |
| 294 | + PCI1760_CMD_ENA_PWM); | |
| 295 | + if (ret < 0) | |
| 296 | + return ret; | |
| 297 | + | |
| 298 | + data[1] = (ret & BIT(chan)) ? 1 : 0; | |
| 299 | + break; | |
| 300 | + default: | |
| 301 | + return -EINVAL; | |
| 302 | + } | |
| 303 | + | |
| 304 | + return insn->n; | |
| 305 | +} | |
| 306 | + | |
| 307 | +static void pci1760_reset(struct comedi_device *dev) | |
| 308 | +{ | |
| 309 | + int i; | |
| 310 | + | |
| 311 | + /* disable interrupts (intcsr2 is read-only) */ | |
| 312 | + outb(0, dev->iobase + PCI1760_INTCSR_REG(0)); | |
| 313 | + outb(0, dev->iobase + PCI1760_INTCSR_REG(1)); | |
| 314 | + outb(0, dev->iobase + PCI1760_INTCSR_REG(3)); | |
| 315 | + | |
| 316 | + /* disable counters */ | |
| 317 | + pci1760_cmd(dev, PCI1760_CMD_ENA_CNT, 0); | |
| 318 | + | |
| 319 | + /* disable overflow interrupts */ | |
| 320 | + pci1760_cmd(dev, PCI1760_CMD_ENA_CNT_OFLOW, 0); | |
| 321 | + | |
| 322 | + /* disable match */ | |
| 323 | + pci1760_cmd(dev, PCI1760_CMD_ENA_CNT_MATCH, 0); | |
| 324 | + | |
| 325 | + /* set match and counter reset values */ | |
| 326 | + for (i = 0; i < 8; i++) { | |
| 327 | + pci1760_cmd(dev, PCI1760_CMD_SET_CNT_MATCH(i), 0x8000); | |
| 328 | + pci1760_cmd(dev, PCI1760_CMD_SET_CNT(i), 0x0000); | |
| 329 | + } | |
| 330 | + | |
| 331 | + /* reset counters to reset values */ | |
| 332 | + pci1760_cmd(dev, PCI1760_CMD_RST_CNT, 0xff); | |
| 333 | + | |
| 334 | + /* set counter count edges */ | |
| 335 | + pci1760_cmd(dev, PCI1760_CMD_SET_CNT_EDGE, 0); | |
| 336 | + | |
| 337 | + /* disable input filters */ | |
| 338 | + pci1760_cmd(dev, PCI1760_CMD_ENA_FILT, 0); | |
| 339 | + | |
| 340 | + /* disable pattern matching */ | |
| 341 | + pci1760_cmd(dev, PCI1760_CMD_ENA_PAT_MATCH, 0); | |
| 342 | + | |
| 343 | + /* set pattern match value */ | |
| 344 | + pci1760_cmd(dev, PCI1760_CMD_SET_PAT_MATCH, 0); | |
| 345 | +} | |
| 346 | + | |
| 347 | +static int pci1760_auto_attach(struct comedi_device *dev, | |
| 348 | + unsigned long context) | |
| 349 | +{ | |
| 350 | + struct pci_dev *pcidev = comedi_to_pci_dev(dev); | |
| 351 | + struct comedi_subdevice *s; | |
| 352 | + int ret; | |
| 353 | + | |
| 354 | + ret = comedi_pci_enable(dev); | |
| 355 | + if (ret) | |
| 356 | + return ret; | |
| 357 | + dev->iobase = pci_resource_start(pcidev, 0); | |
| 358 | + | |
| 359 | + pci1760_reset(dev); | |
| 360 | + | |
| 361 | + ret = comedi_alloc_subdevices(dev, 4); | |
| 362 | + if (ret) | |
| 363 | + return ret; | |
| 364 | + | |
| 365 | + /* Digital Input subdevice */ | |
| 366 | + s = &dev->subdevices[0]; | |
| 367 | + s->type = COMEDI_SUBD_DI; | |
| 368 | + s->subdev_flags = SDF_READABLE; | |
| 369 | + s->n_chan = 8; | |
| 370 | + s->maxdata = 1; | |
| 371 | + s->range_table = &range_digital; | |
| 372 | + s->insn_bits = pci1760_di_insn_bits; | |
| 373 | + | |
| 374 | + /* Digital Output subdevice */ | |
| 375 | + s = &dev->subdevices[1]; | |
| 376 | + s->type = COMEDI_SUBD_DO; | |
| 377 | + s->subdev_flags = SDF_WRITABLE; | |
| 378 | + s->n_chan = 8; | |
| 379 | + s->maxdata = 1; | |
| 380 | + s->range_table = &range_digital; | |
| 381 | + s->insn_bits = pci1760_do_insn_bits; | |
| 382 | + | |
| 383 | + /* get the current state of the outputs */ | |
| 384 | + ret = pci1760_cmd(dev, PCI1760_CMD_GET_DO, 0); | |
| 385 | + if (ret < 0) | |
| 386 | + return ret; | |
| 387 | + s->state = ret; | |
| 388 | + | |
| 389 | + /* PWM subdevice */ | |
| 390 | + s = &dev->subdevices[2]; | |
| 391 | + s->type = COMEDI_SUBD_PWM; | |
| 392 | + s->subdev_flags = SDF_PWM_COUNTER; | |
| 393 | + s->n_chan = 2; | |
| 394 | + s->insn_config = pci1760_pwm_insn_config; | |
| 395 | + | |
| 396 | + /* Counter subdevice */ | |
| 397 | + s = &dev->subdevices[3]; | |
| 398 | + s->type = COMEDI_SUBD_UNUSED; | |
| 399 | + | |
| 400 | + return 0; | |
| 401 | +} | |
| 402 | + | |
| 403 | +static struct comedi_driver pci1760_driver = { | |
| 404 | + .driver_name = "adv_pci1760", | |
| 405 | + .module = THIS_MODULE, | |
| 406 | + .auto_attach = pci1760_auto_attach, | |
| 407 | + .detach = comedi_pci_detach, | |
| 408 | +}; | |
| 409 | + | |
| 410 | +static int pci1760_pci_probe(struct pci_dev *dev, | |
| 411 | + const struct pci_device_id *id) | |
| 412 | +{ | |
| 413 | + return comedi_pci_auto_config(dev, &pci1760_driver, id->driver_data); | |
| 414 | +} | |
| 415 | + | |
| 416 | +static const struct pci_device_id pci1760_pci_table[] = { | |
| 417 | + { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) }, | |
| 418 | + { 0 } | |
| 419 | +}; | |
| 420 | +MODULE_DEVICE_TABLE(pci, pci1760_pci_table); | |
| 421 | + | |
| 422 | +static struct pci_driver pci1760_pci_driver = { | |
| 423 | + .name = "adv_pci1760", | |
| 424 | + .id_table = pci1760_pci_table, | |
| 425 | + .probe = pci1760_pci_probe, | |
| 426 | + .remove = comedi_pci_auto_unconfig, | |
| 427 | +}; | |
| 428 | +module_comedi_pci_driver(pci1760_driver, pci1760_pci_driver); | |
| 429 | + | |
| 430 | +MODULE_AUTHOR("Comedi http://www.comedi.org"); | |
| 431 | +MODULE_DESCRIPTION("Comedi driver for Advantech PCI-1760"); | |
| 432 | +MODULE_LICENSE("GPL"); | |
| @@ -4,30 +4,21 @@ · 3 unmodified lines | ||
| 4 | 4 | * Author: Michal Dobes <dobes@tesnet.cz> |
| 5 | 5 | * |
| 6 | 6 | * Hardware driver for Advantech PCI DIO cards. |
| 7 | −*/ | |
| 8 | −/* | |
| 9 | −Driver: adv_pci_dio | |
| 10 | −Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U, | |
| 11 | − PCI-1736UP, PCI-1739U, PCI-1750, PCI-1751, PCI-1752, | |
| 12 | − PCI-1753/E, PCI-1754, PCI-1756, PCI-1760, PCI-1762 | |
| 13 | −Author: Michal Dobes <dobes@tesnet.cz> | |
| 14 | −Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733, | |
| 15 | − PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750, | |
| 16 | − PCI-1751, PCI-1752, PCI-1753, | |
| 17 | − PCI-1753+PCI-1753E, PCI-1754, PCI-1756, | |
| 18 | − PCI-1760, PCI-1762 | |
| 19 | −Status: untested | |
| 20 | −Updated: Mon, 09 Jan 2012 12:40:46 +0000 | |
| 21 | − | |
| 22 | −This driver supports now only insn interface for DI/DO/DIO. | |
| 7 | + */ | |
| 23 | 8 | |
| 24 | −Configuration options: | |
| 25 | − [0] - PCI bus of device (optional) | |
| 26 | − [1] - PCI slot of device (optional) | |
| 27 | − If bus/slot is not specified, the first available PCI | |
| 28 | − device will be used. | |
| 29 | − | |
| 30 | −*/ | |
| 9 | +/* | |
| 10 | + * Driver: adv_pci_dio | |
| 11 | + * Description: Advantech Digital I/O Cards | |
| 12 | + * Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733, | |
| 13 | + * PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750, | |
| 14 | + * PCI-1751, PCI-1752, PCI-1753, PCI-1753+PCI-1753E, | |
| 15 | + * PCI-1754, PCI-1756, PCI-1762 | |
| 16 | + * Author: Michal Dobes <dobes@tesnet.cz> | |
| 17 | + * Updated: Mon, 09 Jan 2012 12:40:46 +0000 | |
| 18 | + * Status: untested | |
| 19 | + * | |
| 20 | + * Configuration Options: not applicable, uses PCI auto config | |
| 21 | + */ | |
| 31 | 22 | |
| 32 | 23 | #include <linux/module.h> |
| 33 | 24 | #include <linux/delay.h> |
| @@ -37,403 +28,199 @@ Configuration options: · 3 unmodified lines | ||
| 37 | 28 | #include "8255.h" |
| 38 | 29 | #include "comedi_8254.h" |
| 39 | 30 | |
| 40 | −/* hardware types of the cards */ | |
| 41 | −enum hw_cards_id { | |
| 42 | − TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736, | |
| 43 | − TYPE_PCI1739, | |
| 44 | − TYPE_PCI1750, | |
| 45 | − TYPE_PCI1751, | |
| 46 | − TYPE_PCI1752, | |
| 47 | − TYPE_PCI1753, TYPE_PCI1753E, | |
| 48 | − TYPE_PCI1754, TYPE_PCI1756, | |
| 49 | − TYPE_PCI1760, | |
| 50 | − TYPE_PCI1762 | |
| 51 | −}; | |
| 52 | − | |
| 53 | −/* which I/O instructions to use */ | |
| 54 | −enum hw_io_access { | |
| 55 | − IO_8b, IO_16b | |
| 56 | −}; | |
| 57 | − | |
| 58 | −#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */ | |
| 59 | −#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */ | |
| 60 | −#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per | |
| 61 | − * card */ | |
| 62 | − | |
| 63 | −#define PCIDIO_MAINREG 2 /* main I/O region for all Advantech cards? */ | |
| 64 | − | |
| 65 | −/* Register offset definitions */ | |
| 66 | −/* Advantech PCI-1730/3/4 */ | |
| 67 | −#define PCI1730_IDI 0 /* R: Isolated digital input 0-15 */ | |
| 68 | −#define PCI1730_IDO 0 /* W: Isolated digital output 0-15 */ | |
| 69 | −#define PCI1730_DI 2 /* R: Digital input 0-15 */ | |
| 70 | −#define PCI1730_DO 2 /* W: Digital output 0-15 */ | |
| 71 | −#define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */ | |
| 72 | −#define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */ | |
| 73 | −#define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for | |
| 74 | − * interrupts */ | |
| 75 | −#define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */ | |
| 76 | −#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */ | |
| 77 | −#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */ | |
| 78 | − | |
| 79 | −/* Advantech PCI-1735U */ | |
| 80 | −#define PCI1735_DI 0 /* R: Digital input 0-31 */ | |
| 81 | −#define PCI1735_DO 0 /* W: Digital output 0-31 */ | |
| 82 | −#define PCI1735_C8254 4 /* R/W: 8254 counter */ | |
| 83 | −#define PCI1735_BOARDID 8 /* R: Board I/D switch for 1735U */ | |
| 84 | − | |
| 85 | −/* Advantech PCI-1736UP */ | |
| 86 | −#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */ | |
| 87 | −#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */ | |
| 88 | −#define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */ | |
| 89 | −#define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for | |
| 90 | − * interrupts */ | |
| 91 | −#define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */ | |
| 92 | −#define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */ | |
| 93 | −#define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */ | |
| 31 | +/* | |
| 32 | + * Register offset definitions | |
| 33 | + */ | |
| 94 | 34 | |
| 95 | −/* Advantech PCI-1739U */ | |
| 96 | −#define PCI1739_DIO 0 /* R/W: begin of 8255 registers block */ | |
| 97 | −#define PCI1739_ICR 32 /* W: Interrupt control register */ | |
| 98 | −#define PCI1739_ISR 32 /* R: Interrupt status register */ | |
| 99 | −#define PCI1739_BOARDID 8 /* R: Board I/D switch for 1739U */ | |
| 35 | +/* PCI-1730, PCI-1733, PCI-1736 interrupt control registers */ | |
| 36 | +#define PCI173X_INT_EN_REG 0x08 /* R/W: enable/disable */ | |
| 37 | +#define PCI173X_INT_RF_REG 0x0c /* R/W: falling/rising edge */ | |
| 38 | +#define PCI173X_INT_CLR_REG 0x10 /* R/W: clear */ | |
| 100 | 39 | |
| 101 | −/* Advantech PCI-1750 */ | |
| 102 | −#define PCI1750_IDI 0 /* R: Isolated digital input 0-15 */ | |
| 103 | −#define PCI1750_IDO 0 /* W: Isolated digital output 0-15 */ | |
| 104 | −#define PCI1750_ICR 32 /* W: Interrupt control register */ | |
| 105 | −#define PCI1750_ISR 32 /* R: Interrupt status register */ | |
| 40 | +/* PCI-1739U, PCI-1750, PCI1751 interrupt control registers */ | |
| 41 | +#define PCI1750_INT_REG 0x20 /* R/W: status/control */ | |
| 106 | 42 | |
| 107 | −/* Advantech PCI-1751/3/3E */ | |
| 108 | −#define PCI1751_DIO 0 /* R/W: begin of 8255 registers block */ | |
| 109 | −#define PCI1751_CNT 24 /* R/W: begin of 8254 registers block */ | |
| 110 | −#define PCI1751_ICR 32 /* W: Interrupt control register */ | |
| 111 | −#define PCI1751_ISR 32 /* R: Interrupt status register */ | |
| 112 | −#define PCI1753_DIO 0 /* R/W: begin of 8255 registers block */ | |
| 113 | −#define PCI1753_ICR0 16 /* R/W: Interrupt control register group 0 */ | |
| 114 | −#define PCI1753_ICR1 17 /* R/W: Interrupt control register group 1 */ | |
| 115 | −#define PCI1753_ICR2 18 /* R/W: Interrupt control register group 2 */ | |
| 116 | −#define PCI1753_ICR3 19 /* R/W: Interrupt control register group 3 */ | |
| 117 | −#define PCI1753E_DIO 32 /* R/W: begin of 8255 registers block */ | |
| 118 | −#define PCI1753E_ICR0 48 /* R/W: Interrupt control register group 0 */ | |
| 119 | −#define PCI1753E_ICR1 49 /* R/W: Interrupt control register group 1 */ | |
| 120 | −#define PCI1753E_ICR2 50 /* R/W: Interrupt control register group 2 */ | |
| 121 | −#define PCI1753E_ICR3 51 /* R/W: Interrupt control register group 3 */ | |
| 43 | +/* PCI-1753, PCI-1753E interrupt control registers */ | |
| 44 | +#define PCI1753_INT_REG(x) (0x10 + (x)) /* R/W: control group 0 to 3 */ | |
| 45 | +#define PCI1753E_INT_REG(x) (0x30 + (x)) /* R/W: control group 0 to 3 */ | |
| 122 | 46 | |
| 123 | −/* Advantech PCI-1752/4/6 */ | |
| 124 | −#define PCI1752_IDO 0 /* R/W: Digital output 0-31 */ | |
| 125 | −#define PCI1752_IDO2 4 /* R/W: Digital output 32-63 */ | |
| 126 | −#define PCI1754_IDI 0 /* R: Digital input 0-31 */ | |
| 127 | −#define PCI1754_IDI2 4 /* R: Digital input 32-64 */ | |
| 128 | −#define PCI1756_IDI 0 /* R: Digital input 0-31 */ | |
| 129 | −#define PCI1756_IDO 4 /* R/W: Digital output 0-31 */ | |
| 130 | −#define PCI1754_6_ICR0 0x08 /* R/W: Interrupt control register group 0 */ | |
| 131 | −#define PCI1754_6_ICR1 0x0a /* R/W: Interrupt control register group 1 */ | |
| 132 | −#define PCI1754_ICR2 0x0c /* R/W: Interrupt control register group 2 */ | |
| 133 | −#define PCI1754_ICR3 0x0e /* R/W: Interrupt control register group 3 */ | |
| 134 | −#define PCI1752_6_CFC 0x12 /* R/W: set/read channel freeze function */ | |
| 135 | −#define PCI175x_BOARDID 0x10 /* R: Board I/D switch for 1752/4/6 */ | |
| 47 | +/* PCI-1754, PCI-1756 interrupt control registers */ | |
| 48 | +#define PCI1754_INT_REG(x) (0x08 + (x) * 2) /* R/W: control group 0 to 3 */ | |
| 136 | 49 | |
| 137 | −/* Advantech PCI-1762 registers */ | |
| 138 | −#define PCI1762_RO 0 /* R/W: Relays status/output */ | |
| 139 | −#define PCI1762_IDI 2 /* R: Isolated input status */ | |
| 140 | −#define PCI1762_BOARDID 4 /* R: Board I/D switch */ | |
| 141 | −#define PCI1762_ICR 6 /* W: Interrupt control register */ | |
| 142 | −#define PCI1762_ISR 6 /* R: Interrupt status register */ | |
| 50 | +/* PCI-1752, PCI-1756 special registers */ | |
| 51 | +#define PCI1752_CFC_REG 0x12 /* R/W: channel freeze function */ | |
| 143 | 52 | |
| 144 | −/* Advantech PCI-1760 registers */ | |
| 145 | −#define OMB0 0x0c /* W: Mailbox outgoing registers */ | |
| 146 | −#define OMB1 0x0d | |
| 147 | −#define OMB2 0x0e | |
| 148 | −#define OMB3 0x0f | |
| 149 | −#define IMB0 0x1c /* R: Mailbox incoming registers */ | |
| 150 | −#define IMB1 0x1d | |
| 151 | −#define IMB2 0x1e | |
| 152 | −#define IMB3 0x1f | |
| 153 | −#define INTCSR0 0x38 /* R/W: Interrupt control registers */ | |
| 154 | −#define INTCSR1 0x39 | |
| 155 | −#define INTCSR2 0x3a | |
| 156 | −#define INTCSR3 0x3b | |
| 53 | +/* PCI-1762 interrupt control registers */ | |
| 54 | +#define PCI1762_INT_REG 0x06 /* R/W: status/control */ | |
| 157 | 55 | |
| 158 | −/* PCI-1760 mailbox commands */ | |
| 159 | −#define CMD_ClearIMB2 0x00 /* Clear IMB2 status and return actual | |
| 160 | − * DI status in IMB3 */ | |
| 161 | −#define CMD_SetRelaysOutput 0x01 /* Set relay output from OMB0 */ | |
| 162 | −#define CMD_GetRelaysStatus 0x02 /* Get relay status to IMB0 */ | |
| 163 | −#define CMD_ReadCurrentStatus 0x07 /* Read the current status of the | |
| 164 | − * register in OMB0, result in IMB0 */ | |
| 165 | −#define CMD_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in | |
| 166 | − * IMB1.IMB0 */ | |
| 167 | −#define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in | |
| 168 | − * IMB1.IMB0 */ | |
| 169 | −#define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in | |
| 170 | − * OMB0 */ | |
| 171 | −#define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on | |
| 172 | − * bits in OMB0 */ | |
| 173 | −#define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on | |
| 174 | − * bits in OMB0 */ | |
| 175 | −#define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in | |
| 176 | − * OMB0 */ | |
| 177 | −#define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in | |
| 178 | − * OMB0 to its reset values */ | |
| 179 | −#define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow | |
| 180 | − * interrupts based on bits in OMB0 */ | |
| 181 | −#define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value | |
| 182 | − * interrupts based on bits in OMB0 */ | |
| 183 | −#define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0 | |
| 184 | − * - rising, =1 - falling) */ | |
| 185 | −#define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current | |
| 186 | − * value */ | |
| 187 | −#define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value | |
| 188 | − * 256*OMB1+OMB0 */ | |
| 189 | −#define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value | |
| 190 | − * 256*OMB1+OMB0 */ | |
| 191 | −#define CMD_SetIDI2CntResetValue 0x42 /* Set IDI2 Counter Reset Value | |
| 192 | − * 256*OMB1+OMB0 */ | |
| 193 | −#define CMD_SetIDI3CntResetValue 0x43 /* Set IDI3 Counter Reset Value | |
| 194 | − * 256*OMB1+OMB0 */ | |
| 195 | −#define CMD_SetIDI4CntResetValue 0x44 /* Set IDI4 Counter Reset Value | |
| 196 | − * 256*OMB1+OMB0 */ | |
| 197 | −#define CMD_SetIDI5CntResetValue 0x45 /* Set IDI5 Counter Reset Value | |
| 198 | − * 256*OMB1+OMB0 */ | |
| 199 | −#define CMD_SetIDI6CntResetValue 0x46 /* Set IDI6 Counter Reset Value | |
| 200 | − * 256*OMB1+OMB0 */ | |
| 201 | −#define CMD_SetIDI7CntResetValue 0x47 /* Set IDI7 Counter Reset Value | |
| 202 | − * 256*OMB1+OMB0 */ | |
| 203 | −#define CMD_SetIDI0CntMatchValue 0x48 /* Set IDI0 Counter Match Value | |
| 204 | − * 256*OMB1+OMB0 */ | |
| 205 | −#define CMD_SetIDI1CntMatchValue 0x49 /* Set IDI1 Counter Match Value | |
| 206 | − * 256*OMB1+OMB0 */ | |
| 207 | −#define CMD_SetIDI2CntMatchValue 0x4a /* Set IDI2 Counter Match Value | |
| 208 | − * 256*OMB1+OMB0 */ | |
| 209 | −#define CMD_SetIDI3CntMatchValue 0x4b /* Set IDI3 Counter Match Value | |
| 210 | − * 256*OMB1+OMB0 */ | |
| 211 | −#define CMD_SetIDI4CntMatchValue 0x4c /* Set IDI4 Counter Match Value | |
| 212 | − * 256*OMB1+OMB0 */ | |
| 213 | −#define CMD_SetIDI5CntMatchValue 0x4d /* Set IDI5 Counter Match Value | |
| 214 | − * 256*OMB1+OMB0 */ | |
| 215 | −#define CMD_SetIDI6CntMatchValue 0x4e /* Set IDI6 Counter Match Value | |
| 216 | − * 256*OMB1+OMB0 */ | |
| 217 | −#define CMD_SetIDI7CntMatchValue 0x4f /* Set IDI7 Counter Match Value | |
| 218 | − * 256*OMB1+OMB0 */ | |
| 56 | +/* maximum number of subdevice descriptions in the boardinfo */ | |
| 57 | +#define PCI_DIO_MAX_DI_SUBDEVS 2 /* 2 x 8/16/32 input channels max */ | |
| 58 | +#define PCI_DIO_MAX_DO_SUBDEVS 2 /* 2 x 8/16/32 output channels max */ | |
| 59 | +#define PCI_DIO_MAX_DIO_SUBDEVG 2 /* 2 x any number of 8255 devices max */ | |
| 219 | 60 | |
| 220 | −#define OMBCMD_RETRY 0x03 /* 3 times try request before error */ | |
| 61 | +enum pci_dio_boardid { | |
| 62 | + TYPE_PCI1730, | |
| 63 | + TYPE_PCI1733, | |
| 64 | + TYPE_PCI1734, | |
| 65 | + TYPE_PCI1735, | |
| 66 | + TYPE_PCI1736, | |
| 67 | + TYPE_PCI1739, | |
| 68 | + TYPE_PCI1750, | |
| 69 | + TYPE_PCI1751, | |
| 70 | + TYPE_PCI1752, | |
| 71 | + TYPE_PCI1753, | |
| 72 | + TYPE_PCI1753E, | |
| 73 | + TYPE_PCI1754, | |
| 74 | + TYPE_PCI1756, | |
| 75 | + TYPE_PCI1762 | |
| 76 | +}; | |
| 221 | 77 | |
| 222 | 78 | struct diosubd_data { |
| 223 | − int chans; /* num of chans */ | |
| 224 | − int addr; /* PCI address ofset */ | |
| 225 | − int regs; /* number of registers to read or 8255 | |
| 226 | − subdevices */ | |
| 227 | − unsigned int specflags; /* addon subdevice flags */ | |
| 79 | + int chans; /* num of chans or 8255 devices */ | |
| 80 | + unsigned long addr; /* PCI address ofset */ | |
| 228 | 81 | }; |
| 229 | 82 | |
| 230 | 83 | struct dio_boardtype { |
| 231 | 84 | const char *name; /* board name */ |
| 232 | − int main_pci_region; /* main I/O PCI region */ | |
| 233 | − enum hw_cards_id cardtype; | |
| 234 | 85 | int nsubdevs; |
| 235 | − struct diosubd_data sdi[MAX_DI_SUBDEVS]; /* DI chans */ | |
| 236 | − struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */ | |
| 237 | − struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */ | |
| 238 | − struct diosubd_data boardid; /* card supports board ID switch */ | |
| 86 | + struct diosubd_data sdi[PCI_DIO_MAX_DI_SUBDEVS]; | |
| 87 | + struct diosubd_data sdo[PCI_DIO_MAX_DO_SUBDEVS]; | |
| 88 | + struct diosubd_data sdio[PCI_DIO_MAX_DIO_SUBDEVG]; | |
| 89 | + unsigned long id_reg; | |
| 239 | 90 | unsigned long timer_regbase; |
| 240 | − enum hw_io_access io_access; | |
| 91 | + unsigned int is_16bit:1; | |
| 241 | 92 | }; |
| 242 | 93 | |
| 243 | 94 | static const struct dio_boardtype boardtypes[] = { |
| 244 | 95 | [TYPE_PCI1730] = { |
| 245 | 96 | .name = "pci1730", |
| 246 | − .main_pci_region = PCIDIO_MAINREG, | |
| 247 | − .cardtype = TYPE_PCI1730, | |
| 248 | 97 | .nsubdevs = 5, |
| 249 | − .sdi[0] = { 16, PCI1730_DI, 2, 0, }, | |
| 250 | − .sdi[1] = { 16, PCI1730_IDI, 2, 0, }, | |
| 251 | − .sdo[0] = { 16, PCI1730_DO, 2, 0, }, | |
| 252 | − .sdo[1] = { 16, PCI1730_IDO, 2, 0, }, | |
| 253 | − .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, | |
| 254 | − .io_access = IO_8b, | |
| 98 | + .sdi[0] = { 16, 0x02, }, /* DI 0-15 */ | |
| 99 | + .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */ | |
| 100 | + .sdo[0] = { 16, 0x02, }, /* DO 0-15 */ | |
| 101 | + .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ | |
| 102 | + .id_reg = 0x04, | |
| 255 | 103 | }, |
| 256 | 104 | [TYPE_PCI1733] = { |
| 257 | 105 | .name = "pci1733", |
| 258 | − .main_pci_region = PCIDIO_MAINREG, | |
| 259 | − .cardtype = TYPE_PCI1733, | |
| 260 | 106 | .nsubdevs = 2, |
| 261 | − .sdi[1] = { 32, PCI1733_IDI, 4, 0, }, | |
| 262 | − .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, | |
| 263 | − .io_access = IO_8b, | |
| 107 | + .sdi[1] = { 32, 0x00, }, /* ISO DI 0-31 */ | |
| 108 | + .id_reg = 0x04, | |
| 264 | 109 | }, |
| 265 | 110 | [TYPE_PCI1734] = { |
| 266 | 111 | .name = "pci1734", |
| 267 | − .main_pci_region = PCIDIO_MAINREG, | |
| 268 | − .cardtype = TYPE_PCI1734, | |
| 269 | 112 | .nsubdevs = 2, |
| 270 | − .sdo[1] = { 32, PCI1734_IDO, 4, 0, }, | |
| 271 | − .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, | |
| 272 | − .io_access = IO_8b, | |
| 113 | + .sdo[1] = { 32, 0x00, }, /* ISO DO 0-31 */ | |
| 114 | + .id_reg = 0x04, | |
| 273 | 115 | }, |
| 274 | 116 | [TYPE_PCI1735] = { |
| 275 | 117 | .name = "pci1735", |
| 276 | − .main_pci_region = PCIDIO_MAINREG, | |
| 277 | − .cardtype = TYPE_PCI1735, | |
| 278 | 118 | .nsubdevs = 4, |
| 279 | − .sdi[0] = { 32, PCI1735_DI, 4, 0, }, | |
| 280 | − .sdo[0] = { 32, PCI1735_DO, 4, 0, }, | |
| 281 | − .boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, }, | |
| 282 | − .timer_regbase = PCI1735_C8254, | |
| 283 | − .io_access = IO_8b, | |
| 119 | + .sdi[0] = { 32, 0x00, }, /* DI 0-31 */ | |
| 120 | + .sdo[0] = { 32, 0x00, }, /* DO 0-31 */ | |
| 121 | + .id_reg = 0x08, | |
| 122 | + .timer_regbase = 0x04, | |
| 284 | 123 | }, |
| 285 | 124 | [TYPE_PCI1736] = { |
| 286 | 125 | .name = "pci1736", |
| 287 | − .main_pci_region = PCI1736_MAINREG, | |
| 288 | − .cardtype = TYPE_PCI1736, | |
| 289 | 126 | .nsubdevs = 3, |
| 290 | − .sdi[1] = { 16, PCI1736_IDI, 2, 0, }, | |
| 291 | − .sdo[1] = { 16, PCI1736_IDO, 2, 0, }, | |
| 292 | − .boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, }, | |
| 293 | − .io_access = IO_8b, | |
| 127 | + .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */ | |
| 128 | + .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ | |
| 129 | + .id_reg = 0x04, | |
| 294 | 130 | }, |
| 295 | 131 | [TYPE_PCI1739] = { |
| 296 | 132 | .name = "pci1739", |
| 297 | − .main_pci_region = PCIDIO_MAINREG, | |
| 298 | − .cardtype = TYPE_PCI1739, | |
| 299 | − .nsubdevs = 2, | |
| 300 | − .sdio[0] = { 48, PCI1739_DIO, 2, 0, }, | |
| 301 | − .io_access = IO_8b, | |
| 133 | + .nsubdevs = 3, | |
| 134 | + .sdio[0] = { 2, 0x00, }, /* 8255 DIO */ | |
| 135 | + .id_reg = 0x08, | |
| 302 | 136 | }, |
| 303 | 137 | [TYPE_PCI1750] = { |
| 304 | 138 | .name = "pci1750", |
| 305 | − .main_pci_region = PCIDIO_MAINREG, | |
| 306 | − .cardtype = TYPE_PCI1750, | |
| 307 | 139 | .nsubdevs = 2, |
| 308 | − .sdi[1] = { 16, PCI1750_IDI, 2, 0, }, | |
| 309 | − .sdo[1] = { 16, PCI1750_IDO, 2, 0, }, | |
| 310 | − .io_access = IO_8b, | |
| 140 | + .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */ | |
| 141 | + .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ | |
| 311 | 142 | }, |
| 312 | 143 | [TYPE_PCI1751] = { |
| 313 | 144 | .name = "pci1751", |
| 314 | − .main_pci_region = PCIDIO_MAINREG, | |
| 315 | − .cardtype = TYPE_PCI1751, | |
| 316 | 145 | .nsubdevs = 3, |
| 317 | − .sdio[0] = { 48, PCI1751_DIO, 2, 0, }, | |
| 318 | − .timer_regbase = PCI1751_CNT, | |
| 319 | − .io_access = IO_8b, | |
| 146 | + .sdio[0] = { 2, 0x00, }, /* 8255 DIO */ | |
| 147 | + .timer_regbase = 0x18, | |
| 320 | 148 | }, |
| 321 | 149 | [TYPE_PCI1752] = { |
| 322 | 150 | .name = "pci1752", |
| 323 | − .main_pci_region = PCIDIO_MAINREG, | |
| 324 | − .cardtype = TYPE_PCI1752, | |
| 325 | 151 | .nsubdevs = 3, |
| 326 | − .sdo[0] = { 32, PCI1752_IDO, 2, 0, }, | |
| 327 | − .sdo[1] = { 32, PCI1752_IDO2, 2, 0, }, | |
| 328 | − .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, | |
| 329 | − .io_access = IO_16b, | |
| 152 | + .sdo[0] = { 32, 0x00, }, /* DO 0-31 */ | |
| 153 | + .sdo[1] = { 32, 0x04, }, /* DO 32-63 */ | |
| 154 | + .id_reg = 0x10, | |
| 155 | + .is_16bit = 1, | |
| 330 | 156 | }, |
| 331 | 157 | [TYPE_PCI1753] = { |
| 332 | 158 | .name = "pci1753", |
| 333 | − .main_pci_region = PCIDIO_MAINREG, | |
| 334 | − .cardtype = TYPE_PCI1753, | |
| 335 | 159 | .nsubdevs = 4, |
| 336 | − .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, | |
| 337 | − .io_access = IO_8b, | |
| 160 | + .sdio[0] = { 4, 0x00, }, /* 8255 DIO */ | |
| 338 | 161 | }, |
| 339 | 162 | [TYPE_PCI1753E] = { |
| 340 | 163 | .name = "pci1753e", |
| 341 | − .main_pci_region = PCIDIO_MAINREG, | |
| 342 | − .cardtype = TYPE_PCI1753E, | |
| 343 | 164 | .nsubdevs = 8, |
| 344 | − .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, | |
| 345 | − .sdio[1] = { 96, PCI1753E_DIO, 4, 0, }, | |
| 346 | − .io_access = IO_8b, | |
| 165 | + .sdio[0] = { 4, 0x00, }, /* 8255 DIO */ | |
| 166 | + .sdio[1] = { 4, 0x20, }, /* 8255 DIO */ | |
| 347 | 167 | }, |
| 348 | 168 | [TYPE_PCI1754] = { |
| 349 | 169 | .name = "pci1754", |
| 350 | − .main_pci_region = PCIDIO_MAINREG, | |
| 351 | − .cardtype = TYPE_PCI1754, | |
| 352 | 170 | .nsubdevs = 3, |
| 353 | − .sdi[0] = { 32, PCI1754_IDI, 2, 0, }, | |
| 354 | − .sdi[1] = { 32, PCI1754_IDI2, 2, 0, }, | |
| 355 | − .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, | |
| 356 | − .io_access = IO_16b, | |
| 171 | + .sdi[0] = { 32, 0x00, }, /* DI 0-31 */ | |
| 172 | + .sdi[1] = { 32, 0x04, }, /* DI 32-63 */ | |
| 173 | + .id_reg = 0x10, | |
| 174 | + .is_16bit = 1, | |
| 357 | 175 | }, |
| 358 | 176 | [TYPE_PCI1756] = { |
| 359 | 177 | .name = "pci1756", |
| 360 | − .main_pci_region = PCIDIO_MAINREG, | |
| 361 | − .cardtype = TYPE_PCI1756, | |
| 362 | 178 | .nsubdevs = 3, |
| 363 | − .sdi[1] = { 32, PCI1756_IDI, 2, 0, }, | |
| 364 | − .sdo[1] = { 32, PCI1756_IDO, 2, 0, }, | |
| 365 | − .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, | |
| 366 | − .io_access = IO_16b, | |
| 367 | − }, | |
| 368 | − [TYPE_PCI1760] = { | |
| 369 | − /* This card has its own 'attach' */ | |
| 370 | − .name = "pci1760", | |
| 371 | − .main_pci_region = 0, | |
| 372 | − .cardtype = TYPE_PCI1760, | |
| 373 | − .nsubdevs = 4, | |
| 374 | − .io_access = IO_8b, | |
| 179 | + .sdi[1] = { 32, 0x00, }, /* DI 0-31 */ | |
| 180 | + .sdo[1] = { 32, 0x04, }, /* DO 0-31 */ | |
| 181 | + .id_reg = 0x10, | |
| 182 | + .is_16bit = 1, | |
| 375 | 183 | }, |
| 376 | 184 | [TYPE_PCI1762] = { |
| 377 | 185 | .name = "pci1762", |
| 378 | − .main_pci_region = PCIDIO_MAINREG, | |
| 379 | − .cardtype = TYPE_PCI1762, | |
| 380 | 186 | .nsubdevs = 3, |
| 381 | − .sdi[1] = { 16, PCI1762_IDI, 1, 0, }, | |
| 382 | − .sdo[1] = { 16, PCI1762_RO, 1, 0, }, | |
| 383 | − .boardid = { 4, PCI1762_BOARDID, 1, SDF_INTERNAL, }, | |
| 384 | − .io_access = IO_16b, | |
| 187 | + .sdi[1] = { 16, 0x02, }, /* ISO DI 0-15 */ | |
| 188 | + .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ | |
| 189 | + .id_reg = 0x04, | |
| 190 | + .is_16bit = 1, | |
| 385 | 191 | }, |
| 386 | 192 | }; |
| 387 | 193 | |
| 388 | −struct pci_dio_private { | |
| 389 | − char GlobalIrqEnabled; /* 1= any IRQ source is enabled */ | |
| 390 | − /* PCI-1760 specific data */ | |
| 391 | − unsigned char IDICntEnable; /* counter's counting enable status */ | |
| 392 | − unsigned char IDICntOverEnable; /* counter's overflow interrupts enable | |
| 393 | − * status */ | |
| 394 | − unsigned char IDICntMatchEnable; /* counter's match interrupts | |
| 395 | − * enable status */ | |
| 396 | − unsigned char IDICntEdge; /* counter's count edge value | |
| 397 | − * (bit=0 - rising, =1 - falling) */ | |
| 398 | − unsigned short CntResValue[8]; /* counters' reset value */ | |
| 399 | − unsigned short CntMatchValue[8]; /* counters' match interrupt value */ | |
| 400 | − unsigned char IDIFiltersEn; /* IDI's digital filters enable status */ | |
| 401 | − unsigned char IDIPatMatchEn; /* IDI's pattern match enable status */ | |
| 402 | − unsigned char IDIPatMatchValue; /* IDI's pattern match value */ | |
| 403 | − unsigned short IDIFiltrLow[8]; /* IDI's filter value low signal */ | |
| 404 | − unsigned short IDIFiltrHigh[8]; /* IDI's filter value high signal */ | |
| 405 | −}; | |
| 406 | − | |
| 407 | −/* | |
| 408 | −============================================================================== | |
| 409 | −*/ | |
| 410 | 194 | static int pci_dio_insn_bits_di_b(struct comedi_device *dev, |
| 411 | 195 | struct comedi_subdevice *s, |
| 412 | − struct comedi_insn *insn, unsigned int *data) | |
| 196 | + struct comedi_insn *insn, | |
| 197 | + unsigned int *data) | |
| 413 | 198 | { |
| 414 | − const struct diosubd_data *d = (const struct diosubd_data *)s->private; | |
| 415 | − int i; | |
| 199 | + unsigned long reg = (unsigned long)s->private; | |
| 200 | + unsigned long iobase = dev->iobase + reg; | |
| 416 | 201 | |
| 417 | − data[1] = 0; | |
| 418 | − for (i = 0; i < d->regs; i++) | |
| 419 | − data[1] |= inb(dev->iobase + d->addr + i) << (8 * i); | |
| 202 | + data[1] = inb(iobase); | |
| 203 | + if (s->n_chan > 8) | |
| 204 | + data[1] |= (inb(iobase + 1) << 8); | |
| 205 | + if (s->n_chan > 16) | |
| 206 | + data[1] |= (inb(iobase + 2) << 16); | |
| 207 | + if (s->n_chan > 24) | |
| 208 | + data[1] |= (inb(iobase + 3) << 24); | |
| 420 | 209 | |
| 421 | 210 | return insn->n; |
| 422 | 211 | } |
| 423 | 212 | |
| 424 | −/* | |
| 425 | −============================================================================== | |
| 426 | −*/ | |
| 427 | 213 | static int pci_dio_insn_bits_di_w(struct comedi_device *dev, |
| 428 | 214 | struct comedi_subdevice *s, |
| 429 | − struct comedi_insn *insn, unsigned int *data) | |
| 215 | + struct comedi_insn *insn, | |
| 216 | + unsigned int *data) | |
| 430 | 217 | { |
| 431 | − const struct diosubd_data *d = (const struct diosubd_data *)s->private; | |
| 432 | − int i; | |
| 218 | + unsigned long reg = (unsigned long)s->private; | |
| 219 | + unsigned long iobase = dev->iobase + reg; | |
| 433 | 220 | |
| 434 | − data[1] = 0; | |
| 435 | − for (i = 0; i < d->regs; i++) | |
| 436 | − data[1] |= inw(dev->iobase + d->addr + 2 * i) << (16 * i); | |
| 221 | + data[1] = inw(iobase); | |
| 222 | + if (s->n_chan > 16) | |
| 223 | + data[1] |= (inw(iobase + 2) << 16); | |
| 437 | 224 | |
| 438 | 225 | return insn->n; |
| 439 | 226 | } |
| @@ -443,13 +230,17 @@ static int pci_dio_insn_bits_do_b(struct comedi_device *dev, · 3 unmodified lines | ||
| 443 | 230 | struct comedi_insn *insn, |
| 444 | 231 | unsigned int *data) |
| 445 | 232 | { |
| 446 | − const struct diosubd_data *d = (const struct diosubd_data *)s->private; | |
| 447 | − int i; | |
| 233 | + unsigned long reg = (unsigned long)s->private; | |
| 234 | + unsigned long iobase = dev->iobase + reg; | |
| 448 | 235 | |
| 449 | 236 | if (comedi_dio_update_state(s, data)) { |
| 450 | − for (i = 0; i < d->regs; i++) | |
| 451 | − outb((s->state >> (8 * i)) & 0xff, | |
| 452 | − dev->iobase + d->addr + i); | |
| 237 | + outb(s->state & 0xff, iobase); | |
| 238 | + if (s->n_chan > 8) | |
| 239 | + outb((s->state >> 8) & 0xff, iobase + 1); | |
| 240 | + if (s->n_chan > 16) | |
| 241 | + outb((s->state >> 16) & 0xff, iobase + 2); | |
| 242 | + if (s->n_chan > 24) | |
| 243 | + outb((s->state >> 24) & 0xff, iobase + 3); | |
| 453 | 244 | } |
| 454 | 245 | |
| 455 | 246 | data[1] = s->state; |
| @@ -462,13 +253,13 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev, · 6 unmodified lines | ||
| 462 | 253 | struct comedi_insn *insn, |
| 463 | 254 | unsigned int *data) |
| 464 | 255 | { |
| 465 | − const struct diosubd_data *d = (const struct diosubd_data *)s->private; | |
| 466 | − int i; | |
| 256 | + unsigned long reg = (unsigned long)s->private; | |
| 257 | + unsigned long iobase = dev->iobase + reg; | |
| 467 | 258 | |
| 468 | 259 | if (comedi_dio_update_state(s, data)) { |
| 469 | − for (i = 0; i < d->regs; i++) | |
| 470 | − outw((s->state >> (16 * i)) & 0xffff, | |
| 471 | − dev->iobase + d->addr + 2 * i); | |
| 260 | + outw(s->state & 0xffff, iobase); | |
| 261 | + if (s->n_chan > 16) | |
| 262 | + outw((s->state >> 16) & 0xffff, iobase + 2); | |
| 472 | 263 | } |
| 473 | 264 | |
| 474 | 265 | data[1] = s->state; |
| @@ -476,510 +267,64 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev, · 1 unmodified line | ||
| 476 | 267 | return insn->n; |
| 477 | 268 | } |
| 478 | 269 | |
| 479 | −/* | |
| 480 | −============================================================================== | |
| 481 | −*/ | |
| 482 | −static int pci1760_unchecked_mbxrequest(struct comedi_device *dev, | |
| 483 | − unsigned char *omb, unsigned char *imb, | |
| 484 | − int repeats) | |
| 485 | −{ | |
| 486 | − int cnt, tout, ok = 0; | |
| 487 | − | |
| 488 | − for (cnt = 0; cnt < repeats; cnt++) { | |
| 489 | − outb(omb[0], dev->iobase + OMB0); | |
| 490 | − outb(omb[1], dev->iobase + OMB1); | |
| 491 | − outb(omb[2], dev->iobase + OMB2); | |
| 492 | − outb(omb[3], dev->iobase + OMB3); | |
| 493 | − for (tout = 0; tout < 251; tout++) { | |
| 494 | − imb[2] = inb(dev->iobase + IMB2); | |
| 495 | − if (imb[2] == omb[2]) { | |
| 496 | − imb[0] = inb(dev->iobase + IMB0); | |
| 497 | − imb[1] = inb(dev->iobase + IMB1); | |
| 498 | − imb[3] = inb(dev->iobase + IMB3); | |
| 499 | − ok = 1; | |
| 500 | − break; | |
| 501 | − } | |
| 502 | − udelay(1); | |
| 503 | − } | |
| 504 | − if (ok) | |
| 505 | − return 0; | |
| 506 | − } | |
| 507 | − | |
| 508 | − dev_err(dev->class_dev, "PCI-1760 mailbox request timeout!\n"); | |
| 509 | − return -ETIME; | |
| 510 | −} | |
| 511 | − | |
| 512 | −static int pci1760_clear_imb2(struct comedi_device *dev) | |
| 513 | −{ | |
| 514 | − unsigned char omb[4] = { 0x0, 0x0, CMD_ClearIMB2, 0x0 }; | |
| 515 | − unsigned char imb[4]; | |
| 516 | − /* check if imb2 is already clear */ | |
| 517 | − if (inb(dev->iobase + IMB2) == CMD_ClearIMB2) | |
| 518 | − return 0; | |
| 519 | − return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY); | |
| 520 | −} | |
| 521 | − | |
| 522 | −static int pci1760_mbxrequest(struct comedi_device *dev, | |
| 523 | − unsigned char *omb, unsigned char *imb) | |
| 524 | −{ | |
| 525 | − if (omb[2] == CMD_ClearIMB2) { | |
| 526 | − dev_err(dev->class_dev, | |
| 527 | − "bug! this function should not be used for CMD_ClearIMB2 command\n"); | |
| 528 | − return -EINVAL; | |
| 529 | − } | |
| 530 | − if (inb(dev->iobase + IMB2) == omb[2]) { | |
| 531 | − int retval; | |
| 532 | − | |
| 533 | − retval = pci1760_clear_imb2(dev); | |
| 534 | − if (retval < 0) | |
| 535 | − return retval; | |
| 536 | − } | |
| 537 | − return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY); | |
| 538 | −} | |
| 539 | − | |
| 540 | −/* | |
| 541 | −============================================================================== | |
| 542 | −*/ | |
| 543 | −static int pci1760_insn_bits_di(struct comedi_device *dev, | |
| 544 | − struct comedi_subdevice *s, | |
| 545 | − struct comedi_insn *insn, unsigned int *data) | |
| 270 | +static int pci_dio_reset(struct comedi_device *dev, unsigned long cardtype) | |
| 546 | 271 | { |
| 547 | − data[1] = inb(dev->iobase + IMB3); | |
| 272 | + /* disable channel freeze function on the PCI-1752/1756 boards */ | |
| 273 | + if (cardtype == TYPE_PCI1752 || cardtype == TYPE_PCI1756) | |
| 274 | + outw(0, dev->iobase + PCI1752_CFC_REG); | |
| 548 | 275 | |
| 549 | − return insn->n; | |
| 550 | −} | |
| 551 | − | |
| 552 | −static int pci1760_insn_bits_do(struct comedi_device *dev, | |
| 553 | − struct comedi_subdevice *s, | |
| 554 | − struct comedi_insn *insn, | |
| 555 | − unsigned int *data) | |
| 556 | −{ | |
| 557 | − int ret; | |
| 558 | − unsigned char omb[4] = { | |
| 559 | − 0x00, | |
| 560 | − 0x00, | |
| 561 | − CMD_SetRelaysOutput, | |
| 562 | − 0x00 | |
| 563 | − }; | |
| 564 | − unsigned char imb[4]; | |
| 565 | − | |
| 566 | − if (comedi_dio_update_state(s, data)) { | |
| 567 | − omb[0] = s->state; | |
| 568 | − ret = pci1760_mbxrequest(dev, omb, imb); | |
| 569 | − if (!ret) | |
| 570 | − return ret; | |
| 571 | − } | |
| 572 | − | |
| 573 | − data[1] = s->state; | |
| 574 | − | |
| 575 | − return insn->n; | |
| 576 | −} | |
| 577 | − | |
| 578 | −/* | |
| 579 | −============================================================================== | |
| 580 | −*/ | |
| 581 | −static int pci1760_insn_cnt_read(struct comedi_device *dev, | |
| 582 | − struct comedi_subdevice *s, | |
| 583 | − struct comedi_insn *insn, unsigned int *data) | |
| 584 | −{ | |
| 585 | − int ret, n; | |
| 586 | − unsigned char omb[4] = { | |
| 587 | − CR_CHAN(insn->chanspec) & 0x07, | |
| 588 | − 0x00, | |
| 589 | − CMD_GetIDICntCurValue, | |
| 590 | − 0x00 | |
| 591 | − }; | |
| 592 | − unsigned char imb[4]; | |
| 593 | − | |
| 594 | − for (n = 0; n < insn->n; n++) { | |
| 595 | − ret = pci1760_mbxrequest(dev, omb, imb); | |
| 596 | − if (!ret) | |
| 597 | − return ret; | |
| 598 | − data[n] = (imb[1] << 8) + imb[0]; | |
| 599 | − } | |
| 600 | − | |
| 601 | − return n; | |
| 602 | −} | |
| 603 | − | |
| 604 | −/* | |
| 605 | −============================================================================== | |
| 606 | −*/ | |
| 607 | −static int pci1760_insn_cnt_write(struct comedi_device *dev, | |
| 608 | − struct comedi_subdevice *s, | |
| 609 | − struct comedi_insn *insn, unsigned int *data) | |
| 610 | −{ | |
| 611 | − struct pci_dio_private *devpriv = dev->private; | |
| 612 | − int ret; | |
| 613 | − unsigned char chan = CR_CHAN(insn->chanspec) & 0x07; | |
| 614 | − unsigned char bitmask = 1 << chan; | |
| 615 | − unsigned char omb[4] = { | |
| 616 | − data[0] & 0xff, | |
| 617 | − (data[0] >> 8) & 0xff, | |
| 618 | − CMD_SetIDI0CntResetValue + chan, | |
| 619 | − 0x00 | |
| 620 | − }; | |
| 621 | − unsigned char imb[4]; | |
| 622 | − | |
| 623 | − /* Set reset value if different */ | |
| 624 | − if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) { | |
| 625 | − ret = pci1760_mbxrequest(dev, omb, imb); | |
| 626 | − if (!ret) | |
| 627 | − return ret; | |
| 628 | − devpriv->CntResValue[chan] = data[0] & 0xffff; | |
| 629 | − } | |
| 630 | − | |
| 631 | − omb[0] = bitmask; /* reset counter to it reset value */ | |
| 632 | − omb[2] = CMD_ResetIDICounters; | |
| 633 | − ret = pci1760_mbxrequest(dev, omb, imb); | |
| 634 | − if (!ret) | |
| 635 | − return ret; | |
| 636 | − | |
| 637 | − /* start counter if it don't run */ | |
| 638 | − if (!(bitmask & devpriv->IDICntEnable)) { | |
| 639 | − omb[0] = bitmask; | |
| 640 | − omb[2] = CMD_EnableIDICounters; | |
| 641 | − ret = pci1760_mbxrequest(dev, omb, imb); | |
| 642 | − if (!ret) | |
| 643 | − return ret; | |
| 644 | − devpriv->IDICntEnable |= bitmask; | |
| 645 | − } | |
| 646 | − return 1; | |
| 647 | −} | |
| 648 | − | |
| 649 | −/* | |
| 650 | −============================================================================== | |
| 651 | −*/ | |
| 652 | −static int pci1760_reset(struct comedi_device *dev) | |
| 653 | −{ | |
| 654 | − struct pci_dio_private *devpriv = dev->private; | |
| 655 | − int i; | |
| 656 | − unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 }; | |
| 657 | − unsigned char imb[4]; | |
| 658 | − | |
| 659 | − outb(0, dev->iobase + INTCSR0); /* disable IRQ */ | |
| 660 | − outb(0, dev->iobase + INTCSR1); | |
| 661 | − outb(0, dev->iobase + INTCSR2); | |
| 662 | − outb(0, dev->iobase + INTCSR3); | |
| 663 | − devpriv->GlobalIrqEnabled = 0; | |
| 664 | − | |
| 665 | − omb[0] = 0x00; | |
| 666 | − omb[2] = CMD_SetRelaysOutput; /* reset relay outputs */ | |
| 667 | − pci1760_mbxrequest(dev, omb, imb); | |
| 668 | − | |
| 669 | − omb[0] = 0x00; | |
| 670 | − omb[2] = CMD_EnableIDICounters; /* disable IDI up counters */ | |
| 671 | − pci1760_mbxrequest(dev, omb, imb); | |
| 672 | − devpriv->IDICntEnable = 0; | |
| 673 | − | |
| 674 | − omb[0] = 0x00; | |
| 675 | − omb[2] = CMD_OverflowIDICounters; /* disable counters overflow | |
| 676 | − * interrupts */ | |
| 677 | − pci1760_mbxrequest(dev, omb, imb); | |
| 678 | − devpriv->IDICntOverEnable = 0; | |
| 679 | − | |
| 680 | − omb[0] = 0x00; | |
| 681 | − omb[2] = CMD_MatchIntIDICounters; /* disable counters match value | |
| 682 | − * interrupts */ | |
| 683 | − pci1760_mbxrequest(dev, omb, imb); | |
| 684 | − devpriv->IDICntMatchEnable = 0; | |
| 685 | − | |
| 686 | − omb[0] = 0x00; | |
| 687 | − omb[1] = 0x80; | |
| 688 | − for (i = 0; i < 8; i++) { /* set IDI up counters match value */ | |
| 689 | − omb[2] = CMD_SetIDI0CntMatchValue + i; | |
| 690 | − pci1760_mbxrequest(dev, omb, imb); | |
| 691 | − devpriv->CntMatchValue[i] = 0x8000; | |
| 692 | − } | |
| 693 | − | |
| 694 | − omb[0] = 0x00; | |
| 695 | − omb[1] = 0x00; | |
| 696 | − for (i = 0; i < 8; i++) { /* set IDI up counters reset value */ | |
| 697 | − omb[2] = CMD_SetIDI0CntResetValue + i; | |
| 698 | − pci1760_mbxrequest(dev, omb, imb); | |
| 699 | − devpriv->CntResValue[i] = 0x0000; | |
| 700 | − } | |
| 701 | − | |
| 702 | − omb[0] = 0xff; | |
| 703 | − omb[2] = CMD_ResetIDICounters; /* reset IDI up counters to reset | |
| 704 | − * values */ | |
| 705 | − pci1760_mbxrequest(dev, omb, imb); | |
| 706 | − | |
| 707 | − omb[0] = 0x00; | |
| 708 | − omb[2] = CMD_EdgeIDICounters; /* set IDI up counters count edge */ | |
| 709 | − pci1760_mbxrequest(dev, omb, imb); | |
| 710 | − devpriv->IDICntEdge = 0x00; | |
| 711 | − | |
| 712 | − omb[0] = 0x00; | |
| 713 | − omb[2] = CMD_EnableIDIFilters; /* disable all digital in filters */ | |
| 714 | − pci1760_mbxrequest(dev, omb, imb); | |
| 715 | − devpriv->IDIFiltersEn = 0x00; | |
| 716 | − | |
| 717 | − omb[0] = 0x00; | |
| 718 | − omb[2] = CMD_EnableIDIPatternMatch; /* disable pattern matching */ | |
| 719 | − pci1760_mbxrequest(dev, omb, imb); | |
| 720 | − devpriv->IDIPatMatchEn = 0x00; | |
| 721 | − | |
| 722 | − omb[0] = 0x00; | |
| 723 | − omb[2] = CMD_SetIDIPatternMatch; /* set pattern match value */ | |
| 724 | − pci1760_mbxrequest(dev, omb, imb); | |
| 725 | − devpriv->IDIPatMatchValue = 0x00; | |
| 726 | − | |
| 727 | − return 0; | |
| 728 | −} | |
| 729 | − | |
| 730 | −/* | |
| 731 | −============================================================================== | |
| 732 | −*/ | |
| 733 | −static int pci_dio_reset(struct comedi_device *dev) | |
| 734 | −{ | |
| 735 | − const struct dio_boardtype *board = dev->board_ptr; | |
| 736 | − | |
| 737 | − switch (board->cardtype) { | |
| 276 | + /* disable and clear interrupts */ | |
| 277 | + switch (cardtype) { | |
| 738 | 278 | case TYPE_PCI1730: |
| 739 | − outb(0, dev->iobase + PCI1730_DO); /* clear outputs */ | |
| 740 | − outb(0, dev->iobase + PCI1730_DO + 1); | |
| 741 | − outb(0, dev->iobase + PCI1730_IDO); | |
| 742 | − outb(0, dev->iobase + PCI1730_IDO + 1); | |
| 743 | − /* fallthrough */ | |
| 744 | 279 | case TYPE_PCI1733: |
| 745 | − /* disable interrupts */ | |
| 746 | − outb(0, dev->iobase + PCI1730_3_INT_EN); | |
| 747 | − /* clear interrupts */ | |
| 748 | − outb(0x0f, dev->iobase + PCI1730_3_INT_CLR); | |
| 749 | − /* set rising edge trigger */ | |
| 750 | − outb(0, dev->iobase + PCI1730_3_INT_RF); | |
| 751 | − break; | |
| 752 | − case TYPE_PCI1734: | |
| 753 | − outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */ | |
| 754 | − outb(0, dev->iobase + PCI1734_IDO + 1); | |
| 755 | − outb(0, dev->iobase + PCI1734_IDO + 2); | |
| 756 | − outb(0, dev->iobase + PCI1734_IDO + 3); | |
| 757 | − break; | |
| 758 | − case TYPE_PCI1735: | |
| 759 | − outb(0, dev->iobase + PCI1735_DO); /* clear outputs */ | |
| 760 | − outb(0, dev->iobase + PCI1735_DO + 1); | |
| 761 | − outb(0, dev->iobase + PCI1735_DO + 2); | |
| 762 | − outb(0, dev->iobase + PCI1735_DO + 3); | |
| 763 | − break; | |
| 764 | − | |
| 765 | 280 | case TYPE_PCI1736: |
| 766 | − outb(0, dev->iobase + PCI1736_IDO); | |
| 767 | − outb(0, dev->iobase + PCI1736_IDO + 1); | |
| 768 | − /* disable interrupts */ | |
| 769 | − outb(0, dev->iobase + PCI1736_3_INT_EN); | |
| 770 | − /* clear interrupts */ | |
| 771 | − outb(0x0f, dev->iobase + PCI1736_3_INT_CLR); | |
| 772 | − /* set rising edge trigger */ | |
| 773 | − outb(0, dev->iobase + PCI1736_3_INT_RF); | |
| 281 | + outb(0, dev->iobase + PCI173X_INT_EN_REG); | |
| 282 | + outb(0x0f, dev->iobase + PCI173X_INT_CLR_REG); | |
| 283 | + outb(0, dev->iobase + PCI173X_INT_RF_REG); | |
| 774 | 284 | break; |
| 775 | − | |
| 776 | 285 | case TYPE_PCI1739: |
| 777 | − /* disable & clear interrupts */ | |
| 778 | − outb(0x88, dev->iobase + PCI1739_ICR); | |
| 779 | − break; | |
| 780 | − | |
| 781 | 286 | case TYPE_PCI1750: |
| 782 | 287 | case TYPE_PCI1751: |
| 783 | − /* disable & clear interrupts */ | |
| 784 | − outb(0x88, dev->iobase + PCI1750_ICR); | |
| 785 | − break; | |
| 786 | − case TYPE_PCI1752: | |
| 787 | − outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze | |
| 788 | − * function */ | |
| 789 | − outw(0, dev->iobase + PCI1752_IDO); /* clear outputs */ | |
| 790 | − outw(0, dev->iobase + PCI1752_IDO + 2); | |
| 791 | − outw(0, dev->iobase + PCI1752_IDO2); | |
| 792 | − outw(0, dev->iobase + PCI1752_IDO2 + 2); | |
| 288 | + outb(0x88, dev->iobase + PCI1750_INT_REG); | |
| 793 | 289 | break; |
| 794 | − case TYPE_PCI1753E: | |
| 795 | − outb(0x88, dev->iobase + PCI1753E_ICR0); /* disable & clear | |
| 796 | − * interrupts */ | |
| 797 | − outb(0x80, dev->iobase + PCI1753E_ICR1); | |
| 798 | − outb(0x80, dev->iobase + PCI1753E_ICR2); | |
| 799 | − outb(0x80, dev->iobase + PCI1753E_ICR3); | |
| 800 | − /* fallthrough */ | |
| 801 | 290 | case TYPE_PCI1753: |
| 802 | − outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear | |
| 803 | − * interrupts */ | |
| 804 | − outb(0x80, dev->iobase + PCI1753_ICR1); | |
| 805 | − outb(0x80, dev->iobase + PCI1753_ICR2); | |
| 806 | − outb(0x80, dev->iobase + PCI1753_ICR3); | |
| 291 | + case TYPE_PCI1753E: | |
| 292 | + outb(0x88, dev->iobase + PCI1753_INT_REG(0)); | |
| 293 | + outb(0x80, dev->iobase + PCI1753_INT_REG(1)); | |
| 294 | + outb(0x80, dev->iobase + PCI1753_INT_REG(2)); | |
| 295 | + outb(0x80, dev->iobase + PCI1753_INT_REG(3)); | |
| 296 | + if (cardtype == TYPE_PCI1753E) { | |
| 297 | + outb(0x88, dev->iobase + PCI1753E_INT_REG(0)); | |
| 298 | + outb(0x80, dev->iobase + PCI1753E_INT_REG(1)); | |
| 299 | + outb(0x80, dev->iobase + PCI1753E_INT_REG(2)); | |
| 300 | + outb(0x80, dev->iobase + PCI1753E_INT_REG(3)); | |
| 301 | + } | |
| 807 | 302 | break; |
| 808 | 303 | case TYPE_PCI1754: |
| 809 | − outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear | |
| 810 | − * interrupts */ | |
| 811 | − outw(0x08, dev->iobase + PCI1754_6_ICR1); | |
| 812 | − outw(0x08, dev->iobase + PCI1754_ICR2); | |
| 813 | − outw(0x08, dev->iobase + PCI1754_ICR3); | |
| 814 | − break; | |
| 815 | 304 | case TYPE_PCI1756: |
| 816 | − outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze | |
| 817 | − * function */ | |
| 818 | − outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear | |
| 819 | − * interrupts */ | |
| 820 | − outw(0x08, dev->iobase + PCI1754_6_ICR1); | |
| 821 | − outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */ | |
| 822 | − outw(0, dev->iobase + PCI1756_IDO + 2); | |
| 823 | − break; | |
| 824 | − case TYPE_PCI1760: | |
| 825 | − pci1760_reset(dev); | |
| 305 | + outw(0x08, dev->iobase + PCI1754_INT_REG(0)); | |
| 306 | + outw(0x08, dev->iobase + PCI1754_INT_REG(1)); | |
| 307 | + if (cardtype == TYPE_PCI1754) { | |
| 308 | + outw(0x08, dev->iobase + PCI1754_INT_REG(2)); | |
| 309 | + outw(0x08, dev->iobase + PCI1754_INT_REG(3)); | |
| 310 | + } | |
| 826 | 311 | break; |
| 827 | 312 | case TYPE_PCI1762: |
| 828 | − outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear | |
| 829 | − * interrupts */ | |
| 830 | − break; | |
| 831 | − } | |
| 832 | − | |
| 833 | − return 0; | |
| 834 | −} | |
| 835 | − | |
| 836 | −/* | |
| 837 | −============================================================================== | |
| 838 | −*/ | |
| 839 | −static int pci1760_attach(struct comedi_device *dev) | |
| 840 | −{ | |
| 841 | − struct comedi_subdevice *s; | |
| 842 | − | |
| 843 | − s = &dev->subdevices[0]; | |
| 844 | − s->type = COMEDI_SUBD_DI; | |
| 845 | − s->subdev_flags = SDF_READABLE; | |
| 846 | − s->n_chan = 8; | |
| 847 | − s->maxdata = 1; | |
| 848 | − s->len_chanlist = 8; | |
| 849 | − s->range_table = &range_digital; | |
| 850 | − s->insn_bits = pci1760_insn_bits_di; | |
| 851 | − | |
| 852 | − s = &dev->subdevices[1]; | |
| 853 | − s->type = COMEDI_SUBD_DO; | |
| 854 | − s->subdev_flags = SDF_WRITABLE; | |
| 855 | − s->n_chan = 8; | |
| 856 | − s->maxdata = 1; | |
| 857 | − s->len_chanlist = 8; | |
| 858 | − s->range_table = &range_digital; | |
| 859 | − s->state = 0; | |
| 860 | − s->insn_bits = pci1760_insn_bits_do; | |
| 861 | − | |
| 862 | − s = &dev->subdevices[2]; | |
| 863 | − s->type = COMEDI_SUBD_TIMER; | |
| 864 | − s->subdev_flags = SDF_WRITABLE | SDF_LSAMPL; | |
| 865 | − s->n_chan = 2; | |
| 866 | − s->maxdata = 0xffffffff; | |
| 867 | − s->len_chanlist = 2; | |
| 868 | −/* s->insn_config=pci1760_insn_pwm_cfg; */ | |
| 869 | − | |
| 870 | − s = &dev->subdevices[3]; | |
| 871 | − s->type = COMEDI_SUBD_COUNTER; | |
| 872 | − s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | |
| 873 | − s->n_chan = 8; | |
| 874 | − s->maxdata = 0xffff; | |
| 875 | − s->len_chanlist = 8; | |
| 876 | − s->insn_read = pci1760_insn_cnt_read; | |
| 877 | − s->insn_write = pci1760_insn_cnt_write; | |
| 878 | −/* s->insn_config=pci1760_insn_cnt_cfg; */ | |
| 879 | − | |
| 880 | − return 0; | |
| 881 | −} | |
| 882 | − | |
| 883 | −/* | |
| 884 | −============================================================================== | |
| 885 | −*/ | |
| 886 | −static int pci_dio_add_di(struct comedi_device *dev, | |
| 887 | − struct comedi_subdevice *s, | |
| 888 | − const struct diosubd_data *d) | |
| 889 | −{ | |
| 890 | − const struct dio_boardtype *board = dev->board_ptr; | |
| 891 | − | |
| 892 | − s->type = COMEDI_SUBD_DI; | |
| 893 | − s->subdev_flags = SDF_READABLE | d->specflags; | |
| 894 | − if (d->chans > 16) | |
| 895 | − s->subdev_flags |= SDF_LSAMPL; | |
| 896 | − s->n_chan = d->chans; | |
| 897 | − s->maxdata = 1; | |
| 898 | − s->len_chanlist = d->chans; | |
| 899 | − s->range_table = &range_digital; | |
| 900 | − switch (board->io_access) { | |
| 901 | − case IO_8b: | |
| 902 | − s->insn_bits = pci_dio_insn_bits_di_b; | |
| 903 | − break; | |
| 904 | − case IO_16b: | |
| 905 | − s->insn_bits = pci_dio_insn_bits_di_w; | |
| 906 | − break; | |
| 907 | − } | |
| 908 | − s->private = (void *)d; | |
| 909 | − | |
| 910 | − return 0; | |
| 911 | −} | |
| 912 | − | |
| 913 | −/* | |
| 914 | −============================================================================== | |
| 915 | −*/ | |
| 916 | −static int pci_dio_add_do(struct comedi_device *dev, | |
| 917 | − struct comedi_subdevice *s, | |
| 918 | − const struct diosubd_data *d) | |
| 919 | −{ | |
| 920 | − const struct dio_boardtype *board = dev->board_ptr; | |
| 921 | − | |
| 922 | − s->type = COMEDI_SUBD_DO; | |
| 923 | − s->subdev_flags = SDF_WRITABLE; | |
| 924 | − if (d->chans > 16) | |
| 925 | − s->subdev_flags |= SDF_LSAMPL; | |
| 926 | − s->n_chan = d->chans; | |
| 927 | − s->maxdata = 1; | |
| 928 | − s->len_chanlist = d->chans; | |
| 929 | − s->range_table = &range_digital; | |
| 930 | − s->state = 0; | |
| 931 | − switch (board->io_access) { | |
| 932 | − case IO_8b: | |
| 933 | − s->insn_bits = pci_dio_insn_bits_do_b; | |
| 313 | + outw(0x0101, dev->iobase + PCI1762_INT_REG); | |
| 934 | 314 | break; |
| 935 | − case IO_16b: | |
| 936 | − s->insn_bits = pci_dio_insn_bits_do_w; | |
| 315 | + default: | |
| 937 | 316 | break; |
| 938 | 317 | } |
| 939 | − s->private = (void *)d; | |
| 940 | 318 | |
| 941 | 319 | return 0; |
| 942 | 320 | } |
| 943 | 321 | |
| 944 | −static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev, | |
| 945 | − unsigned long cardtype) | |
| 946 | −{ | |
| 947 | − /* | |
| 948 | − * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion | |
| 949 | − * board available. Need to enable PCI device and request the main | |
| 950 | − * registers PCI BAR temporarily to perform the test. | |
| 951 | − */ | |
| 952 | − if (cardtype != TYPE_PCI1753) | |
| 953 | − return cardtype; | |
| 954 | − if (pci_enable_device(pcidev) < 0) | |
| 955 | − return cardtype; | |
| 956 | − if (pci_request_region(pcidev, PCIDIO_MAINREG, "adv_pci_dio") == 0) { | |
| 957 | − /* | |
| 958 | − * This test is based on Advantech's "advdaq" driver source | |
| 959 | − * (which declares its module licence as "GPL" although the | |
| 960 | − * driver source does not include a "COPYING" file). | |
| 961 | − */ | |
| 962 | − unsigned long reg = | |
| 963 | − pci_resource_start(pcidev, PCIDIO_MAINREG) + 53; | |
| 964 | − | |
| 965 | − outb(0x05, reg); | |
| 966 | − if ((inb(reg) & 0x07) == 0x02) { | |
| 967 | − outb(0x02, reg); | |
| 968 | − if ((inb(reg) & 0x07) == 0x05) | |
| 969 | − cardtype = TYPE_PCI1753E; | |
| 970 | − } | |
| 971 | − pci_release_region(pcidev, PCIDIO_MAINREG); | |
| 972 | − } | |
| 973 | − pci_disable_device(pcidev); | |
| 974 | − return cardtype; | |
| 975 | −} | |
| 976 | − | |
| 977 | 322 | static int pci_dio_auto_attach(struct comedi_device *dev, |
| 978 | 323 | unsigned long context) |
| 979 | 324 | { |
| 980 | 325 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 981 | 326 | const struct dio_boardtype *board = NULL; |
| 982 | − struct pci_dio_private *devpriv; | |
| 327 | + const struct diosubd_data *d; | |
| 983 | 328 | struct comedi_subdevice *s; |
| 984 | 329 | int ret, subdev, i, j; |
| 985 | 330 | |
| @@ -990,54 +335,93 @@ static int pci_dio_auto_attach(struct comedi_device *dev, · 4 unmodified lines | ||
| 990 | 335 | dev->board_ptr = board; |
| 991 | 336 | dev->board_name = board->name; |
| 992 | 337 | |
| 993 | − devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | |
| 994 | − if (!devpriv) | |
| 995 | − return -ENOMEM; | |
| 996 | − | |
| 997 | 338 | ret = comedi_pci_enable(dev); |
| 998 | 339 | if (ret) |
| 999 | 340 | return ret; |
| 1000 | − dev->iobase = pci_resource_start(pcidev, board->main_pci_region); | |
| 341 | + if (context == TYPE_PCI1736) | |
| 342 | + dev->iobase = pci_resource_start(pcidev, 0); | |
| 343 | + else | |
| 344 | + dev->iobase = pci_resource_start(pcidev, 2); | |
| 345 | + | |
| 346 | + pci_dio_reset(dev, context); | |
| 1001 | 347 | |
| 1002 | 348 | ret = comedi_alloc_subdevices(dev, board->nsubdevs); |
| 1003 | 349 | if (ret) |
| 1004 | 350 | return ret; |
| 1005 | 351 | |
| 1006 | 352 | subdev = 0; |
| 1007 | − for (i = 0; i < MAX_DI_SUBDEVS; i++) | |
| 1008 | − if (board->sdi[i].chans) { | |
| 1009 | − s = &dev->subdevices[subdev]; | |
| 1010 | − pci_dio_add_di(dev, s, &board->sdi[i]); | |
| 1011 | − subdev++; | |
| 353 | + for (i = 0; i < PCI_DIO_MAX_DI_SUBDEVS; i++) { | |
| 354 | + d = &board->sdi[i]; | |
| 355 | + if (d->chans) { | |
| 356 | + s = &dev->subdevices[subdev++]; | |
| 357 | + s->type = COMEDI_SUBD_DI; | |
| 358 | + s->subdev_flags = SDF_READABLE; | |
| 359 | + s->n_chan = d->chans; | |
| 360 | + s->maxdata = 1; | |
| 361 | + s->range_table = &range_digital; | |
| 362 | + s->insn_bits = board->is_16bit | |
| 363 | + ? pci_dio_insn_bits_di_w | |
| 364 | + : pci_dio_insn_bits_di_b; | |
| 365 | + s->private = (void *)d->addr; | |
| 1012 | 366 | } |
| 367 | + } | |
| 1013 | 368 | |
| 1014 | − for (i = 0; i < MAX_DO_SUBDEVS; i++) | |
| 1015 | − if (board->sdo[i].chans) { | |
| 1016 | − s = &dev->subdevices[subdev]; | |
| 1017 | − pci_dio_add_do(dev, s, &board->sdo[i]); | |
| 1018 | − subdev++; | |
| 369 | + for (i = 0; i < PCI_DIO_MAX_DO_SUBDEVS; i++) { | |
| 370 | + d = &board->sdo[i]; | |
| 371 | + if (d->chans) { | |
| 372 | + s = &dev->subdevices[subdev++]; | |
| 373 | + s->type = COMEDI_SUBD_DO; | |
| 374 | + s->subdev_flags = SDF_WRITABLE; | |
| 375 | + s->n_chan = d->chans; | |
| 376 | + s->maxdata = 1; | |
| 377 | + s->range_table = &range_digital; | |
| 378 | + s->insn_bits = board->is_16bit | |
| 379 | + ? pci_dio_insn_bits_do_w | |
| 380 | + : pci_dio_insn_bits_do_b; | |
| 381 | + s->private = (void *)d->addr; | |
| 382 | + | |
| 383 | + /* reset all outputs to 0 */ | |
| 384 | + if (board->is_16bit) { | |
| 385 | + outw(0, dev->iobase + d->addr); | |
| 386 | + if (s->n_chan > 16) | |
| 387 | + outw(0, dev->iobase + d->addr + 2); | |
| 388 | + } else { | |
| 389 | + outb(0, dev->iobase + d->addr); | |
| 390 | + if (s->n_chan > 8) | |
| 391 | + outb(0, dev->iobase + d->addr + 1); | |
| 392 | + if (s->n_chan > 16) | |
| 393 | + outb(0, dev->iobase + d->addr + 2); | |
| 394 | + if (s->n_chan > 24) | |
| 395 | + outb(0, dev->iobase + d->addr + 3); | |
| 396 | + } | |
| 1019 | 397 | } |
| 398 | + } | |
| 1020 | 399 | |
| 1021 | − for (i = 0; i < MAX_DIO_SUBDEVG; i++) | |
| 1022 | − for (j = 0; j < board->sdio[i].regs; j++) { | |
| 1023 | − s = &dev->subdevices[subdev]; | |
| 400 | + for (i = 0; i < PCI_DIO_MAX_DIO_SUBDEVG; i++) { | |
| 401 | + d = &board->sdio[i]; | |
| 402 | + for (j = 0; j < d->chans; j++) { | |
| 403 | + s = &dev->subdevices[subdev++]; | |
| 1024 | 404 | ret = subdev_8255_init(dev, s, NULL, |
| 1025 | − board->sdio[i].addr + | |
| 1026 | − j * I8255_SIZE); | |
| 405 | + d->addr + j * I8255_SIZE); | |
| 1027 | 406 | if (ret) |
| 1028 | 407 | return ret; |
| 1029 | − subdev++; | |
| 1030 | 408 | } |
| 409 | + } | |
| 1031 | 410 | |
| 1032 | − if (board->boardid.chans) { | |
| 1033 | − s = &dev->subdevices[subdev]; | |
| 1034 | − s->type = COMEDI_SUBD_DI; | |
| 1035 | − pci_dio_add_di(dev, s, &board->boardid); | |
| 1036 | − subdev++; | |
| 411 | + if (board->id_reg) { | |
| 412 | + s = &dev->subdevices[subdev++]; | |
| 413 | + s->type = COMEDI_SUBD_DI; | |
| 414 | + s->subdev_flags = SDF_READABLE | SDF_INTERNAL; | |
| 415 | + s->n_chan = 4; | |
| 416 | + s->maxdata = 1; | |
| 417 | + s->range_table = &range_digital; | |
| 418 | + s->insn_bits = board->is_16bit ? pci_dio_insn_bits_di_w | |
| 419 | + : pci_dio_insn_bits_di_b; | |
| 420 | + s->private = (void *)board->id_reg; | |
| 1037 | 421 | } |
| 1038 | 422 | |
| 1039 | 423 | if (board->timer_regbase) { |
| 1040 | − s = &dev->subdevices[subdev]; | |
| 424 | + s = &dev->subdevices[subdev++]; | |
| 1041 | 425 | |
| 1042 | 426 | dev->pacer = comedi_8254_init(dev->iobase + |
| 1043 | 427 | board->timer_regbase, |
| @@ -1046,32 +430,50 @@ static int pci_dio_auto_attach(struct comedi_device *dev, · 2 unmodified lines | ||
| 1046 | 430 | return -ENOMEM; |
| 1047 | 431 | |
| 1048 | 432 | comedi_8254_subdevice_init(s, dev->pacer); |
| 1049 | − | |
| 1050 | − subdev++; | |
| 1051 | 433 | } |
| 1052 | 434 | |
| 1053 | − if (board->cardtype == TYPE_PCI1760) | |
| 1054 | − pci1760_attach(dev); | |
| 1055 | − | |
| 1056 | − pci_dio_reset(dev); | |
| 1057 | − | |
| 1058 | 435 | return 0; |
| 1059 | 436 | } |
| 1060 | 437 | |
| 1061 | −static void pci_dio_detach(struct comedi_device *dev) | |
| 1062 | −{ | |
| 1063 | − if (dev->iobase) | |
| 1064 | − pci_dio_reset(dev); | |
| 1065 | − comedi_pci_detach(dev); | |
| 1066 | −} | |
| 1067 | − | |
| 1068 | 438 | static struct comedi_driver adv_pci_dio_driver = { |
| 1069 | 439 | .driver_name = "adv_pci_dio", |
| 1070 | 440 | .module = THIS_MODULE, |
| 1071 | 441 | .auto_attach = pci_dio_auto_attach, |
| 1072 | − .detach = pci_dio_detach, | |
| 442 | + .detach = comedi_pci_detach, | |
| 1073 | 443 | }; |
| 1074 | 444 | |
| 445 | +static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev, | |
| 446 | + unsigned long cardtype) | |
| 447 | +{ | |
| 448 | + /* | |
| 449 | + * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion | |
| 450 | + * board available. Need to enable PCI device and request the main | |
| 451 | + * registers PCI BAR temporarily to perform the test. | |
| 452 | + */ | |
| 453 | + if (cardtype != TYPE_PCI1753) | |
| 454 | + return cardtype; | |
| 455 | + if (pci_enable_device(pcidev) < 0) | |
| 456 | + return cardtype; | |
| 457 | + if (pci_request_region(pcidev, 2, "adv_pci_dio") == 0) { | |
| 458 | + /* | |
| 459 | + * This test is based on Advantech's "advdaq" driver source | |
| 460 | + * (which declares its module licence as "GPL" although the | |
| 461 | + * driver source does not include a "COPYING" file). | |
| 462 | + */ | |
| 463 | + unsigned long reg = pci_resource_start(pcidev, 2) + 53; | |
| 464 | + | |
| 465 | + outb(0x05, reg); | |
| 466 | + if ((inb(reg) & 0x07) == 0x02) { | |
| 467 | + outb(0x02, reg); | |
| 468 | + if ((inb(reg) & 0x07) == 0x05) | |
| 469 | + cardtype = TYPE_PCI1753E; | |
| 470 | + } | |
| 471 | + pci_release_region(pcidev, 2); | |
| 472 | + } | |
| 473 | + pci_disable_device(pcidev); | |
| 474 | + return cardtype; | |
| 475 | +} | |
| 476 | + | |
| 1075 | 477 | static int adv_pci_dio_pci_probe(struct pci_dev *dev, |
| 1076 | 478 | const struct pci_device_id *id) |
| 1077 | 479 | { |
| @@ -1094,7 +496,6 @@ static const struct pci_device_id adv_pci_dio_pci_table[] = { · 16 unmodified lines | ||
| 1094 | 496 | { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 }, |
| 1095 | 497 | { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 }, |
| 1096 | 498 | { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 }, |
| 1097 | − { PCI_VDEVICE(ADVANTECH, 0x1760), TYPE_PCI1760 }, | |
| 1098 | 499 | { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 }, |
| 1099 | 500 | { 0 } |
| 1100 | 501 | }; |
| @@ -1109,5 +510,5 @@ static struct pci_driver adv_pci_dio_pci_driver = { · 8 unmodified lines | ||
| 1109 | 510 | module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver); |
| 1110 | 511 | |
| 1111 | 512 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
| 1112 | −MODULE_DESCRIPTION("Comedi low-level driver"); | |
| 513 | +MODULE_DESCRIPTION("Comedi driver for Advantech Digital I/O Cards"); | |
| 1113 | 514 | MODULE_LICENSE("GPL"); |
| @@ -1022,14 +1022,17 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) · 1021 unmodified lines | ||
| 1022 | 1022 | irq = pci_dev->irq; |
| 1023 | 1023 | |
| 1024 | 1024 | /* Allocate buffer to hold values for AO channel scan. */ |
| 1025 | − devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) * | |
| 1026 | − board->ao_chans, GFP_KERNEL); | |
| 1025 | + devpriv->ao_scan_vals = kmalloc_array(board->ao_chans, | |
| 1026 | + sizeof(devpriv->ao_scan_vals[0]), | |
| 1027 | + GFP_KERNEL); | |
| 1027 | 1028 | if (!devpriv->ao_scan_vals) |
| 1028 | 1029 | return -ENOMEM; |
| 1029 | 1030 | |
| 1030 | 1031 | /* Allocate buffer to hold AO channel scan order. */ |
| 1031 | − devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) * | |
| 1032 | − board->ao_chans, GFP_KERNEL); | |
| 1032 | + devpriv->ao_scan_order = | |
| 1033 | + kmalloc_array(board->ao_chans, | |
| 1034 | + sizeof(devpriv->ao_scan_order[0]), | |
| 1035 | + GFP_KERNEL); | |
| 1033 | 1036 | if (!devpriv->ao_scan_order) |
| 1034 | 1037 | return -ENOMEM; |
| 1035 | 1038 | |
| @@ -51,13 +51,13 @@ · 50 unmodified lines | ||
| 51 | 51 | |
| 52 | 52 | /* DAC registers */ |
| 53 | 53 | #define CB_DDA_DA_CTRL_REG 0x00 /* D/A Control Register */ |
| 54 | −#define CB_DDA_DA_CTRL_SU (1 << 0) /* Simultaneous update */ | |
| 55 | −#define CB_DDA_DA_CTRL_EN (1 << 1) /* Enable specified DAC */ | |
| 54 | +#define CB_DDA_DA_CTRL_SU BIT(0) /* Simultaneous update */ | |
| 55 | +#define CB_DDA_DA_CTRL_EN BIT(1) /* Enable specified DAC */ | |
| 56 | 56 | #define CB_DDA_DA_CTRL_DAC(x) ((x) << 2) /* Specify DAC channel */ |
| 57 | 57 | #define CB_DDA_DA_CTRL_RANGE2V5 (0 << 6) /* 2.5V range */ |
| 58 | 58 | #define CB_DDA_DA_CTRL_RANGE5V (2 << 6) /* 5V range */ |
| 59 | 59 | #define CB_DDA_DA_CTRL_RANGE10V (3 << 6) /* 10V range */ |
| 60 | −#define CB_DDA_DA_CTRL_UNIP (1 << 8) /* Unipolar range */ | |
| 60 | +#define CB_DDA_DA_CTRL_UNIP BIT(8) /* Unipolar range */ | |
| 61 | 61 | |
| 62 | 62 | #define DACALIBRATION1 4 /* D/A CALIBRATION REGISTER 1 */ |
| 63 | 63 | /* write bits */ |
| @@ -75,8 +75,8 @@ · 74 unmodified lines | ||
| 75 | 75 | #define PARPORT_DATA_REG 0x00 |
| 76 | 76 | #define PARPORT_STATUS_REG 0x01 |
| 77 | 77 | #define PARPORT_CTRL_REG 0x02 |
| 78 | −#define PARPORT_CTRL_IRQ_ENA (1 << 4) | |
| 79 | −#define PARPORT_CTRL_BIDIR_ENA (1 << 5) | |
| 78 | +#define PARPORT_CTRL_IRQ_ENA BIT(4) | |
| 79 | +#define PARPORT_CTRL_BIDIR_ENA BIT(5) | |
| 80 | 80 | |
| 81 | 81 | static int parport_data_reg_insn_bits(struct comedi_device *dev, |
| 82 | 82 | struct comedi_subdevice *s, |
| @@ -801,9 +801,10 @@ static void das16_ai_munge(struct comedi_device *dev, · 800 unmodified lines | ||
| 801 | 801 | unsigned short *data = array; |
| 802 | 802 | unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes); |
| 803 | 803 | unsigned int i; |
| 804 | + __le16 *buf = array; | |
| 804 | 805 | |
| 805 | 806 | for (i = 0; i < num_samples; i++) { |
| 806 | − data[i] = le16_to_cpu(data[i]); | |
| 807 | + data[i] = le16_to_cpu(buf[i]); | |
| 807 | 808 | if (s->maxdata == 0x0fff) |
| 808 | 809 | data[i] >>= 4; |
| 809 | 810 | data[i] &= s->maxdata; |
| @@ -42,24 +42,24 @@ · 41 unmodified lines | ||
| 42 | 42 | #define NI6527_DO_REG(x) (0x03 + (x)) |
| 43 | 43 | #define NI6527_ID_REG 0x06 |
| 44 | 44 | #define NI6527_CLR_REG 0x07 |
| 45 | −#define NI6527_CLR_EDGE (1 << 3) | |
| 46 | −#define NI6527_CLR_OVERFLOW (1 << 2) | |
| 47 | −#define NI6527_CLR_FILT (1 << 1) | |
| 48 | −#define NI6527_CLR_INTERVAL (1 << 0) | |
| 45 | +#define NI6527_CLR_EDGE BIT(3) | |
| 46 | +#define NI6527_CLR_OVERFLOW BIT(2) | |
| 47 | +#define NI6527_CLR_FILT BIT(1) | |
| 48 | +#define NI6527_CLR_INTERVAL BIT(0) | |
| 49 | 49 | #define NI6527_CLR_IRQS (NI6527_CLR_EDGE | NI6527_CLR_OVERFLOW) |
| 50 | 50 | #define NI6527_CLR_RESET_FILT (NI6527_CLR_FILT | NI6527_CLR_INTERVAL) |
| 51 | 51 | #define NI6527_FILT_INTERVAL_REG(x) (0x08 + (x)) |
| 52 | 52 | #define NI6527_FILT_ENA_REG(x) (0x0c + (x)) |
| 53 | 53 | #define NI6527_STATUS_REG 0x14 |
| 54 | −#define NI6527_STATUS_IRQ (1 << 2) | |
| 55 | −#define NI6527_STATUS_OVERFLOW (1 << 1) | |
| 56 | −#define NI6527_STATUS_EDGE (1 << 0) | |
| 54 | +#define NI6527_STATUS_IRQ BIT(2) | |
| 55 | +#define NI6527_STATUS_OVERFLOW BIT(1) | |
| 56 | +#define NI6527_STATUS_EDGE BIT(0) | |
| 57 | 57 | #define NI6527_CTRL_REG 0x15 |
| 58 | −#define NI6527_CTRL_FALLING (1 << 4) | |
| 59 | −#define NI6527_CTRL_RISING (1 << 3) | |
| 60 | −#define NI6527_CTRL_IRQ (1 << 2) | |
| 61 | −#define NI6527_CTRL_OVERFLOW (1 << 1) | |
| 62 | −#define NI6527_CTRL_EDGE (1 << 0) | |
| 58 | +#define NI6527_CTRL_FALLING BIT(4) | |
| 59 | +#define NI6527_CTRL_RISING BIT(3) | |
| 60 | +#define NI6527_CTRL_IRQ BIT(2) | |
| 61 | +#define NI6527_CTRL_OVERFLOW BIT(1) | |
| 62 | +#define NI6527_CTRL_EDGE BIT(0) | |
| 63 | 63 | #define NI6527_CTRL_DISABLE_IRQS 0 |
| 64 | 64 | #define NI6527_CTRL_ENABLE_IRQS (NI6527_CTRL_FALLING | \ |
| 65 | 65 | NI6527_CTRL_RISING | \ |
| @@ -68,25 +68,25 @@ · 67 unmodified lines | ||
| 68 | 68 | /* Non-recurring Registers (8-bit except where noted) */ |
| 69 | 69 | #define NI_65XX_ID_REG 0x00 |
| 70 | 70 | #define NI_65XX_CLR_REG 0x01 |
| 71 | −#define NI_65XX_CLR_WDOG_INT (1 << 6) | |
| 72 | −#define NI_65XX_CLR_WDOG_PING (1 << 5) | |
| 73 | −#define NI_65XX_CLR_WDOG_EXP (1 << 4) | |
| 74 | −#define NI_65XX_CLR_EDGE_INT (1 << 3) | |
| 75 | −#define NI_65XX_CLR_OVERFLOW_INT (1 << 2) | |
| 71 | +#define NI_65XX_CLR_WDOG_INT BIT(6) | |
| 72 | +#define NI_65XX_CLR_WDOG_PING BIT(5) | |
| 73 | +#define NI_65XX_CLR_WDOG_EXP BIT(4) | |
| 74 | +#define NI_65XX_CLR_EDGE_INT BIT(3) | |
| 75 | +#define NI_65XX_CLR_OVERFLOW_INT BIT(2) | |
| 76 | 76 | #define NI_65XX_STATUS_REG 0x02 |
| 77 | −#define NI_65XX_STATUS_WDOG_INT (1 << 5) | |
| 78 | −#define NI_65XX_STATUS_FALL_EDGE (1 << 4) | |
| 79 | −#define NI_65XX_STATUS_RISE_EDGE (1 << 3) | |
| 80 | −#define NI_65XX_STATUS_INT (1 << 2) | |
| 81 | −#define NI_65XX_STATUS_OVERFLOW_INT (1 << 1) | |
| 82 | −#define NI_65XX_STATUS_EDGE_INT (1 << 0) | |
| 77 | +#define NI_65XX_STATUS_WDOG_INT BIT(5) | |
| 78 | +#define NI_65XX_STATUS_FALL_EDGE BIT(4) | |
| 79 | +#define NI_65XX_STATUS_RISE_EDGE BIT(3) | |
| 80 | +#define NI_65XX_STATUS_INT BIT(2) | |
| 81 | +#define NI_65XX_STATUS_OVERFLOW_INT BIT(1) | |
| 82 | +#define NI_65XX_STATUS_EDGE_INT BIT(0) | |
| 83 | 83 | #define NI_65XX_CTRL_REG 0x03 |
| 84 | −#define NI_65XX_CTRL_WDOG_ENA (1 << 5) | |
| 85 | −#define NI_65XX_CTRL_FALL_EDGE_ENA (1 << 4) | |
| 86 | −#define NI_65XX_CTRL_RISE_EDGE_ENA (1 << 3) | |
| 87 | −#define NI_65XX_CTRL_INT_ENA (1 << 2) | |
| 88 | −#define NI_65XX_CTRL_OVERFLOW_ENA (1 << 1) | |
| 89 | −#define NI_65XX_CTRL_EDGE_ENA (1 << 0) | |
| 84 | +#define NI_65XX_CTRL_WDOG_ENA BIT(5) | |
| 85 | +#define NI_65XX_CTRL_FALL_EDGE_ENA BIT(4) | |
| 86 | +#define NI_65XX_CTRL_RISE_EDGE_ENA BIT(3) | |
| 87 | +#define NI_65XX_CTRL_INT_ENA BIT(2) | |
| 88 | +#define NI_65XX_CTRL_OVERFLOW_ENA BIT(1) | |
| 89 | +#define NI_65XX_CTRL_EDGE_ENA BIT(0) | |
| 90 | 90 | #define NI_65XX_REV_REG 0x04 /* 32-bit */ |
| 91 | 91 | #define NI_65XX_FILTER_REG 0x08 /* 32-bit */ |
| 92 | 92 | #define NI_65XX_RTSI_ROUTE_REG 0x0c /* 16-bit */ |
| @@ -94,24 +94,24 @@ · 1 unmodified line | ||
| 94 | 94 | #define NI_65XX_RTSI_WDOG_REG 0x10 /* 16-bit */ |
| 95 | 95 | #define NI_65XX_RTSI_TRIG_REG 0x12 /* 16-bit */ |
| 96 | 96 | #define NI_65XX_AUTO_CLK_SEL_REG 0x14 /* PXI-6528 only */ |
| 97 | −#define NI_65XX_AUTO_CLK_SEL_STATUS (1 << 1) | |
| 98 | −#define NI_65XX_AUTO_CLK_SEL_DISABLE (1 << 0) | |
| 97 | +#define NI_65XX_AUTO_CLK_SEL_STATUS BIT(1) | |
| 98 | +#define NI_65XX_AUTO_CLK_SEL_DISABLE BIT(0) | |
| 99 | 99 | #define NI_65XX_WDOG_CTRL_REG 0x15 |
| 100 | −#define NI_65XX_WDOG_CTRL_ENA (1 << 0) | |
| 100 | +#define NI_65XX_WDOG_CTRL_ENA BIT(0) | |
| 101 | 101 | #define NI_65XX_RTSI_CFG_REG 0x16 |
| 102 | −#define NI_65XX_RTSI_CFG_RISE_SENSE (1 << 2) | |
| 103 | −#define NI_65XX_RTSI_CFG_FALL_SENSE (1 << 1) | |
| 104 | −#define NI_65XX_RTSI_CFG_SYNC_DETECT (1 << 0) | |
| 102 | +#define NI_65XX_RTSI_CFG_RISE_SENSE BIT(2) | |
| 103 | +#define NI_65XX_RTSI_CFG_FALL_SENSE BIT(1) | |
| 104 | +#define NI_65XX_RTSI_CFG_SYNC_DETECT BIT(0) | |
| 105 | 105 | #define NI_65XX_WDOG_STATUS_REG 0x17 |
| 106 | −#define NI_65XX_WDOG_STATUS_EXP (1 << 0) | |
| 106 | +#define NI_65XX_WDOG_STATUS_EXP BIT(0) | |
| 107 | 107 | #define NI_65XX_WDOG_INTERVAL_REG 0x18 /* 32-bit */ |
| 108 | 108 | |
| 109 | 109 | /* Recurring port registers (8-bit) */ |
| 110 | 110 | #define NI_65XX_PORT(x) ((x) * 0x10) |
| 111 | 111 | #define NI_65XX_IO_DATA_REG(x) (0x40 + NI_65XX_PORT(x)) |
| 112 | 112 | #define NI_65XX_IO_SEL_REG(x) (0x41 + NI_65XX_PORT(x)) |
| 113 | −#define NI_65XX_IO_SEL_OUTPUT (0 << 0) | |
| 114 | −#define NI_65XX_IO_SEL_INPUT (1 << 0) | |
| 113 | +#define NI_65XX_IO_SEL_OUTPUT 0 | |
| 114 | +#define NI_65XX_IO_SEL_INPUT BIT(0) | |
| 115 | 115 | #define NI_65XX_RISE_EDGE_ENA_REG(x) (0x42 + NI_65XX_PORT(x)) |
| 116 | 116 | #define NI_65XX_FALL_EDGE_ENA_REG(x) (0x43 + NI_65XX_PORT(x)) |
| 117 | 117 | #define NI_65XX_FILTER_ENA(x) (0x44 + NI_65XX_PORT(x)) |
| @@ -613,7 +613,7 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev, · 495 unmodified lines | ||
| 613 | 613 | |
| 614 | 614 | /* ripped from mite.h and mite_setup2() to avoid mite dependency */ |
| 615 | 615 | #define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ |
| 616 | −#define WENAB (1 << 7) /* window enable */ | |
| 616 | +#define WENAB BIT(7) /* window enable */ | |
| 617 | 617 | |
| 618 | 618 | static int ni_65xx_mite_init(struct pci_dev *pcidev) |
| 619 | 619 | { |
| @@ -214,8 +214,9 @@ static int ni_670x_auto_attach(struct comedi_device *dev, · 213 unmodified lines | ||
| 214 | 214 | if (s->n_chan == 32) { |
| 215 | 215 | const struct comedi_lrange **range_table_list; |
| 216 | 216 | |
| 217 | − range_table_list = kmalloc(sizeof(struct comedi_lrange *) * 32, | |
| 218 | − GFP_KERNEL); | |
| 217 | + range_table_list = kmalloc_array(32, | |
| 218 | + sizeof(struct comedi_lrange *), | |
| 219 | + GFP_KERNEL); | |
| 219 | 220 | if (!range_table_list) |
| 220 | 221 | return -ENOMEM; |
| 221 | 222 | s->range_table_list = range_table_list; |
| @@ -579,48 +579,54 @@ static inline unsigned ni_stc_dma_channel_select_bitfield(unsigned channel) · 578 unmodified lines | ||
| 579 | 579 | return 0; |
| 580 | 580 | } |
| 581 | 581 | |
| 582 | −/* negative channel means no channel */ | |
| 583 | −static inline void ni_set_ai_dma_channel(struct comedi_device *dev, int channel) | |
| 582 | +static inline void ni_set_ai_dma_channel(struct comedi_device *dev, | |
| 583 | + unsigned channel) | |
| 584 | 584 | { |
| 585 | − unsigned bits = 0; | |
| 586 | − | |
| 587 | − if (channel >= 0) | |
| 588 | − bits = ni_stc_dma_channel_select_bitfield(channel); | |
| 585 | + unsigned bits = ni_stc_dma_channel_select_bitfield(channel); | |
| 589 | 586 | |
| 590 | 587 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
| 591 | 588 | NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits)); |
| 592 | 589 | } |
| 593 | 590 | |
| 594 | −/* negative channel means no channel */ | |
| 595 | −static inline void ni_set_ao_dma_channel(struct comedi_device *dev, int channel) | |
| 591 | +static inline void ni_set_ai_dma_no_channel(struct comedi_device *dev) | |
| 596 | 592 | { |
| 597 | − unsigned bits = 0; | |
| 593 | + ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, NI_E_DMA_AI_SEL_MASK, 0); | |
| 594 | +} | |
| 598 | 595 | |
| 599 | − if (channel >= 0) | |
| 600 | − bits = ni_stc_dma_channel_select_bitfield(channel); | |
| 596 | +static inline void ni_set_ao_dma_channel(struct comedi_device *dev, | |
| 597 | + unsigned channel) | |
| 598 | +{ | |
| 599 | + unsigned bits = ni_stc_dma_channel_select_bitfield(channel); | |
| 601 | 600 | |
| 602 | 601 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
| 603 | 602 | NI_E_DMA_AO_SEL_MASK, NI_E_DMA_AO_SEL(bits)); |
| 604 | 603 | } |
| 605 | 604 | |
| 606 | −/* negative channel means no channel */ | |
| 605 | +static inline void ni_set_ao_dma_no_channel(struct comedi_device *dev) | |
| 606 | +{ | |
| 607 | + ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, NI_E_DMA_AO_SEL_MASK, 0); | |
| 608 | +} | |
| 609 | + | |
| 607 | 610 | static inline void ni_set_gpct_dma_channel(struct comedi_device *dev, |
| 608 | 611 | unsigned gpct_index, |
| 609 | − int channel) | |
| 612 | + unsigned channel) | |
| 610 | 613 | { |
| 611 | − unsigned bits = 0; | |
| 612 | − | |
| 613 | − if (channel >= 0) | |
| 614 | − bits = ni_stc_dma_channel_select_bitfield(channel); | |
| 614 | + unsigned bits = ni_stc_dma_channel_select_bitfield(channel); | |
| 615 | 615 | |
| 616 | 616 | ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, |
| 617 | 617 | NI_E_DMA_G0_G1_SEL_MASK(gpct_index), |
| 618 | 618 | NI_E_DMA_G0_G1_SEL(gpct_index, bits)); |
| 619 | 619 | } |
| 620 | 620 | |
| 621 | −/* negative mite_channel means no channel */ | |
| 621 | +static inline void ni_set_gpct_dma_no_channel(struct comedi_device *dev, | |
| 622 | + unsigned gpct_index) | |
| 623 | +{ | |
| 624 | + ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, | |
| 625 | + NI_E_DMA_G0_G1_SEL_MASK(gpct_index), 0); | |
| 626 | +} | |
| 627 | + | |
| 622 | 628 | static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, |
| 623 | − int mite_channel) | |
| 629 | + unsigned mite_channel) | |
| 624 | 630 | { |
| 625 | 631 | struct ni_private *devpriv = dev->private; |
| 626 | 632 | unsigned long flags; |
| @@ -628,16 +634,26 @@ static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, · 1 unmodified line | ||
| 628 | 634 | |
| 629 | 635 | spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); |
| 630 | 636 | devpriv->cdio_dma_select_reg &= ~NI_M_CDIO_DMA_SEL_CDO_MASK; |
| 631 | − if (mite_channel >= 0) { | |
| 632 | − /* | |
| 633 | − * XXX just guessing ni_stc_dma_channel_select_bitfield() | |
| 634 | − * returns the right bits, under the assumption the cdio dma | |
| 635 | − * selection works just like ai/ao/gpct. | |
| 636 | − * Definitely works for dma channels 0 and 1. | |
| 637 | − */ | |
| 638 | − bits = ni_stc_dma_channel_select_bitfield(mite_channel); | |
| 639 | − devpriv->cdio_dma_select_reg |= NI_M_CDIO_DMA_SEL_CDO(bits); | |
| 640 | − } | |
| 637 | + /* | |
| 638 | + * XXX just guessing ni_stc_dma_channel_select_bitfield() | |
| 639 | + * returns the right bits, under the assumption the cdio dma | |
| 640 | + * selection works just like ai/ao/gpct. | |
| 641 | + * Definitely works for dma channels 0 and 1. | |
| 642 | + */ | |
| 643 | + bits = ni_stc_dma_channel_select_bitfield(mite_channel); | |
| 644 | + devpriv->cdio_dma_select_reg |= NI_M_CDIO_DMA_SEL_CDO(bits); | |
| 645 | + ni_writeb(dev, devpriv->cdio_dma_select_reg, NI_M_CDIO_DMA_SEL_REG); | |
| 646 | + mmiowb(); | |
| 647 | + spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); | |
| 648 | +} | |
| 649 | + | |
| 650 | +static inline void ni_set_cdo_dma_no_channel(struct comedi_device *dev) | |
| 651 | +{ | |
| 652 | + struct ni_private *devpriv = dev->private; | |
| 653 | + unsigned long flags; | |
| 654 | + | |
| 655 | + spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); | |
| 656 | + devpriv->cdio_dma_select_reg &= ~NI_M_CDIO_DMA_SEL_CDO_MASK; | |
| 641 | 657 | ni_writeb(dev, devpriv->cdio_dma_select_reg, NI_M_CDIO_DMA_SEL_REG); |
| 642 | 658 | mmiowb(); |
| 643 | 659 | spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); |
| @@ -745,7 +761,7 @@ static void ni_release_ai_mite_channel(struct comedi_device *dev) · 101 unmodified lines | ||
| 745 | 761 | |
| 746 | 762 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 747 | 763 | if (devpriv->ai_mite_chan) { |
| 748 | − ni_set_ai_dma_channel(dev, -1); | |
| 764 | + ni_set_ai_dma_no_channel(dev); | |
| 749 | 765 | mite_release_channel(devpriv->ai_mite_chan); |
| 750 | 766 | devpriv->ai_mite_chan = NULL; |
| 751 | 767 | } |
| @@ -761,7 +777,7 @@ static void ni_release_ao_mite_channel(struct comedi_device *dev) · 9 unmodified lines | ||
| 761 | 777 | |
| 762 | 778 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 763 | 779 | if (devpriv->ao_mite_chan) { |
| 764 | − ni_set_ao_dma_channel(dev, -1); | |
| 780 | + ni_set_ao_dma_no_channel(dev); | |
| 765 | 781 | mite_release_channel(devpriv->ao_mite_chan); |
| 766 | 782 | devpriv->ao_mite_chan = NULL; |
| 767 | 783 | } |
| @@ -781,7 +797,7 @@ static void ni_release_gpct_mite_channel(struct comedi_device *dev, · 13 unmodified lines | ||
| 781 | 797 | struct mite_channel *mite_chan = |
| 782 | 798 | devpriv->counter_dev->counters[gpct_index].mite_chan; |
| 783 | 799 | |
| 784 | − ni_set_gpct_dma_channel(dev, gpct_index, -1); | |
| 800 | + ni_set_gpct_dma_no_channel(dev, gpct_index); | |
| 785 | 801 | ni_tio_set_mite_channel(&devpriv-> |
| 786 | 802 | counter_dev->counters[gpct_index], |
| 787 | 803 | NULL); |
| @@ -799,7 +815,7 @@ static void ni_release_cdo_mite_channel(struct comedi_device *dev) · 11 unmodified lines | ||
| 799 | 815 | |
| 800 | 816 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 801 | 817 | if (devpriv->cdo_mite_chan) { |
| 802 | − ni_set_cdo_dma_channel(dev, -1); | |
| 818 | + ni_set_cdo_dma_no_channel(dev); | |
| 803 | 819 | mite_release_channel(devpriv->cdo_mite_chan); |
| 804 | 820 | devpriv->cdo_mite_chan = NULL; |
| 805 | 821 | } |
| @@ -1516,13 +1532,17 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, · 710 unmodified lines | ||
| 1516 | 1532 | unsigned short *array = data; |
| 1517 | 1533 | unsigned int *larray = data; |
| 1518 | 1534 | unsigned int i; |
| 1535 | +#ifdef PCIDMA | |
| 1536 | + __le16 *barray = data; | |
| 1537 | + __le32 *blarray = data; | |
| 1538 | +#endif | |
| 1519 | 1539 | |
| 1520 | 1540 | for (i = 0; i < nsamples; i++) { |
| 1521 | 1541 | #ifdef PCIDMA |
| 1522 | 1542 | if (s->subdev_flags & SDF_LSAMPL) |
| 1523 | − larray[i] = le32_to_cpu(larray[i]); | |
| 1543 | + larray[i] = le32_to_cpu(blarray[i]); | |
| 1524 | 1544 | else |
| 1525 | − array[i] = le16_to_cpu(array[i]); | |
| 1545 | + array[i] = le16_to_cpu(barray[i]); | |
| 1526 | 1546 | #endif |
| 1527 | 1547 | if (s->subdev_flags & SDF_LSAMPL) |
| 1528 | 1548 | larray[i] += devpriv->ai_offset[chan_index]; |
| @@ -2574,6 +2594,9 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, · 1045 unmodified lines | ||
| 2574 | 2594 | unsigned int nsamples = comedi_bytes_to_samples(s, num_bytes); |
| 2575 | 2595 | unsigned short *array = data; |
| 2576 | 2596 | unsigned int i; |
| 2597 | +#ifdef PCIDMA | |
| 2598 | + __le16 buf, *barray = data; | |
| 2599 | +#endif | |
| 2577 | 2600 | |
| 2578 | 2601 | for (i = 0; i < nsamples; i++) { |
| 2579 | 2602 | unsigned int range = CR_RANGE(cmd->chanlist[chan_index]); |
| @@ -2586,10 +2609,11 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, · 6 unmodified lines | ||
| 2586 | 2609 | if (comedi_range_is_bipolar(s, range)) |
| 2587 | 2610 | val = comedi_offset_munge(s, val); |
| 2588 | 2611 | #ifdef PCIDMA |
| 2589 | − val = cpu_to_le16(val); | |
| 2590 | −#endif | |
| 2612 | + buf = cpu_to_le16(val); | |
| 2613 | + barray[i] = buf; | |
| 2614 | +#else | |
| 2591 | 2615 | array[i] = val; |
| 2592 | − | |
| 2616 | +#endif | |
| 2593 | 2617 | chan_index++; |
| 2594 | 2618 | chan_index %= cmd->chanlist_len; |
| 2595 | 2619 | } |
| @@ -1,4 +1,5 @@ | ||
| 1 | −/* plx9080.h | |
| 1 | +/* | |
| 2 | + * plx9080.h | |
| 2 | 3 | * |
| 3 | 4 | * Copyright (C) 2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> |
| 4 | 5 | * |
| @@ -33,8 +34,10 @@ struct plx_dma_desc { · 28 unmodified lines | ||
| 33 | 34 | __le32 local_start_addr; |
| 34 | 35 | /* transfer_size is in bytes, only first 23 bits of register are used */ |
| 35 | 36 | __le32 transfer_size; |
| 36 | − /* address of next descriptor (quad word aligned), plus some | |
| 37 | − * additional bits (see PLX_DMA0_DESCRIPTOR_REG) */ | |
| 37 | + /* | |
| 38 | + * address of next descriptor (quad word aligned), plus some | |
| 39 | + * additional bits (see PLX_DMA0_DESCRIPTOR_REG) | |
| 40 | + */ | |
| 38 | 41 | __le32 next; |
| 39 | 42 | }; |
| 40 | 43 | |
| @@ -46,23 +49,31 @@ struct plx_dma_desc { · 5 unmodified lines | ||
| 46 | 49 | ** |
| 47 | 50 | **********************************************************************/ |
| 48 | 51 | |
| 49 | −#define PLX_LAS0RNG_REG 0x0000 /* L, Local Addr Space 0 Range Register */ | |
| 50 | −#define PLX_LAS1RNG_REG 0x00f0 /* L, Local Addr Space 1 Range Register */ | |
| 52 | +/* L, Local Addr Space 0 Range Register */ | |
| 53 | +#define PLX_LAS0RNG_REG 0x0000 | |
| 54 | +/* L, Local Addr Space 1 Range Register */ | |
| 55 | +#define PLX_LAS1RNG_REG 0x00f0 | |
| 51 | 56 | #define LRNG_IO 0x00000001 /* Map to: 1=I/O, 0=Mem */ |
| 52 | 57 | #define LRNG_ANY32 0x00000000 /* Locate anywhere in 32 bit */ |
| 53 | 58 | #define LRNG_LT1MB 0x00000002 /* Locate in 1st meg */ |
| 54 | 59 | #define LRNG_ANY64 0x00000004 /* Locate anywhere in 64 bit */ |
| 55 | −#define LRNG_MEM_MASK 0xfffffff0 /* bits that specify range for memory io */ | |
| 56 | −#define LRNG_IO_MASK 0xfffffffa /* bits that specify range for normal io */ | |
| 57 | − | |
| 58 | −#define PLX_LAS0MAP_REG 0x0004 /* L, Local Addr Space 0 Remap Register */ | |
| 59 | −#define PLX_LAS1MAP_REG 0x00f4 /* L, Local Addr Space 1 Remap Register */ | |
| 60 | +/* bits that specify range for memory io */ | |
| 61 | +#define LRNG_MEM_MASK 0xfffffff0 | |
| 62 | +/* bits that specify range for normal io */ | |
| 63 | +#define LRNG_IO_MASK 0xfffffffa | |
| 64 | +/* L, Local Addr Space 0 Remap Register */ | |
| 65 | +#define PLX_LAS0MAP_REG 0x0004 | |
| 66 | +/* L, Local Addr Space 1 Remap Register */ | |
| 67 | +#define PLX_LAS1MAP_REG 0x00f4 | |
| 60 | 68 | #define LMAP_EN 0x00000001 /* Enable slave decode */ |
| 61 | −#define LMAP_MEM_MASK 0xfffffff0 /* bits that specify decode for memory io */ | |
| 62 | −#define LMAP_IO_MASK 0xfffffffa /* bits that specify decode bits for normal io */ | |
| 69 | +/* bits that specify decode for memory io */ | |
| 70 | +#define LMAP_MEM_MASK 0xfffffff0 | |
| 71 | +/* bits that specify decode bits for normal io */ | |
| 72 | +#define LMAP_IO_MASK 0xfffffffa | |
| 63 | 73 | |
| 64 | −/* Mode/Arbitration Register. | |
| 65 | −*/ | |
| 74 | +/* | |
| 75 | + * Mode/Arbitration Register. | |
| 76 | + */ | |
| 66 | 77 | #define PLX_MARB_REG 0x8 /* L, Local Arbitration Register */ |
| 67 | 78 | #define PLX_DMAARB_REG 0xac |
| 68 | 79 | enum marb_bits { |
| @@ -72,35 +83,45 @@ enum marb_bits { · 3 unmodified lines | ||
| 72 | 83 | MARB_LPEN = 0x00020000, /* Pause Timer Enable */ |
| 73 | 84 | MARB_BREQ = 0x00040000, /* Local Bus BREQ Enable */ |
| 74 | 85 | MARB_DMA_PRIORITY_MASK = 0x00180000, |
| 75 | − MARB_LBDS_GIVE_UP_BUS_MODE = 0x00200000, /* local bus direct slave give up bus mode */ | |
| 76 | − MARB_DS_LLOCK_ENABLE = 0x00400000, /* direct slave LLOCKo# enable */ | |
| 86 | + /* local bus direct slave give up bus mode */ | |
| 87 | + MARB_LBDS_GIVE_UP_BUS_MODE = 0x00200000, | |
| 88 | + /* direct slave LLOCKo# enable */ | |
| 89 | + MARB_DS_LLOCK_ENABLE = 0x00400000, | |
| 77 | 90 | MARB_PCI_REQUEST_MODE = 0x00800000, |
| 78 | 91 | MARB_PCIv21_MODE = 0x01000000, /* pci specification v2.1 mode */ |
| 79 | 92 | MARB_PCI_READ_NO_WRITE_MODE = 0x02000000, |
| 80 | 93 | MARB_PCI_READ_WITH_WRITE_FLUSH_MODE = 0x04000000, |
| 81 | − MARB_GATE_TIMER_WITH_BREQ = 0x08000000, /* gate local bus latency timer with BREQ */ | |
| 94 | + /* gate local bus latency timer with BREQ */ | |
| 95 | + MARB_GATE_TIMER_WITH_BREQ = 0x08000000, | |
| 82 | 96 | MARB_PCI_READ_NO_FLUSH_MODE = 0x10000000, |
| 83 | 97 | MARB_USE_SUBSYSTEM_IDS = 0x20000000, |
| 84 | 98 | }; |
| 85 | 99 | |
| 86 | 100 | #define PLX_BIGEND_REG 0xc |
| 87 | 101 | enum bigend_bits { |
| 88 | − BIGEND_CONFIG = 0x1, /* use big endian ordering for configuration register accesses */ | |
| 102 | + /* use big endian ordering for configuration register accesses */ | |
| 103 | + BIGEND_CONFIG = 0x1, | |
| 89 | 104 | BIGEND_DIRECT_MASTER = 0x2, |
| 90 | 105 | BIGEND_DIRECT_SLAVE_LOCAL0 = 0x4, |
| 91 | 106 | BIGEND_ROM = 0x8, |
| 92 | − BIGEND_BYTE_LANE = 0x10, /* use byte lane consisting of most significant bits instead of least significant */ | |
| 107 | + /* | |
| 108 | + * use byte lane consisting of most significant bits instead of | |
| 109 | + * least significant | |
| 110 | + */ | |
| 111 | + BIGEND_BYTE_LANE = 0x10, | |
| 93 | 112 | BIGEND_DIRECT_SLAVE_LOCAL1 = 0x20, |
| 94 | 113 | BIGEND_DMA1 = 0x40, |
| 95 | 114 | BIGEND_DMA0 = 0x80, |
| 96 | 115 | }; |
| 97 | 116 | |
| 98 | −/* Note: The Expansion ROM stuff is only relevant to the PC environment. | |
| 117 | +/* | |
| 118 | +** Note: The Expansion ROM stuff is only relevant to the PC environment. | |
| 99 | 119 | ** This expansion ROM code is executed by the host CPU at boot time. |
| 100 | 120 | ** For this reason no bit definitions are provided here. |
| 101 | −*/ | |
| 121 | + */ | |
| 102 | 122 | #define PLX_ROMRNG_REG 0x0010 /* L, Expn ROM Space Range Register */ |
| 103 | −#define PLX_ROMMAP_REG 0x0014 /* L, Local Addr Space Range Register */ | |
| 123 | +/* L, Local Addr Space Range Register */ | |
| 124 | +#define PLX_ROMMAP_REG 0x0014 | |
| 104 | 125 | |
| 105 | 126 | #define PLX_REGION0_REG 0x0018 /* L, Local Bus Region 0 Descriptor */ |
| 106 | 127 | #define RGN_WIDTH 0x00000002 /* Local bus width bits */ |
| @@ -190,7 +211,8 @@ enum bigend_bits { · 83 unmodified lines | ||
| 190 | 211 | #define ICS_TA_DMA0 0x02000000 /* Target Abort - DMA #0 */ |
| 191 | 212 | #define ICS_TA_DMA1 0x04000000 /* Target Abort - DMA #1 */ |
| 192 | 213 | #define ICS_TA_RA 0x08000000 /* Target Abort - Retry Timeout */ |
| 193 | −#define ICS_MBIA(x) (0x10000000 << ((x) & 0x3)) /* mailbox x is active */ | |
| 214 | +/* mailbox x is active */ | |
| 215 | +#define ICS_MBIA(x) (0x10000000 << ((x) & 0x3)) | |
| 194 | 216 | |
| 195 | 217 | #define PLX_CONTROL_REG 0x006C /* L, EEPROM Cntl & PCI Cmd Codes */ |
| 196 | 218 | #define CTL_RDMA 0x0000000E /* DMA Read Command */ |
| @@ -221,28 +243,38 @@ enum bigend_bits { · 24 unmodified lines | ||
| 221 | 243 | #define PLX_EN_BTERM_BIT 0x80 /* enable BTERM# input */ |
| 222 | 244 | #define PLX_DMA_LOCAL_BURST_EN_BIT 0x100 /* enable local burst mode */ |
| 223 | 245 | #define PLX_EN_CHAIN_BIT 0x200 /* enables chaining */ |
| 224 | −#define PLX_EN_DMA_DONE_INTR_BIT 0x400 /* enables interrupt on dma done */ | |
| 225 | −#define PLX_LOCAL_ADDR_CONST_BIT 0x800 /* hold local address constant (don't increment) */ | |
| 226 | −#define PLX_DEMAND_MODE_BIT 0x1000 /* enables demand-mode for dma transfer */ | |
| 246 | +/* enables interrupt on dma done */ | |
| 247 | +#define PLX_EN_DMA_DONE_INTR_BIT 0x400 | |
| 248 | +/* hold local address constant (don't increment) */ | |
| 249 | +#define PLX_LOCAL_ADDR_CONST_BIT 0x800 | |
| 250 | +/* enables demand-mode for dma transfer */ | |
| 251 | +#define PLX_DEMAND_MODE_BIT 0x1000 | |
| 227 | 252 | #define PLX_EOT_ENABLE_BIT 0x4000 |
| 228 | 253 | #define PLX_STOP_MODE_BIT 0x8000 |
| 229 | −#define PLX_DMA_INTR_PCI_BIT 0x20000 /* routes dma interrupt to pci bus (instead of local bus) */ | |
| 254 | +/* routes dma interrupt to pci bus (instead of local bus) */ | |
| 255 | +#define PLX_DMA_INTR_PCI_BIT 0x20000 | |
| 230 | 256 | |
| 231 | −#define PLX_DMA0_PCI_ADDRESS_REG 0x84 /* pci address that dma transfers start at */ | |
| 257 | +/* pci address that dma transfers start at */ | |
| 258 | +#define PLX_DMA0_PCI_ADDRESS_REG 0x84 | |
| 232 | 259 | #define PLX_DMA1_PCI_ADDRESS_REG 0x98 |
| 233 | 260 | |
| 234 | −#define PLX_DMA0_LOCAL_ADDRESS_REG 0x88 /* local address that dma transfers start at */ | |
| 261 | +/* local address that dma transfers start at */ | |
| 262 | +#define PLX_DMA0_LOCAL_ADDRESS_REG 0x88 | |
| 235 | 263 | #define PLX_DMA1_LOCAL_ADDRESS_REG 0x9c |
| 236 | 264 | |
| 237 | −#define PLX_DMA0_TRANSFER_SIZE_REG 0x8c /* number of bytes to transfer (first 23 bits) */ | |
| 265 | +/* number of bytes to transfer (first 23 bits) */ | |
| 266 | +#define PLX_DMA0_TRANSFER_SIZE_REG 0x8c | |
| 238 | 267 | #define PLX_DMA1_TRANSFER_SIZE_REG 0xa0 |
| 239 | 268 | |
| 240 | 269 | #define PLX_DMA0_DESCRIPTOR_REG 0x90 /* descriptor pointer register */ |
| 241 | 270 | #define PLX_DMA1_DESCRIPTOR_REG 0xa4 |
| 242 | −#define PLX_DESC_IN_PCI_BIT 0x1 /* descriptor is located in pci space (not local space) */ | |
| 271 | +/* descriptor is located in pci space (not local space) */ | |
| 272 | +#define PLX_DESC_IN_PCI_BIT 0x1 | |
| 243 | 273 | #define PLX_END_OF_CHAIN_BIT 0x2 /* end of chain bit */ |
| 244 | −#define PLX_INTR_TERM_COUNT 0x4 /* interrupt when this descriptor's transfer is finished */ | |
| 245 | −#define PLX_XFER_LOCAL_TO_PCI 0x8 /* transfer from local to pci bus (not pci to local) */ | |
| 274 | +/* interrupt when this descriptor's transfer is finished */ | |
| 275 | +#define PLX_INTR_TERM_COUNT 0x4 | |
| 276 | +/* transfer from local to pci bus (not pci to local) */ | |
| 277 | +#define PLX_XFER_LOCAL_TO_PCI 0x8 | |
| 246 | 278 | |
| 247 | 279 | #define PLX_DMA0_CS_REG 0xa8 /* command status register */ |
| 248 | 280 | #define PLX_DMA1_CS_REG 0xa9 |
| @@ -288,10 +320,11 @@ enum bigend_bits { · 39 unmodified lines | ||
| 288 | 320 | #define MBX_STS_PCIRESET 0x00000100 /* Host issued PCI reset request */ |
| 289 | 321 | #define MBX_STS_BUSY 0x00000080 /* PUTS is in progress */ |
| 290 | 322 | #define MBX_STS_ERROR 0x00000040 /* PUTS has failed */ |
| 291 | −#define MBX_STS_RESERVED 0x000000c0 /* Undefined -> status in transition. | |
| 292 | − We are in process of changing | |
| 293 | − bits; we SET Error bit before | |
| 294 | − RESET of Busy bit */ | |
| 323 | +/* | |
| 324 | + * Undefined -> status in transition. We are in process of changing bits; | |
| 325 | + * we SET Error bit before RESET of Busy bit | |
| 326 | + */ | |
| 327 | +#define MBX_STS_RESERVED 0x000000c0 | |
| 295 | 328 | |
| 296 | 329 | #define MBX_RESERVED_5 0x00000020 /* FYI: reserved/unused bit */ |
| 297 | 330 | #define MBX_RESERVED_4 0x00000010 /* FYI: reserved/unused bit */ |
| @@ -320,12 +353,12 @@ enum bigend_bits { · 22 unmodified lines | ||
| 320 | 353 | #define MBX_CMD_BSWAP_0 0x8c000000 /* use scheme 0 */ |
| 321 | 354 | #define MBX_CMD_BSWAP_1 0x8c000001 /* use scheme 1 */ |
| 322 | 355 | |
| 323 | −#define MBX_CMD_SETHMS 0x8d000000 /* setup host memory access window | |
| 324 | − size */ | |
| 325 | −#define MBX_CMD_SETHBA 0x8e000000 /* setup host memory access base | |
| 326 | − address */ | |
| 327 | −#define MBX_CMD_MGO 0x8f000000 /* perform memory setup and continue | |
| 328 | − (IE. Done) */ | |
| 356 | +/* setup host memory access window size */ | |
| 357 | +#define MBX_CMD_SETHMS 0x8d000000 | |
| 358 | +/* setup host memory access base address */ | |
| 359 | +#define MBX_CMD_SETHBA 0x8e000000 | |
| 360 | +/* perform memory setup and continue (IE. Done) */ | |
| 361 | +#define MBX_CMD_MGO 0x8f000000 | |
| 329 | 362 | #define MBX_CMD_NOOP 0xFF000000 /* dummy, illegal command */ |
| 330 | 363 | |
| 331 | 364 | /*****************************************/ |
| @@ -348,7 +381,8 @@ enum bigend_bits { · 16 unmodified lines | ||
| 348 | 381 | /***************************************/ |
| 349 | 382 | |
| 350 | 383 | #define MBX_BTYPE_MASK 0x0000ffff /* PUTS Board Type Register */ |
| 351 | −#define MBX_BTYPE_FAMILY_MASK 0x0000ff00 /* PUTS Board Family Register */ | |
| 384 | +/* PUTS Board Family Register */ | |
| 385 | +#define MBX_BTYPE_FAMILY_MASK 0x0000ff00 | |
| 352 | 386 | #define MBX_BTYPE_SUBTYPE_MASK 0x000000ff /* PUTS Board Subtype */ |
| 353 | 387 | |
| 354 | 388 | #define MBX_BTYPE_PLX9060 0x00000100 /* PLX family type */ |
| @@ -378,12 +412,12 @@ enum bigend_bits { · 23 unmodified lines | ||
| 378 | 412 | |
| 379 | 413 | /* system allocates this many bytes for address mapping mailbox space */ |
| 380 | 414 | #define MBX_ADDR_SPACE_360 0x80 /* wanXL100s/200/400 */ |
| 381 | −#define MBX_ADDR_MASK_360 (MBX_ADDR_SPACE_360-1) | |
| 415 | +#define MBX_ADDR_MASK_360 (MBX_ADDR_SPACE_360 - 1) | |
| 382 | 416 | |
| 383 | 417 | static inline int plx9080_abort_dma(void __iomem *iobase, unsigned int channel) |
| 384 | 418 | { |
| 385 | 419 | void __iomem *dma_cs_addr; |
| 386 | − uint8_t dma_status; | |
| 420 | + u8 dma_status; | |
| 387 | 421 | const int timeout = 10000; |
| 388 | 422 | unsigned int i; |
| 389 | 423 | |
| @@ -37,7 +37,6 @@ · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | #include <linux/module.h> |
| 39 | 39 | #include "../comedidev.h" |
| 40 | −#include <asm/byteorder.h> | |
| 41 | 40 | |
| 42 | 41 | /* |
| 43 | 42 | * Register I/O map |
| @@ -84,7 +83,92 @@ · 40 unmodified lines | ||
| 84 | 83 | #define S526_GPCT_LSB_REG(x) (0x12 + ((x) * 8)) |
| 85 | 84 | #define S526_GPCT_MSB_REG(x) (0x14 + ((x) * 8)) |
| 86 | 85 | #define S526_GPCT_MODE_REG(x) (0x16 + ((x) * 8)) |
| 86 | +#define S526_GPCT_MODE_COUT_SRC(x) ((x) << 0) | |
| 87 | +#define S526_GPCT_MODE_COUT_SRC_MASK S526_GPCT_MODE_COUT_SRC(0x1) | |
| 88 | +#define S526_GPCT_MODE_COUT_SRC_RCAP S526_GPCT_MODE_COUT_SRC(0) | |
| 89 | +#define S526_GPCT_MODE_COUT_SRC_RTGL S526_GPCT_MODE_COUT_SRC(1) | |
| 90 | +#define S526_GPCT_MODE_COUT_POL(x) ((x) << 1) | |
| 91 | +#define S526_GPCT_MODE_COUT_POL_MASK S526_GPCT_MODE_COUT_POL(0x1) | |
| 92 | +#define S526_GPCT_MODE_COUT_POL_NORM S526_GPCT_MODE_COUT_POL(0) | |
| 93 | +#define S526_GPCT_MODE_COUT_POL_INV S526_GPCT_MODE_COUT_POL(1) | |
| 94 | +#define S526_GPCT_MODE_AUTOLOAD(x) ((x) << 2) | |
| 95 | +#define S526_GPCT_MODE_AUTOLOAD_MASK S526_GPCT_MODE_AUTOLOAD(0x7) | |
| 96 | +#define S526_GPCT_MODE_AUTOLOAD_NONE S526_GPCT_MODE_AUTOLOAD(0) | |
| 97 | +/* these 3 bits can be OR'ed */ | |
| 98 | +#define S526_GPCT_MODE_AUTOLOAD_RO S526_GPCT_MODE_AUTOLOAD(0x1) | |
| 99 | +#define S526_GPCT_MODE_AUTOLOAD_IXFALL S526_GPCT_MODE_AUTOLOAD(0x2) | |
| 100 | +#define S526_GPCT_MODE_AUTOLOAD_IXRISE S526_GPCT_MODE_AUTOLOAD(0x4) | |
| 101 | +#define S526_GPCT_MODE_HWCTEN_SRC(x) ((x) << 5) | |
| 102 | +#define S526_GPCT_MODE_HWCTEN_SRC_MASK S526_GPCT_MODE_HWCTEN_SRC(0x3) | |
| 103 | +#define S526_GPCT_MODE_HWCTEN_SRC_CEN S526_GPCT_MODE_HWCTEN_SRC(0) | |
| 104 | +#define S526_GPCT_MODE_HWCTEN_SRC_IX S526_GPCT_MODE_HWCTEN_SRC(1) | |
| 105 | +#define S526_GPCT_MODE_HWCTEN_SRC_IXRF S526_GPCT_MODE_HWCTEN_SRC(2) | |
| 106 | +#define S526_GPCT_MODE_HWCTEN_SRC_NRCAP S526_GPCT_MODE_HWCTEN_SRC(3) | |
| 107 | +#define S526_GPCT_MODE_CTEN_CTRL(x) ((x) << 7) | |
| 108 | +#define S526_GPCT_MODE_CTEN_CTRL_MASK S526_GPCT_MODE_CTEN_CTRL(0x3) | |
| 109 | +#define S526_GPCT_MODE_CTEN_CTRL_DIS S526_GPCT_MODE_CTEN_CTRL(0) | |
| 110 | +#define S526_GPCT_MODE_CTEN_CTRL_ENA S526_GPCT_MODE_CTEN_CTRL(1) | |
| 111 | +#define S526_GPCT_MODE_CTEN_CTRL_HW S526_GPCT_MODE_CTEN_CTRL(2) | |
| 112 | +#define S526_GPCT_MODE_CTEN_CTRL_INVHW S526_GPCT_MODE_CTEN_CTRL(3) | |
| 113 | +#define S526_GPCT_MODE_CLK_SRC(x) ((x) << 9) | |
| 114 | +#define S526_GPCT_MODE_CLK_SRC_MASK S526_GPCT_MODE_CLK_SRC(0x3) | |
| 115 | +/* if count direction control set to quadrature */ | |
| 116 | +#define S526_GPCT_MODE_CLK_SRC_QUADX1 S526_GPCT_MODE_CLK_SRC(0) | |
| 117 | +#define S526_GPCT_MODE_CLK_SRC_QUADX2 S526_GPCT_MODE_CLK_SRC(1) | |
| 118 | +#define S526_GPCT_MODE_CLK_SRC_QUADX4 S526_GPCT_MODE_CLK_SRC(2) | |
| 119 | +#define S526_GPCT_MODE_CLK_SRC_QUADX4_ S526_GPCT_MODE_CLK_SRC(3) | |
| 120 | +/* if count direction control set to software control */ | |
| 121 | +#define S526_GPCT_MODE_CLK_SRC_ARISE S526_GPCT_MODE_CLK_SRC(0) | |
| 122 | +#define S526_GPCT_MODE_CLK_SRC_AFALL S526_GPCT_MODE_CLK_SRC(1) | |
| 123 | +#define S526_GPCT_MODE_CLK_SRC_INT S526_GPCT_MODE_CLK_SRC(2) | |
| 124 | +#define S526_GPCT_MODE_CLK_SRC_INTHALF S526_GPCT_MODE_CLK_SRC(3) | |
| 125 | +#define S526_GPCT_MODE_CT_DIR(x) ((x) << 11) | |
| 126 | +#define S526_GPCT_MODE_CT_DIR_MASK S526_GPCT_MODE_CT_DIR(0x1) | |
| 127 | +/* if count direction control set to software control */ | |
| 128 | +#define S526_GPCT_MODE_CT_DIR_UP S526_GPCT_MODE_CT_DIR(0) | |
| 129 | +#define S526_GPCT_MODE_CT_DIR_DOWN S526_GPCT_MODE_CT_DIR(1) | |
| 130 | +#define S526_GPCT_MODE_CTDIR_CTRL(x) ((x) << 12) | |
| 131 | +#define S526_GPCT_MODE_CTDIR_CTRL_MASK S526_GPCT_MODE_CTDIR_CTRL(0x1) | |
| 132 | +#define S526_GPCT_MODE_CTDIR_CTRL_QUAD S526_GPCT_MODE_CTDIR_CTRL(0) | |
| 133 | +#define S526_GPCT_MODE_CTDIR_CTRL_SOFT S526_GPCT_MODE_CTDIR_CTRL(1) | |
| 134 | +#define S526_GPCT_MODE_LATCH_CTRL(x) ((x) << 13) | |
| 135 | +#define S526_GPCT_MODE_LATCH_CTRL_MASK S526_GPCT_MODE_LATCH_CTRL(0x1) | |
| 136 | +#define S526_GPCT_MODE_LATCH_CTRL_READ S526_GPCT_MODE_LATCH_CTRL(0) | |
| 137 | +#define S526_GPCT_MODE_LATCH_CTRL_EVENT S526_GPCT_MODE_LATCH_CTRL(1) | |
| 138 | +#define S526_GPCT_MODE_PR_SELECT(x) ((x) << 14) | |
| 139 | +#define S526_GPCT_MODE_PR_SELECT_MASK S526_GPCT_MODE_PR_SELECT(0x1) | |
| 140 | +#define S526_GPCT_MODE_PR_SELECT_PR0 S526_GPCT_MODE_PR_SELECT(0) | |
| 141 | +#define S526_GPCT_MODE_PR_SELECT_PR1 S526_GPCT_MODE_PR_SELECT(1) | |
| 142 | +/* Control/Status - R = readable, W = writeable, C = write 1 to clear */ | |
| 87 | 143 | #define S526_GPCT_CTRL_REG(x) (0x18 + ((x) * 8)) |
| 144 | +#define S526_GPCT_CTRL_EV_STATUS(x) ((x) << 0) /* RC */ | |
| 145 | +#define S526_GPCT_CTRL_EV_STATUS_MASK S526_GPCT_EV_STATUS(0xf) | |
| 146 | +#define S526_GPCT_CTRL_EV_STATUS_NONE S526_GPCT_EV_STATUS(0) | |
| 147 | +/* these 4 bits can be OR'ed */ | |
| 148 | +#define S526_GPCT_CTRL_EV_STATUS_ECAP S526_GPCT_EV_STATUS(0x1) | |
| 149 | +#define S526_GPCT_CTRL_EV_STATUS_ICAPN S526_GPCT_EV_STATUS(0x2) | |
| 150 | +#define S526_GPCT_CTRL_EV_STATUS_ICAPP S526_GPCT_EV_STATUS(0x4) | |
| 151 | +#define S526_GPCT_CTRL_EV_STATUS_RCAP S526_GPCT_EV_STATUS(0x8) | |
| 152 | +#define S526_GPCT_CTRL_COUT_STATUS BIT(4) /* R */ | |
| 153 | +#define S526_GPCT_CTRL_INDEX_STATUS BIT(5) /* R */ | |
| 154 | +#define S525_GPCT_CTRL_INTEN(x) ((x) << 6) /* W */ | |
| 155 | +#define S525_GPCT_CTRL_INTEN_MASK S526_GPCT_CTRL_INTEN(0xf) | |
| 156 | +#define S525_GPCT_CTRL_INTEN_NONE S526_GPCT_CTRL_INTEN(0) | |
| 157 | +/* these 4 bits can be OR'ed */ | |
| 158 | +#define S525_GPCT_CTRL_INTEN_ERROR S526_GPCT_CTRL_INTEN(0x1) | |
| 159 | +#define S525_GPCT_CTRL_INTEN_IXFALL S526_GPCT_CTRL_INTEN(0x2) | |
| 160 | +#define S525_GPCT_CTRL_INTEN_IXRISE S526_GPCT_CTRL_INTEN(0x4) | |
| 161 | +#define S525_GPCT_CTRL_INTEN_RO S526_GPCT_CTRL_INTEN(0x8) | |
| 162 | +#define S525_GPCT_CTRL_LATCH_SEL(x) ((x) << 10) /* W */ | |
| 163 | +#define S525_GPCT_CTRL_LATCH_SEL_MASK S526_GPCT_CTRL_LATCH_SEL(0x7) | |
| 164 | +#define S525_GPCT_CTRL_LATCH_SEL_NONE S526_GPCT_CTRL_LATCH_SEL(0) | |
| 165 | +/* these 3 bits can be OR'ed */ | |
| 166 | +#define S525_GPCT_CTRL_LATCH_SEL_IXFALL S526_GPCT_CTRL_LATCH_SEL(0x1) | |
| 167 | +#define S525_GPCT_CTRL_LATCH_SEL_IXRISE S526_GPCT_CTRL_LATCH_SEL(0x2) | |
| 168 | +#define S525_GPCT_CTRL_LATCH_SEL_ITIMER S526_GPCT_CTRL_LATCH_SEL(0x4) | |
| 169 | +#define S525_GPCT_CTRL_CT_ARM BIT(13) /* W */ | |
| 170 | +#define S525_GPCT_CTRL_CT_LOAD BIT(14) /* W */ | |
| 171 | +#define S526_GPCT_CTRL_CT_RESET BIT(15) /* W */ | |
| 88 | 172 | #define S526_EEPROM_DATA_REG 0x32 |
| 89 | 173 | #define S526_EEPROM_CTRL_REG 0x34 |
| 90 | 174 | #define S526_EEPROM_CTRL_ADDR(x) (((x) & 0x3f) << 3) |
| @@ -92,41 +176,6 @@ · 1 unmodified line | ||
| 92 | 176 | #define S526_EEPROM_CTRL_READ S526_EEPROM_CTRL(2) |
| 93 | 177 | #define S526_EEPROM_CTRL_START BIT(0) |
| 94 | 178 | |
| 95 | −struct counter_mode_register_t { | |
| 96 | −#if defined(__LITTLE_ENDIAN_BITFIELD) | |
| 97 | − unsigned short coutSource:1; | |
| 98 | − unsigned short coutPolarity:1; | |
| 99 | − unsigned short autoLoadResetRcap:3; | |
| 100 | − unsigned short hwCtEnableSource:2; | |
| 101 | − unsigned short ctEnableCtrl:2; | |
| 102 | − unsigned short clockSource:2; | |
| 103 | − unsigned short countDir:1; | |
| 104 | − unsigned short countDirCtrl:1; | |
| 105 | − unsigned short outputRegLatchCtrl:1; | |
| 106 | − unsigned short preloadRegSel:1; | |
| 107 | − unsigned short reserved:1; | |
| 108 | − #elif defined(__BIG_ENDIAN_BITFIELD) | |
| 109 | − unsigned short reserved:1; | |
| 110 | − unsigned short preloadRegSel:1; | |
| 111 | − unsigned short outputRegLatchCtrl:1; | |
| 112 | − unsigned short countDirCtrl:1; | |
| 113 | − unsigned short countDir:1; | |
| 114 | − unsigned short clockSource:2; | |
| 115 | − unsigned short ctEnableCtrl:2; | |
| 116 | − unsigned short hwCtEnableSource:2; | |
| 117 | − unsigned short autoLoadResetRcap:3; | |
| 118 | − unsigned short coutPolarity:1; | |
| 119 | − unsigned short coutSource:1; | |
| 120 | −#else | |
| 121 | −#error Unknown bit field order | |
| 122 | −#endif | |
| 123 | −}; | |
| 124 | − | |
| 125 | −union cmReg { | |
| 126 | − struct counter_mode_register_t reg; | |
| 127 | − unsigned short value; | |
| 128 | −}; | |
| 129 | − | |
| 130 | 179 | struct s526_private { |
| 131 | 180 | unsigned int gpct_config[4]; |
| 132 | 181 | unsigned short ai_ctrl; |
| @@ -174,7 +223,6 @@ static int s526_gpct_insn_config(struct comedi_device *dev, · 41 unmodified lines | ||
| 174 | 223 | struct s526_private *devpriv = dev->private; |
| 175 | 224 | unsigned int chan = CR_CHAN(insn->chanspec); |
| 176 | 225 | unsigned int val; |
| 177 | − union cmReg cmReg; | |
| 178 | 226 | |
| 179 | 227 | /* |
| 180 | 228 | * Check what type of Counter the user requested |
| @@ -192,28 +240,31 @@ static int s526_gpct_insn_config(struct comedi_device *dev, · 11 unmodified lines | ||
| 192 | 240 | |
| 193 | 241 | #if 1 |
| 194 | 242 | /* Set Counter Mode Register */ |
| 195 | − cmReg.value = data[1] & 0xffff; | |
| 196 | − outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 243 | + val = data[1] & 0xffff; | |
| 244 | + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 197 | 245 | |
| 198 | 246 | /* Reset the counter if it is software preload */ |
| 199 | − if (cmReg.reg.autoLoadResetRcap == 0) { | |
| 247 | + if ((val & S526_GPCT_MODE_AUTOLOAD_MASK) == | |
| 248 | + S526_GPCT_MODE_AUTOLOAD_NONE) { | |
| 200 | 249 | /* Reset the counter */ |
| 201 | − outw(0x8000, dev->iobase + S526_GPCT_CTRL_REG(chan)); | |
| 202 | − /* Load the counter from PR0 | |
| 203 | − * outw(0x4000, dev->iobase + S526_GPCT_CTRL_REG(chan)); | |
| 250 | + outw(S526_GPCT_CTRL_CT_RESET, | |
| 251 | + dev->iobase + S526_GPCT_CTRL_REG(chan)); | |
| 252 | + /* | |
| 253 | + * Load the counter from PR0 | |
| 254 | + * outw(S526_GPCT_CTRL_CT_LOAD, | |
| 255 | + * dev->iobase + S526_GPCT_CTRL_REG(chan)); | |
| 204 | 256 | */ |
| 205 | 257 | } |
| 206 | 258 | #else |
| 207 | − /* 0 quadrature, 1 software control */ | |
| 208 | − cmReg.reg.countDirCtrl = 0; | |
| 259 | + val = S526_GPCT_MODE_CTDIR_CTRL_QUAD; | |
| 209 | 260 | |
| 210 | 261 | /* data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4 */ |
| 211 | 262 | if (data[1] == GPCT_X2) |
| 212 | − cmReg.reg.clockSource = 1; | |
| 263 | + val |= S526_GPCT_MODE_CLK_SRC_QUADX2; | |
| 213 | 264 | else if (data[1] == GPCT_X4) |
| 214 | − cmReg.reg.clockSource = 2; | |
| 265 | + val |= S526_GPCT_MODE_CLK_SRC_QUADX4; | |
| 215 | 266 | else |
| 216 | − cmReg.reg.clockSource = 0; | |
| 267 | + val |= S526_GPCT_MODE_CLK_SRC_QUADX1; | |
| 217 | 268 | |
| 218 | 269 | /* When to take into account the indexpulse: */ |
| 219 | 270 | /* |
| @@ -224,13 +275,14 @@ static int s526_gpct_insn_config(struct comedi_device *dev, · 4 unmodified lines | ||
| 224 | 275 | * } |
| 225 | 276 | */ |
| 226 | 277 | /* Take into account the index pulse? */ |
| 227 | − if (data[3] == GPCT_RESET_COUNTER_ON_INDEX) | |
| 278 | + if (data[3] == GPCT_RESET_COUNTER_ON_INDEX) { | |
| 228 | 279 | /* Auto load with INDEX^ */ |
| 229 | − cmReg.reg.autoLoadResetRcap = 4; | |
| 280 | + val |= S526_GPCT_MODE_AUTOLOAD_IXRISE; | |
| 281 | + } | |
| 230 | 282 | |
| 231 | 283 | /* Set Counter Mode Register */ |
| 232 | − cmReg.value = data[1] & 0xffff; | |
| 233 | − outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 284 | + val = data[1] & 0xffff; | |
| 285 | + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 234 | 286 | |
| 235 | 287 | /* Load the pre-load register */ |
| 236 | 288 | s526_gpct_write(dev, chan, data[2]); |
| @@ -241,11 +293,14 @@ static int s526_gpct_insn_config(struct comedi_device *dev, · 4 unmodified lines | ||
| 241 | 293 | dev->iobase + S526_GPCT_CTRL_REG(chan)); |
| 242 | 294 | |
| 243 | 295 | /* Reset the counter if it is software preload */ |
| 244 | − if (cmReg.reg.autoLoadResetRcap == 0) { | |
| 296 | + if ((val & S526_GPCT_MODE_AUTOLOAD_MASK) == | |
| 297 | + S526_GPCT_MODE_AUTOLOAD_NONE) { | |
| 245 | 298 | /* Reset the counter */ |
| 246 | − outw(0x8000, dev->iobase + S526_GPCT_CTRL_REG(chan)); | |
| 299 | + outw(S526_GPCT_CTRL_CT_RESET, | |
| 300 | + dev->iobase + S526_GPCT_CTRL_REG(chan)); | |
| 247 | 301 | /* Load the counter from PR0 */ |
| 248 | − outw(0x4000, dev->iobase + S526_GPCT_CTRL_REG(chan)); | |
| 302 | + outw(S526_GPCT_CTRL_CT_LOAD, | |
| 303 | + dev->iobase + S526_GPCT_CTRL_REG(chan)); | |
| 249 | 304 | } |
| 250 | 305 | #endif |
| 251 | 306 | break; |
| @@ -261,17 +316,21 @@ static int s526_gpct_insn_config(struct comedi_device *dev, · 9 unmodified lines | ||
| 261 | 316 | devpriv->gpct_config[chan] = data[0]; |
| 262 | 317 | |
| 263 | 318 | /* Set Counter Mode Register */ |
| 264 | − cmReg.value = data[1] & 0xffff; | |
| 265 | − cmReg.reg.preloadRegSel = 0; /* PR0 */ | |
| 266 | − outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 319 | + val = data[1] & 0xffff; | |
| 320 | + /* Select PR0 */ | |
| 321 | + val &= ~S526_GPCT_MODE_PR_SELECT_MASK; | |
| 322 | + val |= S526_GPCT_MODE_PR_SELECT_PR0; | |
| 323 | + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 267 | 324 | |
| 268 | 325 | /* Load the pre-load register 0 */ |
| 269 | 326 | s526_gpct_write(dev, chan, data[2]); |
| 270 | 327 | |
| 271 | 328 | /* Set Counter Mode Register */ |
| 272 | − cmReg.value = data[1] & 0xffff; | |
| 273 | − cmReg.reg.preloadRegSel = 1; /* PR1 */ | |
| 274 | − outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 329 | + val = data[1] & 0xffff; | |
| 330 | + /* Select PR1 */ | |
| 331 | + val &= ~S526_GPCT_MODE_PR_SELECT_MASK; | |
| 332 | + val |= S526_GPCT_MODE_PR_SELECT_PR1; | |
| 333 | + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 275 | 334 | |
| 276 | 335 | /* Load the pre-load register 1 */ |
| 277 | 336 | s526_gpct_write(dev, chan, data[3]); |
| @@ -294,17 +353,21 @@ static int s526_gpct_insn_config(struct comedi_device *dev, · 16 unmodified lines | ||
| 294 | 353 | devpriv->gpct_config[chan] = data[0]; |
| 295 | 354 | |
| 296 | 355 | /* Set Counter Mode Register */ |
| 297 | − cmReg.value = data[1] & 0xffff; | |
| 298 | − cmReg.reg.preloadRegSel = 0; /* PR0 */ | |
| 299 | − outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 356 | + val = data[1] & 0xffff; | |
| 357 | + /* Select PR0 */ | |
| 358 | + val &= ~S526_GPCT_MODE_PR_SELECT_MASK; | |
| 359 | + val |= S526_GPCT_MODE_PR_SELECT_PR0; | |
| 360 | + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 300 | 361 | |
| 301 | 362 | /* Load the pre-load register 0 */ |
| 302 | 363 | s526_gpct_write(dev, chan, data[2]); |
| 303 | 364 | |
| 304 | 365 | /* Set Counter Mode Register */ |
| 305 | − cmReg.value = data[1] & 0xffff; | |
| 306 | − cmReg.reg.preloadRegSel = 1; /* PR1 */ | |
| 307 | − outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 366 | + val = data[1] & 0xffff; | |
| 367 | + /* Select PR1 */ | |
| 368 | + val &= ~S526_GPCT_MODE_PR_SELECT_MASK; | |
| 369 | + val |= S526_GPCT_MODE_PR_SELECT_PR1; | |
| 370 | + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); | |
| 308 | 371 | |
| 309 | 372 | /* Load the pre-load register 1 */ |
| 310 | 373 | s526_gpct_write(dev, chan, data[3]); |
| @@ -934,7 +934,7 @@ static void cls_flush_uart_write(struct channel_t *ch) · 933 unmodified lines | ||
| 934 | 934 | |
| 935 | 935 | writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), |
| 936 | 936 | &ch->ch_cls_uart->isr_fcr); |
| 937 | − udelay(10); | |
| 937 | + usleep_range(10, 20); | |
| 938 | 938 | |
| 939 | 939 | ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); |
| 940 | 940 | } |
| @@ -1108,9 +1108,9 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) · 1107 unmodified lines | ||
| 1108 | 1108 | * On the other hand, if the UART IS in FIFO mode, then ask |
| 1109 | 1109 | * the UART to give us an approximation of data it has RX'ed. |
| 1110 | 1110 | */ |
| 1111 | − if (!(ch->ch_flags & CH_FIFO_ENABLED)) | |
| 1111 | + if (!(ch->ch_flags & CH_FIFO_ENABLED)) { | |
| 1112 | 1112 | total = 0; |
| 1113 | − else { | |
| 1113 | + } else { | |
| 1114 | 1114 | total = readb(&ch->ch_neo_uart->rfifo); |
| 1115 | 1115 | |
| 1116 | 1116 | /* |
| @@ -1628,7 +1628,7 @@ static void neo_uart_init(struct channel_t *ch) · 511 unmodified lines | ||
| 1628 | 1628 | |
| 1629 | 1629 | /* Clear out UART and FIFO */ |
| 1630 | 1630 | readb(&ch->ch_neo_uart->txrx); |
| 1631 | − writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr); | |
| 1631 | + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr); | |
| 1632 | 1632 | readb(&ch->ch_neo_uart->lsr); |
| 1633 | 1633 | readb(&ch->ch_neo_uart->msr); |
| 1634 | 1634 | |
| @@ -1779,8 +1779,8 @@ static void neo_vpd(struct dgnc_board *brd) · 144 unmodified lines | ||
| 1779 | 1779 | /* Store the VPD into our buffer */ |
| 1780 | 1780 | for (i = 0; i < NEO_VPD_IMAGESIZE; i++) { |
| 1781 | 1781 | a = neo_read_eeprom(brd->re_map_membase, i); |
| 1782 | − brd->vpd[i*2] = a & 0xff; | |
| 1783 | − brd->vpd[(i*2)+1] = (a >> 8) & 0xff; | |
| 1782 | + brd->vpd[i * 2] = a & 0xff; | |
| 1783 | + brd->vpd[(i * 2) + 1] = (a >> 8) & 0xff; | |
| 1784 | 1784 | } |
| 1785 | 1785 | |
| 1786 | 1786 | if (((brd->vpd[0x08] != 0x82) /* long resource name tag */ |
| @@ -448,7 +448,7 @@ void dgnc_tty_uninit(struct dgnc_board *brd) · 447 unmodified lines | ||
| 448 | 448 | * dgnc_wmove - Write data to transmit queue. |
| 449 | 449 | * |
| 450 | 450 | * ch - Pointer to channel structure. |
| 451 | − * buf - Poiter to characters to be moved. | |
| 451 | + * buf - Pointer to characters to be moved. | |
| 452 | 452 | * n - Number of characters to move. |
| 453 | 453 | * |
| 454 | 454 | *=======================================================================*/ |
| @@ -1,7 +1,6 @@ | ||
| 1 | 1 | #include <linux/tty.h> |
| 2 | 2 | #include <linux/sched.h> |
| 3 | 3 | #include "dgnc_utils.h" |
| 4 | −#include "digi.h" | |
| 5 | 4 | |
| 6 | 5 | /* |
| 7 | 6 | * dgnc_ms_sleep() |
| @@ -823,7 +823,7 @@ static int _nbu2ss_out_dma( · 822 unmodified lines | ||
| 823 | 823 | u32 length |
| 824 | 824 | ) |
| 825 | 825 | { |
| 826 | − u8 *pBuffer; | |
| 826 | + dma_addr_t pBuffer; | |
| 827 | 827 | u32 mpkt; |
| 828 | 828 | u32 lmpkt; |
| 829 | 829 | u32 dmacnt; |
| @@ -836,7 +836,7 @@ static int _nbu2ss_out_dma( · 6 unmodified lines | ||
| 836 | 836 | return 1; /* DMA is forwarded */ |
| 837 | 837 | |
| 838 | 838 | req->dma_flag = TRUE; |
| 839 | − pBuffer = (u8 *)req->req.dma; | |
| 839 | + pBuffer = req->req.dma; | |
| 840 | 840 | pBuffer += req->req.actual; |
| 841 | 841 | |
| 842 | 842 | /* DMA Address */ |
| @@ -1034,7 +1034,7 @@ static int _nbu2ss_in_dma( · 191 unmodified lines | ||
| 1034 | 1034 | u32 length |
| 1035 | 1035 | ) |
| 1036 | 1036 | { |
| 1037 | − u8 *pBuffer; | |
| 1037 | + dma_addr_t pBuffer; | |
| 1038 | 1038 | u32 mpkt; /* MaxPacketSize */ |
| 1039 | 1039 | u32 lmpkt; /* Last Packet Data Size */ |
| 1040 | 1040 | u32 dmacnt; /* IN Data Size */ |
| @@ -1080,7 +1080,7 @@ static int _nbu2ss_in_dma( · 39 unmodified lines | ||
| 1080 | 1080 | _nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, data); |
| 1081 | 1081 | |
| 1082 | 1082 | /* Address setting */ |
| 1083 | − pBuffer = (u8 *)req->req.dma; | |
| 1083 | + pBuffer = req->req.dma; | |
| 1084 | 1084 | pBuffer += req->req.actual; |
| 1085 | 1085 | _nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)pBuffer); |
| 1086 | 1086 | |
| @@ -1285,11 +1285,7 @@ static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep) · 198 unmodified lines | ||
| 1285 | 1285 | bool bflag = FALSE; |
| 1286 | 1286 | struct nbu2ss_req *req; |
| 1287 | 1287 | |
| 1288 | − if (list_empty(&ep->queue)) | |
| 1289 | − req = NULL; | |
| 1290 | − else | |
| 1291 | − req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | |
| 1292 | − | |
| 1288 | + req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); | |
| 1293 | 1289 | if (!req) |
| 1294 | 1290 | return; |
| 1295 | 1291 | |
| @@ -1784,11 +1780,7 @@ static inline int _nbu2ss_ep0_in_data_stage(struct nbu2ss_udc *udc) · 488 unmodified lines | ||
| 1784 | 1780 | struct nbu2ss_req *req; |
| 1785 | 1781 | struct nbu2ss_ep *ep = &udc->ep[0]; |
| 1786 | 1782 | |
| 1787 | − if (list_empty(&ep->queue)) | |
| 1788 | − req = NULL; | |
| 1789 | − else | |
| 1790 | − req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | |
| 1791 | − | |
| 1783 | + req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); | |
| 1792 | 1784 | if (!req) |
| 1793 | 1785 | req = &udc->ep0_req; |
| 1794 | 1786 | |
| @@ -1811,11 +1803,7 @@ static inline int _nbu2ss_ep0_out_data_stage(struct nbu2ss_udc *udc) · 16 unmodified lines | ||
| 1811 | 1803 | struct nbu2ss_req *req; |
| 1812 | 1804 | struct nbu2ss_ep *ep = &udc->ep[0]; |
| 1813 | 1805 | |
| 1814 | − if (list_empty(&ep->queue)) | |
| 1815 | − req = NULL; | |
| 1816 | − else | |
| 1817 | − req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | |
| 1818 | − | |
| 1806 | + req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); | |
| 1819 | 1807 | if (!req) |
| 1820 | 1808 | req = &udc->ep0_req; |
| 1821 | 1809 | |
| @@ -1838,11 +1826,7 @@ static inline int _nbu2ss_ep0_status_stage(struct nbu2ss_udc *udc) · 16 unmodified lines | ||
| 1838 | 1826 | struct nbu2ss_req *req; |
| 1839 | 1827 | struct nbu2ss_ep *ep = &udc->ep[0]; |
| 1840 | 1828 | |
| 1841 | − if (list_empty(&ep->queue)) | |
| 1842 | − req = NULL; | |
| 1843 | − else | |
| 1844 | − req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | |
| 1845 | − | |
| 1829 | + req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); | |
| 1846 | 1830 | if (!req) { |
| 1847 | 1831 | req = &udc->ep0_req; |
| 1848 | 1832 | if (req->req.complete) |
| @@ -2145,11 +2129,7 @@ static inline void _nbu2ss_epn_int(struct nbu2ss_udc *udc, u32 epnum) · 296 unmodified lines | ||
| 2145 | 2129 | /* Interrupt Clear */ |
| 2146 | 2130 | _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_STATUS, ~(u32)status); |
| 2147 | 2131 | |
| 2148 | − if (list_empty(&ep->queue)) | |
| 2149 | − req = NULL; | |
| 2150 | − else | |
| 2151 | − req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | |
| 2152 | − | |
| 2132 | + req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); | |
| 2153 | 2133 | if (!req) { |
| 2154 | 2134 | /* pr_warn("=== %s(%d) req == NULL\n", __func__, epnum); */ |
| 2155 | 2135 | return; |
| @@ -2728,7 +2708,7 @@ static int nbu2ss_ep_queue( · 572 unmodified lines | ||
| 2728 | 2708 | spin_lock_irqsave(&udc->lock, flags); |
| 2729 | 2709 | |
| 2730 | 2710 | #ifdef USE_DMA |
| 2731 | − if ((u32)req->req.buf & 0x3) | |
| 2711 | + if ((uintptr_t)req->req.buf & 0x3) | |
| 2732 | 2712 | req->unaligned = TRUE; |
| 2733 | 2713 | else |
| 2734 | 2714 | req->unaligned = FALSE; |
| @@ -893,11 +893,10 @@ static void fwserial_destroy(struct kref *kref) · 892 unmodified lines | ||
| 893 | 893 | kfree(serial); |
| 894 | 894 | } |
| 895 | 895 | |
| 896 | −void fwtty_port_put(struct fwtty_port *port) | |
| 896 | +static void fwtty_port_put(struct fwtty_port *port) | |
| 897 | 897 | { |
| 898 | 898 | kref_put(&port->serial->kref, fwserial_destroy); |
| 899 | 899 | } |
| 900 | −EXPORT_SYMBOL(fwtty_port_put); | |
| 901 | 900 | |
| 902 | 901 | static void fwtty_port_dtr_rts(struct tty_port *tty_port, int on) |
| 903 | 902 | { |
| @@ -342,16 +342,6 @@ static const char loop_dev_name[] = "fwloop"; · 341 unmodified lines | ||
| 342 | 342 | extern struct tty_driver *fwtty_driver; |
| 343 | 343 | |
| 344 | 344 | struct fwtty_port *fwtty_port_get(unsigned index); |
| 345 | −void fwtty_port_put(struct fwtty_port *port); | |
| 346 | − | |
| 347 | −static inline void fwtty_bind_console(struct fwtty_port *port, | |
| 348 | − struct fwconsole_ops *fwcon_ops, | |
| 349 | − void *data) | |
| 350 | −{ | |
| 351 | − port->con_data = data; | |
| 352 | − port->fwcon_ops = fwcon_ops; | |
| 353 | −} | |
| 354 | − | |
| 355 | 345 | /* |
| 356 | 346 | * Returns the max send async payload size in bytes based on the unit device |
| 357 | 347 | * link speed. Self-limiting asynchronous bandwidth (via reducing the payload) |
| @@ -555,7 +555,7 @@ int gdm_lte_event_init(void) · 554 unmodified lines | ||
| 555 | 555 | void gdm_lte_event_exit(void) |
| 556 | 556 | { |
| 557 | 557 | if (lte_event.sock && --lte_event.ref_cnt == 0) { |
| 558 | − netlink_exit(lte_event.sock); | |
| 558 | + sock_release(lte_event.sock->sk_socket); | |
| 559 | 559 | lte_event.sock = NULL; |
| 560 | 560 | } |
| 561 | 561 | } |
| @@ -64,7 +64,7 @@ static void gdm_port_destruct(struct tty_port *port) · 63 unmodified lines | ||
| 64 | 64 | kfree(gdm); |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | −static struct tty_port_operations gdm_port_ops = { | |
| 67 | +static const struct tty_port_operations gdm_port_ops = { | |
| 68 | 68 | .destruct = gdm_port_destruct, |
| 69 | 69 | }; |
| 70 | 70 | |
| @@ -107,11 +107,6 @@ struct sock *netlink_init(int unit, · 106 unmodified lines | ||
| 107 | 107 | return sock; |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | −void netlink_exit(struct sock *sock) | |
| 111 | −{ | |
| 112 | − sock_release(sock->sk_socket); | |
| 113 | −} | |
| 114 | − | |
| 115 | 110 | int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len) |
| 116 | 111 | { |
| 117 | 112 | static u32 seq; |
| @@ -19,7 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | struct sock *netlink_init(int unit, |
| 21 | 21 | void (*cb)(struct net_device *dev, u16 type, void *msg, int len)); |
| 22 | −void netlink_exit(struct sock *sock); | |
| 23 | 22 | int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len); |
| 24 | 23 | |
| 25 | 24 | #endif /* _NETLINK_K_H_ */ |
| @@ -101,7 +101,7 @@ void gdm_qos_init(void *nic_ptr) · 100 unmodified lines | ||
| 101 | 101 | } |
| 102 | 102 | |
| 103 | 103 | qcb->qos_list_cnt = 0; |
| 104 | − qcb->qos_null_idx = QOS_MAX-1; | |
| 104 | + qcb->qos_null_idx = QOS_MAX - 1; | |
| 105 | 105 | qcb->qos_limit_size = 255; |
| 106 | 106 | |
| 107 | 107 | spin_lock_init(&qcb->qos_lock); |
| @@ -128,7 +128,7 @@ void gdm_qos_release_list(void *nic_ptr) · 20 unmodified lines | ||
| 128 | 128 | } |
| 129 | 129 | |
| 130 | 130 | qcb->qos_list_cnt = 0; |
| 131 | − qcb->qos_null_idx = QOS_MAX-1; | |
| 131 | + qcb->qos_null_idx = QOS_MAX - 1; | |
| 132 | 132 | |
| 133 | 133 | for (i = 0; i < QOS_MAX; i++) { |
| 134 | 134 | list_for_each_entry_safe(entry, n, &qcb->qos_list[i], list) { |
| @@ -143,18 +143,18 @@ static int chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *stream, u8 *port) · 8 unmodified lines | ||
| 143 | 143 | { |
| 144 | 144 | int i; |
| 145 | 145 | |
| 146 | − if (csr->classifier_rule_en&IPTYPEOFSERVICE) { | |
| 146 | + if (csr->classifier_rule_en & IPTYPEOFSERVICE) { | |
| 147 | 147 | if (((stream[1] & csr->ip2s_mask) < csr->ip2s_lo) || |
| 148 | 148 | ((stream[1] & csr->ip2s_mask) > csr->ip2s_hi)) |
| 149 | 149 | return 1; |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | − if (csr->classifier_rule_en&PROTOCOL) { | |
| 152 | + if (csr->classifier_rule_en & PROTOCOL) { | |
| 153 | 153 | if (stream[9] != csr->protocol) |
| 154 | 154 | return 1; |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | − if (csr->classifier_rule_en&IPMASKEDSRCADDRESS) { | |
| 157 | + if (csr->classifier_rule_en & IPMASKEDSRCADDRESS) { | |
| 158 | 158 | for (i = 0; i < 4; i++) { |
| 159 | 159 | if ((stream[12 + i] & csr->ipsrc_addrmask[i]) != |
| 160 | 160 | (csr->ipsrc_addr[i] & csr->ipsrc_addrmask[i])) |
| @@ -162,7 +162,7 @@ static int chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *stream, u8 *port) · 1 unmodified line | ||
| 162 | 162 | } |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | − if (csr->classifier_rule_en&IPMASKEDDSTADDRESS) { | |
| 165 | + if (csr->classifier_rule_en & IPMASKEDDSTADDRESS) { | |
| 166 | 166 | for (i = 0; i < 4; i++) { |
| 167 | 167 | if ((stream[16 + i] & csr->ipdst_addrmask[i]) != |
| 168 | 168 | (csr->ipdst_addr[i] & csr->ipdst_addrmask[i])) |
| @@ -170,14 +170,14 @@ static int chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *stream, u8 *port) · 1 unmodified line | ||
| 170 | 170 | } |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | − if (csr->classifier_rule_en&PROTOCOLSRCPORTRANGE) { | |
| 174 | − i = ((port[0]<<8)&0xff00)+port[1]; | |
| 173 | + if (csr->classifier_rule_en & PROTOCOLSRCPORTRANGE) { | |
| 174 | + i = ((port[0] << 8) & 0xff00) + port[1]; | |
| 175 | 175 | if ((i < csr->srcport_lo) || (i > csr->srcport_hi)) |
| 176 | 176 | return 1; |
| 177 | 177 | } |
| 178 | 178 | |
| 179 | − if (csr->classifier_rule_en&PROTOCOLDSTPORTRANGE) { | |
| 180 | − i = ((port[2]<<8)&0xff00)+port[3]; | |
| 179 | + if (csr->classifier_rule_en & PROTOCOLDSTPORTRANGE) { | |
| 180 | + i = ((port[2] << 8) & 0xff00) + port[3]; | |
| 181 | 181 | if ((i < csr->dstport_lo) || (i > csr->dstport_hi)) |
| 182 | 182 | return 1; |
| 183 | 183 | } |
| @@ -193,7 +193,7 @@ static int get_qos_index(struct nic *nic, u8 *iph, u8 *tcpudph) · 9 unmodified lines | ||
| 193 | 193 | if (!iph || !tcpudph) |
| 194 | 194 | return -1; |
| 195 | 195 | |
| 196 | − ip_ver = (iph[0]>>4)&0xf; | |
| 196 | + ip_ver = (iph[0] >> 4) & 0xf; | |
| 197 | 197 | |
| 198 | 198 | if (ip_ver != 4) |
| 199 | 199 | return -1; |
| @@ -342,17 +342,17 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) · 142 unmodified lines | ||
| 342 | 342 | if (sub_cmd_evt == QOS_REPORT) { |
| 343 | 343 | spin_lock_irqsave(&qcb->qos_lock, flags); |
| 344 | 344 | for (i = 0; i < qcb->qos_list_cnt; i++) { |
| 345 | − sfid = ((buf[(i*5)+6]<<24)&0xff000000); | |
| 346 | − sfid += ((buf[(i*5)+7]<<16)&0xff0000); | |
| 347 | − sfid += ((buf[(i*5)+8]<<8)&0xff00); | |
| 348 | − sfid += (buf[(i*5)+9]); | |
| 345 | + sfid = ((buf[(i*5) + 6] << 24) & 0xff000000); | |
| 346 | + sfid += ((buf[(i*5) + 7] << 16) & 0xff0000); | |
| 347 | + sfid += ((buf[(i*5) + 8] << 8) & 0xff00); | |
| 348 | + sfid += (buf[(i*5) + 9]); | |
| 349 | 349 | index = get_csr(qcb, sfid, 0); |
| 350 | 350 | if (index == -1) { |
| 351 | 351 | spin_unlock_irqrestore(&qcb->qos_lock, flags); |
| 352 | 352 | netdev_err(nic->netdev, "QoS ERROR: No SF\n"); |
| 353 | 353 | return; |
| 354 | 354 | } |
| 355 | − qcb->csr[index].qos_buf_count = buf[(i*5)+10]; | |
| 355 | + qcb->csr[index].qos_buf_count = buf[(i*5) + 10]; | |
| 356 | 356 | } |
| 357 | 357 | |
| 358 | 358 | extract_qos_list(nic, &send_list); |
| @@ -363,9 +363,9 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) · 4 unmodified lines | ||
| 363 | 363 | |
| 364 | 364 | /* sub_cmd_evt == QOS_ADD || sub_cmd_evt == QOS_CHANG_DEL */ |
| 365 | 365 | pos = 6; |
| 366 | − sfid = ((buf[pos++]<<24)&0xff000000); | |
| 367 | − sfid += ((buf[pos++]<<16)&0xff0000); | |
| 368 | − sfid += ((buf[pos++]<<8)&0xff00); | |
| 366 | + sfid = ((buf[pos++] << 24) & 0xff000000); | |
| 367 | + sfid += ((buf[pos++] << 16) & 0xff0000); | |
| 368 | + sfid += ((buf[pos++] << 8) & 0xff00); | |
| 369 | 369 | sfid += (buf[pos++]); |
| 370 | 370 | |
| 371 | 371 | index = get_csr(qcb, sfid, 1); |
| @@ -382,7 +382,7 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) · 10 unmodified lines | ||
| 382 | 382 | |
| 383 | 383 | spin_lock_irqsave(&qcb->qos_lock, flags); |
| 384 | 384 | qcb->csr[index].sfid = sfid; |
| 385 | − qcb->csr[index].classifier_rule_en = ((buf[pos++]<<8)&0xff00); | |
| 385 | + qcb->csr[index].classifier_rule_en = ((buf[pos++] << 8) & 0xff00); | |
| 386 | 386 | qcb->csr[index].classifier_rule_en += buf[pos++]; |
| 387 | 387 | if (qcb->csr[index].classifier_rule_en == 0) |
| 388 | 388 | qcb->qos_null_idx = index; |
| @@ -406,16 +406,16 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) · 17 unmodified lines | ||
| 406 | 406 | qcb->csr[index].ipdst_addr[1] = buf[pos++]; |
| 407 | 407 | qcb->csr[index].ipdst_addr[2] = buf[pos++]; |
| 408 | 408 | qcb->csr[index].ipdst_addr[3] = buf[pos++]; |
| 409 | − qcb->csr[index].srcport_lo = ((buf[pos++]<<8)&0xff00); | |
| 409 | + qcb->csr[index].srcport_lo = ((buf[pos++] << 8) & 0xff00); | |
| 410 | 410 | qcb->csr[index].srcport_lo += buf[pos++]; |
| 411 | − qcb->csr[index].srcport_hi = ((buf[pos++]<<8)&0xff00); | |
| 411 | + qcb->csr[index].srcport_hi = ((buf[pos++] << 8) & 0xff00); | |
| 412 | 412 | qcb->csr[index].srcport_hi += buf[pos++]; |
| 413 | − qcb->csr[index].dstport_lo = ((buf[pos++]<<8)&0xff00); | |
| 413 | + qcb->csr[index].dstport_lo = ((buf[pos++] << 8) & 0xff00); | |
| 414 | 414 | qcb->csr[index].dstport_lo += buf[pos++]; |
| 415 | − qcb->csr[index].dstport_hi = ((buf[pos++]<<8)&0xff00); | |
| 415 | + qcb->csr[index].dstport_hi = ((buf[pos++] << 8) & 0xff00); | |
| 416 | 416 | qcb->csr[index].dstport_hi += buf[pos++]; |
| 417 | 417 | |
| 418 | − qcb->qos_limit_size = 254/qcb->qos_list_cnt; | |
| 418 | + qcb->qos_limit_size = 254 / qcb->qos_list_cnt; | |
| 419 | 419 | spin_unlock_irqrestore(&qcb->qos_lock, flags); |
| 420 | 420 | } else if (sub_cmd_evt == QOS_CHANGE_DEL) { |
| 421 | 421 | netdev_dbg(nic->netdev, "QOS_CHANGE_DEL SFID = 0x%x, index=%d\n", |
| @@ -426,7 +426,7 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) · 4 unmodified lines | ||
| 426 | 426 | spin_lock_irqsave(&qcb->qos_lock, flags); |
| 427 | 427 | qcb->csr[index].enabled = false; |
| 428 | 428 | qcb->qos_list_cnt--; |
| 429 | − qcb->qos_limit_size = 254/qcb->qos_list_cnt; | |
| 429 | + qcb->qos_limit_size = 254 / qcb->qos_list_cnt; | |
| 430 | 430 | |
| 431 | 431 | list_for_each_entry_safe(entry, n, &qcb->qos_list[index], |
| 432 | 432 | list) { |
| @@ -36,7 +36,7 @@ · 35 unmodified lines | ||
| 36 | 36 | #define RX_BUF_SIZE (25*1024) |
| 37 | 37 | |
| 38 | 38 | #define TX_HZ 2000 |
| 39 | −#define TX_INTERVAL (1000000/TX_HZ) | |
| 39 | +#define TX_INTERVAL (NSEC_PER_SEC/TX_HZ) | |
| 40 | 40 | |
| 41 | 41 | static struct sdio_tx *alloc_tx_struct(struct tx_cxt *tx) |
| 42 | 42 | { |
| @@ -303,7 +303,7 @@ static void send_sdu(struct sdio_func *func, struct tx_cxt *tx) · 260 unmodified lines | ||
| 303 | 303 | put_tx_struct(t->tx_cxt, t); |
| 304 | 304 | } |
| 305 | 305 | |
| 306 | − do_gettimeofday(&tx->sdu_stamp); | |
| 306 | + tx->sdu_stamp = ktime_get(); | |
| 307 | 307 | spin_unlock_irqrestore(&tx->lock, flags); |
| 308 | 308 | } |
| 309 | 309 | |
| @@ -330,7 +330,7 @@ static void do_tx(struct work_struct *work) · 20 unmodified lines | ||
| 330 | 330 | struct sdio_func *func = sdev->func; |
| 331 | 331 | struct tx_cxt *tx = &sdev->tx; |
| 332 | 332 | struct sdio_tx *t = NULL; |
| 333 | − struct timeval now, *before; | |
| 333 | + ktime_t now, before; | |
| 334 | 334 | int is_sdu = 0; |
| 335 | 335 | long diff; |
| 336 | 336 | unsigned long flags; |
| @@ -346,11 +346,10 @@ static void do_tx(struct work_struct *work) · 9 unmodified lines | ||
| 346 | 346 | list_del(&t->list); |
| 347 | 347 | is_sdu = 0; |
| 348 | 348 | } else if (!tx->stop_sdu_tx && !list_empty(&tx->sdu_list)) { |
| 349 | − do_gettimeofday(&now); | |
| 350 | − before = &tx->sdu_stamp; | |
| 349 | + now = ktime_get(); | |
| 350 | + before = tx->sdu_stamp; | |
| 351 | 351 | |
| 352 | − diff = (now.tv_sec - before->tv_sec) * 1000000 + | |
| 353 | − (now.tv_usec - before->tv_usec); | |
| 352 | + diff = ktime_to_ns(ktime_sub(now, before)); | |
| 354 | 353 | if (diff >= 0 && diff < TX_INTERVAL) { |
| 355 | 354 | schedule_work(&sdev->ws); |
| 356 | 355 | spin_unlock_irqrestore(&tx->lock, flags); |
| @@ -15,7 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #define __GDM72XX_GDM_SDIO_H__ |
| 16 | 16 | |
| 17 | 17 | #include <linux/types.h> |
| 18 | −#include <linux/time.h> | |
| 18 | +#include <linux/ktime.h> | |
| 19 | 19 | |
| 20 | 20 | #define MAX_NR_SDU_BUF 64 |
| 21 | 21 | |
| @@ -32,7 +32,7 @@ struct tx_cxt { · 10 unmodified lines | ||
| 32 | 32 | struct list_head free_list; |
| 33 | 33 | struct list_head sdu_list; |
| 34 | 34 | struct list_head hci_list; |
| 35 | − struct timeval sdu_stamp; | |
| 35 | + ktime_t sdu_stamp; | |
| 36 | 36 | u8 *sdu_buf; |
| 37 | 37 | spinlock_t lock; |
| 38 | 38 | int can_send; |
| @@ -84,11 +84,6 @@ static inline struct evt_entry *alloc_event_entry(void) · 83 unmodified lines | ||
| 84 | 84 | return kmalloc(sizeof(struct evt_entry), GFP_ATOMIC); |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | −static inline void free_event_entry(struct evt_entry *e) | |
| 88 | −{ | |
| 89 | − kfree(e); | |
| 90 | −} | |
| 91 | − | |
| 92 | 87 | static struct evt_entry *get_event_entry(void) |
| 93 | 88 | { |
| 94 | 89 | struct evt_entry *e; |
| @@ -180,11 +175,11 @@ static void gdm_wimax_event_exit(void) · 85 unmodified lines | ||
| 180 | 175 | |
| 181 | 176 | list_for_each_entry_safe(e, temp, &wm_event.evtq, list) { |
| 182 | 177 | list_del(&e->list); |
| 183 | − free_event_entry(e); | |
| 178 | + kfree(e); | |
| 184 | 179 | } |
| 185 | 180 | list_for_each_entry_safe(e, temp, &wm_event.freeq, list) { |
| 186 | 181 | list_del(&e->list); |
| 187 | − free_event_entry(e); | |
| 182 | + kfree(e); | |
| 188 | 183 | } |
| 189 | 184 | |
| 190 | 185 | spin_unlock_irqrestore(&wm_event.evt_lock, flags); |
| @@ -368,7 +363,7 @@ static void kdelete(void **buf) · 177 unmodified lines | ||
| 368 | 363 | } |
| 369 | 364 | } |
| 370 | 365 | |
| 371 | −static int gdm_wimax_ioctl_get_data(struct data_s *dst, struct data_s *src) | |
| 366 | +static int gdm_wimax_ioctl_get_data(struct udata_s *dst, struct data_s *src) | |
| 372 | 367 | { |
| 373 | 368 | int size; |
| 374 | 369 | |
| @@ -384,7 +379,7 @@ static int gdm_wimax_ioctl_get_data(struct data_s *dst, struct data_s *src) · 9 unmodified lines | ||
| 384 | 379 | return 0; |
| 385 | 380 | } |
| 386 | 381 | |
| 387 | −static int gdm_wimax_ioctl_set_data(struct data_s *dst, struct data_s *src) | |
| 382 | +static int gdm_wimax_ioctl_set_data(struct data_s *dst, struct udata_s *src) | |
| 388 | 383 | { |
| 389 | 384 | if (!src->size) { |
| 390 | 385 | dst->size = 0; |
| @@ -460,6 +455,7 @@ static int gdm_wimax_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) · 69 unmodified lines | ||
| 460 | 455 | struct wm_req_s *req = (struct wm_req_s *)ifr; |
| 461 | 456 | struct nic *nic = netdev_priv(dev); |
| 462 | 457 | int ret; |
| 458 | + struct fsm_s fsm_buf; | |
| 463 | 459 | |
| 464 | 460 | if (cmd != SIOCWMIOCTL) |
| 465 | 461 | return -EOPNOTSUPP; |
| @@ -482,8 +478,11 @@ static int gdm_wimax_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) · 16 unmodified lines | ||
| 482 | 478 | /* NOTE: gdm_update_fsm should be called |
| 483 | 479 | * before gdm_wimax_ioctl_set_data is called. |
| 484 | 480 | */ |
| 485 | − gdm_update_fsm(dev, | |
| 486 | − req->data.buf); | |
| 481 | + if (copy_from_user(&fsm_buf, req->data.buf, | |
| 482 | + sizeof(struct fsm_s))) | |
| 483 | + return -EFAULT; | |
| 484 | + | |
| 485 | + gdm_update_fsm(dev, &fsm_buf); | |
| 487 | 486 | } |
| 488 | 487 | ret = gdm_wimax_ioctl_set_data( |
| 489 | 488 | &nic->sdk_data[req->data_id], &req->data); |
| @@ -78,13 +78,18 @@ struct data_s { · 77 unmodified lines | ||
| 78 | 78 | void *buf; |
| 79 | 79 | }; |
| 80 | 80 | |
| 81 | +struct udata_s { | |
| 82 | + int size; | |
| 83 | + void __user *buf; | |
| 84 | +}; | |
| 85 | + | |
| 81 | 86 | struct wm_req_s { |
| 82 | 87 | union { |
| 83 | 88 | char ifrn_name[IFNAMSIZ]; |
| 84 | 89 | } ifr_ifrn; |
| 85 | 90 | unsigned short cmd; |
| 86 | 91 | unsigned short data_id; |
| 87 | − struct data_s data; | |
| 92 | + struct udata_s data; | |
| 88 | 93 | |
| 89 | 94 | /* NOTE: sizeof(struct wm_req_s) must be less than sizeof(struct ifreq). */ |
| 90 | 95 | }; |
| @@ -17,33 +17,4 @@ source "drivers/staging/iio/meter/Kconfig" · 16 unmodified lines | ||
| 17 | 17 | source "drivers/staging/iio/resolver/Kconfig" |
| 18 | 18 | source "drivers/staging/iio/trigger/Kconfig" |
| 19 | 19 | |
| 20 | −config IIO_DUMMY_EVGEN | |
| 21 | − tristate | |
| 22 | − select IRQ_WORK | |
| 23 | − | |
| 24 | −config IIO_SIMPLE_DUMMY | |
| 25 | − tristate "An example driver with no hardware requirements" | |
| 26 | − help | |
| 27 | − Driver intended mainly as documentation for how to write | |
| 28 | − a driver. May also be useful for testing userspace code | |
| 29 | − without hardware. | |
| 30 | − | |
| 31 | −if IIO_SIMPLE_DUMMY | |
| 32 | − | |
| 33 | −config IIO_SIMPLE_DUMMY_EVENTS | |
| 34 | − bool "Event generation support" | |
| 35 | − select IIO_DUMMY_EVGEN | |
| 36 | − help | |
| 37 | − Add some dummy events to the simple dummy driver. | |
| 38 | − | |
| 39 | −config IIO_SIMPLE_DUMMY_BUFFER | |
| 40 | − bool "Buffered capture support" | |
| 41 | − select IIO_BUFFER | |
| 42 | − select IIO_TRIGGER | |
| 43 | − select IIO_KFIFO_BUF | |
| 44 | − help | |
| 45 | − Add buffered data capture to the simple dummy driver. | |
| 46 | − | |
| 47 | −endif # IIO_SIMPLE_DUMMY | |
| 48 | − | |
| 49 | 20 | endmenu |
| @@ -2,13 +2,6 @@ · 1 unmodified line | ||
| 2 | 2 | # Makefile for the industrial I/O core. |
| 3 | 3 | # |
| 4 | 4 | |
| 5 | −obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o | |
| 6 | −iio_dummy-y := iio_simple_dummy.o | |
| 7 | −iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_EVENTS) += iio_simple_dummy_events.o | |
| 8 | −iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o | |
| 9 | − | |
| 10 | −obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o | |
| 11 | − | |
| 12 | 5 | obj-y += accel/ |
| 13 | 6 | obj-y += adc/ |
| 14 | 7 | obj-y += addac/ |
| @@ -48,7 +48,7 @@ static int sca3000_read_data(struct sca3000_state *st, · 47 unmodified lines | ||
| 48 | 48 | } |
| 49 | 49 | }; |
| 50 | 50 | *rx_p = kmalloc(len, GFP_KERNEL); |
| 51 | − if (*rx_p == NULL) { | |
| 51 | + if (!*rx_p) { | |
| 52 | 52 | ret = -ENOMEM; |
| 53 | 53 | goto error_ret; |
| 54 | 54 | } |
| @@ -609,7 +609,7 @@ static const struct iio_chan_spec ad7192_channels[] = { · 608 unmodified lines | ||
| 609 | 609 | |
| 610 | 610 | static int ad7192_probe(struct spi_device *spi) |
| 611 | 611 | { |
| 612 | − const struct ad7192_platform_data *pdata = spi->dev.platform_data; | |
| 612 | + const struct ad7192_platform_data *pdata = dev_get_platdata(&spi->dev); | |
| 613 | 613 | struct ad7192_state *st; |
| 614 | 614 | struct iio_dev *indio_dev; |
| 615 | 615 | int ret, voltage_uv = 0; |
| @@ -833,7 +833,7 @@ static const struct ad7280_platform_data ad7793_default_pdata = { · 832 unmodified lines | ||
| 833 | 833 | |
| 834 | 834 | static int ad7280_probe(struct spi_device *spi) |
| 835 | 835 | { |
| 836 | − const struct ad7280_platform_data *pdata = spi->dev.platform_data; | |
| 836 | + const struct ad7280_platform_data *pdata = dev_get_platdata(&spi->dev); | |
| 837 | 837 | struct ad7280_state *st; |
| 838 | 838 | int ret; |
| 839 | 839 | const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890}; |
| @@ -15,15 +15,13 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/regulator/consumer.h> |
| 16 | 16 | #include <linux/err.h> |
| 17 | 17 | #include <linux/sched.h> |
| 18 | −#include <linux/gpio.h> | |
| 18 | +#include <linux/gpio/consumer.h> | |
| 19 | 19 | #include <linux/module.h> |
| 20 | 20 | |
| 21 | 21 | #include <linux/iio/iio.h> |
| 22 | 22 | #include <linux/iio/sysfs.h> |
| 23 | 23 | #include <linux/iio/adc/ad_sigma_delta.h> |
| 24 | 24 | |
| 25 | −#include "ad7780.h" | |
| 26 | − | |
| 27 | 25 | #define AD7780_RDY BIT(7) |
| 28 | 26 | #define AD7780_FILTER BIT(6) |
| 29 | 27 | #define AD7780_ERR BIT(5) |
| @@ -42,7 +40,7 @@ struct ad7780_chip_info { · 12 unmodified lines | ||
| 42 | 40 | struct ad7780_state { |
| 43 | 41 | const struct ad7780_chip_info *chip_info; |
| 44 | 42 | struct regulator *reg; |
| 45 | − int powerdown_gpio; | |
| 43 | + struct gpio_desc *powerdown_gpio; | |
| 46 | 44 | unsigned int gain; |
| 47 | 45 | u16 int_vref_mv; |
| 48 | 46 | |
| @@ -77,8 +75,7 @@ static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta, · 28 unmodified lines | ||
| 77 | 75 | break; |
| 78 | 76 | } |
| 79 | 77 | |
| 80 | − if (gpio_is_valid(st->powerdown_gpio)) | |
| 81 | − gpio_set_value(st->powerdown_gpio, val); | |
| 78 | + gpiod_set_value(st->powerdown_gpio, val); | |
| 82 | 79 | |
| 83 | 80 | return 0; |
| 84 | 81 | } |
| @@ -163,7 +160,6 @@ static const struct iio_info ad7780_info = { · 78 unmodified lines | ||
| 163 | 160 | |
| 164 | 161 | static int ad7780_probe(struct spi_device *spi) |
| 165 | 162 | { |
| 166 | − struct ad7780_platform_data *pdata = spi->dev.platform_data; | |
| 167 | 163 | struct ad7780_state *st; |
| 168 | 164 | struct iio_dev *indio_dev; |
| 169 | 165 | int ret, voltage_uv = 0; |
| @@ -189,12 +185,10 @@ static int ad7780_probe(struct spi_device *spi) · 19 unmodified lines | ||
| 189 | 185 | st->chip_info = |
| 190 | 186 | &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; |
| 191 | 187 | |
| 192 | − if (pdata && pdata->vref_mv) | |
| 193 | − st->int_vref_mv = pdata->vref_mv; | |
| 194 | − else if (voltage_uv) | |
| 188 | + if (voltage_uv) | |
| 195 | 189 | st->int_vref_mv = voltage_uv / 1000; |
| 196 | 190 | else |
| 197 | − dev_warn(&spi->dev, "reference voltage unspecified\n"); | |
| 191 | + dev_warn(&spi->dev, "Reference voltage unspecified\n"); | |
| 198 | 192 | |
| 199 | 193 | spi_set_drvdata(spi, indio_dev); |
| 200 | 194 | |
| @@ -205,18 +199,14 @@ static int ad7780_probe(struct spi_device *spi) · 4 unmodified lines | ||
| 205 | 199 | indio_dev->num_channels = 1; |
| 206 | 200 | indio_dev->info = &ad7780_info; |
| 207 | 201 | |
| 208 | − if (pdata && gpio_is_valid(pdata->gpio_pdrst)) { | |
| 209 | − ret = devm_gpio_request_one(&spi->dev, | |
| 210 | − pdata->gpio_pdrst, | |
| 211 | − GPIOF_OUT_INIT_LOW, | |
| 212 | − "AD7780 /PDRST"); | |
| 213 | − if (ret) { | |
| 214 | − dev_err(&spi->dev, "failed to request GPIO PDRST\n"); | |
| 215 | − goto error_disable_reg; | |
| 216 | − } | |
| 217 | − st->powerdown_gpio = pdata->gpio_pdrst; | |
| 218 | − } else { | |
| 219 | − st->powerdown_gpio = -1; | |
| 202 | + st->powerdown_gpio = devm_gpiod_get_optional(&spi->dev, | |
| 203 | + "powerdown", | |
| 204 | + GPIOD_OUT_LOW); | |
| 205 | + if (IS_ERR(st->powerdown_gpio)) { | |
| 206 | + ret = PTR_ERR(st->powerdown_gpio); | |
| 207 | + dev_err(&spi->dev, "Failed to request powerdown GPIO: %d\n", | |
| 208 | + ret); | |
| 209 | + goto error_disable_reg; | |
| 220 | 210 | } |
| 221 | 211 | |
| 222 | 212 | ret = ad_sd_setup_buffer_and_trigger(indio_dev); |
| @@ -1,30 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * AD7780/AD7781 SPI ADC driver | |
| 3 | − * | |
| 4 | − * Copyright 2011 Analog Devices Inc. | |
| 5 | − * | |
| 6 | − * Licensed under the GPL-2. | |
| 7 | − */ | |
| 8 | −#ifndef IIO_ADC_AD7780_H_ | |
| 9 | −#define IIO_ADC_AD7780_H_ | |
| 10 | − | |
| 11 | −/* | |
| 12 | − * TODO: struct ad7780_platform_data needs to go into include/linux/iio | |
| 13 | − */ | |
| 14 | − | |
| 15 | −/* NOTE: | |
| 16 | − * The AD7780 doesn't feature a dedicated SPI chip select, in addition it | |
| 17 | − * features a dual use data out ready DOUT/RDY output. | |
| 18 | − * In order to avoid contentions on the SPI bus, it's therefore necessary | |
| 19 | − * to use spi bus locking combined with a dedicated GPIO to control the | |
| 20 | − * power down reset signal of the AD7780. | |
| 21 | − * | |
| 22 | − * The DOUT/RDY output must also be wired to an interrupt capable GPIO. | |
| 23 | − */ | |
| 24 | − | |
| 25 | −struct ad7780_platform_data { | |
| 26 | − u16 vref_mv; | |
| 27 | − int gpio_pdrst; | |
| 28 | −}; | |
| 29 | − | |
| 30 | −#endif /* IIO_ADC_AD7780_H_ */ | |
| @@ -345,7 +345,7 @@ static int ad7816_probe(struct spi_device *spi_dev) · 344 unmodified lines | ||
| 345 | 345 | { |
| 346 | 346 | struct ad7816_chip_info *chip; |
| 347 | 347 | struct iio_dev *indio_dev; |
| 348 | − unsigned short *pins = spi_dev->dev.platform_data; | |
| 348 | + unsigned short *pins = dev_get_platdata(&spi_dev->dev); | |
| 349 | 349 | int ret = 0; |
| 350 | 350 | int i; |
| 351 | 351 | |
| @@ -319,12 +319,12 @@ struct mxs_lradc { · 318 unmodified lines | ||
| 319 | 319 | #define LRADC_CH_VALUE_OFFSET 0 |
| 320 | 320 | |
| 321 | 321 | #define LRADC_DELAY(n) (0xd0 + (0x10 * (n))) |
| 322 | −#define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xff << 24) | |
| 322 | +#define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xffUL << 24) | |
| 323 | 323 | #define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24 |
| 324 | 324 | #define LRADC_DELAY_TRIGGER(x) \ |
| 325 | 325 | (((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \ |
| 326 | 326 | LRADC_DELAY_TRIGGER_LRADCS_MASK) |
| 327 | −#define LRADC_DELAY_KICK (1 << 20) | |
| 327 | +#define LRADC_DELAY_KICK BIT(20) | |
| 328 | 328 | #define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16) |
| 329 | 329 | #define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16 |
| 330 | 330 | #define LRADC_DELAY_TRIGGER_DELAYS(x) \ |
| @@ -201,7 +201,7 @@ static const struct iio_info ad9832_info = { · 200 unmodified lines | ||
| 201 | 201 | |
| 202 | 202 | static int ad9832_probe(struct spi_device *spi) |
| 203 | 203 | { |
| 204 | − struct ad9832_platform_data *pdata = spi->dev.platform_data; | |
| 204 | + struct ad9832_platform_data *pdata = dev_get_platdata(&spi->dev); | |
| 205 | 205 | struct iio_dev *indio_dev; |
| 206 | 206 | struct ad9832_state *st; |
| 207 | 207 | struct regulator *reg; |
| @@ -318,7 +318,7 @@ static const struct iio_info ad9833_info = { · 317 unmodified lines | ||
| 318 | 318 | |
| 319 | 319 | static int ad9834_probe(struct spi_device *spi) |
| 320 | 320 | { |
| 321 | − struct ad9834_platform_data *pdata = spi->dev.platform_data; | |
| 321 | + struct ad9834_platform_data *pdata = dev_get_platdata(&spi->dev); | |
| 322 | 322 | struct ad9834_state *st; |
| 323 | 323 | struct iio_dev *indio_dev; |
| 324 | 324 | struct regulator *reg; |
| @@ -1898,7 +1898,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp, · 1897 unmodified lines | ||
| 1898 | 1898 | mutex_init(&chip->prox_mutex); |
| 1899 | 1899 | |
| 1900 | 1900 | chip->tsl2x7x_chip_status = TSL2X7X_CHIP_UNKNOWN; |
| 1901 | − chip->pdata = clientp->dev.platform_data; | |
| 1901 | + chip->pdata = dev_get_platdata(&clientp->dev); | |
| 1902 | 1902 | chip->id = id->driver_data; |
| 1903 | 1903 | chip->chip_info = |
| 1904 | 1904 | &tsl2x7x_chip_info_tbl[device_channel_config[id->driver_data]]; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -42,13 +42,6 @@ · 8 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | #include "curproc.h" |
| 44 | 44 | |
| 45 | −static inline int __is_po2(unsigned long long val) | |
| 46 | −{ | |
| 47 | − return !(val & (val - 1)); | |
| 48 | −} | |
| 49 | − | |
| 50 | −#define IS_PO2(val) __is_po2((unsigned long long)(val)) | |
| 51 | − | |
| 52 | 45 | #define LOWEST_BIT_SET(x) ((x) & ~((x) - 1)) |
| 53 | 46 | |
| 54 | 47 | /* |
| @@ -22,7 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | */ |
| 23 | 23 | /* |
| 24 | 24 | * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. |
| 25 | − * Copyright (c) 2012, Intel Corporation. | |
| 25 | + * | |
| 26 | + * Copyright (c) 2012, 2015 Intel Corporation. | |
| 26 | 27 | */ |
| 27 | 28 | /* |
| 28 | 29 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015 Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -41,6 +41,9 @@ · 7 unmodified lines | ||
| 41 | 41 | |
| 42 | 42 | #ifndef __LIBCFS_HASH_H__ |
| 43 | 43 | #define __LIBCFS_HASH_H__ |
| 44 | + | |
| 45 | +#include <linux/hash.h> | |
| 46 | + | |
| 44 | 47 | /* |
| 45 | 48 | * Knuth recommends primes in approximately golden ratio to the maximum |
| 46 | 49 | * integer representable by a machine word for multiplicative hashing. |
| @@ -56,22 +59,13 @@ · 9 unmodified lines | ||
| 56 | 59 | /* 2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */ |
| 57 | 60 | #define CFS_GOLDEN_RATIO_PRIME_64 0x9e37fffffffc0001ULL |
| 58 | 61 | |
| 59 | −/* | |
| 60 | − * Ideally we would use HAVE_HASH_LONG for this, but on linux we configure | |
| 61 | − * the linux kernel and user space at the same time, so we need to differentiate | |
| 62 | − * between them explicitly. If this is not needed on other architectures, then | |
| 63 | − * we'll need to move the functions to architecture specific headers. | |
| 64 | − */ | |
| 65 | − | |
| 66 | −#include <linux/hash.h> | |
| 67 | − | |
| 68 | 62 | /** disable debug */ |
| 69 | −#define CFS_HASH_DEBUG_NONE 0 | |
| 63 | +#define CFS_HASH_DEBUG_NONE 0 | |
| 70 | 64 | /** record hash depth and output to console when it's too deep, |
| 71 | 65 | * computing overhead is low but consume more memory */ |
| 72 | −#define CFS_HASH_DEBUG_1 1 | |
| 66 | +#define CFS_HASH_DEBUG_1 1 | |
| 73 | 67 | /** expensive, check key validation */ |
| 74 | −#define CFS_HASH_DEBUG_2 2 | |
| 68 | +#define CFS_HASH_DEBUG_2 2 | |
| 75 | 69 | |
| 76 | 70 | #define CFS_HASH_DEBUG_LEVEL CFS_HASH_DEBUG_NONE |
| 77 | 71 | |
| @@ -108,16 +102,18 @@ struct cfs_hash_bucket { · 30 unmodified lines | ||
| 108 | 102 | * cfs_hash bucket descriptor, it's normally in stack of caller |
| 109 | 103 | */ |
| 110 | 104 | struct cfs_hash_bd { |
| 111 | − struct cfs_hash_bucket *bd_bucket; /**< address of bucket */ | |
| 112 | − unsigned int bd_offset; /**< offset in bucket */ | |
| 105 | + /* address of bucket */ | |
| 106 | + struct cfs_hash_bucket *bd_bucket; | |
| 107 | + /* offset in bucket */ | |
| 108 | + unsigned int bd_offset; | |
| 113 | 109 | }; |
| 114 | 110 | |
| 115 | −#define CFS_HASH_NAME_LEN 16 /**< default name length */ | |
| 116 | −#define CFS_HASH_BIGNAME_LEN 64 /**< bigname for param tree */ | |
| 111 | +#define CFS_HASH_NAME_LEN 16 /**< default name length */ | |
| 112 | +#define CFS_HASH_BIGNAME_LEN 64 /**< bigname for param tree */ | |
| 117 | 113 | |
| 118 | −#define CFS_HASH_BKT_BITS 3 /**< default bits of bucket */ | |
| 119 | −#define CFS_HASH_BITS_MAX 30 /**< max bits of bucket */ | |
| 120 | −#define CFS_HASH_BITS_MIN CFS_HASH_BKT_BITS | |
| 114 | +#define CFS_HASH_BKT_BITS 3 /**< default bits of bucket */ | |
| 115 | +#define CFS_HASH_BITS_MAX 30 /**< max bits of bucket */ | |
| 116 | +#define CFS_HASH_BITS_MIN CFS_HASH_BKT_BITS | |
| 121 | 117 | |
| 122 | 118 | /** |
| 123 | 119 | * common hash attributes. |
| @@ -133,41 +129,41 @@ enum cfs_hash_tag { · 9 unmodified lines | ||
| 133 | 129 | */ |
| 134 | 130 | CFS_HASH_NO_LOCK = 1 << 0, |
| 135 | 131 | /** no bucket lock, use one spinlock to protect the whole hash */ |
| 136 | − CFS_HASH_NO_BKTLOCK = 1 << 1, | |
| 132 | + CFS_HASH_NO_BKTLOCK = 1 << 1, | |
| 137 | 133 | /** rwlock to protect bucket */ |
| 138 | − CFS_HASH_RW_BKTLOCK = 1 << 2, | |
| 134 | + CFS_HASH_RW_BKTLOCK = 1 << 2, | |
| 139 | 135 | /** spinlock to protect bucket */ |
| 140 | − CFS_HASH_SPIN_BKTLOCK = 1 << 3, | |
| 136 | + CFS_HASH_SPIN_BKTLOCK = 1 << 3, | |
| 141 | 137 | /** always add new item to tail */ |
| 142 | − CFS_HASH_ADD_TAIL = 1 << 4, | |
| 138 | + CFS_HASH_ADD_TAIL = 1 << 4, | |
| 143 | 139 | /** hash-table doesn't have refcount on item */ |
| 144 | − CFS_HASH_NO_ITEMREF = 1 << 5, | |
| 140 | + CFS_HASH_NO_ITEMREF = 1 << 5, | |
| 145 | 141 | /** big name for param-tree */ |
| 146 | 142 | CFS_HASH_BIGNAME = 1 << 6, |
| 147 | 143 | /** track global count */ |
| 148 | 144 | CFS_HASH_COUNTER = 1 << 7, |
| 149 | 145 | /** rehash item by new key */ |
| 150 | − CFS_HASH_REHASH_KEY = 1 << 8, | |
| 146 | + CFS_HASH_REHASH_KEY = 1 << 8, | |
| 151 | 147 | /** Enable dynamic hash resizing */ |
| 152 | − CFS_HASH_REHASH = 1 << 9, | |
| 148 | + CFS_HASH_REHASH = 1 << 9, | |
| 153 | 149 | /** can shrink hash-size */ |
| 154 | − CFS_HASH_SHRINK = 1 << 10, | |
| 150 | + CFS_HASH_SHRINK = 1 << 10, | |
| 155 | 151 | /** assert hash is empty on exit */ |
| 156 | − CFS_HASH_ASSERT_EMPTY = 1 << 11, | |
| 152 | + CFS_HASH_ASSERT_EMPTY = 1 << 11, | |
| 157 | 153 | /** record hlist depth */ |
| 158 | − CFS_HASH_DEPTH = 1 << 12, | |
| 154 | + CFS_HASH_DEPTH = 1 << 12, | |
| 159 | 155 | /** |
| 160 | 156 | * rehash is always scheduled in a different thread, so current |
| 161 | 157 | * change on hash table is non-blocking |
| 162 | 158 | */ |
| 163 | − CFS_HASH_NBLK_CHANGE = 1 << 13, | |
| 159 | + CFS_HASH_NBLK_CHANGE = 1 << 13, | |
| 164 | 160 | /** NB, we typed hs_flags as __u16, please change it |
| 165 | 161 | * if you need to extend >=16 flags */ |
| 166 | 162 | }; |
| 167 | 163 | |
| 168 | 164 | /** most used attributes */ |
| 169 | −#define CFS_HASH_DEFAULT (CFS_HASH_RW_BKTLOCK | \ | |
| 170 | − CFS_HASH_COUNTER | CFS_HASH_REHASH) | |
| 165 | +#define CFS_HASH_DEFAULT (CFS_HASH_RW_BKTLOCK | \ | |
| 166 | + CFS_HASH_COUNTER | CFS_HASH_REHASH) | |
| 171 | 167 | |
| 172 | 168 | /** |
| 173 | 169 | * cfs_hash is a hash-table implementation for general purpose, it can support: |
| @@ -211,7 +207,7 @@ enum cfs_hash_tag { · 37 unmodified lines | ||
| 211 | 207 | struct cfs_hash { |
| 212 | 208 | /** serialize with rehash, or serialize all operations if |
| 213 | 209 | * the hash-table has CFS_HASH_NO_BKTLOCK */ |
| 214 | − union cfs_hash_lock hs_lock; | |
| 210 | + union cfs_hash_lock hs_lock; | |
| 215 | 211 | /** hash operations */ |
| 216 | 212 | struct cfs_hash_ops *hs_ops; |
| 217 | 213 | /** hash lock operations */ |
| @@ -219,57 +215,57 @@ struct cfs_hash { · 1 unmodified line | ||
| 219 | 215 | /** hash list operations */ |
| 220 | 216 | struct cfs_hash_hlist_ops *hs_hops; |
| 221 | 217 | /** hash buckets-table */ |
| 222 | − struct cfs_hash_bucket **hs_buckets; | |
| 218 | + struct cfs_hash_bucket **hs_buckets; | |
| 223 | 219 | /** total number of items on this hash-table */ |
| 224 | − atomic_t hs_count; | |
| 220 | + atomic_t hs_count; | |
| 225 | 221 | /** hash flags, see cfs_hash_tag for detail */ |
| 226 | − __u16 hs_flags; | |
| 222 | + __u16 hs_flags; | |
| 227 | 223 | /** # of extra-bytes for bucket, for user saving extended attributes */ |
| 228 | − __u16 hs_extra_bytes; | |
| 224 | + __u16 hs_extra_bytes; | |
| 229 | 225 | /** wants to iterate */ |
| 230 | − __u8 hs_iterating; | |
| 226 | + __u8 hs_iterating; | |
| 231 | 227 | /** hash-table is dying */ |
| 232 | − __u8 hs_exiting; | |
| 228 | + __u8 hs_exiting; | |
| 233 | 229 | /** current hash bits */ |
| 234 | − __u8 hs_cur_bits; | |
| 230 | + __u8 hs_cur_bits; | |
| 235 | 231 | /** min hash bits */ |
| 236 | − __u8 hs_min_bits; | |
| 232 | + __u8 hs_min_bits; | |
| 237 | 233 | /** max hash bits */ |
| 238 | − __u8 hs_max_bits; | |
| 234 | + __u8 hs_max_bits; | |
| 239 | 235 | /** bits for rehash */ |
| 240 | − __u8 hs_rehash_bits; | |
| 236 | + __u8 hs_rehash_bits; | |
| 241 | 237 | /** bits for each bucket */ |
| 242 | − __u8 hs_bkt_bits; | |
| 238 | + __u8 hs_bkt_bits; | |
| 243 | 239 | /** resize min threshold */ |
| 244 | − __u16 hs_min_theta; | |
| 240 | + __u16 hs_min_theta; | |
| 245 | 241 | /** resize max threshold */ |
| 246 | − __u16 hs_max_theta; | |
| 242 | + __u16 hs_max_theta; | |
| 247 | 243 | /** resize count */ |
| 248 | − __u32 hs_rehash_count; | |
| 244 | + __u32 hs_rehash_count; | |
| 249 | 245 | /** # of iterators (caller of cfs_hash_for_each_*) */ |
| 250 | − __u32 hs_iterators; | |
| 246 | + __u32 hs_iterators; | |
| 251 | 247 | /** rehash workitem */ |
| 252 | − cfs_workitem_t hs_rehash_wi; | |
| 248 | + cfs_workitem_t hs_rehash_wi; | |
| 253 | 249 | /** refcount on this hash table */ |
| 254 | − atomic_t hs_refcount; | |
| 250 | + atomic_t hs_refcount; | |
| 255 | 251 | /** rehash buckets-table */ |
| 256 | − struct cfs_hash_bucket **hs_rehash_buckets; | |
| 252 | + struct cfs_hash_bucket **hs_rehash_buckets; | |
| 257 | 253 | #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1 |
| 258 | 254 | /** serialize debug members */ |
| 259 | 255 | spinlock_t hs_dep_lock; |
| 260 | 256 | /** max depth */ |
| 261 | − unsigned int hs_dep_max; | |
| 257 | + unsigned int hs_dep_max; | |
| 262 | 258 | /** id of the deepest bucket */ |
| 263 | − unsigned int hs_dep_bkt; | |
| 259 | + unsigned int hs_dep_bkt; | |
| 264 | 260 | /** offset in the deepest bucket */ |
| 265 | − unsigned int hs_dep_off; | |
| 261 | + unsigned int hs_dep_off; | |
| 266 | 262 | /** bits when we found the max depth */ |
| 267 | − unsigned int hs_dep_bits; | |
| 263 | + unsigned int hs_dep_bits; | |
| 268 | 264 | /** workitem to output max depth */ |
| 269 | − cfs_workitem_t hs_dep_wi; | |
| 265 | + cfs_workitem_t hs_dep_wi; | |
| 270 | 266 | #endif |
| 271 | 267 | /** name of htable */ |
| 272 | − char hs_name[0]; | |
| 268 | + char hs_name[0]; | |
| 273 | 269 | }; |
| 274 | 270 | |
| 275 | 271 | struct cfs_hash_lock_ops { |
| @@ -324,11 +320,11 @@ struct cfs_hash_ops { · 48 unmodified lines | ||
| 324 | 320 | }; |
| 325 | 321 | |
| 326 | 322 | /** total number of buckets in @hs */ |
| 327 | −#define CFS_HASH_NBKT(hs) \ | |
| 323 | +#define CFS_HASH_NBKT(hs) \ | |
| 328 | 324 | (1U << ((hs)->hs_cur_bits - (hs)->hs_bkt_bits)) |
| 329 | 325 | |
| 330 | 326 | /** total number of buckets in @hs while rehashing */ |
| 331 | −#define CFS_HASH_RH_NBKT(hs) \ | |
| 327 | +#define CFS_HASH_RH_NBKT(hs) \ | |
| 332 | 328 | (1U << ((hs)->hs_rehash_bits - (hs)->hs_bkt_bits)) |
| 333 | 329 | |
| 334 | 330 | /** number of hlist for in bucket */ |
| @@ -433,19 +429,22 @@ cfs_hash_with_nblk_change(struct cfs_hash *hs) · 98 unmodified lines | ||
| 433 | 429 | |
| 434 | 430 | static inline int |
| 435 | 431 | cfs_hash_is_exiting(struct cfs_hash *hs) |
| 436 | −{ /* cfs_hash_destroy is called */ | |
| 432 | +{ | |
| 433 | + /* cfs_hash_destroy is called */ | |
| 437 | 434 | return hs->hs_exiting; |
| 438 | 435 | } |
| 439 | 436 | |
| 440 | 437 | static inline int |
| 441 | 438 | cfs_hash_is_rehashing(struct cfs_hash *hs) |
| 442 | −{ /* rehash is launched */ | |
| 439 | +{ | |
| 440 | + /* rehash is launched */ | |
| 443 | 441 | return hs->hs_rehash_bits != 0; |
| 444 | 442 | } |
| 445 | 443 | |
| 446 | 444 | static inline int |
| 447 | 445 | cfs_hash_is_iterating(struct cfs_hash *hs) |
| 448 | −{ /* someone is calling cfs_hash_for_each_* */ | |
| 446 | +{ | |
| 447 | + /* someone is calling cfs_hash_for_each_* */ | |
| 449 | 448 | return hs->hs_iterating || hs->hs_iterators != 0; |
| 450 | 449 | } |
| 451 | 450 | |
| @@ -641,13 +640,6 @@ cfs_hash_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, · 189 unmodified lines | ||
| 641 | 640 | struct hlist_node * |
| 642 | 641 | cfs_hash_bd_peek_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, |
| 643 | 642 | const void *key); |
| 644 | −struct hlist_node * | |
| 645 | −cfs_hash_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, | |
| 646 | − const void *key, struct hlist_node *hnode, | |
| 647 | − int insist_add); | |
| 648 | −struct hlist_node * | |
| 649 | −cfs_hash_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, | |
| 650 | − const void *key, struct hlist_node *hnode); | |
| 651 | 643 | |
| 652 | 644 | /** |
| 653 | 645 | * operations on cfs_hash bucket (bd: bucket descriptor), |
| @@ -758,7 +750,7 @@ static inline void · 104 unmodified lines | ||
| 758 | 750 | cfs_hash_bucket_validate(struct cfs_hash *hs, struct cfs_hash_bd *bd, |
| 759 | 751 | struct hlist_node *hnode) |
| 760 | 752 | { |
| 761 | − struct cfs_hash_bd bds[2]; | |
| 753 | + struct cfs_hash_bd bds[2]; | |
| 762 | 754 | |
| 763 | 755 | cfs_hash_dual_bd_get(hs, cfs_hash_key(hs, hnode), bds); |
| 764 | 756 | LASSERT(bds[0].bd_bucket == bd->bd_bucket || |
| @@ -777,9 +769,9 @@ cfs_hash_bucket_validate(struct cfs_hash *hs, struct cfs_hash_bd *bd, · 12 unmodified lines | ||
| 777 | 769 | |
| 778 | 770 | #endif /* CFS_HASH_DEBUG_LEVEL */ |
| 779 | 771 | |
| 780 | −#define CFS_HASH_THETA_BITS 10 | |
| 781 | −#define CFS_HASH_MIN_THETA (1U << (CFS_HASH_THETA_BITS - 1)) | |
| 782 | −#define CFS_HASH_MAX_THETA (1U << (CFS_HASH_THETA_BITS + 1)) | |
| 772 | +#define CFS_HASH_THETA_BITS 10 | |
| 773 | +#define CFS_HASH_MIN_THETA (1U << (CFS_HASH_THETA_BITS - 1)) | |
| 774 | +#define CFS_HASH_MAX_THETA (1U << (CFS_HASH_THETA_BITS + 1)) | |
| 783 | 775 | |
| 784 | 776 | /* Return integer component of theta */ |
| 785 | 777 | static inline int __cfs_hash_theta_int(int theta) |
| @@ -848,20 +840,20 @@ cfs_hash_u64_hash(const __u64 key, unsigned mask) · 62 unmodified lines | ||
| 848 | 840 | } |
| 849 | 841 | |
| 850 | 842 | /** iterate over all buckets in @bds (array of struct cfs_hash_bd) */ |
| 851 | −#define cfs_hash_for_each_bd(bds, n, i) \ | |
| 843 | +#define cfs_hash_for_each_bd(bds, n, i) \ | |
| 852 | 844 | for (i = 0; i < n && (bds)[i].bd_bucket != NULL; i++) |
| 853 | 845 | |
| 854 | 846 | /** iterate over all buckets of @hs */ |
| 855 | −#define cfs_hash_for_each_bucket(hs, bd, pos) \ | |
| 856 | − for (pos = 0; \ | |
| 857 | − pos < CFS_HASH_NBKT(hs) && \ | |
| 847 | +#define cfs_hash_for_each_bucket(hs, bd, pos) \ | |
| 848 | + for (pos = 0; \ | |
| 849 | + pos < CFS_HASH_NBKT(hs) && \ | |
| 858 | 850 | ((bd)->bd_bucket = (hs)->hs_buckets[pos]) != NULL; pos++) |
| 859 | 851 | |
| 860 | 852 | /** iterate over all hlist of bucket @bd */ |
| 861 | −#define cfs_hash_bd_for_each_hlist(hs, bd, hlist) \ | |
| 862 | − for ((bd)->bd_offset = 0; \ | |
| 863 | − (bd)->bd_offset < CFS_HASH_BKT_NHLIST(hs) && \ | |
| 864 | − (hlist = cfs_hash_bd_hhead(hs, bd)) != NULL; \ | |
| 853 | +#define cfs_hash_bd_for_each_hlist(hs, bd, hlist) \ | |
| 854 | + for ((bd)->bd_offset = 0; \ | |
| 855 | + (bd)->bd_offset < CFS_HASH_BKT_NHLIST(hs) && \ | |
| 856 | + (hlist = cfs_hash_bd_hhead(hs, bd)) != NULL; \ | |
| 865 | 857 | (bd)->bd_offset++) |
| 866 | 858 | |
| 867 | 859 | /* !__LIBCFS__HASH_H__ */ |
| @@ -91,7 +91,7 @@ typedef int (*libcfs_kkuc_cb_t)(__u32 data, void *cb_arg); · 90 unmodified lines | ||
| 91 | 91 | /* Kernel methods */ |
| 92 | 92 | int libcfs_kkuc_msg_put(struct file *fp, void *payload); |
| 93 | 93 | int libcfs_kkuc_group_put(int group, void *payload); |
| 94 | −int libcfs_kkuc_group_add(struct file *fp, int uid, int group, | |
| 94 | +int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, | |
| 95 | 95 | __u32 data); |
| 96 | 96 | int libcfs_kkuc_group_rem(int uid, int group); |
| 97 | 97 | int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, |
| @@ -185,8 +185,6 @@ int libcfs_debug_cleanup(void); · 184 unmodified lines | ||
| 185 | 185 | int libcfs_debug_clear_buffer(void); |
| 186 | 186 | int libcfs_debug_mark_buffer(const char *text); |
| 187 | 187 | |
| 188 | −void libcfs_debug_set_level(unsigned int debug_level); | |
| 189 | − | |
| 190 | 188 | /* |
| 191 | 189 | * allocate per-cpu-partition data, returned value is an array of pointers, |
| 192 | 190 | * variable can be indexed by CPU ID. |
| @@ -161,12 +161,6 @@ int LNetEQAlloc(unsigned int count_in, · 160 unmodified lines | ||
| 161 | 161 | |
| 162 | 162 | int LNetEQFree(lnet_handle_eq_t eventq_in); |
| 163 | 163 | |
| 164 | −int LNetEQGet(lnet_handle_eq_t eventq_in, | |
| 165 | − lnet_event_t *event_out); | |
| 166 | − | |
| 167 | −int LNetEQWait(lnet_handle_eq_t eventq_in, | |
| 168 | − lnet_event_t *event_out); | |
| 169 | − | |
| 170 | 164 | int LNetEQPoll(lnet_handle_eq_t *eventqs_in, |
| 171 | 165 | int neq_in, |
| 172 | 166 | int timeout_ms, |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | 24 | * Use is subject to license terms. |
| 25 | 25 | * |
| 26 | − * Copyright (c) 2012 - 2015, Intel Corporation. | |
| 26 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 27 | 27 | */ |
| 28 | 28 | /* |
| 29 | 29 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | 24 | * Use is subject to license terms. |
| 25 | 25 | * |
| 26 | − * Copyright (c) 2012 - 2015, Intel Corporation. | |
| 26 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 27 | 27 | */ |
| 28 | 28 | /* |
| 29 | 29 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | 24 | * Use is subject to license terms. |
| 25 | 25 | * |
| 26 | − * Copyright (c) 2011 - 2015, Intel Corporation. | |
| 26 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 27 | 27 | */ |
| 28 | 28 | #ifndef _LNET_NIDSTRINGS_H |
| 29 | 29 | #define _LNET_NIDSTRINGS_H |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -2865,7 +2865,7 @@ static int __init kiblnd_module_init(void) · 2831 unmodified lines | ||
| 2865 | 2865 | return 0; |
| 2866 | 2866 | } |
| 2867 | 2867 | |
| 2868 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 2868 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 2869 | 2869 | MODULE_DESCRIPTION("Kernel OpenIB gen2 LND v2.00"); |
| 2870 | 2870 | MODULE_LICENSE("GPL"); |
| 2871 | 2871 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -2621,8 +2621,8 @@ ksocknal_enumerate_interfaces(ksock_net_t *net) · 2587 unmodified lines | ||
| 2621 | 2621 | |
| 2622 | 2622 | net->ksnn_interfaces[j].ksni_ipaddr = ip; |
| 2623 | 2623 | net->ksnn_interfaces[j].ksni_netmask = mask; |
| 2624 | − strncpy(&net->ksnn_interfaces[j].ksni_name[0], | |
| 2625 | − names[i], IFNAMSIZ); | |
| 2624 | + strlcpy(net->ksnn_interfaces[j].ksni_name, | |
| 2625 | + names[i], sizeof(net->ksnn_interfaces[j].ksni_name)); | |
| 2626 | 2626 | j++; |
| 2627 | 2627 | } |
| 2628 | 2628 | |
| @@ -2805,8 +2805,9 @@ ksocknal_startup(lnet_ni_t *ni) · 176 unmodified lines | ||
| 2805 | 2805 | goto fail_1; |
| 2806 | 2806 | } |
| 2807 | 2807 | |
| 2808 | − strncpy(&net->ksnn_interfaces[i].ksni_name[0], | |
| 2809 | − ni->ni_interfaces[i], IFNAMSIZ); | |
| 2808 | + strlcpy(net->ksnn_interfaces[i].ksni_name, | |
| 2809 | + ni->ni_interfaces[i], | |
| 2810 | + sizeof(net->ksnn_interfaces[i].ksni_name)); | |
| 2810 | 2811 | } |
| 2811 | 2812 | net->ksnn_ninterfaces = i; |
| 2812 | 2813 | } |
| @@ -2868,7 +2869,7 @@ ksocknal_module_init(void) · 55 unmodified lines | ||
| 2868 | 2869 | return 0; |
| 2869 | 2870 | } |
| 2870 | 2871 | |
| 2871 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 2872 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 2872 | 2873 | MODULE_DESCRIPTION("Kernel TCP Socket LND v3.0.0"); |
| 2873 | 2874 | MODULE_LICENSE("GPL"); |
| 2874 | 2875 | MODULE_VERSION("3.0.0"); |
| @@ -679,6 +679,9 @@ int ksocknal_lib_recv_kiov(ksock_conn_t *conn); · 678 unmodified lines | ||
| 679 | 679 | int ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem, |
| 680 | 680 | int *rxmem, int *nagle); |
| 681 | 681 | |
| 682 | +void ksocknal_read_callback(ksock_conn_t *conn); | |
| 683 | +void ksocknal_write_callback(ksock_conn_t *conn); | |
| 684 | + | |
| 682 | 685 | int ksocknal_tunables_init(void); |
| 683 | 686 | |
| 684 | 687 | void ksocknal_lib_csum_tx(ksock_tx_t *tx); |
| @@ -580,8 +580,6 @@ ksocknal_lib_push_conn(ksock_conn_t *conn) · 579 unmodified lines | ||
| 580 | 580 | ksocknal_connsock_decref(conn); |
| 581 | 581 | } |
| 582 | 582 | |
| 583 | −extern void ksocknal_read_callback(ksock_conn_t *conn); | |
| 584 | −extern void ksocknal_write_callback(ksock_conn_t *conn); | |
| 585 | 583 | /* |
| 586 | 584 | * socket call back in Linux |
| 587 | 585 | */ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -354,16 +354,6 @@ lnet_counters_reset(void) · 320 unmodified lines | ||
| 354 | 354 | |
| 355 | 355 | lnet_net_unlock(LNET_LOCK_EX); |
| 356 | 356 | } |
| 357 | −EXPORT_SYMBOL(lnet_counters_reset); | |
| 358 | − | |
| 359 | −static __u64 | |
| 360 | −lnet_create_interface_cookie(void) | |
| 361 | −{ | |
| 362 | − /* NB the interface cookie in wire handles guards against delayed | |
| 363 | − * replies and ACKs appearing valid after reboot. | |
| 364 | − */ | |
| 365 | − return ktime_get_ns(); | |
| 366 | −} | |
| 367 | 357 | |
| 368 | 358 | static char * |
| 369 | 359 | lnet_res_type2str(int type) |
| @@ -553,8 +543,11 @@ lnet_prepare(lnet_pid_t requested_pid) · 183 unmodified lines | ||
| 553 | 543 | rc = lnet_create_remote_nets_table(); |
| 554 | 544 | if (rc != 0) |
| 555 | 545 | goto failed; |
| 556 | − | |
| 557 | − the_lnet.ln_interface_cookie = lnet_create_interface_cookie(); | |
| 546 | + /* | |
| 547 | + * NB the interface cookie in wire handles guards against delayed | |
| 548 | + * replies and ACKs appearing valid after reboot. | |
| 549 | + */ | |
| 550 | + the_lnet.ln_interface_cookie = ktime_get_ns(); | |
| 558 | 551 | |
| 559 | 552 | the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(), |
| 560 | 553 | sizeof(lnet_counters_t)); |
| @@ -1159,7 +1152,6 @@ lnet_init(void) · 598 unmodified lines | ||
| 1159 | 1152 | lnet_register_lnd(&the_lolnd); |
| 1160 | 1153 | return 0; |
| 1161 | 1154 | } |
| 1162 | −EXPORT_SYMBOL(lnet_init); | |
| 1163 | 1155 | |
| 1164 | 1156 | /** |
| 1165 | 1157 | * Finalize LNet library. |
| @@ -1183,7 +1175,6 @@ lnet_fini(void) · 17 unmodified lines | ||
| 1183 | 1175 | |
| 1184 | 1176 | the_lnet.ln_init = 0; |
| 1185 | 1177 | } |
| 1186 | −EXPORT_SYMBOL(lnet_fini); | |
| 1187 | 1178 | |
| 1188 | 1179 | /** |
| 1189 | 1180 | * Set LNet PID and start LNet interfaces, routing, and forwarding. |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -650,8 +650,8 @@ lnet_parse_route(char *str, int *im_a_router) · 616 unmodified lines | ||
| 650 | 650 | INIT_LIST_HEAD(&nets); |
| 651 | 651 | |
| 652 | 652 | /* save a copy of the string for error messages */ |
| 653 | − strncpy(cmd, str, sizeof(cmd) - 1); | |
| 654 | − cmd[sizeof(cmd) - 1] = 0; | |
| 653 | + strncpy(cmd, str, sizeof(cmd)); | |
| 654 | + cmd[sizeof(cmd) - 1] = '\0'; | |
| 655 | 655 | |
| 656 | 656 | sep = str; |
| 657 | 657 | for (;;) { |
| @@ -972,11 +972,13 @@ lnet_splitnets(char *source, struct list_head *nets) · 314 unmodified lines | ||
| 972 | 972 | return 0; |
| 973 | 973 | |
| 974 | 974 | offset += (int)(sep - tb->ltb_text); |
| 975 | − tb2 = lnet_new_text_buf(strlen(sep)); | |
| 975 | + len = strlen(sep); | |
| 976 | + tb2 = lnet_new_text_buf(len); | |
| 976 | 977 | if (tb2 == NULL) |
| 977 | 978 | return -ENOMEM; |
| 978 | 979 | |
| 979 | − strcpy(tb2->ltb_text, sep); | |
| 980 | + strncpy(tb2->ltb_text, sep, len); | |
| 981 | + tb2->ltb_text[len] = '\0'; | |
| 980 | 982 | list_add_tail(&tb2->ltb_list, nets); |
| 981 | 983 | |
| 982 | 984 | tb = tb2; |
| @@ -1021,8 +1023,8 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) · 38 unmodified lines | ||
| 1021 | 1023 | tb = list_entry(raw_entries.next, struct lnet_text_buf_t, |
| 1022 | 1024 | ltb_list); |
| 1023 | 1025 | |
| 1024 | − strncpy(source, tb->ltb_text, sizeof(source)-1); | |
| 1025 | − source[sizeof(source)-1] = 0; | |
| 1026 | + strncpy(source, tb->ltb_text, sizeof(source)); | |
| 1027 | + source[sizeof(source)-1] = '\0'; | |
| 1026 | 1028 | |
| 1027 | 1029 | /* replace ltb_text with the network(s) add on match */ |
| 1028 | 1030 | rc = lnet_match_network_tokens(tb->ltb_text, ipaddrs, nip); |
| @@ -1103,12 +1105,6 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) · 74 unmodified lines | ||
| 1103 | 1105 | return count; |
| 1104 | 1106 | } |
| 1105 | 1107 | |
| 1106 | −static void | |
| 1107 | −lnet_ipaddr_free_enumeration(__u32 *ipaddrs, int nip) | |
| 1108 | −{ | |
| 1109 | − LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); | |
| 1110 | −} | |
| 1111 | − | |
| 1112 | 1108 | static int |
| 1113 | 1109 | lnet_ipaddr_enumerate(__u32 **ipaddrsp) |
| 1114 | 1110 | { |
| @@ -1169,7 +1165,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp) · 54 unmodified lines | ||
| 1169 | 1165 | rc = nip; |
| 1170 | 1166 | } |
| 1171 | 1167 | } |
| 1172 | − lnet_ipaddr_free_enumeration(ipaddrs, nif); | |
| 1168 | + LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); | |
| 1173 | 1169 | } |
| 1174 | 1170 | return nip; |
| 1175 | 1171 | } |
| @@ -1195,7 +1191,7 @@ lnet_parse_ip2nets(char **networksp, char *ip2nets) · 19 unmodified lines | ||
| 1195 | 1191 | } |
| 1196 | 1192 | |
| 1197 | 1193 | rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip); |
| 1198 | − lnet_ipaddr_free_enumeration(ipaddrs, nip); | |
| 1194 | + LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); | |
| 1199 | 1195 | |
| 1200 | 1196 | if (rc < 0) { |
| 1201 | 1197 | LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc); |
| @@ -282,15 +282,6 @@ lnet_eq_dequeue_event(lnet_eq_t *eq, lnet_event_t *ev) · 281 unmodified lines | ||
| 282 | 282 | * at least one event between this event and the last event obtained from the |
| 283 | 283 | * EQ has been dropped due to limited space in the EQ. |
| 284 | 284 | */ |
| 285 | −int | |
| 286 | −LNetEQGet(lnet_handle_eq_t eventq, lnet_event_t *event) | |
| 287 | −{ | |
| 288 | − int which; | |
| 289 | − | |
| 290 | − return LNetEQPoll(&eventq, 1, 0, | |
| 291 | − event, &which); | |
| 292 | −} | |
| 293 | −EXPORT_SYMBOL(LNetEQGet); | |
| 294 | 285 | |
| 295 | 286 | /** |
| 296 | 287 | * Block the calling process until there is an event in the EQ. |
| @@ -308,15 +299,6 @@ EXPORT_SYMBOL(LNetEQGet); · 11 unmodified lines | ||
| 308 | 299 | * at least one event between this event and the last event obtained from the |
| 309 | 300 | * EQ has been dropped due to limited space in the EQ. |
| 310 | 301 | */ |
| 311 | −int | |
| 312 | −LNetEQWait(lnet_handle_eq_t eventq, lnet_event_t *event) | |
| 313 | −{ | |
| 314 | − int which; | |
| 315 | − | |
| 316 | − return LNetEQPoll(&eventq, 1, LNET_TIME_FOREVER, | |
| 317 | − event, &which); | |
| 318 | −} | |
| 319 | −EXPORT_SYMBOL(LNetEQWait); | |
| 320 | 302 | |
| 321 | 303 | static int |
| 322 | 304 | lnet_eq_wait_locked(int *timeout_ms) |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -1645,7 +1645,6 @@ lnet_msgtyp2str(int type) · 1611 unmodified lines | ||
| 1645 | 1645 | return "<UNKNOWN>"; |
| 1646 | 1646 | } |
| 1647 | 1647 | } |
| 1648 | −EXPORT_SYMBOL(lnet_msgtyp2str); | |
| 1649 | 1648 | |
| 1650 | 1649 | void |
| 1651 | 1650 | lnet_print_hdr(lnet_hdr_t *hdr) |
| @@ -21,7 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | * GPL HEADER END |
| 22 | 22 | */ |
| 23 | 23 | /* |
| 24 | − * Copyright (c) 2012, Intel Corporation. | |
| 24 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 25 | 25 | */ |
| 26 | 26 | /* |
| 27 | 27 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | 24 | * Use is subject to license terms. |
| 25 | 25 | * |
| 26 | − * Copyright (c) 2012, 2015 Intel Corporation. | |
| 26 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 27 | 27 | */ |
| 28 | 28 | /* |
| 29 | 29 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -146,7 +146,7 @@ fini_lnet(void) · 112 unmodified lines | ||
| 146 | 146 | lnet_fini(); |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | −MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>"); | |
| 149 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 150 | 150 | MODULE_DESCRIPTION("LNet v3.1"); |
| 151 | 151 | MODULE_LICENSE("GPL"); |
| 152 | 152 | MODULE_VERSION("1.0.0"); |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 3 | 3 | * |
| 4 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 4 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 5 | 5 | * |
| 6 | 6 | * This file is part of Portals |
| 7 | 7 | * http://sourceforge.net/projects/sandiaportals/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -358,7 +358,7 @@ out: · 324 unmodified lines | ||
| 358 | 358 | } |
| 359 | 359 | |
| 360 | 360 | static void |
| 361 | −brw_server_rpc_done(srpc_server_rpc_t *rpc) | |
| 361 | +brw_server_rpc_done(struct srpc_server_rpc *rpc) | |
| 362 | 362 | { |
| 363 | 363 | srpc_bulk_t *blk = rpc->srpc_bulk; |
| 364 | 364 | |
| @@ -378,7 +378,7 @@ brw_server_rpc_done(srpc_server_rpc_t *rpc) · 13 unmodified lines | ||
| 378 | 378 | } |
| 379 | 379 | |
| 380 | 380 | static int |
| 381 | −brw_bulk_ready(srpc_server_rpc_t *rpc, int status) | |
| 381 | +brw_bulk_ready(struct srpc_server_rpc *rpc, int status) | |
| 382 | 382 | { |
| 383 | 383 | __u64 magic = BRW_MAGIC; |
| 384 | 384 | srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply; |
| @@ -925,5 +925,3 @@ out: · 924 unmodified lines | ||
| 925 | 925 | |
| 926 | 926 | return rc; |
| 927 | 927 | } |
| 928 | − | |
| 929 | −EXPORT_SYMBOL(lstcon_ioctl_entry); | |
| @@ -612,8 +612,8 @@ lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, · 611 unmodified lines | ||
| 612 | 612 | msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst; |
| 613 | 613 | msrq->mksn_sid = console_session.ses_id; |
| 614 | 614 | msrq->mksn_force = console_session.ses_force; |
| 615 | − strncpy(msrq->mksn_name, console_session.ses_name, | |
| 616 | − strlen(console_session.ses_name)); | |
| 615 | + strlcpy(msrq->mksn_name, console_session.ses_name, | |
| 616 | + sizeof(msrq->mksn_name)); | |
| 617 | 617 | break; |
| 618 | 618 | |
| 619 | 619 | case LST_TRANS_SESEND: |
| @@ -277,12 +277,6 @@ lstcon_group_find(const char *name, lstcon_group_t **grpp) · 276 unmodified lines | ||
| 277 | 277 | return -ENOENT; |
| 278 | 278 | } |
| 279 | 279 | |
| 280 | −static void | |
| 281 | −lstcon_group_put(lstcon_group_t *grp) | |
| 282 | −{ | |
| 283 | − lstcon_group_decref(grp); | |
| 284 | −} | |
| 285 | − | |
| 286 | 280 | static int |
| 287 | 281 | lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, |
| 288 | 282 | lstcon_ndlink_t **ndlpp, int create) |
| @@ -324,8 +318,6 @@ lstcon_group_ndlink_move(lstcon_group_t *old, · 35 unmodified lines | ||
| 324 | 318 | list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]); |
| 325 | 319 | list_add_tail(&ndl->ndl_link, &new->grp_ndl_list); |
| 326 | 320 | new->grp_nnode++; |
| 327 | − | |
| 328 | − return; | |
| 329 | 321 | } |
| 330 | 322 | |
| 331 | 323 | static void |
| @@ -436,7 +428,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, · 104 unmodified lines | ||
| 436 | 428 | } |
| 437 | 429 | |
| 438 | 430 | if (rc != 0) { |
| 439 | − lstcon_group_put(tmp); | |
| 431 | + lstcon_group_decref(tmp); | |
| 440 | 432 | return rc; |
| 441 | 433 | } |
| 442 | 434 | |
| @@ -445,7 +437,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, · 2 unmodified lines | ||
| 445 | 437 | tmp, lstcon_sesrpc_condition, &trans); |
| 446 | 438 | if (rc != 0) { |
| 447 | 439 | CERROR("Can't create transaction: %d\n", rc); |
| 448 | − lstcon_group_put(tmp); | |
| 440 | + lstcon_group_decref(tmp); | |
| 449 | 441 | return rc; |
| 450 | 442 | } |
| 451 | 443 | |
| @@ -460,7 +452,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, · 8 unmodified lines | ||
| 460 | 452 | lstcon_rpc_trans_destroy(trans); |
| 461 | 453 | |
| 462 | 454 | lstcon_group_move(tmp, grp); |
| 463 | − lstcon_group_put(tmp); | |
| 455 | + lstcon_group_decref(tmp); | |
| 464 | 456 | |
| 465 | 457 | return rc; |
| 466 | 458 | } |
| @@ -510,12 +502,12 @@ lstcon_group_nodes_remove(lstcon_group_t *grp, · 43 unmodified lines | ||
| 510 | 502 | |
| 511 | 503 | lstcon_rpc_trans_destroy(trans); |
| 512 | 504 | /* release nodes anyway, because we can't rollback status */ |
| 513 | − lstcon_group_put(tmp); | |
| 505 | + lstcon_group_decref(tmp); | |
| 514 | 506 | |
| 515 | 507 | return rc; |
| 516 | 508 | error: |
| 517 | 509 | lstcon_group_move(tmp, grp); |
| 518 | − lstcon_group_put(tmp); | |
| 510 | + lstcon_group_decref(tmp); | |
| 519 | 511 | |
| 520 | 512 | return rc; |
| 521 | 513 | } |
| @@ -529,7 +521,7 @@ lstcon_group_add(char *name) · 7 unmodified lines | ||
| 529 | 521 | rc = (lstcon_group_find(name, &grp) == 0) ? -EEXIST : 0; |
| 530 | 522 | if (rc != 0) { |
| 531 | 523 | /* find a group with same name */ |
| 532 | − lstcon_group_put(grp); | |
| 524 | + lstcon_group_decref(grp); | |
| 533 | 525 | return rc; |
| 534 | 526 | } |
| 535 | 527 | |
| @@ -563,14 +555,14 @@ lstcon_nodes_add(char *name, int count, lnet_process_id_t *ids_up, · 27 unmodified lines | ||
| 563 | 555 | if (grp->grp_ref > 2) { |
| 564 | 556 | /* referred by other threads or test */ |
| 565 | 557 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 566 | − lstcon_group_put(grp); | |
| 558 | + lstcon_group_decref(grp); | |
| 567 | 559 | |
| 568 | 560 | return -EBUSY; |
| 569 | 561 | } |
| 570 | 562 | |
| 571 | 563 | rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up); |
| 572 | 564 | |
| 573 | − lstcon_group_put(grp); | |
| 565 | + lstcon_group_decref(grp); | |
| 574 | 566 | |
| 575 | 567 | return rc; |
| 576 | 568 | } |
| @@ -591,7 +583,7 @@ lstcon_group_del(char *name) · 14 unmodified lines | ||
| 591 | 583 | if (grp->grp_ref > 2) { |
| 592 | 584 | /* referred by others threads or test */ |
| 593 | 585 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 594 | − lstcon_group_put(grp); | |
| 586 | + lstcon_group_decref(grp); | |
| 595 | 587 | return -EBUSY; |
| 596 | 588 | } |
| 597 | 589 | |
| @@ -600,7 +592,7 @@ lstcon_group_del(char *name) · 2 unmodified lines | ||
| 600 | 592 | grp, lstcon_sesrpc_condition, &trans); |
| 601 | 593 | if (rc != 0) { |
| 602 | 594 | CERROR("Can't create transaction: %d\n", rc); |
| 603 | − lstcon_group_put(grp); | |
| 595 | + lstcon_group_decref(grp); | |
| 604 | 596 | return rc; |
| 605 | 597 | } |
| 606 | 598 | |
| @@ -608,10 +600,10 @@ lstcon_group_del(char *name) · 1 unmodified line | ||
| 608 | 600 | |
| 609 | 601 | lstcon_rpc_trans_destroy(trans); |
| 610 | 602 | |
| 611 | − lstcon_group_put(grp); | |
| 603 | + lstcon_group_decref(grp); | |
| 612 | 604 | /* -ref for session, it's destroyed, |
| 613 | 605 | * status can't be rolled back, destroy group anyway */ |
| 614 | − lstcon_group_put(grp); | |
| 606 | + lstcon_group_decref(grp); | |
| 615 | 607 | |
| 616 | 608 | return rc; |
| 617 | 609 | } |
| @@ -631,7 +623,7 @@ lstcon_group_clean(char *name, int args) · 13 unmodified lines | ||
| 631 | 623 | if (grp->grp_ref > 2) { |
| 632 | 624 | /* referred by test */ |
| 633 | 625 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 634 | − lstcon_group_put(grp); | |
| 626 | + lstcon_group_decref(grp); | |
| 635 | 627 | return -EBUSY; |
| 636 | 628 | } |
| 637 | 629 | |
| @@ -640,10 +632,10 @@ lstcon_group_clean(char *name, int args) · 2 unmodified lines | ||
| 640 | 632 | |
| 641 | 633 | lstcon_group_drain(grp, args); |
| 642 | 634 | |
| 643 | − lstcon_group_put(grp); | |
| 635 | + lstcon_group_decref(grp); | |
| 644 | 636 | /* release empty group */ |
| 645 | 637 | if (list_empty(&grp->grp_ndl_list)) |
| 646 | − lstcon_group_put(grp); | |
| 638 | + lstcon_group_decref(grp); | |
| 647 | 639 | |
| 648 | 640 | return 0; |
| 649 | 641 | } |
| @@ -664,16 +656,16 @@ lstcon_nodes_remove(char *name, int count, · 14 unmodified lines | ||
| 664 | 656 | if (grp->grp_ref > 2) { |
| 665 | 657 | /* referred by test */ |
| 666 | 658 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 667 | − lstcon_group_put(grp); | |
| 659 | + lstcon_group_decref(grp); | |
| 668 | 660 | return -EBUSY; |
| 669 | 661 | } |
| 670 | 662 | |
| 671 | 663 | rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up); |
| 672 | 664 | |
| 673 | − lstcon_group_put(grp); | |
| 665 | + lstcon_group_decref(grp); | |
| 674 | 666 | /* release empty group */ |
| 675 | 667 | if (list_empty(&grp->grp_ndl_list)) |
| 676 | − lstcon_group_put(grp); | |
| 668 | + lstcon_group_decref(grp); | |
| 677 | 669 | |
| 678 | 670 | return rc; |
| 679 | 671 | } |
| @@ -694,7 +686,7 @@ lstcon_group_refresh(char *name, struct list_head *result_up) · 14 unmodified lines | ||
| 694 | 686 | if (grp->grp_ref > 2) { |
| 695 | 687 | /* referred by test */ |
| 696 | 688 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 697 | − lstcon_group_put(grp); | |
| 689 | + lstcon_group_decref(grp); | |
| 698 | 690 | return -EBUSY; |
| 699 | 691 | } |
| 700 | 692 | |
| @@ -705,7 +697,7 @@ lstcon_group_refresh(char *name, struct list_head *result_up) · 4 unmodified lines | ||
| 705 | 697 | if (rc != 0) { |
| 706 | 698 | /* local error, return */ |
| 707 | 699 | CDEBUG(D_NET, "Can't create transaction: %d\n", rc); |
| 708 | − lstcon_group_put(grp); | |
| 700 | + lstcon_group_decref(grp); | |
| 709 | 701 | return rc; |
| 710 | 702 | } |
| 711 | 703 | |
| @@ -715,7 +707,7 @@ lstcon_group_refresh(char *name, struct list_head *result_up) · 3 unmodified lines | ||
| 715 | 707 | |
| 716 | 708 | lstcon_rpc_trans_destroy(trans); |
| 717 | 709 | /* -ref for me */ |
| 718 | − lstcon_group_put(grp); | |
| 710 | + lstcon_group_decref(grp); | |
| 719 | 711 | |
| 720 | 712 | return rc; |
| 721 | 713 | } |
| @@ -797,7 +789,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p, · 75 unmodified lines | ||
| 797 | 789 | /* verbose query */ |
| 798 | 790 | rc = lstcon_nodes_getent(&grp->grp_ndl_list, |
| 799 | 791 | index_p, count_p, dents_up); |
| 800 | − lstcon_group_put(grp); | |
| 792 | + lstcon_group_decref(grp); | |
| 801 | 793 | |
| 802 | 794 | return rc; |
| 803 | 795 | } |
| @@ -806,7 +798,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p, · 2 unmodified lines | ||
| 806 | 798 | LIBCFS_ALLOC(gentp, sizeof(lstcon_ndlist_ent_t)); |
| 807 | 799 | if (gentp == NULL) { |
| 808 | 800 | CERROR("Can't allocate ndlist_ent\n"); |
| 809 | − lstcon_group_put(grp); | |
| 801 | + lstcon_group_decref(grp); | |
| 810 | 802 | |
| 811 | 803 | return -ENOMEM; |
| 812 | 804 | } |
| @@ -819,7 +811,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p, · 6 unmodified lines | ||
| 819 | 811 | |
| 820 | 812 | LIBCFS_FREE(gentp, sizeof(lstcon_ndlist_ent_t)); |
| 821 | 813 | |
| 822 | − lstcon_group_put(grp); | |
| 814 | + lstcon_group_decref(grp); | |
| 823 | 815 | |
| 824 | 816 | return 0; |
| 825 | 817 | } |
| @@ -1096,8 +1088,8 @@ lstcon_batch_destroy(lstcon_batch_t *bat) · 270 unmodified lines | ||
| 1096 | 1088 | |
| 1097 | 1089 | list_del(&test->tes_link); |
| 1098 | 1090 | |
| 1099 | − lstcon_group_put(test->tes_src_grp); | |
| 1100 | − lstcon_group_put(test->tes_dst_grp); | |
| 1091 | + lstcon_group_decref(test->tes_src_grp); | |
| 1092 | + lstcon_group_decref(test->tes_dst_grp); | |
| 1101 | 1093 | |
| 1102 | 1094 | LIBCFS_FREE(test, offsetof(lstcon_test_t, |
| 1103 | 1095 | tes_param[test->tes_paramlen])); |
| @@ -1352,10 +1344,10 @@ out: · 248 unmodified lines | ||
| 1352 | 1344 | LIBCFS_FREE(test, offsetof(lstcon_test_t, tes_param[paramlen])); |
| 1353 | 1345 | |
| 1354 | 1346 | if (dst_grp != NULL) |
| 1355 | − lstcon_group_put(dst_grp); | |
| 1347 | + lstcon_group_decref(dst_grp); | |
| 1356 | 1348 | |
| 1357 | 1349 | if (src_grp != NULL) |
| 1358 | − lstcon_group_put(src_grp); | |
| 1350 | + lstcon_group_decref(src_grp); | |
| 1359 | 1351 | |
| 1360 | 1352 | return rc; |
| 1361 | 1353 | } |
| @@ -1518,7 +1510,7 @@ lstcon_group_stat(char *grp_name, int timeout, struct list_head *result_up) · 156 unmodified lines | ||
| 1518 | 1510 | |
| 1519 | 1511 | rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up); |
| 1520 | 1512 | |
| 1521 | − lstcon_group_put(grp); | |
| 1513 | + lstcon_group_decref(grp); | |
| 1522 | 1514 | |
| 1523 | 1515 | return rc; |
| 1524 | 1516 | } |
| @@ -1556,13 +1548,13 @@ lstcon_nodes_stat(int count, lnet_process_id_t *ids_up, · 31 unmodified lines | ||
| 1556 | 1548 | } |
| 1557 | 1549 | |
| 1558 | 1550 | if (rc != 0) { |
| 1559 | − lstcon_group_put(tmp); | |
| 1551 | + lstcon_group_decref(tmp); | |
| 1560 | 1552 | return rc; |
| 1561 | 1553 | } |
| 1562 | 1554 | |
| 1563 | 1555 | rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up); |
| 1564 | 1556 | |
| 1565 | − lstcon_group_put(tmp); | |
| 1557 | + lstcon_group_decref(tmp); | |
| 1566 | 1558 | |
| 1567 | 1559 | return rc; |
| 1568 | 1560 | } |
| @@ -1629,7 +1621,7 @@ lstcon_group_debug(int timeout, char *name, · 60 unmodified lines | ||
| 1629 | 1621 | |
| 1630 | 1622 | rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL, |
| 1631 | 1623 | timeout, result_up); |
| 1632 | − lstcon_group_put(grp); | |
| 1624 | + lstcon_group_decref(grp); | |
| 1633 | 1625 | |
| 1634 | 1626 | return rc; |
| 1635 | 1627 | } |
| @@ -1666,14 +1658,14 @@ lstcon_nodes_debug(int timeout, · 30 unmodified lines | ||
| 1666 | 1658 | } |
| 1667 | 1659 | |
| 1668 | 1660 | if (rc != 0) { |
| 1669 | − lstcon_group_put(grp); | |
| 1661 | + lstcon_group_decref(grp); | |
| 1670 | 1662 | return rc; |
| 1671 | 1663 | } |
| 1672 | 1664 | |
| 1673 | 1665 | rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL, |
| 1674 | 1666 | timeout, result_up); |
| 1675 | 1667 | |
| 1676 | − lstcon_group_put(grp); | |
| 1668 | + lstcon_group_decref(grp); | |
| 1677 | 1669 | |
| 1678 | 1670 | return rc; |
| 1679 | 1671 | } |
| @@ -1739,7 +1731,8 @@ lstcon_session_new(char *name, int key, unsigned feats, · 59 unmodified lines | ||
| 1739 | 1731 | console_session.ses_feats_updated = 0; |
| 1740 | 1732 | console_session.ses_timeout = (timeout <= 0) ? |
| 1741 | 1733 | LST_CONSOLE_TIMEOUT : timeout; |
| 1742 | − strcpy(console_session.ses_name, name); | |
| 1734 | + strlcpy(console_session.ses_name, name, | |
| 1735 | + sizeof(console_session.ses_name)); | |
| 1743 | 1736 | |
| 1744 | 1737 | rc = lstcon_batch_add(LST_DEFAULT_BATCH); |
| 1745 | 1738 | if (rc != 0) |
| @@ -1847,7 +1840,7 @@ lstcon_session_end(void) · 101 unmodified lines | ||
| 1847 | 1840 | lstcon_group_t, grp_link); |
| 1848 | 1841 | LASSERT(grp->grp_ref == 1); |
| 1849 | 1842 | |
| 1850 | − lstcon_group_put(grp); | |
| 1843 | + lstcon_group_decref(grp); | |
| 1851 | 1844 | } |
| 1852 | 1845 | |
| 1853 | 1846 | /* all nodes should be released */ |
| @@ -1891,7 +1884,7 @@ lstcon_session_feats_check(unsigned feats) · 37 unmodified lines | ||
| 1891 | 1884 | } |
| 1892 | 1885 | |
| 1893 | 1886 | static int |
| 1894 | −lstcon_acceptor_handle(srpc_server_rpc_t *rpc) | |
| 1887 | +lstcon_acceptor_handle(struct srpc_server_rpc *rpc) | |
| 1895 | 1888 | { |
| 1896 | 1889 | srpc_msg_t *rep = &rpc->srpc_replymsg; |
| 1897 | 1890 | srpc_msg_t *req = &rpc->srpc_reqstbuf->buf_msg; |
| @@ -1959,14 +1952,15 @@ lstcon_acceptor_handle(srpc_server_rpc_t *rpc) · 61 unmodified lines | ||
| 1959 | 1952 | if (grp->grp_userland == 0) |
| 1960 | 1953 | grp->grp_userland = 1; |
| 1961 | 1954 | |
| 1962 | − strcpy(jrep->join_session, console_session.ses_name); | |
| 1955 | + strlcpy(jrep->join_session, console_session.ses_name, | |
| 1956 | + sizeof(jrep->join_session)); | |
| 1963 | 1957 | jrep->join_timeout = console_session.ses_timeout; |
| 1964 | 1958 | jrep->join_status = 0; |
| 1965 | 1959 | |
| 1966 | 1960 | out: |
| 1967 | 1961 | rep->msg_ses_feats = console_session.ses_features; |
| 1968 | 1962 | if (grp != NULL) |
| 1969 | − lstcon_group_put(grp); | |
| 1963 | + lstcon_group_decref(grp); | |
| 1970 | 1964 | |
| 1971 | 1965 | mutex_unlock(&console_session.ses_mutex); |
| 1972 | 1966 | |
| @@ -111,7 +111,7 @@ static struct smoketest_framework { · 110 unmodified lines | ||
| 111 | 111 | spinlock_t fw_lock; /* serialise */ |
| 112 | 112 | sfw_session_t *fw_session; /* _the_ session */ |
| 113 | 113 | int fw_shuttingdown; /* shutdown in progress */ |
| 114 | − srpc_server_rpc_t *fw_active_srpc; /* running RPC */ | |
| 114 | + struct srpc_server_rpc *fw_active_srpc;/* running RPC */ | |
| 115 | 115 | } sfw_data; |
| 116 | 116 | |
| 117 | 117 | /* forward ref's */ |
| @@ -722,7 +722,7 @@ sfw_unpack_addtest_req(srpc_msg_t *msg) · 604 unmodified lines | ||
| 722 | 722 | } |
| 723 | 723 | |
| 724 | 724 | static int |
| 725 | −sfw_add_test_instance(sfw_batch_t *tsb, srpc_server_rpc_t *rpc) | |
| 725 | +sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) | |
| 726 | 726 | { |
| 727 | 727 | srpc_msg_t *msg = &rpc->srpc_reqstbuf->buf_msg; |
| 728 | 728 | srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; |
| @@ -1091,7 +1091,7 @@ sfw_query_batch(sfw_batch_t *tsb, int testidx, srpc_batch_reply_t *reply) · 362 unmodified lines | ||
| 1091 | 1091 | } |
| 1092 | 1092 | |
| 1093 | 1093 | void |
| 1094 | −sfw_free_pages(srpc_server_rpc_t *rpc) | |
| 1094 | +sfw_free_pages(struct srpc_server_rpc *rpc) | |
| 1095 | 1095 | { |
| 1096 | 1096 | srpc_free_bulk(rpc->srpc_bulk); |
| 1097 | 1097 | rpc->srpc_bulk = NULL; |
| @@ -1112,7 +1112,7 @@ sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len, · 14 unmodified lines | ||
| 1112 | 1112 | } |
| 1113 | 1113 | |
| 1114 | 1114 | static int |
| 1115 | −sfw_add_test(srpc_server_rpc_t *rpc) | |
| 1115 | +sfw_add_test(struct srpc_server_rpc *rpc) | |
| 1116 | 1116 | { |
| 1117 | 1117 | sfw_session_t *sn = sfw_data.fw_session; |
| 1118 | 1118 | srpc_test_reply_t *reply = &rpc->srpc_replymsg.msg_body.tes_reply; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -444,15 +444,6 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, · 410 unmodified lines | ||
| 444 | 444 | return 0; |
| 445 | 445 | } |
| 446 | 446 | |
| 447 | −static int | |
| 448 | −srpc_post_active_rqtbuf(lnet_process_id_t peer, int service, void *buf, | |
| 449 | − int len, lnet_handle_md_t *mdh, srpc_event_t *ev) | |
| 450 | −{ | |
| 451 | − return srpc_post_active_rdma(srpc_serv_portal(service), service, | |
| 452 | − buf, len, LNET_MD_OP_PUT, peer, | |
| 453 | − LNET_NID_ANY, mdh, ev); | |
| 454 | −} | |
| 455 | − | |
| 456 | 447 | static int |
| 457 | 448 | srpc_post_passive_rqtbuf(int service, int local, void *buf, int len, |
| 458 | 449 | lnet_handle_md_t *mdh, srpc_event_t *ev) |
| @@ -798,9 +789,11 @@ srpc_send_request(srpc_client_rpc_t *rpc) · 339 unmodified lines | ||
| 798 | 789 | ev->ev_data = rpc; |
| 799 | 790 | ev->ev_type = SRPC_REQUEST_SENT; |
| 800 | 791 | |
| 801 | − rc = srpc_post_active_rqtbuf(rpc->crpc_dest, rpc->crpc_service, | |
| 802 | − &rpc->crpc_reqstmsg, sizeof(srpc_msg_t), | |
| 803 | − &rpc->crpc_reqstmdh, ev); | |
| 792 | + rc = srpc_post_active_rdma(srpc_serv_portal(rpc->crpc_service), | |
| 793 | + rpc->crpc_service, &rpc->crpc_reqstmsg, | |
| 794 | + sizeof(srpc_msg_t), LNET_MD_OP_PUT, | |
| 795 | + rpc->crpc_dest, LNET_NID_ANY, | |
| 796 | + &rpc->crpc_reqstmdh, ev); | |
| 804 | 797 | if (rc != 0) { |
| 805 | 798 | LASSERT(rc == -ENOMEM); |
| 806 | 799 | ev->ev_fired = 1; /* no more event expected */ |
| @@ -866,7 +859,7 @@ srpc_prepare_bulk(srpc_client_rpc_t *rpc) · 59 unmodified lines | ||
| 866 | 859 | } |
| 867 | 860 | |
| 868 | 861 | static int |
| 869 | −srpc_do_bulk(srpc_server_rpc_t *rpc) | |
| 862 | +srpc_do_bulk(struct srpc_server_rpc *rpc) | |
| 870 | 863 | { |
| 871 | 864 | srpc_event_t *ev = &rpc->srpc_ev; |
| 872 | 865 | srpc_bulk_t *bk = rpc->srpc_bulk; |
| @@ -894,7 +887,7 @@ srpc_do_bulk(srpc_server_rpc_t *rpc) · 21 unmodified lines | ||
| 894 | 887 | |
| 895 | 888 | /* only called from srpc_handle_rpc */ |
| 896 | 889 | static void |
| 897 | −srpc_server_rpc_done(srpc_server_rpc_t *rpc, int status) | |
| 890 | +srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status) | |
| 898 | 891 | { |
| 899 | 892 | struct srpc_service_cd *scd = rpc->srpc_scd; |
| 900 | 893 | struct srpc_service *sv = scd->scd_svc; |
| @@ -1404,7 +1397,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) · 503 unmodified lines | ||
| 1404 | 1397 | struct srpc_service_cd *scd; |
| 1405 | 1398 | srpc_event_t *rpcev = ev->md.user_ptr; |
| 1406 | 1399 | srpc_client_rpc_t *crpc; |
| 1407 | − srpc_server_rpc_t *srpc; | |
| 1400 | + struct srpc_server_rpc *srpc; | |
| 1408 | 1401 | srpc_buffer_t *buffer; |
| 1409 | 1402 | srpc_service_t *sv; |
| 1410 | 1403 | srpc_msg_t *msg; |
| @@ -182,7 +182,7 @@ typedef struct swi_workitem { · 181 unmodified lines | ||
| 182 | 182 | } swi_workitem_t; |
| 183 | 183 | |
| 184 | 184 | /* server-side state of a RPC */ |
| 185 | −typedef struct srpc_server_rpc { | |
| 185 | +struct srpc_server_rpc { | |
| 186 | 186 | /* chain on srpc_service::*_rpcq */ |
| 187 | 187 | struct list_head srpc_list; |
| 188 | 188 | struct srpc_service_cd *srpc_scd; |
| @@ -198,7 +198,7 @@ typedef struct srpc_server_rpc { · 9 unmodified lines | ||
| 198 | 198 | unsigned int srpc_aborted; /* being given up */ |
| 199 | 199 | int srpc_status; |
| 200 | 200 | void (*srpc_done)(struct srpc_server_rpc *); |
| 201 | −} srpc_server_rpc_t; | |
| 201 | +}; | |
| 202 | 202 | |
| 203 | 203 | /* client-side state of a RPC */ |
| 204 | 204 | typedef struct srpc_client_rpc { |
| @@ -318,8 +318,8 @@ typedef struct srpc_service { · 113 unmodified lines | ||
| 318 | 318 | * - sv_handler: process incoming RPC request |
| 319 | 319 | * - sv_bulk_ready: notify bulk data |
| 320 | 320 | */ |
| 321 | − int (*sv_handler) (srpc_server_rpc_t *); | |
| 322 | − int (*sv_bulk_ready) (srpc_server_rpc_t *, int); | |
| 321 | + int (*sv_handler)(struct srpc_server_rpc *); | |
| 322 | + int (*sv_bulk_ready)(struct srpc_server_rpc *, int); | |
| 323 | 323 | } srpc_service_t; |
| 324 | 324 | |
| 325 | 325 | typedef struct { |
| @@ -423,9 +423,9 @@ void sfw_abort_rpc(srpc_client_rpc_t *rpc); · 97 unmodified lines | ||
| 423 | 423 | void sfw_post_rpc(srpc_client_rpc_t *rpc); |
| 424 | 424 | void sfw_client_rpc_done(srpc_client_rpc_t *rpc); |
| 425 | 425 | void sfw_unpack_message(srpc_msg_t *msg); |
| 426 | −void sfw_free_pages(srpc_server_rpc_t *rpc); | |
| 426 | +void sfw_free_pages(struct srpc_server_rpc *rpc); | |
| 427 | 427 | void sfw_add_bulk_page(srpc_bulk_t *bk, struct page *pg, int i); |
| 428 | −int sfw_alloc_pages(srpc_server_rpc_t *rpc, int cpt, int npages, int len, | |
| 428 | +int sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len, | |
| 429 | 429 | int sink); |
| 430 | 430 | int sfw_make_session (srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply); |
| 431 | 431 | |
| @@ -440,7 +440,7 @@ void srpc_free_bulk(srpc_bulk_t *bk); · 8 unmodified lines | ||
| 440 | 440 | srpc_bulk_t *srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, |
| 441 | 441 | int sink); |
| 442 | 442 | int srpc_send_rpc(swi_workitem_t *wi); |
| 443 | −int srpc_send_reply(srpc_server_rpc_t *rpc); | |
| 443 | +int srpc_send_reply(struct srpc_server_rpc *rpc); | |
| 444 | 444 | int srpc_add_service(srpc_service_t *sv); |
| 445 | 445 | int srpc_remove_service(srpc_service_t *sv); |
| 446 | 446 | void srpc_shutdown_service(srpc_service_t *sv); |
| @@ -585,7 +585,7 @@ swi_state2str (int state) · 138 unmodified lines | ||
| 585 | 585 | do { \ |
| 586 | 586 | int __I = 2; \ |
| 587 | 587 | while (!(cond)) { \ |
| 588 | − CDEBUG(IS_PO2(++__I) ? D_WARNING : D_NET, \ | |
| 588 | + CDEBUG(is_power_of_2(++__I) ? D_WARNING : D_NET, \ | |
| 589 | 589 | fmt, ## __VA_ARGS__); \ |
| 590 | 590 | spin_unlock(&(lock)); \ |
| 591 | 591 | \ |
| @@ -44,8 +44,6 @@ · 43 unmodified lines | ||
| 44 | 44 | #include "../../include/linux/libcfs/libcfs.h" |
| 45 | 45 | |
| 46 | 46 | /* Functions used internally in module. */ |
| 47 | −int seq_client_alloc_super(struct lu_client_seq *seq, | |
| 48 | − const struct lu_env *env); | |
| 49 | 47 | |
| 50 | 48 | extern struct lprocfs_vars seq_client_debugfs_list[]; |
| 51 | 49 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2013, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -142,27 +142,6 @@ out_req: · 108 unmodified lines | ||
| 142 | 142 | return rc; |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | −/* Request sequence-controller node to allocate new super-sequence. */ | |
| 146 | −int seq_client_alloc_super(struct lu_client_seq *seq, | |
| 147 | − const struct lu_env *env) | |
| 148 | −{ | |
| 149 | − int rc; | |
| 150 | − | |
| 151 | − mutex_lock(&seq->lcs_mutex); | |
| 152 | − | |
| 153 | − /* Check whether the connection to seq controller has been | |
| 154 | − * setup (lcs_exp != NULL) */ | |
| 155 | − if (!seq->lcs_exp) { | |
| 156 | − mutex_unlock(&seq->lcs_mutex); | |
| 157 | − return -EINPROGRESS; | |
| 158 | − } | |
| 159 | − | |
| 160 | − rc = seq_client_rpc(seq, &seq->lcs_space, | |
| 161 | − SEQ_ALLOC_SUPER, "super"); | |
| 162 | − mutex_unlock(&seq->lcs_mutex); | |
| 163 | − return rc; | |
| 164 | −} | |
| 165 | − | |
| 166 | 145 | /* Request sequence-controller node to allocate new meta-sequence. */ |
| 167 | 146 | static int seq_client_alloc_meta(const struct lu_env *env, |
| 168 | 147 | struct lu_client_seq *seq) |
| @@ -483,7 +462,7 @@ static void __exit fid_mod_exit(void) · 314 unmodified lines | ||
| 483 | 462 | ldebugfs_remove(&seq_debugfs_dir); |
| 484 | 463 | } |
| 485 | 464 | |
| 486 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 465 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 487 | 466 | MODULE_DESCRIPTION("Lustre FID Module"); |
| 488 | 467 | MODULE_LICENSE("GPL"); |
| 489 | 468 | MODULE_VERSION("0.1.0"); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -121,8 +121,8 @@ void fld_cache_fini(struct fld_cache *cache) · 120 unmodified lines | ||
| 121 | 121 | /** |
| 122 | 122 | * delete given node from list. |
| 123 | 123 | */ |
| 124 | −void fld_cache_entry_delete(struct fld_cache *cache, | |
| 125 | − struct fld_cache_entry *node) | |
| 124 | +static void fld_cache_entry_delete(struct fld_cache *cache, | |
| 125 | + struct fld_cache_entry *node) | |
| 126 | 126 | { |
| 127 | 127 | list_del(&node->fce_list); |
| 128 | 128 | list_del(&node->fce_lru); |
| @@ -227,7 +227,6 @@ static int fld_cache_shrink(struct fld_cache *cache) · 98 unmodified lines | ||
| 227 | 227 | |
| 228 | 228 | while (cache->fci_cache_count + cache->fci_threshold > |
| 229 | 229 | cache->fci_cache_size && curr != &cache->fci_lru) { |
| 230 | − | |
| 231 | 230 | flde = list_entry(curr, struct fld_cache_entry, fce_lru); |
| 232 | 231 | curr = curr->prev; |
| 233 | 232 | fld_cache_entry_delete(cache, flde); |
| @@ -377,8 +376,8 @@ struct fld_cache_entry · 143 unmodified lines | ||
| 377 | 376 | * This function handles all cases of merging and breaking up of |
| 378 | 377 | * ranges. |
| 379 | 378 | */ |
| 380 | −int fld_cache_insert_nolock(struct fld_cache *cache, | |
| 381 | − struct fld_cache_entry *f_new) | |
| 379 | +static int fld_cache_insert_nolock(struct fld_cache *cache, | |
| 380 | + struct fld_cache_entry *f_new) | |
| 382 | 381 | { |
| 383 | 382 | struct fld_cache_entry *f_curr; |
| 384 | 383 | struct fld_cache_entry *n; |
| @@ -444,36 +443,10 @@ int fld_cache_insert(struct fld_cache *cache, · 59 unmodified lines | ||
| 444 | 443 | return rc; |
| 445 | 444 | } |
| 446 | 445 | |
| 447 | −void fld_cache_delete_nolock(struct fld_cache *cache, | |
| 448 | − const struct lu_seq_range *range) | |
| 449 | −{ | |
| 450 | − struct fld_cache_entry *flde; | |
| 451 | − struct fld_cache_entry *tmp; | |
| 452 | − struct list_head *head; | |
| 453 | − | |
| 454 | − head = &cache->fci_entries_head; | |
| 455 | − list_for_each_entry_safe(flde, tmp, head, fce_list) { | |
| 456 | − /* add list if next is end of list */ | |
| 457 | − if (range->lsr_start == flde->fce_range.lsr_start || | |
| 458 | − (range->lsr_end == flde->fce_range.lsr_end && | |
| 459 | − range->lsr_flags == flde->fce_range.lsr_flags)) { | |
| 460 | − fld_cache_entry_delete(cache, flde); | |
| 461 | − break; | |
| 462 | − } | |
| 463 | − } | |
| 464 | −} | |
| 465 | − | |
| 466 | 446 | /** |
| 467 | 447 | * Delete FLD entry in FLD cache. |
| 468 | 448 | * |
| 469 | 449 | */ |
| 470 | −void fld_cache_delete(struct fld_cache *cache, | |
| 471 | − const struct lu_seq_range *range) | |
| 472 | −{ | |
| 473 | − write_lock(&cache->fci_lock); | |
| 474 | − fld_cache_delete_nolock(cache, range); | |
| 475 | − write_unlock(&cache->fci_lock); | |
| 476 | −} | |
| 477 | 450 | |
| 478 | 451 | struct fld_cache_entry |
| 479 | 452 | *fld_cache_entry_lookup_nolock(struct fld_cache *cache, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, 2013, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -156,20 +156,11 @@ int fld_cache_insert(struct fld_cache *cache, · 122 unmodified lines | ||
| 156 | 156 | struct fld_cache_entry |
| 157 | 157 | *fld_cache_entry_create(const struct lu_seq_range *range); |
| 158 | 158 | |
| 159 | −int fld_cache_insert_nolock(struct fld_cache *cache, | |
| 160 | − struct fld_cache_entry *f_new); | |
| 161 | −void fld_cache_delete(struct fld_cache *cache, | |
| 162 | − const struct lu_seq_range *range); | |
| 163 | −void fld_cache_delete_nolock(struct fld_cache *cache, | |
| 164 | − const struct lu_seq_range *range); | |
| 165 | 159 | int fld_cache_lookup(struct fld_cache *cache, |
| 166 | 160 | const u64 seq, struct lu_seq_range *range); |
| 167 | 161 | |
| 168 | 162 | struct fld_cache_entry* |
| 169 | 163 | fld_cache_entry_lookup(struct fld_cache *cache, struct lu_seq_range *range); |
| 170 | −void fld_cache_entry_delete(struct fld_cache *cache, | |
| 171 | − struct fld_cache_entry *node); | |
| 172 | −void fld_dump_cache_entries(struct fld_cache *cache); | |
| 173 | 164 | |
| 174 | 165 | struct fld_cache_entry |
| 175 | 166 | *fld_cache_entry_lookup_nolock(struct fld_cache *cache, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2013, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -501,7 +501,7 @@ static void __exit fld_mod_exit(void) · 467 unmodified lines | ||
| 501 | 501 | ldebugfs_remove(&fld_debugfs_dir); |
| 502 | 502 | } |
| 503 | 503 | |
| 504 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 504 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 505 | 505 | MODULE_DESCRIPTION("Lustre FLD"); |
| 506 | 506 | MODULE_LICENSE("GPL"); |
| 507 | 507 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, 2013, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -3127,7 +3127,6 @@ void cl_page_list_disown (const struct lu_env *env, · 3093 unmodified lines | ||
| 3127 | 3127 | struct cl_io *io, struct cl_page_list *plist); |
| 3128 | 3128 | |
| 3129 | 3129 | void cl_2queue_init (struct cl_2queue *queue); |
| 3130 | −void cl_2queue_add (struct cl_2queue *queue, struct cl_page *page); | |
| 3131 | 3130 | void cl_2queue_disown (const struct lu_env *env, |
| 3132 | 3131 | struct cl_io *io, struct cl_2queue *queue); |
| 3133 | 3132 | void cl_2queue_discard (const struct lu_env *env, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -624,9 +624,6 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx, · 590 unmodified lines | ||
| 624 | 624 | int lprocfs_single_release(struct inode *, struct file *); |
| 625 | 625 | int lprocfs_seq_release(struct inode *, struct file *); |
| 626 | 626 | |
| 627 | −#define LPROCFS_CLIMP_EXIT(obd) \ | |
| 628 | − up_read(&(obd)->u.cli.cl_sem) | |
| 629 | − | |
| 630 | 627 | /* write the name##_seq_show function, call LPROC_SEQ_FOPS_RO for read-only |
| 631 | 628 | proc entries; otherwise, you will define name##_seq_write function also for |
| 632 | 629 | a read-write proc entry, and then call LPROC_SEQ_SEQ instead. Finally, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | ||
| 26 | 26 | /* |
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | + * | |
| 30 | + * Copyright (c) 2014, 2015, Intel Corporation. | |
| 29 | 31 | */ |
| 30 | 32 | /* |
| 31 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2010, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2010, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -68,6 +68,7 @@ · 67 unmodified lines | ||
| 68 | 68 | everything as string options */ |
| 69 | 69 | |
| 70 | 70 | #define LMD_MAGIC 0xbdacbd03 |
| 71 | +#define LMD_PARAMS_MAXLEN 4096 | |
| 71 | 72 | |
| 72 | 73 | /* gleaned from the mount command - no persistent info here */ |
| 73 | 74 | struct lustre_mount_data { |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2010, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2010, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -872,8 +872,6 @@ struct ldlm_resource { · 838 unmodified lines | ||
| 872 | 872 | */ |
| 873 | 873 | struct mutex lr_lvb_mutex; |
| 874 | 874 | int lr_lvb_len; |
| 875 | − /** protected by lr_lock */ | |
| 876 | − void *lr_lvb_data; | |
| 877 | 875 | |
| 878 | 876 | /** When the resource was considered as contended. */ |
| 879 | 877 | unsigned long lr_contention_time; |
| @@ -76,8 +76,6 @@ extern int · 75 unmodified lines | ||
| 76 | 76 | lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, size_t size, |
| 77 | 77 | posix_acl_xattr_header **out); |
| 78 | 78 | extern void |
| 79 | −lustre_posix_acl_xattr_free(posix_acl_xattr_header *header, int size); | |
| 80 | −extern void | |
| 81 | 79 | lustre_ext_acl_xattr_free(ext_acl_xattr_header *header); |
| 82 | 80 | extern ext_acl_xattr_header * |
| 83 | 81 | lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2013, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -94,9 +94,6 @@ int llog_open(const struct lu_env *env, struct llog_ctxt *ctxt, · 60 unmodified lines | ||
| 94 | 94 | struct llog_handle **lgh, struct llog_logid *logid, |
| 95 | 95 | char *name, enum llog_open_param open_param); |
| 96 | 96 | int llog_close(const struct lu_env *env, struct llog_handle *cathandle); |
| 97 | −int llog_backup(const struct lu_env *env, struct obd_device *obd, | |
| 98 | − struct llog_ctxt *ctxt, struct llog_ctxt *bak_ctxt, | |
| 99 | − char *name, char *backup); | |
| 100 | 97 | |
| 101 | 98 | /* llog_process flags */ |
| 102 | 99 | #define LLOG_FLAG_NODEAMON 0x0001 |
| @@ -62,12 +62,6 @@ struct mds_group_info { · 61 unmodified lines | ||
| 62 | 62 | #define MDD_OBD_NAME "mdd_obd" |
| 63 | 63 | #define MDD_OBD_UUID "mdd_obd_uuid" |
| 64 | 64 | |
| 65 | −static inline int md_should_create(__u64 flags) | |
| 66 | −{ | |
| 67 | − return !(flags & MDS_OPEN_DELAY_CREATE || | |
| 68 | − !(flags & FMODE_WRITE)); | |
| 69 | −} | |
| 70 | − | |
| 71 | 65 | /* these are local flags, used only on the client, private */ |
| 72 | 66 | #define M_CHECK_STALE 0200000000 |
| 73 | 67 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2010, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2010, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -963,123 +963,123 @@ struct md_enqueue_info { · 929 unmodified lines | ||
| 963 | 963 | }; |
| 964 | 964 | |
| 965 | 965 | struct obd_ops { |
| 966 | − struct module *o_owner; | |
| 967 | − int (*o_iocontrol)(unsigned int cmd, struct obd_export *exp, int len, | |
| 968 | − void *karg, void *uarg); | |
| 969 | − int (*o_get_info)(const struct lu_env *env, struct obd_export *, | |
| 970 | − __u32 keylen, void *key, __u32 *vallen, void *val, | |
| 971 | − struct lov_stripe_md *lsm); | |
| 972 | − int (*o_set_info_async)(const struct lu_env *, struct obd_export *, | |
| 973 | − __u32 keylen, void *key, | |
| 974 | − __u32 vallen, void *val, | |
| 975 | − struct ptlrpc_request_set *set); | |
| 976 | − int (*o_attach)(struct obd_device *dev, u32 len, void *data); | |
| 977 | − int (*o_detach)(struct obd_device *dev); | |
| 978 | − int (*o_setup)(struct obd_device *dev, struct lustre_cfg *cfg); | |
| 979 | − int (*o_precleanup)(struct obd_device *dev, | |
| 980 | − enum obd_cleanup_stage cleanup_stage); | |
| 981 | − int (*o_cleanup)(struct obd_device *dev); | |
| 982 | − int (*o_process_config)(struct obd_device *dev, u32 len, void *data); | |
| 983 | − int (*o_postrecov)(struct obd_device *dev); | |
| 984 | − int (*o_add_conn)(struct obd_import *imp, struct obd_uuid *uuid, | |
| 985 | − int priority); | |
| 986 | − int (*o_del_conn)(struct obd_import *imp, struct obd_uuid *uuid); | |
| 966 | + struct module *owner; | |
| 967 | + int (*iocontrol)(unsigned int cmd, struct obd_export *exp, int len, | |
| 968 | + void *karg, void *uarg); | |
| 969 | + int (*get_info)(const struct lu_env *env, struct obd_export *, | |
| 970 | + __u32 keylen, void *key, __u32 *vallen, void *val, | |
| 971 | + struct lov_stripe_md *lsm); | |
| 972 | + int (*set_info_async)(const struct lu_env *, struct obd_export *, | |
| 973 | + __u32 keylen, void *key, | |
| 974 | + __u32 vallen, void *val, | |
| 975 | + struct ptlrpc_request_set *set); | |
| 976 | + int (*attach)(struct obd_device *dev, u32 len, void *data); | |
| 977 | + int (*detach)(struct obd_device *dev); | |
| 978 | + int (*setup)(struct obd_device *dev, struct lustre_cfg *cfg); | |
| 979 | + int (*precleanup)(struct obd_device *dev, | |
| 980 | + enum obd_cleanup_stage cleanup_stage); | |
| 981 | + int (*cleanup)(struct obd_device *dev); | |
| 982 | + int (*process_config)(struct obd_device *dev, u32 len, void *data); | |
| 983 | + int (*postrecov)(struct obd_device *dev); | |
| 984 | + int (*add_conn)(struct obd_import *imp, struct obd_uuid *uuid, | |
| 985 | + int priority); | |
| 986 | + int (*del_conn)(struct obd_import *imp, struct obd_uuid *uuid); | |
| 987 | 987 | /* connect to the target device with given connection |
| 988 | 988 | * data. @ocd->ocd_connect_flags is modified to reflect flags actually |
| 989 | 989 | * granted by the target, which are guaranteed to be a subset of flags |
| 990 | 990 | * asked for. If @ocd == NULL, use default parameters. */ |
| 991 | − int (*o_connect)(const struct lu_env *env, | |
| 992 | − struct obd_export **exp, struct obd_device *src, | |
| 993 | − struct obd_uuid *cluuid, struct obd_connect_data *ocd, | |
| 991 | + int (*connect)(const struct lu_env *env, | |
| 992 | + struct obd_export **exp, struct obd_device *src, | |
| 993 | + struct obd_uuid *cluuid, struct obd_connect_data *ocd, | |
| 994 | + void *localdata); | |
| 995 | + int (*reconnect)(const struct lu_env *env, | |
| 996 | + struct obd_export *exp, struct obd_device *src, | |
| 997 | + struct obd_uuid *cluuid, | |
| 998 | + struct obd_connect_data *ocd, | |
| 994 | 999 | void *localdata); |
| 995 | − int (*o_reconnect)(const struct lu_env *env, | |
| 996 | − struct obd_export *exp, struct obd_device *src, | |
| 997 | − struct obd_uuid *cluuid, | |
| 998 | − struct obd_connect_data *ocd, | |
| 999 | − void *localdata); | |
| 1000 | − int (*o_disconnect)(struct obd_export *exp); | |
| 1000 | + int (*disconnect)(struct obd_export *exp); | |
| 1001 | 1001 | |
| 1002 | 1002 | /* Initialize/finalize fids infrastructure. */ |
| 1003 | − int (*o_fid_init)(struct obd_device *obd, | |
| 1004 | − struct obd_export *exp, enum lu_cli_type type); | |
| 1005 | − int (*o_fid_fini)(struct obd_device *obd); | |
| 1003 | + int (*fid_init)(struct obd_device *obd, | |
| 1004 | + struct obd_export *exp, enum lu_cli_type type); | |
| 1005 | + int (*fid_fini)(struct obd_device *obd); | |
| 1006 | 1006 | |
| 1007 | 1007 | /* Allocate new fid according to passed @hint. */ |
| 1008 | − int (*o_fid_alloc)(struct obd_export *exp, struct lu_fid *fid, | |
| 1009 | − struct md_op_data *op_data); | |
| 1008 | + int (*fid_alloc)(struct obd_export *exp, struct lu_fid *fid, | |
| 1009 | + struct md_op_data *op_data); | |
| 1010 | 1010 | |
| 1011 | 1011 | /* |
| 1012 | 1012 | * Object with @fid is getting deleted, we may want to do something |
| 1013 | 1013 | * about this. |
| 1014 | 1014 | */ |
| 1015 | − int (*o_statfs)(const struct lu_env *, struct obd_export *exp, | |
| 1016 | − struct obd_statfs *osfs, __u64 max_age, __u32 flags); | |
| 1017 | − int (*o_statfs_async)(struct obd_export *exp, struct obd_info *oinfo, | |
| 1018 | − __u64 max_age, struct ptlrpc_request_set *set); | |
| 1019 | − int (*o_packmd)(struct obd_export *exp, struct lov_mds_md **disk_tgt, | |
| 1020 | − struct lov_stripe_md *mem_src); | |
| 1021 | − int (*o_unpackmd)(struct obd_export *exp, | |
| 1022 | − struct lov_stripe_md **mem_tgt, | |
| 1023 | − struct lov_mds_md *disk_src, int disk_len); | |
| 1024 | − int (*o_preallocate)(struct lustre_handle *, u32 *req, u64 *ids); | |
| 1025 | − int (*o_create)(const struct lu_env *env, struct obd_export *exp, | |
| 1026 | − struct obdo *oa, struct lov_stripe_md **ea, | |
| 1027 | − struct obd_trans_info *oti); | |
| 1028 | − int (*o_destroy)(const struct lu_env *env, struct obd_export *exp, | |
| 1029 | − struct obdo *oa, struct lov_stripe_md *ea, | |
| 1030 | − struct obd_trans_info *oti, struct obd_export *md_exp); | |
| 1031 | − int (*o_setattr)(const struct lu_env *, struct obd_export *exp, | |
| 1032 | − struct obd_info *oinfo, struct obd_trans_info *oti); | |
| 1033 | − int (*o_setattr_async)(struct obd_export *exp, struct obd_info *oinfo, | |
| 1034 | − struct obd_trans_info *oti, | |
| 1035 | − struct ptlrpc_request_set *rqset); | |
| 1036 | − int (*o_getattr)(const struct lu_env *env, struct obd_export *exp, | |
| 1037 | − struct obd_info *oinfo); | |
| 1038 | − int (*o_getattr_async)(struct obd_export *exp, struct obd_info *oinfo, | |
| 1039 | − struct ptlrpc_request_set *set); | |
| 1040 | − int (*o_adjust_kms)(struct obd_export *exp, struct lov_stripe_md *lsm, | |
| 1041 | − u64 size, int shrink); | |
| 1042 | − int (*o_preprw)(const struct lu_env *env, int cmd, | |
| 1043 | − struct obd_export *exp, struct obdo *oa, int objcount, | |
| 1044 | − struct obd_ioobj *obj, struct niobuf_remote *remote, | |
| 1045 | − int *nr_pages, struct niobuf_local *local, | |
| 1046 | − struct obd_trans_info *oti); | |
| 1047 | − int (*o_commitrw)(const struct lu_env *env, int cmd, | |
| 1048 | − struct obd_export *exp, struct obdo *oa, | |
| 1049 | − int objcount, struct obd_ioobj *obj, | |
| 1050 | − struct niobuf_remote *remote, int pages, | |
| 1051 | − struct niobuf_local *local, | |
| 1052 | − struct obd_trans_info *oti, int rc); | |
| 1053 | − int (*o_find_cbdata)(struct obd_export *, struct lov_stripe_md *, | |
| 1054 | − ldlm_iterator_t it, void *data); | |
| 1055 | − int (*o_init_export)(struct obd_export *exp); | |
| 1056 | − int (*o_destroy_export)(struct obd_export *exp); | |
| 1015 | + int (*statfs)(const struct lu_env *, struct obd_export *exp, | |
| 1016 | + struct obd_statfs *osfs, __u64 max_age, __u32 flags); | |
| 1017 | + int (*statfs_async)(struct obd_export *exp, struct obd_info *oinfo, | |
| 1018 | + __u64 max_age, struct ptlrpc_request_set *set); | |
| 1019 | + int (*packmd)(struct obd_export *exp, struct lov_mds_md **disk_tgt, | |
| 1020 | + struct lov_stripe_md *mem_src); | |
| 1021 | + int (*unpackmd)(struct obd_export *exp, | |
| 1022 | + struct lov_stripe_md **mem_tgt, | |
| 1023 | + struct lov_mds_md *disk_src, int disk_len); | |
| 1024 | + int (*preallocate)(struct lustre_handle *, u32 *req, u64 *ids); | |
| 1025 | + int (*create)(const struct lu_env *env, struct obd_export *exp, | |
| 1026 | + struct obdo *oa, struct lov_stripe_md **ea, | |
| 1027 | + struct obd_trans_info *oti); | |
| 1028 | + int (*destroy)(const struct lu_env *env, struct obd_export *exp, | |
| 1029 | + struct obdo *oa, struct lov_stripe_md *ea, | |
| 1030 | + struct obd_trans_info *oti, struct obd_export *md_exp); | |
| 1031 | + int (*setattr)(const struct lu_env *, struct obd_export *exp, | |
| 1032 | + struct obd_info *oinfo, struct obd_trans_info *oti); | |
| 1033 | + int (*setattr_async)(struct obd_export *exp, struct obd_info *oinfo, | |
| 1034 | + struct obd_trans_info *oti, | |
| 1035 | + struct ptlrpc_request_set *rqset); | |
| 1036 | + int (*getattr)(const struct lu_env *env, struct obd_export *exp, | |
| 1037 | + struct obd_info *oinfo); | |
| 1038 | + int (*getattr_async)(struct obd_export *exp, struct obd_info *oinfo, | |
| 1039 | + struct ptlrpc_request_set *set); | |
| 1040 | + int (*adjust_kms)(struct obd_export *exp, struct lov_stripe_md *lsm, | |
| 1041 | + u64 size, int shrink); | |
| 1042 | + int (*preprw)(const struct lu_env *env, int cmd, | |
| 1043 | + struct obd_export *exp, struct obdo *oa, int objcount, | |
| 1044 | + struct obd_ioobj *obj, struct niobuf_remote *remote, | |
| 1045 | + int *nr_pages, struct niobuf_local *local, | |
| 1046 | + struct obd_trans_info *oti); | |
| 1047 | + int (*commitrw)(const struct lu_env *env, int cmd, | |
| 1048 | + struct obd_export *exp, struct obdo *oa, | |
| 1049 | + int objcount, struct obd_ioobj *obj, | |
| 1050 | + struct niobuf_remote *remote, int pages, | |
| 1051 | + struct niobuf_local *local, | |
| 1052 | + struct obd_trans_info *oti, int rc); | |
| 1053 | + int (*find_cbdata)(struct obd_export *, struct lov_stripe_md *, | |
| 1054 | + ldlm_iterator_t it, void *data); | |
| 1055 | + int (*init_export)(struct obd_export *exp); | |
| 1056 | + int (*destroy_export)(struct obd_export *exp); | |
| 1057 | 1057 | |
| 1058 | 1058 | /* metadata-only methods */ |
| 1059 | − int (*o_import_event)(struct obd_device *, struct obd_import *, | |
| 1060 | − enum obd_import_event); | |
| 1059 | + int (*import_event)(struct obd_device *, struct obd_import *, | |
| 1060 | + enum obd_import_event); | |
| 1061 | 1061 | |
| 1062 | − int (*o_notify)(struct obd_device *obd, struct obd_device *watched, | |
| 1063 | − enum obd_notify_event ev, void *data); | |
| 1062 | + int (*notify)(struct obd_device *obd, struct obd_device *watched, | |
| 1063 | + enum obd_notify_event ev, void *data); | |
| 1064 | 1064 | |
| 1065 | − int (*o_health_check)(const struct lu_env *env, struct obd_device *); | |
| 1066 | − struct obd_uuid *(*o_get_uuid)(struct obd_export *exp); | |
| 1065 | + int (*health_check)(const struct lu_env *env, struct obd_device *); | |
| 1066 | + struct obd_uuid *(*get_uuid)(struct obd_export *exp); | |
| 1067 | 1067 | |
| 1068 | 1068 | /* quota methods */ |
| 1069 | − int (*o_quotacheck)(struct obd_device *, struct obd_export *, | |
| 1070 | − struct obd_quotactl *); | |
| 1071 | − int (*o_quotactl)(struct obd_device *, struct obd_export *, | |
| 1069 | + int (*quotacheck)(struct obd_device *, struct obd_export *, | |
| 1072 | 1070 | struct obd_quotactl *); |
| 1071 | + int (*quotactl)(struct obd_device *, struct obd_export *, | |
| 1072 | + struct obd_quotactl *); | |
| 1073 | 1073 | |
| 1074 | 1074 | /* pools methods */ |
| 1075 | − int (*o_pool_new)(struct obd_device *obd, char *poolname); | |
| 1076 | − int (*o_pool_del)(struct obd_device *obd, char *poolname); | |
| 1077 | − int (*o_pool_add)(struct obd_device *obd, char *poolname, | |
| 1078 | − char *ostname); | |
| 1079 | − int (*o_pool_rem)(struct obd_device *obd, char *poolname, | |
| 1080 | − char *ostname); | |
| 1081 | − void (*o_getref)(struct obd_device *obd); | |
| 1082 | − void (*o_putref)(struct obd_device *obd); | |
| 1075 | + int (*pool_new)(struct obd_device *obd, char *poolname); | |
| 1076 | + int (*pool_del)(struct obd_device *obd, char *poolname); | |
| 1077 | + int (*pool_add)(struct obd_device *obd, char *poolname, | |
| 1078 | + char *ostname); | |
| 1079 | + int (*pool_rem)(struct obd_device *obd, char *poolname, | |
| 1080 | + char *ostname); | |
| 1081 | + void (*getref)(struct obd_device *obd); | |
| 1082 | + void (*putref)(struct obd_device *obd); | |
| 1083 | 1083 | /* |
| 1084 | 1084 | * NOTE: If adding ops, add another LPROCFS_OBD_OP_INIT() line |
| 1085 | 1085 | * to lprocfs_alloc_obd_stats() in obdclass/lprocfs_status.c. |
| @@ -1124,89 +1124,89 @@ struct md_open_data { · 38 unmodified lines | ||
| 1124 | 1124 | struct lookup_intent; |
| 1125 | 1125 | |
| 1126 | 1126 | struct md_ops { |
| 1127 | − int (*m_getstatus)(struct obd_export *, struct lu_fid *); | |
| 1128 | − int (*m_null_inode)(struct obd_export *, const struct lu_fid *); | |
| 1129 | − int (*m_find_cbdata)(struct obd_export *, const struct lu_fid *, | |
| 1130 | − ldlm_iterator_t, void *); | |
| 1131 | − int (*m_close)(struct obd_export *, struct md_op_data *, | |
| 1132 | − struct md_open_data *, struct ptlrpc_request **); | |
| 1133 | − int (*m_create)(struct obd_export *, struct md_op_data *, | |
| 1134 | − const void *, int, int, __u32, __u32, cfs_cap_t, | |
| 1135 | − __u64, struct ptlrpc_request **); | |
| 1136 | − int (*m_done_writing)(struct obd_export *, struct md_op_data *, | |
| 1137 | − struct md_open_data *); | |
| 1138 | − int (*m_enqueue)(struct obd_export *, struct ldlm_enqueue_info *, | |
| 1139 | − struct lookup_intent *, struct md_op_data *, | |
| 1140 | − struct lustre_handle *, void *, int, | |
| 1141 | − struct ptlrpc_request **, __u64); | |
| 1142 | − int (*m_getattr)(struct obd_export *, struct md_op_data *, | |
| 1143 | − struct ptlrpc_request **); | |
| 1144 | − int (*m_getattr_name)(struct obd_export *, struct md_op_data *, | |
| 1145 | − struct ptlrpc_request **); | |
| 1146 | − int (*m_intent_lock)(struct obd_export *, struct md_op_data *, | |
| 1147 | − void *, int, struct lookup_intent *, int, | |
| 1148 | − struct ptlrpc_request **, | |
| 1149 | − ldlm_blocking_callback, __u64); | |
| 1150 | − int (*m_link)(struct obd_export *, struct md_op_data *, | |
| 1127 | + int (*getstatus)(struct obd_export *, struct lu_fid *); | |
| 1128 | + int (*null_inode)(struct obd_export *, const struct lu_fid *); | |
| 1129 | + int (*find_cbdata)(struct obd_export *, const struct lu_fid *, | |
| 1130 | + ldlm_iterator_t, void *); | |
| 1131 | + int (*close)(struct obd_export *, struct md_op_data *, | |
| 1132 | + struct md_open_data *, struct ptlrpc_request **); | |
| 1133 | + int (*create)(struct obd_export *, struct md_op_data *, | |
| 1134 | + const void *, int, int, __u32, __u32, cfs_cap_t, | |
| 1135 | + __u64, struct ptlrpc_request **); | |
| 1136 | + int (*done_writing)(struct obd_export *, struct md_op_data *, | |
| 1137 | + struct md_open_data *); | |
| 1138 | + int (*enqueue)(struct obd_export *, struct ldlm_enqueue_info *, | |
| 1139 | + struct lookup_intent *, struct md_op_data *, | |
| 1140 | + struct lustre_handle *, void *, int, | |
| 1141 | + struct ptlrpc_request **, __u64); | |
| 1142 | + int (*getattr)(struct obd_export *, struct md_op_data *, | |
| 1143 | + struct ptlrpc_request **); | |
| 1144 | + int (*getattr_name)(struct obd_export *, struct md_op_data *, | |
| 1145 | + struct ptlrpc_request **); | |
| 1146 | + int (*intent_lock)(struct obd_export *, struct md_op_data *, | |
| 1147 | + void *, int, struct lookup_intent *, int, | |
| 1148 | + struct ptlrpc_request **, | |
| 1149 | + ldlm_blocking_callback, __u64); | |
| 1150 | + int (*link)(struct obd_export *, struct md_op_data *, | |
| 1151 | + struct ptlrpc_request **); | |
| 1152 | + int (*rename)(struct obd_export *, struct md_op_data *, | |
| 1153 | + const char *, int, const char *, int, | |
| 1151 | 1154 | struct ptlrpc_request **); |
| 1152 | − int (*m_rename)(struct obd_export *, struct md_op_data *, | |
| 1153 | − const char *, int, const char *, int, | |
| 1154 | − struct ptlrpc_request **); | |
| 1155 | − int (*m_is_subdir)(struct obd_export *, const struct lu_fid *, | |
| 1156 | − const struct lu_fid *, | |
| 1155 | + int (*is_subdir)(struct obd_export *, const struct lu_fid *, | |
| 1156 | + const struct lu_fid *, | |
| 1157 | 1157 | struct ptlrpc_request **); |
| 1158 | − int (*m_setattr)(struct obd_export *, struct md_op_data *, void *, | |
| 1159 | − int, void *, int, struct ptlrpc_request **, | |
| 1158 | + int (*setattr)(struct obd_export *, struct md_op_data *, void *, | |
| 1159 | + int, void *, int, struct ptlrpc_request **, | |
| 1160 | 1160 | struct md_open_data **mod); |
| 1161 | − int (*m_sync)(struct obd_export *, const struct lu_fid *, | |
| 1161 | + int (*sync)(struct obd_export *, const struct lu_fid *, | |
| 1162 | + struct ptlrpc_request **); | |
| 1163 | + int (*readpage)(struct obd_export *, struct md_op_data *, | |
| 1164 | + struct page **, struct ptlrpc_request **); | |
| 1165 | + | |
| 1166 | + int (*unlink)(struct obd_export *, struct md_op_data *, | |
| 1162 | 1167 | struct ptlrpc_request **); |
| 1163 | − int (*m_readpage)(struct obd_export *, struct md_op_data *, | |
| 1164 | − struct page **, struct ptlrpc_request **); | |
| 1165 | 1168 | |
| 1166 | − int (*m_unlink)(struct obd_export *, struct md_op_data *, | |
| 1169 | + int (*setxattr)(struct obd_export *, const struct lu_fid *, | |
| 1170 | + u64, const char *, const char *, int, int, int, __u32, | |
| 1167 | 1171 | struct ptlrpc_request **); |
| 1168 | 1172 | |
| 1169 | − int (*m_setxattr)(struct obd_export *, const struct lu_fid *, | |
| 1170 | − u64, const char *, const char *, int, int, int, __u32, | |
| 1171 | − struct ptlrpc_request **); | |
| 1172 | − | |
| 1173 | − int (*m_getxattr)(struct obd_export *, const struct lu_fid *, | |
| 1174 | − u64, const char *, const char *, int, int, int, | |
| 1175 | − struct ptlrpc_request **); | |
| 1173 | + int (*getxattr)(struct obd_export *, const struct lu_fid *, | |
| 1174 | + u64, const char *, const char *, int, int, int, | |
| 1175 | + struct ptlrpc_request **); | |
| 1176 | 1176 | |
| 1177 | − int (*m_init_ea_size)(struct obd_export *, int, int, int, int); | |
| 1177 | + int (*init_ea_size)(struct obd_export *, int, int, int, int); | |
| 1178 | 1178 | |
| 1179 | − int (*m_get_lustre_md)(struct obd_export *, struct ptlrpc_request *, | |
| 1180 | − struct obd_export *, struct obd_export *, | |
| 1181 | − struct lustre_md *); | |
| 1179 | + int (*get_lustre_md)(struct obd_export *, struct ptlrpc_request *, | |
| 1180 | + struct obd_export *, struct obd_export *, | |
| 1181 | + struct lustre_md *); | |
| 1182 | 1182 | |
| 1183 | − int (*m_free_lustre_md)(struct obd_export *, struct lustre_md *); | |
| 1183 | + int (*free_lustre_md)(struct obd_export *, struct lustre_md *); | |
| 1184 | 1184 | |
| 1185 | − int (*m_set_open_replay_data)(struct obd_export *, | |
| 1186 | − struct obd_client_handle *, | |
| 1187 | − struct lookup_intent *); | |
| 1188 | − int (*m_clear_open_replay_data)(struct obd_export *, | |
| 1189 | − struct obd_client_handle *); | |
| 1190 | − int (*m_set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *); | |
| 1185 | + int (*set_open_replay_data)(struct obd_export *, | |
| 1186 | + struct obd_client_handle *, | |
| 1187 | + struct lookup_intent *); | |
| 1188 | + int (*clear_open_replay_data)(struct obd_export *, | |
| 1189 | + struct obd_client_handle *); | |
| 1190 | + int (*set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *); | |
| 1191 | 1191 | |
| 1192 | − ldlm_mode_t (*m_lock_match)(struct obd_export *, __u64, | |
| 1193 | − const struct lu_fid *, ldlm_type_t, | |
| 1194 | − ldlm_policy_data_t *, ldlm_mode_t, | |
| 1195 | − struct lustre_handle *); | |
| 1192 | + ldlm_mode_t (*lock_match)(struct obd_export *, __u64, | |
| 1193 | + const struct lu_fid *, ldlm_type_t, | |
| 1194 | + ldlm_policy_data_t *, ldlm_mode_t, | |
| 1195 | + struct lustre_handle *); | |
| 1196 | 1196 | |
| 1197 | − int (*m_cancel_unused)(struct obd_export *, const struct lu_fid *, | |
| 1198 | − ldlm_policy_data_t *, ldlm_mode_t, | |
| 1199 | − ldlm_cancel_flags_t flags, void *opaque); | |
| 1197 | + int (*cancel_unused)(struct obd_export *, const struct lu_fid *, | |
| 1198 | + ldlm_policy_data_t *, ldlm_mode_t, | |
| 1199 | + ldlm_cancel_flags_t flags, void *opaque); | |
| 1200 | 1200 | |
| 1201 | − int (*m_get_remote_perm)(struct obd_export *, const struct lu_fid *, | |
| 1202 | − __u32, struct ptlrpc_request **); | |
| 1201 | + int (*get_remote_perm)(struct obd_export *, const struct lu_fid *, | |
| 1202 | + __u32, struct ptlrpc_request **); | |
| 1203 | 1203 | |
| 1204 | − int (*m_intent_getattr_async)(struct obd_export *, | |
| 1205 | − struct md_enqueue_info *, | |
| 1206 | − struct ldlm_enqueue_info *); | |
| 1204 | + int (*intent_getattr_async)(struct obd_export *, | |
| 1205 | + struct md_enqueue_info *, | |
| 1206 | + struct ldlm_enqueue_info *); | |
| 1207 | 1207 | |
| 1208 | − int (*m_revalidate_lock)(struct obd_export *, struct lookup_intent *, | |
| 1209 | − struct lu_fid *, __u64 *bits); | |
| 1208 | + int (*revalidate_lock)(struct obd_export *, struct lookup_intent *, | |
| 1209 | + struct lu_fid *, __u64 *bits); | |
| 1210 | 1210 | |
| 1211 | 1211 | /* |
| 1212 | 1212 | * NOTE: If adding ops, add another LPROCFS_MD_OP_INIT() line to |
| @@ -133,29 +133,6 @@ static inline cksum_type_t cksum_types_supported_client(void) · 132 unmodified lines | ||
| 133 | 133 | return ret; |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | −/* Server uses algos that perform at 50% or better of the Adler */ | |
| 137 | −static inline cksum_type_t cksum_types_supported_server(void) | |
| 138 | −{ | |
| 139 | − int base_speed; | |
| 140 | − cksum_type_t ret = OBD_CKSUM_ADLER; | |
| 141 | − | |
| 142 | − CDEBUG(D_INFO, "Crypto hash speed: crc %d, crc32c %d, adler %d\n", | |
| 143 | − cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_CRC32)), | |
| 144 | − cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_CRC32C)), | |
| 145 | − cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_ADLER))); | |
| 146 | − | |
| 147 | − base_speed = cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_ADLER)) / 2; | |
| 148 | − | |
| 149 | − if (cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_CRC32C)) >= | |
| 150 | − base_speed) | |
| 151 | − ret |= OBD_CKSUM_CRC32C; | |
| 152 | − if (cfs_crypto_hash_speed(cksum_obd2cfs(OBD_CKSUM_CRC32)) >= | |
| 153 | − base_speed) | |
| 154 | − ret |= OBD_CKSUM_CRC32; | |
| 155 | − | |
| 156 | − return ret; | |
| 157 | −} | |
| 158 | − | |
| 159 | 136 | /* Select the best checksum algorithm among those supplied in the cksum_types |
| 160 | 137 | * input. |
| 161 | 138 | * |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -270,8 +270,8 @@ void obdo_to_ioobj(struct obdo *oa, struct obd_ioobj *ioobj); · 236 unmodified lines | ||
| 270 | 270 | void md_from_obdo(struct md_op_data *op_data, struct obdo *oa, u32 valid); |
| 271 | 271 | |
| 272 | 272 | #define OBT(dev) (dev)->obd_type |
| 273 | −#define OBP(dev, op) (dev)->obd_type->typ_dt_ops->o_ ## op | |
| 274 | −#define MDP(dev, op) (dev)->obd_type->typ_md_ops->m_ ## op | |
| 273 | +#define OBP(dev, op) (dev)->obd_type->typ_dt_ops->op | |
| 274 | +#define MDP(dev, op) (dev)->obd_type->typ_md_ops->op | |
| 275 | 275 | #define CTXTP(ctxt, op) (ctxt)->loc_logops->lop_##op |
| 276 | 276 | |
| 277 | 277 | /* Ensure obd_setup: used for cleanup which must be called |
| @@ -301,9 +301,9 @@ static inline int obd_check_dev_active(struct obd_device *obd) · 23 unmodified lines | ||
| 301 | 301 | } |
| 302 | 302 | |
| 303 | 303 | #define OBD_COUNTER_OFFSET(op) \ |
| 304 | − ((offsetof(struct obd_ops, o_ ## op) - \ | |
| 305 | − offsetof(struct obd_ops, o_iocontrol)) \ | |
| 306 | − / sizeof(((struct obd_ops *)(0))->o_iocontrol)) | |
| 304 | + ((offsetof(struct obd_ops, op) - \ | |
| 305 | + offsetof(struct obd_ops, iocontrol)) \ | |
| 306 | + / sizeof(((struct obd_ops *)(0))->iocontrol)) | |
| 307 | 307 | |
| 308 | 308 | #define OBD_COUNTER_INCREMENT(obdx, op) \ |
| 309 | 309 | if ((obdx)->obd_stats != NULL) { \ |
| @@ -324,9 +324,9 @@ static inline int obd_check_dev_active(struct obd_device *obd) · 14 unmodified lines | ||
| 324 | 324 | } |
| 325 | 325 | |
| 326 | 326 | #define MD_COUNTER_OFFSET(op) \ |
| 327 | − ((offsetof(struct md_ops, m_ ## op) - \ | |
| 328 | − offsetof(struct md_ops, m_getstatus)) \ | |
| 329 | − / sizeof(((struct md_ops *)(0))->m_getstatus)) | |
| 327 | + ((offsetof(struct md_ops, op) - \ | |
| 328 | + offsetof(struct md_ops, getstatus)) \ | |
| 329 | + / sizeof(((struct md_ops *)(0))->getstatus)) | |
| 330 | 330 | |
| 331 | 331 | #define MD_COUNTER_INCREMENT(obdx, op) \ |
| 332 | 332 | if ((obd)->md_stats != NULL) { \ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -427,7 +427,7 @@ static void ccc_object_size_lock(struct cl_object *obj) · 393 unmodified lines | ||
| 427 | 427 | { |
| 428 | 428 | struct inode *inode = ccc_object_inode(obj); |
| 429 | 429 | |
| 430 | − cl_isize_lock(inode); | |
| 430 | + ll_inode_size_lock(inode); | |
| 431 | 431 | cl_object_attr_lock(obj); |
| 432 | 432 | } |
| 433 | 433 | |
| @@ -436,7 +436,7 @@ static void ccc_object_size_unlock(struct cl_object *obj) · 2 unmodified lines | ||
| 436 | 436 | struct inode *inode = ccc_object_inode(obj); |
| 437 | 437 | |
| 438 | 438 | cl_object_attr_unlock(obj); |
| 439 | − cl_isize_unlock(inode); | |
| 439 | + ll_inode_size_unlock(inode); | |
| 440 | 440 | } |
| 441 | 441 | |
| 442 | 442 | /***************************************************************************** |
| @@ -96,18 +96,6 @@ static inline int extent_equal(struct interval_node_extent *e1, · 95 unmodified lines | ||
| 96 | 96 | return (e1->start == e2->start) && (e1->end == e2->end); |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | −static inline int node_compare(struct interval_node *n1, | |
| 100 | − struct interval_node *n2) | |
| 101 | −{ | |
| 102 | − return extent_compare(&n1->in_extent, &n2->in_extent); | |
| 103 | −} | |
| 104 | − | |
| 105 | −static inline int node_equal(struct interval_node *n1, | |
| 106 | − struct interval_node *n2) | |
| 107 | −{ | |
| 108 | − return extent_equal(&n1->in_extent, &n2->in_extent); | |
| 109 | −} | |
| 110 | − | |
| 111 | 99 | static inline __u64 max_u64(__u64 x, __u64 y) |
| 112 | 100 | { |
| 113 | 101 | return x > y ? x : y; |
| @@ -278,14 +266,14 @@ struct interval_node *interval_insert(struct interval_node *node, · 164 unmodified lines | ||
| 278 | 266 | p = root; |
| 279 | 267 | while (*p) { |
| 280 | 268 | parent = *p; |
| 281 | − if (node_equal(parent, node)) | |
| 269 | + if (extent_equal(&parent->in_extent, &node->in_extent)) | |
| 282 | 270 | return parent; |
| 283 | 271 | |
| 284 | 272 | /* max_high field must be updated after each iteration */ |
| 285 | 273 | if (parent->in_max_high < interval_high(node)) |
| 286 | 274 | parent->in_max_high = interval_high(node); |
| 287 | 275 | |
| 288 | − if (node_compare(node, parent) < 0) | |
| 276 | + if (extent_compare(&node->in_extent, &parent->in_extent) < 0) | |
| 289 | 277 | p = &parent->in_left; |
| 290 | 278 | else |
| 291 | 279 | p = &parent->in_right; |
| @@ -149,7 +149,7 @@ static inline int lock_mode_to_index(ldlm_mode_t mode) · 148 unmodified lines | ||
| 149 | 149 | int index; |
| 150 | 150 | |
| 151 | 151 | LASSERT(mode != 0); |
| 152 | − LASSERT(IS_PO2(mode)); | |
| 152 | + LASSERT(is_power_of_2(mode)); | |
| 153 | 153 | for (index = -1; mode; index++) |
| 154 | 154 | mode >>= 1; |
| 155 | 155 | LASSERT(index < LCK_MODE_NUM); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2010, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2010, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2010, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2010, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2010, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2010, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2010, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2010, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -176,11 +176,6 @@ enum { · 142 unmodified lines | ||
| 176 | 176 | LDLM_POOL_LAST_STAT |
| 177 | 177 | }; |
| 178 | 178 | |
| 179 | −static inline struct ldlm_namespace *ldlm_pl2ns(struct ldlm_pool *pl) | |
| 180 | −{ | |
| 181 | − return container_of(pl, struct ldlm_namespace, ns_pool); | |
| 182 | −} | |
| 183 | − | |
| 184 | 179 | /** |
| 185 | 180 | * Calculates suggested grant_step in % of available locks for passed |
| 186 | 181 | * \a period. This is later used in grant_plan calculations. |
| @@ -212,22 +207,6 @@ static inline int ldlm_pool_t2gsp(unsigned int t) · 25 unmodified lines | ||
| 212 | 207 | (t >> LDLM_POOL_GSP_STEP_SHIFT)); |
| 213 | 208 | } |
| 214 | 209 | |
| 215 | −/** | |
| 216 | − * Returns current \a pl limit. | |
| 217 | − */ | |
| 218 | −static __u32 ldlm_pool_get_limit(struct ldlm_pool *pl) | |
| 219 | −{ | |
| 220 | − return atomic_read(&pl->pl_limit); | |
| 221 | −} | |
| 222 | − | |
| 223 | −/** | |
| 224 | − * Sets passed \a limit to \a pl. | |
| 225 | − */ | |
| 226 | −static void ldlm_pool_set_limit(struct ldlm_pool *pl, __u32 limit) | |
| 227 | −{ | |
| 228 | − atomic_set(&pl->pl_limit, limit); | |
| 229 | −} | |
| 230 | − | |
| 231 | 210 | /** |
| 232 | 211 | * Recalculates next stats on passed \a pl. |
| 233 | 212 | * |
| @@ -254,7 +233,8 @@ static void ldlm_pool_recalc_stats(struct ldlm_pool *pl) · 20 unmodified lines | ||
| 254 | 233 | } |
| 255 | 234 | |
| 256 | 235 | /** |
| 257 | − * Sets SLV and Limit from ldlm_pl2ns(pl)->ns_obd tp passed \a pl. | |
| 236 | + * Sets SLV and Limit from container_of(pl, struct ldlm_namespace, | |
| 237 | + * ns_pool)->ns_obd tp passed \a pl. | |
| 258 | 238 | */ |
| 259 | 239 | static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl) |
| 260 | 240 | { |
| @@ -264,11 +244,12 @@ static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl) · 3 unmodified lines | ||
| 264 | 244 | * Get new SLV and Limit from obd which is updated with coming |
| 265 | 245 | * RPCs. |
| 266 | 246 | */ |
| 267 | − obd = ldlm_pl2ns(pl)->ns_obd; | |
| 247 | + obd = container_of(pl, struct ldlm_namespace, | |
| 248 | + ns_pool)->ns_obd; | |
| 268 | 249 | LASSERT(obd != NULL); |
| 269 | 250 | read_lock(&obd->obd_pool_lock); |
| 270 | 251 | pl->pl_server_lock_volume = obd->obd_pool_slv; |
| 271 | − ldlm_pool_set_limit(pl, obd->obd_pool_limit); | |
| 252 | + atomic_set(&pl->pl_limit, obd->obd_pool_limit); | |
| 272 | 253 | read_unlock(&obd->obd_pool_lock); |
| 273 | 254 | } |
| 274 | 255 | |
| @@ -304,7 +285,8 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) · 29 unmodified lines | ||
| 304 | 285 | /* |
| 305 | 286 | * Do not cancel locks in case lru resize is disabled for this ns. |
| 306 | 287 | */ |
| 307 | − if (!ns_connect_lru_resize(ldlm_pl2ns(pl))) { | |
| 288 | + if (!ns_connect_lru_resize(container_of(pl, struct ldlm_namespace, | |
| 289 | + ns_pool))) { | |
| 308 | 290 | ret = 0; |
| 309 | 291 | goto out; |
| 310 | 292 | } |
| @@ -315,7 +297,8 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) · 4 unmodified lines | ||
| 315 | 297 | * It may be called when SLV has changed much, this is why we do not |
| 316 | 298 | * take into account pl->pl_recalc_time here. |
| 317 | 299 | */ |
| 318 | − ret = ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC, LDLM_CANCEL_LRUR); | |
| 300 | + ret = ldlm_cancel_lru(container_of(pl, struct ldlm_namespace, ns_pool), | |
| 301 | + 0, LCF_ASYNC, LDLM_CANCEL_LRUR); | |
| 319 | 302 | |
| 320 | 303 | out: |
| 321 | 304 | spin_lock(&pl->pl_lock); |
| @@ -341,7 +324,7 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl, · 19 unmodified lines | ||
| 341 | 324 | struct ldlm_namespace *ns; |
| 342 | 325 | int unused; |
| 343 | 326 | |
| 344 | − ns = ldlm_pl2ns(pl); | |
| 327 | + ns = container_of(pl, struct ldlm_namespace, ns_pool); | |
| 345 | 328 | |
| 346 | 329 | /* |
| 347 | 330 | * Do not cancel locks in case lru resize is disabled for this ns. |
| @@ -453,7 +436,7 @@ static int lprocfs_pool_state_seq_show(struct seq_file *m, void *unused) · 105 unmodified lines | ||
| 453 | 436 | spin_lock(&pl->pl_lock); |
| 454 | 437 | slv = pl->pl_server_lock_volume; |
| 455 | 438 | clv = pl->pl_client_lock_volume; |
| 456 | − limit = ldlm_pool_get_limit(pl); | |
| 439 | + limit = atomic_read(&pl->pl_limit); | |
| 457 | 440 | granted = atomic_read(&pl->pl_granted); |
| 458 | 441 | grant_rate = atomic_read(&pl->pl_grant_rate); |
| 459 | 442 | cancel_rate = atomic_read(&pl->pl_cancel_rate); |
| @@ -558,7 +541,8 @@ static struct kobj_type ldlm_pl_ktype = { · 98 unmodified lines | ||
| 558 | 541 | |
| 559 | 542 | static int ldlm_pool_sysfs_init(struct ldlm_pool *pl) |
| 560 | 543 | { |
| 561 | − struct ldlm_namespace *ns = ldlm_pl2ns(pl); | |
| 544 | + struct ldlm_namespace *ns = container_of(pl, struct ldlm_namespace, | |
| 545 | + ns_pool); | |
| 562 | 546 | int err; |
| 563 | 547 | |
| 564 | 548 | init_completion(&pl->pl_kobj_unregister); |
| @@ -570,7 +554,8 @@ static int ldlm_pool_sysfs_init(struct ldlm_pool *pl) · 5 unmodified lines | ||
| 570 | 554 | |
| 571 | 555 | static int ldlm_pool_debugfs_init(struct ldlm_pool *pl) |
| 572 | 556 | { |
| 573 | − struct ldlm_namespace *ns = ldlm_pl2ns(pl); | |
| 557 | + struct ldlm_namespace *ns = container_of(pl, struct ldlm_namespace, | |
| 558 | + ns_pool); | |
| 574 | 559 | struct dentry *debugfs_ns_parent; |
| 575 | 560 | struct lprocfs_vars pool_vars[2]; |
| 576 | 561 | char *var_name = NULL; |
| @@ -685,7 +670,7 @@ int ldlm_pool_init(struct ldlm_pool *pl, struct ldlm_namespace *ns, · 108 unmodified lines | ||
| 685 | 670 | snprintf(pl->pl_name, sizeof(pl->pl_name), "ldlm-pool-%s-%d", |
| 686 | 671 | ldlm_ns_name(ns), idx); |
| 687 | 672 | |
| 688 | − ldlm_pool_set_limit(pl, 1); | |
| 673 | + atomic_set(&pl->pl_limit, 1); | |
| 689 | 674 | pl->pl_server_lock_volume = 0; |
| 690 | 675 | pl->pl_ops = &ldlm_cli_pool_ops; |
| 691 | 676 | pl->pl_recalc_period = LDLM_POOL_CLI_DEF_RECALC_PERIOD; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2010, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2010, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2010, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2010, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -1154,8 +1154,6 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, · 1120 unmodified lines | ||
| 1154 | 1154 | CERROR("%s: lvbo_init failed for resource %#llx:%#llx: rc = %d\n", |
| 1155 | 1155 | ns->ns_obd->obd_name, name->name[0], |
| 1156 | 1156 | name->name[1], rc); |
| 1157 | − kfree(res->lr_lvb_data); | |
| 1158 | − res->lr_lvb_data = NULL; | |
| 1159 | 1157 | res->lr_lvb_len = rc; |
| 1160 | 1158 | mutex_unlock(&res->lr_lvb_mutex); |
| 1161 | 1159 | ldlm_resource_putref(res); |
| @@ -94,17 +94,14 @@ static struct kernel_param_ops param_ops_debugmb = { · 93 unmodified lines | ||
| 94 | 94 | static unsigned int libcfs_debug_mb; |
| 95 | 95 | module_param(libcfs_debug_mb, debugmb, 0644); |
| 96 | 96 | MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size."); |
| 97 | −EXPORT_SYMBOL(libcfs_debug_mb); | |
| 98 | 97 | |
| 99 | 98 | unsigned int libcfs_printk = D_CANTMASK; |
| 100 | 99 | module_param(libcfs_printk, uint, 0644); |
| 101 | 100 | MODULE_PARM_DESC(libcfs_printk, "Lustre kernel debug console mask"); |
| 102 | −EXPORT_SYMBOL(libcfs_printk); | |
| 103 | 101 | |
| 104 | 102 | unsigned int libcfs_console_ratelimit = 1; |
| 105 | 103 | module_param(libcfs_console_ratelimit, uint, 0644); |
| 106 | 104 | MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)"); |
| 107 | −EXPORT_SYMBOL(libcfs_console_ratelimit); | |
| 108 | 105 | |
| 109 | 106 | static int param_set_delay_minmax(const char *val, |
| 110 | 107 | const struct kernel_param *kp, |
| @@ -135,9 +132,7 @@ static int param_get_delay(char *buffer, const struct kernel_param *kp) · 24 unmodified lines | ||
| 135 | 132 | } |
| 136 | 133 | |
| 137 | 134 | unsigned int libcfs_console_max_delay; |
| 138 | −EXPORT_SYMBOL(libcfs_console_max_delay); | |
| 139 | 135 | unsigned int libcfs_console_min_delay; |
| 140 | −EXPORT_SYMBOL(libcfs_console_min_delay); | |
| 141 | 136 | |
| 142 | 137 | static int param_set_console_max_delay(const char *val, |
| 143 | 138 | const struct kernel_param *kp) |
| @@ -207,10 +202,8 @@ static struct kernel_param_ops param_ops_uintpos = { · 63 unmodified lines | ||
| 207 | 202 | unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF; |
| 208 | 203 | module_param(libcfs_console_backoff, uintpos, 0644); |
| 209 | 204 | MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor"); |
| 210 | −EXPORT_SYMBOL(libcfs_console_backoff); | |
| 211 | 205 | |
| 212 | 206 | unsigned int libcfs_debug_binary = 1; |
| 213 | −EXPORT_SYMBOL(libcfs_debug_binary); | |
| 214 | 207 | |
| 215 | 208 | unsigned int libcfs_stack = 3 * THREAD_SIZE / 4; |
| 216 | 209 | EXPORT_SYMBOL(libcfs_stack); |
| @@ -221,7 +214,6 @@ EXPORT_SYMBOL(libcfs_catastrophe); · 4 unmodified lines | ||
| 221 | 214 | unsigned int libcfs_panic_on_lbug = 1; |
| 222 | 215 | module_param(libcfs_panic_on_lbug, uint, 0644); |
| 223 | 216 | MODULE_PARM_DESC(libcfs_panic_on_lbug, "Lustre kernel panic on LBUG"); |
| 224 | −EXPORT_SYMBOL(libcfs_panic_on_lbug); | |
| 225 | 217 | |
| 226 | 218 | static wait_queue_head_t debug_ctlwq; |
| 227 | 219 | |
| @@ -512,9 +504,9 @@ int libcfs_debug_init(unsigned long bufsize) · 284 unmodified lines | ||
| 512 | 504 | } |
| 513 | 505 | |
| 514 | 506 | if (libcfs_debug_file_path != NULL) { |
| 515 | − strncpy(libcfs_debug_file_path_arr, | |
| 516 | − libcfs_debug_file_path, PATH_MAX-1); | |
| 517 | − libcfs_debug_file_path_arr[PATH_MAX - 1] = '\0'; | |
| 507 | + strlcpy(libcfs_debug_file_path_arr, | |
| 508 | + libcfs_debug_file_path, | |
| 509 | + sizeof(libcfs_debug_file_path_arr)); | |
| 518 | 510 | } |
| 519 | 511 | |
| 520 | 512 | /* If libcfs_debug_mb is set to an invalid value or uninitialized |
| @@ -565,12 +557,3 @@ int libcfs_debug_mark_buffer(const char *text) · 44 unmodified lines | ||
| 565 | 557 | |
| 566 | 558 | #undef DEBUG_SUBSYSTEM |
| 567 | 559 | #define DEBUG_SUBSYSTEM S_LNET |
| 568 | − | |
| 569 | −void libcfs_debug_set_level(unsigned int debug_level) | |
| 570 | −{ | |
| 571 | − pr_warn("Lustre: Setting portals debug level to %08x\n", | |
| 572 | − debug_level); | |
| 573 | − libcfs_debug = debug_level; | |
| 574 | −} | |
| 575 | − | |
| 576 | −EXPORT_SYMBOL(libcfs_debug_set_level); | |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 27 | 27 | * Use is subject to license terms. |
| 28 | 28 | * |
| 29 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 29 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 30 | 30 | */ |
| 31 | 31 | /* |
| 32 | 32 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -126,7 +126,7 @@ int __cfs_fail_timeout_set(__u32 id, __u32 value, int ms, int set) · 93 unmodified lines | ||
| 126 | 126 | int ret; |
| 127 | 127 | |
| 128 | 128 | ret = __cfs_fail_check_set(id, value, set); |
| 129 | − if (ret) { | |
| 129 | + if (ret && likely(ms > 0)) { | |
| 130 | 130 | CERROR("cfs_fail_timeout id %x sleeping for %dms\n", |
| 131 | 131 | id, ms); |
| 132 | 132 | set_current_state(TASK_UNINTERRUPTIBLE); |
| @@ -106,9 +106,10 @@ · 105 unmodified lines | ||
| 106 | 106 | * Now we support both locked iteration & lockless iteration of hash |
| 107 | 107 | * table. Also, user can break the iteration by return 1 in callback. |
| 108 | 108 | */ |
| 109 | +#include <linux/seq_file.h> | |
| 110 | +#include <linux/log2.h> | |
| 109 | 111 | |
| 110 | 112 | #include "../../include/linux/libcfs/libcfs.h" |
| 111 | −#include <linux/seq_file.h> | |
| 112 | 113 | |
| 113 | 114 | #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1 |
| 114 | 115 | static unsigned int warn_on_depth = 8; |
| @@ -161,49 +162,49 @@ cfs_hash_rw_unlock(union cfs_hash_lock *lock, int exclusive) · 46 unmodified lines | ||
| 161 | 162 | /** No lock hash */ |
| 162 | 163 | static struct cfs_hash_lock_ops cfs_hash_nl_lops = { |
| 163 | 164 | .hs_lock = cfs_hash_nl_lock, |
| 164 | − .hs_unlock = cfs_hash_nl_unlock, | |
| 165 | − .hs_bkt_lock = cfs_hash_nl_lock, | |
| 166 | − .hs_bkt_unlock = cfs_hash_nl_unlock, | |
| 165 | + .hs_unlock = cfs_hash_nl_unlock, | |
| 166 | + .hs_bkt_lock = cfs_hash_nl_lock, | |
| 167 | + .hs_bkt_unlock = cfs_hash_nl_unlock, | |
| 167 | 168 | }; |
| 168 | 169 | |
| 169 | 170 | /** no bucket lock, one spinlock to protect everything */ |
| 170 | 171 | static struct cfs_hash_lock_ops cfs_hash_nbl_lops = { |
| 171 | 172 | .hs_lock = cfs_hash_spin_lock, |
| 172 | − .hs_unlock = cfs_hash_spin_unlock, | |
| 173 | − .hs_bkt_lock = cfs_hash_nl_lock, | |
| 174 | − .hs_bkt_unlock = cfs_hash_nl_unlock, | |
| 173 | + .hs_unlock = cfs_hash_spin_unlock, | |
| 174 | + .hs_bkt_lock = cfs_hash_nl_lock, | |
| 175 | + .hs_bkt_unlock = cfs_hash_nl_unlock, | |
| 175 | 176 | }; |
| 176 | 177 | |
| 177 | 178 | /** spin bucket lock, rehash is enabled */ |
| 178 | 179 | static struct cfs_hash_lock_ops cfs_hash_bkt_spin_lops = { |
| 179 | 180 | .hs_lock = cfs_hash_rw_lock, |
| 180 | − .hs_unlock = cfs_hash_rw_unlock, | |
| 181 | − .hs_bkt_lock = cfs_hash_spin_lock, | |
| 182 | − .hs_bkt_unlock = cfs_hash_spin_unlock, | |
| 181 | + .hs_unlock = cfs_hash_rw_unlock, | |
| 182 | + .hs_bkt_lock = cfs_hash_spin_lock, | |
| 183 | + .hs_bkt_unlock = cfs_hash_spin_unlock, | |
| 183 | 184 | }; |
| 184 | 185 | |
| 185 | 186 | /** rw bucket lock, rehash is enabled */ |
| 186 | 187 | static struct cfs_hash_lock_ops cfs_hash_bkt_rw_lops = { |
| 187 | 188 | .hs_lock = cfs_hash_rw_lock, |
| 188 | − .hs_unlock = cfs_hash_rw_unlock, | |
| 189 | − .hs_bkt_lock = cfs_hash_rw_lock, | |
| 190 | − .hs_bkt_unlock = cfs_hash_rw_unlock, | |
| 189 | + .hs_unlock = cfs_hash_rw_unlock, | |
| 190 | + .hs_bkt_lock = cfs_hash_rw_lock, | |
| 191 | + .hs_bkt_unlock = cfs_hash_rw_unlock, | |
| 191 | 192 | }; |
| 192 | 193 | |
| 193 | 194 | /** spin bucket lock, rehash is disabled */ |
| 194 | 195 | static struct cfs_hash_lock_ops cfs_hash_nr_bkt_spin_lops = { |
| 195 | 196 | .hs_lock = cfs_hash_nl_lock, |
| 196 | − .hs_unlock = cfs_hash_nl_unlock, | |
| 197 | − .hs_bkt_lock = cfs_hash_spin_lock, | |
| 198 | − .hs_bkt_unlock = cfs_hash_spin_unlock, | |
| 197 | + .hs_unlock = cfs_hash_nl_unlock, | |
| 198 | + .hs_bkt_lock = cfs_hash_spin_lock, | |
| 199 | + .hs_bkt_unlock = cfs_hash_spin_unlock, | |
| 199 | 200 | }; |
| 200 | 201 | |
| 201 | 202 | /** rw bucket lock, rehash is disabled */ |
| 202 | 203 | static struct cfs_hash_lock_ops cfs_hash_nr_bkt_rw_lops = { |
| 203 | 204 | .hs_lock = cfs_hash_nl_lock, |
| 204 | − .hs_unlock = cfs_hash_nl_unlock, | |
| 205 | − .hs_bkt_lock = cfs_hash_rw_lock, | |
| 206 | − .hs_bkt_unlock = cfs_hash_rw_unlock, | |
| 205 | + .hs_unlock = cfs_hash_nl_unlock, | |
| 206 | + .hs_bkt_lock = cfs_hash_rw_lock, | |
| 207 | + .hs_bkt_unlock = cfs_hash_rw_unlock, | |
| 207 | 208 | }; |
| 208 | 209 | |
| 209 | 210 | static void |
| @@ -280,7 +281,7 @@ cfs_hash_hh_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd, · 70 unmodified lines | ||
| 280 | 281 | */ |
| 281 | 282 | struct cfs_hash_head_dep { |
| 282 | 283 | struct hlist_head hd_head; /**< entries list */ |
| 283 | − unsigned int hd_depth; /**< list length */ | |
| 284 | + unsigned int hd_depth; /**< list length */ | |
| 284 | 285 | }; |
| 285 | 286 | |
| 286 | 287 | static int |
| @@ -328,7 +329,7 @@ cfs_hash_hd_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd, · 41 unmodified lines | ||
| 328 | 329 | */ |
| 329 | 330 | struct cfs_hash_dhead { |
| 330 | 331 | struct hlist_head dh_head; /**< entries list */ |
| 331 | − struct hlist_node *dh_tail; /**< the last entry */ | |
| 332 | + struct hlist_node *dh_tail; /**< the last entry */ | |
| 332 | 333 | }; |
| 333 | 334 | |
| 334 | 335 | static int |
| @@ -384,8 +385,8 @@ cfs_hash_dh_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd, · 49 unmodified lines | ||
| 384 | 385 | */ |
| 385 | 386 | struct cfs_hash_dhead_dep { |
| 386 | 387 | struct hlist_head dd_head; /**< entries list */ |
| 387 | − struct hlist_node *dd_tail; /**< the last entry */ | |
| 388 | − unsigned int dd_depth; /**< list length */ | |
| 388 | + struct hlist_node *dd_tail; /**< the last entry */ | |
| 389 | + unsigned int dd_depth; /**< list length */ | |
| 389 | 390 | }; |
| 390 | 391 | |
| 391 | 392 | static int |
| @@ -436,31 +437,31 @@ cfs_hash_dd_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd, · 44 unmodified lines | ||
| 436 | 437 | } |
| 437 | 438 | |
| 438 | 439 | static struct cfs_hash_hlist_ops cfs_hash_hh_hops = { |
| 439 | − .hop_hhead = cfs_hash_hh_hhead, | |
| 440 | − .hop_hhead_size = cfs_hash_hh_hhead_size, | |
| 441 | − .hop_hnode_add = cfs_hash_hh_hnode_add, | |
| 442 | − .hop_hnode_del = cfs_hash_hh_hnode_del, | |
| 440 | + .hop_hhead = cfs_hash_hh_hhead, | |
| 441 | + .hop_hhead_size = cfs_hash_hh_hhead_size, | |
| 442 | + .hop_hnode_add = cfs_hash_hh_hnode_add, | |
| 443 | + .hop_hnode_del = cfs_hash_hh_hnode_del, | |
| 443 | 444 | }; |
| 444 | 445 | |
| 445 | 446 | static struct cfs_hash_hlist_ops cfs_hash_hd_hops = { |
| 446 | − .hop_hhead = cfs_hash_hd_hhead, | |
| 447 | − .hop_hhead_size = cfs_hash_hd_hhead_size, | |
| 448 | − .hop_hnode_add = cfs_hash_hd_hnode_add, | |
| 449 | − .hop_hnode_del = cfs_hash_hd_hnode_del, | |
| 447 | + .hop_hhead = cfs_hash_hd_hhead, | |
| 448 | + .hop_hhead_size = cfs_hash_hd_hhead_size, | |
| 449 | + .hop_hnode_add = cfs_hash_hd_hnode_add, | |
| 450 | + .hop_hnode_del = cfs_hash_hd_hnode_del, | |
| 450 | 451 | }; |
| 451 | 452 | |
| 452 | 453 | static struct cfs_hash_hlist_ops cfs_hash_dh_hops = { |
| 453 | − .hop_hhead = cfs_hash_dh_hhead, | |
| 454 | − .hop_hhead_size = cfs_hash_dh_hhead_size, | |
| 455 | − .hop_hnode_add = cfs_hash_dh_hnode_add, | |
| 456 | − .hop_hnode_del = cfs_hash_dh_hnode_del, | |
| 454 | + .hop_hhead = cfs_hash_dh_hhead, | |
| 455 | + .hop_hhead_size = cfs_hash_dh_hhead_size, | |
| 456 | + .hop_hnode_add = cfs_hash_dh_hnode_add, | |
| 457 | + .hop_hnode_del = cfs_hash_dh_hnode_del, | |
| 457 | 458 | }; |
| 458 | 459 | |
| 459 | 460 | static struct cfs_hash_hlist_ops cfs_hash_dd_hops = { |
| 460 | − .hop_hhead = cfs_hash_dd_hhead, | |
| 461 | − .hop_hhead_size = cfs_hash_dd_hhead_size, | |
| 462 | − .hop_hnode_add = cfs_hash_dd_hnode_add, | |
| 463 | − .hop_hnode_del = cfs_hash_dd_hnode_del, | |
| 461 | + .hop_hhead = cfs_hash_dd_hhead, | |
| 462 | + .hop_hhead_size = cfs_hash_dd_hhead_size, | |
| 463 | + .hop_hnode_add = cfs_hash_dd_hnode_add, | |
| 464 | + .hop_hnode_del = cfs_hash_dd_hnode_del, | |
| 464 | 465 | }; |
| 465 | 466 | |
| 466 | 467 | static void |
| @@ -529,7 +530,7 @@ void · 62 unmodified lines | ||
| 529 | 530 | cfs_hash_bd_add_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, |
| 530 | 531 | struct hlist_node *hnode) |
| 531 | 532 | { |
| 532 | − int rc; | |
| 533 | + int rc; | |
| 533 | 534 | |
| 534 | 535 | rc = hs->hs_hops->hop_hnode_add(hs, bd, hnode); |
| 535 | 536 | cfs_hash_bd_dep_record(hs, bd, rc); |
| @@ -572,7 +573,7 @@ cfs_hash_bd_move_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd_old, · 36 unmodified lines | ||
| 572 | 573 | { |
| 573 | 574 | struct cfs_hash_bucket *obkt = bd_old->bd_bucket; |
| 574 | 575 | struct cfs_hash_bucket *nbkt = bd_new->bd_bucket; |
| 575 | − int rc; | |
| 576 | + int rc; | |
| 576 | 577 | |
| 577 | 578 | if (cfs_hash_bd_compare(bd_old, bd_new) == 0) |
| 578 | 579 | return; |
| @@ -593,34 +594,33 @@ cfs_hash_bd_move_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd_old, · 14 unmodified lines | ||
| 593 | 594 | if (unlikely(nbkt->hsb_version == 0)) |
| 594 | 595 | nbkt->hsb_version++; |
| 595 | 596 | } |
| 596 | −EXPORT_SYMBOL(cfs_hash_bd_move_locked); | |
| 597 | 597 | |
| 598 | 598 | enum { |
| 599 | 599 | /** always set, for sanity (avoid ZERO intent) */ |
| 600 | − CFS_HS_LOOKUP_MASK_FIND = BIT(0), | |
| 600 | + CFS_HS_LOOKUP_MASK_FIND = BIT(0), | |
| 601 | 601 | /** return entry with a ref */ |
| 602 | − CFS_HS_LOOKUP_MASK_REF = BIT(1), | |
| 602 | + CFS_HS_LOOKUP_MASK_REF = BIT(1), | |
| 603 | 603 | /** add entry if not existing */ |
| 604 | − CFS_HS_LOOKUP_MASK_ADD = BIT(2), | |
| 604 | + CFS_HS_LOOKUP_MASK_ADD = BIT(2), | |
| 605 | 605 | /** delete entry, ignore other masks */ |
| 606 | − CFS_HS_LOOKUP_MASK_DEL = BIT(3), | |
| 606 | + CFS_HS_LOOKUP_MASK_DEL = BIT(3), | |
| 607 | 607 | }; |
| 608 | 608 | |
| 609 | 609 | enum cfs_hash_lookup_intent { |
| 610 | 610 | /** return item w/o refcount */ |
| 611 | − CFS_HS_LOOKUP_IT_PEEK = CFS_HS_LOOKUP_MASK_FIND, | |
| 611 | + CFS_HS_LOOKUP_IT_PEEK = CFS_HS_LOOKUP_MASK_FIND, | |
| 612 | 612 | /** return item with refcount */ |
| 613 | − CFS_HS_LOOKUP_IT_FIND = (CFS_HS_LOOKUP_MASK_FIND | | |
| 614 | − CFS_HS_LOOKUP_MASK_REF), | |
| 613 | + CFS_HS_LOOKUP_IT_FIND = (CFS_HS_LOOKUP_MASK_FIND | | |
| 614 | + CFS_HS_LOOKUP_MASK_REF), | |
| 615 | 615 | /** return item w/o refcount if existed, otherwise add */ |
| 616 | − CFS_HS_LOOKUP_IT_ADD = (CFS_HS_LOOKUP_MASK_FIND | | |
| 617 | − CFS_HS_LOOKUP_MASK_ADD), | |
| 616 | + CFS_HS_LOOKUP_IT_ADD = (CFS_HS_LOOKUP_MASK_FIND | | |
| 617 | + CFS_HS_LOOKUP_MASK_ADD), | |
| 618 | 618 | /** return item with refcount if existed, otherwise add */ |
| 619 | − CFS_HS_LOOKUP_IT_FINDADD = (CFS_HS_LOOKUP_IT_FIND | | |
| 620 | − CFS_HS_LOOKUP_MASK_ADD), | |
| 619 | + CFS_HS_LOOKUP_IT_FINDADD = (CFS_HS_LOOKUP_IT_FIND | | |
| 620 | + CFS_HS_LOOKUP_MASK_ADD), | |
| 621 | 621 | /** delete if existed */ |
| 622 | − CFS_HS_LOOKUP_IT_FINDDEL = (CFS_HS_LOOKUP_MASK_FIND | | |
| 623 | − CFS_HS_LOOKUP_MASK_DEL) | |
| 622 | + CFS_HS_LOOKUP_IT_FINDDEL = (CFS_HS_LOOKUP_MASK_FIND | | |
| 623 | + CFS_HS_LOOKUP_MASK_DEL) | |
| 624 | 624 | }; |
| 625 | 625 | |
| 626 | 626 | static struct hlist_node * |
| @@ -629,10 +629,10 @@ cfs_hash_bd_lookup_intent(struct cfs_hash *hs, struct cfs_hash_bd *bd, · 2 unmodified lines | ||
| 629 | 629 | enum cfs_hash_lookup_intent intent) |
| 630 | 630 | |
| 631 | 631 | { |
| 632 | − struct hlist_head *hhead = cfs_hash_bd_hhead(hs, bd); | |
| 633 | − struct hlist_node *ehnode; | |
| 634 | − struct hlist_node *match; | |
| 635 | − int intent_add = (intent & CFS_HS_LOOKUP_MASK_ADD) != 0; | |
| 632 | + struct hlist_head *hhead = cfs_hash_bd_hhead(hs, bd); | |
| 633 | + struct hlist_node *ehnode; | |
| 634 | + struct hlist_node *match; | |
| 635 | + int intent_add = (intent & CFS_HS_LOOKUP_MASK_ADD) != 0; | |
| 636 | 636 | |
| 637 | 637 | /* with this function, we can avoid a lot of useless refcount ops, |
| 638 | 638 | * which are expensive atomic operations most time. */ |
| @@ -665,7 +665,8 @@ cfs_hash_bd_lookup_intent(struct cfs_hash *hs, struct cfs_hash_bd *bd, · 26 unmodified lines | ||
| 665 | 665 | } |
| 666 | 666 | |
| 667 | 667 | struct hlist_node * |
| 668 | −cfs_hash_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, const void *key) | |
| 668 | +cfs_hash_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, | |
| 669 | + const void *key) | |
| 669 | 670 | { |
| 670 | 671 | return cfs_hash_bd_lookup_intent(hs, bd, key, NULL, |
| 671 | 672 | CFS_HS_LOOKUP_IT_FIND); |
| @@ -673,40 +674,20 @@ cfs_hash_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, const voi · 1 unmodified line | ||
| 673 | 674 | EXPORT_SYMBOL(cfs_hash_bd_lookup_locked); |
| 674 | 675 | |
| 675 | 676 | struct hlist_node * |
| 676 | −cfs_hash_bd_peek_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, const void *key) | |
| 677 | +cfs_hash_bd_peek_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, | |
| 678 | + const void *key) | |
| 677 | 679 | { |
| 678 | 680 | return cfs_hash_bd_lookup_intent(hs, bd, key, NULL, |
| 679 | 681 | CFS_HS_LOOKUP_IT_PEEK); |
| 680 | 682 | } |
| 681 | 683 | EXPORT_SYMBOL(cfs_hash_bd_peek_locked); |
| 682 | 684 | |
| 683 | −struct hlist_node * | |
| 684 | −cfs_hash_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, | |
| 685 | − const void *key, struct hlist_node *hnode, | |
| 686 | − int noref) | |
| 687 | −{ | |
| 688 | − return cfs_hash_bd_lookup_intent(hs, bd, key, hnode, | |
| 689 | − (!noref * CFS_HS_LOOKUP_MASK_REF) | | |
| 690 | − CFS_HS_LOOKUP_IT_ADD); | |
| 691 | −} | |
| 692 | −EXPORT_SYMBOL(cfs_hash_bd_findadd_locked); | |
| 693 | − | |
| 694 | −struct hlist_node * | |
| 695 | −cfs_hash_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, | |
| 696 | − const void *key, struct hlist_node *hnode) | |
| 697 | −{ | |
| 698 | − /* hnode can be NULL, we find the first item with @key */ | |
| 699 | − return cfs_hash_bd_lookup_intent(hs, bd, key, hnode, | |
| 700 | − CFS_HS_LOOKUP_IT_FINDDEL); | |
| 701 | −} | |
| 702 | −EXPORT_SYMBOL(cfs_hash_bd_finddel_locked); | |
| 703 | − | |
| 704 | 685 | static void |
| 705 | 686 | cfs_hash_multi_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, |
| 706 | 687 | unsigned n, int excl) |
| 707 | 688 | { |
| 708 | 689 | struct cfs_hash_bucket *prev = NULL; |
| 709 | − int i; | |
| 690 | + int i; | |
| 710 | 691 | |
| 711 | 692 | /** |
| 712 | 693 | * bds must be ascendantly ordered by bd->bd_bucket->hsb_index. |
| @@ -729,7 +710,7 @@ cfs_hash_multi_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds, · 16 unmodified lines | ||
| 729 | 710 | unsigned n, int excl) |
| 730 | 711 | { |
| 731 | 712 | struct cfs_hash_bucket *prev = NULL; |
| 732 | − int i; | |
| 713 | + int i; | |
| 733 | 714 | |
| 734 | 715 | cfs_hash_for_each_bd(bds, n, i) { |
| 735 | 716 | if (prev != bds[i].bd_bucket) { |
| @@ -743,8 +724,8 @@ static struct hlist_node * · 7 unmodified lines | ||
| 743 | 724 | cfs_hash_multi_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, |
| 744 | 725 | unsigned n, const void *key) |
| 745 | 726 | { |
| 746 | − struct hlist_node *ehnode; | |
| 747 | − unsigned i; | |
| 727 | + struct hlist_node *ehnode; | |
| 728 | + unsigned i; | |
| 748 | 729 | |
| 749 | 730 | cfs_hash_for_each_bd(bds, n, i) { |
| 750 | 731 | ehnode = cfs_hash_bd_lookup_intent(hs, &bds[i], key, NULL, |
| @@ -756,13 +737,13 @@ cfs_hash_multi_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, · 5 unmodified lines | ||
| 756 | 737 | } |
| 757 | 738 | |
| 758 | 739 | static struct hlist_node * |
| 759 | −cfs_hash_multi_bd_findadd_locked(struct cfs_hash *hs, | |
| 760 | − struct cfs_hash_bd *bds, unsigned n, const void *key, | |
| 740 | +cfs_hash_multi_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, | |
| 741 | + unsigned n, const void *key, | |
| 761 | 742 | struct hlist_node *hnode, int noref) |
| 762 | 743 | { |
| 763 | − struct hlist_node *ehnode; | |
| 764 | − int intent; | |
| 765 | − unsigned i; | |
| 744 | + struct hlist_node *ehnode; | |
| 745 | + int intent; | |
| 746 | + unsigned i; | |
| 766 | 747 | |
| 767 | 748 | LASSERT(hnode != NULL); |
| 768 | 749 | intent = (!noref * CFS_HS_LOOKUP_MASK_REF) | CFS_HS_LOOKUP_IT_PEEK; |
| @@ -777,7 +758,7 @@ cfs_hash_multi_bd_findadd_locked(struct cfs_hash *hs, · 8 unmodified lines | ||
| 777 | 758 | if (i == 1) { /* only one bucket */ |
| 778 | 759 | cfs_hash_bd_add_locked(hs, &bds[0], hnode); |
| 779 | 760 | } else { |
| 780 | − struct cfs_hash_bd mybd; | |
| 761 | + struct cfs_hash_bd mybd; | |
| 781 | 762 | |
| 782 | 763 | cfs_hash_bd_get(hs, key, &mybd); |
| 783 | 764 | cfs_hash_bd_add_locked(hs, &mybd, hnode); |
| @@ -791,8 +772,8 @@ cfs_hash_multi_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, · 7 unmodified lines | ||
| 791 | 772 | unsigned n, const void *key, |
| 792 | 773 | struct hlist_node *hnode) |
| 793 | 774 | { |
| 794 | − struct hlist_node *ehnode; | |
| 795 | − unsigned i; | |
| 775 | + struct hlist_node *ehnode; | |
| 776 | + unsigned int i; | |
| 796 | 777 | |
| 797 | 778 | cfs_hash_for_each_bd(bds, n, i) { |
| 798 | 779 | ehnode = cfs_hash_bd_lookup_intent(hs, &bds[i], key, hnode, |
| @@ -806,7 +787,7 @@ cfs_hash_multi_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, · 7 unmodified lines | ||
| 806 | 787 | static void |
| 807 | 788 | cfs_hash_bd_order(struct cfs_hash_bd *bd1, struct cfs_hash_bd *bd2) |
| 808 | 789 | { |
| 809 | − int rc; | |
| 790 | + int rc; | |
| 810 | 791 | |
| 811 | 792 | if (bd2->bd_bucket == NULL) |
| 812 | 793 | return; |
| @@ -831,7 +812,8 @@ cfs_hash_bd_order(struct cfs_hash_bd *bd1, struct cfs_hash_bd *bd2) · 18 unmodified lines | ||
| 831 | 812 | } |
| 832 | 813 | |
| 833 | 814 | void |
| 834 | −cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *bds) | |
| 815 | +cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key, | |
| 816 | + struct cfs_hash_bd *bds) | |
| 835 | 817 | { |
| 836 | 818 | /* NB: caller should hold hs_lock.rw if REHASH is set */ |
| 837 | 819 | cfs_hash_bd_from_key(hs, hs->hs_buckets, |
| @@ -848,21 +830,18 @@ cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *b · 10 unmodified lines | ||
| 848 | 830 | |
| 849 | 831 | cfs_hash_bd_order(&bds[0], &bds[1]); |
| 850 | 832 | } |
| 851 | −EXPORT_SYMBOL(cfs_hash_dual_bd_get); | |
| 852 | 833 | |
| 853 | 834 | void |
| 854 | 835 | cfs_hash_dual_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl) |
| 855 | 836 | { |
| 856 | 837 | cfs_hash_multi_bd_lock(hs, bds, 2, excl); |
| 857 | 838 | } |
| 858 | −EXPORT_SYMBOL(cfs_hash_dual_bd_lock); | |
| 859 | 839 | |
| 860 | 840 | void |
| 861 | 841 | cfs_hash_dual_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl) |
| 862 | 842 | { |
| 863 | 843 | cfs_hash_multi_bd_unlock(hs, bds, 2, excl); |
| 864 | 844 | } |
| 865 | −EXPORT_SYMBOL(cfs_hash_dual_bd_unlock); | |
| 866 | 845 | |
| 867 | 846 | struct hlist_node * |
| 868 | 847 | cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, |
| @@ -870,7 +849,6 @@ cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, · 1 unmodified line | ||
| 870 | 849 | { |
| 871 | 850 | return cfs_hash_multi_bd_lookup_locked(hs, bds, 2, key); |
| 872 | 851 | } |
| 873 | −EXPORT_SYMBOL(cfs_hash_dual_bd_lookup_locked); | |
| 874 | 852 | |
| 875 | 853 | struct hlist_node * |
| 876 | 854 | cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, |
| @@ -880,7 +858,6 @@ cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, · 3 unmodified lines | ||
| 880 | 858 | return cfs_hash_multi_bd_findadd_locked(hs, bds, 2, key, |
| 881 | 859 | hnode, noref); |
| 882 | 860 | } |
| 883 | −EXPORT_SYMBOL(cfs_hash_dual_bd_findadd_locked); | |
| 884 | 861 | |
| 885 | 862 | struct hlist_node * |
| 886 | 863 | cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, |
| @@ -888,13 +865,12 @@ cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, · 1 unmodified line | ||
| 888 | 865 | { |
| 889 | 866 | return cfs_hash_multi_bd_finddel_locked(hs, bds, 2, key, hnode); |
| 890 | 867 | } |
| 891 | −EXPORT_SYMBOL(cfs_hash_dual_bd_finddel_locked); | |
| 892 | 868 | |
| 893 | 869 | static void |
| 894 | 870 | cfs_hash_buckets_free(struct cfs_hash_bucket **buckets, |
| 895 | 871 | int bkt_size, int prev_size, int size) |
| 896 | 872 | { |
| 897 | − int i; | |
| 873 | + int i; | |
| 898 | 874 | |
| 899 | 875 | for (i = prev_size; i < size; i++) { |
| 900 | 876 | if (buckets[i] != NULL) |
| @@ -914,7 +890,7 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts, · 13 unmodified lines | ||
| 914 | 890 | unsigned int old_size, unsigned int new_size) |
| 915 | 891 | { |
| 916 | 892 | struct cfs_hash_bucket **new_bkts; |
| 917 | − int i; | |
| 893 | + int i; | |
| 918 | 894 | |
| 919 | 895 | LASSERT(old_size == 0 || old_bkts != NULL); |
| 920 | 896 | |
| @@ -932,7 +908,7 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts, · 11 unmodified lines | ||
| 932 | 908 | |
| 933 | 909 | for (i = old_size; i < new_size; i++) { |
| 934 | 910 | struct hlist_head *hhead; |
| 935 | − struct cfs_hash_bd bd; | |
| 911 | + struct cfs_hash_bd bd; | |
| 936 | 912 | |
| 937 | 913 | LIBCFS_ALLOC(new_bkts[i], cfs_hash_bkt_size(hs)); |
| 938 | 914 | if (new_bkts[i] == NULL) { |
| @@ -969,7 +945,7 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts, · 30 unmodified lines | ||
| 969 | 945 | * @max_bits - Maximum allowed hash table resize, in bits |
| 970 | 946 | * @ops - Registered hash table operations |
| 971 | 947 | * @flags - CFS_HASH_REHASH enable synamic hash resizing |
| 972 | − * - CFS_HASH_SORT enable chained hash sort | |
| 948 | + * - CFS_HASH_SORT enable chained hash sort | |
| 973 | 949 | */ |
| 974 | 950 | static int cfs_hash_rehash_worker(cfs_workitem_t *wi); |
| 975 | 951 | |
| @@ -977,10 +953,10 @@ static int cfs_hash_rehash_worker(cfs_workitem_t *wi); · 1 unmodified line | ||
| 977 | 953 | static int cfs_hash_dep_print(cfs_workitem_t *wi) |
| 978 | 954 | { |
| 979 | 955 | struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_dep_wi); |
| 980 | − int dep; | |
| 981 | − int bkt; | |
| 982 | − int off; | |
| 983 | − int bits; | |
| 956 | + int dep; | |
| 957 | + int bkt; | |
| 958 | + int off; | |
| 959 | + int bits; | |
| 984 | 960 | |
| 985 | 961 | spin_lock(&hs->hs_dep_lock); |
| 986 | 962 | dep = hs->hs_dep_max; |
| @@ -1031,7 +1007,7 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits, · 44 unmodified lines | ||
| 1031 | 1007 | struct cfs_hash_ops *ops, unsigned flags) |
| 1032 | 1008 | { |
| 1033 | 1009 | struct cfs_hash *hs; |
| 1034 | − int len; | |
| 1010 | + int len; | |
| 1035 | 1011 | |
| 1036 | 1012 | CLASSERT(CFS_HASH_THETA_BITS < 15); |
| 1037 | 1013 | |
| @@ -1062,8 +1038,7 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits, · 24 unmodified lines | ||
| 1062 | 1038 | if (hs == NULL) |
| 1063 | 1039 | return NULL; |
| 1064 | 1040 | |
| 1065 | − strncpy(hs->hs_name, name, len); | |
| 1066 | − hs->hs_name[len - 1] = '\0'; | |
| 1041 | + strlcpy(hs->hs_name, name, len); | |
| 1067 | 1042 | hs->hs_flags = flags; |
| 1068 | 1043 | |
| 1069 | 1044 | atomic_set(&hs->hs_refcount, 1); |
| @@ -1077,7 +1052,7 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits, · 7 unmodified lines | ||
| 1077 | 1052 | hs->hs_max_bits = (__u8)max_bits; |
| 1078 | 1053 | hs->hs_bkt_bits = (__u8)bkt_bits; |
| 1079 | 1054 | |
| 1080 | − hs->hs_ops = ops; | |
| 1055 | + hs->hs_ops = ops; | |
| 1081 | 1056 | hs->hs_extra_bytes = extra_bytes; |
| 1082 | 1057 | hs->hs_rehash_bits = 0; |
| 1083 | 1058 | cfs_wi_init(&hs->hs_rehash_wi, hs, cfs_hash_rehash_worker); |
| @@ -1102,10 +1077,10 @@ EXPORT_SYMBOL(cfs_hash_create); · 18 unmodified lines | ||
| 1102 | 1077 | static void |
| 1103 | 1078 | cfs_hash_destroy(struct cfs_hash *hs) |
| 1104 | 1079 | { |
| 1105 | − struct hlist_node *hnode; | |
| 1106 | − struct hlist_node *pos; | |
| 1107 | − struct cfs_hash_bd bd; | |
| 1108 | − int i; | |
| 1080 | + struct hlist_node *hnode; | |
| 1081 | + struct hlist_node *pos; | |
| 1082 | + struct cfs_hash_bd bd; | |
| 1083 | + int i; | |
| 1109 | 1084 | |
| 1110 | 1085 | LASSERT(hs != NULL); |
| 1111 | 1086 | LASSERT(!cfs_hash_is_exiting(hs) && |
| @@ -1223,8 +1198,8 @@ cfs_hash_rehash_inline(struct cfs_hash *hs) · 111 unmodified lines | ||
| 1223 | 1198 | void |
| 1224 | 1199 | cfs_hash_add(struct cfs_hash *hs, const void *key, struct hlist_node *hnode) |
| 1225 | 1200 | { |
| 1226 | − struct cfs_hash_bd bd; | |
| 1227 | − int bits; | |
| 1201 | + struct cfs_hash_bd bd; | |
| 1202 | + int bits; | |
| 1228 | 1203 | |
| 1229 | 1204 | LASSERT(hlist_unhashed(hnode)); |
| 1230 | 1205 | |
| @@ -1248,8 +1223,8 @@ cfs_hash_find_or_add(struct cfs_hash *hs, const void *key, · 17 unmodified lines | ||
| 1248 | 1223 | struct hlist_node *hnode, int noref) |
| 1249 | 1224 | { |
| 1250 | 1225 | struct hlist_node *ehnode; |
| 1251 | − struct cfs_hash_bd bds[2]; | |
| 1252 | − int bits = 0; | |
| 1226 | + struct cfs_hash_bd bds[2]; | |
| 1227 | + int bits = 0; | |
| 1253 | 1228 | |
| 1254 | 1229 | LASSERT(hlist_unhashed(hnode)); |
| 1255 | 1230 | |
| @@ -1261,7 +1236,7 @@ cfs_hash_find_or_add(struct cfs_hash *hs, const void *key, · 5 unmodified lines | ||
| 1261 | 1236 | hnode, noref); |
| 1262 | 1237 | cfs_hash_dual_bd_unlock(hs, bds, 1); |
| 1263 | 1238 | |
| 1264 | − if (ehnode == hnode) /* new item added */ | |
| 1239 | + if (ehnode == hnode) /* new item added */ | |
| 1265 | 1240 | bits = cfs_hash_rehash_bits(hs); |
| 1266 | 1241 | cfs_hash_unlock(hs, 0); |
| 1267 | 1242 | if (bits > 0) |
| @@ -1276,7 +1251,8 @@ cfs_hash_find_or_add(struct cfs_hash *hs, const void *key, · 8 unmodified lines | ||
| 1276 | 1251 | * Returns 0 on success or -EALREADY on key collisions. |
| 1277 | 1252 | */ |
| 1278 | 1253 | int |
| 1279 | −cfs_hash_add_unique(struct cfs_hash *hs, const void *key, struct hlist_node *hnode) | |
| 1254 | +cfs_hash_add_unique(struct cfs_hash *hs, const void *key, | |
| 1255 | + struct hlist_node *hnode) | |
| 1280 | 1256 | { |
| 1281 | 1257 | return cfs_hash_find_or_add(hs, key, hnode, 1) != hnode ? |
| 1282 | 1258 | -EALREADY : 0; |
| @@ -1309,9 +1285,9 @@ EXPORT_SYMBOL(cfs_hash_findadd_unique); · 26 unmodified lines | ||
| 1309 | 1285 | void * |
| 1310 | 1286 | cfs_hash_del(struct cfs_hash *hs, const void *key, struct hlist_node *hnode) |
| 1311 | 1287 | { |
| 1312 | − void *obj = NULL; | |
| 1313 | − int bits = 0; | |
| 1314 | − struct cfs_hash_bd bds[2]; | |
| 1288 | + void *obj = NULL; | |
| 1289 | + int bits = 0; | |
| 1290 | + struct cfs_hash_bd bds[2]; | |
| 1315 | 1291 | |
| 1316 | 1292 | cfs_hash_lock(hs, 0); |
| 1317 | 1293 | cfs_hash_dual_bd_get_and_lock(hs, key, bds, 1); |
| @@ -1364,9 +1340,9 @@ EXPORT_SYMBOL(cfs_hash_del_key); · 46 unmodified lines | ||
| 1364 | 1340 | void * |
| 1365 | 1341 | cfs_hash_lookup(struct cfs_hash *hs, const void *key) |
| 1366 | 1342 | { |
| 1367 | − void *obj = NULL; | |
| 1368 | − struct hlist_node *hnode; | |
| 1369 | − struct cfs_hash_bd bds[2]; | |
| 1343 | + void *obj = NULL; | |
| 1344 | + struct hlist_node *hnode; | |
| 1345 | + struct cfs_hash_bd bds[2]; | |
| 1370 | 1346 | |
| 1371 | 1347 | cfs_hash_lock(hs, 0); |
| 1372 | 1348 | cfs_hash_dual_bd_get_and_lock(hs, key, bds, 0); |
| @@ -1383,7 +1359,8 @@ cfs_hash_lookup(struct cfs_hash *hs, const void *key) · 10 unmodified lines | ||
| 1383 | 1359 | EXPORT_SYMBOL(cfs_hash_lookup); |
| 1384 | 1360 | |
| 1385 | 1361 | static void |
| 1386 | −cfs_hash_for_each_enter(struct cfs_hash *hs) { | |
| 1362 | +cfs_hash_for_each_enter(struct cfs_hash *hs) | |
| 1363 | +{ | |
| 1387 | 1364 | LASSERT(!cfs_hash_is_exiting(hs)); |
| 1388 | 1365 | |
| 1389 | 1366 | if (!cfs_hash_with_rehash(hs)) |
| @@ -1408,7 +1385,8 @@ cfs_hash_for_each_enter(struct cfs_hash *hs) { · 18 unmodified lines | ||
| 1408 | 1385 | } |
| 1409 | 1386 | |
| 1410 | 1387 | static void |
| 1411 | −cfs_hash_for_each_exit(struct cfs_hash *hs) { | |
| 1388 | +cfs_hash_for_each_exit(struct cfs_hash *hs) | |
| 1389 | +{ | |
| 1412 | 1390 | int remained; |
| 1413 | 1391 | int bits; |
| 1414 | 1392 | |
| @@ -1439,14 +1417,15 @@ cfs_hash_for_each_exit(struct cfs_hash *hs) { · 24 unmodified lines | ||
| 1439 | 1417 | */ |
| 1440 | 1418 | static __u64 |
| 1441 | 1419 | cfs_hash_for_each_tight(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, |
| 1442 | − void *data, int remove_safe) { | |
| 1443 | − struct hlist_node *hnode; | |
| 1444 | − struct hlist_node *pos; | |
| 1445 | − struct cfs_hash_bd bd; | |
| 1446 | − __u64 count = 0; | |
| 1447 | − int excl = !!remove_safe; | |
| 1448 | − int loop = 0; | |
| 1449 | − int i; | |
| 1420 | + void *data, int remove_safe) | |
| 1421 | +{ | |
| 1422 | + struct hlist_node *hnode; | |
| 1423 | + struct hlist_node *pos; | |
| 1424 | + struct cfs_hash_bd bd; | |
| 1425 | + __u64 count = 0; | |
| 1426 | + int excl = !!remove_safe; | |
| 1427 | + int loop = 0; | |
| 1428 | + int i; | |
| 1450 | 1429 | |
| 1451 | 1430 | cfs_hash_for_each_enter(hs); |
| 1452 | 1431 | |
| @@ -1514,8 +1493,8 @@ void · 61 unmodified lines | ||
| 1514 | 1493 | cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t func, void *data) |
| 1515 | 1494 | { |
| 1516 | 1495 | struct cfs_hash_cond_arg arg = { |
| 1517 | − .func = func, | |
| 1518 | − .arg = data, | |
| 1496 | + .func = func, | |
| 1497 | + .arg = data, | |
| 1519 | 1498 | }; |
| 1520 | 1499 | |
| 1521 | 1500 | cfs_hash_for_each_tight(hs, cfs_hash_cond_del_locked, &arg, 1); |
| @@ -1523,16 +1502,17 @@ cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t func, void *data) · 1 unmodified line | ||
| 1523 | 1502 | EXPORT_SYMBOL(cfs_hash_cond_del); |
| 1524 | 1503 | |
| 1525 | 1504 | void |
| 1526 | −cfs_hash_for_each(struct cfs_hash *hs, | |
| 1527 | − cfs_hash_for_each_cb_t func, void *data) | |
| 1505 | +cfs_hash_for_each(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, | |
| 1506 | + void *data) | |
| 1528 | 1507 | { |
| 1529 | 1508 | cfs_hash_for_each_tight(hs, func, data, 0); |
| 1530 | 1509 | } |
| 1531 | 1510 | EXPORT_SYMBOL(cfs_hash_for_each); |
| 1532 | 1511 | |
| 1533 | 1512 | void |
| 1534 | −cfs_hash_for_each_safe(struct cfs_hash *hs, | |
| 1535 | − cfs_hash_for_each_cb_t func, void *data) { | |
| 1513 | +cfs_hash_for_each_safe(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, | |
| 1514 | + void *data) | |
| 1515 | +{ | |
| 1536 | 1516 | cfs_hash_for_each_tight(hs, func, data, 1); |
| 1537 | 1517 | } |
| 1538 | 1518 | EXPORT_SYMBOL(cfs_hash_for_each_safe); |
| @@ -1581,15 +1561,16 @@ EXPORT_SYMBOL(cfs_hash_size_get); · 42 unmodified lines | ||
| 1581 | 1561 | */ |
| 1582 | 1562 | static int |
| 1583 | 1563 | cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, |
| 1584 | − void *data) { | |
| 1564 | + void *data) | |
| 1565 | +{ | |
| 1585 | 1566 | struct hlist_node *hnode; |
| 1586 | 1567 | struct hlist_node *tmp; |
| 1587 | − struct cfs_hash_bd bd; | |
| 1588 | − __u32 version; | |
| 1589 | − int count = 0; | |
| 1590 | − int stop_on_change; | |
| 1591 | − int rc; | |
| 1592 | − int i; | |
| 1568 | + struct cfs_hash_bd bd; | |
| 1569 | + __u32 version; | |
| 1570 | + int count = 0; | |
| 1571 | + int stop_on_change; | |
| 1572 | + int rc; | |
| 1573 | + int i; | |
| 1593 | 1574 | |
| 1594 | 1575 | stop_on_change = cfs_hash_with_rehash_key(hs) || |
| 1595 | 1576 | !cfs_hash_with_no_itemref(hs) || |
| @@ -1645,8 +1626,9 @@ cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, · 49 unmodified lines | ||
| 1645 | 1626 | } |
| 1646 | 1627 | |
| 1647 | 1628 | int |
| 1648 | −cfs_hash_for_each_nolock(struct cfs_hash *hs, | |
| 1649 | − cfs_hash_for_each_cb_t func, void *data) { | |
| 1629 | +cfs_hash_for_each_nolock(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, | |
| 1630 | + void *data) | |
| 1631 | +{ | |
| 1650 | 1632 | if (cfs_hash_with_no_lock(hs) || |
| 1651 | 1633 | cfs_hash_with_rehash_key(hs) || |
| 1652 | 1634 | !cfs_hash_with_no_itemref(hs)) |
| @@ -1677,9 +1659,10 @@ EXPORT_SYMBOL(cfs_hash_for_each_nolock); · 24 unmodified lines | ||
| 1677 | 1659 | * the required locking is in place to prevent concurrent insertions. |
| 1678 | 1660 | */ |
| 1679 | 1661 | int |
| 1680 | −cfs_hash_for_each_empty(struct cfs_hash *hs, | |
| 1681 | − cfs_hash_for_each_cb_t func, void *data) { | |
| 1682 | − unsigned i = 0; | |
| 1662 | +cfs_hash_for_each_empty(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, | |
| 1663 | + void *data) | |
| 1664 | +{ | |
| 1665 | + unsigned i = 0; | |
| 1683 | 1666 | |
| 1684 | 1667 | if (cfs_hash_with_no_lock(hs)) |
| 1685 | 1668 | return -EOPNOTSUPP; |
| @@ -1703,9 +1686,9 @@ void · 17 unmodified lines | ||
| 1703 | 1686 | cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex, |
| 1704 | 1687 | cfs_hash_for_each_cb_t func, void *data) |
| 1705 | 1688 | { |
| 1706 | − struct hlist_head *hhead; | |
| 1707 | − struct hlist_node *hnode; | |
| 1708 | − struct cfs_hash_bd bd; | |
| 1689 | + struct hlist_head *hhead; | |
| 1690 | + struct hlist_node *hnode; | |
| 1691 | + struct cfs_hash_bd bd; | |
| 1709 | 1692 | |
| 1710 | 1693 | cfs_hash_for_each_enter(hs); |
| 1711 | 1694 | cfs_hash_lock(hs, 0); |
| @@ -1721,7 +1704,7 @@ cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex, · 9 unmodified lines | ||
| 1721 | 1704 | break; |
| 1722 | 1705 | } |
| 1723 | 1706 | cfs_hash_bd_unlock(hs, &bd, 0); |
| 1724 | − out: | |
| 1707 | +out: | |
| 1725 | 1708 | cfs_hash_unlock(hs, 0); |
| 1726 | 1709 | cfs_hash_for_each_exit(hs); |
| 1727 | 1710 | } |
| @@ -1736,10 +1719,11 @@ EXPORT_SYMBOL(cfs_hash_hlist_for_each); · 8 unmodified lines | ||
| 1736 | 1719 | */ |
| 1737 | 1720 | void |
| 1738 | 1721 | cfs_hash_for_each_key(struct cfs_hash *hs, const void *key, |
| 1739 | − cfs_hash_for_each_cb_t func, void *data) { | |
| 1740 | − struct hlist_node *hnode; | |
| 1741 | − struct cfs_hash_bd bds[2]; | |
| 1742 | − unsigned i; | |
| 1722 | + cfs_hash_for_each_cb_t func, void *data) | |
| 1723 | +{ | |
| 1724 | + struct hlist_node *hnode; | |
| 1725 | + struct cfs_hash_bd bds[2]; | |
| 1726 | + unsigned int i; | |
| 1743 | 1727 | |
| 1744 | 1728 | cfs_hash_lock(hs, 0); |
| 1745 | 1729 | |
| @@ -1777,7 +1761,7 @@ EXPORT_SYMBOL(cfs_hash_for_each_key); · 31 unmodified lines | ||
| 1777 | 1761 | void |
| 1778 | 1762 | cfs_hash_rehash_cancel_locked(struct cfs_hash *hs) |
| 1779 | 1763 | { |
| 1780 | − int i; | |
| 1764 | + int i; | |
| 1781 | 1765 | |
| 1782 | 1766 | /* need hold cfs_hash_lock(hs, 1) */ |
| 1783 | 1767 | LASSERT(cfs_hash_with_rehash(hs) && |
| @@ -1794,14 +1778,13 @@ cfs_hash_rehash_cancel_locked(struct cfs_hash *hs) · 10 unmodified lines | ||
| 1794 | 1778 | for (i = 2; cfs_hash_is_rehashing(hs); i++) { |
| 1795 | 1779 | cfs_hash_unlock(hs, 1); |
| 1796 | 1780 | /* raise console warning while waiting too long */ |
| 1797 | − CDEBUG(IS_PO2(i >> 3) ? D_WARNING : D_INFO, | |
| 1781 | + CDEBUG(is_power_of_2(i >> 3) ? D_WARNING : D_INFO, | |
| 1798 | 1782 | "hash %s is still rehashing, rescheded %d\n", |
| 1799 | 1783 | hs->hs_name, i - 1); |
| 1800 | 1784 | cond_resched(); |
| 1801 | 1785 | cfs_hash_lock(hs, 1); |
| 1802 | 1786 | } |
| 1803 | 1787 | } |
| 1804 | −EXPORT_SYMBOL(cfs_hash_rehash_cancel_locked); | |
| 1805 | 1788 | |
| 1806 | 1789 | void |
| 1807 | 1790 | cfs_hash_rehash_cancel(struct cfs_hash *hs) |
| @@ -1810,12 +1793,11 @@ cfs_hash_rehash_cancel(struct cfs_hash *hs) · 2 unmodified lines | ||
| 1810 | 1793 | cfs_hash_rehash_cancel_locked(hs); |
| 1811 | 1794 | cfs_hash_unlock(hs, 1); |
| 1812 | 1795 | } |
| 1813 | −EXPORT_SYMBOL(cfs_hash_rehash_cancel); | |
| 1814 | 1796 | |
| 1815 | 1797 | int |
| 1816 | 1798 | cfs_hash_rehash(struct cfs_hash *hs, int do_rehash) |
| 1817 | 1799 | { |
| 1818 | − int rc; | |
| 1800 | + int rc; | |
| 1819 | 1801 | |
| 1820 | 1802 | LASSERT(cfs_hash_with_rehash(hs) && !cfs_hash_with_no_lock(hs)); |
| 1821 | 1803 | |
| @@ -1840,17 +1822,16 @@ cfs_hash_rehash(struct cfs_hash *hs, int do_rehash) · 18 unmodified lines | ||
| 1840 | 1822 | |
| 1841 | 1823 | return cfs_hash_rehash_worker(&hs->hs_rehash_wi); |
| 1842 | 1824 | } |
| 1843 | −EXPORT_SYMBOL(cfs_hash_rehash); | |
| 1844 | 1825 | |
| 1845 | 1826 | static int |
| 1846 | 1827 | cfs_hash_rehash_bd(struct cfs_hash *hs, struct cfs_hash_bd *old) |
| 1847 | 1828 | { |
| 1848 | − struct cfs_hash_bd new; | |
| 1849 | − struct hlist_head *hhead; | |
| 1850 | − struct hlist_node *hnode; | |
| 1851 | − struct hlist_node *pos; | |
| 1852 | − void *key; | |
| 1853 | − int c = 0; | |
| 1829 | + struct cfs_hash_bd new; | |
| 1830 | + struct hlist_head *hhead; | |
| 1831 | + struct hlist_node *hnode; | |
| 1832 | + struct hlist_node *pos; | |
| 1833 | + void *key; | |
| 1834 | + int c = 0; | |
| 1854 | 1835 | |
| 1855 | 1836 | /* hold cfs_hash_lock(hs, 1), so don't need any bucket lock */ |
| 1856 | 1837 | cfs_hash_bd_for_each_hlist(hs, old, hhead) { |
| @@ -1876,17 +1857,17 @@ cfs_hash_rehash_bd(struct cfs_hash *hs, struct cfs_hash_bd *old) · 19 unmodified lines | ||
| 1876 | 1857 | static int |
| 1877 | 1858 | cfs_hash_rehash_worker(cfs_workitem_t *wi) |
| 1878 | 1859 | { |
| 1879 | − struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_rehash_wi); | |
| 1860 | + struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_rehash_wi); | |
| 1880 | 1861 | struct cfs_hash_bucket **bkts; |
| 1881 | − struct cfs_hash_bd bd; | |
| 1882 | − unsigned int old_size; | |
| 1883 | − unsigned int new_size; | |
| 1884 | − int bsize; | |
| 1885 | − int count = 0; | |
| 1886 | − int rc = 0; | |
| 1887 | − int i; | |
| 1862 | + struct cfs_hash_bd bd; | |
| 1863 | + unsigned int old_size; | |
| 1864 | + unsigned int new_size; | |
| 1865 | + int bsize; | |
| 1866 | + int count = 0; | |
| 1867 | + int rc = 0; | |
| 1868 | + int i; | |
| 1888 | 1869 | |
| 1889 | − LASSERT (hs != NULL && cfs_hash_with_rehash(hs)); | |
| 1870 | + LASSERT(hs != NULL && cfs_hash_with_rehash(hs)); | |
| 1890 | 1871 | |
| 1891 | 1872 | cfs_hash_lock(hs, 0); |
| 1892 | 1873 | LASSERT(cfs_hash_is_rehashing(hs)); |
| @@ -1958,7 +1939,7 @@ cfs_hash_rehash_worker(cfs_workitem_t *wi) · 65 unmodified lines | ||
| 1958 | 1939 | hs->hs_rehash_buckets = NULL; |
| 1959 | 1940 | |
| 1960 | 1941 | hs->hs_cur_bits = hs->hs_rehash_bits; |
| 1961 | − out: | |
| 1942 | +out: | |
| 1962 | 1943 | hs->hs_rehash_bits = 0; |
| 1963 | 1944 | if (rc == -ESRCH) /* never be scheduled again */ |
| 1964 | 1945 | cfs_wi_exit(cfs_sched_rehash, wi); |
| @@ -1986,9 +1967,9 @@ cfs_hash_rehash_worker(cfs_workitem_t *wi) · 21 unmodified lines | ||
| 1986 | 1967 | void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key, |
| 1987 | 1968 | void *new_key, struct hlist_node *hnode) |
| 1988 | 1969 | { |
| 1989 | − struct cfs_hash_bd bds[3]; | |
| 1990 | − struct cfs_hash_bd old_bds[2]; | |
| 1991 | − struct cfs_hash_bd new_bd; | |
| 1970 | + struct cfs_hash_bd bds[3]; | |
| 1971 | + struct cfs_hash_bd old_bds[2]; | |
| 1972 | + struct cfs_hash_bd new_bd; | |
| 1992 | 1973 | |
| 1993 | 1974 | LASSERT(!hlist_unhashed(hnode)); |
| 1994 | 1975 | |
| @@ -2014,7 +1995,7 @@ void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key, · 19 unmodified lines | ||
| 2014 | 1995 | } |
| 2015 | 1996 | /* overwrite key inside locks, otherwise may screw up with |
| 2016 | 1997 | * other operations, i.e: rehash */ |
| 2017 | − cfs_hash_keycpy(hs, new_key, hnode); | |
| 1998 | + cfs_hash_keycpy(hs, hnode, new_key); | |
| 2018 | 1999 | |
| 2019 | 2000 | cfs_hash_multi_bd_unlock(hs, bds, 3, 1); |
| 2020 | 2001 | cfs_hash_unlock(hs, 0); |
| @@ -2054,12 +2035,12 @@ cfs_hash_full_nbkt(struct cfs_hash *hs) · 33 unmodified lines | ||
| 2054 | 2035 | |
| 2055 | 2036 | void cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m) |
| 2056 | 2037 | { |
| 2057 | − int dist[8] = { 0, }; | |
| 2058 | − int maxdep = -1; | |
| 2059 | − int maxdepb = -1; | |
| 2060 | − int total = 0; | |
| 2061 | − int theta; | |
| 2062 | − int i; | |
| 2038 | + int dist[8] = { 0, }; | |
| 2039 | + int maxdep = -1; | |
| 2040 | + int maxdepb = -1; | |
| 2041 | + int total = 0; | |
| 2042 | + int theta; | |
| 2043 | + int i; | |
| 2063 | 2044 | |
| 2064 | 2045 | cfs_hash_lock(hs, 0); |
| 2065 | 2046 | theta = __cfs_hash_theta(hs); |
| @@ -2085,11 +2066,11 @@ void cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m) · 19 unmodified lines | ||
| 2085 | 2066 | * If you hash function results in a non-uniform hash the will |
| 2086 | 2067 | * be observable by outlier bucks in the distribution histogram. |
| 2087 | 2068 | * |
| 2088 | − * Uniform hash distribution: 128/128/0/0/0/0/0/0 | |
| 2089 | − * Non-Uniform hash distribution: 128/125/0/0/0/0/2/1 | |
| 2069 | + * Uniform hash distribution: 128/128/0/0/0/0/0/0 | |
| 2070 | + * Non-Uniform hash distribution: 128/125/0/0/0/0/2/1 | |
| 2090 | 2071 | */ |
| 2091 | 2072 | for (i = 0; i < cfs_hash_full_nbkt(hs); i++) { |
| 2092 | − struct cfs_hash_bd bd; | |
| 2073 | + struct cfs_hash_bd bd; | |
| 2093 | 2074 | |
| 2094 | 2075 | bd.bd_bucket = cfs_hash_full_bkts(hs)[i]; |
| 2095 | 2076 | cfs_hash_bd_lock(hs, &bd, 0); |
| @@ -110,7 +110,8 @@ static DECLARE_RWSEM(kg_sem); · 109 unmodified lines | ||
| 110 | 110 | * @param uid identifier for this receiver |
| 111 | 111 | * @param group group number |
| 112 | 112 | */ |
| 113 | −int libcfs_kkuc_group_add(struct file *filp, int uid, int group, __u32 data) | |
| 113 | +int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, | |
| 114 | + __u32 data) | |
| 114 | 115 | { |
| 115 | 116 | struct kkuc_reg *reg; |
| 116 | 117 | |
| @@ -21,7 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | * GPL HEADER END |
| 22 | 22 | */ |
| 23 | 23 | /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | − * Copyright (c) 2012, Intel Corporation. | |
| 24 | + * Copyright (c) 2012, 2015 Intel Corporation. | |
| 25 | 25 | */ |
| 26 | 26 | /* |
| 27 | 27 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -134,7 +134,6 @@ cfs_percpt_current(void *vars) · 133 unmodified lines | ||
| 134 | 134 | |
| 135 | 135 | return arr->va_ptrs[cpt]; |
| 136 | 136 | } |
| 137 | −EXPORT_SYMBOL(cfs_percpt_current); | |
| 138 | 137 | |
| 139 | 138 | void * |
| 140 | 139 | cfs_percpt_index(void *vars, int idx) |
| @@ -146,7 +145,6 @@ cfs_percpt_index(void *vars, int idx) · 5 unmodified lines | ||
| 146 | 145 | LASSERT(idx >= 0 && idx < arr->va_count); |
| 147 | 146 | return arr->va_ptrs[idx]; |
| 148 | 147 | } |
| 149 | −EXPORT_SYMBOL(cfs_percpt_index); | |
| 150 | 148 | |
| 151 | 149 | /* |
| 152 | 150 | * free variable array, see more detail in cfs_array_alloc |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015 Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -22,7 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | */ |
| 23 | 23 | /* |
| 24 | 24 | * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. |
| 25 | − * Copyright (c) 2012, Intel Corporation. | |
| 25 | + * | |
| 26 | + * Copyright (c) 2012, 2015 Intel Corporation. | |
| 26 | 27 | */ |
| 27 | 28 | /* |
| 28 | 29 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -78,23 +79,6 @@ struct cfs_cpt_data { · 49 unmodified lines | ||
| 78 | 79 | |
| 79 | 80 | static struct cfs_cpt_data cpt_data; |
| 80 | 81 | |
| 81 | −static void cfs_cpu_core_siblings(int cpu, cpumask_t *mask) | |
| 82 | −{ | |
| 83 | − /* return cpumask of cores in the same socket */ | |
| 84 | − cpumask_copy(mask, topology_core_cpumask(cpu)); | |
| 85 | −} | |
| 86 | − | |
| 87 | −/* return cpumask of HTs in the same core */ | |
| 88 | −static void cfs_cpu_ht_siblings(int cpu, cpumask_t *mask) | |
| 89 | −{ | |
| 90 | − cpumask_copy(mask, topology_sibling_cpumask(cpu)); | |
| 91 | −} | |
| 92 | − | |
| 93 | −static void cfs_node_to_cpumask(int node, cpumask_t *mask) | |
| 94 | −{ | |
| 95 | − cpumask_copy(mask, cpumask_of_node(node)); | |
| 96 | −} | |
| 97 | − | |
| 98 | 82 | void |
| 99 | 83 | cfs_cpt_table_free(struct cfs_cpt_table *cptab) |
| 100 | 84 | { |
| @@ -426,7 +410,7 @@ cfs_cpt_set_node(struct cfs_cpt_table *cptab, int cpt, int node) · 325 unmodified lines | ||
| 426 | 410 | mutex_lock(&cpt_data.cpt_mutex); |
| 427 | 411 | |
| 428 | 412 | mask = cpt_data.cpt_cpumask; |
| 429 | − cfs_node_to_cpumask(node, mask); | |
| 413 | + cpumask_copy(mask, cpumask_of_node(node)); | |
| 430 | 414 | |
| 431 | 415 | rc = cfs_cpt_set_cpumask(cptab, cpt, mask); |
| 432 | 416 | |
| @@ -450,7 +434,7 @@ cfs_cpt_unset_node(struct cfs_cpt_table *cptab, int cpt, int node) · 17 unmodified lines | ||
| 450 | 434 | mutex_lock(&cpt_data.cpt_mutex); |
| 451 | 435 | |
| 452 | 436 | mask = cpt_data.cpt_cpumask; |
| 453 | − cfs_node_to_cpumask(node, mask); | |
| 437 | + cpumask_copy(mask, cpumask_of_node(node)); | |
| 454 | 438 | |
| 455 | 439 | cfs_cpt_unset_cpumask(cptab, cpt, mask); |
| 456 | 440 | |
| @@ -643,7 +627,7 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt, · 186 unmodified lines | ||
| 643 | 627 | cpu = cpumask_first(node); |
| 644 | 628 | |
| 645 | 629 | /* get cpumask for cores in the same socket */ |
| 646 | − cfs_cpu_core_siblings(cpu, socket); | |
| 630 | + cpumask_copy(socket, topology_core_cpumask(cpu)); | |
| 647 | 631 | cpumask_and(socket, socket, node); |
| 648 | 632 | |
| 649 | 633 | LASSERT(!cpumask_empty(socket)); |
| @@ -652,7 +636,7 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt, · 2 unmodified lines | ||
| 652 | 636 | int i; |
| 653 | 637 | |
| 654 | 638 | /* get cpumask for hts in the same core */ |
| 655 | − cfs_cpu_ht_siblings(cpu, core); | |
| 639 | + cpumask_copy(core, topology_sibling_cpumask(cpu)); | |
| 656 | 640 | cpumask_and(core, core, node); |
| 657 | 641 | |
| 658 | 642 | LASSERT(!cpumask_empty(core)); |
| @@ -769,7 +753,7 @@ cfs_cpt_table_create(int ncpt) · 110 unmodified lines | ||
| 769 | 753 | } |
| 770 | 754 | |
| 771 | 755 | for_each_online_node(i) { |
| 772 | − cfs_node_to_cpumask(i, mask); | |
| 756 | + cpumask_copy(mask, cpumask_of_node(i)); | |
| 773 | 757 | |
| 774 | 758 | while (!cpumask_empty(mask)) { |
| 775 | 759 | struct cfs_cpu_partition *part; |
| @@ -968,7 +952,8 @@ cfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) · 192 unmodified lines | ||
| 968 | 952 | |
| 969 | 953 | mutex_lock(&cpt_data.cpt_mutex); |
| 970 | 954 | /* if all HTs in a core are offline, it may break affinity */ |
| 971 | − cfs_cpu_ht_siblings(cpu, cpt_data.cpt_cpumask); | |
| 955 | + cpumask_copy(cpt_data.cpt_cpumask, | |
| 956 | + topology_sibling_cpumask(cpu)); | |
| 972 | 957 | warn = cpumask_any_and(cpt_data.cpt_cpumask, |
| 973 | 958 | cpu_online_mask) >= nr_cpu_ids; |
| 974 | 959 | mutex_unlock(&cpt_data.cpt_mutex); |
| @@ -37,11 +37,6 @@ · 36 unmodified lines | ||
| 37 | 37 | #define CHKSUM_BLOCK_SIZE 1 |
| 38 | 38 | #define CHKSUM_DIGEST_SIZE 4 |
| 39 | 39 | |
| 40 | −static u32 __adler32(u32 cksum, unsigned char const *p, size_t len) | |
| 41 | −{ | |
| 42 | − return zlib_adler32(cksum, p, len); | |
| 43 | −} | |
| 44 | − | |
| 45 | 40 | static int adler32_cra_init(struct crypto_tfm *tfm) |
| 46 | 41 | { |
| 47 | 42 | u32 *key = crypto_tfm_ctx(tfm); |
| @@ -79,14 +74,14 @@ static int adler32_update(struct shash_desc *desc, const u8 *data, · 31 unmodified lines | ||
| 79 | 74 | { |
| 80 | 75 | u32 *cksump = shash_desc_ctx(desc); |
| 81 | 76 | |
| 82 | − *cksump = __adler32(*cksump, data, len); | |
| 77 | + *cksump = zlib_adler32(*cksump, data, len); | |
| 83 | 78 | return 0; |
| 84 | 79 | } |
| 85 | 80 | |
| 86 | 81 | static int __adler32_finup(u32 *cksump, const u8 *data, unsigned int len, |
| 87 | 82 | u8 *out) |
| 88 | 83 | { |
| 89 | − *(u32 *)out = __adler32(*cksump, data, len); | |
| 84 | + *(u32 *)out = zlib_adler32(*cksump, data, len); | |
| 90 | 85 | return 0; |
| 91 | 86 | } |
| 92 | 87 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -195,6 +195,5 @@ void libcfs_unregister_panic_notifier(void) · 194 unmodified lines | ||
| 195 | 195 | atomic_notifier_chain_unregister(&panic_notifier_list, &libcfs_panic_notifier); |
| 196 | 196 | } |
| 197 | 197 | |
| 198 | −EXPORT_SYMBOL(libcfs_run_upcall); | |
| 199 | 198 | EXPORT_SYMBOL(libcfs_run_lbug_upcall); |
| 200 | 199 | EXPORT_SYMBOL(lbug_with_loc); |
| @@ -1,48 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * GPL HEADER START | |
| 3 | − * | |
| 4 | − * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 5 | − * | |
| 6 | − * This program is free software; you can redistribute it and/or modify | |
| 7 | − * it under the terms of the GNU General Public License version 2 only, | |
| 8 | − * as published by the Free Software Foundation. | |
| 9 | − * | |
| 10 | − * This program is distributed in the hope that it will be useful, but | |
| 11 | − * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 13 | − * General Public License version 2 for more details (a copy is included | |
| 14 | − * in the LICENSE file that accompanied this code). | |
| 15 | − * | |
| 16 | − * You should have received a copy of the GNU General Public License | |
| 17 | − * version 2 along with this program; If not, see | |
| 18 | − * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf | |
| 19 | − * | |
| 20 | − * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
| 21 | − * CA 95054 USA or visit www.sun.com if you need additional information or | |
| 22 | − * have any questions. | |
| 23 | − * | |
| 24 | − * GPL HEADER END | |
| 25 | − */ | |
| 26 | −/* | |
| 27 | − * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. | |
| 28 | − * Use is subject to license terms. | |
| 29 | − */ | |
| 30 | −/* | |
| 31 | − * This file is part of Lustre, http://www.lustre.org/ | |
| 32 | − * Lustre is a trademark of Sun Microsystems, Inc. | |
| 33 | − */ | |
| 34 | − | |
| 35 | −#ifndef __LIBCFS_LINUX_TRACEFILE_H__ | |
| 36 | −#define __LIBCFS_LINUX_TRACEFILE_H__ | |
| 37 | − | |
| 38 | −/** | |
| 39 | − * three types of trace_data in linux | |
| 40 | − */ | |
| 41 | −typedef enum { | |
| 42 | − CFS_TCD_TYPE_PROC = 0, | |
| 43 | − CFS_TCD_TYPE_SOFTIRQ, | |
| 44 | − CFS_TCD_TYPE_IRQ, | |
| 45 | − CFS_TCD_TYPE_MAX | |
| 46 | −} cfs_trace_buf_type_t; | |
| 47 | − | |
| 48 | −#endif | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015 Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -62,7 +62,7 @@ · 28 unmodified lines | ||
| 62 | 62 | #include "../../include/linux/lnet/lnet.h" |
| 63 | 63 | #include "tracefile.h" |
| 64 | 64 | |
| 65 | −MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>"); | |
| 65 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 66 | 66 | MODULE_DESCRIPTION("Portals v3.1"); |
| 67 | 67 | MODULE_LICENSE("GPL"); |
| 68 | 68 | |
| @@ -375,7 +375,7 @@ static int __proc_dobitmasks(void *data, int write, · 306 unmodified lines | ||
| 375 | 375 | } else { |
| 376 | 376 | rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob); |
| 377 | 377 | if (rc < 0) { |
| 378 | − cfs_trace_free_string_buffer(tmpstr, tmpstrlen); | |
| 378 | + kfree(tmpstr); | |
| 379 | 379 | return rc; |
| 380 | 380 | } |
| 381 | 381 | |
| @@ -385,7 +385,7 @@ static int __proc_dobitmasks(void *data, int write, · 3 unmodified lines | ||
| 385 | 385 | *mask |= D_EMERG; |
| 386 | 386 | } |
| 387 | 387 | |
| 388 | − cfs_trace_free_string_buffer(tmpstr, tmpstrlen); | |
| 388 | + kfree(tmpstr); | |
| 389 | 389 | return rc; |
| 390 | 390 | } |
| 391 | 391 | |
| @@ -199,7 +199,6 @@ static void cfs_tcd_shrink(struct cfs_trace_cpu_data *tcd) · 198 unmodified lines | ||
| 199 | 199 | pgcount + 1, tcd->tcd_cur_pages); |
| 200 | 200 | |
| 201 | 201 | INIT_LIST_HEAD(&pc.pc_pages); |
| 202 | − spin_lock_init(&pc.pc_lock); | |
| 203 | 202 | |
| 204 | 203 | list_for_each_entry_safe(tage, tmp, &tcd->tcd_pages, linkage) { |
| 205 | 204 | if (pgcount-- == 0) |
| @@ -451,7 +450,7 @@ console: · 245 unmodified lines | ||
| 451 | 450 | cfs_print_to_console(&header, mask, |
| 452 | 451 | string_buf, needed, file, msgdata->msg_fn); |
| 453 | 452 | |
| 454 | − cfs_trace_put_console_buffer(string_buf); | |
| 453 | + put_cpu(); | |
| 455 | 454 | } |
| 456 | 455 | |
| 457 | 456 | if (cdls != NULL && cdls->cdls_count != 0) { |
| @@ -465,7 +464,7 @@ console: · 7 unmodified lines | ||
| 465 | 464 | cfs_print_to_console(&header, mask, |
| 466 | 465 | string_buf, needed, file, msgdata->msg_fn); |
| 467 | 466 | |
| 468 | − cfs_trace_put_console_buffer(string_buf); | |
| 467 | + put_cpu(); | |
| 469 | 468 | cdls->cdls_count = 0; |
| 470 | 469 | } |
| 471 | 470 | |
| @@ -522,7 +521,6 @@ static void collect_pages_on_all_cpus(struct page_collection *pc) · 50 unmodified lines | ||
| 522 | 521 | struct cfs_trace_cpu_data *tcd; |
| 523 | 522 | int i, cpu; |
| 524 | 523 | |
| 525 | − spin_lock(&pc->pc_lock); | |
| 526 | 524 | for_each_possible_cpu(cpu) { |
| 527 | 525 | cfs_tcd_for_each_type_lock(tcd, i, cpu) { |
| 528 | 526 | list_splice_init(&tcd->tcd_pages, &pc->pc_pages); |
| @@ -534,7 +532,6 @@ static void collect_pages_on_all_cpus(struct page_collection *pc) · 5 unmodified lines | ||
| 534 | 532 | } |
| 535 | 533 | } |
| 536 | 534 | } |
| 537 | − spin_unlock(&pc->pc_lock); | |
| 538 | 535 | } |
| 539 | 536 | |
| 540 | 537 | static void collect_pages(struct page_collection *pc) |
| @@ -555,7 +552,6 @@ static void put_pages_back_on_all_cpus(struct page_collection *pc) · 14 unmodified lines | ||
| 555 | 552 | struct cfs_trace_page *tmp; |
| 556 | 553 | int i, cpu; |
| 557 | 554 | |
| 558 | − spin_lock(&pc->pc_lock); | |
| 559 | 555 | for_each_possible_cpu(cpu) { |
| 560 | 556 | cfs_tcd_for_each_type_lock(tcd, i, cpu) { |
| 561 | 557 | cur_head = tcd->tcd_pages.next; |
| @@ -573,7 +569,6 @@ static void put_pages_back_on_all_cpus(struct page_collection *pc) · 11 unmodified lines | ||
| 573 | 569 | } |
| 574 | 570 | } |
| 575 | 571 | } |
| 576 | − spin_unlock(&pc->pc_lock); | |
| 577 | 572 | } |
| 578 | 573 | |
| 579 | 574 | static void put_pages_back(struct page_collection *pc) |
| @@ -592,7 +587,6 @@ static void put_pages_on_tcd_daemon_list(struct page_collection *pc, · 12 unmodified lines | ||
| 592 | 587 | struct cfs_trace_page *tage; |
| 593 | 588 | struct cfs_trace_page *tmp; |
| 594 | 589 | |
| 595 | − spin_lock(&pc->pc_lock); | |
| 596 | 590 | list_for_each_entry_safe(tage, tmp, &pc->pc_pages, linkage) { |
| 597 | 591 | |
| 598 | 592 | __LASSERT_TAGE_INVARIANT(tage); |
| @@ -616,7 +610,6 @@ static void put_pages_on_tcd_daemon_list(struct page_collection *pc, · 17 unmodified lines | ||
| 616 | 610 | tcd->tcd_cur_daemon_pages--; |
| 617 | 611 | } |
| 618 | 612 | } |
| 619 | − spin_unlock(&pc->pc_lock); | |
| 620 | 613 | } |
| 621 | 614 | |
| 622 | 615 | static void put_pages_on_daemon_list(struct page_collection *pc) |
| @@ -636,8 +629,6 @@ void cfs_trace_debug_print(void) · 13 unmodified lines | ||
| 636 | 629 | struct cfs_trace_page *tage; |
| 637 | 630 | struct cfs_trace_page *tmp; |
| 638 | 631 | |
| 639 | − spin_lock_init(&pc.pc_lock); | |
| 640 | − | |
| 641 | 632 | pc.pc_want_daemon_pages = 1; |
| 642 | 633 | collect_pages(&pc); |
| 643 | 634 | list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { |
| @@ -692,7 +683,6 @@ int cfs_tracefile_dump_all_pages(char *filename) · 48 unmodified lines | ||
| 692 | 683 | goto out; |
| 693 | 684 | } |
| 694 | 685 | |
| 695 | − spin_lock_init(&pc.pc_lock); | |
| 696 | 686 | pc.pc_want_daemon_pages = 1; |
| 697 | 687 | collect_pages(&pc); |
| 698 | 688 | if (list_empty(&pc.pc_pages)) { |
| @@ -739,8 +729,6 @@ void cfs_trace_flush_pages(void) · 40 unmodified lines | ||
| 739 | 729 | struct cfs_trace_page *tage; |
| 740 | 730 | struct cfs_trace_page *tmp; |
| 741 | 731 | |
| 742 | − spin_lock_init(&pc.pc_lock); | |
| 743 | − | |
| 744 | 732 | pc.pc_want_daemon_pages = 1; |
| 745 | 733 | collect_pages(&pc); |
| 746 | 734 | list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { |
| @@ -817,11 +805,6 @@ int cfs_trace_allocate_string_buffer(char **str, int nob) · 70 unmodified lines | ||
| 817 | 805 | return 0; |
| 818 | 806 | } |
| 819 | 807 | |
| 820 | −void cfs_trace_free_string_buffer(char *str, int nob) | |
| 821 | −{ | |
| 822 | − kfree(str); | |
| 823 | −} | |
| 824 | − | |
| 825 | 808 | int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob) |
| 826 | 809 | { |
| 827 | 810 | char *str; |
| @@ -842,7 +825,7 @@ int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob) · 14 unmodified lines | ||
| 842 | 825 | } |
| 843 | 826 | rc = cfs_tracefile_dump_all_pages(str); |
| 844 | 827 | out: |
| 845 | − cfs_trace_free_string_buffer(str, usr_str_nob + 1); | |
| 828 | + kfree(str); | |
| 846 | 829 | return rc; |
| 847 | 830 | } |
| 848 | 831 | |
| @@ -898,7 +881,7 @@ int cfs_trace_daemon_command_usrstr(void __user *usr_str, int usr_str_nob) · 49 unmodified lines | ||
| 898 | 881 | if (rc == 0) |
| 899 | 882 | rc = cfs_trace_daemon_command(str); |
| 900 | 883 | |
| 901 | − cfs_trace_free_string_buffer(str, usr_str_nob + 1); | |
| 884 | + kfree(str); | |
| 902 | 885 | return rc; |
| 903 | 886 | } |
| 904 | 887 | |
| @@ -970,7 +953,6 @@ static int tracefiled(void *arg) · 65 unmodified lines | ||
| 970 | 953 | /* we're started late enough that we pick up init's fs context */ |
| 971 | 954 | /* this is so broken in uml? what on earth is going on? */ |
| 972 | 955 | |
| 973 | − spin_lock_init(&pc.pc_lock); | |
| 974 | 956 | complete(&tctl->tctl_start); |
| 975 | 957 | |
| 976 | 958 | while (1) { |
| @@ -1170,7 +1152,6 @@ static void cfs_trace_cleanup(void) · 193 unmodified lines | ||
| 1170 | 1152 | struct page_collection pc; |
| 1171 | 1153 | |
| 1172 | 1154 | INIT_LIST_HEAD(&pc.pc_pages); |
| 1173 | − spin_lock_init(&pc.pc_lock); | |
| 1174 | 1155 | |
| 1175 | 1156 | trace_cleanup_on_all_cpus(); |
| 1176 | 1157 | |
| @@ -39,7 +39,12 @@ · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | #include "../../include/linux/libcfs/libcfs.h" |
| 41 | 41 | |
| 42 | −#include "linux/linux-tracefile.h" | |
| 42 | +typedef enum { | |
| 43 | + CFS_TCD_TYPE_PROC = 0, | |
| 44 | + CFS_TCD_TYPE_SOFTIRQ, | |
| 45 | + CFS_TCD_TYPE_IRQ, | |
| 46 | + CFS_TCD_TYPE_MAX | |
| 47 | +} cfs_trace_buf_type_t; | |
| 43 | 48 | |
| 44 | 49 | /* trace file lock routines */ |
| 45 | 50 | |
| @@ -70,7 +75,6 @@ int cfs_trace_copyin_string(char *knl_buffer, int knl_buffer_nob, · 24 unmodified lines | ||
| 70 | 75 | int cfs_trace_copyout_string(char __user *usr_buffer, int usr_buffer_nob, |
| 71 | 76 | const char *knl_str, char *append); |
| 72 | 77 | int cfs_trace_allocate_string_buffer(char **str, int nob); |
| 73 | −void cfs_trace_free_string_buffer(char *str, int nob); | |
| 74 | 78 | int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob); |
| 75 | 79 | int cfs_trace_daemon_command(char *str); |
| 76 | 80 | int cfs_trace_daemon_command_usrstr(void __user *usr_str, int usr_str_nob); |
| @@ -195,14 +199,6 @@ extern union cfs_trace_data_union (*cfs_trace_data[TCD_MAX_TYPES])[NR_CPUS]; · 118 unmodified lines | ||
| 195 | 199 | * be moved there */ |
| 196 | 200 | struct page_collection { |
| 197 | 201 | struct list_head pc_pages; |
| 198 | − /* | |
| 199 | − * spin-lock protecting ->pc_pages. It is taken by smp_call_function() | |
| 200 | − * call-back functions. XXX nikita: Which is horrible: all processors | |
| 201 | − * receive NMI at the same time only to be serialized by this | |
| 202 | − * lock. Probably ->pc_pages should be replaced with an array of | |
| 203 | − * NR_CPUS elements accessed locklessly. | |
| 204 | − */ | |
| 205 | − spinlock_t pc_lock; | |
| 206 | 202 | /* |
| 207 | 203 | * if this flag is set, collect_pages() will spill both |
| 208 | 204 | * ->tcd_daemon_pages and ->tcd_pages to the ->pc_pages. Otherwise, |
| @@ -260,13 +256,6 @@ void cfs_print_to_console(struct ptldebug_header *hdr, int mask, · 51 unmodified lines | ||
| 260 | 256 | int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking); |
| 261 | 257 | void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking); |
| 262 | 258 | |
| 263 | −/** | |
| 264 | − * trace_buf_type_t, trace_buf_idx_get() and trace_console_buffers[][] | |
| 265 | − * are not public libcfs API; they should be defined in | |
| 266 | − * platform-specific tracefile include files | |
| 267 | − * (see, for example, linux-tracefile.h). | |
| 268 | − */ | |
| 269 | − | |
| 270 | 259 | extern char *cfs_trace_console_buffers[NR_CPUS][CFS_TCD_TYPE_MAX]; |
| 271 | 260 | cfs_trace_buf_type_t cfs_trace_buf_idx_get(void); |
| 272 | 261 | |
| @@ -279,12 +268,6 @@ cfs_trace_get_console_buffer(void) · 6 unmodified lines | ||
| 279 | 268 | return cfs_trace_console_buffers[i][j]; |
| 280 | 269 | } |
| 281 | 270 | |
| 282 | −static inline void | |
| 283 | −cfs_trace_put_console_buffer(char *buffer) | |
| 284 | −{ | |
| 285 | − put_cpu(); | |
| 286 | −} | |
| 287 | − | |
| 288 | 271 | static inline struct cfs_trace_cpu_data * |
| 289 | 272 | cfs_trace_get_tcd(void) |
| 290 | 273 | { |
| @@ -86,32 +86,20 @@ static struct cfs_workitem_data { · 85 unmodified lines | ||
| 86 | 86 | int wi_stopping; |
| 87 | 87 | } cfs_wi_data; |
| 88 | 88 | |
| 89 | −static inline void | |
| 90 | −cfs_wi_sched_lock(struct cfs_wi_sched *sched) | |
| 91 | −{ | |
| 92 | − spin_lock(&sched->ws_lock); | |
| 93 | −} | |
| 94 | − | |
| 95 | −static inline void | |
| 96 | −cfs_wi_sched_unlock(struct cfs_wi_sched *sched) | |
| 97 | −{ | |
| 98 | − spin_unlock(&sched->ws_lock); | |
| 99 | −} | |
| 100 | − | |
| 101 | 89 | static inline int |
| 102 | 90 | cfs_wi_sched_cansleep(struct cfs_wi_sched *sched) |
| 103 | 91 | { |
| 104 | − cfs_wi_sched_lock(sched); | |
| 92 | + spin_lock(&sched->ws_lock); | |
| 105 | 93 | if (sched->ws_stopping) { |
| 106 | − cfs_wi_sched_unlock(sched); | |
| 94 | + spin_unlock(&sched->ws_lock); | |
| 107 | 95 | return 0; |
| 108 | 96 | } |
| 109 | 97 | |
| 110 | 98 | if (!list_empty(&sched->ws_runq)) { |
| 111 | − cfs_wi_sched_unlock(sched); | |
| 99 | + spin_unlock(&sched->ws_lock); | |
| 112 | 100 | return 0; |
| 113 | 101 | } |
| 114 | − cfs_wi_sched_unlock(sched); | |
| 102 | + spin_unlock(&sched->ws_lock); | |
| 115 | 103 | return 1; |
| 116 | 104 | } |
| 117 | 105 | |
| @@ -125,7 +113,7 @@ cfs_wi_exit(struct cfs_wi_sched *sched, cfs_workitem_t *wi) · 7 unmodified lines | ||
| 125 | 113 | LASSERT(!in_interrupt()); /* because we use plain spinlock */ |
| 126 | 114 | LASSERT(!sched->ws_stopping); |
| 127 | 115 | |
| 128 | − cfs_wi_sched_lock(sched); | |
| 116 | + spin_lock(&sched->ws_lock); | |
| 129 | 117 | |
| 130 | 118 | LASSERT(wi->wi_running); |
| 131 | 119 | if (wi->wi_scheduled) { /* cancel pending schedules */ |
| @@ -139,7 +127,7 @@ cfs_wi_exit(struct cfs_wi_sched *sched, cfs_workitem_t *wi) · 7 unmodified lines | ||
| 139 | 127 | LASSERT(list_empty(&wi->wi_list)); |
| 140 | 128 | |
| 141 | 129 | wi->wi_scheduled = 1; /* LBUG future schedule attempts */ |
| 142 | − cfs_wi_sched_unlock(sched); | |
| 130 | + spin_unlock(&sched->ws_lock); | |
| 143 | 131 | |
| 144 | 132 | return; |
| 145 | 133 | } |
| @@ -161,7 +149,7 @@ cfs_wi_deschedule(struct cfs_wi_sched *sched, cfs_workitem_t *wi) · 15 unmodified lines | ||
| 161 | 149 | * means the workitem will not be scheduled and will not have |
| 162 | 150 | * any race with wi_action. |
| 163 | 151 | */ |
| 164 | − cfs_wi_sched_lock(sched); | |
| 152 | + spin_lock(&sched->ws_lock); | |
| 165 | 153 | |
| 166 | 154 | rc = !(wi->wi_running); |
| 167 | 155 | |
| @@ -177,7 +165,7 @@ cfs_wi_deschedule(struct cfs_wi_sched *sched, cfs_workitem_t *wi) · 9 unmodified lines | ||
| 177 | 165 | |
| 178 | 166 | LASSERT (list_empty(&wi->wi_list)); |
| 179 | 167 | |
| 180 | − cfs_wi_sched_unlock(sched); | |
| 168 | + spin_unlock(&sched->ws_lock); | |
| 181 | 169 | return rc; |
| 182 | 170 | } |
| 183 | 171 | EXPORT_SYMBOL(cfs_wi_deschedule); |
| @@ -195,7 +183,7 @@ cfs_wi_schedule(struct cfs_wi_sched *sched, cfs_workitem_t *wi) · 11 unmodified lines | ||
| 195 | 183 | LASSERT(!in_interrupt()); /* because we use plain spinlock */ |
| 196 | 184 | LASSERT(!sched->ws_stopping); |
| 197 | 185 | |
| 198 | − cfs_wi_sched_lock(sched); | |
| 186 | + spin_lock(&sched->ws_lock); | |
| 199 | 187 | |
| 200 | 188 | if (!wi->wi_scheduled) { |
| 201 | 189 | LASSERT (list_empty(&wi->wi_list)); |
| @@ -211,7 +199,7 @@ cfs_wi_schedule(struct cfs_wi_sched *sched, cfs_workitem_t *wi) · 9 unmodified lines | ||
| 211 | 199 | } |
| 212 | 200 | |
| 213 | 201 | LASSERT (!list_empty(&wi->wi_list)); |
| 214 | − cfs_wi_sched_unlock(sched); | |
| 202 | + spin_unlock(&sched->ws_lock); | |
| 215 | 203 | return; |
| 216 | 204 | } |
| 217 | 205 | EXPORT_SYMBOL(cfs_wi_schedule); |
| @@ -225,7 +213,9 @@ cfs_wi_scheduler (void *arg) · 7 unmodified lines | ||
| 225 | 213 | |
| 226 | 214 | /* CPT affinity scheduler? */ |
| 227 | 215 | if (sched->ws_cptab != NULL) |
| 228 | − cfs_cpt_bind(sched->ws_cptab, sched->ws_cpt); | |
| 216 | + if (cfs_cpt_bind(sched->ws_cptab, sched->ws_cpt) != 0) | |
| 217 | + CWARN("Failed to bind %s on CPT %d\n", | |
| 218 | + sched->ws_name, sched->ws_cpt); | |
| 229 | 219 | |
| 230 | 220 | spin_lock(&cfs_wi_data.wi_glock); |
| 231 | 221 | |
| @@ -235,7 +225,7 @@ cfs_wi_scheduler (void *arg) · 3 unmodified lines | ||
| 235 | 225 | |
| 236 | 226 | spin_unlock(&cfs_wi_data.wi_glock); |
| 237 | 227 | |
| 238 | − cfs_wi_sched_lock(sched); | |
| 228 | + spin_lock(&sched->ws_lock); | |
| 239 | 229 | |
| 240 | 230 | while (!sched->ws_stopping) { |
| 241 | 231 | int nloops = 0; |
| @@ -256,12 +246,12 @@ cfs_wi_scheduler (void *arg) · 14 unmodified lines | ||
| 256 | 246 | wi->wi_running = 1; |
| 257 | 247 | wi->wi_scheduled = 0; |
| 258 | 248 | |
| 259 | − cfs_wi_sched_unlock(sched); | |
| 249 | + spin_unlock(&sched->ws_lock); | |
| 260 | 250 | nloops++; |
| 261 | 251 | |
| 262 | 252 | rc = (*wi->wi_action) (wi); |
| 263 | 253 | |
| 264 | − cfs_wi_sched_lock(sched); | |
| 254 | + spin_lock(&sched->ws_lock); | |
| 265 | 255 | if (rc != 0) /* WI should be dead, even be freed! */ |
| 266 | 256 | continue; |
| 267 | 257 | |
| @@ -276,21 +266,21 @@ cfs_wi_scheduler (void *arg) · 8 unmodified lines | ||
| 276 | 266 | } |
| 277 | 267 | |
| 278 | 268 | if (!list_empty(&sched->ws_runq)) { |
| 279 | − cfs_wi_sched_unlock(sched); | |
| 269 | + spin_unlock(&sched->ws_lock); | |
| 280 | 270 | /* don't sleep because some workitems still |
| 281 | 271 | * expect me to come back soon */ |
| 282 | 272 | cond_resched(); |
| 283 | − cfs_wi_sched_lock(sched); | |
| 273 | + spin_lock(&sched->ws_lock); | |
| 284 | 274 | continue; |
| 285 | 275 | } |
| 286 | 276 | |
| 287 | − cfs_wi_sched_unlock(sched); | |
| 277 | + spin_unlock(&sched->ws_lock); | |
| 288 | 278 | rc = wait_event_interruptible_exclusive(sched->ws_waitq, |
| 289 | 279 | !cfs_wi_sched_cansleep(sched)); |
| 290 | − cfs_wi_sched_lock(sched); | |
| 280 | + spin_lock(&sched->ws_lock); | |
| 291 | 281 | } |
| 292 | 282 | |
| 293 | − cfs_wi_sched_unlock(sched); | |
| 283 | + spin_unlock(&sched->ws_lock); | |
| 294 | 284 | |
| 295 | 285 | spin_lock(&cfs_wi_data.wi_glock); |
| 296 | 286 | sched->ws_nthreads--; |
| @@ -325,7 +315,7 @@ cfs_wi_sched_destroy(struct cfs_wi_sched *sched) · 28 unmodified lines | ||
| 325 | 315 | |
| 326 | 316 | spin_lock(&cfs_wi_data.wi_glock); |
| 327 | 317 | while (sched->ws_nthreads > 0) { |
| 328 | − CDEBUG(IS_PO2(++i) ? D_WARNING : D_NET, | |
| 318 | + CDEBUG(is_power_of_2(++i) ? D_WARNING : D_NET, | |
| 329 | 319 | "waiting for %d threads of WI sched[%s] to terminate\n", |
| 330 | 320 | sched->ws_nthreads, sched->ws_name); |
| 331 | 321 | |
| @@ -360,8 +350,8 @@ cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab, · 28 unmodified lines | ||
| 360 | 350 | if (sched == NULL) |
| 361 | 351 | return -ENOMEM; |
| 362 | 352 | |
| 363 | − strncpy(sched->ws_name, name, CFS_WS_NAME_LEN); | |
| 364 | − sched->ws_name[CFS_WS_NAME_LEN - 1] = '\0'; | |
| 353 | + strlcpy(sched->ws_name, name, CFS_WS_NAME_LEN); | |
| 354 | + | |
| 365 | 355 | sched->ws_cptab = cptab; |
| 366 | 356 | sched->ws_cpt = cpt; |
| 367 | 357 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -239,12 +239,6 @@ static int ll_dir_filler(void *_hash, struct page *page0) · 205 unmodified lines | ||
| 239 | 239 | return rc; |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | −static void ll_check_page(struct inode *dir, struct page *page) | |
| 243 | −{ | |
| 244 | − /* XXX: check page format later */ | |
| 245 | − SetPageChecked(page); | |
| 246 | −} | |
| 247 | − | |
| 248 | 242 | void ll_release_page(struct page *page, int remove) |
| 249 | 243 | { |
| 250 | 244 | kunmap(page); |
| @@ -432,7 +426,8 @@ struct page *ll_get_dir_page(struct inode *dir, __u64 hash, · 181 unmodified lines | ||
| 432 | 426 | goto fail; |
| 433 | 427 | } |
| 434 | 428 | if (!PageChecked(page)) |
| 435 | − ll_check_page(dir, page); | |
| 429 | + /* XXX: check page format later */ | |
| 430 | + SetPageChecked(page); | |
| 436 | 431 | if (PageError(page)) { |
| 437 | 432 | CERROR("page error: "DFID" at %llu: rc %d\n", |
| 438 | 433 | PFID(ll_inode2fid(dir)), hash, -5); |
| @@ -641,7 +636,7 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string) · 202 unmodified lines | ||
| 641 | 636 | if (!msp) |
| 642 | 637 | return -ENOMEM; |
| 643 | 638 | |
| 644 | − strncpy(msp->mgs_param, string, MGS_PARAM_MAXLEN); | |
| 639 | + strlcpy(msp->mgs_param, string, sizeof(msp->mgs_param)); | |
| 645 | 640 | rc = obd_set_info_async(NULL, mgc, sizeof(KEY_SET_INFO), KEY_SET_INFO, |
| 646 | 641 | sizeof(struct mgs_send_param), msp, NULL); |
| 647 | 642 | if (rc) |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -1285,16 +1285,6 @@ static inline struct ll_file_data *cl_iattr2fd(struct inode *inode, · 1251 unmodified lines | ||
| 1285 | 1285 | return LUSTRE_FPRIVATE(attr->ia_file); |
| 1286 | 1286 | } |
| 1287 | 1287 | |
| 1288 | −static inline void cl_isize_lock(struct inode *inode) | |
| 1289 | −{ | |
| 1290 | − ll_inode_size_lock(inode); | |
| 1291 | −} | |
| 1292 | − | |
| 1293 | −static inline void cl_isize_unlock(struct inode *inode) | |
| 1294 | −{ | |
| 1295 | − ll_inode_size_unlock(inode); | |
| 1296 | −} | |
| 1297 | − | |
| 1298 | 1288 | static inline void cl_isize_write_nolock(struct inode *inode, loff_t kms) |
| 1299 | 1289 | { |
| 1300 | 1290 | LASSERT(mutex_is_locked(&ll_i2info(inode)->lli_size_mutex)); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -877,6 +877,6 @@ module_exit(lloop_exit); · 876 unmodified lines | ||
| 877 | 877 | |
| 878 | 878 | module_param(max_loop, int, 0444); |
| 879 | 879 | MODULE_PARM_DESC(max_loop, "maximum of lloop_device"); |
| 880 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 880 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 881 | 881 | MODULE_DESCRIPTION("Lustre virtual block device"); |
| 882 | 882 | MODULE_LICENSE("GPL"); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -554,7 +554,6 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, · 520 unmodified lines | ||
| 554 | 554 | retval = NULL; |
| 555 | 555 | else |
| 556 | 556 | retval = dentry; |
| 557 | − goto out; | |
| 558 | 557 | out: |
| 559 | 558 | if (req) |
| 560 | 559 | ptlrpc_req_finished(req); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -880,14 +880,6 @@ static void ras_update_stride_detector(struct ll_readahead_state *ras, · 846 unmodified lines | ||
| 880 | 880 | return; |
| 881 | 881 | } |
| 882 | 882 | |
| 883 | −static unsigned long | |
| 884 | −stride_page_count(struct ll_readahead_state *ras, unsigned long len) | |
| 885 | −{ | |
| 886 | − return stride_pg_count(ras->ras_stride_offset, ras->ras_stride_length, | |
| 887 | − ras->ras_stride_pages, ras->ras_stride_offset, | |
| 888 | − len); | |
| 889 | −} | |
| 890 | − | |
| 891 | 883 | /* Stride Read-ahead window will be increased inc_len according to |
| 892 | 884 | * stride I/O pattern */ |
| 893 | 885 | static void ras_stride_increase_window(struct ll_readahead_state *ras, |
| @@ -921,7 +913,9 @@ static void ras_stride_increase_window(struct ll_readahead_state *ras, · 27 unmodified lines | ||
| 921 | 913 | |
| 922 | 914 | window_len += step * ras->ras_stride_length + left; |
| 923 | 915 | |
| 924 | − if (stride_page_count(ras, window_len) <= ra->ra_max_pages_per_file) | |
| 916 | + if (stride_pg_count(ras->ras_stride_offset, ras->ras_stride_length, | |
| 917 | + ras->ras_stride_pages, ras->ras_stride_offset, | |
| 918 | + window_len) <= ra->ra_max_pages_per_file) | |
| 925 | 919 | ras->ras_window_len = window_len; |
| 926 | 920 | |
| 927 | 921 | RAS_CDEBUG(ras); |
| @@ -298,7 +298,10 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, · 297 unmodified lines | ||
| 298 | 298 | } |
| 299 | 299 | |
| 300 | 300 | if (likely(do_io)) { |
| 301 | − cl_2queue_add(queue, clp); | |
| 301 | + /* | |
| 302 | + * Add a page to the incoming page list of 2-queue. | |
| 303 | + */ | |
| 304 | + cl_page_list_add(&queue->c2_qin, clp); | |
| 302 | 305 | |
| 303 | 306 | /* |
| 304 | 307 | * Set page clip to tell transfer formation engine |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -87,11 +87,6 @@ struct ll_sa_entry { · 53 unmodified lines | ||
| 87 | 87 | static unsigned int sai_generation; |
| 88 | 88 | static DEFINE_SPINLOCK(sai_generation_lock); |
| 89 | 89 | |
| 90 | −static inline int ll_sa_entry_unhashed(struct ll_sa_entry *entry) | |
| 91 | −{ | |
| 92 | − return list_empty(&entry->se_hash); | |
| 93 | −} | |
| 94 | − | |
| 95 | 90 | /* |
| 96 | 91 | * The entry only can be released by the caller, it is necessary to hold lock. |
| 97 | 92 | */ |
| @@ -138,20 +133,6 @@ static inline int agl_should_run(struct ll_statahead_info *sai, · 40 unmodified lines | ||
| 138 | 133 | return (inode != NULL && S_ISREG(inode->i_mode) && sai->sai_agl_valid); |
| 139 | 134 | } |
| 140 | 135 | |
| 141 | −static inline struct ll_sa_entry * | |
| 142 | −sa_first_received_entry(struct ll_statahead_info *sai) | |
| 143 | −{ | |
| 144 | − return list_entry(sai->sai_entries_received.next, | |
| 145 | − struct ll_sa_entry, se_list); | |
| 146 | −} | |
| 147 | − | |
| 148 | −static inline struct ll_inode_info * | |
| 149 | −agl_first_entry(struct ll_statahead_info *sai) | |
| 150 | −{ | |
| 151 | − return list_entry(sai->sai_entries_agl.next, | |
| 152 | − struct ll_inode_info, lli_agl_list); | |
| 153 | −} | |
| 154 | − | |
| 155 | 136 | static inline int sa_sent_full(struct ll_statahead_info *sai) |
| 156 | 137 | { |
| 157 | 138 | return atomic_read(&sai->sai_cache_count) >= sai->sai_max; |
| @@ -331,7 +312,7 @@ static void ll_sa_entry_put(struct ll_statahead_info *sai, · 173 unmodified lines | ||
| 331 | 312 | |
| 332 | 313 | LASSERT(list_empty(&entry->se_link)); |
| 333 | 314 | LASSERT(list_empty(&entry->se_list)); |
| 334 | − LASSERT(ll_sa_entry_unhashed(entry)); | |
| 315 | + LASSERT(list_empty(&entry->se_hash)); | |
| 335 | 316 | |
| 336 | 317 | ll_sa_entry_cleanup(sai, entry); |
| 337 | 318 | iput(entry->se_inode); |
| @@ -346,7 +327,7 @@ do_sa_entry_fini(struct ll_statahead_info *sai, struct ll_sa_entry *entry) · 8 unmodified lines | ||
| 346 | 327 | { |
| 347 | 328 | struct ll_inode_info *lli = ll_i2info(sai->sai_inode); |
| 348 | 329 | |
| 349 | − LASSERT(!ll_sa_entry_unhashed(entry)); | |
| 330 | + LASSERT(!list_empty(&entry->se_hash)); | |
| 350 | 331 | LASSERT(!list_empty(&entry->se_link)); |
| 351 | 332 | |
| 352 | 333 | ll_sa_entry_unhash(sai, entry); |
| @@ -447,7 +428,7 @@ static void ll_agl_add(struct ll_statahead_info *sai, · 94 unmodified lines | ||
| 447 | 428 | |
| 448 | 429 | igrab(inode); |
| 449 | 430 | spin_lock(&parent->lli_agl_lock); |
| 450 | − if (agl_list_empty(sai)) | |
| 431 | + if (list_empty(&sai->sai_entries_agl)) | |
| 451 | 432 | added = 1; |
| 452 | 433 | list_add_tail(&child->lli_agl_list, &sai->sai_entries_agl); |
| 453 | 434 | spin_unlock(&parent->lli_agl_lock); |
| @@ -537,11 +518,11 @@ static void ll_sai_put(struct ll_statahead_info *sai) · 83 unmodified lines | ||
| 537 | 518 | do_sa_entry_fini(sai, entry); |
| 538 | 519 | |
| 539 | 520 | LASSERT(list_empty(&sai->sai_entries)); |
| 540 | − LASSERT(sa_received_empty(sai)); | |
| 521 | + LASSERT(list_empty(&sai->sai_entries_received)); | |
| 541 | 522 | LASSERT(list_empty(&sai->sai_entries_stated)); |
| 542 | 523 | |
| 543 | 524 | LASSERT(atomic_read(&sai->sai_cache_count) == 0); |
| 544 | − LASSERT(agl_list_empty(sai)); | |
| 525 | + LASSERT(list_empty(&sai->sai_entries_agl)); | |
| 545 | 526 | |
| 546 | 527 | iput(inode); |
| 547 | 528 | kfree(sai); |
| @@ -621,11 +602,12 @@ static void ll_post_statahead(struct ll_statahead_info *sai) · 73 unmodified lines | ||
| 621 | 602 | int rc = 0; |
| 622 | 603 | |
| 623 | 604 | spin_lock(&lli->lli_sa_lock); |
| 624 | − if (unlikely(sa_received_empty(sai))) { | |
| 605 | + if (unlikely(list_empty(&sai->sai_entries_received))) { | |
| 625 | 606 | spin_unlock(&lli->lli_sa_lock); |
| 626 | 607 | return; |
| 627 | 608 | } |
| 628 | − entry = sa_first_received_entry(sai); | |
| 609 | + entry = list_entry(sai->sai_entries_received.next, | |
| 610 | + struct ll_sa_entry, se_list); | |
| 629 | 611 | atomic_inc(&entry->se_refcount); |
| 630 | 612 | list_del_init(&entry->se_list); |
| 631 | 613 | spin_unlock(&lli->lli_sa_lock); |
| @@ -756,7 +738,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, · 124 unmodified lines | ||
| 756 | 738 | * for readpage and other tries to enqueue lock on child |
| 757 | 739 | * with parent's lock held, for example: unlink. */ |
| 758 | 740 | entry->se_handle = handle; |
| 759 | − wakeup = sa_received_empty(sai); | |
| 741 | + wakeup = list_empty(&sai->sai_entries_received); | |
| 760 | 742 | list_add_tail(&entry->se_list, |
| 761 | 743 | &sai->sai_entries_received); |
| 762 | 744 | } |
| @@ -973,7 +955,7 @@ static int ll_agl_thread(void *arg) · 210 unmodified lines | ||
| 973 | 955 | |
| 974 | 956 | while (1) { |
| 975 | 957 | l_wait_event(thread->t_ctl_waitq, |
| 976 | − !agl_list_empty(sai) || | |
| 958 | + !list_empty(&sai->sai_entries_agl) || | |
| 977 | 959 | !thread_is_running(thread), |
| 978 | 960 | &lwi); |
| 979 | 961 | |
| @@ -983,8 +965,9 @@ static int ll_agl_thread(void *arg) · 3 unmodified lines | ||
| 983 | 965 | spin_lock(&plli->lli_agl_lock); |
| 984 | 966 | /* The statahead thread maybe help to process AGL entries, |
| 985 | 967 | * so check whether list empty again. */ |
| 986 | − if (!agl_list_empty(sai)) { | |
| 987 | − clli = agl_first_entry(sai); | |
| 968 | + if (!list_empty(&sai->sai_entries_agl)) { | |
| 969 | + clli = list_entry(sai->sai_entries_agl.next, | |
| 970 | + struct ll_inode_info, lli_agl_list); | |
| 988 | 971 | list_del_init(&clli->lli_agl_list); |
| 989 | 972 | spin_unlock(&plli->lli_agl_lock); |
| 990 | 973 | ll_agl_trigger(&clli->lli_vfs_inode, sai); |
| @@ -995,8 +978,9 @@ static int ll_agl_thread(void *arg) · 4 unmodified lines | ||
| 995 | 978 | |
| 996 | 979 | spin_lock(&plli->lli_agl_lock); |
| 997 | 980 | sai->sai_agl_valid = 0; |
| 998 | − while (!agl_list_empty(sai)) { | |
| 999 | − clli = agl_first_entry(sai); | |
| 981 | + while (!list_empty(&sai->sai_entries_agl)) { | |
| 982 | + clli = list_entry(sai->sai_entries_agl.next, | |
| 983 | + struct ll_inode_info, lli_agl_list); | |
| 1000 | 984 | list_del_init(&clli->lli_agl_list); |
| 1001 | 985 | spin_unlock(&plli->lli_agl_lock); |
| 1002 | 986 | clli->lli_agl_index = 0; |
| @@ -1136,13 +1120,13 @@ static int ll_statahead_thread(void *arg) · 133 unmodified lines | ||
| 1136 | 1120 | keep_it: |
| 1137 | 1121 | l_wait_event(thread->t_ctl_waitq, |
| 1138 | 1122 | !sa_sent_full(sai) || |
| 1139 | − !sa_received_empty(sai) || | |
| 1140 | − !agl_list_empty(sai) || | |
| 1123 | + !list_empty(&sai->sai_entries_received) || | |
| 1124 | + !list_empty(&sai->sai_entries_agl) || | |
| 1141 | 1125 | !thread_is_running(thread), |
| 1142 | 1126 | &lwi); |
| 1143 | 1127 | |
| 1144 | 1128 | interpret_it: |
| 1145 | − while (!sa_received_empty(sai)) | |
| 1129 | + while (!list_empty(&sai->sai_entries_received)) | |
| 1146 | 1130 | ll_post_statahead(sai); |
| 1147 | 1131 | |
| 1148 | 1132 | if (unlikely(!thread_is_running(thread))) { |
| @@ -1156,14 +1140,15 @@ interpret_it: · 7 unmodified lines | ||
| 1156 | 1140 | * to process the AGL entries. */ |
| 1157 | 1141 | if (sa_sent_full(sai)) { |
| 1158 | 1142 | spin_lock(&plli->lli_agl_lock); |
| 1159 | − while (!agl_list_empty(sai)) { | |
| 1160 | − clli = agl_first_entry(sai); | |
| 1143 | + while (!list_empty(&sai->sai_entries_agl)) { | |
| 1144 | + clli = list_entry(sai->sai_entries_agl.next, | |
| 1145 | + struct ll_inode_info, lli_agl_list); | |
| 1161 | 1146 | list_del_init(&clli->lli_agl_list); |
| 1162 | 1147 | spin_unlock(&plli->lli_agl_lock); |
| 1163 | 1148 | ll_agl_trigger(&clli->lli_vfs_inode, |
| 1164 | 1149 | sai); |
| 1165 | 1150 | |
| 1166 | − if (!sa_received_empty(sai)) | |
| 1151 | + if (!list_empty(&sai->sai_entries_received)) | |
| 1167 | 1152 | goto interpret_it; |
| 1168 | 1153 | |
| 1169 | 1154 | if (unlikely( |
| @@ -1194,12 +1179,12 @@ do_it: · 24 unmodified lines | ||
| 1194 | 1179 | ll_release_page(page, 0); |
| 1195 | 1180 | while (1) { |
| 1196 | 1181 | l_wait_event(thread->t_ctl_waitq, |
| 1197 | − !sa_received_empty(sai) || | |
| 1182 | + !list_empty(&sai->sai_entries_received) || | |
| 1198 | 1183 | sai->sai_sent == sai->sai_replied || |
| 1199 | 1184 | !thread_is_running(thread), |
| 1200 | 1185 | &lwi); |
| 1201 | 1186 | |
| 1202 | − while (!sa_received_empty(sai)) | |
| 1187 | + while (!list_empty(&sai->sai_entries_received)) | |
| 1203 | 1188 | ll_post_statahead(sai); |
| 1204 | 1189 | |
| 1205 | 1190 | if (unlikely(!thread_is_running(thread))) { |
| @@ -1208,14 +1193,15 @@ do_it: · 2 unmodified lines | ||
| 1208 | 1193 | } |
| 1209 | 1194 | |
| 1210 | 1195 | if (sai->sai_sent == sai->sai_replied && |
| 1211 | − sa_received_empty(sai)) | |
| 1196 | + list_empty(&sai->sai_entries_received)) | |
| 1212 | 1197 | break; |
| 1213 | 1198 | } |
| 1214 | 1199 | |
| 1215 | 1200 | spin_lock(&plli->lli_agl_lock); |
| 1216 | − while (!agl_list_empty(sai) && | |
| 1201 | + while (!list_empty(&sai->sai_entries_agl) && | |
| 1217 | 1202 | thread_is_running(thread)) { |
| 1218 | − clli = agl_first_entry(sai); | |
| 1203 | + clli = list_entry(sai->sai_entries_agl.next, | |
| 1204 | + struct ll_inode_info, lli_agl_list); | |
| 1219 | 1205 | list_del_init(&clli->lli_agl_list); |
| 1220 | 1206 | spin_unlock(&plli->lli_agl_lock); |
| 1221 | 1207 | ll_agl_trigger(&clli->lli_vfs_inode, sai); |
| @@ -1260,12 +1246,12 @@ out: · 38 unmodified lines | ||
| 1260 | 1246 | } |
| 1261 | 1247 | ll_dir_chain_fini(&chain); |
| 1262 | 1248 | spin_lock(&plli->lli_sa_lock); |
| 1263 | − if (!sa_received_empty(sai)) { | |
| 1249 | + if (!list_empty(&sai->sai_entries_received)) { | |
| 1264 | 1250 | thread_set_flags(thread, SVC_STOPPING); |
| 1265 | 1251 | spin_unlock(&plli->lli_sa_lock); |
| 1266 | 1252 | |
| 1267 | 1253 | /* To release the resources held by received entries. */ |
| 1268 | − while (!sa_received_empty(sai)) | |
| 1254 | + while (!list_empty(&sai->sai_entries_received)) | |
| 1269 | 1255 | ll_post_statahead(sai); |
| 1270 | 1256 | |
| 1271 | 1257 | spin_lock(&plli->lli_sa_lock); |
| @@ -205,7 +205,7 @@ static void __exit exit_lustre_lite(void) · 204 unmodified lines | ||
| 205 | 205 | kmem_cache_destroy(ll_file_data_slab); |
| 206 | 206 | } |
| 207 | 207 | |
| 208 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 208 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 209 | 209 | MODULE_DESCRIPTION("Lustre Lite Client File System"); |
| 210 | 210 | MODULE_LICENSE("GPL"); |
| 211 | 211 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | ||
| 26 | 26 | /* |
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | + * | |
| 30 | + * Copyright (c) 2013, 2015, Intel Corporation. | |
| 29 | 31 | */ |
| 30 | 32 | /* |
| 31 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -849,7 +849,7 @@ static int vvp_io_read_page(const struct lu_env *env, · 815 unmodified lines | ||
| 849 | 849 | * Add page into the queue even when it is marked uptodate above. |
| 850 | 850 | * this will unlock it automatically as part of cl_page_list_disown(). |
| 851 | 851 | */ |
| 852 | − cl_2queue_add(queue, page); | |
| 852 | + cl_page_list_add(&queue->c2_qin, page); | |
| 853 | 853 | if (sbi->ll_ra_info.ra_max_pages_per_file && |
| 854 | 854 | sbi->ll_ra_info.ra_max_pages) |
| 855 | 855 | ll_readahead(env, io, ras, |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | ||
| 26 | 26 | /* |
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | + * | |
| 30 | + * Copyright (c) 2014, 2015, Intel Corporation. | |
| 29 | 31 | */ |
| 30 | 32 | /* |
| 31 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -193,7 +193,10 @@ int ll_setxattr_common(struct inode *inode, const char *name, · 159 unmodified lines | ||
| 193 | 193 | ll_i2suppgid(inode), &req); |
| 194 | 194 | #ifdef CONFIG_FS_POSIX_ACL |
| 195 | 195 | if (new_value != NULL) |
| 196 | − lustre_posix_acl_xattr_free(new_value, size); | |
| 196 | + /* | |
| 197 | + * Release the posix ACL space. | |
| 198 | + */ | |
| 199 | + kfree(new_value); | |
| 197 | 200 | if (acl != NULL) |
| 198 | 201 | lustre_ext_acl_xattr_free(acl); |
| 199 | 202 | #endif |
| @@ -1,6 +1,8 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * Copyright 2012 Xyratex Technology Limited |
| 3 | 3 | * |
| 4 | + * Copyright (c) 2013, 2015, Intel Corporation. | |
| 5 | + * | |
| 4 | 6 | * Author: Andrew Perepechko <Andrew_Perepechko@xyratex.com> |
| 5 | 7 | * |
| 6 | 8 | */ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -156,11 +156,11 @@ out: · 122 unmodified lines | ||
| 156 | 156 | * IT_OPEN is intended to open (and create, possible) an object. Parent (pid) |
| 157 | 157 | * may be split dir. |
| 158 | 158 | */ |
| 159 | −int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, | |
| 160 | − void *lmm, int lmmsize, struct lookup_intent *it, | |
| 161 | − int flags, struct ptlrpc_request **reqp, | |
| 162 | − ldlm_blocking_callback cb_blocking, | |
| 163 | − __u64 extra_lock_flags) | |
| 159 | +static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, | |
| 160 | + void *lmm, int lmmsize, struct lookup_intent *it, | |
| 161 | + int flags, struct ptlrpc_request **reqp, | |
| 162 | + ldlm_blocking_callback cb_blocking, | |
| 163 | + __u64 extra_lock_flags) | |
| 164 | 164 | { |
| 165 | 165 | struct obd_device *obd = exp->exp_obd; |
| 166 | 166 | struct lmv_obd *lmv = &obd->u.lmv; |
| @@ -239,11 +239,12 @@ int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, · 72 unmodified lines | ||
| 239 | 239 | /* |
| 240 | 240 | * Handler for: getattr, lookup and revalidate cases. |
| 241 | 241 | */ |
| 242 | −int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data, | |
| 243 | − void *lmm, int lmmsize, struct lookup_intent *it, | |
| 244 | − int flags, struct ptlrpc_request **reqp, | |
| 245 | − ldlm_blocking_callback cb_blocking, | |
| 246 | − __u64 extra_lock_flags) | |
| 242 | +static int lmv_intent_lookup(struct obd_export *exp, | |
| 243 | + struct md_op_data *op_data, | |
| 244 | + void *lmm, int lmmsize, struct lookup_intent *it, | |
| 245 | + int flags, struct ptlrpc_request **reqp, | |
| 246 | + ldlm_blocking_callback cb_blocking, | |
| 247 | + __u64 extra_lock_flags) | |
| 247 | 248 | { |
| 248 | 249 | struct obd_device *obd = exp->exp_obd; |
| 249 | 250 | struct lmv_obd *lmv = &obd->u.lmv; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -56,20 +56,6 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, · 22 unmodified lines | ||
| 56 | 56 | ldlm_blocking_callback cb_blocking, |
| 57 | 57 | __u64 extra_lock_flags); |
| 58 | 58 | |
| 59 | −int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data, | |
| 60 | − void *lmm, int lmmsize, struct lookup_intent *it, | |
| 61 | − int flags, struct ptlrpc_request **reqp, | |
| 62 | − ldlm_blocking_callback cb_blocking, | |
| 63 | − __u64 extra_lock_flags); | |
| 64 | − | |
| 65 | −int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, | |
| 66 | − void *lmm, int lmmsize, struct lookup_intent *it, | |
| 67 | − int flags, struct ptlrpc_request **reqp, | |
| 68 | − ldlm_blocking_callback cb_blocking, | |
| 69 | − __u64 extra_lock_flags); | |
| 70 | − | |
| 71 | −int lmv_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *, | |
| 72 | − void *, int); | |
| 73 | 59 | int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds); |
| 74 | 60 | int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds); |
| 75 | 61 | int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -2744,55 +2744,55 @@ static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, · 2710 unmodified lines | ||
| 2744 | 2744 | } |
| 2745 | 2745 | |
| 2746 | 2746 | static struct obd_ops lmv_obd_ops = { |
| 2747 | − .o_owner = THIS_MODULE, | |
| 2748 | − .o_setup = lmv_setup, | |
| 2749 | − .o_cleanup = lmv_cleanup, | |
| 2750 | − .o_precleanup = lmv_precleanup, | |
| 2751 | − .o_process_config = lmv_process_config, | |
| 2752 | − .o_connect = lmv_connect, | |
| 2753 | − .o_disconnect = lmv_disconnect, | |
| 2754 | − .o_statfs = lmv_statfs, | |
| 2755 | − .o_get_info = lmv_get_info, | |
| 2756 | − .o_set_info_async = lmv_set_info_async, | |
| 2757 | − .o_packmd = lmv_packmd, | |
| 2758 | − .o_unpackmd = lmv_unpackmd, | |
| 2759 | − .o_notify = lmv_notify, | |
| 2760 | − .o_get_uuid = lmv_get_uuid, | |
| 2761 | − .o_iocontrol = lmv_iocontrol, | |
| 2762 | − .o_quotacheck = lmv_quotacheck, | |
| 2763 | − .o_quotactl = lmv_quotactl | |
| 2747 | + .owner = THIS_MODULE, | |
| 2748 | + .setup = lmv_setup, | |
| 2749 | + .cleanup = lmv_cleanup, | |
| 2750 | + .precleanup = lmv_precleanup, | |
| 2751 | + .process_config = lmv_process_config, | |
| 2752 | + .connect = lmv_connect, | |
| 2753 | + .disconnect = lmv_disconnect, | |
| 2754 | + .statfs = lmv_statfs, | |
| 2755 | + .get_info = lmv_get_info, | |
| 2756 | + .set_info_async = lmv_set_info_async, | |
| 2757 | + .packmd = lmv_packmd, | |
| 2758 | + .unpackmd = lmv_unpackmd, | |
| 2759 | + .notify = lmv_notify, | |
| 2760 | + .get_uuid = lmv_get_uuid, | |
| 2761 | + .iocontrol = lmv_iocontrol, | |
| 2762 | + .quotacheck = lmv_quotacheck, | |
| 2763 | + .quotactl = lmv_quotactl | |
| 2764 | 2764 | }; |
| 2765 | 2765 | |
| 2766 | 2766 | static struct md_ops lmv_md_ops = { |
| 2767 | − .m_getstatus = lmv_getstatus, | |
| 2768 | − .m_null_inode = lmv_null_inode, | |
| 2769 | − .m_find_cbdata = lmv_find_cbdata, | |
| 2770 | − .m_close = lmv_close, | |
| 2771 | − .m_create = lmv_create, | |
| 2772 | − .m_done_writing = lmv_done_writing, | |
| 2773 | − .m_enqueue = lmv_enqueue, | |
| 2774 | − .m_getattr = lmv_getattr, | |
| 2775 | − .m_getxattr = lmv_getxattr, | |
| 2776 | − .m_getattr_name = lmv_getattr_name, | |
| 2777 | − .m_intent_lock = lmv_intent_lock, | |
| 2778 | − .m_link = lmv_link, | |
| 2779 | − .m_rename = lmv_rename, | |
| 2780 | − .m_setattr = lmv_setattr, | |
| 2781 | − .m_setxattr = lmv_setxattr, | |
| 2782 | − .m_sync = lmv_sync, | |
| 2783 | − .m_readpage = lmv_readpage, | |
| 2784 | − .m_unlink = lmv_unlink, | |
| 2785 | − .m_init_ea_size = lmv_init_ea_size, | |
| 2786 | − .m_cancel_unused = lmv_cancel_unused, | |
| 2787 | − .m_set_lock_data = lmv_set_lock_data, | |
| 2788 | − .m_lock_match = lmv_lock_match, | |
| 2789 | − .m_get_lustre_md = lmv_get_lustre_md, | |
| 2790 | − .m_free_lustre_md = lmv_free_lustre_md, | |
| 2791 | − .m_set_open_replay_data = lmv_set_open_replay_data, | |
| 2792 | − .m_clear_open_replay_data = lmv_clear_open_replay_data, | |
| 2793 | − .m_get_remote_perm = lmv_get_remote_perm, | |
| 2794 | − .m_intent_getattr_async = lmv_intent_getattr_async, | |
| 2795 | − .m_revalidate_lock = lmv_revalidate_lock | |
| 2767 | + .getstatus = lmv_getstatus, | |
| 2768 | + .null_inode = lmv_null_inode, | |
| 2769 | + .find_cbdata = lmv_find_cbdata, | |
| 2770 | + .close = lmv_close, | |
| 2771 | + .create = lmv_create, | |
| 2772 | + .done_writing = lmv_done_writing, | |
| 2773 | + .enqueue = lmv_enqueue, | |
| 2774 | + .getattr = lmv_getattr, | |
| 2775 | + .getxattr = lmv_getxattr, | |
| 2776 | + .getattr_name = lmv_getattr_name, | |
| 2777 | + .intent_lock = lmv_intent_lock, | |
| 2778 | + .link = lmv_link, | |
| 2779 | + .rename = lmv_rename, | |
| 2780 | + .setattr = lmv_setattr, | |
| 2781 | + .setxattr = lmv_setxattr, | |
| 2782 | + .sync = lmv_sync, | |
| 2783 | + .readpage = lmv_readpage, | |
| 2784 | + .unlink = lmv_unlink, | |
| 2785 | + .init_ea_size = lmv_init_ea_size, | |
| 2786 | + .cancel_unused = lmv_cancel_unused, | |
| 2787 | + .set_lock_data = lmv_set_lock_data, | |
| 2788 | + .lock_match = lmv_lock_match, | |
| 2789 | + .get_lustre_md = lmv_get_lustre_md, | |
| 2790 | + .free_lustre_md = lmv_free_lustre_md, | |
| 2791 | + .set_open_replay_data = lmv_set_open_replay_data, | |
| 2792 | + .clear_open_replay_data = lmv_clear_open_replay_data, | |
| 2793 | + .get_remote_perm = lmv_get_remote_perm, | |
| 2794 | + .intent_getattr_async = lmv_intent_getattr_async, | |
| 2795 | + .revalidate_lock = lmv_revalidate_lock | |
| 2796 | 2796 | }; |
| 2797 | 2797 | |
| 2798 | 2798 | static int __init lmv_init(void) |
| @@ -2812,7 +2812,7 @@ static void lmv_exit(void) · 13 unmodified lines | ||
| 2812 | 2812 | class_unregister_type(LUSTRE_LMV_NAME); |
| 2813 | 2813 | } |
| 2814 | 2814 | |
| 2815 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 2815 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 2816 | 2816 | MODULE_DESCRIPTION("Lustre Logical Metadata Volume OBD driver"); |
| 2817 | 2817 | MODULE_LICENSE("GPL"); |
| 2818 | 2818 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015 Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -151,23 +151,10 @@ int lov_stripe_number(struct lov_stripe_md *lsm, u64 lov_off); · 117 unmodified lines | ||
| 151 | 151 | /* lov_qos.c */ |
| 152 | 152 | #define LOV_USES_ASSIGNED_STRIPE 0 |
| 153 | 153 | #define LOV_USES_DEFAULT_STRIPE 1 |
| 154 | −int qos_add_tgt(struct obd_device *obd, __u32 index); | |
| 155 | −int qos_del_tgt(struct obd_device *obd, struct lov_tgt_desc *tgt); | |
| 156 | −void qos_shrink_lsm(struct lov_request_set *set); | |
| 157 | −int qos_prep_create(struct obd_export *exp, struct lov_request_set *set); | |
| 158 | −void qos_update(struct lov_obd *lov); | |
| 159 | −void qos_statfs_done(struct lov_obd *lov); | |
| 160 | −void qos_statfs_update(struct obd_device *obd, __u64 max_age, int wait); | |
| 161 | −int qos_remedy_create(struct lov_request_set *set, struct lov_request *req); | |
| 162 | 154 | |
| 163 | 155 | /* lov_request.c */ |
| 164 | −void lov_set_add_req(struct lov_request *req, struct lov_request_set *set); | |
| 165 | −int lov_set_finished(struct lov_request_set *set, int idempotent); | |
| 166 | −void lov_update_set(struct lov_request_set *set, | |
| 167 | − struct lov_request *req, int rc); | |
| 168 | 156 | int lov_update_common_set(struct lov_request_set *set, |
| 169 | 157 | struct lov_request *req, int rc); |
| 170 | −int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx); | |
| 171 | 158 | int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, |
| 172 | 159 | struct lov_request_set **reqset); |
| 173 | 160 | int lov_fini_getattr_set(struct lov_request_set *set); |
| @@ -184,8 +171,6 @@ int lov_update_setattr_set(struct lov_request_set *set, · 10 unmodified lines | ||
| 184 | 171 | int lov_fini_setattr_set(struct lov_request_set *set); |
| 185 | 172 | int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo, |
| 186 | 173 | struct lov_request_set **reqset); |
| 187 | −void lov_update_statfs(struct obd_statfs *osfs, struct obd_statfs *lov_sfs, | |
| 188 | − int success); | |
| 189 | 174 | int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs, |
| 190 | 175 | int success); |
| 191 | 176 | int lov_fini_statfs_set(struct lov_request_set *set); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -2277,35 +2277,35 @@ out: · 2243 unmodified lines | ||
| 2277 | 2277 | } |
| 2278 | 2278 | |
| 2279 | 2279 | static struct obd_ops lov_obd_ops = { |
| 2280 | − .o_owner = THIS_MODULE, | |
| 2281 | − .o_setup = lov_setup, | |
| 2282 | − .o_precleanup = lov_precleanup, | |
| 2283 | − .o_cleanup = lov_cleanup, | |
| 2284 | − /*.o_process_config = lov_process_config,*/ | |
| 2285 | − .o_connect = lov_connect, | |
| 2286 | − .o_disconnect = lov_disconnect, | |
| 2287 | − .o_statfs = lov_statfs, | |
| 2288 | − .o_statfs_async = lov_statfs_async, | |
| 2289 | − .o_packmd = lov_packmd, | |
| 2290 | − .o_unpackmd = lov_unpackmd, | |
| 2291 | − .o_create = lov_create, | |
| 2292 | − .o_destroy = lov_destroy, | |
| 2293 | − .o_getattr_async = lov_getattr_async, | |
| 2294 | − .o_setattr_async = lov_setattr_async, | |
| 2295 | − .o_adjust_kms = lov_adjust_kms, | |
| 2296 | − .o_find_cbdata = lov_find_cbdata, | |
| 2297 | − .o_iocontrol = lov_iocontrol, | |
| 2298 | − .o_get_info = lov_get_info, | |
| 2299 | − .o_set_info_async = lov_set_info_async, | |
| 2300 | − .o_notify = lov_notify, | |
| 2301 | − .o_pool_new = lov_pool_new, | |
| 2302 | − .o_pool_rem = lov_pool_remove, | |
| 2303 | − .o_pool_add = lov_pool_add, | |
| 2304 | − .o_pool_del = lov_pool_del, | |
| 2305 | − .o_getref = lov_getref, | |
| 2306 | − .o_putref = lov_putref, | |
| 2307 | − .o_quotactl = lov_quotactl, | |
| 2308 | − .o_quotacheck = lov_quotacheck, | |
| 2280 | + .owner = THIS_MODULE, | |
| 2281 | + .setup = lov_setup, | |
| 2282 | + .precleanup = lov_precleanup, | |
| 2283 | + .cleanup = lov_cleanup, | |
| 2284 | + /*.process_config = lov_process_config,*/ | |
| 2285 | + .connect = lov_connect, | |
| 2286 | + .disconnect = lov_disconnect, | |
| 2287 | + .statfs = lov_statfs, | |
| 2288 | + .statfs_async = lov_statfs_async, | |
| 2289 | + .packmd = lov_packmd, | |
| 2290 | + .unpackmd = lov_unpackmd, | |
| 2291 | + .create = lov_create, | |
| 2292 | + .destroy = lov_destroy, | |
| 2293 | + .getattr_async = lov_getattr_async, | |
| 2294 | + .setattr_async = lov_setattr_async, | |
| 2295 | + .adjust_kms = lov_adjust_kms, | |
| 2296 | + .find_cbdata = lov_find_cbdata, | |
| 2297 | + .iocontrol = lov_iocontrol, | |
| 2298 | + .get_info = lov_get_info, | |
| 2299 | + .set_info_async = lov_set_info_async, | |
| 2300 | + .notify = lov_notify, | |
| 2301 | + .pool_new = lov_pool_new, | |
| 2302 | + .pool_rem = lov_pool_remove, | |
| 2303 | + .pool_add = lov_pool_add, | |
| 2304 | + .pool_del = lov_pool_del, | |
| 2305 | + .getref = lov_getref, | |
| 2306 | + .putref = lov_putref, | |
| 2307 | + .quotactl = lov_quotactl, | |
| 2308 | + .quotacheck = lov_quotacheck, | |
| 2309 | 2309 | }; |
| 2310 | 2310 | |
| 2311 | 2311 | struct kmem_cache *lov_oinfo_slab; |
| @@ -2352,7 +2352,7 @@ static void /*__exit*/ lov_exit(void) · 40 unmodified lines | ||
| 2352 | 2352 | lu_kmem_fini(lov_caches); |
| 2353 | 2353 | } |
| 2354 | 2354 | |
| 2355 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 2355 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 2356 | 2356 | MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver"); |
| 2357 | 2357 | MODULE_LICENSE("GPL"); |
| 2358 | 2358 | MODULE_VERSION(LUSTRE_VERSION_STRING); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -258,22 +258,9 @@ static int lov_verify_lmm(void *lmm, int lmm_bytes, __u16 *stripe_count) · 224 unmodified lines | ||
| 258 | 258 | int rc; |
| 259 | 259 | |
| 260 | 260 | if (lsm_op_find(le32_to_cpu(*(__u32 *)lmm)) == NULL) { |
| 261 | − char *buffer; | |
| 262 | − int sz; | |
| 263 | − | |
| 264 | 261 | CERROR("bad disk LOV MAGIC: 0x%08X; dumping LMM (size=%d):\n", |
| 265 | 262 | le32_to_cpu(*(__u32 *)lmm), lmm_bytes); |
| 266 | − sz = lmm_bytes * 2 + 1; | |
| 267 | − buffer = libcfs_kvzalloc(sz, GFP_NOFS); | |
| 268 | − if (buffer != NULL) { | |
| 269 | − int i; | |
| 270 | − | |
| 271 | − for (i = 0; i < lmm_bytes; i++) | |
| 272 | − sprintf(buffer+2*i, "%.2X", ((char *)lmm)[i]); | |
| 273 | − buffer[sz - 1] = '\0'; | |
| 274 | − CERROR("%s\n", buffer); | |
| 275 | − kvfree(buffer); | |
| 276 | − } | |
| 263 | + CERROR("%*phN\n", lmm_bytes, lmm); | |
| 277 | 264 | return -EINVAL; |
| 278 | 265 | } |
| 279 | 266 | rc = lsm_op_find(le32_to_cpu(*(__u32 *)lmm))->lsm_lmm_verify(lmm, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -412,8 +412,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname) · 411 unmodified lines | ||
| 412 | 412 | if (!new_pool) |
| 413 | 413 | return -ENOMEM; |
| 414 | 414 | |
| 415 | − strncpy(new_pool->pool_name, poolname, LOV_MAXPOOLNAME); | |
| 416 | − new_pool->pool_name[LOV_MAXPOOLNAME] = '\0'; | |
| 415 | + strlcpy(new_pool->pool_name, poolname, sizeof(new_pool->pool_name)); | |
| 417 | 416 | new_pool->pool_lobd = obd; |
| 418 | 417 | /* ref count init to 1 because when created a pool is always used |
| 419 | 418 | * up to deletion |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -74,7 +74,7 @@ void lov_finish_set(struct lov_request_set *set) · 40 unmodified lines | ||
| 74 | 74 | kfree(set); |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | −int lov_set_finished(struct lov_request_set *set, int idempotent) | |
| 77 | +static int lov_set_finished(struct lov_request_set *set, int idempotent) | |
| 78 | 78 | { |
| 79 | 79 | int completes = atomic_read(&set->set_completes); |
| 80 | 80 | |
| @@ -89,8 +89,8 @@ int lov_set_finished(struct lov_request_set *set, int idempotent) · 8 unmodified lines | ||
| 89 | 89 | return 0; |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | −void lov_update_set(struct lov_request_set *set, | |
| 93 | − struct lov_request *req, int rc) | |
| 92 | +static void lov_update_set(struct lov_request_set *set, | |
| 93 | + struct lov_request *req, int rc) | |
| 94 | 94 | { |
| 95 | 95 | req->rq_complete = 1; |
| 96 | 96 | req->rq_rc = rc; |
| @@ -118,7 +118,8 @@ int lov_update_common_set(struct lov_request_set *set, · 21 unmodified lines | ||
| 118 | 118 | return rc; |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | −void lov_set_add_req(struct lov_request *req, struct lov_request_set *set) | |
| 121 | +static void lov_set_add_req(struct lov_request *req, | |
| 122 | + struct lov_request_set *set) | |
| 122 | 123 | { |
| 123 | 124 | list_add_tail(&req->rq_link, &set->set_list); |
| 124 | 125 | set->set_count++; |
| @@ -144,7 +145,7 @@ static int lov_check_set(struct lov_obd *lov, int idx) · 19 unmodified lines | ||
| 144 | 145 | * If the OSC has not yet had a chance to connect to the OST the first time, |
| 145 | 146 | * wait once for it to connect instead of returning an error. |
| 146 | 147 | */ |
| 147 | −int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx) | |
| 148 | +static int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx) | |
| 148 | 149 | { |
| 149 | 150 | wait_queue_head_t waitq; |
| 150 | 151 | struct l_wait_info lwi; |
| @@ -591,8 +592,9 @@ int lov_fini_statfs_set(struct lov_request_set *set) · 440 unmodified lines | ||
| 591 | 592 | return rc; |
| 592 | 593 | } |
| 593 | 594 | |
| 594 | −void lov_update_statfs(struct obd_statfs *osfs, struct obd_statfs *lov_sfs, | |
| 595 | − int success) | |
| 595 | +static void lov_update_statfs(struct obd_statfs *osfs, | |
| 596 | + struct obd_statfs *lov_sfs, | |
| 597 | + int success) | |
| 596 | 598 | { |
| 597 | 599 | int shift = 0, quit = 0; |
| 598 | 600 | __u64 tmp; |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | ||
| 26 | 26 | /* |
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | + * | |
| 30 | + * Copyright (c) 2013, 2015, Intel Corporation. | |
| 29 | 31 | */ |
| 30 | 32 | /* |
| 31 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015 Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2012, 2015 Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -82,82 +82,6 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, · 48 unmodified lines | ||
| 82 | 82 | } |
| 83 | 83 | LUSTRE_RW_ATTR(max_rpcs_in_flight); |
| 84 | 84 | |
| 85 | −static int mdc_kuc_open(struct inode *inode, struct file *file) | |
| 86 | −{ | |
| 87 | − return single_open(file, NULL, inode->i_private); | |
| 88 | −} | |
| 89 | − | |
| 90 | −/* temporary for testing */ | |
| 91 | −static ssize_t mdc_kuc_write(struct file *file, | |
| 92 | − const char __user *buffer, | |
| 93 | − size_t count, loff_t *off) | |
| 94 | −{ | |
| 95 | − struct obd_device *obd = | |
| 96 | − ((struct seq_file *)file->private_data)->private; | |
| 97 | − struct kuc_hdr *lh; | |
| 98 | − struct hsm_action_list *hal; | |
| 99 | − struct hsm_action_item *hai; | |
| 100 | − int len; | |
| 101 | − int fd, rc; | |
| 102 | − | |
| 103 | − rc = lprocfs_write_helper(buffer, count, &fd); | |
| 104 | − if (rc) | |
| 105 | − return rc; | |
| 106 | − | |
| 107 | − if (fd < 0) | |
| 108 | − return -ERANGE; | |
| 109 | − CWARN("message to fd %d\n", fd); | |
| 110 | − | |
| 111 | − len = sizeof(*lh) + sizeof(*hal) + MTI_NAME_MAXLEN + | |
| 112 | − /* for mockup below */ 2 * cfs_size_round(sizeof(*hai)); | |
| 113 | − | |
| 114 | − lh = kzalloc(len, GFP_NOFS); | |
| 115 | − if (!lh) | |
| 116 | − return -ENOMEM; | |
| 117 | − | |
| 118 | − lh->kuc_magic = KUC_MAGIC; | |
| 119 | − lh->kuc_transport = KUC_TRANSPORT_HSM; | |
| 120 | − lh->kuc_msgtype = HMT_ACTION_LIST; | |
| 121 | − lh->kuc_msglen = len; | |
| 122 | − | |
| 123 | − hal = (struct hsm_action_list *)(lh + 1); | |
| 124 | − hal->hal_version = HAL_VERSION; | |
| 125 | − hal->hal_archive_id = 1; | |
| 126 | − hal->hal_flags = 0; | |
| 127 | − obd_uuid2fsname(hal->hal_fsname, obd->obd_name, MTI_NAME_MAXLEN); | |
| 128 | − | |
| 129 | − /* mock up an action list */ | |
| 130 | − hal->hal_count = 2; | |
| 131 | − hai = hai_zero(hal); | |
| 132 | − hai->hai_action = HSMA_ARCHIVE; | |
| 133 | − hai->hai_fid.f_oid = 5; | |
| 134 | − hai->hai_len = sizeof(*hai); | |
| 135 | − hai = hai_next(hai); | |
| 136 | − hai->hai_action = HSMA_RESTORE; | |
| 137 | − hai->hai_fid.f_oid = 10; | |
| 138 | − hai->hai_len = sizeof(*hai); | |
| 139 | − | |
| 140 | − /* This works for either broadcast or unicast to a single fd */ | |
| 141 | − if (fd == 0) { | |
| 142 | − rc = libcfs_kkuc_group_put(KUC_GRP_HSM, lh); | |
| 143 | − } else { | |
| 144 | − struct file *fp = fget(fd); | |
| 145 | − | |
| 146 | − rc = libcfs_kkuc_msg_put(fp, lh); | |
| 147 | − fput(fp); | |
| 148 | − } | |
| 149 | − kfree(lh); | |
| 150 | − if (rc < 0) | |
| 151 | − return rc; | |
| 152 | − return count; | |
| 153 | −} | |
| 154 | − | |
| 155 | −static struct file_operations mdc_kuc_fops = { | |
| 156 | − .open = mdc_kuc_open, | |
| 157 | − .write = mdc_kuc_write, | |
| 158 | − .release = single_release, | |
| 159 | −}; | |
| 160 | − | |
| 161 | 85 | LPROC_SEQ_FOPS_WR_ONLY(mdc, ping); |
| 162 | 86 | |
| 163 | 87 | LPROC_SEQ_FOPS_RO_TYPE(mdc, connect_flags); |
| @@ -196,7 +120,6 @@ static struct lprocfs_vars lprocfs_mdc_obd_vars[] = { · 32 unmodified lines | ||
| 196 | 120 | { "timeouts", &mdc_timeouts_fops, NULL, 0 }, |
| 197 | 121 | { "import", &mdc_import_fops, NULL, 0 }, |
| 198 | 122 | { "state", &mdc_state_fops, NULL, 0 }, |
| 199 | − { "hsm_nl", &mdc_kuc_fops, NULL, 0200 }, | |
| 200 | 123 | { "pinger_recov", &mdc_pinger_recov_fops, NULL, 0 }, |
| 201 | 124 | { NULL } |
| 202 | 125 | }; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015 Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -44,7 +44,6 @@ void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars); · 10 unmodified lines | ||
| 44 | 44 | |
| 45 | 45 | void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, |
| 46 | 46 | __u64 valid, int ea_size, __u32 suppgid, int flags); |
| 47 | −int mdc_pack_req(struct ptlrpc_request *req, int version, int opc); | |
| 48 | 47 | void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid, |
| 49 | 48 | const struct lu_fid *cfid, int flags); |
| 50 | 49 | void mdc_swap_layouts_pack(struct ptlrpc_request *req, |
| @@ -62,7 +61,6 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, · 11 unmodified lines | ||
| 62 | 61 | __u32 mode, __u64 rdev, __u64 flags, const void *data, |
| 63 | 62 | int datalen); |
| 64 | 63 | void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data); |
| 65 | −void mdc_getxattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data); | |
| 66 | 64 | void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data); |
| 67 | 65 | void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, |
| 68 | 66 | const char *old, int oldlen, const char *new, int newlen); |
| @@ -97,25 +95,12 @@ int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid, · 28 unmodified lines | ||
| 97 | 95 | /* mdc/mdc_request.c */ |
| 98 | 96 | int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, |
| 99 | 97 | struct md_op_data *op_data); |
| 100 | − | |
| 101 | −int mdc_open(struct obd_export *exp, u64 ino, int type, int flags, | |
| 102 | − struct lov_mds_md *lmm, int lmm_size, struct lustre_handle *fh, | |
| 103 | − struct ptlrpc_request **); | |
| 104 | − | |
| 105 | 98 | struct obd_client_handle; |
| 106 | 99 | |
| 107 | −int mdc_get_lustre_md(struct obd_export *md_exp, struct ptlrpc_request *req, | |
| 108 | − struct obd_export *dt_exp, struct obd_export *lmv_exp, | |
| 109 | − struct lustre_md *md); | |
| 110 | − | |
| 111 | −int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md); | |
| 112 | − | |
| 113 | 100 | int mdc_set_open_replay_data(struct obd_export *exp, |
| 114 | 101 | struct obd_client_handle *och, |
| 115 | 102 | struct lookup_intent *it); |
| 116 | 103 | |
| 117 | −int mdc_clear_open_replay_data(struct obd_export *exp, | |
| 118 | − struct obd_client_handle *och); | |
| 119 | 104 | void mdc_commit_open(struct ptlrpc_request *req); |
| 120 | 105 | void mdc_replay_open(struct ptlrpc_request *req); |
| 121 | 106 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -447,9 +447,11 @@ static int mdc_unpack_acl(struct ptlrpc_request *req, struct lustre_md *md) · 413 unmodified lines | ||
| 447 | 447 | #define mdc_unpack_acl(req, md) 0 |
| 448 | 448 | #endif |
| 449 | 449 | |
| 450 | −int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req, | |
| 451 | − struct obd_export *dt_exp, struct obd_export *md_exp, | |
| 452 | − struct lustre_md *md) | |
| 450 | +static int mdc_get_lustre_md(struct obd_export *exp, | |
| 451 | + struct ptlrpc_request *req, | |
| 452 | + struct obd_export *dt_exp, | |
| 453 | + struct obd_export *md_exp, | |
| 454 | + struct lustre_md *md) | |
| 453 | 455 | { |
| 454 | 456 | struct req_capsule *pill = &req->rq_pill; |
| 455 | 457 | int rc; |
| @@ -573,7 +575,7 @@ out: · 117 unmodified lines | ||
| 573 | 575 | return rc; |
| 574 | 576 | } |
| 575 | 577 | |
| 576 | −int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md) | |
| 578 | +static int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md) | |
| 577 | 579 | { |
| 578 | 580 | return 0; |
| 579 | 581 | } |
| @@ -737,8 +739,8 @@ static void mdc_free_open(struct md_open_data *mod) · 157 unmodified lines | ||
| 737 | 739 | ptlrpc_request_committed(mod->mod_close_req, committed); |
| 738 | 740 | } |
| 739 | 741 | |
| 740 | −int mdc_clear_open_replay_data(struct obd_export *exp, | |
| 741 | − struct obd_client_handle *och) | |
| 742 | +static int mdc_clear_open_replay_data(struct obd_export *exp, | |
| 743 | + struct obd_client_handle *och) | |
| 742 | 744 | { |
| 743 | 745 | struct md_open_data *mod = och->och_mod; |
| 744 | 746 | |
| @@ -1179,7 +1181,6 @@ static int mdc_ioc_hsm_progress(struct obd_export *exp, · 434 unmodified lines | ||
| 1179 | 1181 | ptlrpc_request_set_replen(req); |
| 1180 | 1182 | |
| 1181 | 1183 | rc = mdc_queue_wait(req); |
| 1182 | − goto out; | |
| 1183 | 1184 | out: |
| 1184 | 1185 | ptlrpc_req_finished(req); |
| 1185 | 1186 | return rc; |
| @@ -1214,7 +1215,6 @@ static int mdc_ioc_hsm_ct_register(struct obd_import *imp, __u32 archives) · 28 unmodified lines | ||
| 1214 | 1215 | ptlrpc_request_set_replen(req); |
| 1215 | 1216 | |
| 1216 | 1217 | rc = mdc_queue_wait(req); |
| 1217 | − goto out; | |
| 1218 | 1218 | out: |
| 1219 | 1219 | ptlrpc_req_finished(req); |
| 1220 | 1220 | return rc; |
| @@ -1280,7 +1280,6 @@ static int mdc_ioc_hsm_ct_unregister(struct obd_import *imp) · 59 unmodified lines | ||
| 1280 | 1280 | ptlrpc_request_set_replen(req); |
| 1281 | 1281 | |
| 1282 | 1282 | rc = mdc_queue_wait(req); |
| 1283 | − goto out; | |
| 1284 | 1283 | out: |
| 1285 | 1284 | ptlrpc_req_finished(req); |
| 1286 | 1285 | return rc; |
| @@ -1360,8 +1359,6 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp, · 73 unmodified lines | ||
| 1360 | 1359 | ptlrpc_request_set_replen(req); |
| 1361 | 1360 | |
| 1362 | 1361 | rc = mdc_queue_wait(req); |
| 1363 | − goto out; | |
| 1364 | − | |
| 1365 | 1362 | out: |
| 1366 | 1363 | ptlrpc_req_finished(req); |
| 1367 | 1364 | return rc; |
| @@ -1425,8 +1422,6 @@ static int mdc_ioc_hsm_request(struct obd_export *exp, · 57 unmodified lines | ||
| 1425 | 1422 | ptlrpc_request_set_replen(req); |
| 1426 | 1423 | |
| 1427 | 1424 | rc = mdc_queue_wait(req); |
| 1428 | − goto out; | |
| 1429 | − | |
| 1430 | 1425 | out: |
| 1431 | 1426 | ptlrpc_req_finished(req); |
| 1432 | 1427 | return rc; |
| @@ -2035,17 +2030,6 @@ static int mdc_hsm_ct_reregister(__u32 data, void *cb_arg) · 602 unmodified lines | ||
| 2035 | 2030 | return ((rc != 0) && (rc != -EEXIST)) ? rc : 0; |
| 2036 | 2031 | } |
| 2037 | 2032 | |
| 2038 | −/** | |
| 2039 | − * Re-establish all kuc contexts with MDT | |
| 2040 | − * after MDT shutdown/recovery. | |
| 2041 | − */ | |
| 2042 | −static int mdc_kuc_reregister(struct obd_import *imp) | |
| 2043 | −{ | |
| 2044 | − /* re-register HSM agents */ | |
| 2045 | − return libcfs_kkuc_group_foreach(KUC_GRP_HSM, mdc_hsm_ct_reregister, | |
| 2046 | − (void *)imp); | |
| 2047 | −} | |
| 2048 | − | |
| 2049 | 2033 | static int mdc_set_info_async(const struct lu_env *env, |
| 2050 | 2034 | struct obd_export *exp, |
| 2051 | 2035 | u32 keylen, void *key, |
| @@ -2208,7 +2192,10 @@ static int mdc_import_event(struct obd_device *obd, struct obd_import *imp, · 156 unmodified lines | ||
| 2208 | 2192 | rc = obd_notify_observer(obd, obd, OBD_NOTIFY_ACTIVE, NULL); |
| 2209 | 2193 | /* redo the kuc registration after reconnecting */ |
| 2210 | 2194 | if (rc == 0) |
| 2211 | − rc = mdc_kuc_reregister(imp); | |
| 2195 | + /* re-register HSM agents */ | |
| 2196 | + rc = libcfs_kkuc_group_foreach(KUC_GRP_HSM, | |
| 2197 | + mdc_hsm_ct_reregister, | |
| 2198 | + (void *)imp); | |
| 2212 | 2199 | break; |
| 2213 | 2200 | case IMP_EVENT_OCD: |
| 2214 | 2201 | rc = obd_notify_observer(obd, obd, OBD_NOTIFY_OCD, NULL); |
| @@ -2460,59 +2447,59 @@ static int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid, · 245 unmodified lines | ||
| 2460 | 2447 | } |
| 2461 | 2448 | |
| 2462 | 2449 | static struct obd_ops mdc_obd_ops = { |
| 2463 | − .o_owner = THIS_MODULE, | |
| 2464 | − .o_setup = mdc_setup, | |
| 2465 | − .o_precleanup = mdc_precleanup, | |
| 2466 | − .o_cleanup = mdc_cleanup, | |
| 2467 | − .o_add_conn = client_import_add_conn, | |
| 2468 | − .o_del_conn = client_import_del_conn, | |
| 2469 | − .o_connect = client_connect_import, | |
| 2470 | − .o_disconnect = client_disconnect_export, | |
| 2471 | − .o_iocontrol = mdc_iocontrol, | |
| 2472 | − .o_set_info_async = mdc_set_info_async, | |
| 2473 | − .o_statfs = mdc_statfs, | |
| 2474 | − .o_fid_init = client_fid_init, | |
| 2475 | − .o_fid_fini = client_fid_fini, | |
| 2476 | − .o_fid_alloc = mdc_fid_alloc, | |
| 2477 | − .o_import_event = mdc_import_event, | |
| 2478 | − .o_get_info = mdc_get_info, | |
| 2479 | − .o_process_config = mdc_process_config, | |
| 2480 | − .o_get_uuid = mdc_get_uuid, | |
| 2481 | − .o_quotactl = mdc_quotactl, | |
| 2482 | − .o_quotacheck = mdc_quotacheck | |
| 2450 | + .owner = THIS_MODULE, | |
| 2451 | + .setup = mdc_setup, | |
| 2452 | + .precleanup = mdc_precleanup, | |
| 2453 | + .cleanup = mdc_cleanup, | |
| 2454 | + .add_conn = client_import_add_conn, | |
| 2455 | + .del_conn = client_import_del_conn, | |
| 2456 | + .connect = client_connect_import, | |
| 2457 | + .disconnect = client_disconnect_export, | |
| 2458 | + .iocontrol = mdc_iocontrol, | |
| 2459 | + .set_info_async = mdc_set_info_async, | |
| 2460 | + .statfs = mdc_statfs, | |
| 2461 | + .fid_init = client_fid_init, | |
| 2462 | + .fid_fini = client_fid_fini, | |
| 2463 | + .fid_alloc = mdc_fid_alloc, | |
| 2464 | + .import_event = mdc_import_event, | |
| 2465 | + .get_info = mdc_get_info, | |
| 2466 | + .process_config = mdc_process_config, | |
| 2467 | + .get_uuid = mdc_get_uuid, | |
| 2468 | + .quotactl = mdc_quotactl, | |
| 2469 | + .quotacheck = mdc_quotacheck | |
| 2483 | 2470 | }; |
| 2484 | 2471 | |
| 2485 | 2472 | static struct md_ops mdc_md_ops = { |
| 2486 | − .m_getstatus = mdc_getstatus, | |
| 2487 | − .m_null_inode = mdc_null_inode, | |
| 2488 | − .m_find_cbdata = mdc_find_cbdata, | |
| 2489 | − .m_close = mdc_close, | |
| 2490 | − .m_create = mdc_create, | |
| 2491 | − .m_done_writing = mdc_done_writing, | |
| 2492 | − .m_enqueue = mdc_enqueue, | |
| 2493 | − .m_getattr = mdc_getattr, | |
| 2494 | − .m_getattr_name = mdc_getattr_name, | |
| 2495 | − .m_intent_lock = mdc_intent_lock, | |
| 2496 | − .m_link = mdc_link, | |
| 2497 | − .m_is_subdir = mdc_is_subdir, | |
| 2498 | − .m_rename = mdc_rename, | |
| 2499 | − .m_setattr = mdc_setattr, | |
| 2500 | − .m_setxattr = mdc_setxattr, | |
| 2501 | − .m_getxattr = mdc_getxattr, | |
| 2502 | − .m_sync = mdc_sync, | |
| 2503 | − .m_readpage = mdc_readpage, | |
| 2504 | − .m_unlink = mdc_unlink, | |
| 2505 | − .m_cancel_unused = mdc_cancel_unused, | |
| 2506 | − .m_init_ea_size = mdc_init_ea_size, | |
| 2507 | − .m_set_lock_data = mdc_set_lock_data, | |
| 2508 | − .m_lock_match = mdc_lock_match, | |
| 2509 | − .m_get_lustre_md = mdc_get_lustre_md, | |
| 2510 | − .m_free_lustre_md = mdc_free_lustre_md, | |
| 2511 | − .m_set_open_replay_data = mdc_set_open_replay_data, | |
| 2512 | − .m_clear_open_replay_data = mdc_clear_open_replay_data, | |
| 2513 | − .m_get_remote_perm = mdc_get_remote_perm, | |
| 2514 | − .m_intent_getattr_async = mdc_intent_getattr_async, | |
| 2515 | − .m_revalidate_lock = mdc_revalidate_lock | |
| 2473 | + .getstatus = mdc_getstatus, | |
| 2474 | + .null_inode = mdc_null_inode, | |
| 2475 | + .find_cbdata = mdc_find_cbdata, | |
| 2476 | + .close = mdc_close, | |
| 2477 | + .create = mdc_create, | |
| 2478 | + .done_writing = mdc_done_writing, | |
| 2479 | + .enqueue = mdc_enqueue, | |
| 2480 | + .getattr = mdc_getattr, | |
| 2481 | + .getattr_name = mdc_getattr_name, | |
| 2482 | + .intent_lock = mdc_intent_lock, | |
| 2483 | + .link = mdc_link, | |
| 2484 | + .is_subdir = mdc_is_subdir, | |
| 2485 | + .rename = mdc_rename, | |
| 2486 | + .setattr = mdc_setattr, | |
| 2487 | + .setxattr = mdc_setxattr, | |
| 2488 | + .getxattr = mdc_getxattr, | |
| 2489 | + .sync = mdc_sync, | |
| 2490 | + .readpage = mdc_readpage, | |
| 2491 | + .unlink = mdc_unlink, | |
| 2492 | + .cancel_unused = mdc_cancel_unused, | |
| 2493 | + .init_ea_size = mdc_init_ea_size, | |
| 2494 | + .set_lock_data = mdc_set_lock_data, | |
| 2495 | + .lock_match = mdc_lock_match, | |
| 2496 | + .get_lustre_md = mdc_get_lustre_md, | |
| 2497 | + .free_lustre_md = mdc_free_lustre_md, | |
| 2498 | + .set_open_replay_data = mdc_set_open_replay_data, | |
| 2499 | + .clear_open_replay_data = mdc_clear_open_replay_data, | |
| 2500 | + .get_remote_perm = mdc_get_remote_perm, | |
| 2501 | + .intent_getattr_async = mdc_intent_getattr_async, | |
| 2502 | + .revalidate_lock = mdc_revalidate_lock | |
| 2516 | 2503 | }; |
| 2517 | 2504 | |
| 2518 | 2505 | static int __init mdc_init(void) |
| @@ -2530,7 +2517,7 @@ static void /*__exit*/ mdc_exit(void) · 11 unmodified lines | ||
| 2530 | 2517 | class_unregister_type(LUSTRE_MDC_NAME); |
| 2531 | 2518 | } |
| 2532 | 2519 | |
| 2533 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 2520 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 2534 | 2521 | MODULE_DESCRIPTION("Lustre Metadata Client"); |
| 2535 | 2522 | MODULE_LICENSE("GPL"); |
| 2536 | 2523 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -463,7 +463,7 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data) · 429 unmodified lines | ||
| 463 | 463 | } |
| 464 | 464 | spin_unlock(&config_list_lock); |
| 465 | 465 | |
| 466 | − LPROCFS_CLIMP_EXIT(obd); | |
| 466 | + up_read(&obd->u.cli.cl_sem); | |
| 467 | 467 | return 0; |
| 468 | 468 | } |
| 469 | 469 | |
| @@ -1293,7 +1293,7 @@ static int mgc_process_recover_log(struct obd_device *obd, · 823 unmodified lines | ||
| 1293 | 1293 | struct page **pages; |
| 1294 | 1294 | int nrpages; |
| 1295 | 1295 | bool eof = true; |
| 1296 | − bool mne_swab = false; | |
| 1296 | + bool mne_swab; | |
| 1297 | 1297 | int i; |
| 1298 | 1298 | int ealen; |
| 1299 | 1299 | int rc; |
| @@ -1698,20 +1698,20 @@ out: · 398 unmodified lines | ||
| 1698 | 1698 | } |
| 1699 | 1699 | |
| 1700 | 1700 | static struct obd_ops mgc_obd_ops = { |
| 1701 | − .o_owner = THIS_MODULE, | |
| 1702 | − .o_setup = mgc_setup, | |
| 1703 | − .o_precleanup = mgc_precleanup, | |
| 1704 | − .o_cleanup = mgc_cleanup, | |
| 1705 | − .o_add_conn = client_import_add_conn, | |
| 1706 | − .o_del_conn = client_import_del_conn, | |
| 1707 | − .o_connect = client_connect_import, | |
| 1708 | − .o_disconnect = client_disconnect_export, | |
| 1709 | − /* .o_enqueue = mgc_enqueue, */ | |
| 1710 | − /* .o_iocontrol = mgc_iocontrol, */ | |
| 1711 | − .o_set_info_async = mgc_set_info_async, | |
| 1712 | − .o_get_info = mgc_get_info, | |
| 1713 | − .o_import_event = mgc_import_event, | |
| 1714 | − .o_process_config = mgc_process_config, | |
| 1701 | + .owner = THIS_MODULE, | |
| 1702 | + .setup = mgc_setup, | |
| 1703 | + .precleanup = mgc_precleanup, | |
| 1704 | + .cleanup = mgc_cleanup, | |
| 1705 | + .add_conn = client_import_add_conn, | |
| 1706 | + .del_conn = client_import_del_conn, | |
| 1707 | + .connect = client_connect_import, | |
| 1708 | + .disconnect = client_disconnect_export, | |
| 1709 | + /* .enqueue = mgc_enqueue, */ | |
| 1710 | + /* .iocontrol = mgc_iocontrol, */ | |
| 1711 | + .set_info_async = mgc_set_info_async, | |
| 1712 | + .get_info = mgc_get_info, | |
| 1713 | + .import_event = mgc_import_event, | |
| 1714 | + .process_config = mgc_process_config, | |
| 1715 | 1715 | }; |
| 1716 | 1716 | |
| 1717 | 1717 | static int __init mgc_init(void) |
| @@ -1725,7 +1725,7 @@ static void /*__exit*/ mgc_exit(void) · 7 unmodified lines | ||
| 1725 | 1725 | class_unregister_type(LUSTRE_MGC_NAME); |
| 1726 | 1726 | } |
| 1727 | 1727 | |
| 1728 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 1728 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 1729 | 1729 | MODULE_DESCRIPTION("Lustre Management Client"); |
| 1730 | 1730 | MODULE_LICENSE("GPL"); |
| 1731 | 1731 | |
| @@ -235,15 +235,6 @@ _out: · 234 unmodified lines | ||
| 235 | 235 | } |
| 236 | 236 | EXPORT_SYMBOL(lustre_posix_acl_xattr_filter); |
| 237 | 237 | |
| 238 | −/* | |
| 239 | − * Release the posix ACL space. | |
| 240 | − */ | |
| 241 | −void lustre_posix_acl_xattr_free(posix_acl_xattr_header *header, int size) | |
| 242 | −{ | |
| 243 | − kfree(header); | |
| 244 | −} | |
| 245 | −EXPORT_SYMBOL(lustre_posix_acl_xattr_free); | |
| 246 | − | |
| 247 | 238 | /* |
| 248 | 239 | * Release the extended ACL space. |
| 249 | 240 | */ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -236,16 +236,11 @@ int cl_io_rw_init(const struct lu_env *env, struct cl_io *io, · 202 unmodified lines | ||
| 236 | 236 | } |
| 237 | 237 | EXPORT_SYMBOL(cl_io_rw_init); |
| 238 | 238 | |
| 239 | −static inline const struct lu_fid * | |
| 240 | −cl_lock_descr_fid(const struct cl_lock_descr *descr) | |
| 241 | −{ | |
| 242 | − return lu_object_fid(&descr->cld_obj->co_lu); | |
| 243 | −} | |
| 244 | − | |
| 245 | 239 | static int cl_lock_descr_sort(const struct cl_lock_descr *d0, |
| 246 | 240 | const struct cl_lock_descr *d1) |
| 247 | 241 | { |
| 248 | − return lu_fid_cmp(cl_lock_descr_fid(d0), cl_lock_descr_fid(d1)) ?: | |
| 242 | + return lu_fid_cmp(lu_object_fid(&d0->cld_obj->co_lu), | |
| 243 | + lu_object_fid(&d1->cld_obj->co_lu)) ?: | |
| 249 | 244 | __diff_normalize(d0->cld_start, d1->cld_start); |
| 250 | 245 | } |
| 251 | 246 | |
| @@ -254,7 +249,8 @@ static int cl_lock_descr_cmp(const struct cl_lock_descr *d0, · 2 unmodified lines | ||
| 254 | 249 | { |
| 255 | 250 | int ret; |
| 256 | 251 | |
| 257 | − ret = lu_fid_cmp(cl_lock_descr_fid(d0), cl_lock_descr_fid(d1)); | |
| 252 | + ret = lu_fid_cmp(lu_object_fid(&d0->cld_obj->co_lu), | |
| 253 | + lu_object_fid(&d1->cld_obj->co_lu)); | |
| 258 | 254 | if (ret) |
| 259 | 255 | return ret; |
| 260 | 256 | if (d0->cld_end < d1->cld_start) |
| @@ -1215,15 +1211,6 @@ void cl_2queue_init(struct cl_2queue *queue) · 954 unmodified lines | ||
| 1215 | 1211 | } |
| 1216 | 1212 | EXPORT_SYMBOL(cl_2queue_init); |
| 1217 | 1213 | |
| 1218 | −/** | |
| 1219 | − * Add a page to the incoming page list of 2-queue. | |
| 1220 | − */ | |
| 1221 | −void cl_2queue_add(struct cl_2queue *queue, struct cl_page *page) | |
| 1222 | −{ | |
| 1223 | − cl_page_list_add(&queue->c2_qin, page); | |
| 1224 | −} | |
| 1225 | −EXPORT_SYMBOL(cl_2queue_add); | |
| 1226 | − | |
| 1227 | 1214 | /** |
| 1228 | 1215 | * Disown pages in both lists of a 2-queue. |
| 1229 | 1216 | */ |
| @@ -1262,7 +1249,10 @@ EXPORT_SYMBOL(cl_2queue_fini); · 32 unmodified lines | ||
| 1262 | 1249 | void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page) |
| 1263 | 1250 | { |
| 1264 | 1251 | cl_2queue_init(queue); |
| 1265 | − cl_2queue_add(queue, page); | |
| 1252 | + /* | |
| 1253 | + * Add a page to the incoming page list of 2-queue. | |
| 1254 | + */ | |
| 1255 | + cl_page_list_add(&queue->c2_qin, page); | |
| 1266 | 1256 | } |
| 1267 | 1257 | EXPORT_SYMBOL(cl_2queue_init_page); |
| 1268 | 1258 | |
| @@ -687,7 +687,7 @@ EXPORT_SYMBOL(cl_lock_mutex_get); · 686 unmodified lines | ||
| 687 | 687 | * |
| 688 | 688 | * \see cl_lock_mutex_get() |
| 689 | 689 | */ |
| 690 | −int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock) | |
| 690 | +static int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock) | |
| 691 | 691 | { |
| 692 | 692 | int result; |
| 693 | 693 | |
| @@ -705,7 +705,6 @@ int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock) · 11 unmodified lines | ||
| 705 | 705 | result = -EBUSY; |
| 706 | 706 | return result; |
| 707 | 707 | } |
| 708 | −EXPORT_SYMBOL(cl_lock_mutex_try); | |
| 709 | 708 | |
| 710 | 709 | /** |
| 711 | 710 | {* Unlocks cl_lock object. |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -704,7 +704,7 @@ static inline struct cl_env *cl_env_container(struct lu_env *env) · 670 unmodified lines | ||
| 704 | 704 | return container_of(env, struct cl_env, ce_lu); |
| 705 | 705 | } |
| 706 | 706 | |
| 707 | −struct lu_env *cl_env_peek(int *refcheck) | |
| 707 | +static struct lu_env *cl_env_peek(int *refcheck) | |
| 708 | 708 | { |
| 709 | 709 | struct lu_env *env; |
| 710 | 710 | struct cl_env *cle; |
| @@ -724,7 +724,6 @@ struct lu_env *cl_env_peek(int *refcheck) · 13 unmodified lines | ||
| 724 | 724 | CDEBUG(D_OTHER, "%d@%p\n", cle ? cle->ce_ref : 0, cle); |
| 725 | 725 | return env; |
| 726 | 726 | } |
| 727 | −EXPORT_SYMBOL(cl_env_peek); | |
| 728 | 727 | |
| 729 | 728 | /** |
| 730 | 729 | * Returns lu_env: if there already is an environment associated with the |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -576,7 +576,7 @@ static void cleanup_obdclass(void) · 542 unmodified lines | ||
| 576 | 576 | obd_zombie_impexp_stop(); |
| 577 | 577 | } |
| 578 | 578 | |
| 579 | −MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
| 579 | +MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); | |
| 580 | 580 | MODULE_DESCRIPTION("Lustre Class Driver Build Version: " BUILD_VERSION); |
| 581 | 581 | MODULE_LICENSE("GPL"); |
| 582 | 582 | MODULE_VERSION(LUSTRE_VERSION_STRING); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | 28 | * Use is subject to license terms. |
| 29 | 29 | * |
| 30 | − * Copyright (c) 2011, 2012, Intel Corporation. | |
| 30 | + * Copyright (c) 2011, 2015, Intel Corporation. | |
| 31 | 31 | */ |
| 32 | 32 | /* |
| 33 | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -132,7 +132,7 @@ static struct obd_type *class_get_type(const char *name) · 98 unmodified lines | ||
| 132 | 132 | if (type) { |
| 133 | 133 | spin_lock(&type->obd_type_lock); |
| 134 | 134 | type->typ_refcnt++; |
| 135 | − try_module_get(type->typ_dt_ops->o_owner); | |
| 135 | + try_module_get(type->typ_dt_ops->owner); | |
| 136 | 136 | spin_unlock(&type->obd_type_lock); |
| 137 | 137 | } |
| 138 | 138 | return type; |
| @@ -143,7 +143,7 @@ void class_put_type(struct obd_type *type) · 4 unmodified lines | ||
| 143 | 143 | LASSERT(type); |
| 144 | 144 | spin_lock(&type->obd_type_lock); |
| 145 | 145 | type->typ_refcnt--; |
| 146 | − module_put(type->typ_dt_ops->o_owner); | |
| 146 | + module_put(type->typ_dt_ops->owner); | |
| 147 | 147 | spin_unlock(&type->obd_type_lock); |
| 148 | 148 | } |
| 149 | 149 | EXPORT_SYMBOL(class_put_type); |
| @@ -155,7 +155,7 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, · 5 unmodified lines | ||
| 155 | 155 | struct lu_device_type *ldt) |
| 156 | 156 | { |
| 157 | 157 | struct obd_type *type; |
| 158 | − int rc = 0; | |
| 158 | + int rc; | |
| 159 | 159 | |
| 160 | 160 | /* sanity check */ |
| 161 | 161 | LASSERT(strnlen(name, CLASS_MAX_NAME) < CLASS_MAX_NAME); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines |
8 more lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 1101 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 333 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 217 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 4290 lines aren’t shown here.
This diff is large: its 308 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 812 lines aren’t shown here.
This diff is large: its 389 lines aren’t shown here.
This diff is large: its 170 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 194 lines aren’t shown here.
This diff is large: its 597 lines aren’t shown here.
This diff is large: its 289 lines aren’t shown here.
This diff is large: its 205 lines aren’t shown here.
This diff is large: its 242 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 414 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 164 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 239 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 656 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 223 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 234 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 245 lines aren’t shown here.
This diff is large: its 311 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 4685 lines aren’t shown here.
This diff is large: its 1122 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 2195 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 252 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 410 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 1185 lines aren’t shown here.
This diff is large: its 1181 lines aren’t shown here.
This diff is large: its 3697 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 2564 lines aren’t shown here.
This diff is large: its 461 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.