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 | adi,adt7490 +/-1C TDM Extended Temp Range I.C | 20 | adi,adt7490 +/-1C TDM Extended Temp Range I.C |
| 21 | adi,adxl345 Three-Axis Digital Accelerometer | 21 | adi,adxl345 Three-Axis Digital Accelerometer |
| 22 | adi,adxl346 Three-Axis Digital Accelerometer (backward-compatibility value "adi,adxl345" must be listed too) | 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 | at,24c08 i2c serial eeprom (24cxx) | 24 | at,24c08 i2c serial eeprom (24cxx) |
| 24 | atmel,24c00 i2c serial eeprom (24cxx) | 25 | atmel,24c00 i2c serial eeprom (24cxx) |
| 25 | atmel,24c01 i2c serial eeprom (24cxx) | 26 | atmel,24c01 i2c serial eeprom (24cxx) |
| @@ -7,13 +7,18 @@ Required properties: · 6 unmodified lines | |||
| 7 | * "fsl,mma8453" | 7 | * "fsl,mma8453" |
| 8 | * "fsl,mma8652" | 8 | * "fsl,mma8652" |
| 9 | * "fsl,mma8653" | 9 | * "fsl,mma8653" |
| 10 | |||
| 10 | - reg: the I2C address of the chip | 11 | - reg: the I2C address of the chip |
| 11 | 12 | ||
| 12 | Optional properties: | 13 | Optional properties: |
| 13 | 14 | ||
| 14 | - interrupt-parent: should be the phandle for the interrupt controller | 15 | - interrupt-parent: should be the phandle for the interrupt controller |
| 16 | |||
| 15 | - interrupts: interrupt mapping for GPIO IRQ | 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 | Example: | 22 | Example: |
| 18 | 23 | ||
| 19 | mma8453fc@1d { | 24 | mma8453fc@1d { |
| @@ -21,4 +26,5 @@ Example: · 1 unmodified line | |||
| 21 | reg = <0x1d>; | 26 | reg = <0x1d>; |
| 22 | interrupt-parent = <&gpio1>; | 27 | interrupt-parent = <&gpio1>; |
| 23 | interrupts = <5 0>; | 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 | Required properties: | 10 | Required properties: |
| 11 | - compatible: Must be one of the following, depending on the | 11 | - compatible: Must be one of the following, depending on the |
| 12 | model: | 12 | model: |
| 13 | "mcp3001" | 13 | "mcp3001" (DEPRECATED) |
| 14 | "mcp3002" | 14 | "mcp3002" (DEPRECATED) |
| 15 | "mcp3004" | 15 | "mcp3004" (DEPRECATED) |
| 16 | "mcp3008" | 16 | "mcp3008" (DEPRECATED) |
| 17 | "mcp3201" | 17 | "mcp3201" (DEPRECATED) |
| 18 | "mcp3202" | 18 | "mcp3202" (DEPRECATED) |
| 19 | "mcp3204" | 19 | "mcp3204" (DEPRECATED) |
| 20 | "mcp3208" | 20 | "mcp3208" (DEPRECATED) |
| 21 | "mcp3301" | 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 | Examples: | 36 | Examples: |
| 25 | spi_controller { | 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 | Required properties: | 3 | Required properties: |
| 4 | - compatible: Should be | 4 | - compatible: Should be |
| 5 | "microchip,mcp3421" or | ||
| 5 | "microchip,mcp3422" or | 6 | "microchip,mcp3422" or |
| 6 | "microchip,mcp3423" or | 7 | "microchip,mcp3423" or |
| 7 | "microchip,mcp3424" or | 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 | Required properties: | 3 | Required properties: |
| 4 | - compatible: Should be "ti,adc128s052" or "ti,adc122s021" | 4 | - compatible: Should be "ti,adc128s052", "ti,adc122s021" or "ti,adc124s021" |
| 5 | - reg: spi chip select number for the device | 5 | - reg: spi chip select number for the device |
| 6 | - vref-supply: The regulator supply for ADC reference voltage | 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 | Optional properties: | 7 | Optional properties: |
| 8 | - upisemi,glass-coef: glass attenuation factor - compensation factor of | 8 | - upisemi,glass-coef: glass attenuation factor - compensation factor of |
| 9 | resolution 1000 for material transmittance. | 9 | resolution 1000 for material transmittance. |
| 10 | |||
| 10 | - upisemi,dark-ths: array of 8 elements containing 16-bit thresholds (adc | 11 | - upisemi,dark-ths: array of 8 elements containing 16-bit thresholds (adc |
| 11 | counts) corresponding to every scale. | 12 | counts) corresponding to every scale. |
| 13 | |||
| 12 | - upisemi,upper-dark-gain: 8-bit dark gain compensation factor(4 int and 4 | 14 | - upisemi,upper-dark-gain: 8-bit dark gain compensation factor(4 int and 4 |
| 13 | fractional bits - Q4.4) applied when light > threshold | 15 | fractional bits - Q4.4) applied when light > threshold |
| 16 | |||
| 14 | - upisemi,lower-dark-gain: 8-bit dark gain compensation factor(4 int and 4 | 17 | - upisemi,lower-dark-gain: 8-bit dark gain compensation factor(4 int and 4 |
| 15 | fractional bits - Q4.4) applied when light < threshold | 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 | If the optional properties are not specified these factors will default to the | 28 | If the optional properties are not specified these factors will default to the |
| 18 | values in the below example. | 29 | values in the below example. |
| 19 | The glass-coef defaults to no compensation for the covering material. | 30 | The glass-coef defaults to no compensation for the covering material. |
| @@ -36,6 +36,7 @@ Accelerometers: · 35 unmodified lines | |||
| 36 | - st,lsm303dlm-accel | 36 | - st,lsm303dlm-accel |
| 37 | - st,lsm330-accel | 37 | - st,lsm330-accel |
| 38 | - st,lsm303agr-accel | 38 | - st,lsm303agr-accel |
| 39 | - st,lis2dh12-accel | ||
| 39 | 40 | ||
| 40 | Gyroscopes: | 41 | Gyroscopes: |
| 41 | - st,l3g4200d-gyro | 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 | source "drivers/iio/buffer/Kconfig" | 22 | source "drivers/iio/buffer/Kconfig" |
| 23 | endif # IIO_BUFFER | 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 | config IIO_TRIGGER | 33 | config IIO_TRIGGER |
| 26 | bool "Enable triggered sampling support" | 34 | bool "Enable triggered sampling support" |
| 27 | help | 35 | help |
| @@ -38,6 +46,14 @@ config IIO_CONSUMERS_PER_TRIGGER · 10 unmodified lines | |||
| 38 | This value controls the maximum number of consumers that a | 46 | This value controls the maximum number of consumers that a |
| 39 | given trigger may handle. Default is 2. | 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 | config IIO_TRIGGERED_EVENT | 57 | config IIO_TRIGGERED_EVENT |
| 42 | tristate | 58 | tristate |
| 43 | select IIO_TRIGGER | 59 | select IIO_TRIGGER |
| @@ -50,8 +66,10 @@ source "drivers/iio/amplifiers/Kconfig" · 6 unmodified lines | |||
| 50 | source "drivers/iio/chemical/Kconfig" | 66 | source "drivers/iio/chemical/Kconfig" |
| 51 | source "drivers/iio/common/Kconfig" | 67 | source "drivers/iio/common/Kconfig" |
| 52 | source "drivers/iio/dac/Kconfig" | 68 | source "drivers/iio/dac/Kconfig" |
| 69 | source "drivers/iio/dummy/Kconfig" | ||
| 53 | source "drivers/iio/frequency/Kconfig" | 70 | source "drivers/iio/frequency/Kconfig" |
| 54 | source "drivers/iio/gyro/Kconfig" | 71 | source "drivers/iio/gyro/Kconfig" |
| 72 | source "drivers/iio/health/Kconfig" | ||
| 55 | source "drivers/iio/humidity/Kconfig" | 73 | source "drivers/iio/humidity/Kconfig" |
| 56 | source "drivers/iio/imu/Kconfig" | 74 | source "drivers/iio/imu/Kconfig" |
| 57 | source "drivers/iio/light/Kconfig" | 75 | source "drivers/iio/light/Kconfig" |
| @@ -7,6 +7,8 @@ industrialio-y := industrialio-core.o industrialio-event.o inkern.o · 6 unmodified lines | |||
| 7 | industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o | 7 | industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o |
| 8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o | 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 | obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o | 12 | obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o |
| 11 | 13 | ||
| 12 | obj-y += accel/ | 14 | obj-y += accel/ |
| @@ -16,8 +18,10 @@ obj-y += buffer/ · 3 unmodified lines | |||
| 16 | obj-y += chemical/ | 18 | obj-y += chemical/ |
| 17 | obj-y += common/ | 19 | obj-y += common/ |
| 18 | obj-y += dac/ | 20 | obj-y += dac/ |
| 21 | obj-y += dummy/ | ||
| 19 | obj-y += gyro/ | 22 | obj-y += gyro/ |
| 20 | obj-y += frequency/ | 23 | obj-y += frequency/ |
| 24 | obj-y += health/ | ||
| 21 | obj-y += humidity/ | 25 | obj-y += humidity/ |
| 22 | obj-y += imu/ | 26 | obj-y += imu/ |
| 23 | obj-y += light/ | 27 | obj-y += light/ |
| @@ -64,7 +64,7 @@ config IIO_ST_ACCEL_3AXIS · 63 unmodified lines | |||
| 64 | help | 64 | help |
| 65 | Say yes here to build support for STMicroelectronics accelerometers: | 65 | Say yes here to build support for STMicroelectronics accelerometers: |
| 66 | LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC, | 66 | LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC, |
| 67 | LIS331DLH, LSM303DL, LSM303DLM, LSM330. | 67 | LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12. |
| 68 | 68 | ||
| 69 | This driver can also be built as a module. If so, these modules | 69 | This driver can also be built as a module. If so, these modules |
| 70 | will be created: | 70 | will be created: |
| @@ -107,6 +107,35 @@ config KXCJK1013 · 36 unmodified lines | |||
| 107 | To compile this driver as a module, choose M here: the module will | 107 | To compile this driver as a module, choose M here: the module will |
| 108 | be called kxcjk-1013. | 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 | config MMA8452 | 139 | config MMA8452 |
| 111 | tristate "Freescale MMA8452Q and similar Accelerometers Driver" | 140 | tristate "Freescale MMA8452Q and similar Accelerometers Driver" |
| 112 | depends on I2C | 141 | depends on I2C |
| @@ -158,6 +187,17 @@ config MXC4005 · 45 unmodified lines | |||
| 158 | To compile this driver as a module, choose M. The module will be | 187 | To compile this driver as a module, choose M. The module will be |
| 159 | called mxc4005. | 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 | config STK8312 | 201 | config STK8312 |
| 162 | tristate "Sensortek STK8312 3-Axis Accelerometer Driver" | 202 | tristate "Sensortek STK8312 3-Axis Accelerometer Driver" |
| 163 | depends on I2C | 203 | depends on I2C |
| @@ -10,6 +10,11 @@ obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o · 9 unmodified lines | |||
| 10 | obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o | 10 | obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o |
| 11 | obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o | 11 | obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o |
| 12 | obj-$(CONFIG_KXSD9) += kxsd9.o | 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 | obj-$(CONFIG_MMA8452) += mma8452.o | 18 | obj-$(CONFIG_MMA8452) += mma8452.o |
| 14 | 19 | ||
| 15 | obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o | 20 | obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o |
| @@ -17,6 +22,7 @@ obj-$(CONFIG_MMA9551) += mma9551.o · 1 unmodified line | |||
| 17 | obj-$(CONFIG_MMA9553) += mma9553.o | 22 | obj-$(CONFIG_MMA9553) += mma9553.o |
| 18 | 23 | ||
| 19 | obj-$(CONFIG_MXC4005) += mxc4005.o | 24 | obj-$(CONFIG_MXC4005) += mxc4005.o |
| 25 | obj-$(CONFIG_MXC6255) += mxc6255.o | ||
| 20 | 26 | ||
| 21 | obj-$(CONFIG_STK8312) += stk8312.o | 27 | obj-$(CONFIG_STK8312) += stk8312.o |
| 22 | obj-$(CONFIG_STK8BA50) += stk8ba50.o | 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 | ret = pm_runtime_set_active(dev); | 1626 | ret = pm_runtime_set_active(dev); |
| 1633 | if (ret) | 1627 | if (ret) |
| 1634 | goto err_iio_unregister; | 1628 | goto err_trigger_unregister; |
| 1635 | 1629 | ||
| 1636 | pm_runtime_enable(dev); | 1630 | pm_runtime_enable(dev); |
| 1637 | pm_runtime_set_autosuspend_delay(dev, BMC150_AUTO_SUSPEND_DELAY_MS); | 1631 | pm_runtime_set_autosuspend_delay(dev, BMC150_AUTO_SUSPEND_DELAY_MS); |
| 1638 | pm_runtime_use_autosuspend(dev); | 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 | return 0; | 1640 | return 0; |
| 1641 | 1641 | ||
| 1642 | err_iio_unregister: | ||
| 1643 | iio_device_unregister(indio_dev); | ||
| 1644 | err_trigger_unregister: | 1642 | err_trigger_unregister: |
| 1645 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); | 1643 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); |
| 1646 | err_buffer_cleanup: | 1644 | err_buffer_cleanup: |
| @@ -1655,12 +1653,12 @@ int bmc150_accel_core_remove(struct device *dev) · 8 unmodified lines | |||
| 1655 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | 1653 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
| 1656 | struct bmc150_accel_data *data = iio_priv(indio_dev); | 1654 | struct bmc150_accel_data *data = iio_priv(indio_dev); |
| 1657 | 1655 | ||
| 1656 | iio_device_unregister(indio_dev); | ||
| 1657 | |||
| 1658 | pm_runtime_disable(data->dev); | 1658 | pm_runtime_disable(data->dev); |
| 1659 | pm_runtime_set_suspended(data->dev); | 1659 | pm_runtime_set_suspended(data->dev); |
| 1660 | pm_runtime_put_noidle(data->dev); | 1660 | pm_runtime_put_noidle(data->dev); |
| 1661 | 1661 | ||
| 1662 | iio_device_unregister(indio_dev); | ||
| 1663 | |||
| 1664 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); | 1662 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); |
| 1665 | 1663 | ||
| 1666 | iio_triggered_buffer_cleanup(indio_dev); | 1664 | iio_triggered_buffer_cleanup(indio_dev); |
| @@ -1264,25 +1264,23 @@ static int kxcjk1013_probe(struct i2c_client *client, · 1263 unmodified lines | |||
| 1264 | goto err_trigger_unregister; | 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 | ret = pm_runtime_set_active(&client->dev); | 1267 | ret = pm_runtime_set_active(&client->dev); |
| 1274 | if (ret) | 1268 | if (ret) |
| 1275 | goto err_iio_unregister; | 1269 | goto err_buffer_cleanup; |
| 1276 | 1270 | ||
| 1277 | pm_runtime_enable(&client->dev); | 1271 | pm_runtime_enable(&client->dev); |
| 1278 | pm_runtime_set_autosuspend_delay(&client->dev, | 1272 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 1279 | KXCJK1013_SLEEP_DELAY_MS); | 1273 | KXCJK1013_SLEEP_DELAY_MS); |
| 1280 | pm_runtime_use_autosuspend(&client->dev); | 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 | return 0; | 1282 | return 0; |
| 1283 | 1283 | ||
| 1284 | err_iio_unregister: | ||
| 1285 | iio_device_unregister(indio_dev); | ||
| 1286 | err_buffer_cleanup: | 1284 | err_buffer_cleanup: |
| 1287 | if (data->dready_trig) | 1285 | if (data->dready_trig) |
| 1288 | iio_triggered_buffer_cleanup(indio_dev); | 1286 | iio_triggered_buffer_cleanup(indio_dev); |
| @@ -1302,12 +1300,12 @@ static int kxcjk1013_remove(struct i2c_client *client) · 13 unmodified lines | |||
| 1302 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | 1300 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 1303 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 1301 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1304 | 1302 | ||
| 1303 | iio_device_unregister(indio_dev); | ||
| 1304 | |||
| 1305 | pm_runtime_disable(&client->dev); | 1305 | pm_runtime_disable(&client->dev); |
| 1306 | pm_runtime_set_suspended(&client->dev); | 1306 | pm_runtime_set_suspended(&client->dev); |
| 1307 | pm_runtime_put_noidle(&client->dev); | 1307 | pm_runtime_put_noidle(&client->dev); |
| 1308 | 1308 | ||
| 1309 | iio_device_unregister(indio_dev); | ||
| 1310 | |||
| 1311 | if (data->dready_trig) { | 1309 | if (data->dready_trig) { |
| 1312 | iio_triggered_buffer_cleanup(indio_dev); | 1310 | iio_triggered_buffer_cleanup(indio_dev); |
| 1313 | iio_trigger_unregister(data->dready_trig); | 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 | #include <linux/iio/events.h> | 29 | #include <linux/iio/events.h> |
| 30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
| 32 | #include <linux/of_irq.h> | ||
| 32 | 33 | ||
| 33 | #define MMA8452_STATUS 0x00 | 34 | #define MMA8452_STATUS 0x00 |
| 34 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) | 35 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) |
| @@ -57,7 +58,6 @@ · 22 unmodified lines | |||
| 57 | #define MMA8452_FF_MT_COUNT 0x18 | 58 | #define MMA8452_FF_MT_COUNT 0x18 |
| 58 | #define MMA8452_TRANSIENT_CFG 0x1d | 59 | #define MMA8452_TRANSIENT_CFG 0x1d |
| 59 | #define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0) | 60 | #define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0) |
| 60 | #define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1) | ||
| 61 | #define MMA8452_TRANSIENT_CFG_ELE BIT(4) | 61 | #define MMA8452_TRANSIENT_CFG_ELE BIT(4) |
| 62 | #define MMA8452_TRANSIENT_SRC 0x1e | 62 | #define MMA8452_TRANSIENT_SRC 0x1e |
| 63 | #define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1) | 63 | #define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1) |
| @@ -143,6 +143,13 @@ struct mma_chip_info { · 79 unmodified lines | |||
| 143 | u8 ev_count; | 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 | static int mma8452_drdy(struct mma8452_data *data) | 153 | static int mma8452_drdy(struct mma8452_data *data) |
| 147 | { | 154 | { |
| 148 | int tries = 150; | 155 | int tries = 150; |
| @@ -816,31 +823,31 @@ static struct attribute_group mma8452_event_attribute_group = { · 667 unmodified lines | |||
| 816 | } | 823 | } |
| 817 | 824 | ||
| 818 | static const struct iio_chan_spec mma8452_channels[] = { | 825 | static const struct iio_chan_spec mma8452_channels[] = { |
| 819 | MMA8452_CHANNEL(X, 0, 12), | 826 | MMA8452_CHANNEL(X, idx_x, 12), |
| 820 | MMA8452_CHANNEL(Y, 1, 12), | 827 | MMA8452_CHANNEL(Y, idx_y, 12), |
| 821 | MMA8452_CHANNEL(Z, 2, 12), | 828 | MMA8452_CHANNEL(Z, idx_z, 12), |
| 822 | IIO_CHAN_SOFT_TIMESTAMP(3), | 829 | IIO_CHAN_SOFT_TIMESTAMP(idx_ts), |
| 823 | }; | 830 | }; |
| 824 | 831 | ||
| 825 | static const struct iio_chan_spec mma8453_channels[] = { | 832 | static const struct iio_chan_spec mma8453_channels[] = { |
| 826 | MMA8452_CHANNEL(X, 0, 10), | 833 | MMA8452_CHANNEL(X, idx_x, 10), |
| 827 | MMA8452_CHANNEL(Y, 1, 10), | 834 | MMA8452_CHANNEL(Y, idx_y, 10), |
| 828 | MMA8452_CHANNEL(Z, 2, 10), | 835 | MMA8452_CHANNEL(Z, idx_z, 10), |
| 829 | IIO_CHAN_SOFT_TIMESTAMP(3), | 836 | IIO_CHAN_SOFT_TIMESTAMP(idx_ts), |
| 830 | }; | 837 | }; |
| 831 | 838 | ||
| 832 | static const struct iio_chan_spec mma8652_channels[] = { | 839 | static const struct iio_chan_spec mma8652_channels[] = { |
| 833 | MMA8652_CHANNEL(X, 0, 12), | 840 | MMA8652_CHANNEL(X, idx_x, 12), |
| 834 | MMA8652_CHANNEL(Y, 1, 12), | 841 | MMA8652_CHANNEL(Y, idx_y, 12), |
| 835 | MMA8652_CHANNEL(Z, 2, 12), | 842 | MMA8652_CHANNEL(Z, idx_z, 12), |
| 836 | IIO_CHAN_SOFT_TIMESTAMP(3), | 843 | IIO_CHAN_SOFT_TIMESTAMP(idx_ts), |
| 837 | }; | 844 | }; |
| 838 | 845 | ||
| 839 | static const struct iio_chan_spec mma8653_channels[] = { | 846 | static const struct iio_chan_spec mma8653_channels[] = { |
| 840 | MMA8652_CHANNEL(X, 0, 10), | 847 | MMA8652_CHANNEL(X, idx_x, 10), |
| 841 | MMA8652_CHANNEL(Y, 1, 10), | 848 | MMA8652_CHANNEL(Y, idx_y, 10), |
| 842 | MMA8652_CHANNEL(Z, 2, 10), | 849 | MMA8652_CHANNEL(Z, idx_z, 10), |
| 843 | IIO_CHAN_SOFT_TIMESTAMP(3), | 850 | IIO_CHAN_SOFT_TIMESTAMP(idx_ts), |
| 844 | }; | 851 | }; |
| 845 | 852 | ||
| 846 | enum { | 853 | enum { |
| @@ -1130,13 +1137,21 @@ static int mma8452_probe(struct i2c_client *client, · 283 unmodified lines | |||
| 1130 | MMA8452_INT_FF_MT; | 1137 | MMA8452_INT_FF_MT; |
| 1131 | int enabled_interrupts = MMA8452_INT_TRANS | | 1138 | int enabled_interrupts = MMA8452_INT_TRANS | |
| 1132 | MMA8452_INT_FF_MT; | 1139 | MMA8452_INT_FF_MT; |
| 1140 | int irq2; | ||
| 1133 | 1141 | ||
| 1134 | /* Assume wired to INT1 pin */ | 1142 | irq2 = of_irq_get_byname(client->dev.of_node, "INT2"); |
| 1135 | ret = i2c_smbus_write_byte_data(client, | 1143 | |
| 1136 | MMA8452_CTRL_REG5, | 1144 | if (irq2 == client->irq) { |
| 1137 | supported_interrupts); | 1145 | dev_dbg(&client->dev, "using interrupt line INT2\n"); |
| 1138 | if (ret < 0) | 1146 | } else { |
| 1139 | return ret; | 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 | ret = i2c_smbus_write_byte_data(client, | 1156 | ret = i2c_smbus_write_byte_data(client, |
| 1142 | MMA8452_CTRL_REG4, | 1157 | MMA8452_CTRL_REG4, |
| @@ -495,25 +495,23 @@ static int mma9551_probe(struct i2c_client *client, · 494 unmodified lines | |||
| 495 | if (ret < 0) | 495 | if (ret < 0) |
| 496 | goto out_poweroff; | 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 | ret = pm_runtime_set_active(&client->dev); | 498 | ret = pm_runtime_set_active(&client->dev); |
| 505 | if (ret < 0) | 499 | if (ret < 0) |
| 506 | goto out_iio_unregister; | 500 | goto out_poweroff; |
| 507 | 501 | ||
| 508 | pm_runtime_enable(&client->dev); | 502 | pm_runtime_enable(&client->dev); |
| 509 | pm_runtime_set_autosuspend_delay(&client->dev, | 503 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 510 | MMA9551_AUTO_SUSPEND_DELAY_MS); | 504 | MMA9551_AUTO_SUSPEND_DELAY_MS); |
| 511 | pm_runtime_use_autosuspend(&client->dev); | 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 | return 0; | 513 | return 0; |
| 514 | 514 | ||
| 515 | out_iio_unregister: | ||
| 516 | iio_device_unregister(indio_dev); | ||
| 517 | out_poweroff: | 515 | out_poweroff: |
| 518 | mma9551_set_device_state(client, false); | 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 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | 523 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 526 | struct mma9551_data *data = iio_priv(indio_dev); | 524 | struct mma9551_data *data = iio_priv(indio_dev); |
| 527 | 525 | ||
| 526 | iio_device_unregister(indio_dev); | ||
| 527 | |||
| 528 | pm_runtime_disable(&client->dev); | 528 | pm_runtime_disable(&client->dev); |
| 529 | pm_runtime_set_suspended(&client->dev); | 529 | pm_runtime_set_suspended(&client->dev); |
| 530 | pm_runtime_put_noidle(&client->dev); | 530 | pm_runtime_put_noidle(&client->dev); |
| 531 | 531 | ||
| 532 | iio_device_unregister(indio_dev); | ||
| 533 | mutex_lock(&data->mutex); | 532 | mutex_lock(&data->mutex); |
| 534 | mma9551_set_device_state(data->client, false); | 533 | mma9551_set_device_state(data->client, false); |
| 535 | mutex_unlock(&data->mutex); | 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 | ret = pm_runtime_set_active(&client->dev); | 1136 | ret = pm_runtime_set_active(&client->dev); |
| 1143 | if (ret < 0) | 1137 | if (ret < 0) |
| 1144 | goto out_iio_unregister; | 1138 | goto out_poweroff; |
| 1145 | 1139 | ||
| 1146 | pm_runtime_enable(&client->dev); | 1140 | pm_runtime_enable(&client->dev); |
| 1147 | pm_runtime_set_autosuspend_delay(&client->dev, | 1141 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 1148 | MMA9551_AUTO_SUSPEND_DELAY_MS); | 1142 | MMA9551_AUTO_SUSPEND_DELAY_MS); |
| 1149 | pm_runtime_use_autosuspend(&client->dev); | 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 | return 0; | 1152 | return 0; |
| 1154 | 1153 | ||
| 1155 | out_iio_unregister: | ||
| 1156 | iio_device_unregister(indio_dev); | ||
| 1157 | out_poweroff: | 1154 | out_poweroff: |
| 1158 | mma9551_set_device_state(client, false); | 1155 | mma9551_set_device_state(client, false); |
| 1159 | return ret; | 1156 | return ret; |
| @@ -1164,11 +1161,12 @@ static int mma9553_remove(struct i2c_client *client) · 4 unmodified lines | |||
| 1164 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | 1161 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 1165 | struct mma9553_data *data = iio_priv(indio_dev); | 1162 | struct mma9553_data *data = iio_priv(indio_dev); |
| 1166 | 1163 | ||
| 1164 | iio_device_unregister(indio_dev); | ||
| 1165 | |||
| 1167 | pm_runtime_disable(&client->dev); | 1166 | pm_runtime_disable(&client->dev); |
| 1168 | pm_runtime_set_suspended(&client->dev); | 1167 | pm_runtime_set_suspended(&client->dev); |
| 1169 | pm_runtime_put_noidle(&client->dev); | 1168 | pm_runtime_put_noidle(&client->dev); |
| 1170 | 1169 | ||
| 1171 | iio_device_unregister(indio_dev); | ||
| 1172 | mutex_lock(&data->mutex); | 1170 | mutex_lock(&data->mutex); |
| 1173 | mma9551_set_device_state(data->client, false); | 1171 | mma9551_set_device_state(data->client, false); |
| 1174 | mutex_unlock(&data->mutex); | 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 | #define LSM303DLM_ACCEL_DEV_NAME "lsm303dlm_accel" | 27 | #define LSM303DLM_ACCEL_DEV_NAME "lsm303dlm_accel" |
| 28 | #define LSM330_ACCEL_DEV_NAME "lsm330_accel" | 28 | #define LSM330_ACCEL_DEV_NAME "lsm330_accel" |
| 29 | #define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel" | 29 | #define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel" |
| 30 | #define LIS2DH12_ACCEL_DEV_NAME "lis2dh12_accel" | ||
| 30 | 31 | ||
| 31 | /** | 32 | /** |
| 32 | * struct st_sensors_platform_data - default accel platform data | 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 | [3] = LSM330DL_ACCEL_DEV_NAME, | 232 | [3] = LSM330DL_ACCEL_DEV_NAME, |
| 233 | [4] = LSM330DLC_ACCEL_DEV_NAME, | 233 | [4] = LSM330DLC_ACCEL_DEV_NAME, |
| 234 | [5] = LSM303AGR_ACCEL_DEV_NAME, | 234 | [5] = LSM303AGR_ACCEL_DEV_NAME, |
| 235 | [6] = LIS2DH12_ACCEL_DEV_NAME, | ||
| 235 | }, | 236 | }, |
| 236 | .ch = (struct iio_chan_spec *)st_accel_12bit_channels, | 237 | .ch = (struct iio_chan_spec *)st_accel_12bit_channels, |
| 237 | .odr = { | 238 | .odr = { |
| @@ -72,6 +72,10 @@ static const struct of_device_id st_accel_of_match[] = { · 71 unmodified lines | |||
| 72 | .compatible = "st,lsm303agr-accel", | 72 | .compatible = "st,lsm303agr-accel", |
| 73 | .data = LSM303AGR_ACCEL_DEV_NAME, | 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 | MODULE_DEVICE_TABLE(of, st_accel_of_match); | 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 | { LSM303DLM_ACCEL_DEV_NAME }, | 125 | { LSM303DLM_ACCEL_DEV_NAME }, |
| 122 | { LSM330_ACCEL_DEV_NAME }, | 126 | { LSM330_ACCEL_DEV_NAME }, |
| 123 | { LSM303AGR_ACCEL_DEV_NAME }, | 127 | { LSM303AGR_ACCEL_DEV_NAME }, |
| 128 | { LIS2DH12_ACCEL_DEV_NAME }, | ||
| 124 | {}, | 129 | {}, |
| 125 | }; | 130 | }; |
| 126 | MODULE_DEVICE_TABLE(i2c, st_accel_id_table); | 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 | { LSM303DLM_ACCEL_DEV_NAME }, | 58 | { LSM303DLM_ACCEL_DEV_NAME }, |
| 59 | { LSM330_ACCEL_DEV_NAME }, | 59 | { LSM330_ACCEL_DEV_NAME }, |
| 60 | { LSM303AGR_ACCEL_DEV_NAME }, | 60 | { LSM303AGR_ACCEL_DEV_NAME }, |
| 61 | { LIS2DH12_ACCEL_DEV_NAME }, | ||
| 61 | {}, | 62 | {}, |
| 62 | }; | 63 | }; |
| 63 | MODULE_DEVICE_TABLE(spi, st_accel_id_table); | 64 | MODULE_DEVICE_TABLE(spi, st_accel_id_table); |
| @@ -194,6 +194,25 @@ config HI8435 · 193 unmodified lines | |||
| 194 | This driver can also be built as a module. If so, the module will be | 194 | This driver can also be built as a module. If so, the module will be |
| 195 | called hi8435. | 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 | config LP8788_ADC | 216 | config LP8788_ADC |
| 198 | tristate "LP8788 ADC driver" | 217 | tristate "LP8788 ADC driver" |
| 199 | depends on MFD_LP8788 | 218 | depends on MFD_LP8788 |
| @@ -275,6 +294,14 @@ config NAU7802 · 75 unmodified lines | |||
| 275 | To compile this driver as a module, choose M here: the | 294 | To compile this driver as a module, choose M here: the |
| 276 | module will be called nau7802. | 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 | config QCOM_SPMI_IADC | 305 | config QCOM_SPMI_IADC |
| 279 | tristate "Qualcomm SPMI PMIC current ADC" | 306 | tristate "Qualcomm SPMI PMIC current ADC" |
| 280 | depends on SPMI | 307 | depends on SPMI |
| @@ -324,15 +351,25 @@ config TI_ADC081C · 43 unmodified lines | |||
| 324 | called ti-adc081c. | 351 | called ti-adc081c. |
| 325 | 352 | ||
| 326 | config TI_ADC128S052 | 353 | config TI_ADC128S052 |
| 327 | tristate "Texas Instruments ADC128S052/ADC122S021" | 354 | tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021" |
| 328 | depends on SPI | 355 | depends on SPI |
| 329 | help | 356 | help |
| 330 | If you say yes here you get support for Texas Instruments ADC128S052 | 357 | If you say yes here you get support for Texas Instruments ADC128S052, |
| 331 | and ADC122S021 chips. | 358 | ADC122S021 and ADC124S021 chips. |
| 332 | 359 | ||
| 333 | This driver can also be built as a module. If so, the module will be | 360 | This driver can also be built as a module. If so, the module will be |
| 334 | called ti-adc128s052. | 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 | config TI_AM335X_ADC | 373 | config TI_AM335X_ADC |
| 337 | tristate "TI's AM335X ADC driver" | 374 | tristate "TI's AM335X ADC driver" |
| 338 | depends on MFD_TI_AM335X_TSCADC | 375 | depends on MFD_TI_AM335X_TSCADC |
| @@ -20,6 +20,8 @@ obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o · 19 unmodified lines | |||
| 20 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o | 20 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o |
| 21 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o | 21 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o |
| 22 | obj-$(CONFIG_HI8435) += hi8435.o | 22 | obj-$(CONFIG_HI8435) += hi8435.o |
| 23 | obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o | ||
| 24 | obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o | ||
| 23 | obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o | 25 | obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o |
| 24 | obj-$(CONFIG_MAX1027) += max1027.o | 26 | obj-$(CONFIG_MAX1027) += max1027.o |
| 25 | obj-$(CONFIG_MAX1363) += max1363.o | 27 | obj-$(CONFIG_MAX1363) += max1363.o |
| @@ -27,11 +29,13 @@ obj-$(CONFIG_MCP320X) += mcp320x.o · 1 unmodified line | |||
| 27 | obj-$(CONFIG_MCP3422) += mcp3422.o | 29 | obj-$(CONFIG_MCP3422) += mcp3422.o |
| 28 | obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o | 30 | obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o |
| 29 | obj-$(CONFIG_NAU7802) += nau7802.o | 31 | obj-$(CONFIG_NAU7802) += nau7802.o |
| 32 | obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o | ||
| 30 | obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o | 33 | obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o |
| 31 | obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o | 34 | obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o |
| 32 | obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o | 35 | obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o |
| 33 | obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o | 36 | obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o |
| 34 | obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o | 37 | obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o |
| 38 | obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o | ||
| 35 | obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o | 39 | obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o |
| 36 | obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o | 40 | obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o |
| 37 | obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o | 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 | *val2 = st-> | 478 | *val2 = st-> |
| 479 | scale_avail[(st->conf >> 8) & 0x7][1]; | 479 | scale_avail[(st->conf >> 8) & 0x7][1]; |
| 480 | return IIO_VAL_INT_PLUS_NANO; | 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 | break; | 484 | break; |
| 486 | case IIO_TEMP: | 485 | case IIO_TEMP: |
| 487 | /* 1170mV / 0.81 mV/C / 2^23 */ | 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 | return count; | 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 | if (!resolutions) | 746 | if (!resolutions) |
| 747 | return -ENOMEM; | 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 | #if defined(CONFIG_OF) | 355 | #if defined(CONFIG_OF) |
| 356 | static const struct of_device_id mcp320x_dt_ids[] = { | 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 | .compatible = "mcp3001", | 359 | .compatible = "mcp3001", |
| 359 | .data = &mcp320x_chip_infos[mcp3001], | 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 | .compatible = "mcp3301", | 383 | .compatible = "mcp3301", |
| 383 | .data = &mcp320x_chip_infos[mcp3301], | 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 | .attrs = mcp3422_attributes, | 305 | .attrs = mcp3422_attributes, |
| 306 | }; | 306 | }; |
| 307 | 307 | ||
| 308 | static const struct iio_chan_spec mcp3421_channels[] = { | ||
| 309 | MCP3422_CHAN(0), | ||
| 310 | }; | ||
| 311 | |||
| 308 | static const struct iio_chan_spec mcp3422_channels[] = { | 312 | static const struct iio_chan_spec mcp3422_channels[] = { |
| 309 | MCP3422_CHAN(0), | 313 | MCP3422_CHAN(0), |
| 310 | MCP3422_CHAN(1), | 314 | MCP3422_CHAN(1), |
| @@ -352,6 +356,10 @@ static int mcp3422_probe(struct i2c_client *client, · 41 unmodified lines | |||
| 352 | indio_dev->info = &mcp3422_info; | 356 | indio_dev->info = &mcp3422_info; |
| 353 | 357 | ||
| 354 | switch (adc->id) { | 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 | case 2: | 363 | case 2: |
| 356 | case 3: | 364 | case 3: |
| 357 | case 6: | 365 | case 6: |
| @@ -383,6 +391,7 @@ static int mcp3422_probe(struct i2c_client *client, · 25 unmodified lines | |||
| 383 | } | 391 | } |
| 384 | 392 | ||
| 385 | static const struct i2c_device_id mcp3422_id[] = { | 393 | static const struct i2c_device_id mcp3422_id[] = { |
| 394 | { "mcp3421", 1 }, | ||
| 386 | { "mcp3422", 2 }, | 395 | { "mcp3422", 2 }, |
| 387 | { "mcp3423", 3 }, | 396 | { "mcp3423", 3 }, |
| 388 | { "mcp3424", 4 }, | 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 | * Copyright (C) 2014 Angelo Compagnucci <angelo.compagnucci@gmail.com> | 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 | * Datasheets can be found here: | 5 | * Datasheets can be found here: |
| 6 | * http://www.ti.com/lit/ds/symlink/adc128s052.pdf | 6 | * http://www.ti.com/lit/ds/symlink/adc128s052.pdf |
| 7 | * http://www.ti.com/lit/ds/symlink/adc122s021.pdf | 7 | * http://www.ti.com/lit/ds/symlink/adc122s021.pdf |
| 8 | * http://www.ti.com/lit/ds/symlink/adc124s021.pdf | ||
| 8 | * | 9 | * |
| 9 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 10 | * it under the terms of the GNU General Public License version 2 as | 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 | ADC128_VOLTAGE_CHANNEL(1), | 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 | static const struct adc128_configuration adc128_config[] = { | 125 | static const struct adc128_configuration adc128_config[] = { |
| 118 | { adc128s052_channels, ARRAY_SIZE(adc128s052_channels) }, | 126 | { adc128s052_channels, ARRAY_SIZE(adc128s052_channels) }, |
| 119 | { adc122s021_channels, ARRAY_SIZE(adc122s021_channels) }, | 127 | { adc122s021_channels, ARRAY_SIZE(adc122s021_channels) }, |
| 128 | { adc124s021_channels, ARRAY_SIZE(adc124s021_channels) }, | ||
| 120 | }; | 129 | }; |
| 121 | 130 | ||
| 122 | static const struct iio_info adc128_info = { | 131 | static const struct iio_info adc128_info = { |
| @@ -177,6 +186,7 @@ static int adc128_remove(struct spi_device *spi) · 54 unmodified lines | |||
| 177 | static const struct of_device_id adc128_of_match[] = { | 186 | static const struct of_device_id adc128_of_match[] = { |
| 178 | { .compatible = "ti,adc128s052", }, | 187 | { .compatible = "ti,adc128s052", }, |
| 179 | { .compatible = "ti,adc122s021", }, | 188 | { .compatible = "ti,adc122s021", }, |
| 189 | { .compatible = "ti,adc124s021", }, | ||
| 180 | { /* sentinel */ }, | 190 | { /* sentinel */ }, |
| 181 | }; | 191 | }; |
| 182 | MODULE_DEVICE_TABLE(of, adc128_of_match); | 192 | MODULE_DEVICE_TABLE(of, adc128_of_match); |
| @@ -184,6 +194,7 @@ MODULE_DEVICE_TABLE(of, adc128_of_match); · 1 unmodified line | |||
| 184 | static const struct spi_device_id adc128_id[] = { | 194 | static const struct spi_device_id adc128_id[] = { |
| 185 | { "adc128s052", 0}, /* index into adc128_config */ | 195 | { "adc128s052", 0}, /* index into adc128_config */ |
| 186 | { "adc122s021", 1}, | 196 | { "adc122s021", 1}, |
| 197 | { "adc124s021", 2}, | ||
| 187 | { } | 198 | { } |
| 188 | }; | 199 | }; |
| 189 | MODULE_DEVICE_TABLE(spi, adc128_id); | 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 | return ret; | 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 | .preenable = &xadc_preenable, | 807 | .preenable = &xadc_preenable, |
| 808 | .postenable = &iio_triggered_buffer_postenable, | 808 | .postenable = &iio_triggered_buffer_postenable, |
| 809 | .predisable = &iio_triggered_buffer_predisable, | 809 | .predisable = &iio_triggered_buffer_predisable, |
| @@ -9,6 +9,26 @@ config IIO_BUFFER_CB · 8 unmodified lines | |||
| 9 | Should be selected by any drivers that do in-kernel push | 9 | Should be selected by any drivers that do in-kernel push |
| 10 | usage. That is, those where the data is pushed to the consumer. | 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 | config IIO_KFIFO_BUF | 32 | config IIO_KFIFO_BUF |
| 13 | tristate "Industrial I/O buffering based on kfifo" | 33 | tristate "Industrial I/O buffering based on kfifo" |
| 14 | help | 34 | help |
| @@ -4,5 +4,7 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | # When adding new entries keep the list in alphabetical order | 5 | # When adding new entries keep the list in alphabetical order |
| 6 | obj-$(CONFIG_IIO_BUFFER_CB) += industrialio-buffer-cb.o | 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 | obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o | 9 | obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o |
| 8 | obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o | 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 | menu "Chemical Sensors" | 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 | config VZ89X | 15 | config VZ89X |
| 8 | tristate "SGX Sensortech MiCS VZ89X VOC sensor" | 16 | tristate "SGX Sensortech MiCS VZ89X VOC sensor" |
| 9 | depends on I2C | 17 | depends on I2C |
| @@ -3,4 +3,5 @@ · 2 unmodified lines | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | # When adding new entries keep the list in alphabetical order | 5 | # When adding new entries keep the list in alphabetical order |
| 6 | obj-$(CONFIG_IAQCORE) += ams-iaq-core.o | ||
| 6 | obj-$(CONFIG_VZ89X) += vz89x.o | 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 | struct vz89x_data { | 34 | struct vz89x_data { |
| 35 | struct i2c_client *client; | 35 | struct i2c_client *client; |
| 36 | struct mutex lock; | 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 | u8 buffer[VZ89X_REG_MEASUREMENT_SIZE]; | 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 | return !!(data->buffer[VZ89X_REG_MEASUREMENT_SIZE - 1] > 0); | 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 | int ret; | 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 */ | 111 | msg[0].addr = client->addr; |
| 109 | if (!time_after(jiffies, data->last_update + HZ)) | 112 | msg[0].flags = client->flags; |
| 110 | return 0; | 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, | 123 | return (ret == 2) ? 0 : ret; |
| 113 | VZ89X_REG_MEASUREMENT, 0); | 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 | if (ret < 0) | 133 | if (ret < 0) |
| 115 | return ret; | 134 | return ret; |
| 116 | 135 | ||
| 117 | for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) { | 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 | if (ret < 0) | 138 | if (ret < 0) |
| 120 | return ret; | 139 | return ret; |
| 121 | data->buffer[i] = ret; | 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 | ret = vz89x_measurement_is_valid(data); | 158 | ret = vz89x_measurement_is_valid(data); |
| 125 | if (ret) | 159 | if (ret) |
| 126 | return -EAGAIN; | 160 | return -EAGAIN; |
| @@ -204,15 +238,19 @@ static int vz89x_probe(struct i2c_client *client, · 77 unmodified lines | |||
| 204 | struct iio_dev *indio_dev; | 238 | struct iio_dev *indio_dev; |
| 205 | struct vz89x_data *data; | 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 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | 241 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
| 212 | if (!indio_dev) | 242 | if (!indio_dev) |
| 213 | return -ENOMEM; | 243 | return -ENOMEM; |
| 214 | |||
| 215 | data = iio_priv(indio_dev); | 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 | i2c_set_clientdata(client, indio_dev); | 254 | i2c_set_clientdata(client, indio_dev); |
| 217 | data->client = client; | 255 | data->client = client; |
| 218 | data->last_update = jiffies - HZ; | 256 | data->last_update = jiffies - HZ; |
| @@ -18,9 +18,6 @@ · 17 unmodified lines | |||
| 18 | #include <asm/unaligned.h> | 18 | #include <asm/unaligned.h> |
| 19 | #include <linux/iio/common/st_sensors.h> | 19 | #include <linux/iio/common/st_sensors.h> |
| 20 | 20 | ||
| 21 | |||
| 22 | #define ST_SENSORS_WAI_ADDRESS 0x0f | ||
| 23 | |||
| 24 | static inline u32 st_sensors_get_unaligned_le24(const u8 *p) | 21 | static inline u32 st_sensors_get_unaligned_le24(const u8 *p) |
| 25 | { | 22 | { |
| 26 | return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8; | 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 | if (ret) | 435 | if (ret) |
| 436 | return ret; | 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 | if (prod_id != device_id) | 442 | if (prod_id != device_id) |
| 441 | dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", | 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 | goto err_trigger_unregister; | 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 | ret = pm_runtime_set_active(dev); | 1080 | ret = pm_runtime_set_active(dev); |
| 1087 | if (ret) | 1081 | if (ret) |
| 1088 | goto err_iio_unregister; | 1082 | goto err_buffer_cleanup; |
| 1089 | 1083 | ||
| 1090 | pm_runtime_enable(dev); | 1084 | pm_runtime_enable(dev); |
| 1091 | pm_runtime_set_autosuspend_delay(dev, | 1085 | pm_runtime_set_autosuspend_delay(dev, |
| 1092 | BMG160_AUTO_SUSPEND_DELAY_MS); | 1086 | BMG160_AUTO_SUSPEND_DELAY_MS); |
| 1093 | pm_runtime_use_autosuspend(dev); | 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 | return 0; | 1095 | return 0; |
| 1096 | 1096 | ||
| 1097 | err_iio_unregister: | ||
| 1098 | iio_device_unregister(indio_dev); | ||
| 1099 | err_buffer_cleanup: | 1097 | err_buffer_cleanup: |
| 1100 | iio_triggered_buffer_cleanup(indio_dev); | 1098 | iio_triggered_buffer_cleanup(indio_dev); |
| 1101 | err_trigger_unregister: | 1099 | err_trigger_unregister: |
| @@ -1113,11 +1111,12 @@ void bmg160_core_remove(struct device *dev) · 11 unmodified lines | |||
| 1113 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | 1111 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
| 1114 | struct bmg160_data *data = iio_priv(indio_dev); | 1112 | struct bmg160_data *data = iio_priv(indio_dev); |
| 1115 | 1113 | ||
| 1114 | iio_device_unregister(indio_dev); | ||
| 1115 | |||
| 1116 | pm_runtime_disable(dev); | 1116 | pm_runtime_disable(dev); |
| 1117 | pm_runtime_set_suspended(dev); | 1117 | pm_runtime_set_suspended(dev); |
| 1118 | pm_runtime_put_noidle(dev); | 1118 | pm_runtime_put_noidle(dev); |
| 1119 | 1119 | ||
| 1120 | iio_device_unregister(indio_dev); | ||
| 1121 | iio_triggered_buffer_cleanup(indio_dev); | 1120 | iio_triggered_buffer_cleanup(indio_dev); |
| 1122 | 1121 | ||
| 1123 | if (data->dready_trig) { | 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 | if (ret) | 288 | if (ret) |
| 289 | goto err_ret; | 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 | if (prod_id != device_id) | 297 | if (prod_id != device_id) |
| 294 | dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", | 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 | if (ret) | 765 | if (ret) |
| 766 | return ret; | 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 | if (prod_id != device_id) | 772 | if (prod_id != device_id) |
| 771 | dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", | 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 | ret = iio_device_register(data->acc_indio_dev); | 1401 | ret = iio_device_register(data->acc_indio_dev); |
| 1394 | if (ret < 0) { | 1402 | if (ret < 0) { |
| 1395 | dev_err(&client->dev, "Failed to register acc iio device\n"); | 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 | goto err_iio_unregister_acc; | 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 | return 0; | 1413 | return 0; |
| 1414 | 1414 | ||
| 1415 | err_iio_unregister_mag: | ||
| 1416 | iio_device_unregister(data->mag_indio_dev); | ||
| 1417 | err_iio_unregister_acc: | 1415 | err_iio_unregister_acc: |
| 1418 | iio_device_unregister(data->acc_indio_dev); | 1416 | iio_device_unregister(data->acc_indio_dev); |
| 1419 | err_buffer_cleanup_mag: | 1417 | err_buffer_cleanup_mag: |
| @@ -1437,13 +1435,13 @@ static int kmx61_remove(struct i2c_client *client) · 17 unmodified lines | |||
| 1437 | { | 1435 | { |
| 1438 | struct kmx61_data *data = i2c_get_clientdata(client); | 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 | pm_runtime_disable(&client->dev); | 1441 | pm_runtime_disable(&client->dev); |
| 1441 | pm_runtime_set_suspended(&client->dev); | 1442 | pm_runtime_set_suspended(&client->dev); |
| 1442 | pm_runtime_put_noidle(&client->dev); | 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 | if (client->irq > 0) { | 1445 | if (client->irq > 0) { |
| 1448 | iio_triggered_buffer_cleanup(data->acc_indio_dev); | 1446 | iio_triggered_buffer_cleanup(data->acc_indio_dev); |
| 1449 | iio_triggered_buffer_cleanup(data->mag_indio_dev); | 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 | INIT_LIST_HEAD(&buffer->buffer_list); | 193 | INIT_LIST_HEAD(&buffer->buffer_list); |
| 194 | init_waitqueue_head(&buffer->pollq); | 194 | init_waitqueue_head(&buffer->pollq); |
| 195 | kref_init(&buffer->ref); | 195 | kref_init(&buffer->ref); |
| 196 | buffer->watermark = 1; | 196 | if (!buffer->watermark) |
| 197 | buffer->watermark = 1; | ||
| 197 | } | 198 | } |
| 198 | EXPORT_SYMBOL(iio_buffer_init); | 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 | iio_buffer_deactivate(buffer); | 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 | static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, | 587 | static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, |
| 571 | struct iio_buffer *buffer) | 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 | struct iio_device_config { | 628 | struct iio_device_config { |
| 612 | unsigned int mode; | 629 | unsigned int mode; |
| 630 | unsigned int watermark; | ||
| 613 | const unsigned long *scan_mask; | 631 | const unsigned long *scan_mask; |
| 614 | unsigned int scan_bytes; | 632 | unsigned int scan_bytes; |
| 615 | bool scan_timestamp; | 633 | bool scan_timestamp; |
| @@ -642,10 +660,14 @@ static int iio_verify_update(struct iio_dev *indio_dev, · 26 unmodified lines | |||
| 642 | if (buffer == remove_buffer) | 660 | if (buffer == remove_buffer) |
| 643 | continue; | 661 | continue; |
| 644 | modes &= buffer->access->modes; | 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 | modes &= insert_buffer->access->modes; | 667 | modes &= insert_buffer->access->modes; |
| 668 | config->watermark = min(config->watermark, | ||
| 669 | insert_buffer->watermark); | ||
| 670 | } | ||
| 649 | 671 | ||
| 650 | /* Definitely possible for devices to support both of these. */ | 672 | /* Definitely possible for devices to support both of these. */ |
| 651 | if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) { | 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 | static int iio_enable_buffers(struct iio_dev *indio_dev, | 735 | static int iio_enable_buffers(struct iio_dev *indio_dev, |
| 714 | struct iio_device_config *config) | 736 | struct iio_device_config *config) |
| 715 | { | 737 | { |
| 738 | struct iio_buffer *buffer; | ||
| 716 | int ret; | 739 | int ret; |
| 717 | 740 | ||
| 718 | indio_dev->active_scan_mask = config->scan_mask; | 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 | indio_dev->currentmode = config->mode; | 779 | indio_dev->currentmode = config->mode; |
| 747 | 780 | ||
| 748 | if (indio_dev->setup_ops->postenable) { | 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 | if (ret) { | 783 | if (ret) { |
| 751 | dev_dbg(&indio_dev->dev, | 784 | dev_dbg(&indio_dev->dev, |
| 752 | "Buffer not started: postenable failed (%d)\n", ret); | 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 | return 0; | 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 | err_run_postdisable: | 796 | err_run_postdisable: |
| 760 | indio_dev->currentmode = INDIO_DIRECT_MODE; | 797 | indio_dev->currentmode = INDIO_DIRECT_MODE; |
| 761 | if (indio_dev->setup_ops->postdisable) | 798 | if (indio_dev->setup_ops->postdisable) |
| @@ -768,6 +805,7 @@ err_undo_config: · 6 unmodified lines | |||
| 768 | 805 | ||
| 769 | static int iio_disable_buffers(struct iio_dev *indio_dev) | 806 | static int iio_disable_buffers(struct iio_dev *indio_dev) |
| 770 | { | 807 | { |
| 808 | struct iio_buffer *buffer; | ||
| 771 | int ret = 0; | 809 | int ret = 0; |
| 772 | int ret2; | 810 | int ret2; |
| 773 | 811 | ||
| @@ -788,6 +826,12 @@ static int iio_disable_buffers(struct iio_dev *indio_dev) · 14 unmodified lines | |||
| 788 | ret = ret2; | 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 | indio_dev->currentmode = INDIO_DIRECT_MODE; | 835 | indio_dev->currentmode = INDIO_DIRECT_MODE; |
| 792 | 836 | ||
| 793 | if (indio_dev->setup_ops->postdisable) { | 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 | buffer->watermark = val; | 1020 | buffer->watermark = val; |
| 977 | |||
| 978 | if (indio_dev->info->hwfifo_set_watermark) | ||
| 979 | indio_dev->info->hwfifo_set_watermark(indio_dev, val); | ||
| 980 | out: | 1021 | out: |
| 981 | mutex_unlock(&indio_dev->mlock); | 1022 | mutex_unlock(&indio_dev->mlock); |
| 982 | 1023 | ||
| @@ -991,6 +1032,8 @@ static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, · 8 unmodified lines | |||
| 991 | iio_buffer_show_enable, iio_buffer_store_enable); | 1032 | iio_buffer_show_enable, iio_buffer_store_enable); |
| 992 | static DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR, | 1033 | static DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR, |
| 993 | iio_buffer_show_watermark, iio_buffer_store_watermark); | 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 | static struct attribute *iio_buffer_attrs[] = { | 1038 | static struct attribute *iio_buffer_attrs[] = { |
| 996 | &dev_attr_length.attr, | 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 | if (!buffer->access->set_length) | 1076 | if (!buffer->access->set_length) |
| 1034 | attr[0] = &dev_attr_length_ro.attr; | 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 | if (buffer->attrs) | 1082 | if (buffer->attrs) |
| 1037 | memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs, | 1083 | memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs, |
| 1038 | sizeof(struct attribute *) * attrcount); | 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 | return 0; | 470 | return 0; |
| 471 | } | 471 | } |
| 472 | } | 472 | } |
| 473 | EXPORT_SYMBOL_GPL(iio_format_value); | ||
| 473 | 474 | ||
| 474 | static ssize_t iio_read_channel_info(struct device *dev, | 475 | static ssize_t iio_read_channel_info(struct device *dev, |
| 475 | struct device_attribute *attr, | 476 | struct device_attribute *attr, |
| @@ -512,6 +513,12 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, · 36 unmodified lines | |||
| 512 | int i = 0, f = 0; | 513 | int i = 0, f = 0; |
| 513 | bool integer_part = true, negative = false; | 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 | if (str[0] == '-') { | 522 | if (str[0] == '-') { |
| 516 | negative = true; | 523 | negative = true; |
| 517 | str++; | 524 | str++; |
| @@ -571,6 +578,9 @@ static ssize_t iio_write_channel_info(struct device *dev, · 53 unmodified lines | |||
| 571 | if (indio_dev->info->write_raw_get_fmt) | 578 | if (indio_dev->info->write_raw_get_fmt) |
| 572 | switch (indio_dev->info->write_raw_get_fmt(indio_dev, | 579 | switch (indio_dev->info->write_raw_get_fmt(indio_dev, |
| 573 | this_attr->c, this_attr->address)) { | 580 | this_attr->c, this_attr->address)) { |
| 581 | case IIO_VAL_INT: | ||
| 582 | fract_mult = 0; | ||
| 583 | break; | ||
| 574 | case IIO_VAL_INT_PLUS_MICRO: | 584 | case IIO_VAL_INT_PLUS_MICRO: |
| 575 | fract_mult = 100000; | 585 | fract_mult = 100000; |
| 576 | break; | 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 | int iio_map_array_unregister(struct iio_dev *indio_dev) | 61 | int iio_map_array_unregister(struct iio_dev *indio_dev) |
| 62 | { | 62 | { |
| 63 | int ret = -ENODEV; | 63 | int ret = -ENODEV; |
| 64 | struct iio_map_internal *mapi; | 64 | struct iio_map_internal *mapi, *next; |
| 65 | struct list_head *pos, *tmp; | ||
| 66 | 65 | ||
| 67 | mutex_lock(&iio_map_list_lock); | 66 | mutex_lock(&iio_map_list_lock); |
| 68 | list_for_each_safe(pos, tmp, &iio_map_list) { | 67 | list_for_each_entry_safe(mapi, next, &iio_map_list, l) { |
| 69 | mapi = list_entry(pos, struct iio_map_internal, l); | ||
| 70 | if (indio_dev == mapi->indio_dev) { | 68 | if (indio_dev == mapi->indio_dev) { |
| 71 | list_del(&mapi->l); | 69 | list_del(&mapi->l); |
| 72 | kfree(mapi); | 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 | int ret; | 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 | return -EINVAL; | 748 | return -EINVAL; |
| 749 | }; | ||
| 748 | 750 | ||
| 749 | ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val); | 751 | ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val); |
| 750 | if (ret) { | 752 | if (ret) { |
| @@ -381,17 +381,23 @@ static int pa12203001_probe(struct i2c_client *client, · 380 unmodified lines | |||
| 381 | return ret; | 381 | return ret; |
| 382 | 382 | ||
| 383 | ret = pm_runtime_set_active(&client->dev); | 383 | ret = pm_runtime_set_active(&client->dev); |
| 384 | if (ret < 0) { | 384 | if (ret < 0) |
| 385 | pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE); | 385 | goto out_err; |
| 386 | return ret; | ||
| 387 | } | ||
| 388 | 386 | ||
| 389 | pm_runtime_enable(&client->dev); | 387 | pm_runtime_enable(&client->dev); |
| 390 | pm_runtime_set_autosuspend_delay(&client->dev, | 388 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 391 | PA12203001_SLEEP_DELAY_MS); | 389 | PA12203001_SLEEP_DELAY_MS); |
| 392 | pm_runtime_use_autosuspend(&client->dev); | 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 | static int pa12203001_remove(struct i2c_client *client) | 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 | dev_err(&client->dev, "rpr0521 chip init failed\n"); | 507 | dev_err(&client->dev, "rpr0521 chip init failed\n"); |
| 508 | return ret; | 508 | return ret; |
| 509 | } | 509 | } |
| 510 | ret = iio_device_register(indio_dev); | ||
| 511 | if (ret < 0) | ||
| 512 | return ret; | ||
| 513 | 510 | ||
| 514 | ret = pm_runtime_set_active(&client->dev); | 511 | ret = pm_runtime_set_active(&client->dev); |
| 515 | if (ret < 0) | 512 | if (ret < 0) |
| 516 | goto err_iio_unregister; | 513 | return ret; |
| 517 | 514 | ||
| 518 | pm_runtime_enable(&client->dev); | 515 | pm_runtime_enable(&client->dev); |
| 519 | pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS); | 516 | pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS); |
| 520 | pm_runtime_use_autosuspend(&client->dev); | 517 | pm_runtime_use_autosuspend(&client->dev); |
| 521 | 518 | ||
| 522 | return 0; | 519 | return iio_device_register(indio_dev); |
| 523 | |||
| 524 | err_iio_unregister: | ||
| 525 | iio_device_unregister(indio_dev); | ||
| 526 | return ret; | ||
| 527 | } | 520 | } |
| 528 | 521 | ||
| 529 | static int rpr0521_remove(struct i2c_client *client) | 522 | static int rpr0521_remove(struct i2c_client *client) |
| 530 | { | 523 | { |
| 531 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | 524 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 532 | 525 | ||
| 526 | iio_device_unregister(indio_dev); | ||
| 527 | |||
| 533 | pm_runtime_disable(&client->dev); | 528 | pm_runtime_disable(&client->dev); |
| 534 | pm_runtime_set_suspended(&client->dev); | 529 | pm_runtime_set_suspended(&client->dev); |
| 535 | pm_runtime_put_noidle(&client->dev); | 530 | pm_runtime_put_noidle(&client->dev); |
| 536 | 531 | ||
| 537 | iio_device_unregister(indio_dev); | ||
| 538 | rpr0521_poweroff(iio_priv(indio_dev)); | 532 | rpr0521_poweroff(iio_priv(indio_dev)); |
| 539 | 533 | ||
| 540 | return 0; | 534 | return 0; |
| @@ -20,14 +20,21 @@ · 19 unmodified lines | |||
| 20 | #include <linux/acpi.h> | 20 | #include <linux/acpi.h> |
| 21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
| 22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
| 23 | #include <linux/iio/events.h> | ||
| 23 | #include <linux/iio/iio.h> | 24 | #include <linux/iio/iio.h> |
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/irq.h> | ||
| 24 | #include <linux/iio/sysfs.h> | 27 | #include <linux/iio/sysfs.h> |
| 25 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
| 29 | #include <linux/pm.h> | ||
| 30 | #include <linux/pm_runtime.h> | ||
| 26 | 31 | ||
| 27 | #define US5182D_REG_CFG0 0x00 | 32 | #define US5182D_REG_CFG0 0x00 |
| 28 | #define US5182D_CFG0_ONESHOT_EN BIT(6) | 33 | #define US5182D_CFG0_ONESHOT_EN BIT(6) |
| 29 | #define US5182D_CFG0_SHUTDOWN_EN BIT(7) | 34 | #define US5182D_CFG0_SHUTDOWN_EN BIT(7) |
| 30 | #define US5182D_CFG0_WORD_ENABLE BIT(0) | 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 | #define US5182D_REG_CFG1 0x01 | 39 | #define US5182D_REG_CFG1 0x01 |
| 33 | #define US5182D_CFG1_ALS_RES16 BIT(4) | 40 | #define US5182D_CFG1_ALS_RES16 BIT(4) |
| @@ -39,6 +46,7 @@ · 5 unmodified lines | |||
| 39 | 46 | ||
| 40 | #define US5182D_REG_CFG3 0x03 | 47 | #define US5182D_REG_CFG3 0x03 |
| 41 | #define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5)) | 48 | #define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5)) |
| 49 | #define US5182D_CFG3_INT_SOURCE_PX BIT(3) | ||
| 42 | 50 | ||
| 43 | #define US5182D_REG_CFG4 0x10 | 51 | #define US5182D_REG_CFG4 0x10 |
| 44 | 52 | ||
| @@ -53,6 +61,13 @@ · 8 unmodified lines | |||
| 53 | #define US5182D_REG_AUTO_LDARK_GAIN 0x29 | 61 | #define US5182D_REG_AUTO_LDARK_GAIN 0x29 |
| 54 | #define US5182D_REG_AUTO_HDARK_GAIN 0x2a | 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 | #define US5182D_OPMODE_ALS 0x01 | 71 | #define US5182D_OPMODE_ALS 0x01 |
| 57 | #define US5182D_OPMODE_PX 0x02 | 72 | #define US5182D_OPMODE_PX 0x02 |
| 58 | #define US5182D_OPMODE_SHIFT 4 | 73 | #define US5182D_OPMODE_SHIFT 4 |
| @@ -81,6 +96,9 @@ · 22 unmodified lines | |||
| 81 | #define US5182D_READ_BYTE 1 | 96 | #define US5182D_READ_BYTE 1 |
| 82 | #define US5182D_READ_WORD 2 | 97 | #define US5182D_READ_WORD 2 |
| 83 | #define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */ | 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 | /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */ | 103 | /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */ |
| 86 | static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600, | 104 | static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600, |
| @@ -99,6 +117,11 @@ enum mode { · 12 unmodified lines | |||
| 99 | US5182D_PX_ONLY | 117 | US5182D_PX_ONLY |
| 100 | }; | 118 | }; |
| 101 | 119 | ||
| 120 | enum pmode { | ||
| 121 | US5182D_CONTINUOUS, | ||
| 122 | US5182D_ONESHOT | ||
| 123 | }; | ||
| 124 | |||
| 102 | struct us5182d_data { | 125 | struct us5182d_data { |
| 103 | struct i2c_client *client; | 126 | struct i2c_client *client; |
| 104 | struct mutex lock; | 127 | struct mutex lock; |
| @@ -111,7 +134,19 @@ struct us5182d_data { · 6 unmodified lines | |||
| 111 | u8 upper_dark_gain; | 134 | u8 upper_dark_gain; |
| 112 | u16 *us5182d_dark_ths; | 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 | u8 opmode; | 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 | static IIO_CONST_ATTR(in_illuminance_scale_available, | 152 | static IIO_CONST_ATTR(in_illuminance_scale_available, |
| @@ -130,16 +165,30 @@ static const struct { · 12 unmodified lines | |||
| 130 | u8 reg; | 165 | u8 reg; |
| 131 | u8 val; | 166 | u8 val; |
| 132 | } us5182d_regvals[] = { | 167 | } us5182d_regvals[] = { |
| 133 | {US5182D_REG_CFG0, (US5182D_CFG0_SHUTDOWN_EN | | 168 | {US5182D_REG_CFG0, US5182D_CFG0_WORD_ENABLE}, |
| 134 | US5182D_CFG0_WORD_ENABLE)}, | ||
| 135 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, | 169 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, |
| 136 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | | 170 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | |
| 137 | US5182D_CFG2_PXGAIN_DEFAULT)}, | 171 | US5182D_CFG2_PXGAIN_DEFAULT)}, |
| 138 | {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100}, | 172 | {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100 | |
| 139 | {US5182D_REG_MODE_STORE, US5182D_STORE_MODE}, | 173 | US5182D_CFG3_INT_SOURCE_PX}, |
| 140 | {US5182D_REG_CFG4, 0x00}, | 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 | static const struct iio_chan_spec us5182d_channels[] = { | 192 | static const struct iio_chan_spec us5182d_channels[] = { |
| 144 | { | 193 | { |
| 145 | .type = IIO_LIGHT, | 194 | .type = IIO_LIGHT, |
| @@ -149,40 +198,39 @@ static const struct iio_chan_spec us5182d_channels[] = { · 3 unmodified lines | |||
| 149 | { | 198 | { |
| 150 | .type = IIO_PROXIMITY, | 199 | .type = IIO_PROXIMITY, |
| 151 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | 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 | int ret; | 208 | int ret; |
| 158 | unsigned long result; | ||
| 159 | 209 | ||
| 160 | ret = i2c_smbus_read_word_data(data->client, | 210 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); |
| 161 | US5182D_REG_ADL); | ||
| 162 | if (ret < 0) | 211 | if (ret < 0) |
| 163 | return ret; | 212 | return ret; |
| 164 | 213 | ||
| 165 | result = ret * data->ga / US5182D_GA_RESOLUTION; | 214 | /* |
| 166 | if (result > 0xffff) | 215 | * In oneshot mode the chip will power itself down after taking the |
| 167 | result = 0xffff; | 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 | static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) | 223 | static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) |
| 173 | { | 224 | { |
| 174 | int ret; | 225 | int ret; |
| 175 | 226 | ||
| 227 | if (mode == data->opmode) | ||
| 228 | return 0; | ||
| 229 | |||
| 176 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | 230 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); |
| 177 | if (ret < 0) | 231 | if (ret < 0) |
| 178 | return ret; | 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 | /* update mode */ | 234 | /* update mode */ |
| 187 | ret = ret & ~US5182D_OPMODE_MASK; | 235 | ret = ret & ~US5182D_OPMODE_MASK; |
| 188 | ret = ret | (mode << US5182D_OPMODE_SHIFT); | 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 | if (ret < 0) | 244 | if (ret < 0) |
| 197 | return ret; | 245 | return ret; |
| 198 | 246 | ||
| 199 | if (mode == data->opmode) | ||
| 200 | return 0; | ||
| 201 | |||
| 202 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE, | 247 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE, |
| 203 | US5182D_STORE_MODE); | 248 | US5182D_STORE_MODE); |
| 204 | if (ret < 0) | 249 | if (ret < 0) |
| @@ -210,6 +255,177 @@ static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) · 5 unmodified lines | |||
| 210 | return 0; | 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 | static int us5182d_read_raw(struct iio_dev *indio_dev, | 429 | static int us5182d_read_raw(struct iio_dev *indio_dev, |
| 214 | struct iio_chan_spec const *chan, int *val, | 430 | struct iio_chan_spec const *chan, int *val, |
| 215 | int *val2, long mask) | 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 | switch (mask) { | 436 | switch (mask) { |
| 221 | case IIO_CHAN_INFO_RAW: | 437 | case IIO_CHAN_INFO_RAW: |
| 222 | switch (chan->type) { | 438 | ret = us5182d_read_value(data, chan); |
| 223 | case IIO_LIGHT: | 439 | if (ret < 0) |
| 224 | mutex_lock(&data->lock); | 440 | return ret; |
| 225 | ret = us5182d_set_opmode(data, US5182D_OPMODE_ALS); | 441 | *val = ret; |
| 226 | if (ret < 0) | 442 | return IIO_VAL_INT; |
| 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 | |||
| 252 | case IIO_CHAN_INFO_SCALE: | 443 | case IIO_CHAN_INFO_SCALE: |
| 253 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); | 444 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); |
| 254 | if (ret < 0) | 445 | if (ret < 0) |
| 255 | return ret; | 446 | return ret; |
| 256 | |||
| 257 | *val = 0; | 447 | *val = 0; |
| 258 | *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK]; | 448 | *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK]; |
| 259 | |||
| 260 | return IIO_VAL_INT_PLUS_MICRO; | 449 | return IIO_VAL_INT_PLUS_MICRO; |
| 261 | default: | 450 | default: |
| 262 | return -EINVAL; | 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 | return -EINVAL; | 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 | static const struct iio_info us5182d_info = { | 716 | static const struct iio_info us5182d_info = { |
| 347 | .driver_module = THIS_MODULE, | 717 | .driver_module = THIS_MODULE, |
| 348 | .read_raw = us5182d_read_raw, | 718 | .read_raw = us5182d_read_raw, |
| 349 | .write_raw = us5182d_write_raw, | 719 | .write_raw = us5182d_write_raw, |
| 350 | .attrs = &us5182d_attr_group, | 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 | static int us5182d_reset(struct iio_dev *indio_dev) | 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 | return ret; | 742 | return ret; |
| 369 | 743 | ||
| 370 | data->opmode = 0; | 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 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { | 749 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { |
| 372 | ret = i2c_smbus_write_byte_data(data->client, | 750 | ret = i2c_smbus_write_byte_data(data->client, |
| 373 | us5182d_regvals[i].reg, | 751 | us5182d_regvals[i].reg, |
| @@ -376,7 +754,17 @@ static int us5182d_init(struct iio_dev *indio_dev) · 2 unmodified lines | |||
| 376 | return ret; | 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 | static void us5182d_get_platform_data(struct iio_dev *indio_dev) | 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 | "upisemi,lower-dark-gain", | 787 | "upisemi,lower-dark-gain", |
| 400 | &data->lower_dark_gain)) | 788 | &data->lower_dark_gain)) |
| 401 | data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT; | 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 | static int us5182d_dark_gain_config(struct iio_dev *indio_dev) | 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 | US5182D_REG_DARK_AUTO_EN_DEFAULT); | 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 | static int us5182d_probe(struct i2c_client *client, | 846 | static int us5182d_probe(struct i2c_client *client, |
| 430 | const struct i2c_device_id *id) | 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 | return (ret < 0) ? ret : -ENODEV; | 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 | us5182d_get_platform_data(indio_dev); | 887 | us5182d_get_platform_data(indio_dev); |
| 461 | ret = us5182d_init(indio_dev); | 888 | ret = us5182d_init(indio_dev); |
| 462 | if (ret < 0) | 889 | if (ret < 0) |
| @@ -464,18 +891,73 @@ static int us5182d_probe(struct i2c_client *client, · 1 unmodified line | |||
| 464 | 891 | ||
| 465 | ret = us5182d_dark_gain_config(indio_dev); | 892 | ret = us5182d_dark_gain_config(indio_dev); |
| 466 | if (ret < 0) | 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 | static int us5182d_remove(struct i2c_client *client) | 919 | static int us5182d_remove(struct i2c_client *client) |
| 473 | { | 920 | { |
| 921 | struct us5182d_data *data = iio_priv(i2c_get_clientdata(client)); | ||
| 922 | |||
| 474 | iio_device_unregister(i2c_get_clientdata(client)); | 923 | iio_device_unregister(i2c_get_clientdata(client)); |
| 475 | return i2c_smbus_write_byte_data(client, US5182D_REG_CFG0, | 924 | |
| 476 | US5182D_CFG0_SHUTDOWN_EN); | 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 | static const struct acpi_device_id us5182d_acpi_match[] = { | 961 | static const struct acpi_device_id us5182d_acpi_match[] = { |
| 480 | { "USD5182", 0}, | 962 | { "USD5182", 0}, |
| 481 | {} | 963 | {} |
| @@ -493,6 +975,7 @@ MODULE_DEVICE_TABLE(i2c, us5182d_id); · 11 unmodified lines | |||
| 493 | static struct i2c_driver us5182d_driver = { | 975 | static struct i2c_driver us5182d_driver = { |
| 494 | .driver = { | 976 | .driver = { |
| 495 | .name = US5182D_DRV_NAME, | 977 | .name = US5182D_DRV_NAME, |
| 978 | .pm = &us5182d_pm_ops, | ||
| 496 | .acpi_match_table = ACPI_PTR(us5182d_acpi_match), | 979 | .acpi_match_table = ACPI_PTR(us5182d_acpi_match), |
| 497 | }, | 980 | }, |
| 498 | .probe = us5182d_probe, | 981 | .probe = us5182d_probe, |
| @@ -928,27 +928,24 @@ static int bmc150_magn_probe(struct i2c_client *client, · 927 unmodified lines | |||
| 928 | goto err_free_irq; | 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 | ret = pm_runtime_set_active(&client->dev); | 931 | ret = pm_runtime_set_active(&client->dev); |
| 938 | if (ret) | 932 | if (ret) |
| 939 | goto err_iio_unregister; | 933 | goto err_buffer_cleanup; |
| 940 | 934 | ||
| 941 | pm_runtime_enable(&client->dev); | 935 | pm_runtime_enable(&client->dev); |
| 942 | pm_runtime_set_autosuspend_delay(&client->dev, | 936 | pm_runtime_set_autosuspend_delay(&client->dev, |
| 943 | BMC150_MAGN_AUTO_SUSPEND_DELAY_MS); | 937 | BMC150_MAGN_AUTO_SUSPEND_DELAY_MS); |
| 944 | pm_runtime_use_autosuspend(&client->dev); | 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 | return 0; | 947 | return 0; |
| 949 | 948 | ||
| 950 | err_iio_unregister: | ||
| 951 | iio_device_unregister(indio_dev); | ||
| 952 | err_buffer_cleanup: | 949 | err_buffer_cleanup: |
| 953 | iio_triggered_buffer_cleanup(indio_dev); | 950 | iio_triggered_buffer_cleanup(indio_dev); |
| 954 | err_free_irq: | 951 | err_free_irq: |
| @@ -967,11 +964,12 @@ static int bmc150_magn_remove(struct i2c_client *client) · 12 unmodified lines | |||
| 967 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | 964 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 968 | struct bmc150_magn_data *data = iio_priv(indio_dev); | 965 | struct bmc150_magn_data *data = iio_priv(indio_dev); |
| 969 | 966 | ||
| 967 | iio_device_unregister(indio_dev); | ||
| 968 | |||
| 970 | pm_runtime_disable(&client->dev); | 969 | pm_runtime_disable(&client->dev); |
| 971 | pm_runtime_set_suspended(&client->dev); | 970 | pm_runtime_set_suspended(&client->dev); |
| 972 | pm_runtime_put_noidle(&client->dev); | 971 | pm_runtime_put_noidle(&client->dev); |
| 973 | 972 | ||
| 974 | iio_device_unregister(indio_dev); | ||
| 975 | iio_triggered_buffer_cleanup(indio_dev); | 973 | iio_triggered_buffer_cleanup(indio_dev); |
| 976 | 974 | ||
| 977 | if (client->irq > 0) | 975 | if (client->irq > 0) |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | |||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. | 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 | #include <linux/err.h> | 19 | #include <linux/err.h> |
| @@ -21,6 +21,7 @@ · 1 unmodified line | |||
| 21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
| 22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/pm_runtime.h> | ||
| 24 | #include <linux/iio/iio.h> | 25 | #include <linux/iio/iio.h> |
| 25 | #include <linux/iio/sysfs.h> | 26 | #include <linux/iio/sysfs.h> |
| 26 | #include <linux/iio/buffer.h> | 27 | #include <linux/iio/buffer.h> |
| @@ -35,8 +36,11 @@ · 8 unmodified lines | |||
| 35 | #define LIDAR_REG_STATUS_INVALID BIT(3) | 36 | #define LIDAR_REG_STATUS_INVALID BIT(3) |
| 36 | #define LIDAR_REG_STATUS_READY BIT(0) | 37 | #define LIDAR_REG_STATUS_READY BIT(0) |
| 37 | 38 | ||
| 38 | #define LIDAR_REG_DATA_HBYTE 0x0f | 39 | #define LIDAR_REG_DATA_HBYTE 0x0f |
| 39 | #define LIDAR_REG_DATA_LBYTE 0x10 | 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 | #define LIDAR_DRV_NAME "lidar" | 45 | #define LIDAR_DRV_NAME "lidar" |
| 42 | 46 | ||
| @@ -44,6 +48,9 @@ struct lidar_data { · 1 unmodified line | |||
| 44 | struct iio_dev *indio_dev; | 48 | struct iio_dev *indio_dev; |
| 45 | struct i2c_client *client; | 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 | u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */ | 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 | IIO_CHAN_SOFT_TIMESTAMP(1), | 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 | struct i2c_client *client = data->client; | 95 | struct i2c_client *client = data->client; |
| 68 | int ret; | 96 | int ret; |
| @@ -72,17 +100,35 @@ static int lidar_read_byte(struct lidar_data *data, int reg) · 3 unmodified lines | |||
| 72 | * so in turn i2c_smbus_read_byte_data cannot be used | 100 | * so in turn i2c_smbus_read_byte_data cannot be used |
| 73 | */ | 101 | */ |
| 74 | 102 | ||
| 75 | ret = i2c_smbus_write_byte(client, reg); | 103 | while (len--) { |
| 76 | if (ret < 0) { | 104 | ret = i2c_smbus_write_byte(client, reg++); |
| 77 | dev_err(&client->dev, "cannot write addr value"); | 105 | if (ret < 0) { |
| 78 | return ret; | 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 | if (ret < 0) | 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 | static inline int lidar_write_control(struct lidar_data *data, int val) | 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 | return i2c_smbus_write_byte_data(data->client, LIDAR_REG_CONTROL, val); | 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; | 141 | return i2c_smbus_write_byte_data(data->client, |
| 96 | int val; | 142 | LIDAR_REG_PWR_CONTROL, val); |
| 97 | 143 | } | |
| 98 | ret = lidar_read_byte(data, LIDAR_REG_DATA_HBYTE); | ||
| 99 | if (ret < 0) | ||
| 100 | return ret; | ||
| 101 | val = ret << 8; | ||
| 102 | 144 | ||
| 103 | ret = lidar_read_byte(data, LIDAR_REG_DATA_LBYTE); | 145 | static int lidar_read_measurement(struct lidar_data *data, u16 *reg) |
| 104 | if (ret < 0) | 146 | { |
| 105 | return ret; | 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; | 151 | if (!ret) |
| 108 | *reg = val; | 152 | *reg = be16_to_cpu(*reg); |
| 109 | 153 | ||
| 110 | return 0; | 154 | return ret; |
| 111 | } | 155 | } |
| 112 | 156 | ||
| 113 | static int lidar_get_measurement(struct lidar_data *data, u16 *reg) | 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 | int tries = 10; | 160 | int tries = 10; |
| 117 | int ret; | 161 | int ret; |
| 118 | 162 | ||
| 163 | pm_runtime_get_sync(&client->dev); | ||
| 164 | |||
| 119 | /* start sample */ | 165 | /* start sample */ |
| 120 | ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); | 166 | ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); |
| 121 | if (ret < 0) { | 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 | ret = -EIO; | 191 | ret = -EIO; |
| 146 | } | 192 | } |
| 193 | pm_runtime_mark_last_busy(&client->dev); | ||
| 194 | pm_runtime_put_autosuspend(&client->dev); | ||
| 147 | 195 | ||
| 148 | return ret; | 196 | return ret; |
| 149 | } | 197 | } |
| @@ -221,6 +269,16 @@ static int lidar_probe(struct i2c_client *client, · 71 unmodified lines | |||
| 221 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | 269 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
| 222 | if (!indio_dev) | 270 | if (!indio_dev) |
| 223 | return -ENOMEM; | 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 | indio_dev->info = &lidar_info; | 283 | indio_dev->info = &lidar_info; |
| 226 | indio_dev->name = LIDAR_DRV_NAME; | 284 | indio_dev->name = LIDAR_DRV_NAME; |
| @@ -228,7 +286,6 @@ static int lidar_probe(struct i2c_client *client, · 1 unmodified line | |||
| 228 | indio_dev->num_channels = ARRAY_SIZE(lidar_channels); | 286 | indio_dev->num_channels = ARRAY_SIZE(lidar_channels); |
| 229 | indio_dev->modes = INDIO_DIRECT_MODE; | 287 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 230 | 288 | ||
| 231 | data = iio_priv(indio_dev); | ||
| 232 | i2c_set_clientdata(client, indio_dev); | 289 | i2c_set_clientdata(client, indio_dev); |
| 233 | 290 | ||
| 234 | data->client = client; | 291 | data->client = client; |
| @@ -243,6 +300,17 @@ static int lidar_probe(struct i2c_client *client, · 8 unmodified lines | |||
| 243 | if (ret) | 300 | if (ret) |
| 244 | goto error_unreg_buffer; | 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 | return 0; | 314 | return 0; |
| 247 | 315 | ||
| 248 | error_unreg_buffer: | 316 | error_unreg_buffer: |
| @@ -258,6 +326,9 @@ static int lidar_remove(struct i2c_client *client) · 9 unmodified lines | |||
| 258 | iio_device_unregister(indio_dev); | 326 | iio_device_unregister(indio_dev); |
| 259 | iio_triggered_buffer_cleanup(indio_dev); | 327 | iio_triggered_buffer_cleanup(indio_dev); |
| 260 | 328 | ||
| 329 | pm_runtime_disable(&client->dev); | ||
| 330 | pm_runtime_set_suspended(&client->dev); | ||
| 331 | |||
| 261 | return 0; | 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 | MODULE_DEVICE_TABLE(of, lidar_dt_ids); | 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 | static struct i2c_driver lidar_driver = { | 374 | static struct i2c_driver lidar_driver = { |
| 277 | .driver = { | 375 | .driver = { |
| 278 | .name = LIDAR_DRV_NAME, | 376 | .name = LIDAR_DRV_NAME, |
| 279 | .of_match_table = of_match_ptr(lidar_dt_ids), | 377 | .of_match_table = of_match_ptr(lidar_dt_ids), |
| 378 | .pm = &lidar_pm_ops, | ||
| 280 | }, | 379 | }, |
| 281 | .probe = lidar_probe, | 380 | .probe = lidar_probe, |
| 282 | .remove = lidar_remove, | 381 | .remove = lidar_remove, |
| @@ -5,6 +5,16 @@ · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | menu "Triggers - standalone" | 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 | config IIO_INTERRUPT_TRIGGER | 18 | config IIO_INTERRUPT_TRIGGER |
| 9 | tristate "Generic interrupt trigger" | 19 | tristate "Generic interrupt trigger" |
| 10 | help | 20 | help |
| @@ -3,5 +3,7 @@ · 2 unmodified lines | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | # When adding new entries keep the list in alphabetical order | 5 | # When adding new entries keep the list in alphabetical order |
| 6 | |||
| 7 | obj-$(CONFIG_IIO_HRTIMER_TRIGGER) += iio-trig-hrtimer.o | ||
| 6 | obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o | 8 | obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o |
| 7 | obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o | 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 | exposes existing cma regions and doesn't reserve unecessarily memory when | 25 | exposes existing cma regions and doesn't reserve unecessarily memory when |
| 26 | booting a system which doesn't use ion. | 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 | Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc: | 36 | Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc: |
| 29 | Arve Hjønnevåg <arve@android.com> and Riley Andrews <riandrews@android.com> | 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 | static int __init ashmem_init(void) | 832 | static int __init ashmem_init(void) |
| 833 | { | 833 | { |
| 834 | int ret; | 834 | int ret = -ENOMEM; |
| 835 | 835 | ||
| 836 | ashmem_area_cachep = kmem_cache_create("ashmem_area_cache", | 836 | ashmem_area_cachep = kmem_cache_create("ashmem_area_cache", |
| 837 | sizeof(struct ashmem_area), | 837 | sizeof(struct ashmem_area), |
| 838 | 0, 0, NULL); | 838 | 0, 0, NULL); |
| 839 | if (unlikely(!ashmem_area_cachep)) { | 839 | if (unlikely(!ashmem_area_cachep)) { |
| 840 | pr_err("failed to create slab cache\n"); | 840 | pr_err("failed to create slab cache\n"); |
| 841 | return -ENOMEM; | 841 | goto out; |
| 842 | } | 842 | } |
| 843 | 843 | ||
| 844 | ashmem_range_cachep = kmem_cache_create("ashmem_range_cache", | 844 | ashmem_range_cachep = kmem_cache_create("ashmem_range_cache", |
| @@ -846,13 +846,13 @@ static int __init ashmem_init(void) · 1 unmodified line | |||
| 846 | 0, 0, NULL); | 846 | 0, 0, NULL); |
| 847 | if (unlikely(!ashmem_range_cachep)) { | 847 | if (unlikely(!ashmem_range_cachep)) { |
| 848 | pr_err("failed to create slab cache\n"); | 848 | pr_err("failed to create slab cache\n"); |
| 849 | return -ENOMEM; | 849 | goto out_free1; |
| 850 | } | 850 | } |
| 851 | 851 | ||
| 852 | ret = misc_register(&ashmem_misc); | 852 | ret = misc_register(&ashmem_misc); |
| 853 | if (unlikely(ret)) { | 853 | if (unlikely(ret)) { |
| 854 | pr_err("failed to register misc device!\n"); | 854 | pr_err("failed to register misc device!\n"); |
| 855 | return ret; | 855 | goto out_free2; |
| 856 | } | 856 | } |
| 857 | 857 | ||
| 858 | register_shrinker(&ashmem_shrinker); | 858 | register_shrinker(&ashmem_shrinker); |
| @@ -860,5 +860,12 @@ static int __init ashmem_init(void) · 1 unmodified line | |||
| 860 | pr_info("initialized\n"); | 860 | pr_info("initialized\n"); |
| 861 | 861 | ||
| 862 | return 0; | 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 | device_initcall(ashmem_init); | 871 | device_initcall(ashmem_init); |
| @@ -33,3 +33,10 @@ config ION_TEGRA · 32 unmodified lines | |||
| 33 | help | 33 | help |
| 34 | Choose this option if you wish to use ion on an nVidia Tegra. | 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 | obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o | 8 | obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o |
| 9 | obj-$(CONFIG_ION_TEGRA) += tegra/ | 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 | data32 = compat_ptr(arg); | 138 | data32 = compat_ptr(arg); |
| 139 | data = compat_alloc_user_space(sizeof(*data)); | 139 | data = compat_alloc_user_space(sizeof(*data)); |
| 140 | if (data == NULL) | 140 | if (!data) |
| 141 | return -EFAULT; | 141 | return -EFAULT; |
| 142 | 142 | ||
| 143 | err = compat_get_ion_allocation_data(data32, data); | 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 | data32 = compat_ptr(arg); | 157 | data32 = compat_ptr(arg); |
| 158 | data = compat_alloc_user_space(sizeof(*data)); | 158 | data = compat_alloc_user_space(sizeof(*data)); |
| 159 | if (data == NULL) | 159 | if (!data) |
| 160 | return -EFAULT; | 160 | return -EFAULT; |
| 161 | 161 | ||
| 162 | err = compat_get_ion_handle_data(data32, data); | 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 | data32 = compat_ptr(arg); | 174 | data32 = compat_ptr(arg); |
| 175 | data = compat_alloc_user_space(sizeof(*data)); | 175 | data = compat_alloc_user_space(sizeof(*data)); |
| 176 | if (data == NULL) | 176 | if (!data) |
| 177 | return -EFAULT; | 177 | return -EFAULT; |
| 178 | 178 | ||
| 179 | err = compat_get_ion_custom_data(data32, data); | 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 | #include <linux/profile.h> | 43 | #include <linux/profile.h> |
| 44 | #include <linux/notifier.h> | 44 | #include <linux/notifier.h> |
| 45 | 45 | ||
| 46 | static uint32_t lowmem_debug_level = 1; | 46 | static u32 lowmem_debug_level = 1; |
| 47 | static short lowmem_adj[6] = { | 47 | static short lowmem_adj[6] = { |
| 48 | 0, | 48 | 0, |
| 49 | 1, | 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 | lowmem_print(3, "lowmem_scan %lu, %x, ofree %d %d, ma %hd\n", | 107 | lowmem_print(3, "lowmem_scan %lu, %x, ofree %d %d, ma %hd\n", |
| 108 | sc->nr_to_scan, sc->gfp_mask, other_free, | 108 | sc->nr_to_scan, sc->gfp_mask, other_free, |
| 109 | other_file, min_score_adj); | 109 | other_file, min_score_adj); |
| 110 | 110 | ||
| 111 | if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) { | 111 | if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) { |
| 112 | lowmem_print(5, "lowmem_scan %lu, %x, return 0\n", | 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 | return NULL; | 43 | return NULL; |
| 44 | 44 | ||
| 45 | obj = kzalloc(size, GFP_KERNEL); | 45 | obj = kzalloc(size, GFP_KERNEL); |
| 46 | if (obj == NULL) | 46 | if (!obj) |
| 47 | return NULL; | 47 | return NULL; |
| 48 | 48 | ||
| 49 | kref_init(&obj->kref); | 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 | return NULL; | 130 | return NULL; |
| 131 | 131 | ||
| 132 | pt = kzalloc(size, GFP_KERNEL); | 132 | pt = kzalloc(size, GFP_KERNEL); |
| 133 | if (pt == NULL) | 133 | if (!pt) |
| 134 | return NULL; | 134 | return NULL; |
| 135 | 135 | ||
| 136 | spin_lock_irqsave(&obj->child_list_lock, flags); | 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 | struct sync_fence *fence; | 155 | struct sync_fence *fence; |
| 156 | 156 | ||
| 157 | fence = kzalloc(size, GFP_KERNEL); | 157 | fence = kzalloc(size, GFP_KERNEL); |
| 158 | if (fence == NULL) | 158 | if (!fence) |
| 159 | return NULL; | 159 | return NULL; |
| 160 | 160 | ||
| 161 | fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops, | 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 | /* TODO: implement a create which takes more that one sync_pt */ | 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 | struct sync_fence *fence; | 193 | struct sync_fence *fence; |
| 194 | 194 | ||
| 195 | fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name); | 195 | fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name); |
| 196 | if (fence == NULL) | 196 | if (!fence) |
| 197 | return NULL; | 197 | return NULL; |
| 198 | 198 | ||
| 199 | fence->num_fences = 1; | 199 | fence->num_fences = 1; |
| 200 | atomic_set(&fence->status, 1); | 200 | atomic_set(&fence->status, 1); |
| 201 | 201 | ||
| 202 | fence->cbs[0].sync_pt = &pt->base; | 202 | fence->cbs[0].sync_pt = pt; |
| 203 | fence->cbs[0].fence = fence; | 203 | fence->cbs[0].fence = fence; |
| 204 | if (fence_add_callback(&pt->base, &fence->cbs[0].cb, | 204 | if (fence_add_callback(pt, &fence->cbs[0].cb, fence_check_cb_func)) |
| 205 | fence_check_cb_func)) | ||
| 206 | atomic_dec(&fence->status); | 205 | atomic_dec(&fence->status); |
| 207 | 206 | ||
| 208 | sync_fence_debug_add(fence); | 207 | sync_fence_debug_add(fence); |
| 209 | 208 | ||
| 210 | return fence; | 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 | EXPORT_SYMBOL(sync_fence_create); | 217 | EXPORT_SYMBOL(sync_fence_create); |
| 213 | 218 | ||
| 214 | struct sync_fence *sync_fence_fdget(int fd) | 219 | struct sync_fence *sync_fence_fdget(int fd) |
| 215 | { | 220 | { |
| 216 | struct file *file = fget(fd); | 221 | struct file *file = fget(fd); |
| 217 | 222 | ||
| 218 | if (file == NULL) | 223 | if (!file) |
| 219 | return NULL; | 224 | return NULL; |
| 220 | 225 | ||
| 221 | if (file->f_op != &sync_fence_fops) | 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 | unsigned long size = offsetof(struct sync_fence, cbs[num_fences]); | 267 | unsigned long size = offsetof(struct sync_fence, cbs[num_fences]); |
| 263 | 268 | ||
| 264 | fence = sync_fence_alloc(size, name); | 269 | fence = sync_fence_alloc(size, name); |
| 265 | if (fence == NULL) | 270 | if (!fence) |
| 266 | return NULL; | 271 | return NULL; |
| 267 | 272 | ||
| 268 | atomic_set(&fence->status, num_fences); | 273 | atomic_set(&fence->status, num_fences); |
| @@ -313,7 +318,7 @@ struct sync_fence *sync_fence_merge(const char *name, · 44 unmodified lines | |||
| 313 | EXPORT_SYMBOL(sync_fence_merge); | 318 | EXPORT_SYMBOL(sync_fence_merge); |
| 314 | 319 | ||
| 315 | int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode, | 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 | struct sync_fence_waiter *wait; | 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 | EXPORT_SYMBOL(sync_fence_wait_async); | 358 | EXPORT_SYMBOL(sync_fence_wait_async); |
| 354 | 359 | ||
| 355 | int sync_fence_cancel_async(struct sync_fence *fence, | 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 | unsigned long flags; | 363 | unsigned long flags; |
| 359 | int ret = 0; | 364 | int ret = 0; |
| @@ -519,12 +524,10 @@ static const struct fence_ops android_fence_ops = { · 159 unmodified lines | |||
| 519 | static void sync_fence_free(struct kref *kref) | 524 | static void sync_fence_free(struct kref *kref) |
| 520 | { | 525 | { |
| 521 | struct sync_fence *fence = container_of(kref, struct sync_fence, kref); | 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 | for (i = 0; i < fence->num_fences; ++i) { | 529 | for (i = 0; i < fence->num_fences; ++i) { |
| 525 | if (status) | 530 | fence_remove_callback(fence->cbs[i].sync_pt, &fence->cbs[i].cb); |
| 526 | fence_remove_callback(fence->cbs[i].sync_pt, | ||
| 527 | &fence->cbs[i].cb); | ||
| 528 | fence_put(fence->cbs[i].sync_pt); | 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 | fence2 = sync_fence_fdget(data.fd2); | 588 | fence2 = sync_fence_fdget(data.fd2); |
| 586 | if (fence2 == NULL) { | 589 | if (!fence2) { |
| 587 | err = -ENOENT; | 590 | err = -ENOENT; |
| 588 | goto err_put_fd; | 591 | goto err_put_fd; |
| 589 | } | 592 | } |
| 590 | 593 | ||
| 591 | data.name[sizeof(data.name) - 1] = '\0'; | 594 | data.name[sizeof(data.name) - 1] = '\0'; |
| 592 | fence3 = sync_fence_merge(data.name, fence, fence2); | 595 | fence3 = sync_fence_merge(data.name, fence, fence2); |
| 593 | if (fence3 == NULL) { | 596 | if (!fence3) { |
| 594 | err = -ENOMEM; | 597 | err = -ENOMEM; |
| 595 | goto err_put_fence2; | 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 | size = 4096; | 669 | size = 4096; |
| 667 | 670 | ||
| 668 | data = kzalloc(size, GFP_KERNEL); | 671 | data = kzalloc(size, GFP_KERNEL); |
| 669 | if (data == NULL) | 672 | if (!data) |
| 670 | return -ENOMEM; | 673 | return -ENOMEM; |
| 671 | 674 | ||
| 672 | strlcpy(data->name, fence->name, sizeof(data->name)); | 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 | struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt); | 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 | * API for sync_fence consumers | 268 | * API for sync_fence consumers |
| 259 | */ | 269 | */ |
| @@ -82,36 +82,42 @@ static const char *sync_status_str(int status) · 81 unmodified lines | |||
| 82 | return "error"; | 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 | int status = 1; | 87 | int status = 1; |
| 88 | struct sync_timeline *parent = sync_pt_parent(pt); | ||
| 89 | 88 | ||
| 90 | if (fence_is_signaled_locked(&pt->base)) | 89 | if (fence_is_signaled_locked(pt)) |
| 91 | status = pt->base.status; | 90 | status = pt->status; |
| 92 | 91 | ||
| 93 | seq_printf(s, " %s%spt %s", | 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 | fence ? "_" : "", | 95 | fence ? "_" : "", |
| 96 | sync_status_str(status)); | 96 | sync_status_str(status)); |
| 97 | 97 | ||
| 98 | if (status <= 0) { | 98 | if (status <= 0) { |
| 99 | struct timespec64 ts64 = | 99 | struct timespec64 ts64 = |
| 100 | ktime_to_timespec64(pt->base.timestamp); | 100 | ktime_to_timespec64(pt->timestamp); |
| 101 | 101 | ||
| 102 | seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); | 102 | seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | if (parent->ops->timeline_value_str && | 105 | if ((!fence || pt->ops->timeline_value_str) && |
| 106 | parent->ops->pt_value_str) { | 106 | pt->ops->fence_value_str) { |
| 107 | char value[64]; | 107 | char value[64]; |
| 108 | bool success; | ||
| 108 | 109 | ||
| 109 | parent->ops->pt_value_str(pt, value, sizeof(value)); | 110 | pt->ops->fence_value_str(pt, value, sizeof(value)); |
| 110 | seq_printf(s, ": %s", value); | 111 | success = strlen(value); |
| 111 | if (fence) { | 112 | |
| 112 | parent->ops->timeline_value_str(parent, value, | 113 | if (success) |
| 113 | sizeof(value)); | 114 | seq_printf(s, ": %s", value); |
| 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 | list_for_each(pos, &obj->child_list_head) { | 144 | list_for_each(pos, &obj->child_list_head) { |
| 139 | struct sync_pt *pt = | 145 | struct sync_pt *pt = |
| 140 | container_of(pos, struct sync_pt, child_list); | 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 | spin_unlock_irqrestore(&obj->child_list_lock, flags); | 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 | sync_status_str(atomic_read(&fence->status))); | 159 | sync_status_str(atomic_read(&fence->status))); |
| 154 | 160 | ||
| 155 | for (i = 0; i < fence->num_fences; ++i) { | 161 | for (i = 0; i < fence->num_fences; ++i) { |
| 156 | struct sync_pt *pt = | 162 | sync_print_pt(s, fence->cbs[i].sync_pt, true); |
| 157 | container_of(fence->cbs[i].sync_pt, | ||
| 158 | struct sync_pt, base); | ||
| 159 | |||
| 160 | sync_print_pt(s, pt, true); | ||
| 161 | } | 163 | } |
| 162 | 164 | ||
| 163 | spin_lock_irqsave(&fence->wq.lock, flags); | 165 | spin_lock_irqsave(&fence->wq.lock, flags); |
| @@ -25,7 +25,6 @@ · 24 unmodified lines | |||
| 25 | #include "timed_output.h" | 25 | #include "timed_output.h" |
| 26 | #include "timed_gpio.h" | 26 | #include "timed_gpio.h" |
| 27 | 27 | ||
| 28 | |||
| 29 | struct timed_gpio_data { | 28 | struct timed_gpio_data { |
| 30 | struct timed_output_dev dev; | 29 | struct timed_output_dev dev; |
| 31 | struct hrtimer timer; | 30 | struct hrtimer timer; |
| @@ -76,8 +75,8 @@ static void gpio_enable(struct timed_output_dev *dev, int value) · 44 unmodified lines | |||
| 76 | value = data->max_timeout; | 75 | value = data->max_timeout; |
| 77 | 76 | ||
| 78 | hrtimer_start(&data->timer, | 77 | hrtimer_start(&data->timer, |
| 79 | ktime_set(value / 1000, (value % 1000) * 1000000), | 78 | ktime_set(value / 1000, (value % 1000) * 1000000), |
| 80 | HRTIMER_MODE_REL); | 79 | HRTIMER_MODE_REL); |
| 81 | } | 80 | } |
| 82 | 81 | ||
| 83 | spin_unlock_irqrestore(&data->lock, flags); | 82 | spin_unlock_irqrestore(&data->lock, flags); |
| @@ -94,8 +93,8 @@ static int timed_gpio_probe(struct platform_device *pdev) · 10 unmodified lines | |||
| 94 | return -EBUSY; | 93 | return -EBUSY; |
| 95 | 94 | ||
| 96 | gpio_data = devm_kzalloc(&pdev->dev, | 95 | gpio_data = devm_kzalloc(&pdev->dev, |
| 97 | sizeof(struct timed_gpio_data) * pdata->num_gpios, | 96 | sizeof(*gpio_data) * pdata->num_gpios, |
| 98 | GFP_KERNEL); | 97 | GFP_KERNEL); |
| 99 | if (!gpio_data) | 98 | if (!gpio_data) |
| 100 | return -ENOMEM; | 99 | return -ENOMEM; |
| 101 | 100 | ||
| @@ -104,7 +103,7 @@ static int timed_gpio_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 104 | gpio_dat = &gpio_data[i]; | 103 | gpio_dat = &gpio_data[i]; |
| 105 | 104 | ||
| 106 | hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, | 105 | hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, |
| 107 | HRTIMER_MODE_REL); | 106 | HRTIMER_MODE_REL); |
| 108 | gpio_dat->timer.function = gpio_timer_func; | 107 | gpio_dat->timer.function = gpio_timer_func; |
| 109 | spin_lock_init(&gpio_dat->lock); | 108 | spin_lock_init(&gpio_dat->lock); |
| 110 | 109 | ||
| @@ -737,15 +737,23 @@ config COMEDI_ADL_PCI9118 · 736 unmodified lines | |||
| 737 | called adl_pci9118. | 737 | called adl_pci9118. |
| 738 | 738 | ||
| 739 | config COMEDI_ADV_PCI1710 | 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 | select COMEDI_8254 | 741 | select COMEDI_8254 |
| 742 | ---help--- | 742 | ---help--- |
| 743 | Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711, | 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 | To compile this driver as a module, choose M here: the module will be | 746 | To compile this driver as a module, choose M here: the module will be |
| 747 | called adv_pci1710. | 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 | config COMEDI_ADV_PCI1723 | 757 | config COMEDI_ADV_PCI1723 |
| 750 | tristate "Advantech PCI-1723 support" | 758 | tristate "Advantech PCI-1723 support" |
| 751 | ---help--- | 759 | ---help--- |
| @@ -764,6 +772,14 @@ config COMEDI_ADV_PCI1724 · 12 unmodified lines | |||
| 764 | To compile this driver as a module, choose M here: the module will be | 772 | To compile this driver as a module, choose M here: the module will be |
| 765 | called adv_pci1724. | 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 | config COMEDI_ADV_PCI_DIO | 783 | config COMEDI_ADV_PCI_DIO |
| 768 | tristate "Advantech PCI DIO card support" | 784 | tristate "Advantech PCI DIO card support" |
| 769 | select COMEDI_8254 | 785 | select COMEDI_8254 |
| @@ -771,8 +787,8 @@ config COMEDI_ADV_PCI_DIO · 1 unmodified line | |||
| 771 | ---help--- | 787 | ---help--- |
| 772 | Enable support for Advantech PCI DIO cards | 788 | Enable support for Advantech PCI DIO cards |
| 773 | PCI-1730, PCI-1733, PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, | 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, | 790 | PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754, PCI-1756 and |
| 775 | PCI-1760 and PCI-1762 | 791 | PCI-1762 |
| 776 | 792 | ||
| 777 | To compile this driver as a module, choose M here: the module will be | 793 | To compile this driver as a module, choose M here: the module will be |
| 778 | called adv_pci_dio. | 794 | called adv_pci_dio. |
| @@ -1,20 +1,20 @@ | |||
| 1 | /* | 1 | /* |
| 2 | include/comedi.h (installed as /usr/include/comedi.h) | 2 | * include/comedi.h (installed as /usr/include/comedi.h) |
| 3 | header file for comedi | 3 | * header file for comedi |
| 4 | 4 | * | |
| 5 | COMEDI - Linux Control and Measurement Device Interface | 5 | * COMEDI - Linux Control and Measurement Device Interface |
| 6 | Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> | 6 | * Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> |
| 7 | 7 | * | |
| 8 | This program is free software; you can redistribute it and/or modify | 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 | 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 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | (at your option) any later version. | 11 | * (at your option) any later version. |
| 12 | 12 | * | |
| 13 | This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #ifndef _COMEDI_H | 19 | #ifndef _COMEDI_H |
| 20 | #define _COMEDI_H | 20 | #define _COMEDI_H |
| @@ -28,9 +28,9 @@ · 7 unmodified lines | |||
| 28 | #define COMEDI_MAJOR 98 | 28 | #define COMEDI_MAJOR 98 |
| 29 | 29 | ||
| 30 | /* | 30 | /* |
| 31 | maximum number of minor devices. This can be increased, although | 31 | * maximum number of minor devices. This can be increased, although |
| 32 | kernel structures are currently statically allocated, thus you | 32 | * kernel structures are currently statically allocated, thus you |
| 33 | don't want this to be much more than you actually use. | 33 | * don't want this to be much more than you actually use. |
| 34 | */ | 34 | */ |
| 35 | #define COMEDI_NDEVICES 16 | 35 | #define COMEDI_NDEVICES 16 |
| 36 | 36 | ||
| @@ -63,21 +63,21 @@ · 26 unmodified lines | |||
| 63 | /* packs and unpacks a channel/range number */ | 63 | /* packs and unpacks a channel/range number */ |
| 64 | 64 | ||
| 65 | #define CR_PACK(chan, rng, aref) \ | 65 | #define CR_PACK(chan, rng, aref) \ |
| 66 | ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan)) | 66 | ((((aref) & 0x3) << 24) | (((rng) & 0xff) << 16) | (chan)) |
| 67 | #define CR_PACK_FLAGS(chan, range, aref, flags) \ | 67 | #define CR_PACK_FLAGS(chan, range, aref, flags) \ |
| 68 | (CR_PACK(chan, range, aref) | ((flags) & CR_FLAGS_MASK)) | 68 | (CR_PACK(chan, range, aref) | ((flags) & CR_FLAGS_MASK)) |
| 69 | 69 | ||
| 70 | #define CR_CHAN(a) ((a)&0xffff) | 70 | #define CR_CHAN(a) ((a) & 0xffff) |
| 71 | #define CR_RANGE(a) (((a)>>16)&0xff) | 71 | #define CR_RANGE(a) (((a) >> 16) & 0xff) |
| 72 | #define CR_AREF(a) (((a)>>24)&0x03) | 72 | #define CR_AREF(a) (((a) >> 24) & 0x03) |
| 73 | 73 | ||
| 74 | #define CR_FLAGS_MASK 0xfc000000 | 74 | #define CR_FLAGS_MASK 0xfc000000 |
| 75 | #define CR_ALT_FILTER (1<<26) | 75 | #define CR_ALT_FILTER (1 << 26) |
| 76 | #define CR_DITHER CR_ALT_FILTER | 76 | #define CR_DITHER CR_ALT_FILTER |
| 77 | #define CR_DEGLITCH CR_ALT_FILTER | 77 | #define CR_DEGLITCH CR_ALT_FILTER |
| 78 | #define CR_ALT_SOURCE (1<<27) | 78 | #define CR_ALT_SOURCE (1 << 27) |
| 79 | #define CR_EDGE (1<<30) | 79 | #define CR_EDGE (1 << 30) |
| 80 | #define CR_INVERT (1<<31) | 80 | #define CR_INVERT (1 << 31) |
| 81 | 81 | ||
| 82 | #define AREF_GROUND 0x00 /* analog ref = analog ground */ | 82 | #define AREF_GROUND 0x00 /* analog ref = analog ground */ |
| 83 | #define AREF_COMMON 0x01 /* analog ref = analog common */ | 83 | #define AREF_COMMON 0x01 /* analog ref = analog common */ |
| @@ -114,11 +114,11 @@ · 30 unmodified lines | |||
| 114 | 114 | ||
| 115 | #define INSN_READ (0 | INSN_MASK_READ) | 115 | #define INSN_READ (0 | INSN_MASK_READ) |
| 116 | #define INSN_WRITE (1 | INSN_MASK_WRITE) | 116 | #define INSN_WRITE (1 | INSN_MASK_WRITE) |
| 117 | #define INSN_BITS (2 | INSN_MASK_READ|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) | 118 | #define INSN_CONFIG (3 | INSN_MASK_READ | INSN_MASK_WRITE) |
| 119 | #define INSN_GTOD (4 | INSN_MASK_READ|INSN_MASK_SPECIAL) | 119 | #define INSN_GTOD (4 | INSN_MASK_READ | INSN_MASK_SPECIAL) |
| 120 | #define INSN_WAIT (5 | INSN_MASK_WRITE|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) | 121 | #define INSN_INTTRIG (6 | INSN_MASK_WRITE | INSN_MASK_SPECIAL) |
| 122 | 122 | ||
| 123 | /* trigger flags */ | 123 | /* trigger flags */ |
| 124 | /* These flags are used in comedi_trig structures */ | 124 | /* These flags are used in comedi_trig structures */ |
| @@ -279,7 +279,8 @@ enum configuration_ids { · 154 unmodified lines | |||
| 279 | INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ | 279 | INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ |
| 280 | /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ | 280 | /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ |
| 281 | /* Get size in bytes of subdevice's on-board fifos used during | 281 | /* Get size in bytes of subdevice's on-board fifos used during |
| 282 | * streaming input/output */ | 282 | * streaming input/output |
| 283 | */ | ||
| 283 | INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, | 284 | INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, |
| 284 | INSN_CONFIG_SET_COUNTER_MODE = 4097, | 285 | INSN_CONFIG_SET_COUNTER_MODE = 4097, |
| 285 | /* INSN_CONFIG_8254_SET_MODE is deprecated */ | 286 | /* INSN_CONFIG_8254_SET_MODE is deprecated */ |
| @@ -292,7 +293,8 @@ enum configuration_ids { · 6 unmodified lines | |||
| 292 | INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ | 293 | INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ |
| 293 | INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ | 294 | INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ |
| 294 | /* sets H bridge: duty cycle and sign bit for a relay at the | 295 | /* sets H bridge: duty cycle and sign bit for a relay at the |
| 295 | * same time */ | 296 | * same time |
| 297 | */ | ||
| 296 | INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, | 298 | INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, |
| 297 | /* gets H bridge data: duty cycle and the sign bit */ | 299 | /* gets H bridge data: duty cycle and the sign bit */ |
| 298 | INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 | 300 | INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 |
| @@ -502,13 +504,13 @@ struct comedi_bufinfo { · 203 unmodified lines | |||
| 502 | 504 | ||
| 503 | /* range stuff */ | 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) | 509 | #define RANGE_OFFSET(a) (((a) >> 16) & 0xffff) |
| 508 | #define RANGE_LENGTH(b) ((b)&0xffff) | 510 | #define RANGE_LENGTH(b) ((b) & 0xffff) |
| 509 | 511 | ||
| 510 | #define RF_UNIT(flags) ((flags)&0xff) | 512 | #define RF_UNIT(flags) ((flags) & 0xff) |
| 511 | #define RF_EXTERNAL (1<<8) | 513 | #define RF_EXTERNAL (1 << 8) |
| 512 | 514 | ||
| 513 | #define UNIT_volt 0 | 515 | #define UNIT_volt 0 |
| 514 | #define UNIT_mA 1 | 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. | 526 | * 8254 specific configuration. |
| 525 | 527 | * | |
| 526 | It supports two config commands: | 528 | * It supports two config commands: |
| 527 | 529 | * | |
| 528 | 0 ID: INSN_CONFIG_SET_COUNTER_MODE | 530 | * 0 ID: INSN_CONFIG_SET_COUNTER_MODE |
| 529 | 1 8254 Mode | 531 | * 1 8254 Mode |
| 530 | I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 | 532 | * I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 |
| 531 | OR'ed with: | 533 | * OR'ed with: |
| 532 | I8254_BCD, I8254_BINARY | 534 | * I8254_BCD, I8254_BINARY |
| 533 | 535 | * | |
| 534 | 0 ID: INSN_CONFIG_8254_READ_STATUS | 536 | * 0 ID: INSN_CONFIG_8254_READ_STATUS |
| 535 | 1 <-- Status byte returned here. | 537 | * 1 <-- Status byte returned here. |
| 536 | B7 = Output | 538 | * B7 = Output |
| 537 | B6 = NULL Count | 539 | * B6 = NULL Count |
| 538 | B5 - B0 Current mode. | 540 | * B5 - B0 Current mode. |
| 539 | 541 | */ | |
| 540 | */ | ||
| 541 | 542 | ||
| 542 | enum i8254_mode { | 543 | enum i8254_mode { |
| 543 | I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ | 544 | I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ |
| @@ -545,18 +546,20 @@ enum i8254_mode { · 1 unmodified line | |||
| 545 | I8254_MODE2 = (2 << 1), /* Rate generator */ | 546 | I8254_MODE2 = (2 << 1), /* Rate generator */ |
| 546 | I8254_MODE3 = (3 << 1), /* Square wave mode */ | 547 | I8254_MODE3 = (3 << 1), /* Square wave mode */ |
| 547 | I8254_MODE4 = (4 << 1), /* Software triggered strobe */ | 548 | I8254_MODE4 = (4 << 1), /* Software triggered strobe */ |
| 548 | I8254_MODE5 = (5 << 1), /* Hardware triggered strobe | 549 | /* Hardware triggered strobe (retriggerable) */ |
| 549 | * (retriggerable) */ | 550 | I8254_MODE5 = (5 << 1), |
| 550 | I8254_BCD = 1, /* use binary-coded decimal instead of binary | 551 | /* Use binary-coded decimal instead of binary (pretty useless) */ |
| 551 | * (pretty useless) */ | 552 | I8254_BCD = 1, |
| 552 | I8254_BINARY = 0 | 553 | I8254_BINARY = 0 |
| 553 | }; | 554 | }; |
| 554 | 555 | ||
| 555 | #define NI_USUAL_PFI_SELECT(x) (((x) < 10) ? (0x1 + (x)) : (0xb + (x))) | 556 | #define NI_USUAL_PFI_SELECT(x) (((x) < 10) ? (0x1 + (x)) : (0xb + (x))) |
| 556 | #define NI_USUAL_RTSI_SELECT(x) (((x) < 7) ? (0xb + (x)) : 0x1b) | 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 | /* |
| 559 | * INSN_CONFIG_SET_COUNTER_MODE */ | 560 | * mode bits for NI general-purpose counters, set with |
| 561 | * INSN_CONFIG_SET_COUNTER_MODE | ||
| 562 | */ | ||
| 560 | #define NI_GPCT_COUNTING_MODE_SHIFT 16 | 563 | #define NI_GPCT_COUNTING_MODE_SHIFT 16 |
| 561 | #define NI_GPCT_INDEX_PHASE_BITSHIFT 20 | 564 | #define NI_GPCT_INDEX_PHASE_BITSHIFT 20 |
| 562 | #define NI_GPCT_COUNTING_DIRECTION_SHIFT 24 | 565 | #define NI_GPCT_COUNTING_DIRECTION_SHIFT 24 |
| @@ -624,8 +627,10 @@ enum ni_gpct_mode_bits { · 61 unmodified lines | |||
| 624 | NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 | 627 | NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 |
| 625 | }; | 628 | }; |
| 626 | 629 | ||
| 627 | /* Bits for setting a clock source with | 630 | /* |
| 628 | * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. */ | 631 | * Bits for setting a clock source with |
| 632 | * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. | ||
| 633 | */ | ||
| 629 | enum ni_gpct_clock_source_bits { | 634 | enum ni_gpct_clock_source_bits { |
| 630 | NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, | 635 | NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, |
| 631 | NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, | 636 | NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, |
| @@ -656,9 +661,11 @@ enum ni_gpct_clock_source_bits { · 24 unmodified lines | |||
| 656 | /* no pfi on NI 660x */ | 661 | /* no pfi on NI 660x */ |
| 657 | #define NI_GPCT_PFI_CLOCK_SRC_BITS(x) (0x20 + (x)) | 662 | #define NI_GPCT_PFI_CLOCK_SRC_BITS(x) (0x20 + (x)) |
| 658 | 663 | ||
| 659 | /* Possibilities for setting a gate source with | 664 | /* |
| 660 | INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. | 665 | * Possibilities for setting a gate source with |
| 661 | May be bitwise-or'd with CR_EDGE or CR_INVERT. */ | 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 | enum ni_gpct_gate_select { | 669 | enum ni_gpct_gate_select { |
| 663 | /* m-series gates */ | 670 | /* m-series gates */ |
| 664 | NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, | 671 | NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, |
| @@ -675,9 +682,11 @@ enum ni_gpct_gate_select { · 10 unmodified lines | |||
| 675 | /* more gates for 660x "second gate" */ | 682 | /* more gates for 660x "second gate" */ |
| 676 | NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, | 683 | NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, |
| 677 | NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e, | 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 | * we should add them here with an offset of 0x300 when | 687 | * we should add them here with an offset of 0x300 when |
| 680 | * known. */ | 688 | * known. |
| 689 | */ | ||
| 681 | NI_GPCT_DISABLED_GATE_SELECT = 0x8000, | 690 | NI_GPCT_DISABLED_GATE_SELECT = 0x8000, |
| 682 | }; | 691 | }; |
| 683 | 692 | ||
| @@ -686,8 +695,10 @@ enum ni_gpct_gate_select { · 2 unmodified lines | |||
| 686 | #define NI_GPCT_PFI_GATE_SELECT(x) NI_USUAL_PFI_SELECT(x) | 695 | #define NI_GPCT_PFI_GATE_SELECT(x) NI_USUAL_PFI_SELECT(x) |
| 687 | #define NI_GPCT_UP_DOWN_PIN_GATE_SELECT(x) (0x202 + (x)) | 696 | #define NI_GPCT_UP_DOWN_PIN_GATE_SELECT(x) (0x202 + (x)) |
| 688 | 697 | ||
| 689 | /* Possibilities for setting a source with | 698 | /* |
| 690 | INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */ | 699 | * Possibilities for setting a source with |
| 700 | * INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. | ||
| 701 | */ | ||
| 691 | enum ni_gpct_other_index { | 702 | enum ni_gpct_other_index { |
| 692 | NI_GPCT_SOURCE_ENCODER_A, | 703 | NI_GPCT_SOURCE_ENCODER_A, |
| 693 | NI_GPCT_SOURCE_ENCODER_B, | 704 | NI_GPCT_SOURCE_ENCODER_B, |
| @@ -702,18 +713,24 @@ enum ni_gpct_other_select { · 8 unmodified lines | |||
| 702 | 713 | ||
| 703 | #define NI_GPCT_PFI_OTHER_SELECT(x) NI_USUAL_PFI_SELECT(x) | 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 | 716 | /* |
| 706 | INSN_CONFIG_ARM */ | 717 | * start sources for ni general-purpose counters for use with |
| 718 | * INSN_CONFIG_ARM | ||
| 719 | */ | ||
| 707 | enum ni_gpct_arm_source { | 720 | enum ni_gpct_arm_source { |
| 708 | NI_GPCT_ARM_IMMEDIATE = 0x0, | 721 | NI_GPCT_ARM_IMMEDIATE = 0x0, |
| 709 | NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter | 722 | /* |
| 710 | * and the adjacent paired | 723 | * Start both the counter and the adjacent pared |
| 711 | * counter simultaneously */ | 724 | * counter simultaneously |
| 712 | /* NI doesn't document bits for selecting hardware arm triggers. | 725 | */ |
| 726 | NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, | ||
| 727 | /* | ||
| 728 | * NI doesn't document bits for selecting hardware arm triggers. | ||
| 713 | * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least | 729 | * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least |
| 714 | * significant bits (3 bits for 660x or 5 bits for m-series) | 730 | * significant bits (3 bits for 660x or 5 bits for m-series) |
| 715 | * through to the hardware. This will at least allow someone to | 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 | NI_GPCT_ARM_UNKNOWN = 0x1000, | 734 | NI_GPCT_ARM_UNKNOWN = 0x1000, |
| 718 | }; | 735 | }; |
| 719 | 736 | ||
| @@ -728,8 +745,10 @@ enum ni_gpct_filter_select { · 8 unmodified lines | |||
| 728 | NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 | 745 | NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 |
| 729 | }; | 746 | }; |
| 730 | 747 | ||
| 731 | /* PFI digital filtering options for ni m-series for use with | 748 | /* |
| 732 | * INSN_CONFIG_FILTER. */ | 749 | * PFI digital filtering options for ni m-series for use with |
| 750 | * INSN_CONFIG_FILTER. | ||
| 751 | */ | ||
| 733 | enum ni_pfi_filter_select { | 752 | enum ni_pfi_filter_select { |
| 734 | NI_PFI_FILTER_OFF = 0x0, | 753 | NI_PFI_FILTER_OFF = 0x0, |
| 735 | NI_PFI_FILTER_125ns = 0x1, | 754 | NI_PFI_FILTER_125ns = 0x1, |
| @@ -740,9 +759,11 @@ enum ni_pfi_filter_select { · 4 unmodified lines | |||
| 740 | /* master clock sources for ni mio boards and INSN_CONFIG_SET_CLOCK_SRC */ | 759 | /* master clock sources for ni mio boards and INSN_CONFIG_SET_CLOCK_SRC */ |
| 741 | enum ni_mio_clock_source { | 760 | enum ni_mio_clock_source { |
| 742 | NI_MIO_INTERNAL_CLOCK = 0, | 761 | NI_MIO_INTERNAL_CLOCK = 0, |
| 743 | NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use | 762 | /* |
| 744 | NI_MIO_PLL_RTSI_CLOCK() */ | 763 | * Doesn't work for m-series, use NI_MIO_PLL_RTSI_CLOCK() |
| 745 | /* the NI_MIO_PLL_* sources are m-series only */ | 764 | * the NI_MIO_PLL_* sources are m-series only |
| 765 | */ | ||
| 766 | NI_MIO_RTSI_CLOCK = 1, | ||
| 746 | NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, | 767 | NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, |
| 747 | NI_MIO_PLL_PXI10_CLOCK = 3, | 768 | NI_MIO_PLL_PXI10_CLOCK = 3, |
| 748 | NI_MIO_PLL_RTSI0_CLOCK = 4 | 769 | NI_MIO_PLL_RTSI0_CLOCK = 4 |
| @@ -750,9 +771,11 @@ enum ni_mio_clock_source { · 1 unmodified line | |||
| 750 | 771 | ||
| 751 | #define NI_MIO_PLL_RTSI_CLOCK(x) (NI_MIO_PLL_RTSI0_CLOCK + (x)) | 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. | 774 | /* |
| 754 | The numbers assigned are not arbitrary, they correspond to the bits required | 775 | * Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. |
| 755 | to program the board. */ | 776 | * The numbers assigned are not arbitrary, they correspond to the bits required |
| 777 | * to program the board. | ||
| 778 | */ | ||
| 756 | enum ni_rtsi_routing { | 779 | enum ni_rtsi_routing { |
| 757 | NI_RTSI_OUTPUT_ADR_START1 = 0, | 780 | NI_RTSI_OUTPUT_ADR_START1 = 0, |
| 758 | NI_RTSI_OUTPUT_ADR_START2 = 1, | 781 | NI_RTSI_OUTPUT_ADR_START2 = 1, |
| @@ -763,17 +786,19 @@ enum ni_rtsi_routing { · 4 unmodified lines | |||
| 763 | NI_RTSI_OUTPUT_G_GATE0 = 6, | 786 | NI_RTSI_OUTPUT_G_GATE0 = 6, |
| 764 | NI_RTSI_OUTPUT_RGOUT0 = 7, | 787 | NI_RTSI_OUTPUT_RGOUT0 = 7, |
| 765 | NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, | 788 | NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, |
| 766 | NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI | 789 | /* Pre-m-series always have RTSI clock on line 7 */ |
| 767 | * clock on line 7 */ | 790 | NI_RTSI_OUTPUT_RTSI_OSC = 12 |
| 768 | }; | 791 | }; |
| 769 | 792 | ||
| 770 | #define NI_RTSI_OUTPUT_RTSI_BRD(x) (NI_RTSI_OUTPUT_RTSI_BRD_0 + (x)) | 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 | * INSN_CONFIG_SET_ROUTING. These numbers are also returned by | 797 | * INSN_CONFIG_SET_ROUTING. These numbers are also returned by |
| 774 | * INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though their routing | 798 | * INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though their routing |
| 775 | * cannot be changed. The numbers assigned are not arbitrary, they correspond | 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 | enum ni_pfi_routing { | 802 | enum ni_pfi_routing { |
| 778 | NI_PFI_OUTPUT_PFI_DEFAULT = 0, | 803 | NI_PFI_OUTPUT_PFI_DEFAULT = 0, |
| 779 | NI_PFI_OUTPUT_AI_START1 = 1, | 804 | NI_PFI_OUTPUT_AI_START1 = 1, |
| @@ -803,20 +828,24 @@ enum ni_pfi_routing { · 23 unmodified lines | |||
| 803 | 828 | ||
| 804 | #define NI_PFI_OUTPUT_RTSI(x) (NI_PFI_OUTPUT_RTSI0 + (x)) | 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 | 831 | /* |
| 807 | with INSN_CONFIG_SET_ROUTING. The numbers assigned are | 832 | * Signals which can be routed to output on a NI PFI pin on a 660x board |
| 808 | not arbitrary, they correspond to the bits required | 833 | * with INSN_CONFIG_SET_ROUTING. The numbers assigned are |
| 809 | to program the board. Lines 0 to 7 can only be set to | 834 | * not arbitrary, they correspond to the bits required |
| 810 | NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to | 835 | * to program the board. Lines 0 to 7 can only be set to |
| 811 | NI_660X_PFI_OUTPUT_COUNTER. */ | 836 | * NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to |
| 837 | * NI_660X_PFI_OUTPUT_COUNTER. | ||
| 838 | */ | ||
| 812 | enum ni_660x_pfi_routing { | 839 | enum ni_660x_pfi_routing { |
| 813 | NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ | 840 | NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ |
| 814 | NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */ | 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 | * to the bits required to program the board (offset by 1 for historical | 846 | * to the bits required to program the board (offset by 1 for historical |
| 819 | * reasons). */ | 847 | * reasons). |
| 848 | */ | ||
| 820 | #define NI_EXT_PFI(x) (NI_USUAL_PFI_SELECT(x) - 1) | 849 | #define NI_EXT_PFI(x) (NI_USUAL_PFI_SELECT(x) - 1) |
| 821 | #define NI_EXT_RTSI(x) (NI_USUAL_RTSI_SELECT(x) - 1) | 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 | COMEDI_COUNTER_TERMINAL_COUNT = 0x4, | 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 | * scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd | 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 | enum ni_m_series_cdio_scan_begin_src { | 864 | enum ni_m_series_cdio_scan_begin_src { |
| 834 | NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, | 865 | NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, |
| 835 | NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18, | 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 | #define NI_CDIO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) | 877 | #define NI_CDIO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) |
| 847 | #define NI_CDIO_SCAN_BEGIN_SRC_RTSI(x) NI_USUAL_RTSI_SELECT(x) | 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 | * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to | 882 | * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to |
| 851 | * change polarity. */ | 883 | * change polarity. |
| 884 | */ | ||
| 852 | #define NI_AO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) | 885 | #define NI_AO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) |
| 853 | #define NI_AO_SCAN_BEGIN_SRC_RTSI(x) NI_USUAL_RTSI_SELECT(x) | 886 | #define NI_AO_SCAN_BEGIN_SRC_RTSI(x) NI_USUAL_RTSI_SELECT(x) |
| 854 | 887 | ||
| 855 | /* Bits for setting a clock source with | 888 | /* |
| 856 | * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */ | 889 | * Bits for setting a clock source with |
| 890 | * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. | ||
| 891 | */ | ||
| 857 | enum ni_freq_out_clock_source_bits { | 892 | enum ni_freq_out_clock_source_bits { |
| 858 | NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ | 893 | NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ |
| 859 | NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */ | 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 | 897 | /* |
| 863 | * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ | 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 | enum amplc_dio_clock_source { | 901 | enum amplc_dio_clock_source { |
| 865 | AMPLC_DIO_CLK_CLKN, /* per channel external clock | 902 | /* |
| 866 | input/output pin (pin is only an | 903 | * Per channel external clock |
| 867 | input when clock source set to this | 904 | * input/output pin (pin is only an |
| 868 | value, otherwise it is an output) */ | 905 | * input when clock source set to this value, |
| 906 | * otherwise it is an output) | ||
| 907 | */ | ||
| 908 | AMPLC_DIO_CLK_CLKN, | ||
| 869 | AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ | 909 | AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ |
| 870 | AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ | 910 | AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ |
| 871 | AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ | 911 | AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ |
| 872 | AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ | 912 | AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ |
| 873 | AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ | 913 | AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ |
| 874 | AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel | 914 | /* |
| 875 | (for channel 0, preceding counter | 915 | * Output of preceding counter channel |
| 876 | channel is channel 2 on preceding | 916 | * (for channel 0, preceding counter |
| 877 | counter subdevice, for first counter | 917 | * channel is channel 2 on preceding |
| 878 | subdevice, preceding counter | 918 | * counter subdevice, for first counter |
| 879 | subdevice is the last counter | 919 | * subdevice, preceding counter |
| 880 | subdevice) */ | 920 | * subdevice is the last counter |
| 921 | * subdevice) | ||
| 922 | */ | ||
| 923 | AMPLC_DIO_CLK_OUTNM1, | ||
| 881 | AMPLC_DIO_CLK_EXT, /* per chip external input pin */ | 924 | AMPLC_DIO_CLK_EXT, /* per chip external input pin */ |
| 882 | /* the following are "enhanced" clock sources for PCIe models */ | 925 | /* the following are "enhanced" clock sources for PCIe models */ |
| 883 | AMPLC_DIO_CLK_VCC, /* clock input HIGH */ | 926 | AMPLC_DIO_CLK_VCC, /* clock input HIGH */ |
| @@ -886,35 +929,39 @@ enum amplc_dio_clock_source { · 2 unmodified lines | |||
| 886 | AMPLC_DIO_CLK_20MHZ /* 20 MHz internal clock */ | 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 | 932 | /* |
| 890 | * timer subdevice on some Amplicon DIO PCIe boards (amplc_dio200 driver). */ | 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 | enum amplc_dio_ts_clock_src { | 936 | enum amplc_dio_ts_clock_src { |
| 892 | AMPLC_DIO_TS_CLK_1GHZ, /* 1 ns period with 20 ns granularity */ | 937 | AMPLC_DIO_TS_CLK_1GHZ, /* 1 ns period with 20 ns granularity */ |
| 893 | AMPLC_DIO_TS_CLK_1MHZ, /* 1 us period */ | 938 | AMPLC_DIO_TS_CLK_1MHZ, /* 1 us period */ |
| 894 | AMPLC_DIO_TS_CLK_1KHZ /* 1 ms period */ | 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 | 942 | /* |
| 898 | * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ | 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 | enum amplc_dio_gate_source { | 946 | enum amplc_dio_gate_source { |
| 900 | AMPLC_DIO_GAT_VCC, /* internal high logic level */ | 947 | AMPLC_DIO_GAT_VCC, /* internal high logic level */ |
| 901 | AMPLC_DIO_GAT_GND, /* internal low logic level */ | 948 | AMPLC_DIO_GAT_GND, /* internal low logic level */ |
| 902 | AMPLC_DIO_GAT_GATN, /* per channel external gate input */ | 949 | AMPLC_DIO_GAT_GATN, /* per channel external gate input */ |
| 903 | AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel | 950 | /* |
| 904 | minus 2 (for channels 0 or 1, | 951 | * negated output of counter channel minus 2 |
| 905 | channel minus 2 is channel 1 or 2 on | 952 | * (for channels 0 or 1, channel minus 2 is channel 1 or 2 on |
| 906 | the preceding counter subdevice, for | 953 | * the preceding counter subdevice, for the first counter subdevice |
| 907 | the first counter subdevice the | 954 | * the preceding counter subdevice is the last counter subdevice) |
| 908 | preceding counter subdevice is the | 955 | */ |
| 909 | last counter subdevice) */ | 956 | AMPLC_DIO_GAT_NOUTNM2, |
| 910 | AMPLC_DIO_GAT_RESERVED4, | 957 | AMPLC_DIO_GAT_RESERVED4, |
| 911 | AMPLC_DIO_GAT_RESERVED5, | 958 | AMPLC_DIO_GAT_RESERVED5, |
| 912 | AMPLC_DIO_GAT_RESERVED6, | 959 | AMPLC_DIO_GAT_RESERVED6, |
| 913 | AMPLC_DIO_GAT_RESERVED7, | 960 | AMPLC_DIO_GAT_RESERVED7, |
| 914 | /* the following are "enhanced" gate sources for PCIe models */ | 961 | /* the following are "enhanced" gate sources for PCIe models */ |
| 915 | AMPLC_DIO_GAT_NGATN = 6, /* negated per channel gate input */ | 962 | AMPLC_DIO_GAT_NGATN = 6, /* negated per channel gate input */ |
| 916 | AMPLC_DIO_GAT_OUTNM2, /* non-negated output of counter | 963 | /* non-negated output of counter channel minus 2 */ |
| 917 | channel minus 2 */ | 964 | AMPLC_DIO_GAT_OUTNM2, |
| 918 | AMPLC_DIO_GAT_PAT_PRESENT, /* "pattern present" signal */ | 965 | AMPLC_DIO_GAT_PAT_PRESENT, /* "pattern present" signal */ |
| 919 | AMPLC_DIO_GAT_PAT_OCCURRED, /* "pattern occurred" latched */ | 966 | AMPLC_DIO_GAT_PAT_OCCURRED, /* "pattern occurred" latched */ |
| 920 | AMPLC_DIO_GAT_PAT_GONE, /* "pattern gone away" latched */ | 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 | struct comedi_subdevice *s; | 2304 | struct comedi_subdevice *s; |
| 2305 | struct comedi_async *async; | 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 | DECLARE_WAITQUEUE(wait, current); | 2309 | DECLARE_WAITQUEUE(wait, current); |
| 2308 | struct comedi_file *cfp = file->private_data; | 2310 | struct comedi_file *cfp = file->private_data; |
| 2309 | struct comedi_device *dev = cfp->dev; | 2311 | struct comedi_device *dev = cfp->dev; |
| 2310 | bool on_wait_queue = false; | 2312 | bool become_nonbusy = false; |
| 2311 | bool attach_locked; | 2313 | bool attach_locked; |
| 2312 | unsigned int old_detach_count; | 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 | async = s->async; | 2333 | async = s->async; |
| 2332 | 2334 | if (s->busy != file || !(async->cmd.flags & CMDF_WRITE)) { | |
| 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)) { | ||
| 2340 | retval = -EINVAL; | 2335 | retval = -EINVAL; |
| 2341 | goto out; | 2336 | goto out; |
| 2342 | } | 2337 | } |
| 2343 | 2338 | ||
| 2344 | add_wait_queue(&async->wait_head, &wait); | 2339 | add_wait_queue(&async->wait_head, &wait); |
| 2345 | on_wait_queue = true; | 2340 | while (count == 0 && !retval) { |
| 2346 | while (nbytes > 0 && !retval) { | ||
| 2347 | unsigned runflags; | 2341 | unsigned runflags; |
| 2342 | unsigned int wp, n1, n2; | ||
| 2348 | 2343 | ||
| 2349 | set_current_state(TASK_INTERRUPTIBLE); | 2344 | set_current_state(TASK_INTERRUPTIBLE); |
| 2350 | 2345 | ||
| 2351 | runflags = comedi_get_subdevice_runflags(s); | 2346 | runflags = comedi_get_subdevice_runflags(s); |
| 2352 | if (!comedi_is_runflags_running(runflags)) { | 2347 | if (!comedi_is_runflags_running(runflags)) { |
| 2353 | if (count == 0) { | 2348 | if (comedi_is_runflags_in_error(runflags)) |
| 2354 | struct comedi_subdevice *new_s; | 2349 | retval = -EPIPE; |
| 2355 | 2350 | if (retval || nbytes) | |
| 2356 | if (comedi_is_runflags_in_error(runflags)) | 2351 | become_nonbusy = true; |
| 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 | } | ||
| 2387 | break; | 2352 | break; |
| 2388 | } | 2353 | } |
| 2354 | if (nbytes == 0) | ||
| 2355 | break; | ||
| 2389 | 2356 | ||
| 2390 | n = nbytes; | 2357 | /* Allocate all free buffer space. */ |
| 2391 | |||
| 2392 | m = n; | ||
| 2393 | if (async->buf_write_ptr + m > async->prealloc_bufsz) | ||
| 2394 | m = async->prealloc_bufsz - async->buf_write_ptr; | ||
| 2395 | comedi_buf_write_alloc(s, async->prealloc_bufsz); | 2358 | comedi_buf_write_alloc(s, async->prealloc_bufsz); |
| 2396 | if (m > comedi_buf_write_n_allocated(s)) | 2359 | m = comedi_buf_write_n_allocated(s); |
| 2397 | m = comedi_buf_write_n_allocated(s); | 2360 | n = min_t(size_t, m, nbytes); |
| 2398 | if (m < n) | ||
| 2399 | n = m; | ||
| 2400 | 2361 | ||
| 2401 | if (n == 0) { | 2362 | if (n == 0) { |
| 2402 | if (file->f_flags & O_NONBLOCK) { | 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 | retval = -ERESTARTSYS; | 2369 | retval = -ERESTARTSYS; |
| 2409 | break; | 2370 | break; |
| 2410 | } | 2371 | } |
| 2411 | if (!s->busy) | 2372 | if (s->busy != file || |
| 2412 | break; | 2373 | !(async->cmd.flags & CMDF_WRITE)) { |
| 2413 | if (s->busy != file) { | ||
| 2414 | retval = -EACCES; | ||
| 2415 | break; | ||
| 2416 | } | ||
| 2417 | if (!(async->cmd.flags & CMDF_WRITE)) { | ||
| 2418 | retval = -EINVAL; | 2374 | retval = -EINVAL; |
| 2419 | break; | 2375 | break; |
| 2420 | } | 2376 | } |
| 2421 | continue; | 2377 | continue; |
| 2422 | } | 2378 | } |
| 2423 | 2379 | ||
| 2424 | m = copy_from_user(async->prealloc_buf + async->buf_write_ptr, | 2380 | wp = async->buf_write_ptr; |
| 2425 | buf, n); | 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 | if (m) { | 2388 | if (m) { |
| 2427 | n -= m; | 2389 | n -= m; |
| 2428 | retval = -EFAULT; | 2390 | retval = -EFAULT; |
| @@ -2433,12 +2395,38 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, · 4 unmodified lines | |||
| 2433 | nbytes -= n; | 2395 | nbytes -= n; |
| 2434 | 2396 | ||
| 2435 | buf += n; | 2397 | buf += n; |
| 2436 | break; /* makes device work like a pipe */ | ||
| 2437 | } | 2398 | } |
| 2438 | out: | 2399 | remove_wait_queue(&async->wait_head, &wait); |
| 2439 | if (on_wait_queue) | ||
| 2440 | remove_wait_queue(&async->wait_head, &wait); | ||
| 2441 | set_current_state(TASK_RUNNING); | 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 | if (attach_locked) | 2430 | if (attach_locked) |
| 2443 | up_read(&dev->attach_lock); | 2431 | up_read(&dev->attach_lock); |
| 2444 | 2432 | ||
| @@ -1,20 +1,20 @@ | |||
| 1 | /* | 1 | /* |
| 2 | linux/include/comedilib.h | 2 | * comedilib.h |
| 3 | header file for kcomedilib | 3 | * Header file for kcomedilib |
| 4 | 4 | * | |
| 5 | COMEDI - Linux Control and Measurement Device Interface | 5 | * COMEDI - Linux Control and Measurement Device Interface |
| 6 | Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> | 6 | * Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> |
| 7 | 7 | * | |
| 8 | This program is free software; you can redistribute it and/or modify | 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 | 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 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | (at your option) any later version. | 11 | * (at your option) any later version. |
| 12 | 12 | * | |
| 13 | This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #ifndef _LINUX_COMEDILIB_H | 19 | #ifndef _LINUX_COMEDILIB_H |
| 20 | #define _LINUX_COMEDILIB_H | 20 | #define _LINUX_COMEDILIB_H |
| @@ -78,8 +78,10 @@ obj-$(CONFIG_COMEDI_ADL_PCI8164) += adl_pci8164.o · 77 unmodified lines | |||
| 78 | obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o | 78 | obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o |
| 79 | obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o | 79 | obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o |
| 80 | obj-$(CONFIG_COMEDI_ADV_PCI1710) += adv_pci1710.o | 80 | obj-$(CONFIG_COMEDI_ADV_PCI1710) += adv_pci1710.o |
| 81 | obj-$(CONFIG_COMEDI_ADV_PCI1720) += adv_pci1720.o | ||
| 81 | obj-$(CONFIG_COMEDI_ADV_PCI1723) += adv_pci1723.o | 82 | obj-$(CONFIG_COMEDI_ADV_PCI1723) += adv_pci1723.o |
| 82 | obj-$(CONFIG_COMEDI_ADV_PCI1724) += adv_pci1724.o | 83 | obj-$(CONFIG_COMEDI_ADV_PCI1724) += adv_pci1724.o |
| 84 | obj-$(CONFIG_COMEDI_ADV_PCI1760) += adv_pci1760.o | ||
| 83 | obj-$(CONFIG_COMEDI_ADV_PCI_DIO) += adv_pci_dio.o | 85 | obj-$(CONFIG_COMEDI_ADV_PCI_DIO) += adv_pci_dio.o |
| 84 | obj-$(CONFIG_COMEDI_AMPLC_DIO200_PCI) += amplc_dio200_pci.o | 86 | obj-$(CONFIG_COMEDI_AMPLC_DIO200_PCI) += amplc_dio200_pci.o |
| 85 | obj-$(CONFIG_COMEDI_AMPLC_PC236_PCI) += amplc_pci236.o | 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 | unsigned short *array = data; | 603 | unsigned short *array = data; |
| 604 | unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes); | 604 | unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes); |
| 605 | unsigned int i; | 605 | unsigned int i; |
| 606 | __be16 *barray = data; | ||
| 606 | 607 | ||
| 607 | for (i = 0; i < num_samples; i++) { | 608 | for (i = 0; i < num_samples; i++) { |
| 608 | if (devpriv->usedma) | 609 | if (devpriv->usedma) |
| 609 | array[i] = be16_to_cpu(array[i]); | 610 | array[i] = be16_to_cpu(barray[i]); |
| 610 | if (s->maxdata == 0xffff) | 611 | if (s->maxdata == 0xffff) |
| 611 | array[i] ^= 0x8000; | 612 | array[i] ^= 0x8000; |
| 612 | else | 613 | else |
| @@ -11,8 +11,9 @@ · 10 unmodified lines | |||
| 11 | * Driver: adv_pci1710 | 11 | * Driver: adv_pci1710 |
| 12 | * Description: Comedi driver for Advantech PCI-1710 series boards | 12 | * Description: Comedi driver for Advantech PCI-1710 series boards |
| 13 | * Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG, PCI-1711, | 13 | * Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG, PCI-1711, |
| 14 | * PCI-1713, PCI-1720, PCI-1731 | 14 | * PCI-1713, PCI-1731 |
| 15 | * Author: Michal Dobes <dobes@tesnet.cz> | 15 | * Author: Michal Dobes <dobes@tesnet.cz> |
| 16 | * Updated: Fri, 29 Oct 2015 17:19:35 -0700 | ||
| 16 | * Status: works | 17 | * Status: works |
| 17 | * | 18 | * |
| 18 | * Configuration options: not applicable, uses PCI auto config | 19 | * Configuration options: not applicable, uses PCI auto config |
| @@ -40,7 +41,13 @@ · 21 unmodified lines | |||
| 40 | #define PCI171X_AD_DATA_REG 0x00 /* R: A/D data */ | 41 | #define PCI171X_AD_DATA_REG 0x00 /* R: A/D data */ |
| 41 | #define PCI171X_SOFTTRG_REG 0x00 /* W: soft trigger for A/D */ | 42 | #define PCI171X_SOFTTRG_REG 0x00 /* W: soft trigger for A/D */ |
| 42 | #define PCI171X_RANGE_REG 0x02 /* W: A/D gain/range register */ | 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 | #define PCI171X_MUX_REG 0x04 /* W: A/D multiplexor control */ | 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 | #define PCI171X_STATUS_REG 0x06 /* R: status register */ | 51 | #define PCI171X_STATUS_REG 0x06 /* R: status register */ |
| 45 | #define PCI171X_STATUS_IRQ BIT(11) /* 1=IRQ occurred */ | 52 | #define PCI171X_STATUS_IRQ BIT(11) /* 1=IRQ occurred */ |
| 46 | #define PCI171X_STATUS_FF BIT(10) /* 1=FIFO is full, fatal error */ | 53 | #define PCI171X_STATUS_FF BIT(10) /* 1=FIFO is full, fatal error */ |
| @@ -58,83 +65,58 @@ · 11 unmodified lines | |||
| 58 | #define PCI171X_CLRFIFO_REG 0x09 /* W: clear FIFO */ | 65 | #define PCI171X_CLRFIFO_REG 0x09 /* W: clear FIFO */ |
| 59 | #define PCI171X_DA_REG(x) (0x0a + ((x) * 2)) /* W: D/A register */ | 66 | #define PCI171X_DA_REG(x) (0x0a + ((x) * 2)) /* W: D/A register */ |
| 60 | #define PCI171X_DAREF_REG 0x0e /* W: D/A reference control */ | 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 | #define PCI171X_DI_REG 0x10 /* R: digital inputs */ | 70 | #define PCI171X_DI_REG 0x10 /* R: digital inputs */ |
| 62 | #define PCI171X_DO_REG 0x10 /* W: digital outputs */ | 71 | #define PCI171X_DO_REG 0x10 /* W: digital outputs */ |
| 63 | #define PCI171X_TIMER_BASE 0x18 /* R/W: 8254 timer */ | 72 | #define PCI171X_TIMER_BASE 0x18 /* R/W: 8254 timer */ |
| 64 | 73 | ||
| 65 | /* | 74 | static const struct comedi_lrange pci1710_ai_range = { |
| 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 = { | ||
| 76 | 9, { | 75 | 9, { |
| 77 | BIP_RANGE(5), | 76 | BIP_RANGE(5), /* gain 1 (0x00) */ |
| 78 | BIP_RANGE(2.5), | 77 | BIP_RANGE(2.5), /* gain 2 (0x01) */ |
| 79 | BIP_RANGE(1.25), | 78 | BIP_RANGE(1.25), /* gain 4 (0x02) */ |
| 80 | BIP_RANGE(0.625), | 79 | BIP_RANGE(0.625), /* gain 8 (0x03) */ |
| 81 | BIP_RANGE(10), | 80 | BIP_RANGE(10), /* gain 0.5 (0x04) */ |
| 82 | UNI_RANGE(10), | 81 | UNI_RANGE(10), /* gain 1 (0x00 | UNI) */ |
| 83 | UNI_RANGE(5), | 82 | UNI_RANGE(5), /* gain 2 (0x01 | UNI) */ |
| 84 | UNI_RANGE(2.5), | 83 | UNI_RANGE(2.5), /* gain 4 (0x02 | UNI) */ |
| 85 | UNI_RANGE(1.25) | 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, | 88 | static const struct comedi_lrange pci1710hg_ai_range = { |
| 90 | 0x10, 0x11, 0x12, 0x13 }; | ||
| 91 | |||
| 92 | static const struct comedi_lrange range_pci1710hg = { | ||
| 93 | 12, { | 89 | 12, { |
| 94 | BIP_RANGE(5), | 90 | BIP_RANGE(5), /* gain 1 (0x00) */ |
| 95 | BIP_RANGE(0.5), | 91 | BIP_RANGE(0.5), /* gain 10 (0x01) */ |
| 96 | BIP_RANGE(0.05), | 92 | BIP_RANGE(0.05), /* gain 100 (0x02) */ |
| 97 | BIP_RANGE(0.005), | 93 | BIP_RANGE(0.005), /* gain 1000 (0x03) */ |
| 98 | BIP_RANGE(10), | 94 | BIP_RANGE(10), /* gain 0.5 (0x04) */ |
| 99 | BIP_RANGE(1), | 95 | BIP_RANGE(1), /* gain 5 (0x05) */ |
| 100 | BIP_RANGE(0.1), | 96 | BIP_RANGE(0.1), /* gain 50 (0x06) */ |
| 101 | BIP_RANGE(0.01), | 97 | BIP_RANGE(0.01), /* gain 500 (0x07) */ |
| 102 | UNI_RANGE(10), | 98 | UNI_RANGE(10), /* gain 1 (0x00 | UNI) */ |
| 103 | UNI_RANGE(1), | 99 | UNI_RANGE(1), /* gain 10 (0x01 | UNI) */ |
| 104 | UNI_RANGE(0.1), | 100 | UNI_RANGE(0.1), /* gain 100 (0x02 | UNI) */ |
| 105 | UNI_RANGE(0.01) | 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, | 105 | static const struct comedi_lrange pci1711_ai_range = { |
| 110 | 0x05, 0x06, 0x07, 0x10, 0x11, | ||
| 111 | 0x12, 0x13 }; | ||
| 112 | |||
| 113 | static const struct comedi_lrange range_pci17x1 = { | ||
| 114 | 5, { | 106 | 5, { |
| 115 | BIP_RANGE(10), | 107 | BIP_RANGE(10), /* gain 1 (0x00) */ |
| 116 | BIP_RANGE(5), | 108 | BIP_RANGE(5), /* gain 2 (0x01) */ |
| 117 | BIP_RANGE(2.5), | 109 | BIP_RANGE(2.5), /* gain 4 (0x02) */ |
| 118 | BIP_RANGE(1.25), | 110 | BIP_RANGE(1.25), /* gain 8 (0x03) */ |
| 119 | BIP_RANGE(0.625) | 111 | BIP_RANGE(0.625) /* gain 16 (0x04) */ |
| 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) | ||
| 131 | } | 112 | } |
| 132 | }; | 113 | }; |
| 133 | 114 | ||
| 134 | static const struct comedi_lrange pci171x_ao_range = { | 115 | static const struct comedi_lrange pci171x_ao_range = { |
| 135 | 2, { | 116 | 3, { |
| 136 | UNI_RANGE(5), | 117 | UNI_RANGE(5), /* internal -5V ref */ |
| 137 | UNI_RANGE(10) | 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 | BOARD_PCI1710HG, | 125 | BOARD_PCI1710HG, |
| 144 | BOARD_PCI1711, | 126 | BOARD_PCI1711, |
| 145 | BOARD_PCI1713, | 127 | BOARD_PCI1713, |
| 146 | BOARD_PCI1720, | ||
| 147 | BOARD_PCI1731, | 128 | BOARD_PCI1731, |
| 148 | }; | 129 | }; |
| 149 | 130 | ||
| 150 | struct boardtype { | 131 | struct boardtype { |
| 151 | const char *name; /* board name */ | 132 | const char *name; |
| 152 | int n_aichan; /* num of A/D chans */ | 133 | const struct comedi_lrange *ai_range; |
| 153 | const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ | 134 | unsigned int is_pci1711:1; |
| 154 | const char *rangecode_ai; /* range codes for programming */ | ||
| 155 | unsigned int is_pci1713:1; | 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 | unsigned int has_ao:1; | 136 | unsigned int has_ao:1; |
| 161 | unsigned int has_di_do:1; | ||
| 162 | unsigned int has_counter:1; | ||
| 163 | }; | 137 | }; |
| 164 | 138 | ||
| 165 | static const struct boardtype boardtypes[] = { | 139 | static const struct boardtype boardtypes[] = { |
| 166 | [BOARD_PCI1710] = { | 140 | [BOARD_PCI1710] = { |
| 167 | .name = "pci1710", | 141 | .name = "pci1710", |
| 168 | .n_aichan = 16, | 142 | .ai_range = &pci1710_ai_range, |
| 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, | ||
| 174 | .has_ao = 1, | 143 | .has_ao = 1, |
| 175 | .has_di_do = 1, | ||
| 176 | .has_counter = 1, | ||
| 177 | }, | 144 | }, |
| 178 | [BOARD_PCI1710HG] = { | 145 | [BOARD_PCI1710HG] = { |
| 179 | .name = "pci1710hg", | 146 | .name = "pci1710hg", |
| 180 | .n_aichan = 16, | 147 | .ai_range = &pci1710hg_ai_range, |
| 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, | ||
| 186 | .has_ao = 1, | 148 | .has_ao = 1, |
| 187 | .has_di_do = 1, | ||
| 188 | .has_counter = 1, | ||
| 189 | }, | 149 | }, |
| 190 | [BOARD_PCI1711] = { | 150 | [BOARD_PCI1711] = { |
| 191 | .name = "pci1711", | 151 | .name = "pci1711", |
| 192 | .n_aichan = 16, | 152 | .ai_range = &pci1711_ai_range, |
| 193 | .rangelist_ai = &range_pci17x1, | 153 | .is_pci1711 = 1, |
| 194 | .rangecode_ai = range_codes_pci17x1, | ||
| 195 | .has_irq = 1, | ||
| 196 | .has_ao = 1, | 154 | .has_ao = 1, |
| 197 | .has_di_do = 1, | ||
| 198 | .has_counter = 1, | ||
| 199 | }, | 155 | }, |
| 200 | [BOARD_PCI1713] = { | 156 | [BOARD_PCI1713] = { |
| 201 | .name = "pci1713", | 157 | .name = "pci1713", |
| 202 | .n_aichan = 32, | 158 | .ai_range = &pci1710_ai_range, |
| 203 | .rangelist_ai = &range_pci1710_3, | ||
| 204 | .rangecode_ai = range_codes_pci1710_3, | ||
| 205 | .is_pci1713 = 1, | 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 | [BOARD_PCI1731] = { | 161 | [BOARD_PCI1731] = { |
| 216 | .name = "pci1731", | 162 | .name = "pci1731", |
| 217 | .n_aichan = 16, | 163 | .ai_range = &pci1711_ai_range, |
| 218 | .rangelist_ai = &range_pci17x1, | 164 | .is_pci1711 = 1, |
| 219 | .rangecode_ai = range_codes_pci17x1, | ||
| 220 | .has_irq = 1, | ||
| 221 | .has_di_do = 1, | ||
| 222 | }, | 165 | }, |
| 223 | }; | 166 | }; |
| 224 | 167 | ||
| @@ -226,14 +169,15 @@ struct pci1710_private { · 1 unmodified line | |||
| 226 | unsigned int max_samples; | 169 | unsigned int max_samples; |
| 227 | unsigned int ctrl; /* control register value */ | 170 | unsigned int ctrl; /* control register value */ |
| 228 | unsigned int ctrl_ext; /* used to switch from TRIG_EXT to TRIG_xxx */ | 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 | unsigned char ai_et; | 173 | unsigned char ai_et; |
| 231 | unsigned int act_chanlist[32]; /* list of scanned channel */ | 174 | unsigned int act_chanlist[32]; /* list of scanned channel */ |
| 232 | unsigned char saved_seglen; /* len of the non-repeating chanlist */ | 175 | unsigned char saved_seglen; /* len of the non-repeating chanlist */ |
| 233 | unsigned char da_ranges; /* copy of D/A outpit range register */ | 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 | struct comedi_subdevice *s, | 181 | struct comedi_subdevice *s, |
| 238 | struct comedi_cmd *cmd) | 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 | return 0; | 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 | struct comedi_subdevice *s, | 247 | struct comedi_subdevice *s, |
| 304 | unsigned int *chanlist, | 248 | unsigned int *chanlist, |
| 305 | unsigned int n_chan, | 249 | unsigned int n_chan, |
| 306 | unsigned int seglen) | 250 | unsigned int seglen) |
| 307 | { | 251 | { |
| 308 | const struct boardtype *board = dev->board_ptr; | ||
| 309 | struct pci1710_private *devpriv = dev->private; | 252 | struct pci1710_private *devpriv = dev->private; |
| 310 | unsigned int first_chan = CR_CHAN(chanlist[0]); | 253 | unsigned int first_chan = CR_CHAN(chanlist[0]); |
| 311 | unsigned int last_chan = CR_CHAN(chanlist[seglen - 1]); | 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 | unsigned int chan = CR_CHAN(chanlist[i]); | 258 | unsigned int chan = CR_CHAN(chanlist[i]); |
| 316 | unsigned int range = CR_RANGE(chanlist[i]); | 259 | unsigned int range = CR_RANGE(chanlist[i]); |
| 317 | unsigned int aref = CR_AREF(chanlist[i]); | 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 | if (aref == AREF_DIFF) | 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 | /* select channel and set range */ | 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 | outw(rangeval, dev->iobase + PCI171X_RANGE_REG); | 273 | outw(rangeval, dev->iobase + PCI171X_RANGE_REG); |
| 327 | 274 | ||
| 328 | devpriv->act_chanlist[i] = chan; | 275 | devpriv->act_chanlist[i] = chan; |
| @@ -331,11 +278,12 @@ static void pci171x_ai_setup_chanlist(struct comedi_device *dev, · 2 unmodified lines | |||
| 331 | devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); | 278 | devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); |
| 332 | 279 | ||
| 333 | /* select channel interval to scan */ | 280 | /* select channel interval to scan */ |
| 334 | devpriv->mux_ext = first_chan | (last_chan << 8); | 281 | devpriv->mux_scan = PCI171X_MUX_CHANL(first_chan) | |
| 335 | outw(devpriv->mux_ext, dev->iobase + PCI171X_MUX_REG); | 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 | struct comedi_subdevice *s, | 287 | struct comedi_subdevice *s, |
| 340 | struct comedi_insn *insn, | 288 | struct comedi_insn *insn, |
| 341 | unsigned long context) | 289 | unsigned long context) |
| @@ -348,7 +296,7 @@ static int pci171x_ai_eoc(struct comedi_device *dev, · 6 unmodified lines | |||
| 348 | return -EBUSY; | 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 | struct comedi_subdevice *s, | 300 | struct comedi_subdevice *s, |
| 353 | unsigned int cur_chan, | 301 | unsigned int cur_chan, |
| 354 | unsigned int *val) | 302 | unsigned int *val) |
| @@ -377,7 +325,7 @@ static int pci171x_ai_read_sample(struct comedi_device *dev, · 22 unmodified lines | |||
| 377 | return 0; | 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 | struct comedi_subdevice *s, | 329 | struct comedi_subdevice *s, |
| 382 | struct comedi_insn *insn, | 330 | struct comedi_insn *insn, |
| 383 | unsigned int *data) | 331 | unsigned int *data) |
| @@ -386,13 +334,14 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, · 2 unmodified lines | |||
| 386 | int ret = 0; | 334 | int ret = 0; |
| 387 | int i; | 335 | int i; |
| 388 | 336 | ||
| 389 | devpriv->ctrl &= PCI171X_CTRL_CNT0; | 337 | /* enable software trigger */ |
| 390 | devpriv->ctrl |= PCI171X_CTRL_SW; /* set software trigger */ | 338 | devpriv->ctrl |= PCI171X_CTRL_SW; |
| 391 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); | 339 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); |
| 340 | |||
| 392 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); | 341 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 393 | outb(0, dev->iobase + PCI171X_CLRINT_REG); | 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 | for (i = 0; i < insn->n; i++) { | 346 | for (i = 0; i < insn->n; i++) { |
| 398 | unsigned int val; | 347 | unsigned int val; |
| @@ -400,111 +349,40 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, · 1 unmodified line | |||
| 400 | /* start conversion */ | 349 | /* start conversion */ |
| 401 | outw(0, dev->iobase + PCI171X_SOFTTRG_REG); | 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 | if (ret) | 353 | if (ret) |
| 405 | break; | 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 | if (ret) | 357 | if (ret) |
| 409 | break; | 358 | break; |
| 410 | 359 | ||
| 411 | data[i] = val; | 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 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); | 367 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 415 | outb(0, dev->iobase + PCI171X_CLRINT_REG); | 368 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 416 | 369 | ||
| 417 | return ret ? ret : insn->n; | 370 | return ret ? ret : insn->n; |
| 418 | } | 371 | } |
| 419 | 372 | ||
| 420 | static int pci171x_ao_insn_write(struct comedi_device *dev, | 373 | static int pci1710_ai_cancel(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, | ||
| 499 | struct comedi_subdevice *s) | 374 | struct comedi_subdevice *s) |
| 500 | { | 375 | { |
| 501 | struct pci1710_private *devpriv = dev->private; | 376 | struct pci1710_private *devpriv = dev->private; |
| 502 | 377 | ||
| 503 | devpriv->ctrl &= PCI171X_CTRL_CNT0; | 378 | /* disable A/D triggers and interrupt sources */ |
| 504 | devpriv->ctrl |= PCI171X_CTRL_SW; | 379 | devpriv->ctrl &= PCI171X_CTRL_CNT0; /* preserve counter 0 clk src */ |
| 505 | /* reset any operations */ | ||
| 506 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); | 380 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); |
| 381 | |||
| 382 | /* disable pacer */ | ||
| 507 | comedi_8254_pacer_enable(dev->pacer, 1, 2, false); | 383 | comedi_8254_pacer_enable(dev->pacer, 1, 2, false); |
| 384 | |||
| 385 | /* clear A/D FIFO and any pending interrutps */ | ||
| 508 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); | 386 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 509 | outb(0, dev->iobase + PCI171X_CLRINT_REG); | 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 | outb(0, dev->iobase + PCI171X_CLRINT_REG); | 413 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 536 | 414 | ||
| 537 | for (; !(inw(dev->iobase + PCI171X_STATUS_REG) & PCI171X_STATUS_FE);) { | 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 | if (ret) { | 417 | if (ret) { |
| 540 | s->async->events |= COMEDI_CB_ERROR; | 418 | s->async->events |= COMEDI_CB_ERROR; |
| 541 | break; | 419 | break; |
| @@ -579,7 +457,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev, · 37 unmodified lines | |||
| 579 | unsigned int val; | 457 | unsigned int val; |
| 580 | int ret; | 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 | if (ret) { | 461 | if (ret) { |
| 584 | s->async->events |= COMEDI_CB_ERROR; | 462 | s->async->events |= COMEDI_CB_ERROR; |
| 585 | break; | 463 | break; |
| @@ -598,7 +476,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev, · 12 unmodified lines | |||
| 598 | outb(0, dev->iobase + PCI171X_CLRINT_REG); | 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 | struct comedi_device *dev = d; | 481 | struct comedi_device *dev = d; |
| 604 | struct pci1710_private *devpriv = dev->private; | 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 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); | 502 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 625 | outb(0, dev->iobase + PCI171X_CLRINT_REG); | 503 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 626 | /* no sample on this interrupt; reset the channel interval */ | 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 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); | 506 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); |
| 629 | comedi_8254_pacer_enable(dev->pacer, 1, 2, true); | 507 | comedi_8254_pacer_enable(dev->pacer, 1, 2, true); |
| 630 | return IRQ_HANDLED; | 508 | return IRQ_HANDLED; |
| @@ -640,12 +518,12 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) · 9 unmodified lines | |||
| 640 | return IRQ_HANDLED; | 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 | struct pci1710_private *devpriv = dev->private; | 523 | struct pci1710_private *devpriv = dev->private; |
| 646 | struct comedi_cmd *cmd = &s->async->cmd; | 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 | devpriv->saved_seglen); | 527 | devpriv->saved_seglen); |
| 650 | 528 | ||
| 651 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); | 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 | return 0; | 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 | struct comedi_subdevice *s, | 563 | struct comedi_subdevice *s, |
| 686 | struct comedi_cmd *cmd) | 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 | /* Step 5: check channel list */ | 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 | if (err) | 628 | if (err) |
| 751 | return 5; | 629 | return 5; |
| @@ -753,7 +631,55 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, · 1 unmodified line | |||
| 753 | return 0; | 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 | struct comedi_subdevice *s, | 683 | struct comedi_subdevice *s, |
| 758 | struct comedi_insn *insn, | 684 | struct comedi_insn *insn, |
| 759 | unsigned int *data) | 685 | unsigned int *data) |
| @@ -780,7 +706,7 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, · 20 unmodified lines | |||
| 780 | data[2] = 0; | 706 | data[2] = 0; |
| 781 | } else { | 707 | } else { |
| 782 | data[1] = 0; | 708 | data[1] = 0; |
| 783 | data[2] = I8254_OSC_BASE_10MHZ; | 709 | data[2] = I8254_OSC_BASE_1MHZ; |
| 784 | } | 710 | } |
| 785 | break; | 711 | break; |
| 786 | default: | 712 | default: |
| @@ -790,56 +716,29 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, · 3 unmodified lines | |||
| 790 | return insn->n; | 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 | const struct boardtype *board = dev->board_ptr; | 721 | const struct boardtype *board = dev->board_ptr; |
| 796 | struct pci1710_private *devpriv = dev->private; | ||
| 797 | 722 | ||
| 798 | /* Software trigger, CNT0=external */ | 723 | /* |
| 799 | devpriv->ctrl = PCI171X_CTRL_SW | PCI171X_CTRL_CNT0; | 724 | * Disable A/D triggers and interrupt sources, set counter 0 |
| 800 | /* reset any operations */ | 725 | * to use internal 1 MHz clock. |
| 801 | outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); | 726 | */ |
| 727 | outw(0, dev->iobase + PCI171X_CTRL_REG); | ||
| 728 | |||
| 729 | /* clear A/D FIFO and any pending interrutps */ | ||
| 802 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); | 730 | outb(0, dev->iobase + PCI171X_CLRFIFO_REG); |
| 803 | outb(0, dev->iobase + PCI171X_CLRINT_REG); | 731 | outb(0, dev->iobase + PCI171X_CLRINT_REG); |
| 804 | devpriv->da_ranges = 0; | 732 | |
| 805 | if (board->has_ao) { | 733 | if (board->has_ao) { |
| 806 | /* set DACs to 0..5V and outputs to 0V */ | 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 | outw(0, dev->iobase + PCI171X_DA_REG(0)); | 736 | outw(0, dev->iobase + PCI171X_DA_REG(0)); |
| 809 | outw(0, dev->iobase + PCI171X_DA_REG(1)); | 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; | 740 | /* set digital outputs to 0 */ |
| 816 | } | 741 | outw(0, dev->iobase + PCI171X_DO_REG); |
| 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); | ||
| 843 | } | 742 | } |
| 844 | 743 | ||
| 845 | static int pci1710_auto_attach(struct comedi_device *dev, | 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 | struct pci1710_private *devpriv; | 749 | struct pci1710_private *devpriv; |
| 851 | struct comedi_subdevice *s; | 750 | struct comedi_subdevice *s; |
| 852 | int ret, subdev, n_subdevices; | 751 | int ret, subdev, n_subdevices; |
| 752 | int i; | ||
| 853 | 753 | ||
| 854 | if (context < ARRAY_SIZE(boardtypes)) | 754 | if (context < ARRAY_SIZE(boardtypes)) |
| 855 | board = &boardtypes[context]; | 755 | board = &boardtypes[context]; |
| @@ -872,15 +772,16 @@ static int pci1710_auto_attach(struct comedi_device *dev, · 16 unmodified lines | |||
| 872 | if (!dev->pacer) | 772 | if (!dev->pacer) |
| 873 | return -ENOMEM; | 773 | return -ENOMEM; |
| 874 | 774 | ||
| 875 | n_subdevices = 0; | 775 | n_subdevices = 1; /* all boards have analog inputs */ |
| 876 | if (board->n_aichan) | ||
| 877 | n_subdevices++; | ||
| 878 | if (board->has_ao) | 776 | if (board->has_ao) |
| 879 | n_subdevices++; | 777 | n_subdevices++; |
| 880 | if (board->has_di_do) | 778 | if (!board->is_pci1713) { |
| 881 | n_subdevices += 2; | 779 | /* |
| 882 | if (board->has_counter) | 780 | * All other boards have digital inputs and outputs as |
| 883 | n_subdevices++; | 781 | * well as a user counter. |
| 782 | */ | ||
| 783 | n_subdevices += 3; | ||
| 784 | } | ||
| 884 | 785 | ||
| 885 | ret = comedi_alloc_subdevices(dev, n_subdevices); | 786 | ret = comedi_alloc_subdevices(dev, n_subdevices); |
| 886 | if (ret) | 787 | if (ret) |
| @@ -888,8 +789,8 @@ static int pci1710_auto_attach(struct comedi_device *dev, · 1 unmodified line | |||
| 888 | 789 | ||
| 889 | pci1710_reset(dev); | 790 | pci1710_reset(dev); |
| 890 | 791 | ||
| 891 | if (board->has_irq && pcidev->irq) { | 792 | if (pcidev->irq) { |
| 892 | ret = request_irq(pcidev->irq, interrupt_service_pci1710, | 793 | ret = request_irq(pcidev->irq, pci1710_irq_handler, |
| 893 | IRQF_SHARED, dev->board_name, dev); | 794 | IRQF_SHARED, dev->board_name, dev); |
| 894 | if (ret == 0) | 795 | if (ret == 0) |
| 895 | dev->irq = pcidev->irq; | 796 | dev->irq = pcidev->irq; |
| @@ -897,109 +798,89 @@ static int pci1710_auto_attach(struct comedi_device *dev, · 1 unmodified line | |||
| 897 | 798 | ||
| 898 | subdev = 0; | 799 | subdev = 0; |
| 899 | 800 | ||
| 900 | if (board->n_aichan) { | 801 | /* Analog Input subdevice */ |
| 901 | s = &dev->subdevices[subdev]; | 802 | s = &dev->subdevices[subdev++]; |
| 902 | s->type = COMEDI_SUBD_AI; | 803 | s->type = COMEDI_SUBD_AI; |
| 903 | s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; | 804 | s->subdev_flags = SDF_READABLE | SDF_GROUND; |
| 904 | if (board->has_diff_ai) | 805 | if (!board->is_pci1711) |
| 905 | s->subdev_flags |= SDF_DIFF; | 806 | s->subdev_flags |= SDF_DIFF; |
| 906 | s->n_chan = board->n_aichan; | 807 | s->n_chan = board->is_pci1713 ? 32 : 16; |
| 907 | s->maxdata = 0x0fff; | 808 | s->maxdata = 0x0fff; |
| 908 | s->range_table = board->rangelist_ai; | 809 | s->range_table = board->ai_range; |
| 909 | s->insn_read = pci171x_ai_insn_read; | 810 | s->insn_read = pci1710_ai_insn_read; |
| 910 | if (dev->irq) { | 811 | if (dev->irq) { |
| 911 | dev->read_subdev = s; | 812 | dev->read_subdev = s; |
| 912 | s->subdev_flags |= SDF_CMD_READ; | 813 | s->subdev_flags |= SDF_CMD_READ; |
| 913 | s->len_chanlist = s->n_chan; | 814 | s->len_chanlist = s->n_chan; |
| 914 | s->do_cmdtest = pci171x_ai_cmdtest; | 815 | s->do_cmdtest = pci1710_ai_cmdtest; |
| 915 | s->do_cmd = pci171x_ai_cmd; | 816 | s->do_cmd = pci1710_ai_cmd; |
| 916 | s->cancel = pci171x_ai_cancel; | 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 | if (board->has_ao) { | 828 | if (board->has_ao) { |
| 922 | s = &dev->subdevices[subdev]; | 829 | /* Analog Output subdevice */ |
| 830 | s = &dev->subdevices[subdev++]; | ||
| 923 | s->type = COMEDI_SUBD_AO; | 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 | s->maxdata = 0x0fff; | 834 | s->maxdata = 0x0fff; |
| 926 | if (board->is_pci1720) { | 835 | s->range_table = &pci171x_ao_range; |
| 927 | s->n_chan = 4; | 836 | s->insn_write = pci1710_ao_insn_write; |
| 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 | } | ||
| 935 | 837 | ||
| 936 | ret = comedi_alloc_subdev_readback(s); | 838 | ret = comedi_alloc_subdev_readback(s); |
| 937 | if (ret) | 839 | if (ret) |
| 938 | return ret; | 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) { | 843 | if (!board->is_pci1713) { |
| 952 | s = &dev->subdevices[subdev]; | 844 | /* Digital Input subdevice */ |
| 845 | s = &dev->subdevices[subdev++]; | ||
| 953 | s->type = COMEDI_SUBD_DI; | 846 | s->type = COMEDI_SUBD_DI; |
| 954 | s->subdev_flags = SDF_READABLE; | 847 | s->subdev_flags = SDF_READABLE; |
| 955 | s->n_chan = 16; | 848 | s->n_chan = 16; |
| 956 | s->maxdata = 1; | 849 | s->maxdata = 1; |
| 957 | s->range_table = &range_digital; | 850 | s->range_table = &range_digital; |
| 958 | s->insn_bits = pci171x_di_insn_bits; | 851 | s->insn_bits = pci1710_di_insn_bits; |
| 959 | subdev++; | ||
| 960 | 852 | ||
| 961 | s = &dev->subdevices[subdev]; | 853 | /* Digital Output subdevice */ |
| 854 | s = &dev->subdevices[subdev++]; | ||
| 962 | s->type = COMEDI_SUBD_DO; | 855 | s->type = COMEDI_SUBD_DO; |
| 963 | s->subdev_flags = SDF_WRITABLE; | 856 | s->subdev_flags = SDF_WRITABLE; |
| 964 | s->n_chan = 16; | 857 | s->n_chan = 16; |
| 965 | s->maxdata = 1; | 858 | s->maxdata = 1; |
| 966 | s->range_table = &range_digital; | 859 | s->range_table = &range_digital; |
| 967 | s->insn_bits = pci171x_do_insn_bits; | 860 | s->insn_bits = pci1710_do_insn_bits; |
| 968 | subdev++; | ||
| 969 | } | ||
| 970 | 861 | ||
| 971 | /* Counter subdevice (8254) */ | 862 | /* Counter subdevice (8254) */ |
| 972 | if (board->has_counter) { | 863 | s = &dev->subdevices[subdev++]; |
| 973 | s = &dev->subdevices[subdev]; | ||
| 974 | comedi_8254_subdevice_init(s, dev->pacer); | 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 | /* counters 1 and 2 are used internally for the pacer */ | 868 | /* counters 1 and 2 are used internally for the pacer */ |
| 979 | comedi_8254_set_busy(dev->pacer, 1, true); | 869 | comedi_8254_set_busy(dev->pacer, 1, true); |
| 980 | comedi_8254_set_busy(dev->pacer, 2, true); | 870 | comedi_8254_set_busy(dev->pacer, 2, true); |
| 981 | |||
| 982 | subdev++; | ||
| 983 | } | 871 | } |
| 984 | 872 | ||
| 985 | /* max_samples is half the FIFO size (2 bytes/sample) */ | 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 | return 0; | 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 | static struct comedi_driver adv_pci1710_driver = { | 879 | static struct comedi_driver adv_pci1710_driver = { |
| 999 | .driver_name = "adv_pci1710", | 880 | .driver_name = "adv_pci1710", |
| 1000 | .module = THIS_MODULE, | 881 | .module = THIS_MODULE, |
| 1001 | .auto_attach = pci1710_auto_attach, | 882 | .auto_attach = pci1710_auto_attach, |
| 1002 | .detach = pci1710_detach, | 883 | .detach = comedi_pci_detach, |
| 1003 | }; | 884 | }; |
| 1004 | 885 | ||
| 1005 | static int adv_pci1710_pci_probe(struct pci_dev *dev, | 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 | { PCI_VDEVICE(ADVANTECH, 0x1711), BOARD_PCI1711 }, | 945 | { PCI_VDEVICE(ADVANTECH, 0x1711), BOARD_PCI1711 }, |
| 1065 | { PCI_VDEVICE(ADVANTECH, 0x1713), BOARD_PCI1713 }, | 946 | { PCI_VDEVICE(ADVANTECH, 0x1713), BOARD_PCI1713 }, |
| 1066 | { PCI_VDEVICE(ADVANTECH, 0x1720), BOARD_PCI1720 }, | ||
| 1067 | { PCI_VDEVICE(ADVANTECH, 0x1731), BOARD_PCI1731 }, | 947 | { PCI_VDEVICE(ADVANTECH, 0x1731), BOARD_PCI1731 }, |
| 1068 | { 0 } | 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 | * Author: Michal Dobes <dobes@tesnet.cz> | 4 | * Author: Michal Dobes <dobes@tesnet.cz> |
| 5 | * | 5 | * |
| 6 | * Hardware driver for Advantech PCI DIO cards. | 6 | * Hardware driver for Advantech PCI DIO cards. |
| 7 | */ | 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. | ||
| 23 | 8 | ||
| 24 | Configuration options: | 9 | /* |
| 25 | [0] - PCI bus of device (optional) | 10 | * Driver: adv_pci_dio |
| 26 | [1] - PCI slot of device (optional) | 11 | * Description: Advantech Digital I/O Cards |
| 27 | If bus/slot is not specified, the first available PCI | 12 | * Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733, |
| 28 | device will be used. | 13 | * PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750, |
| 29 | 14 | * PCI-1751, PCI-1752, PCI-1753, PCI-1753+PCI-1753E, | |
| 30 | */ | 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 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 33 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| @@ -37,403 +28,199 @@ Configuration options: · 3 unmodified lines | |||
| 37 | #include "8255.h" | 28 | #include "8255.h" |
| 38 | #include "comedi_8254.h" | 29 | #include "comedi_8254.h" |
| 39 | 30 | ||
| 40 | /* hardware types of the cards */ | 31 | /* |
| 41 | enum hw_cards_id { | 32 | * Register offset definitions |
| 42 | TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736, | 33 | */ |
| 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 */ | ||
| 94 | 34 | ||
| 95 | /* Advantech PCI-1739U */ | 35 | /* PCI-1730, PCI-1733, PCI-1736 interrupt control registers */ |
| 96 | #define PCI1739_DIO 0 /* R/W: begin of 8255 registers block */ | 36 | #define PCI173X_INT_EN_REG 0x08 /* R/W: enable/disable */ |
| 97 | #define PCI1739_ICR 32 /* W: Interrupt control register */ | 37 | #define PCI173X_INT_RF_REG 0x0c /* R/W: falling/rising edge */ |
| 98 | #define PCI1739_ISR 32 /* R: Interrupt status register */ | 38 | #define PCI173X_INT_CLR_REG 0x10 /* R/W: clear */ |
| 99 | #define PCI1739_BOARDID 8 /* R: Board I/D switch for 1739U */ | ||
| 100 | 39 | ||
| 101 | /* Advantech PCI-1750 */ | 40 | /* PCI-1739U, PCI-1750, PCI1751 interrupt control registers */ |
| 102 | #define PCI1750_IDI 0 /* R: Isolated digital input 0-15 */ | 41 | #define PCI1750_INT_REG 0x20 /* R/W: status/control */ |
| 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 */ | ||
| 106 | 42 | ||
| 107 | /* Advantech PCI-1751/3/3E */ | 43 | /* PCI-1753, PCI-1753E interrupt control registers */ |
| 108 | #define PCI1751_DIO 0 /* R/W: begin of 8255 registers block */ | 44 | #define PCI1753_INT_REG(x) (0x10 + (x)) /* R/W: control group 0 to 3 */ |
| 109 | #define PCI1751_CNT 24 /* R/W: begin of 8254 registers block */ | 45 | #define PCI1753E_INT_REG(x) (0x30 + (x)) /* R/W: control group 0 to 3 */ |
| 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 */ | ||
| 122 | 46 | ||
| 123 | /* Advantech PCI-1752/4/6 */ | 47 | /* PCI-1754, PCI-1756 interrupt control registers */ |
| 124 | #define PCI1752_IDO 0 /* R/W: Digital output 0-31 */ | 48 | #define PCI1754_INT_REG(x) (0x08 + (x) * 2) /* R/W: control group 0 to 3 */ |
| 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 */ | ||
| 136 | 49 | ||
| 137 | /* Advantech PCI-1762 registers */ | 50 | /* PCI-1752, PCI-1756 special registers */ |
| 138 | #define PCI1762_RO 0 /* R/W: Relays status/output */ | 51 | #define PCI1752_CFC_REG 0x12 /* R/W: channel freeze function */ |
| 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 */ | ||
| 143 | 52 | ||
| 144 | /* Advantech PCI-1760 registers */ | 53 | /* PCI-1762 interrupt control registers */ |
| 145 | #define OMB0 0x0c /* W: Mailbox outgoing registers */ | 54 | #define PCI1762_INT_REG 0x06 /* R/W: status/control */ |
| 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 | ||
| 157 | 55 | ||
| 158 | /* PCI-1760 mailbox commands */ | 56 | /* maximum number of subdevice descriptions in the boardinfo */ |
| 159 | #define CMD_ClearIMB2 0x00 /* Clear IMB2 status and return actual | 57 | #define PCI_DIO_MAX_DI_SUBDEVS 2 /* 2 x 8/16/32 input channels max */ |
| 160 | * DI status in IMB3 */ | 58 | #define PCI_DIO_MAX_DO_SUBDEVS 2 /* 2 x 8/16/32 output channels max */ |
| 161 | #define CMD_SetRelaysOutput 0x01 /* Set relay output from OMB0 */ | 59 | #define PCI_DIO_MAX_DIO_SUBDEVG 2 /* 2 x any number of 8255 devices max */ |
| 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 */ | ||
| 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 | struct diosubd_data { | 78 | struct diosubd_data { |
| 223 | int chans; /* num of chans */ | 79 | int chans; /* num of chans or 8255 devices */ |
| 224 | int addr; /* PCI address ofset */ | 80 | unsigned long addr; /* PCI address ofset */ |
| 225 | int regs; /* number of registers to read or 8255 | ||
| 226 | subdevices */ | ||
| 227 | unsigned int specflags; /* addon subdevice flags */ | ||
| 228 | }; | 81 | }; |
| 229 | 82 | ||
| 230 | struct dio_boardtype { | 83 | struct dio_boardtype { |
| 231 | const char *name; /* board name */ | 84 | const char *name; /* board name */ |
| 232 | int main_pci_region; /* main I/O PCI region */ | ||
| 233 | enum hw_cards_id cardtype; | ||
| 234 | int nsubdevs; | 85 | int nsubdevs; |
| 235 | struct diosubd_data sdi[MAX_DI_SUBDEVS]; /* DI chans */ | 86 | struct diosubd_data sdi[PCI_DIO_MAX_DI_SUBDEVS]; |
| 236 | struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */ | 87 | struct diosubd_data sdo[PCI_DIO_MAX_DO_SUBDEVS]; |
| 237 | struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */ | 88 | struct diosubd_data sdio[PCI_DIO_MAX_DIO_SUBDEVG]; |
| 238 | struct diosubd_data boardid; /* card supports board ID switch */ | 89 | unsigned long id_reg; |
| 239 | unsigned long timer_regbase; | 90 | unsigned long timer_regbase; |
| 240 | enum hw_io_access io_access; | 91 | unsigned int is_16bit:1; |
| 241 | }; | 92 | }; |
| 242 | 93 | ||
| 243 | static const struct dio_boardtype boardtypes[] = { | 94 | static const struct dio_boardtype boardtypes[] = { |
| 244 | [TYPE_PCI1730] = { | 95 | [TYPE_PCI1730] = { |
| 245 | .name = "pci1730", | 96 | .name = "pci1730", |
| 246 | .main_pci_region = PCIDIO_MAINREG, | ||
| 247 | .cardtype = TYPE_PCI1730, | ||
| 248 | .nsubdevs = 5, | 97 | .nsubdevs = 5, |
| 249 | .sdi[0] = { 16, PCI1730_DI, 2, 0, }, | 98 | .sdi[0] = { 16, 0x02, }, /* DI 0-15 */ |
| 250 | .sdi[1] = { 16, PCI1730_IDI, 2, 0, }, | 99 | .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */ |
| 251 | .sdo[0] = { 16, PCI1730_DO, 2, 0, }, | 100 | .sdo[0] = { 16, 0x02, }, /* DO 0-15 */ |
| 252 | .sdo[1] = { 16, PCI1730_IDO, 2, 0, }, | 101 | .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ |
| 253 | .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, | 102 | .id_reg = 0x04, |
| 254 | .io_access = IO_8b, | ||
| 255 | }, | 103 | }, |
| 256 | [TYPE_PCI1733] = { | 104 | [TYPE_PCI1733] = { |
| 257 | .name = "pci1733", | 105 | .name = "pci1733", |
| 258 | .main_pci_region = PCIDIO_MAINREG, | ||
| 259 | .cardtype = TYPE_PCI1733, | ||
| 260 | .nsubdevs = 2, | 106 | .nsubdevs = 2, |
| 261 | .sdi[1] = { 32, PCI1733_IDI, 4, 0, }, | 107 | .sdi[1] = { 32, 0x00, }, /* ISO DI 0-31 */ |
| 262 | .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, | 108 | .id_reg = 0x04, |
| 263 | .io_access = IO_8b, | ||
| 264 | }, | 109 | }, |
| 265 | [TYPE_PCI1734] = { | 110 | [TYPE_PCI1734] = { |
| 266 | .name = "pci1734", | 111 | .name = "pci1734", |
| 267 | .main_pci_region = PCIDIO_MAINREG, | ||
| 268 | .cardtype = TYPE_PCI1734, | ||
| 269 | .nsubdevs = 2, | 112 | .nsubdevs = 2, |
| 270 | .sdo[1] = { 32, PCI1734_IDO, 4, 0, }, | 113 | .sdo[1] = { 32, 0x00, }, /* ISO DO 0-31 */ |
| 271 | .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, | 114 | .id_reg = 0x04, |
| 272 | .io_access = IO_8b, | ||
| 273 | }, | 115 | }, |
| 274 | [TYPE_PCI1735] = { | 116 | [TYPE_PCI1735] = { |
| 275 | .name = "pci1735", | 117 | .name = "pci1735", |
| 276 | .main_pci_region = PCIDIO_MAINREG, | ||
| 277 | .cardtype = TYPE_PCI1735, | ||
| 278 | .nsubdevs = 4, | 118 | .nsubdevs = 4, |
| 279 | .sdi[0] = { 32, PCI1735_DI, 4, 0, }, | 119 | .sdi[0] = { 32, 0x00, }, /* DI 0-31 */ |
| 280 | .sdo[0] = { 32, PCI1735_DO, 4, 0, }, | 120 | .sdo[0] = { 32, 0x00, }, /* DO 0-31 */ |
| 281 | .boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, }, | 121 | .id_reg = 0x08, |
| 282 | .timer_regbase = PCI1735_C8254, | 122 | .timer_regbase = 0x04, |
| 283 | .io_access = IO_8b, | ||
| 284 | }, | 123 | }, |
| 285 | [TYPE_PCI1736] = { | 124 | [TYPE_PCI1736] = { |
| 286 | .name = "pci1736", | 125 | .name = "pci1736", |
| 287 | .main_pci_region = PCI1736_MAINREG, | ||
| 288 | .cardtype = TYPE_PCI1736, | ||
| 289 | .nsubdevs = 3, | 126 | .nsubdevs = 3, |
| 290 | .sdi[1] = { 16, PCI1736_IDI, 2, 0, }, | 127 | .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */ |
| 291 | .sdo[1] = { 16, PCI1736_IDO, 2, 0, }, | 128 | .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ |
| 292 | .boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, }, | 129 | .id_reg = 0x04, |
| 293 | .io_access = IO_8b, | ||
| 294 | }, | 130 | }, |
| 295 | [TYPE_PCI1739] = { | 131 | [TYPE_PCI1739] = { |
| 296 | .name = "pci1739", | 132 | .name = "pci1739", |
| 297 | .main_pci_region = PCIDIO_MAINREG, | 133 | .nsubdevs = 3, |
| 298 | .cardtype = TYPE_PCI1739, | 134 | .sdio[0] = { 2, 0x00, }, /* 8255 DIO */ |
| 299 | .nsubdevs = 2, | 135 | .id_reg = 0x08, |
| 300 | .sdio[0] = { 48, PCI1739_DIO, 2, 0, }, | ||
| 301 | .io_access = IO_8b, | ||
| 302 | }, | 136 | }, |
| 303 | [TYPE_PCI1750] = { | 137 | [TYPE_PCI1750] = { |
| 304 | .name = "pci1750", | 138 | .name = "pci1750", |
| 305 | .main_pci_region = PCIDIO_MAINREG, | ||
| 306 | .cardtype = TYPE_PCI1750, | ||
| 307 | .nsubdevs = 2, | 139 | .nsubdevs = 2, |
| 308 | .sdi[1] = { 16, PCI1750_IDI, 2, 0, }, | 140 | .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */ |
| 309 | .sdo[1] = { 16, PCI1750_IDO, 2, 0, }, | 141 | .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ |
| 310 | .io_access = IO_8b, | ||
| 311 | }, | 142 | }, |
| 312 | [TYPE_PCI1751] = { | 143 | [TYPE_PCI1751] = { |
| 313 | .name = "pci1751", | 144 | .name = "pci1751", |
| 314 | .main_pci_region = PCIDIO_MAINREG, | ||
| 315 | .cardtype = TYPE_PCI1751, | ||
| 316 | .nsubdevs = 3, | 145 | .nsubdevs = 3, |
| 317 | .sdio[0] = { 48, PCI1751_DIO, 2, 0, }, | 146 | .sdio[0] = { 2, 0x00, }, /* 8255 DIO */ |
| 318 | .timer_regbase = PCI1751_CNT, | 147 | .timer_regbase = 0x18, |
| 319 | .io_access = IO_8b, | ||
| 320 | }, | 148 | }, |
| 321 | [TYPE_PCI1752] = { | 149 | [TYPE_PCI1752] = { |
| 322 | .name = "pci1752", | 150 | .name = "pci1752", |
| 323 | .main_pci_region = PCIDIO_MAINREG, | ||
| 324 | .cardtype = TYPE_PCI1752, | ||
| 325 | .nsubdevs = 3, | 151 | .nsubdevs = 3, |
| 326 | .sdo[0] = { 32, PCI1752_IDO, 2, 0, }, | 152 | .sdo[0] = { 32, 0x00, }, /* DO 0-31 */ |
| 327 | .sdo[1] = { 32, PCI1752_IDO2, 2, 0, }, | 153 | .sdo[1] = { 32, 0x04, }, /* DO 32-63 */ |
| 328 | .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, | 154 | .id_reg = 0x10, |
| 329 | .io_access = IO_16b, | 155 | .is_16bit = 1, |
| 330 | }, | 156 | }, |
| 331 | [TYPE_PCI1753] = { | 157 | [TYPE_PCI1753] = { |
| 332 | .name = "pci1753", | 158 | .name = "pci1753", |
| 333 | .main_pci_region = PCIDIO_MAINREG, | ||
| 334 | .cardtype = TYPE_PCI1753, | ||
| 335 | .nsubdevs = 4, | 159 | .nsubdevs = 4, |
| 336 | .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, | 160 | .sdio[0] = { 4, 0x00, }, /* 8255 DIO */ |
| 337 | .io_access = IO_8b, | ||
| 338 | }, | 161 | }, |
| 339 | [TYPE_PCI1753E] = { | 162 | [TYPE_PCI1753E] = { |
| 340 | .name = "pci1753e", | 163 | .name = "pci1753e", |
| 341 | .main_pci_region = PCIDIO_MAINREG, | ||
| 342 | .cardtype = TYPE_PCI1753E, | ||
| 343 | .nsubdevs = 8, | 164 | .nsubdevs = 8, |
| 344 | .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, | 165 | .sdio[0] = { 4, 0x00, }, /* 8255 DIO */ |
| 345 | .sdio[1] = { 96, PCI1753E_DIO, 4, 0, }, | 166 | .sdio[1] = { 4, 0x20, }, /* 8255 DIO */ |
| 346 | .io_access = IO_8b, | ||
| 347 | }, | 167 | }, |
| 348 | [TYPE_PCI1754] = { | 168 | [TYPE_PCI1754] = { |
| 349 | .name = "pci1754", | 169 | .name = "pci1754", |
| 350 | .main_pci_region = PCIDIO_MAINREG, | ||
| 351 | .cardtype = TYPE_PCI1754, | ||
| 352 | .nsubdevs = 3, | 170 | .nsubdevs = 3, |
| 353 | .sdi[0] = { 32, PCI1754_IDI, 2, 0, }, | 171 | .sdi[0] = { 32, 0x00, }, /* DI 0-31 */ |
| 354 | .sdi[1] = { 32, PCI1754_IDI2, 2, 0, }, | 172 | .sdi[1] = { 32, 0x04, }, /* DI 32-63 */ |
| 355 | .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, | 173 | .id_reg = 0x10, |
| 356 | .io_access = IO_16b, | 174 | .is_16bit = 1, |
| 357 | }, | 175 | }, |
| 358 | [TYPE_PCI1756] = { | 176 | [TYPE_PCI1756] = { |
| 359 | .name = "pci1756", | 177 | .name = "pci1756", |
| 360 | .main_pci_region = PCIDIO_MAINREG, | ||
| 361 | .cardtype = TYPE_PCI1756, | ||
| 362 | .nsubdevs = 3, | 178 | .nsubdevs = 3, |
| 363 | .sdi[1] = { 32, PCI1756_IDI, 2, 0, }, | 179 | .sdi[1] = { 32, 0x00, }, /* DI 0-31 */ |
| 364 | .sdo[1] = { 32, PCI1756_IDO, 2, 0, }, | 180 | .sdo[1] = { 32, 0x04, }, /* DO 0-31 */ |
| 365 | .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, | 181 | .id_reg = 0x10, |
| 366 | .io_access = IO_16b, | 182 | .is_16bit = 1, |
| 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, | ||
| 375 | }, | 183 | }, |
| 376 | [TYPE_PCI1762] = { | 184 | [TYPE_PCI1762] = { |
| 377 | .name = "pci1762", | 185 | .name = "pci1762", |
| 378 | .main_pci_region = PCIDIO_MAINREG, | ||
| 379 | .cardtype = TYPE_PCI1762, | ||
| 380 | .nsubdevs = 3, | 186 | .nsubdevs = 3, |
| 381 | .sdi[1] = { 16, PCI1762_IDI, 1, 0, }, | 187 | .sdi[1] = { 16, 0x02, }, /* ISO DI 0-15 */ |
| 382 | .sdo[1] = { 16, PCI1762_RO, 1, 0, }, | 188 | .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ |
| 383 | .boardid = { 4, PCI1762_BOARDID, 1, SDF_INTERNAL, }, | 189 | .id_reg = 0x04, |
| 384 | .io_access = IO_16b, | 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 | static int pci_dio_insn_bits_di_b(struct comedi_device *dev, | 194 | static int pci_dio_insn_bits_di_b(struct comedi_device *dev, |
| 411 | struct comedi_subdevice *s, | 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; | 199 | unsigned long reg = (unsigned long)s->private; |
| 415 | int i; | 200 | unsigned long iobase = dev->iobase + reg; |
| 416 | 201 | ||
| 417 | data[1] = 0; | 202 | data[1] = inb(iobase); |
| 418 | for (i = 0; i < d->regs; i++) | 203 | if (s->n_chan > 8) |
| 419 | data[1] |= inb(dev->iobase + d->addr + i) << (8 * i); | 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 | return insn->n; | 210 | return insn->n; |
| 422 | } | 211 | } |
| 423 | 212 | ||
| 424 | /* | ||
| 425 | ============================================================================== | ||
| 426 | */ | ||
| 427 | static int pci_dio_insn_bits_di_w(struct comedi_device *dev, | 213 | static int pci_dio_insn_bits_di_w(struct comedi_device *dev, |
| 428 | struct comedi_subdevice *s, | 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; | 218 | unsigned long reg = (unsigned long)s->private; |
| 432 | int i; | 219 | unsigned long iobase = dev->iobase + reg; |
| 433 | 220 | ||
| 434 | data[1] = 0; | 221 | data[1] = inw(iobase); |
| 435 | for (i = 0; i < d->regs; i++) | 222 | if (s->n_chan > 16) |
| 436 | data[1] |= inw(dev->iobase + d->addr + 2 * i) << (16 * i); | 223 | data[1] |= (inw(iobase + 2) << 16); |
| 437 | 224 | ||
| 438 | return insn->n; | 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 | struct comedi_insn *insn, | 230 | struct comedi_insn *insn, |
| 444 | unsigned int *data) | 231 | unsigned int *data) |
| 445 | { | 232 | { |
| 446 | const struct diosubd_data *d = (const struct diosubd_data *)s->private; | 233 | unsigned long reg = (unsigned long)s->private; |
| 447 | int i; | 234 | unsigned long iobase = dev->iobase + reg; |
| 448 | 235 | ||
| 449 | if (comedi_dio_update_state(s, data)) { | 236 | if (comedi_dio_update_state(s, data)) { |
| 450 | for (i = 0; i < d->regs; i++) | 237 | outb(s->state & 0xff, iobase); |
| 451 | outb((s->state >> (8 * i)) & 0xff, | 238 | if (s->n_chan > 8) |
| 452 | dev->iobase + d->addr + i); | 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 | data[1] = s->state; | 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 | struct comedi_insn *insn, | 253 | struct comedi_insn *insn, |
| 463 | unsigned int *data) | 254 | unsigned int *data) |
| 464 | { | 255 | { |
| 465 | const struct diosubd_data *d = (const struct diosubd_data *)s->private; | 256 | unsigned long reg = (unsigned long)s->private; |
| 466 | int i; | 257 | unsigned long iobase = dev->iobase + reg; |
| 467 | 258 | ||
| 468 | if (comedi_dio_update_state(s, data)) { | 259 | if (comedi_dio_update_state(s, data)) { |
| 469 | for (i = 0; i < d->regs; i++) | 260 | outw(s->state & 0xffff, iobase); |
| 470 | outw((s->state >> (16 * i)) & 0xffff, | 261 | if (s->n_chan > 16) |
| 471 | dev->iobase + d->addr + 2 * i); | 262 | outw((s->state >> 16) & 0xffff, iobase + 2); |
| 472 | } | 263 | } |
| 473 | 264 | ||
| 474 | data[1] = s->state; | 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 | return insn->n; | 267 | return insn->n; |
| 477 | } | 268 | } |
| 478 | 269 | ||
| 479 | /* | 270 | static int pci_dio_reset(struct comedi_device *dev, unsigned long cardtype) |
| 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) | ||
| 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; | 276 | /* disable and clear interrupts */ |
| 550 | } | 277 | switch (cardtype) { |
| 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) { | ||
| 738 | case TYPE_PCI1730: | 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 | case TYPE_PCI1733: | 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 | case TYPE_PCI1736: | 280 | case TYPE_PCI1736: |
| 766 | outb(0, dev->iobase + PCI1736_IDO); | 281 | outb(0, dev->iobase + PCI173X_INT_EN_REG); |
| 767 | outb(0, dev->iobase + PCI1736_IDO + 1); | 282 | outb(0x0f, dev->iobase + PCI173X_INT_CLR_REG); |
| 768 | /* disable interrupts */ | 283 | outb(0, dev->iobase + PCI173X_INT_RF_REG); |
| 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); | ||
| 774 | break; | 284 | break; |
| 775 | |||
| 776 | case TYPE_PCI1739: | 285 | case TYPE_PCI1739: |
| 777 | /* disable & clear interrupts */ | ||
| 778 | outb(0x88, dev->iobase + PCI1739_ICR); | ||
| 779 | break; | ||
| 780 | |||
| 781 | case TYPE_PCI1750: | 286 | case TYPE_PCI1750: |
| 782 | case TYPE_PCI1751: | 287 | case TYPE_PCI1751: |
| 783 | /* disable & clear interrupts */ | 288 | outb(0x88, dev->iobase + PCI1750_INT_REG); |
| 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); | ||
| 793 | break; | 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 | case TYPE_PCI1753: | 290 | case TYPE_PCI1753: |
| 802 | outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear | 291 | case TYPE_PCI1753E: |
| 803 | * interrupts */ | 292 | outb(0x88, dev->iobase + PCI1753_INT_REG(0)); |
| 804 | outb(0x80, dev->iobase + PCI1753_ICR1); | 293 | outb(0x80, dev->iobase + PCI1753_INT_REG(1)); |
| 805 | outb(0x80, dev->iobase + PCI1753_ICR2); | 294 | outb(0x80, dev->iobase + PCI1753_INT_REG(2)); |
| 806 | outb(0x80, dev->iobase + PCI1753_ICR3); | 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 | break; | 302 | break; |
| 808 | case TYPE_PCI1754: | 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 | case TYPE_PCI1756: | 304 | case TYPE_PCI1756: |
| 816 | outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze | 305 | outw(0x08, dev->iobase + PCI1754_INT_REG(0)); |
| 817 | * function */ | 306 | outw(0x08, dev->iobase + PCI1754_INT_REG(1)); |
| 818 | outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear | 307 | if (cardtype == TYPE_PCI1754) { |
| 819 | * interrupts */ | 308 | outw(0x08, dev->iobase + PCI1754_INT_REG(2)); |
| 820 | outw(0x08, dev->iobase + PCI1754_6_ICR1); | 309 | outw(0x08, dev->iobase + PCI1754_INT_REG(3)); |
| 821 | outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */ | 310 | } |
| 822 | outw(0, dev->iobase + PCI1756_IDO + 2); | ||
| 823 | break; | ||
| 824 | case TYPE_PCI1760: | ||
| 825 | pci1760_reset(dev); | ||
| 826 | break; | 311 | break; |
| 827 | case TYPE_PCI1762: | 312 | case TYPE_PCI1762: |
| 828 | outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear | 313 | outw(0x0101, dev->iobase + PCI1762_INT_REG); |
| 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; | ||
| 934 | break; | 314 | break; |
| 935 | case IO_16b: | 315 | default: |
| 936 | s->insn_bits = pci_dio_insn_bits_do_w; | ||
| 937 | break; | 316 | break; |
| 938 | } | 317 | } |
| 939 | s->private = (void *)d; | ||
| 940 | 318 | ||
| 941 | return 0; | 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 | static int pci_dio_auto_attach(struct comedi_device *dev, | 322 | static int pci_dio_auto_attach(struct comedi_device *dev, |
| 978 | unsigned long context) | 323 | unsigned long context) |
| 979 | { | 324 | { |
| 980 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 325 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 981 | const struct dio_boardtype *board = NULL; | 326 | const struct dio_boardtype *board = NULL; |
| 982 | struct pci_dio_private *devpriv; | 327 | const struct diosubd_data *d; |
| 983 | struct comedi_subdevice *s; | 328 | struct comedi_subdevice *s; |
| 984 | int ret, subdev, i, j; | 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 | dev->board_ptr = board; | 335 | dev->board_ptr = board; |
| 991 | dev->board_name = board->name; | 336 | dev->board_name = board->name; |
| 992 | 337 | ||
| 993 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | ||
| 994 | if (!devpriv) | ||
| 995 | return -ENOMEM; | ||
| 996 | |||
| 997 | ret = comedi_pci_enable(dev); | 338 | ret = comedi_pci_enable(dev); |
| 998 | if (ret) | 339 | if (ret) |
| 999 | return ret; | 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 | ret = comedi_alloc_subdevices(dev, board->nsubdevs); | 348 | ret = comedi_alloc_subdevices(dev, board->nsubdevs); |
| 1003 | if (ret) | 349 | if (ret) |
| 1004 | return ret; | 350 | return ret; |
| 1005 | 351 | ||
| 1006 | subdev = 0; | 352 | subdev = 0; |
| 1007 | for (i = 0; i < MAX_DI_SUBDEVS; i++) | 353 | for (i = 0; i < PCI_DIO_MAX_DI_SUBDEVS; i++) { |
| 1008 | if (board->sdi[i].chans) { | 354 | d = &board->sdi[i]; |
| 1009 | s = &dev->subdevices[subdev]; | 355 | if (d->chans) { |
| 1010 | pci_dio_add_di(dev, s, &board->sdi[i]); | 356 | s = &dev->subdevices[subdev++]; |
| 1011 | 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++) | 369 | for (i = 0; i < PCI_DIO_MAX_DO_SUBDEVS; i++) { |
| 1015 | if (board->sdo[i].chans) { | 370 | d = &board->sdo[i]; |
| 1016 | s = &dev->subdevices[subdev]; | 371 | if (d->chans) { |
| 1017 | pci_dio_add_do(dev, s, &board->sdo[i]); | 372 | s = &dev->subdevices[subdev++]; |
| 1018 | 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++) | 400 | for (i = 0; i < PCI_DIO_MAX_DIO_SUBDEVG; i++) { |
| 1022 | for (j = 0; j < board->sdio[i].regs; j++) { | 401 | d = &board->sdio[i]; |
| 1023 | s = &dev->subdevices[subdev]; | 402 | for (j = 0; j < d->chans; j++) { |
| 403 | s = &dev->subdevices[subdev++]; | ||
| 1024 | ret = subdev_8255_init(dev, s, NULL, | 404 | ret = subdev_8255_init(dev, s, NULL, |
| 1025 | board->sdio[i].addr + | 405 | d->addr + j * I8255_SIZE); |
| 1026 | j * I8255_SIZE); | ||
| 1027 | if (ret) | 406 | if (ret) |
| 1028 | return ret; | 407 | return ret; |
| 1029 | subdev++; | ||
| 1030 | } | 408 | } |
| 409 | } | ||
| 1031 | 410 | ||
| 1032 | if (board->boardid.chans) { | 411 | if (board->id_reg) { |
| 1033 | s = &dev->subdevices[subdev]; | 412 | s = &dev->subdevices[subdev++]; |
| 1034 | s->type = COMEDI_SUBD_DI; | 413 | s->type = COMEDI_SUBD_DI; |
| 1035 | pci_dio_add_di(dev, s, &board->boardid); | 414 | s->subdev_flags = SDF_READABLE | SDF_INTERNAL; |
| 1036 | subdev++; | 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 | if (board->timer_regbase) { | 423 | if (board->timer_regbase) { |
| 1040 | s = &dev->subdevices[subdev]; | 424 | s = &dev->subdevices[subdev++]; |
| 1041 | 425 | ||
| 1042 | dev->pacer = comedi_8254_init(dev->iobase + | 426 | dev->pacer = comedi_8254_init(dev->iobase + |
| 1043 | board->timer_regbase, | 427 | board->timer_regbase, |
| @@ -1046,32 +430,50 @@ static int pci_dio_auto_attach(struct comedi_device *dev, · 2 unmodified lines | |||
| 1046 | return -ENOMEM; | 430 | return -ENOMEM; |
| 1047 | 431 | ||
| 1048 | comedi_8254_subdevice_init(s, dev->pacer); | 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 | return 0; | 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 | static struct comedi_driver adv_pci_dio_driver = { | 438 | static struct comedi_driver adv_pci_dio_driver = { |
| 1069 | .driver_name = "adv_pci_dio", | 439 | .driver_name = "adv_pci_dio", |
| 1070 | .module = THIS_MODULE, | 440 | .module = THIS_MODULE, |
| 1071 | .auto_attach = pci_dio_auto_attach, | 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 | static int adv_pci_dio_pci_probe(struct pci_dev *dev, | 477 | static int adv_pci_dio_pci_probe(struct pci_dev *dev, |
| 1076 | const struct pci_device_id *id) | 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 | { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 }, | 496 | { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 }, |
| 1095 | { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 }, | 497 | { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 }, |
| 1096 | { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 }, | 498 | { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 }, |
| 1097 | { PCI_VDEVICE(ADVANTECH, 0x1760), TYPE_PCI1760 }, | ||
| 1098 | { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 }, | 499 | { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 }, |
| 1099 | { 0 } | 500 | { 0 } |
| 1100 | }; | 501 | }; |
| @@ -1109,5 +510,5 @@ static struct pci_driver adv_pci_dio_pci_driver = { · 8 unmodified lines | |||
| 1109 | module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver); | 510 | module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver); |
| 1110 | 511 | ||
| 1111 | MODULE_AUTHOR("Comedi http://www.comedi.org"); | 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 | MODULE_LICENSE("GPL"); | 514 | MODULE_LICENSE("GPL"); |
| @@ -1022,14 +1022,17 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) · 1021 unmodified lines | |||
| 1022 | irq = pci_dev->irq; | 1022 | irq = pci_dev->irq; |
| 1023 | 1023 | ||
| 1024 | /* Allocate buffer to hold values for AO channel scan. */ | 1024 | /* Allocate buffer to hold values for AO channel scan. */ |
| 1025 | devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) * | 1025 | devpriv->ao_scan_vals = kmalloc_array(board->ao_chans, |
| 1026 | board->ao_chans, GFP_KERNEL); | 1026 | sizeof(devpriv->ao_scan_vals[0]), |
| 1027 | GFP_KERNEL); | ||
| 1027 | if (!devpriv->ao_scan_vals) | 1028 | if (!devpriv->ao_scan_vals) |
| 1028 | return -ENOMEM; | 1029 | return -ENOMEM; |
| 1029 | 1030 | ||
| 1030 | /* Allocate buffer to hold AO channel scan order. */ | 1031 | /* Allocate buffer to hold AO channel scan order. */ |
| 1031 | devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) * | 1032 | devpriv->ao_scan_order = |
| 1032 | board->ao_chans, GFP_KERNEL); | 1033 | kmalloc_array(board->ao_chans, |
| 1034 | sizeof(devpriv->ao_scan_order[0]), | ||
| 1035 | GFP_KERNEL); | ||
| 1033 | if (!devpriv->ao_scan_order) | 1036 | if (!devpriv->ao_scan_order) |
| 1034 | return -ENOMEM; | 1037 | return -ENOMEM; |
| 1035 | 1038 | ||
| @@ -51,13 +51,13 @@ · 50 unmodified lines | |||
| 51 | 51 | ||
| 52 | /* DAC registers */ | 52 | /* DAC registers */ |
| 53 | #define CB_DDA_DA_CTRL_REG 0x00 /* D/A Control Register */ | 53 | #define CB_DDA_DA_CTRL_REG 0x00 /* D/A Control Register */ |
| 54 | #define CB_DDA_DA_CTRL_SU (1 << 0) /* Simultaneous update */ | 54 | #define CB_DDA_DA_CTRL_SU BIT(0) /* Simultaneous update */ |
| 55 | #define CB_DDA_DA_CTRL_EN (1 << 1) /* Enable specified DAC */ | 55 | #define CB_DDA_DA_CTRL_EN BIT(1) /* Enable specified DAC */ |
| 56 | #define CB_DDA_DA_CTRL_DAC(x) ((x) << 2) /* Specify DAC channel */ | 56 | #define CB_DDA_DA_CTRL_DAC(x) ((x) << 2) /* Specify DAC channel */ |
| 57 | #define CB_DDA_DA_CTRL_RANGE2V5 (0 << 6) /* 2.5V range */ | 57 | #define CB_DDA_DA_CTRL_RANGE2V5 (0 << 6) /* 2.5V range */ |
| 58 | #define CB_DDA_DA_CTRL_RANGE5V (2 << 6) /* 5V range */ | 58 | #define CB_DDA_DA_CTRL_RANGE5V (2 << 6) /* 5V range */ |
| 59 | #define CB_DDA_DA_CTRL_RANGE10V (3 << 6) /* 10V range */ | 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 | #define DACALIBRATION1 4 /* D/A CALIBRATION REGISTER 1 */ | 62 | #define DACALIBRATION1 4 /* D/A CALIBRATION REGISTER 1 */ |
| 63 | /* write bits */ | 63 | /* write bits */ |
| @@ -75,8 +75,8 @@ · 74 unmodified lines | |||
| 75 | #define PARPORT_DATA_REG 0x00 | 75 | #define PARPORT_DATA_REG 0x00 |
| 76 | #define PARPORT_STATUS_REG 0x01 | 76 | #define PARPORT_STATUS_REG 0x01 |
| 77 | #define PARPORT_CTRL_REG 0x02 | 77 | #define PARPORT_CTRL_REG 0x02 |
| 78 | #define PARPORT_CTRL_IRQ_ENA (1 << 4) | 78 | #define PARPORT_CTRL_IRQ_ENA BIT(4) |
| 79 | #define PARPORT_CTRL_BIDIR_ENA (1 << 5) | 79 | #define PARPORT_CTRL_BIDIR_ENA BIT(5) |
| 80 | 80 | ||
| 81 | static int parport_data_reg_insn_bits(struct comedi_device *dev, | 81 | static int parport_data_reg_insn_bits(struct comedi_device *dev, |
| 82 | struct comedi_subdevice *s, | 82 | struct comedi_subdevice *s, |
| @@ -801,9 +801,10 @@ static void das16_ai_munge(struct comedi_device *dev, · 800 unmodified lines | |||
| 801 | unsigned short *data = array; | 801 | unsigned short *data = array; |
| 802 | unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes); | 802 | unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes); |
| 803 | unsigned int i; | 803 | unsigned int i; |
| 804 | __le16 *buf = array; | ||
| 804 | 805 | ||
| 805 | for (i = 0; i < num_samples; i++) { | 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 | if (s->maxdata == 0x0fff) | 808 | if (s->maxdata == 0x0fff) |
| 808 | data[i] >>= 4; | 809 | data[i] >>= 4; |
| 809 | data[i] &= s->maxdata; | 810 | data[i] &= s->maxdata; |
| @@ -42,24 +42,24 @@ · 41 unmodified lines | |||
| 42 | #define NI6527_DO_REG(x) (0x03 + (x)) | 42 | #define NI6527_DO_REG(x) (0x03 + (x)) |
| 43 | #define NI6527_ID_REG 0x06 | 43 | #define NI6527_ID_REG 0x06 |
| 44 | #define NI6527_CLR_REG 0x07 | 44 | #define NI6527_CLR_REG 0x07 |
| 45 | #define NI6527_CLR_EDGE (1 << 3) | 45 | #define NI6527_CLR_EDGE BIT(3) |
| 46 | #define NI6527_CLR_OVERFLOW (1 << 2) | 46 | #define NI6527_CLR_OVERFLOW BIT(2) |
| 47 | #define NI6527_CLR_FILT (1 << 1) | 47 | #define NI6527_CLR_FILT BIT(1) |
| 48 | #define NI6527_CLR_INTERVAL (1 << 0) | 48 | #define NI6527_CLR_INTERVAL BIT(0) |
| 49 | #define NI6527_CLR_IRQS (NI6527_CLR_EDGE | NI6527_CLR_OVERFLOW) | 49 | #define NI6527_CLR_IRQS (NI6527_CLR_EDGE | NI6527_CLR_OVERFLOW) |
| 50 | #define NI6527_CLR_RESET_FILT (NI6527_CLR_FILT | NI6527_CLR_INTERVAL) | 50 | #define NI6527_CLR_RESET_FILT (NI6527_CLR_FILT | NI6527_CLR_INTERVAL) |
| 51 | #define NI6527_FILT_INTERVAL_REG(x) (0x08 + (x)) | 51 | #define NI6527_FILT_INTERVAL_REG(x) (0x08 + (x)) |
| 52 | #define NI6527_FILT_ENA_REG(x) (0x0c + (x)) | 52 | #define NI6527_FILT_ENA_REG(x) (0x0c + (x)) |
| 53 | #define NI6527_STATUS_REG 0x14 | 53 | #define NI6527_STATUS_REG 0x14 |
| 54 | #define NI6527_STATUS_IRQ (1 << 2) | 54 | #define NI6527_STATUS_IRQ BIT(2) |
| 55 | #define NI6527_STATUS_OVERFLOW (1 << 1) | 55 | #define NI6527_STATUS_OVERFLOW BIT(1) |
| 56 | #define NI6527_STATUS_EDGE (1 << 0) | 56 | #define NI6527_STATUS_EDGE BIT(0) |
| 57 | #define NI6527_CTRL_REG 0x15 | 57 | #define NI6527_CTRL_REG 0x15 |
| 58 | #define NI6527_CTRL_FALLING (1 << 4) | 58 | #define NI6527_CTRL_FALLING BIT(4) |
| 59 | #define NI6527_CTRL_RISING (1 << 3) | 59 | #define NI6527_CTRL_RISING BIT(3) |
| 60 | #define NI6527_CTRL_IRQ (1 << 2) | 60 | #define NI6527_CTRL_IRQ BIT(2) |
| 61 | #define NI6527_CTRL_OVERFLOW (1 << 1) | 61 | #define NI6527_CTRL_OVERFLOW BIT(1) |
| 62 | #define NI6527_CTRL_EDGE (1 << 0) | 62 | #define NI6527_CTRL_EDGE BIT(0) |
| 63 | #define NI6527_CTRL_DISABLE_IRQS 0 | 63 | #define NI6527_CTRL_DISABLE_IRQS 0 |
| 64 | #define NI6527_CTRL_ENABLE_IRQS (NI6527_CTRL_FALLING | \ | 64 | #define NI6527_CTRL_ENABLE_IRQS (NI6527_CTRL_FALLING | \ |
| 65 | NI6527_CTRL_RISING | \ | 65 | NI6527_CTRL_RISING | \ |
| @@ -68,25 +68,25 @@ · 67 unmodified lines | |||
| 68 | /* Non-recurring Registers (8-bit except where noted) */ | 68 | /* Non-recurring Registers (8-bit except where noted) */ |
| 69 | #define NI_65XX_ID_REG 0x00 | 69 | #define NI_65XX_ID_REG 0x00 |
| 70 | #define NI_65XX_CLR_REG 0x01 | 70 | #define NI_65XX_CLR_REG 0x01 |
| 71 | #define NI_65XX_CLR_WDOG_INT (1 << 6) | 71 | #define NI_65XX_CLR_WDOG_INT BIT(6) |
| 72 | #define NI_65XX_CLR_WDOG_PING (1 << 5) | 72 | #define NI_65XX_CLR_WDOG_PING BIT(5) |
| 73 | #define NI_65XX_CLR_WDOG_EXP (1 << 4) | 73 | #define NI_65XX_CLR_WDOG_EXP BIT(4) |
| 74 | #define NI_65XX_CLR_EDGE_INT (1 << 3) | 74 | #define NI_65XX_CLR_EDGE_INT BIT(3) |
| 75 | #define NI_65XX_CLR_OVERFLOW_INT (1 << 2) | 75 | #define NI_65XX_CLR_OVERFLOW_INT BIT(2) |
| 76 | #define NI_65XX_STATUS_REG 0x02 | 76 | #define NI_65XX_STATUS_REG 0x02 |
| 77 | #define NI_65XX_STATUS_WDOG_INT (1 << 5) | 77 | #define NI_65XX_STATUS_WDOG_INT BIT(5) |
| 78 | #define NI_65XX_STATUS_FALL_EDGE (1 << 4) | 78 | #define NI_65XX_STATUS_FALL_EDGE BIT(4) |
| 79 | #define NI_65XX_STATUS_RISE_EDGE (1 << 3) | 79 | #define NI_65XX_STATUS_RISE_EDGE BIT(3) |
| 80 | #define NI_65XX_STATUS_INT (1 << 2) | 80 | #define NI_65XX_STATUS_INT BIT(2) |
| 81 | #define NI_65XX_STATUS_OVERFLOW_INT (1 << 1) | 81 | #define NI_65XX_STATUS_OVERFLOW_INT BIT(1) |
| 82 | #define NI_65XX_STATUS_EDGE_INT (1 << 0) | 82 | #define NI_65XX_STATUS_EDGE_INT BIT(0) |
| 83 | #define NI_65XX_CTRL_REG 0x03 | 83 | #define NI_65XX_CTRL_REG 0x03 |
| 84 | #define NI_65XX_CTRL_WDOG_ENA (1 << 5) | 84 | #define NI_65XX_CTRL_WDOG_ENA BIT(5) |
| 85 | #define NI_65XX_CTRL_FALL_EDGE_ENA (1 << 4) | 85 | #define NI_65XX_CTRL_FALL_EDGE_ENA BIT(4) |
| 86 | #define NI_65XX_CTRL_RISE_EDGE_ENA (1 << 3) | 86 | #define NI_65XX_CTRL_RISE_EDGE_ENA BIT(3) |
| 87 | #define NI_65XX_CTRL_INT_ENA (1 << 2) | 87 | #define NI_65XX_CTRL_INT_ENA BIT(2) |
| 88 | #define NI_65XX_CTRL_OVERFLOW_ENA (1 << 1) | 88 | #define NI_65XX_CTRL_OVERFLOW_ENA BIT(1) |
| 89 | #define NI_65XX_CTRL_EDGE_ENA (1 << 0) | 89 | #define NI_65XX_CTRL_EDGE_ENA BIT(0) |
| 90 | #define NI_65XX_REV_REG 0x04 /* 32-bit */ | 90 | #define NI_65XX_REV_REG 0x04 /* 32-bit */ |
| 91 | #define NI_65XX_FILTER_REG 0x08 /* 32-bit */ | 91 | #define NI_65XX_FILTER_REG 0x08 /* 32-bit */ |
| 92 | #define NI_65XX_RTSI_ROUTE_REG 0x0c /* 16-bit */ | 92 | #define NI_65XX_RTSI_ROUTE_REG 0x0c /* 16-bit */ |
| @@ -94,24 +94,24 @@ · 1 unmodified line | |||
| 94 | #define NI_65XX_RTSI_WDOG_REG 0x10 /* 16-bit */ | 94 | #define NI_65XX_RTSI_WDOG_REG 0x10 /* 16-bit */ |
| 95 | #define NI_65XX_RTSI_TRIG_REG 0x12 /* 16-bit */ | 95 | #define NI_65XX_RTSI_TRIG_REG 0x12 /* 16-bit */ |
| 96 | #define NI_65XX_AUTO_CLK_SEL_REG 0x14 /* PXI-6528 only */ | 96 | #define NI_65XX_AUTO_CLK_SEL_REG 0x14 /* PXI-6528 only */ |
| 97 | #define NI_65XX_AUTO_CLK_SEL_STATUS (1 << 1) | 97 | #define NI_65XX_AUTO_CLK_SEL_STATUS BIT(1) |
| 98 | #define NI_65XX_AUTO_CLK_SEL_DISABLE (1 << 0) | 98 | #define NI_65XX_AUTO_CLK_SEL_DISABLE BIT(0) |
| 99 | #define NI_65XX_WDOG_CTRL_REG 0x15 | 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 | #define NI_65XX_RTSI_CFG_REG 0x16 | 101 | #define NI_65XX_RTSI_CFG_REG 0x16 |
| 102 | #define NI_65XX_RTSI_CFG_RISE_SENSE (1 << 2) | 102 | #define NI_65XX_RTSI_CFG_RISE_SENSE BIT(2) |
| 103 | #define NI_65XX_RTSI_CFG_FALL_SENSE (1 << 1) | 103 | #define NI_65XX_RTSI_CFG_FALL_SENSE BIT(1) |
| 104 | #define NI_65XX_RTSI_CFG_SYNC_DETECT (1 << 0) | 104 | #define NI_65XX_RTSI_CFG_SYNC_DETECT BIT(0) |
| 105 | #define NI_65XX_WDOG_STATUS_REG 0x17 | 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 | #define NI_65XX_WDOG_INTERVAL_REG 0x18 /* 32-bit */ | 107 | #define NI_65XX_WDOG_INTERVAL_REG 0x18 /* 32-bit */ |
| 108 | 108 | ||
| 109 | /* Recurring port registers (8-bit) */ | 109 | /* Recurring port registers (8-bit) */ |
| 110 | #define NI_65XX_PORT(x) ((x) * 0x10) | 110 | #define NI_65XX_PORT(x) ((x) * 0x10) |
| 111 | #define NI_65XX_IO_DATA_REG(x) (0x40 + NI_65XX_PORT(x)) | 111 | #define NI_65XX_IO_DATA_REG(x) (0x40 + NI_65XX_PORT(x)) |
| 112 | #define NI_65XX_IO_SEL_REG(x) (0x41 + NI_65XX_PORT(x)) | 112 | #define NI_65XX_IO_SEL_REG(x) (0x41 + NI_65XX_PORT(x)) |
| 113 | #define NI_65XX_IO_SEL_OUTPUT (0 << 0) | 113 | #define NI_65XX_IO_SEL_OUTPUT 0 |
| 114 | #define NI_65XX_IO_SEL_INPUT (1 << 0) | 114 | #define NI_65XX_IO_SEL_INPUT BIT(0) |
| 115 | #define NI_65XX_RISE_EDGE_ENA_REG(x) (0x42 + NI_65XX_PORT(x)) | 115 | #define NI_65XX_RISE_EDGE_ENA_REG(x) (0x42 + NI_65XX_PORT(x)) |
| 116 | #define NI_65XX_FALL_EDGE_ENA_REG(x) (0x43 + NI_65XX_PORT(x)) | 116 | #define NI_65XX_FALL_EDGE_ENA_REG(x) (0x43 + NI_65XX_PORT(x)) |
| 117 | #define NI_65XX_FILTER_ENA(x) (0x44 + NI_65XX_PORT(x)) | 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 | /* ripped from mite.h and mite_setup2() to avoid mite dependency */ | 614 | /* ripped from mite.h and mite_setup2() to avoid mite dependency */ |
| 615 | #define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ | 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 | static int ni_65xx_mite_init(struct pci_dev *pcidev) | 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 | if (s->n_chan == 32) { | 214 | if (s->n_chan == 32) { |
| 215 | const struct comedi_lrange **range_table_list; | 215 | const struct comedi_lrange **range_table_list; |
| 216 | 216 | ||
| 217 | range_table_list = kmalloc(sizeof(struct comedi_lrange *) * 32, | 217 | range_table_list = kmalloc_array(32, |
| 218 | GFP_KERNEL); | 218 | sizeof(struct comedi_lrange *), |
| 219 | GFP_KERNEL); | ||
| 219 | if (!range_table_list) | 220 | if (!range_table_list) |
| 220 | return -ENOMEM; | 221 | return -ENOMEM; |
| 221 | s->range_table_list = range_table_list; | 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 | return 0; | 579 | return 0; |
| 580 | } | 580 | } |
| 581 | 581 | ||
| 582 | /* negative channel means no channel */ | 582 | static inline void ni_set_ai_dma_channel(struct comedi_device *dev, |
| 583 | static inline void ni_set_ai_dma_channel(struct comedi_device *dev, int channel) | 583 | unsigned channel) |
| 584 | { | 584 | { |
| 585 | unsigned bits = 0; | 585 | unsigned bits = ni_stc_dma_channel_select_bitfield(channel); |
| 586 | |||
| 587 | if (channel >= 0) | ||
| 588 | bits = ni_stc_dma_channel_select_bitfield(channel); | ||
| 589 | 586 | ||
| 590 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, | 587 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
| 591 | NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits)); | 588 | NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits)); |
| 592 | } | 589 | } |
| 593 | 590 | ||
| 594 | /* negative channel means no channel */ | 591 | static inline void ni_set_ai_dma_no_channel(struct comedi_device *dev) |
| 595 | static inline void ni_set_ao_dma_channel(struct comedi_device *dev, int channel) | ||
| 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) | 596 | static inline void ni_set_ao_dma_channel(struct comedi_device *dev, |
| 600 | bits = ni_stc_dma_channel_select_bitfield(channel); | 597 | unsigned channel) |
| 598 | { | ||
| 599 | unsigned bits = ni_stc_dma_channel_select_bitfield(channel); | ||
| 601 | 600 | ||
| 602 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, | 601 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
| 603 | NI_E_DMA_AO_SEL_MASK, NI_E_DMA_AO_SEL(bits)); | 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 | static inline void ni_set_gpct_dma_channel(struct comedi_device *dev, | 610 | static inline void ni_set_gpct_dma_channel(struct comedi_device *dev, |
| 608 | unsigned gpct_index, | 611 | unsigned gpct_index, |
| 609 | int channel) | 612 | unsigned channel) |
| 610 | { | 613 | { |
| 611 | unsigned bits = 0; | 614 | unsigned bits = ni_stc_dma_channel_select_bitfield(channel); |
| 612 | |||
| 613 | if (channel >= 0) | ||
| 614 | bits = ni_stc_dma_channel_select_bitfield(channel); | ||
| 615 | 615 | ||
| 616 | ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, | 616 | ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, |
| 617 | NI_E_DMA_G0_G1_SEL_MASK(gpct_index), | 617 | NI_E_DMA_G0_G1_SEL_MASK(gpct_index), |
| 618 | NI_E_DMA_G0_G1_SEL(gpct_index, bits)); | 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 | static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, | 628 | static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, |
| 623 | int mite_channel) | 629 | unsigned mite_channel) |
| 624 | { | 630 | { |
| 625 | struct ni_private *devpriv = dev->private; | 631 | struct ni_private *devpriv = dev->private; |
| 626 | unsigned long flags; | 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 | spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); | 635 | spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); |
| 630 | devpriv->cdio_dma_select_reg &= ~NI_M_CDIO_DMA_SEL_CDO_MASK; | 636 | devpriv->cdio_dma_select_reg &= ~NI_M_CDIO_DMA_SEL_CDO_MASK; |
| 631 | if (mite_channel >= 0) { | 637 | /* |
| 632 | /* | 638 | * XXX just guessing ni_stc_dma_channel_select_bitfield() |
| 633 | * XXX just guessing ni_stc_dma_channel_select_bitfield() | 639 | * returns the right bits, under the assumption the cdio dma |
| 634 | * returns the right bits, under the assumption the cdio dma | 640 | * selection works just like ai/ao/gpct. |
| 635 | * selection works just like ai/ao/gpct. | 641 | * Definitely works for dma channels 0 and 1. |
| 636 | * Definitely works for dma channels 0 and 1. | 642 | */ |
| 637 | */ | 643 | bits = ni_stc_dma_channel_select_bitfield(mite_channel); |
| 638 | bits = ni_stc_dma_channel_select_bitfield(mite_channel); | 644 | devpriv->cdio_dma_select_reg |= NI_M_CDIO_DMA_SEL_CDO(bits); |
| 639 | 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); |
| 640 | } | 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 | ni_writeb(dev, devpriv->cdio_dma_select_reg, NI_M_CDIO_DMA_SEL_REG); | 657 | ni_writeb(dev, devpriv->cdio_dma_select_reg, NI_M_CDIO_DMA_SEL_REG); |
| 642 | mmiowb(); | 658 | mmiowb(); |
| 643 | spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); | 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 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); | 762 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 747 | if (devpriv->ai_mite_chan) { | 763 | if (devpriv->ai_mite_chan) { |
| 748 | ni_set_ai_dma_channel(dev, -1); | 764 | ni_set_ai_dma_no_channel(dev); |
| 749 | mite_release_channel(devpriv->ai_mite_chan); | 765 | mite_release_channel(devpriv->ai_mite_chan); |
| 750 | devpriv->ai_mite_chan = NULL; | 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 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); | 778 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 763 | if (devpriv->ao_mite_chan) { | 779 | if (devpriv->ao_mite_chan) { |
| 764 | ni_set_ao_dma_channel(dev, -1); | 780 | ni_set_ao_dma_no_channel(dev); |
| 765 | mite_release_channel(devpriv->ao_mite_chan); | 781 | mite_release_channel(devpriv->ao_mite_chan); |
| 766 | devpriv->ao_mite_chan = NULL; | 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 | struct mite_channel *mite_chan = | 797 | struct mite_channel *mite_chan = |
| 782 | devpriv->counter_dev->counters[gpct_index].mite_chan; | 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 | ni_tio_set_mite_channel(&devpriv-> | 801 | ni_tio_set_mite_channel(&devpriv-> |
| 786 | counter_dev->counters[gpct_index], | 802 | counter_dev->counters[gpct_index], |
| 787 | NULL); | 803 | NULL); |
| @@ -799,7 +815,7 @@ static void ni_release_cdo_mite_channel(struct comedi_device *dev) · 11 unmodified lines | |||
| 799 | 815 | ||
| 800 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); | 816 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 801 | if (devpriv->cdo_mite_chan) { | 817 | if (devpriv->cdo_mite_chan) { |
| 802 | ni_set_cdo_dma_channel(dev, -1); | 818 | ni_set_cdo_dma_no_channel(dev); |
| 803 | mite_release_channel(devpriv->cdo_mite_chan); | 819 | mite_release_channel(devpriv->cdo_mite_chan); |
| 804 | devpriv->cdo_mite_chan = NULL; | 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 | unsigned short *array = data; | 1532 | unsigned short *array = data; |
| 1517 | unsigned int *larray = data; | 1533 | unsigned int *larray = data; |
| 1518 | unsigned int i; | 1534 | unsigned int i; |
| 1535 | #ifdef PCIDMA | ||
| 1536 | __le16 *barray = data; | ||
| 1537 | __le32 *blarray = data; | ||
| 1538 | #endif | ||
| 1519 | 1539 | ||
| 1520 | for (i = 0; i < nsamples; i++) { | 1540 | for (i = 0; i < nsamples; i++) { |
| 1521 | #ifdef PCIDMA | 1541 | #ifdef PCIDMA |
| 1522 | if (s->subdev_flags & SDF_LSAMPL) | 1542 | if (s->subdev_flags & SDF_LSAMPL) |
| 1523 | larray[i] = le32_to_cpu(larray[i]); | 1543 | larray[i] = le32_to_cpu(blarray[i]); |
| 1524 | else | 1544 | else |
| 1525 | array[i] = le16_to_cpu(array[i]); | 1545 | array[i] = le16_to_cpu(barray[i]); |
| 1526 | #endif | 1546 | #endif |
| 1527 | if (s->subdev_flags & SDF_LSAMPL) | 1547 | if (s->subdev_flags & SDF_LSAMPL) |
| 1528 | larray[i] += devpriv->ai_offset[chan_index]; | 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 | unsigned int nsamples = comedi_bytes_to_samples(s, num_bytes); | 2594 | unsigned int nsamples = comedi_bytes_to_samples(s, num_bytes); |
| 2575 | unsigned short *array = data; | 2595 | unsigned short *array = data; |
| 2576 | unsigned int i; | 2596 | unsigned int i; |
| 2597 | #ifdef PCIDMA | ||
| 2598 | __le16 buf, *barray = data; | ||
| 2599 | #endif | ||
| 2577 | 2600 | ||
| 2578 | for (i = 0; i < nsamples; i++) { | 2601 | for (i = 0; i < nsamples; i++) { |
| 2579 | unsigned int range = CR_RANGE(cmd->chanlist[chan_index]); | 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 | if (comedi_range_is_bipolar(s, range)) | 2609 | if (comedi_range_is_bipolar(s, range)) |
| 2587 | val = comedi_offset_munge(s, val); | 2610 | val = comedi_offset_munge(s, val); |
| 2588 | #ifdef PCIDMA | 2611 | #ifdef PCIDMA |
| 2589 | val = cpu_to_le16(val); | 2612 | buf = cpu_to_le16(val); |
| 2590 | #endif | 2613 | barray[i] = buf; |
| 2614 | #else | ||
| 2591 | array[i] = val; | 2615 | array[i] = val; |
| 2592 | 2616 | #endif | |
| 2593 | chan_index++; | 2617 | chan_index++; |
| 2594 | chan_index %= cmd->chanlist_len; | 2618 | chan_index %= cmd->chanlist_len; |
| 2595 | } | 2619 | } |
| @@ -1,4 +1,5 @@ | |||
| 1 | /* plx9080.h | 1 | /* |
| 2 | * plx9080.h | ||
| 2 | * | 3 | * |
| 3 | * Copyright (C) 2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> | 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 | __le32 local_start_addr; | 34 | __le32 local_start_addr; |
| 34 | /* transfer_size is in bytes, only first 23 bits of register are used */ | 35 | /* transfer_size is in bytes, only first 23 bits of register are used */ |
| 35 | __le32 transfer_size; | 36 | __le32 transfer_size; |
| 36 | /* address of next descriptor (quad word aligned), plus some | 37 | /* |
| 37 | * additional bits (see PLX_DMA0_DESCRIPTOR_REG) */ | 38 | * address of next descriptor (quad word aligned), plus some |
| 39 | * additional bits (see PLX_DMA0_DESCRIPTOR_REG) | ||
| 40 | */ | ||
| 38 | __le32 next; | 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 */ | 52 | /* L, Local Addr Space 0 Range Register */ |
| 50 | #define PLX_LAS1RNG_REG 0x00f0 /* L, Local Addr Space 1 Range Register */ | 53 | #define PLX_LAS0RNG_REG 0x0000 |
| 54 | /* L, Local Addr Space 1 Range Register */ | ||
| 55 | #define PLX_LAS1RNG_REG 0x00f0 | ||
| 51 | #define LRNG_IO 0x00000001 /* Map to: 1=I/O, 0=Mem */ | 56 | #define LRNG_IO 0x00000001 /* Map to: 1=I/O, 0=Mem */ |
| 52 | #define LRNG_ANY32 0x00000000 /* Locate anywhere in 32 bit */ | 57 | #define LRNG_ANY32 0x00000000 /* Locate anywhere in 32 bit */ |
| 53 | #define LRNG_LT1MB 0x00000002 /* Locate in 1st meg */ | 58 | #define LRNG_LT1MB 0x00000002 /* Locate in 1st meg */ |
| 54 | #define LRNG_ANY64 0x00000004 /* Locate anywhere in 64 bit */ | 59 | #define LRNG_ANY64 0x00000004 /* Locate anywhere in 64 bit */ |
| 55 | #define LRNG_MEM_MASK 0xfffffff0 /* bits that specify range for memory io */ | 60 | /* bits that specify range for memory io */ |
| 56 | #define LRNG_IO_MASK 0xfffffffa /* bits that specify range for normal io */ | 61 | #define LRNG_MEM_MASK 0xfffffff0 |
| 57 | 62 | /* bits that specify range for normal io */ | |
| 58 | #define PLX_LAS0MAP_REG 0x0004 /* L, Local Addr Space 0 Remap Register */ | 63 | #define LRNG_IO_MASK 0xfffffffa |
| 59 | #define PLX_LAS1MAP_REG 0x00f4 /* L, Local Addr Space 1 Remap Register */ | 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 | #define LMAP_EN 0x00000001 /* Enable slave decode */ | 68 | #define LMAP_EN 0x00000001 /* Enable slave decode */ |
| 61 | #define LMAP_MEM_MASK 0xfffffff0 /* bits that specify decode for memory io */ | 69 | /* bits that specify decode for memory io */ |
| 62 | #define LMAP_IO_MASK 0xfffffffa /* bits that specify decode bits for normal 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. | 74 | /* |
| 65 | */ | 75 | * Mode/Arbitration Register. |
| 76 | */ | ||
| 66 | #define PLX_MARB_REG 0x8 /* L, Local Arbitration Register */ | 77 | #define PLX_MARB_REG 0x8 /* L, Local Arbitration Register */ |
| 67 | #define PLX_DMAARB_REG 0xac | 78 | #define PLX_DMAARB_REG 0xac |
| 68 | enum marb_bits { | 79 | enum marb_bits { |
| @@ -72,35 +83,45 @@ enum marb_bits { · 3 unmodified lines | |||
| 72 | MARB_LPEN = 0x00020000, /* Pause Timer Enable */ | 83 | MARB_LPEN = 0x00020000, /* Pause Timer Enable */ |
| 73 | MARB_BREQ = 0x00040000, /* Local Bus BREQ Enable */ | 84 | MARB_BREQ = 0x00040000, /* Local Bus BREQ Enable */ |
| 74 | MARB_DMA_PRIORITY_MASK = 0x00180000, | 85 | MARB_DMA_PRIORITY_MASK = 0x00180000, |
| 75 | MARB_LBDS_GIVE_UP_BUS_MODE = 0x00200000, /* local bus direct slave give up bus mode */ | 86 | /* local bus direct slave give up bus mode */ |
| 76 | MARB_DS_LLOCK_ENABLE = 0x00400000, /* direct slave LLOCKo# enable */ | 87 | MARB_LBDS_GIVE_UP_BUS_MODE = 0x00200000, |
| 88 | /* direct slave LLOCKo# enable */ | ||
| 89 | MARB_DS_LLOCK_ENABLE = 0x00400000, | ||
| 77 | MARB_PCI_REQUEST_MODE = 0x00800000, | 90 | MARB_PCI_REQUEST_MODE = 0x00800000, |
| 78 | MARB_PCIv21_MODE = 0x01000000, /* pci specification v2.1 mode */ | 91 | MARB_PCIv21_MODE = 0x01000000, /* pci specification v2.1 mode */ |
| 79 | MARB_PCI_READ_NO_WRITE_MODE = 0x02000000, | 92 | MARB_PCI_READ_NO_WRITE_MODE = 0x02000000, |
| 80 | MARB_PCI_READ_WITH_WRITE_FLUSH_MODE = 0x04000000, | 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 | MARB_PCI_READ_NO_FLUSH_MODE = 0x10000000, | 96 | MARB_PCI_READ_NO_FLUSH_MODE = 0x10000000, |
| 83 | MARB_USE_SUBSYSTEM_IDS = 0x20000000, | 97 | MARB_USE_SUBSYSTEM_IDS = 0x20000000, |
| 84 | }; | 98 | }; |
| 85 | 99 | ||
| 86 | #define PLX_BIGEND_REG 0xc | 100 | #define PLX_BIGEND_REG 0xc |
| 87 | enum bigend_bits { | 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 | BIGEND_DIRECT_MASTER = 0x2, | 104 | BIGEND_DIRECT_MASTER = 0x2, |
| 90 | BIGEND_DIRECT_SLAVE_LOCAL0 = 0x4, | 105 | BIGEND_DIRECT_SLAVE_LOCAL0 = 0x4, |
| 91 | BIGEND_ROM = 0x8, | 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 | BIGEND_DIRECT_SLAVE_LOCAL1 = 0x20, | 112 | BIGEND_DIRECT_SLAVE_LOCAL1 = 0x20, |
| 94 | BIGEND_DMA1 = 0x40, | 113 | BIGEND_DMA1 = 0x40, |
| 95 | BIGEND_DMA0 = 0x80, | 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 | ** This expansion ROM code is executed by the host CPU at boot time. | 119 | ** This expansion ROM code is executed by the host CPU at boot time. |
| 100 | ** For this reason no bit definitions are provided here. | 120 | ** For this reason no bit definitions are provided here. |
| 101 | */ | 121 | */ |
| 102 | #define PLX_ROMRNG_REG 0x0010 /* L, Expn ROM Space Range Register */ | 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 | #define PLX_REGION0_REG 0x0018 /* L, Local Bus Region 0 Descriptor */ | 126 | #define PLX_REGION0_REG 0x0018 /* L, Local Bus Region 0 Descriptor */ |
| 106 | #define RGN_WIDTH 0x00000002 /* Local bus width bits */ | 127 | #define RGN_WIDTH 0x00000002 /* Local bus width bits */ |
| @@ -190,7 +211,8 @@ enum bigend_bits { · 83 unmodified lines | |||
| 190 | #define ICS_TA_DMA0 0x02000000 /* Target Abort - DMA #0 */ | 211 | #define ICS_TA_DMA0 0x02000000 /* Target Abort - DMA #0 */ |
| 191 | #define ICS_TA_DMA1 0x04000000 /* Target Abort - DMA #1 */ | 212 | #define ICS_TA_DMA1 0x04000000 /* Target Abort - DMA #1 */ |
| 192 | #define ICS_TA_RA 0x08000000 /* Target Abort - Retry Timeout */ | 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 | #define PLX_CONTROL_REG 0x006C /* L, EEPROM Cntl & PCI Cmd Codes */ | 217 | #define PLX_CONTROL_REG 0x006C /* L, EEPROM Cntl & PCI Cmd Codes */ |
| 196 | #define CTL_RDMA 0x0000000E /* DMA Read Command */ | 218 | #define CTL_RDMA 0x0000000E /* DMA Read Command */ |
| @@ -221,28 +243,38 @@ enum bigend_bits { · 24 unmodified lines | |||
| 221 | #define PLX_EN_BTERM_BIT 0x80 /* enable BTERM# input */ | 243 | #define PLX_EN_BTERM_BIT 0x80 /* enable BTERM# input */ |
| 222 | #define PLX_DMA_LOCAL_BURST_EN_BIT 0x100 /* enable local burst mode */ | 244 | #define PLX_DMA_LOCAL_BURST_EN_BIT 0x100 /* enable local burst mode */ |
| 223 | #define PLX_EN_CHAIN_BIT 0x200 /* enables chaining */ | 245 | #define PLX_EN_CHAIN_BIT 0x200 /* enables chaining */ |
| 224 | #define PLX_EN_DMA_DONE_INTR_BIT 0x400 /* enables interrupt on dma done */ | 246 | /* enables interrupt on dma done */ |
| 225 | #define PLX_LOCAL_ADDR_CONST_BIT 0x800 /* hold local address constant (don't increment) */ | 247 | #define PLX_EN_DMA_DONE_INTR_BIT 0x400 |
| 226 | #define PLX_DEMAND_MODE_BIT 0x1000 /* enables demand-mode for dma transfer */ | 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 | #define PLX_EOT_ENABLE_BIT 0x4000 | 252 | #define PLX_EOT_ENABLE_BIT 0x4000 |
| 228 | #define PLX_STOP_MODE_BIT 0x8000 | 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 | #define PLX_DMA1_PCI_ADDRESS_REG 0x98 | 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 | #define PLX_DMA1_LOCAL_ADDRESS_REG 0x9c | 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 | #define PLX_DMA1_TRANSFER_SIZE_REG 0xa0 | 267 | #define PLX_DMA1_TRANSFER_SIZE_REG 0xa0 |
| 239 | 268 | ||
| 240 | #define PLX_DMA0_DESCRIPTOR_REG 0x90 /* descriptor pointer register */ | 269 | #define PLX_DMA0_DESCRIPTOR_REG 0x90 /* descriptor pointer register */ |
| 241 | #define PLX_DMA1_DESCRIPTOR_REG 0xa4 | 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 | #define PLX_END_OF_CHAIN_BIT 0x2 /* end of chain bit */ | 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 */ | 274 | /* 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) */ | 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 | #define PLX_DMA0_CS_REG 0xa8 /* command status register */ | 279 | #define PLX_DMA0_CS_REG 0xa8 /* command status register */ |
| 248 | #define PLX_DMA1_CS_REG 0xa9 | 280 | #define PLX_DMA1_CS_REG 0xa9 |
| @@ -288,10 +320,11 @@ enum bigend_bits { · 39 unmodified lines | |||
| 288 | #define MBX_STS_PCIRESET 0x00000100 /* Host issued PCI reset request */ | 320 | #define MBX_STS_PCIRESET 0x00000100 /* Host issued PCI reset request */ |
| 289 | #define MBX_STS_BUSY 0x00000080 /* PUTS is in progress */ | 321 | #define MBX_STS_BUSY 0x00000080 /* PUTS is in progress */ |
| 290 | #define MBX_STS_ERROR 0x00000040 /* PUTS has failed */ | 322 | #define MBX_STS_ERROR 0x00000040 /* PUTS has failed */ |
| 291 | #define MBX_STS_RESERVED 0x000000c0 /* Undefined -> status in transition. | 323 | /* |
| 292 | We are in process of changing | 324 | * Undefined -> status in transition. We are in process of changing bits; |
| 293 | bits; we SET Error bit before | 325 | * we SET Error bit before RESET of Busy bit |
| 294 | RESET of Busy bit */ | 326 | */ |
| 327 | #define MBX_STS_RESERVED 0x000000c0 | ||
| 295 | 328 | ||
| 296 | #define MBX_RESERVED_5 0x00000020 /* FYI: reserved/unused bit */ | 329 | #define MBX_RESERVED_5 0x00000020 /* FYI: reserved/unused bit */ |
| 297 | #define MBX_RESERVED_4 0x00000010 /* FYI: reserved/unused bit */ | 330 | #define MBX_RESERVED_4 0x00000010 /* FYI: reserved/unused bit */ |
| @@ -320,12 +353,12 @@ enum bigend_bits { · 22 unmodified lines | |||
| 320 | #define MBX_CMD_BSWAP_0 0x8c000000 /* use scheme 0 */ | 353 | #define MBX_CMD_BSWAP_0 0x8c000000 /* use scheme 0 */ |
| 321 | #define MBX_CMD_BSWAP_1 0x8c000001 /* use scheme 1 */ | 354 | #define MBX_CMD_BSWAP_1 0x8c000001 /* use scheme 1 */ |
| 322 | 355 | ||
| 323 | #define MBX_CMD_SETHMS 0x8d000000 /* setup host memory access window | 356 | /* setup host memory access window size */ |
| 324 | size */ | 357 | #define MBX_CMD_SETHMS 0x8d000000 |
| 325 | #define MBX_CMD_SETHBA 0x8e000000 /* setup host memory access base | 358 | /* setup host memory access base address */ |
| 326 | address */ | 359 | #define MBX_CMD_SETHBA 0x8e000000 |
| 327 | #define MBX_CMD_MGO 0x8f000000 /* perform memory setup and continue | 360 | /* perform memory setup and continue (IE. Done) */ |
| 328 | (IE. Done) */ | 361 | #define MBX_CMD_MGO 0x8f000000 |
| 329 | #define MBX_CMD_NOOP 0xFF000000 /* dummy, illegal command */ | 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 | #define MBX_BTYPE_MASK 0x0000ffff /* PUTS Board Type Register */ | 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 | #define MBX_BTYPE_SUBTYPE_MASK 0x000000ff /* PUTS Board Subtype */ | 386 | #define MBX_BTYPE_SUBTYPE_MASK 0x000000ff /* PUTS Board Subtype */ |
| 353 | 387 | ||
| 354 | #define MBX_BTYPE_PLX9060 0x00000100 /* PLX family type */ | 388 | #define MBX_BTYPE_PLX9060 0x00000100 /* PLX family type */ |
| @@ -378,12 +412,12 @@ enum bigend_bits { · 23 unmodified lines | |||
| 378 | 412 | ||
| 379 | /* system allocates this many bytes for address mapping mailbox space */ | 413 | /* system allocates this many bytes for address mapping mailbox space */ |
| 380 | #define MBX_ADDR_SPACE_360 0x80 /* wanXL100s/200/400 */ | 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 | static inline int plx9080_abort_dma(void __iomem *iobase, unsigned int channel) | 417 | static inline int plx9080_abort_dma(void __iomem *iobase, unsigned int channel) |
| 384 | { | 418 | { |
| 385 | void __iomem *dma_cs_addr; | 419 | void __iomem *dma_cs_addr; |
| 386 | uint8_t dma_status; | 420 | u8 dma_status; |
| 387 | const int timeout = 10000; | 421 | const int timeout = 10000; |
| 388 | unsigned int i; | 422 | unsigned int i; |
| 389 | 423 | ||
| @@ -37,7 +37,6 @@ · 36 unmodified lines | |||
| 37 | 37 | ||
| 38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
| 39 | #include "../comedidev.h" | 39 | #include "../comedidev.h" |
| 40 | #include <asm/byteorder.h> | ||
| 41 | 40 | ||
| 42 | /* | 41 | /* |
| 43 | * Register I/O map | 42 | * Register I/O map |
| @@ -84,7 +83,92 @@ · 40 unmodified lines | |||
| 84 | #define S526_GPCT_LSB_REG(x) (0x12 + ((x) * 8)) | 83 | #define S526_GPCT_LSB_REG(x) (0x12 + ((x) * 8)) |
| 85 | #define S526_GPCT_MSB_REG(x) (0x14 + ((x) * 8)) | 84 | #define S526_GPCT_MSB_REG(x) (0x14 + ((x) * 8)) |
| 86 | #define S526_GPCT_MODE_REG(x) (0x16 + ((x) * 8)) | 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 | #define S526_GPCT_CTRL_REG(x) (0x18 + ((x) * 8)) | 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 | #define S526_EEPROM_DATA_REG 0x32 | 172 | #define S526_EEPROM_DATA_REG 0x32 |
| 89 | #define S526_EEPROM_CTRL_REG 0x34 | 173 | #define S526_EEPROM_CTRL_REG 0x34 |
| 90 | #define S526_EEPROM_CTRL_ADDR(x) (((x) & 0x3f) << 3) | 174 | #define S526_EEPROM_CTRL_ADDR(x) (((x) & 0x3f) << 3) |
| @@ -92,41 +176,6 @@ · 1 unmodified line | |||
| 92 | #define S526_EEPROM_CTRL_READ S526_EEPROM_CTRL(2) | 176 | #define S526_EEPROM_CTRL_READ S526_EEPROM_CTRL(2) |
| 93 | #define S526_EEPROM_CTRL_START BIT(0) | 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 | struct s526_private { | 179 | struct s526_private { |
| 131 | unsigned int gpct_config[4]; | 180 | unsigned int gpct_config[4]; |
| 132 | unsigned short ai_ctrl; | 181 | unsigned short ai_ctrl; |
| @@ -174,7 +223,6 @@ static int s526_gpct_insn_config(struct comedi_device *dev, · 41 unmodified lines | |||
| 174 | struct s526_private *devpriv = dev->private; | 223 | struct s526_private *devpriv = dev->private; |
| 175 | unsigned int chan = CR_CHAN(insn->chanspec); | 224 | unsigned int chan = CR_CHAN(insn->chanspec); |
| 176 | unsigned int val; | 225 | unsigned int val; |
| 177 | union cmReg cmReg; | ||
| 178 | 226 | ||
| 179 | /* | 227 | /* |
| 180 | * Check what type of Counter the user requested | 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 | #if 1 | 241 | #if 1 |
| 194 | /* Set Counter Mode Register */ | 242 | /* Set Counter Mode Register */ |
| 195 | cmReg.value = data[1] & 0xffff; | 243 | val = data[1] & 0xffff; |
| 196 | outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | 244 | outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); |
| 197 | 245 | ||
| 198 | /* Reset the counter if it is software preload */ | 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 | /* Reset the counter */ | 249 | /* Reset the counter */ |
| 201 | outw(0x8000, dev->iobase + S526_GPCT_CTRL_REG(chan)); | 250 | outw(S526_GPCT_CTRL_CT_RESET, |
| 202 | /* Load the counter from PR0 | 251 | dev->iobase + S526_GPCT_CTRL_REG(chan)); |
| 203 | * outw(0x4000, 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 | #else | 258 | #else |
| 207 | /* 0 quadrature, 1 software control */ | 259 | val = S526_GPCT_MODE_CTDIR_CTRL_QUAD; |
| 208 | cmReg.reg.countDirCtrl = 0; | ||
| 209 | 260 | ||
| 210 | /* data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4 */ | 261 | /* data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4 */ |
| 211 | if (data[1] == GPCT_X2) | 262 | if (data[1] == GPCT_X2) |
| 212 | cmReg.reg.clockSource = 1; | 263 | val |= S526_GPCT_MODE_CLK_SRC_QUADX2; |
| 213 | else if (data[1] == GPCT_X4) | 264 | else if (data[1] == GPCT_X4) |
| 214 | cmReg.reg.clockSource = 2; | 265 | val |= S526_GPCT_MODE_CLK_SRC_QUADX4; |
| 215 | else | 266 | else |
| 216 | cmReg.reg.clockSource = 0; | 267 | val |= S526_GPCT_MODE_CLK_SRC_QUADX1; |
| 217 | 268 | ||
| 218 | /* When to take into account the indexpulse: */ | 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 | /* Take into account the index pulse? */ | 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 | /* Auto load with INDEX^ */ | 279 | /* Auto load with INDEX^ */ |
| 229 | cmReg.reg.autoLoadResetRcap = 4; | 280 | val |= S526_GPCT_MODE_AUTOLOAD_IXRISE; |
| 281 | } | ||
| 230 | 282 | ||
| 231 | /* Set Counter Mode Register */ | 283 | /* Set Counter Mode Register */ |
| 232 | cmReg.value = data[1] & 0xffff; | 284 | val = data[1] & 0xffff; |
| 233 | outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | 285 | outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); |
| 234 | 286 | ||
| 235 | /* Load the pre-load register */ | 287 | /* Load the pre-load register */ |
| 236 | s526_gpct_write(dev, chan, data[2]); | 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 | dev->iobase + S526_GPCT_CTRL_REG(chan)); | 293 | dev->iobase + S526_GPCT_CTRL_REG(chan)); |
| 242 | 294 | ||
| 243 | /* Reset the counter if it is software preload */ | 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 | /* Reset the counter */ | 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 | /* Load the counter from PR0 */ | 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 | #endif | 305 | #endif |
| 251 | break; | 306 | break; |
| @@ -261,17 +316,21 @@ static int s526_gpct_insn_config(struct comedi_device *dev, · 9 unmodified lines | |||
| 261 | devpriv->gpct_config[chan] = data[0]; | 316 | devpriv->gpct_config[chan] = data[0]; |
| 262 | 317 | ||
| 263 | /* Set Counter Mode Register */ | 318 | /* Set Counter Mode Register */ |
| 264 | cmReg.value = data[1] & 0xffff; | 319 | val = data[1] & 0xffff; |
| 265 | cmReg.reg.preloadRegSel = 0; /* PR0 */ | 320 | /* Select PR0 */ |
| 266 | outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | 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 | /* Load the pre-load register 0 */ | 325 | /* Load the pre-load register 0 */ |
| 269 | s526_gpct_write(dev, chan, data[2]); | 326 | s526_gpct_write(dev, chan, data[2]); |
| 270 | 327 | ||
| 271 | /* Set Counter Mode Register */ | 328 | /* Set Counter Mode Register */ |
| 272 | cmReg.value = data[1] & 0xffff; | 329 | val = data[1] & 0xffff; |
| 273 | cmReg.reg.preloadRegSel = 1; /* PR1 */ | 330 | /* Select PR1 */ |
| 274 | outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | 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 | /* Load the pre-load register 1 */ | 335 | /* Load the pre-load register 1 */ |
| 277 | s526_gpct_write(dev, chan, data[3]); | 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 | devpriv->gpct_config[chan] = data[0]; | 353 | devpriv->gpct_config[chan] = data[0]; |
| 295 | 354 | ||
| 296 | /* Set Counter Mode Register */ | 355 | /* Set Counter Mode Register */ |
| 297 | cmReg.value = data[1] & 0xffff; | 356 | val = data[1] & 0xffff; |
| 298 | cmReg.reg.preloadRegSel = 0; /* PR0 */ | 357 | /* Select PR0 */ |
| 299 | outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | 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 | /* Load the pre-load register 0 */ | 362 | /* Load the pre-load register 0 */ |
| 302 | s526_gpct_write(dev, chan, data[2]); | 363 | s526_gpct_write(dev, chan, data[2]); |
| 303 | 364 | ||
| 304 | /* Set Counter Mode Register */ | 365 | /* Set Counter Mode Register */ |
| 305 | cmReg.value = data[1] & 0xffff; | 366 | val = data[1] & 0xffff; |
| 306 | cmReg.reg.preloadRegSel = 1; /* PR1 */ | 367 | /* Select PR1 */ |
| 307 | outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); | 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 | /* Load the pre-load register 1 */ | 372 | /* Load the pre-load register 1 */ |
| 310 | s526_gpct_write(dev, chan, data[3]); | 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 | writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), | 935 | writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), |
| 936 | &ch->ch_cls_uart->isr_fcr); | 936 | &ch->ch_cls_uart->isr_fcr); |
| 937 | udelay(10); | 937 | usleep_range(10, 20); |
| 938 | 938 | ||
| 939 | ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); | 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 | * On the other hand, if the UART IS in FIFO mode, then ask | 1108 | * On the other hand, if the UART IS in FIFO mode, then ask |
| 1109 | * the UART to give us an approximation of data it has RX'ed. | 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 | total = 0; | 1112 | total = 0; |
| 1113 | else { | 1113 | } else { |
| 1114 | total = readb(&ch->ch_neo_uart->rfifo); | 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 | /* Clear out UART and FIFO */ | 1629 | /* Clear out UART and FIFO */ |
| 1630 | readb(&ch->ch_neo_uart->txrx); | 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 | readb(&ch->ch_neo_uart->lsr); | 1632 | readb(&ch->ch_neo_uart->lsr); |
| 1633 | readb(&ch->ch_neo_uart->msr); | 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 | /* Store the VPD into our buffer */ | 1779 | /* Store the VPD into our buffer */ |
| 1780 | for (i = 0; i < NEO_VPD_IMAGESIZE; i++) { | 1780 | for (i = 0; i < NEO_VPD_IMAGESIZE; i++) { |
| 1781 | a = neo_read_eeprom(brd->re_map_membase, i); | 1781 | a = neo_read_eeprom(brd->re_map_membase, i); |
| 1782 | brd->vpd[i*2] = a & 0xff; | 1782 | brd->vpd[i * 2] = a & 0xff; |
| 1783 | brd->vpd[(i*2)+1] = (a >> 8) & 0xff; | 1783 | brd->vpd[(i * 2) + 1] = (a >> 8) & 0xff; |
| 1784 | } | 1784 | } |
| 1785 | 1785 | ||
| 1786 | if (((brd->vpd[0x08] != 0x82) /* long resource name tag */ | 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 | * dgnc_wmove - Write data to transmit queue. | 448 | * dgnc_wmove - Write data to transmit queue. |
| 449 | * | 449 | * |
| 450 | * ch - Pointer to channel structure. | 450 | * ch - Pointer to channel structure. |
| 451 | * buf - Poiter to characters to be moved. | 451 | * buf - Pointer to characters to be moved. |
| 452 | * n - Number of characters to move. | 452 | * n - Number of characters to move. |
| 453 | * | 453 | * |
| 454 | *=======================================================================*/ | 454 | *=======================================================================*/ |
| @@ -1,7 +1,6 @@ | |||
| 1 | #include <linux/tty.h> | 1 | #include <linux/tty.h> |
| 2 | #include <linux/sched.h> | 2 | #include <linux/sched.h> |
| 3 | #include "dgnc_utils.h" | 3 | #include "dgnc_utils.h" |
| 4 | #include "digi.h" | ||
| 5 | 4 | ||
| 6 | /* | 5 | /* |
| 7 | * dgnc_ms_sleep() | 6 | * dgnc_ms_sleep() |
| @@ -823,7 +823,7 @@ static int _nbu2ss_out_dma( · 822 unmodified lines | |||
| 823 | u32 length | 823 | u32 length |
| 824 | ) | 824 | ) |
| 825 | { | 825 | { |
| 826 | u8 *pBuffer; | 826 | dma_addr_t pBuffer; |
| 827 | u32 mpkt; | 827 | u32 mpkt; |
| 828 | u32 lmpkt; | 828 | u32 lmpkt; |
| 829 | u32 dmacnt; | 829 | u32 dmacnt; |
| @@ -836,7 +836,7 @@ static int _nbu2ss_out_dma( · 6 unmodified lines | |||
| 836 | return 1; /* DMA is forwarded */ | 836 | return 1; /* DMA is forwarded */ |
| 837 | 837 | ||
| 838 | req->dma_flag = TRUE; | 838 | req->dma_flag = TRUE; |
| 839 | pBuffer = (u8 *)req->req.dma; | 839 | pBuffer = req->req.dma; |
| 840 | pBuffer += req->req.actual; | 840 | pBuffer += req->req.actual; |
| 841 | 841 | ||
| 842 | /* DMA Address */ | 842 | /* DMA Address */ |
| @@ -1034,7 +1034,7 @@ static int _nbu2ss_in_dma( · 191 unmodified lines | |||
| 1034 | u32 length | 1034 | u32 length |
| 1035 | ) | 1035 | ) |
| 1036 | { | 1036 | { |
| 1037 | u8 *pBuffer; | 1037 | dma_addr_t pBuffer; |
| 1038 | u32 mpkt; /* MaxPacketSize */ | 1038 | u32 mpkt; /* MaxPacketSize */ |
| 1039 | u32 lmpkt; /* Last Packet Data Size */ | 1039 | u32 lmpkt; /* Last Packet Data Size */ |
| 1040 | u32 dmacnt; /* IN Data Size */ | 1040 | u32 dmacnt; /* IN Data Size */ |
| @@ -1080,7 +1080,7 @@ static int _nbu2ss_in_dma( · 39 unmodified lines | |||
| 1080 | _nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, data); | 1080 | _nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, data); |
| 1081 | 1081 | ||
| 1082 | /* Address setting */ | 1082 | /* Address setting */ |
| 1083 | pBuffer = (u8 *)req->req.dma; | 1083 | pBuffer = req->req.dma; |
| 1084 | pBuffer += req->req.actual; | 1084 | pBuffer += req->req.actual; |
| 1085 | _nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)pBuffer); | 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 | bool bflag = FALSE; | 1285 | bool bflag = FALSE; |
| 1286 | struct nbu2ss_req *req; | 1286 | struct nbu2ss_req *req; |
| 1287 | 1287 | ||
| 1288 | if (list_empty(&ep->queue)) | 1288 | req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); |
| 1289 | req = NULL; | ||
| 1290 | else | ||
| 1291 | req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | ||
| 1292 | |||
| 1293 | if (!req) | 1289 | if (!req) |
| 1294 | return; | 1290 | return; |
| 1295 | 1291 | ||
| @@ -1784,11 +1780,7 @@ static inline int _nbu2ss_ep0_in_data_stage(struct nbu2ss_udc *udc) · 488 unmodified lines | |||
| 1784 | struct nbu2ss_req *req; | 1780 | struct nbu2ss_req *req; |
| 1785 | struct nbu2ss_ep *ep = &udc->ep[0]; | 1781 | struct nbu2ss_ep *ep = &udc->ep[0]; |
| 1786 | 1782 | ||
| 1787 | if (list_empty(&ep->queue)) | 1783 | req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); |
| 1788 | req = NULL; | ||
| 1789 | else | ||
| 1790 | req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | ||
| 1791 | |||
| 1792 | if (!req) | 1784 | if (!req) |
| 1793 | req = &udc->ep0_req; | 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 | struct nbu2ss_req *req; | 1803 | struct nbu2ss_req *req; |
| 1812 | struct nbu2ss_ep *ep = &udc->ep[0]; | 1804 | struct nbu2ss_ep *ep = &udc->ep[0]; |
| 1813 | 1805 | ||
| 1814 | if (list_empty(&ep->queue)) | 1806 | req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); |
| 1815 | req = NULL; | ||
| 1816 | else | ||
| 1817 | req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | ||
| 1818 | |||
| 1819 | if (!req) | 1807 | if (!req) |
| 1820 | req = &udc->ep0_req; | 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 | struct nbu2ss_req *req; | 1826 | struct nbu2ss_req *req; |
| 1839 | struct nbu2ss_ep *ep = &udc->ep[0]; | 1827 | struct nbu2ss_ep *ep = &udc->ep[0]; |
| 1840 | 1828 | ||
| 1841 | if (list_empty(&ep->queue)) | 1829 | req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); |
| 1842 | req = NULL; | ||
| 1843 | else | ||
| 1844 | req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | ||
| 1845 | |||
| 1846 | if (!req) { | 1830 | if (!req) { |
| 1847 | req = &udc->ep0_req; | 1831 | req = &udc->ep0_req; |
| 1848 | if (req->req.complete) | 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 | /* Interrupt Clear */ | 2129 | /* Interrupt Clear */ |
| 2146 | _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_STATUS, ~(u32)status); | 2130 | _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_STATUS, ~(u32)status); |
| 2147 | 2131 | ||
| 2148 | if (list_empty(&ep->queue)) | 2132 | req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); |
| 2149 | req = NULL; | ||
| 2150 | else | ||
| 2151 | req = list_entry(ep->queue.next, struct nbu2ss_req, queue); | ||
| 2152 | |||
| 2153 | if (!req) { | 2133 | if (!req) { |
| 2154 | /* pr_warn("=== %s(%d) req == NULL\n", __func__, epnum); */ | 2134 | /* pr_warn("=== %s(%d) req == NULL\n", __func__, epnum); */ |
| 2155 | return; | 2135 | return; |
| @@ -2728,7 +2708,7 @@ static int nbu2ss_ep_queue( · 572 unmodified lines | |||
| 2728 | spin_lock_irqsave(&udc->lock, flags); | 2708 | spin_lock_irqsave(&udc->lock, flags); |
| 2729 | 2709 | ||
| 2730 | #ifdef USE_DMA | 2710 | #ifdef USE_DMA |
| 2731 | if ((u32)req->req.buf & 0x3) | 2711 | if ((uintptr_t)req->req.buf & 0x3) |
| 2732 | req->unaligned = TRUE; | 2712 | req->unaligned = TRUE; |
| 2733 | else | 2713 | else |
| 2734 | req->unaligned = FALSE; | 2714 | req->unaligned = FALSE; |
| @@ -893,11 +893,10 @@ static void fwserial_destroy(struct kref *kref) · 892 unmodified lines | |||
| 893 | kfree(serial); | 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 | kref_put(&port->serial->kref, fwserial_destroy); | 898 | kref_put(&port->serial->kref, fwserial_destroy); |
| 899 | } | 899 | } |
| 900 | EXPORT_SYMBOL(fwtty_port_put); | ||
| 901 | 900 | ||
| 902 | static void fwtty_port_dtr_rts(struct tty_port *tty_port, int on) | 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 | extern struct tty_driver *fwtty_driver; | 342 | extern struct tty_driver *fwtty_driver; |
| 343 | 343 | ||
| 344 | struct fwtty_port *fwtty_port_get(unsigned index); | 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 | * Returns the max send async payload size in bytes based on the unit device | 346 | * Returns the max send async payload size in bytes based on the unit device |
| 357 | * link speed. Self-limiting asynchronous bandwidth (via reducing the payload) | 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 | void gdm_lte_event_exit(void) | 555 | void gdm_lte_event_exit(void) |
| 556 | { | 556 | { |
| 557 | if (lte_event.sock && --lte_event.ref_cnt == 0) { | 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 | lte_event.sock = NULL; | 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 | kfree(gdm); | 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 | .destruct = gdm_port_destruct, | 68 | .destruct = gdm_port_destruct, |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| @@ -107,11 +107,6 @@ struct sock *netlink_init(int unit, · 106 unmodified lines | |||
| 107 | return sock; | 107 | return sock; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | void netlink_exit(struct sock *sock) | ||
| 111 | { | ||
| 112 | sock_release(sock->sk_socket); | ||
| 113 | } | ||
| 114 | |||
| 115 | int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len) | 110 | int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len) |
| 116 | { | 111 | { |
| 117 | static u32 seq; | 112 | static u32 seq; |
| @@ -19,7 +19,6 @@ · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | struct sock *netlink_init(int unit, | 20 | struct sock *netlink_init(int unit, |
| 21 | void (*cb)(struct net_device *dev, u16 type, void *msg, int len)); | 21 | void (*cb)(struct net_device *dev, u16 type, void *msg, int len)); |
| 22 | void netlink_exit(struct sock *sock); | ||
| 23 | int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len); | 22 | int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len); |
| 24 | 23 | ||
| 25 | #endif /* _NETLINK_K_H_ */ | 24 | #endif /* _NETLINK_K_H_ */ |
| @@ -101,7 +101,7 @@ void gdm_qos_init(void *nic_ptr) · 100 unmodified lines | |||
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | qcb->qos_list_cnt = 0; | 103 | qcb->qos_list_cnt = 0; |
| 104 | qcb->qos_null_idx = QOS_MAX-1; | 104 | qcb->qos_null_idx = QOS_MAX - 1; |
| 105 | qcb->qos_limit_size = 255; | 105 | qcb->qos_limit_size = 255; |
| 106 | 106 | ||
| 107 | spin_lock_init(&qcb->qos_lock); | 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 | qcb->qos_list_cnt = 0; | 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 | for (i = 0; i < QOS_MAX; i++) { | 133 | for (i = 0; i < QOS_MAX; i++) { |
| 134 | list_for_each_entry_safe(entry, n, &qcb->qos_list[i], list) { | 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 | int i; | 144 | int i; |
| 145 | 145 | ||
| 146 | if (csr->classifier_rule_en&IPTYPEOFSERVICE) { | 146 | if (csr->classifier_rule_en & IPTYPEOFSERVICE) { |
| 147 | if (((stream[1] & csr->ip2s_mask) < csr->ip2s_lo) || | 147 | if (((stream[1] & csr->ip2s_mask) < csr->ip2s_lo) || |
| 148 | ((stream[1] & csr->ip2s_mask) > csr->ip2s_hi)) | 148 | ((stream[1] & csr->ip2s_mask) > csr->ip2s_hi)) |
| 149 | return 1; | 149 | return 1; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | if (csr->classifier_rule_en&PROTOCOL) { | 152 | if (csr->classifier_rule_en & PROTOCOL) { |
| 153 | if (stream[9] != csr->protocol) | 153 | if (stream[9] != csr->protocol) |
| 154 | return 1; | 154 | return 1; |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | if (csr->classifier_rule_en&IPMASKEDSRCADDRESS) { | 157 | if (csr->classifier_rule_en & IPMASKEDSRCADDRESS) { |
| 158 | for (i = 0; i < 4; i++) { | 158 | for (i = 0; i < 4; i++) { |
| 159 | if ((stream[12 + i] & csr->ipsrc_addrmask[i]) != | 159 | if ((stream[12 + i] & csr->ipsrc_addrmask[i]) != |
| 160 | (csr->ipsrc_addr[i] & csr->ipsrc_addrmask[i])) | 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 | for (i = 0; i < 4; i++) { | 166 | for (i = 0; i < 4; i++) { |
| 167 | if ((stream[16 + i] & csr->ipdst_addrmask[i]) != | 167 | if ((stream[16 + i] & csr->ipdst_addrmask[i]) != |
| 168 | (csr->ipdst_addr[i] & csr->ipdst_addrmask[i])) | 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) { | 173 | if (csr->classifier_rule_en & PROTOCOLSRCPORTRANGE) { |
| 174 | i = ((port[0]<<8)&0xff00)+port[1]; | 174 | i = ((port[0] << 8) & 0xff00) + port[1]; |
| 175 | if ((i < csr->srcport_lo) || (i > csr->srcport_hi)) | 175 | if ((i < csr->srcport_lo) || (i > csr->srcport_hi)) |
| 176 | return 1; | 176 | return 1; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | if (csr->classifier_rule_en&PROTOCOLDSTPORTRANGE) { | 179 | if (csr->classifier_rule_en & PROTOCOLDSTPORTRANGE) { |
| 180 | i = ((port[2]<<8)&0xff00)+port[3]; | 180 | i = ((port[2] << 8) & 0xff00) + port[3]; |
| 181 | if ((i < csr->dstport_lo) || (i > csr->dstport_hi)) | 181 | if ((i < csr->dstport_lo) || (i > csr->dstport_hi)) |
| 182 | return 1; | 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 | if (!iph || !tcpudph) | 193 | if (!iph || !tcpudph) |
| 194 | return -1; | 194 | return -1; |
| 195 | 195 | ||
| 196 | ip_ver = (iph[0]>>4)&0xf; | 196 | ip_ver = (iph[0] >> 4) & 0xf; |
| 197 | 197 | ||
| 198 | if (ip_ver != 4) | 198 | if (ip_ver != 4) |
| 199 | return -1; | 199 | return -1; |
| @@ -342,17 +342,17 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) · 142 unmodified lines | |||
| 342 | if (sub_cmd_evt == QOS_REPORT) { | 342 | if (sub_cmd_evt == QOS_REPORT) { |
| 343 | spin_lock_irqsave(&qcb->qos_lock, flags); | 343 | spin_lock_irqsave(&qcb->qos_lock, flags); |
| 344 | for (i = 0; i < qcb->qos_list_cnt; i++) { | 344 | for (i = 0; i < qcb->qos_list_cnt; i++) { |
| 345 | sfid = ((buf[(i*5)+6]<<24)&0xff000000); | 345 | sfid = ((buf[(i*5) + 6] << 24) & 0xff000000); |
| 346 | sfid += ((buf[(i*5)+7]<<16)&0xff0000); | 346 | sfid += ((buf[(i*5) + 7] << 16) & 0xff0000); |
| 347 | sfid += ((buf[(i*5)+8]<<8)&0xff00); | 347 | sfid += ((buf[(i*5) + 8] << 8) & 0xff00); |
| 348 | sfid += (buf[(i*5)+9]); | 348 | sfid += (buf[(i*5) + 9]); |
| 349 | index = get_csr(qcb, sfid, 0); | 349 | index = get_csr(qcb, sfid, 0); |
| 350 | if (index == -1) { | 350 | if (index == -1) { |
| 351 | spin_unlock_irqrestore(&qcb->qos_lock, flags); | 351 | spin_unlock_irqrestore(&qcb->qos_lock, flags); |
| 352 | netdev_err(nic->netdev, "QoS ERROR: No SF\n"); | 352 | netdev_err(nic->netdev, "QoS ERROR: No SF\n"); |
| 353 | return; | 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 | extract_qos_list(nic, &send_list); | 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 | /* sub_cmd_evt == QOS_ADD || sub_cmd_evt == QOS_CHANG_DEL */ | 364 | /* sub_cmd_evt == QOS_ADD || sub_cmd_evt == QOS_CHANG_DEL */ |
| 365 | pos = 6; | 365 | pos = 6; |
| 366 | sfid = ((buf[pos++]<<24)&0xff000000); | 366 | sfid = ((buf[pos++] << 24) & 0xff000000); |
| 367 | sfid += ((buf[pos++]<<16)&0xff0000); | 367 | sfid += ((buf[pos++] << 16) & 0xff0000); |
| 368 | sfid += ((buf[pos++]<<8)&0xff00); | 368 | sfid += ((buf[pos++] << 8) & 0xff00); |
| 369 | sfid += (buf[pos++]); | 369 | sfid += (buf[pos++]); |
| 370 | 370 | ||
| 371 | index = get_csr(qcb, sfid, 1); | 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 | spin_lock_irqsave(&qcb->qos_lock, flags); | 383 | spin_lock_irqsave(&qcb->qos_lock, flags); |
| 384 | qcb->csr[index].sfid = sfid; | 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 | qcb->csr[index].classifier_rule_en += buf[pos++]; | 386 | qcb->csr[index].classifier_rule_en += buf[pos++]; |
| 387 | if (qcb->csr[index].classifier_rule_en == 0) | 387 | if (qcb->csr[index].classifier_rule_en == 0) |
| 388 | qcb->qos_null_idx = index; | 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 | qcb->csr[index].ipdst_addr[1] = buf[pos++]; | 406 | qcb->csr[index].ipdst_addr[1] = buf[pos++]; |
| 407 | qcb->csr[index].ipdst_addr[2] = buf[pos++]; | 407 | qcb->csr[index].ipdst_addr[2] = buf[pos++]; |
| 408 | qcb->csr[index].ipdst_addr[3] = buf[pos++]; | 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 | qcb->csr[index].srcport_lo += buf[pos++]; | 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 | qcb->csr[index].srcport_hi += buf[pos++]; | 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 | qcb->csr[index].dstport_lo += buf[pos++]; | 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 | qcb->csr[index].dstport_hi += buf[pos++]; | 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 | spin_unlock_irqrestore(&qcb->qos_lock, flags); | 419 | spin_unlock_irqrestore(&qcb->qos_lock, flags); |
| 420 | } else if (sub_cmd_evt == QOS_CHANGE_DEL) { | 420 | } else if (sub_cmd_evt == QOS_CHANGE_DEL) { |
| 421 | netdev_dbg(nic->netdev, "QOS_CHANGE_DEL SFID = 0x%x, index=%d\n", | 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 | spin_lock_irqsave(&qcb->qos_lock, flags); | 426 | spin_lock_irqsave(&qcb->qos_lock, flags); |
| 427 | qcb->csr[index].enabled = false; | 427 | qcb->csr[index].enabled = false; |
| 428 | qcb->qos_list_cnt--; | 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 | list_for_each_entry_safe(entry, n, &qcb->qos_list[index], | 431 | list_for_each_entry_safe(entry, n, &qcb->qos_list[index], |
| 432 | list) { | 432 | list) { |
| @@ -36,7 +36,7 @@ · 35 unmodified lines | |||
| 36 | #define RX_BUF_SIZE (25*1024) | 36 | #define RX_BUF_SIZE (25*1024) |
| 37 | 37 | ||
| 38 | #define TX_HZ 2000 | 38 | #define TX_HZ 2000 |
| 39 | #define TX_INTERVAL (1000000/TX_HZ) | 39 | #define TX_INTERVAL (NSEC_PER_SEC/TX_HZ) |
| 40 | 40 | ||
| 41 | static struct sdio_tx *alloc_tx_struct(struct tx_cxt *tx) | 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 | put_tx_struct(t->tx_cxt, t); | 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 | spin_unlock_irqrestore(&tx->lock, flags); | 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 | struct sdio_func *func = sdev->func; | 330 | struct sdio_func *func = sdev->func; |
| 331 | struct tx_cxt *tx = &sdev->tx; | 331 | struct tx_cxt *tx = &sdev->tx; |
| 332 | struct sdio_tx *t = NULL; | 332 | struct sdio_tx *t = NULL; |
| 333 | struct timeval now, *before; | 333 | ktime_t now, before; |
| 334 | int is_sdu = 0; | 334 | int is_sdu = 0; |
| 335 | long diff; | 335 | long diff; |
| 336 | unsigned long flags; | 336 | unsigned long flags; |
| @@ -346,11 +346,10 @@ static void do_tx(struct work_struct *work) · 9 unmodified lines | |||
| 346 | list_del(&t->list); | 346 | list_del(&t->list); |
| 347 | is_sdu = 0; | 347 | is_sdu = 0; |
| 348 | } else if (!tx->stop_sdu_tx && !list_empty(&tx->sdu_list)) { | 348 | } else if (!tx->stop_sdu_tx && !list_empty(&tx->sdu_list)) { |
| 349 | do_gettimeofday(&now); | 349 | now = ktime_get(); |
| 350 | before = &tx->sdu_stamp; | 350 | before = tx->sdu_stamp; |
| 351 | 351 | ||
| 352 | diff = (now.tv_sec - before->tv_sec) * 1000000 + | 352 | diff = ktime_to_ns(ktime_sub(now, before)); |
| 353 | (now.tv_usec - before->tv_usec); | ||
| 354 | if (diff >= 0 && diff < TX_INTERVAL) { | 353 | if (diff >= 0 && diff < TX_INTERVAL) { |
| 355 | schedule_work(&sdev->ws); | 354 | schedule_work(&sdev->ws); |
| 356 | spin_unlock_irqrestore(&tx->lock, flags); | 355 | spin_unlock_irqrestore(&tx->lock, flags); |
| @@ -15,7 +15,7 @@ · 14 unmodified lines | |||
| 15 | #define __GDM72XX_GDM_SDIO_H__ | 15 | #define __GDM72XX_GDM_SDIO_H__ |
| 16 | 16 | ||
| 17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
| 18 | #include <linux/time.h> | 18 | #include <linux/ktime.h> |
| 19 | 19 | ||
| 20 | #define MAX_NR_SDU_BUF 64 | 20 | #define MAX_NR_SDU_BUF 64 |
| 21 | 21 | ||
| @@ -32,7 +32,7 @@ struct tx_cxt { · 10 unmodified lines | |||
| 32 | struct list_head free_list; | 32 | struct list_head free_list; |
| 33 | struct list_head sdu_list; | 33 | struct list_head sdu_list; |
| 34 | struct list_head hci_list; | 34 | struct list_head hci_list; |
| 35 | struct timeval sdu_stamp; | 35 | ktime_t sdu_stamp; |
| 36 | u8 *sdu_buf; | 36 | u8 *sdu_buf; |
| 37 | spinlock_t lock; | 37 | spinlock_t lock; |
| 38 | int can_send; | 38 | int can_send; |
| @@ -84,11 +84,6 @@ static inline struct evt_entry *alloc_event_entry(void) · 83 unmodified lines | |||
| 84 | return kmalloc(sizeof(struct evt_entry), GFP_ATOMIC); | 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 | static struct evt_entry *get_event_entry(void) | 87 | static struct evt_entry *get_event_entry(void) |
| 93 | { | 88 | { |
| 94 | struct evt_entry *e; | 89 | struct evt_entry *e; |
| @@ -180,11 +175,11 @@ static void gdm_wimax_event_exit(void) · 85 unmodified lines | |||
| 180 | 175 | ||
| 181 | list_for_each_entry_safe(e, temp, &wm_event.evtq, list) { | 176 | list_for_each_entry_safe(e, temp, &wm_event.evtq, list) { |
| 182 | list_del(&e->list); | 177 | list_del(&e->list); |
| 183 | free_event_entry(e); | 178 | kfree(e); |
| 184 | } | 179 | } |
| 185 | list_for_each_entry_safe(e, temp, &wm_event.freeq, list) { | 180 | list_for_each_entry_safe(e, temp, &wm_event.freeq, list) { |
| 186 | list_del(&e->list); | 181 | list_del(&e->list); |
| 187 | free_event_entry(e); | 182 | kfree(e); |
| 188 | } | 183 | } |
| 189 | 184 | ||
| 190 | spin_unlock_irqrestore(&wm_event.evt_lock, flags); | 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 | int size; | 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 | return 0; | 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 | if (!src->size) { | 384 | if (!src->size) { |
| 390 | dst->size = 0; | 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 | struct wm_req_s *req = (struct wm_req_s *)ifr; | 455 | struct wm_req_s *req = (struct wm_req_s *)ifr; |
| 461 | struct nic *nic = netdev_priv(dev); | 456 | struct nic *nic = netdev_priv(dev); |
| 462 | int ret; | 457 | int ret; |
| 458 | struct fsm_s fsm_buf; | ||
| 463 | 459 | ||
| 464 | if (cmd != SIOCWMIOCTL) | 460 | if (cmd != SIOCWMIOCTL) |
| 465 | return -EOPNOTSUPP; | 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 | /* NOTE: gdm_update_fsm should be called | 478 | /* NOTE: gdm_update_fsm should be called |
| 483 | * before gdm_wimax_ioctl_set_data is called. | 479 | * before gdm_wimax_ioctl_set_data is called. |
| 484 | */ | 480 | */ |
| 485 | gdm_update_fsm(dev, | 481 | if (copy_from_user(&fsm_buf, req->data.buf, |
| 486 | req->data.buf); | 482 | sizeof(struct fsm_s))) |
| 483 | return -EFAULT; | ||
| 484 | |||
| 485 | gdm_update_fsm(dev, &fsm_buf); | ||
| 487 | } | 486 | } |
| 488 | ret = gdm_wimax_ioctl_set_data( | 487 | ret = gdm_wimax_ioctl_set_data( |
| 489 | &nic->sdk_data[req->data_id], &req->data); | 488 | &nic->sdk_data[req->data_id], &req->data); |
| @@ -78,13 +78,18 @@ struct data_s { · 77 unmodified lines | |||
| 78 | void *buf; | 78 | void *buf; |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | struct udata_s { | ||
| 82 | int size; | ||
| 83 | void __user *buf; | ||
| 84 | }; | ||
| 85 | |||
| 81 | struct wm_req_s { | 86 | struct wm_req_s { |
| 82 | union { | 87 | union { |
| 83 | char ifrn_name[IFNAMSIZ]; | 88 | char ifrn_name[IFNAMSIZ]; |
| 84 | } ifr_ifrn; | 89 | } ifr_ifrn; |
| 85 | unsigned short cmd; | 90 | unsigned short cmd; |
| 86 | unsigned short data_id; | 91 | unsigned short data_id; |
| 87 | struct data_s data; | 92 | struct udata_s data; |
| 88 | 93 | ||
| 89 | /* NOTE: sizeof(struct wm_req_s) must be less than sizeof(struct ifreq). */ | 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 | source "drivers/staging/iio/resolver/Kconfig" | 17 | source "drivers/staging/iio/resolver/Kconfig" |
| 18 | source "drivers/staging/iio/trigger/Kconfig" | 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 | endmenu | 20 | endmenu |
| @@ -2,13 +2,6 @@ · 1 unmodified line | |||
| 2 | # Makefile for the industrial I/O core. | 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 | obj-y += accel/ | 5 | obj-y += accel/ |
| 13 | obj-y += adc/ | 6 | obj-y += adc/ |
| 14 | obj-y += addac/ | 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 | *rx_p = kmalloc(len, GFP_KERNEL); | 50 | *rx_p = kmalloc(len, GFP_KERNEL); |
| 51 | if (*rx_p == NULL) { | 51 | if (!*rx_p) { |
| 52 | ret = -ENOMEM; | 52 | ret = -ENOMEM; |
| 53 | goto error_ret; | 53 | goto error_ret; |
| 54 | } | 54 | } |
| @@ -609,7 +609,7 @@ static const struct iio_chan_spec ad7192_channels[] = { · 608 unmodified lines | |||
| 609 | 609 | ||
| 610 | static int ad7192_probe(struct spi_device *spi) | 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 | struct ad7192_state *st; | 613 | struct ad7192_state *st; |
| 614 | struct iio_dev *indio_dev; | 614 | struct iio_dev *indio_dev; |
| 615 | int ret, voltage_uv = 0; | 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 | static int ad7280_probe(struct spi_device *spi) | 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 | struct ad7280_state *st; | 837 | struct ad7280_state *st; |
| 838 | int ret; | 838 | int ret; |
| 839 | const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890}; | 839 | const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890}; |
| @@ -15,15 +15,13 @@ · 14 unmodified lines | |||
| 15 | #include <linux/regulator/consumer.h> | 15 | #include <linux/regulator/consumer.h> |
| 16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
| 17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
| 18 | #include <linux/gpio.h> | 18 | #include <linux/gpio/consumer.h> |
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | 20 | ||
| 21 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
| 22 | #include <linux/iio/sysfs.h> | 22 | #include <linux/iio/sysfs.h> |
| 23 | #include <linux/iio/adc/ad_sigma_delta.h> | 23 | #include <linux/iio/adc/ad_sigma_delta.h> |
| 24 | 24 | ||
| 25 | #include "ad7780.h" | ||
| 26 | |||
| 27 | #define AD7780_RDY BIT(7) | 25 | #define AD7780_RDY BIT(7) |
| 28 | #define AD7780_FILTER BIT(6) | 26 | #define AD7780_FILTER BIT(6) |
| 29 | #define AD7780_ERR BIT(5) | 27 | #define AD7780_ERR BIT(5) |
| @@ -42,7 +40,7 @@ struct ad7780_chip_info { · 12 unmodified lines | |||
| 42 | struct ad7780_state { | 40 | struct ad7780_state { |
| 43 | const struct ad7780_chip_info *chip_info; | 41 | const struct ad7780_chip_info *chip_info; |
| 44 | struct regulator *reg; | 42 | struct regulator *reg; |
| 45 | int powerdown_gpio; | 43 | struct gpio_desc *powerdown_gpio; |
| 46 | unsigned int gain; | 44 | unsigned int gain; |
| 47 | u16 int_vref_mv; | 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 | break; | 75 | break; |
| 78 | } | 76 | } |
| 79 | 77 | ||
| 80 | if (gpio_is_valid(st->powerdown_gpio)) | 78 | gpiod_set_value(st->powerdown_gpio, val); |
| 81 | gpio_set_value(st->powerdown_gpio, val); | ||
| 82 | 79 | ||
| 83 | return 0; | 80 | return 0; |
| 84 | } | 81 | } |
| @@ -163,7 +160,6 @@ static const struct iio_info ad7780_info = { · 78 unmodified lines | |||
| 163 | 160 | ||
| 164 | static int ad7780_probe(struct spi_device *spi) | 161 | static int ad7780_probe(struct spi_device *spi) |
| 165 | { | 162 | { |
| 166 | struct ad7780_platform_data *pdata = spi->dev.platform_data; | ||
| 167 | struct ad7780_state *st; | 163 | struct ad7780_state *st; |
| 168 | struct iio_dev *indio_dev; | 164 | struct iio_dev *indio_dev; |
| 169 | int ret, voltage_uv = 0; | 165 | int ret, voltage_uv = 0; |
| @@ -189,12 +185,10 @@ static int ad7780_probe(struct spi_device *spi) · 19 unmodified lines | |||
| 189 | st->chip_info = | 185 | st->chip_info = |
| 190 | &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | 186 | &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; |
| 191 | 187 | ||
| 192 | if (pdata && pdata->vref_mv) | 188 | if (voltage_uv) |
| 193 | st->int_vref_mv = pdata->vref_mv; | ||
| 194 | else if (voltage_uv) | ||
| 195 | st->int_vref_mv = voltage_uv / 1000; | 189 | st->int_vref_mv = voltage_uv / 1000; |
| 196 | else | 190 | else |
| 197 | dev_warn(&spi->dev, "reference voltage unspecified\n"); | 191 | dev_warn(&spi->dev, "Reference voltage unspecified\n"); |
| 198 | 192 | ||
| 199 | spi_set_drvdata(spi, indio_dev); | 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 | indio_dev->num_channels = 1; | 199 | indio_dev->num_channels = 1; |
| 206 | indio_dev->info = &ad7780_info; | 200 | indio_dev->info = &ad7780_info; |
| 207 | 201 | ||
| 208 | if (pdata && gpio_is_valid(pdata->gpio_pdrst)) { | 202 | st->powerdown_gpio = devm_gpiod_get_optional(&spi->dev, |
| 209 | ret = devm_gpio_request_one(&spi->dev, | 203 | "powerdown", |
| 210 | pdata->gpio_pdrst, | 204 | GPIOD_OUT_LOW); |
| 211 | GPIOF_OUT_INIT_LOW, | 205 | if (IS_ERR(st->powerdown_gpio)) { |
| 212 | "AD7780 /PDRST"); | 206 | ret = PTR_ERR(st->powerdown_gpio); |
| 213 | if (ret) { | 207 | dev_err(&spi->dev, "Failed to request powerdown GPIO: %d\n", |
| 214 | dev_err(&spi->dev, "failed to request GPIO PDRST\n"); | 208 | ret); |
| 215 | goto error_disable_reg; | 209 | goto error_disable_reg; |
| 216 | } | ||
| 217 | st->powerdown_gpio = pdata->gpio_pdrst; | ||
| 218 | } else { | ||
| 219 | st->powerdown_gpio = -1; | ||
| 220 | } | 210 | } |
| 221 | 211 | ||
| 222 | ret = ad_sd_setup_buffer_and_trigger(indio_dev); | 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 | struct ad7816_chip_info *chip; | 346 | struct ad7816_chip_info *chip; |
| 347 | struct iio_dev *indio_dev; | 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 | int ret = 0; | 349 | int ret = 0; |
| 350 | int i; | 350 | int i; |
| 351 | 351 | ||
| @@ -319,12 +319,12 @@ struct mxs_lradc { · 318 unmodified lines | |||
| 319 | #define LRADC_CH_VALUE_OFFSET 0 | 319 | #define LRADC_CH_VALUE_OFFSET 0 |
| 320 | 320 | ||
| 321 | #define LRADC_DELAY(n) (0xd0 + (0x10 * (n))) | 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 | #define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24 | 323 | #define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24 |
| 324 | #define LRADC_DELAY_TRIGGER(x) \ | 324 | #define LRADC_DELAY_TRIGGER(x) \ |
| 325 | (((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \ | 325 | (((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \ |
| 326 | LRADC_DELAY_TRIGGER_LRADCS_MASK) | 326 | LRADC_DELAY_TRIGGER_LRADCS_MASK) |
| 327 | #define LRADC_DELAY_KICK (1 << 20) | 327 | #define LRADC_DELAY_KICK BIT(20) |
| 328 | #define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16) | 328 | #define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16) |
| 329 | #define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16 | 329 | #define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16 |
| 330 | #define LRADC_DELAY_TRIGGER_DELAYS(x) \ | 330 | #define LRADC_DELAY_TRIGGER_DELAYS(x) \ |
| @@ -201,7 +201,7 @@ static const struct iio_info ad9832_info = { · 200 unmodified lines | |||
| 201 | 201 | ||
| 202 | static int ad9832_probe(struct spi_device *spi) | 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 | struct iio_dev *indio_dev; | 205 | struct iio_dev *indio_dev; |
| 206 | struct ad9832_state *st; | 206 | struct ad9832_state *st; |
| 207 | struct regulator *reg; | 207 | struct regulator *reg; |
| @@ -318,7 +318,7 @@ static const struct iio_info ad9833_info = { · 317 unmodified lines | |||
| 318 | 318 | ||
| 319 | static int ad9834_probe(struct spi_device *spi) | 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 | struct ad9834_state *st; | 322 | struct ad9834_state *st; |
| 323 | struct iio_dev *indio_dev; | 323 | struct iio_dev *indio_dev; |
| 324 | struct regulator *reg; | 324 | struct regulator *reg; |
| @@ -1898,7 +1898,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp, · 1897 unmodified lines | |||
| 1898 | mutex_init(&chip->prox_mutex); | 1898 | mutex_init(&chip->prox_mutex); |
| 1899 | 1899 | ||
| 1900 | chip->tsl2x7x_chip_status = TSL2X7X_CHIP_UNKNOWN; | 1900 | chip->tsl2x7x_chip_status = TSL2X7X_CHIP_UNKNOWN; |
| 1901 | chip->pdata = clientp->dev.platform_data; | 1901 | chip->pdata = dev_get_platdata(&clientp->dev); |
| 1902 | chip->id = id->driver_data; | 1902 | chip->id = id->driver_data; |
| 1903 | chip->chip_info = | 1903 | chip->chip_info = |
| 1904 | &tsl2x7x_chip_info_tbl[device_channel_config[id->driver_data]]; | 1904 | &tsl2x7x_chip_info_tbl[device_channel_config[id->driver_data]]; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -42,13 +42,6 @@ · 8 unmodified lines | |||
| 42 | 42 | ||
| 43 | #include "curproc.h" | 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 | #define LOWEST_BIT_SET(x) ((x) & ~((x) - 1)) | 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 | * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 29 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -41,6 +41,9 @@ · 7 unmodified lines | |||
| 41 | 41 | ||
| 42 | #ifndef __LIBCFS_HASH_H__ | 42 | #ifndef __LIBCFS_HASH_H__ |
| 43 | #define __LIBCFS_HASH_H__ | 43 | #define __LIBCFS_HASH_H__ |
| 44 | |||
| 45 | #include <linux/hash.h> | ||
| 46 | |||
| 44 | /* | 47 | /* |
| 45 | * Knuth recommends primes in approximately golden ratio to the maximum | 48 | * Knuth recommends primes in approximately golden ratio to the maximum |
| 46 | * integer representable by a machine word for multiplicative hashing. | 49 | * integer representable by a machine word for multiplicative hashing. |
| @@ -56,22 +59,13 @@ · 9 unmodified lines | |||
| 56 | /* 2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */ | 59 | /* 2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */ |
| 57 | #define CFS_GOLDEN_RATIO_PRIME_64 0x9e37fffffffc0001ULL | 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 | /** disable debug */ | 62 | /** disable debug */ |
| 69 | #define CFS_HASH_DEBUG_NONE 0 | 63 | #define CFS_HASH_DEBUG_NONE 0 |
| 70 | /** record hash depth and output to console when it's too deep, | 64 | /** record hash depth and output to console when it's too deep, |
| 71 | * computing overhead is low but consume more memory */ | 65 | * computing overhead is low but consume more memory */ |
| 72 | #define CFS_HASH_DEBUG_1 1 | 66 | #define CFS_HASH_DEBUG_1 1 |
| 73 | /** expensive, check key validation */ | 67 | /** expensive, check key validation */ |
| 74 | #define CFS_HASH_DEBUG_2 2 | 68 | #define CFS_HASH_DEBUG_2 2 |
| 75 | 69 | ||
| 76 | #define CFS_HASH_DEBUG_LEVEL CFS_HASH_DEBUG_NONE | 70 | #define CFS_HASH_DEBUG_LEVEL CFS_HASH_DEBUG_NONE |
| 77 | 71 | ||
| @@ -108,16 +102,18 @@ struct cfs_hash_bucket { · 30 unmodified lines | |||
| 108 | * cfs_hash bucket descriptor, it's normally in stack of caller | 102 | * cfs_hash bucket descriptor, it's normally in stack of caller |
| 109 | */ | 103 | */ |
| 110 | struct cfs_hash_bd { | 104 | struct cfs_hash_bd { |
| 111 | struct cfs_hash_bucket *bd_bucket; /**< address of bucket */ | 105 | /* address of bucket */ |
| 112 | unsigned int bd_offset; /**< offset in 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 */ | 111 | #define CFS_HASH_NAME_LEN 16 /**< default name length */ |
| 116 | #define CFS_HASH_BIGNAME_LEN 64 /**< bigname for param tree */ | 112 | #define CFS_HASH_BIGNAME_LEN 64 /**< bigname for param tree */ |
| 117 | 113 | ||
| 118 | #define CFS_HASH_BKT_BITS 3 /**< default bits of bucket */ | 114 | #define CFS_HASH_BKT_BITS 3 /**< default bits of bucket */ |
| 119 | #define CFS_HASH_BITS_MAX 30 /**< max bits of bucket */ | 115 | #define CFS_HASH_BITS_MAX 30 /**< max bits of bucket */ |
| 120 | #define CFS_HASH_BITS_MIN CFS_HASH_BKT_BITS | 116 | #define CFS_HASH_BITS_MIN CFS_HASH_BKT_BITS |
| 121 | 117 | ||
| 122 | /** | 118 | /** |
| 123 | * common hash attributes. | 119 | * common hash attributes. |
| @@ -133,41 +129,41 @@ enum cfs_hash_tag { · 9 unmodified lines | |||
| 133 | */ | 129 | */ |
| 134 | CFS_HASH_NO_LOCK = 1 << 0, | 130 | CFS_HASH_NO_LOCK = 1 << 0, |
| 135 | /** no bucket lock, use one spinlock to protect the whole hash */ | 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 | /** rwlock to protect bucket */ | 133 | /** rwlock to protect bucket */ |
| 138 | CFS_HASH_RW_BKTLOCK = 1 << 2, | 134 | CFS_HASH_RW_BKTLOCK = 1 << 2, |
| 139 | /** spinlock to protect bucket */ | 135 | /** spinlock to protect bucket */ |
| 140 | CFS_HASH_SPIN_BKTLOCK = 1 << 3, | 136 | CFS_HASH_SPIN_BKTLOCK = 1 << 3, |
| 141 | /** always add new item to tail */ | 137 | /** always add new item to tail */ |
| 142 | CFS_HASH_ADD_TAIL = 1 << 4, | 138 | CFS_HASH_ADD_TAIL = 1 << 4, |
| 143 | /** hash-table doesn't have refcount on item */ | 139 | /** hash-table doesn't have refcount on item */ |
| 144 | CFS_HASH_NO_ITEMREF = 1 << 5, | 140 | CFS_HASH_NO_ITEMREF = 1 << 5, |
| 145 | /** big name for param-tree */ | 141 | /** big name for param-tree */ |
| 146 | CFS_HASH_BIGNAME = 1 << 6, | 142 | CFS_HASH_BIGNAME = 1 << 6, |
| 147 | /** track global count */ | 143 | /** track global count */ |
| 148 | CFS_HASH_COUNTER = 1 << 7, | 144 | CFS_HASH_COUNTER = 1 << 7, |
| 149 | /** rehash item by new key */ | 145 | /** rehash item by new key */ |
| 150 | CFS_HASH_REHASH_KEY = 1 << 8, | 146 | CFS_HASH_REHASH_KEY = 1 << 8, |
| 151 | /** Enable dynamic hash resizing */ | 147 | /** Enable dynamic hash resizing */ |
| 152 | CFS_HASH_REHASH = 1 << 9, | 148 | CFS_HASH_REHASH = 1 << 9, |
| 153 | /** can shrink hash-size */ | 149 | /** can shrink hash-size */ |
| 154 | CFS_HASH_SHRINK = 1 << 10, | 150 | CFS_HASH_SHRINK = 1 << 10, |
| 155 | /** assert hash is empty on exit */ | 151 | /** assert hash is empty on exit */ |
| 156 | CFS_HASH_ASSERT_EMPTY = 1 << 11, | 152 | CFS_HASH_ASSERT_EMPTY = 1 << 11, |
| 157 | /** record hlist depth */ | 153 | /** record hlist depth */ |
| 158 | CFS_HASH_DEPTH = 1 << 12, | 154 | CFS_HASH_DEPTH = 1 << 12, |
| 159 | /** | 155 | /** |
| 160 | * rehash is always scheduled in a different thread, so current | 156 | * rehash is always scheduled in a different thread, so current |
| 161 | * change on hash table is non-blocking | 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 | /** NB, we typed hs_flags as __u16, please change it | 160 | /** NB, we typed hs_flags as __u16, please change it |
| 165 | * if you need to extend >=16 flags */ | 161 | * if you need to extend >=16 flags */ |
| 166 | }; | 162 | }; |
| 167 | 163 | ||
| 168 | /** most used attributes */ | 164 | /** most used attributes */ |
| 169 | #define CFS_HASH_DEFAULT (CFS_HASH_RW_BKTLOCK | \ | 165 | #define CFS_HASH_DEFAULT (CFS_HASH_RW_BKTLOCK | \ |
| 170 | CFS_HASH_COUNTER | CFS_HASH_REHASH) | 166 | CFS_HASH_COUNTER | CFS_HASH_REHASH) |
| 171 | 167 | ||
| 172 | /** | 168 | /** |
| 173 | * cfs_hash is a hash-table implementation for general purpose, it can support: | 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 | struct cfs_hash { | 207 | struct cfs_hash { |
| 212 | /** serialize with rehash, or serialize all operations if | 208 | /** serialize with rehash, or serialize all operations if |
| 213 | * the hash-table has CFS_HASH_NO_BKTLOCK */ | 209 | * the hash-table has CFS_HASH_NO_BKTLOCK */ |
| 214 | union cfs_hash_lock hs_lock; | 210 | union cfs_hash_lock hs_lock; |
| 215 | /** hash operations */ | 211 | /** hash operations */ |
| 216 | struct cfs_hash_ops *hs_ops; | 212 | struct cfs_hash_ops *hs_ops; |
| 217 | /** hash lock operations */ | 213 | /** hash lock operations */ |
| @@ -219,57 +215,57 @@ struct cfs_hash { · 1 unmodified line | |||
| 219 | /** hash list operations */ | 215 | /** hash list operations */ |
| 220 | struct cfs_hash_hlist_ops *hs_hops; | 216 | struct cfs_hash_hlist_ops *hs_hops; |
| 221 | /** hash buckets-table */ | 217 | /** hash buckets-table */ |
| 222 | struct cfs_hash_bucket **hs_buckets; | 218 | struct cfs_hash_bucket **hs_buckets; |
| 223 | /** total number of items on this hash-table */ | 219 | /** total number of items on this hash-table */ |
| 224 | atomic_t hs_count; | 220 | atomic_t hs_count; |
| 225 | /** hash flags, see cfs_hash_tag for detail */ | 221 | /** hash flags, see cfs_hash_tag for detail */ |
| 226 | __u16 hs_flags; | 222 | __u16 hs_flags; |
| 227 | /** # of extra-bytes for bucket, for user saving extended attributes */ | 223 | /** # of extra-bytes for bucket, for user saving extended attributes */ |
| 228 | __u16 hs_extra_bytes; | 224 | __u16 hs_extra_bytes; |
| 229 | /** wants to iterate */ | 225 | /** wants to iterate */ |
| 230 | __u8 hs_iterating; | 226 | __u8 hs_iterating; |
| 231 | /** hash-table is dying */ | 227 | /** hash-table is dying */ |
| 232 | __u8 hs_exiting; | 228 | __u8 hs_exiting; |
| 233 | /** current hash bits */ | 229 | /** current hash bits */ |
| 234 | __u8 hs_cur_bits; | 230 | __u8 hs_cur_bits; |
| 235 | /** min hash bits */ | 231 | /** min hash bits */ |
| 236 | __u8 hs_min_bits; | 232 | __u8 hs_min_bits; |
| 237 | /** max hash bits */ | 233 | /** max hash bits */ |
| 238 | __u8 hs_max_bits; | 234 | __u8 hs_max_bits; |
| 239 | /** bits for rehash */ | 235 | /** bits for rehash */ |
| 240 | __u8 hs_rehash_bits; | 236 | __u8 hs_rehash_bits; |
| 241 | /** bits for each bucket */ | 237 | /** bits for each bucket */ |
| 242 | __u8 hs_bkt_bits; | 238 | __u8 hs_bkt_bits; |
| 243 | /** resize min threshold */ | 239 | /** resize min threshold */ |
| 244 | __u16 hs_min_theta; | 240 | __u16 hs_min_theta; |
| 245 | /** resize max threshold */ | 241 | /** resize max threshold */ |
| 246 | __u16 hs_max_theta; | 242 | __u16 hs_max_theta; |
| 247 | /** resize count */ | 243 | /** resize count */ |
| 248 | __u32 hs_rehash_count; | 244 | __u32 hs_rehash_count; |
| 249 | /** # of iterators (caller of cfs_hash_for_each_*) */ | 245 | /** # of iterators (caller of cfs_hash_for_each_*) */ |
| 250 | __u32 hs_iterators; | 246 | __u32 hs_iterators; |
| 251 | /** rehash workitem */ | 247 | /** rehash workitem */ |
| 252 | cfs_workitem_t hs_rehash_wi; | 248 | cfs_workitem_t hs_rehash_wi; |
| 253 | /** refcount on this hash table */ | 249 | /** refcount on this hash table */ |
| 254 | atomic_t hs_refcount; | 250 | atomic_t hs_refcount; |
| 255 | /** rehash buckets-table */ | 251 | /** rehash buckets-table */ |
| 256 | struct cfs_hash_bucket **hs_rehash_buckets; | 252 | struct cfs_hash_bucket **hs_rehash_buckets; |
| 257 | #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1 | 253 | #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1 |
| 258 | /** serialize debug members */ | 254 | /** serialize debug members */ |
| 259 | spinlock_t hs_dep_lock; | 255 | spinlock_t hs_dep_lock; |
| 260 | /** max depth */ | 256 | /** max depth */ |
| 261 | unsigned int hs_dep_max; | 257 | unsigned int hs_dep_max; |
| 262 | /** id of the deepest bucket */ | 258 | /** id of the deepest bucket */ |
| 263 | unsigned int hs_dep_bkt; | 259 | unsigned int hs_dep_bkt; |
| 264 | /** offset in the deepest bucket */ | 260 | /** offset in the deepest bucket */ |
| 265 | unsigned int hs_dep_off; | 261 | unsigned int hs_dep_off; |
| 266 | /** bits when we found the max depth */ | 262 | /** bits when we found the max depth */ |
| 267 | unsigned int hs_dep_bits; | 263 | unsigned int hs_dep_bits; |
| 268 | /** workitem to output max depth */ | 264 | /** workitem to output max depth */ |
| 269 | cfs_workitem_t hs_dep_wi; | 265 | cfs_workitem_t hs_dep_wi; |
| 270 | #endif | 266 | #endif |
| 271 | /** name of htable */ | 267 | /** name of htable */ |
| 272 | char hs_name[0]; | 268 | char hs_name[0]; |
| 273 | }; | 269 | }; |
| 274 | 270 | ||
| 275 | struct cfs_hash_lock_ops { | 271 | struct cfs_hash_lock_ops { |
| @@ -324,11 +320,11 @@ struct cfs_hash_ops { · 48 unmodified lines | |||
| 324 | }; | 320 | }; |
| 325 | 321 | ||
| 326 | /** total number of buckets in @hs */ | 322 | /** total number of buckets in @hs */ |
| 327 | #define CFS_HASH_NBKT(hs) \ | 323 | #define CFS_HASH_NBKT(hs) \ |
| 328 | (1U << ((hs)->hs_cur_bits - (hs)->hs_bkt_bits)) | 324 | (1U << ((hs)->hs_cur_bits - (hs)->hs_bkt_bits)) |
| 329 | 325 | ||
| 330 | /** total number of buckets in @hs while rehashing */ | 326 | /** total number of buckets in @hs while rehashing */ |
| 331 | #define CFS_HASH_RH_NBKT(hs) \ | 327 | #define CFS_HASH_RH_NBKT(hs) \ |
| 332 | (1U << ((hs)->hs_rehash_bits - (hs)->hs_bkt_bits)) | 328 | (1U << ((hs)->hs_rehash_bits - (hs)->hs_bkt_bits)) |
| 333 | 329 | ||
| 334 | /** number of hlist for in bucket */ | 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 | static inline int | 430 | static inline int |
| 435 | cfs_hash_is_exiting(struct cfs_hash *hs) | 431 | cfs_hash_is_exiting(struct cfs_hash *hs) |
| 436 | { /* cfs_hash_destroy is called */ | 432 | { |
| 433 | /* cfs_hash_destroy is called */ | ||
| 437 | return hs->hs_exiting; | 434 | return hs->hs_exiting; |
| 438 | } | 435 | } |
| 439 | 436 | ||
| 440 | static inline int | 437 | static inline int |
| 441 | cfs_hash_is_rehashing(struct cfs_hash *hs) | 438 | cfs_hash_is_rehashing(struct cfs_hash *hs) |
| 442 | { /* rehash is launched */ | 439 | { |
| 440 | /* rehash is launched */ | ||
| 443 | return hs->hs_rehash_bits != 0; | 441 | return hs->hs_rehash_bits != 0; |
| 444 | } | 442 | } |
| 445 | 443 | ||
| 446 | static inline int | 444 | static inline int |
| 447 | cfs_hash_is_iterating(struct cfs_hash *hs) | 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 | return hs->hs_iterating || hs->hs_iterators != 0; | 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 | struct hlist_node * | 640 | struct hlist_node * |
| 642 | cfs_hash_bd_peek_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, | 641 | cfs_hash_bd_peek_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, |
| 643 | const void *key); | 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 | * operations on cfs_hash bucket (bd: bucket descriptor), | 645 | * operations on cfs_hash bucket (bd: bucket descriptor), |
| @@ -758,7 +750,7 @@ static inline void · 104 unmodified lines | |||
| 758 | cfs_hash_bucket_validate(struct cfs_hash *hs, struct cfs_hash_bd *bd, | 750 | cfs_hash_bucket_validate(struct cfs_hash *hs, struct cfs_hash_bd *bd, |
| 759 | struct hlist_node *hnode) | 751 | struct hlist_node *hnode) |
| 760 | { | 752 | { |
| 761 | struct cfs_hash_bd bds[2]; | 753 | struct cfs_hash_bd bds[2]; |
| 762 | 754 | ||
| 763 | cfs_hash_dual_bd_get(hs, cfs_hash_key(hs, hnode), bds); | 755 | cfs_hash_dual_bd_get(hs, cfs_hash_key(hs, hnode), bds); |
| 764 | LASSERT(bds[0].bd_bucket == bd->bd_bucket || | 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 | #endif /* CFS_HASH_DEBUG_LEVEL */ | 770 | #endif /* CFS_HASH_DEBUG_LEVEL */ |
| 779 | 771 | ||
| 780 | #define CFS_HASH_THETA_BITS 10 | 772 | #define CFS_HASH_THETA_BITS 10 |
| 781 | #define CFS_HASH_MIN_THETA (1U << (CFS_HASH_THETA_BITS - 1)) | 773 | #define CFS_HASH_MIN_THETA (1U << (CFS_HASH_THETA_BITS - 1)) |
| 782 | #define CFS_HASH_MAX_THETA (1U << (CFS_HASH_THETA_BITS + 1)) | 774 | #define CFS_HASH_MAX_THETA (1U << (CFS_HASH_THETA_BITS + 1)) |
| 783 | 775 | ||
| 784 | /* Return integer component of theta */ | 776 | /* Return integer component of theta */ |
| 785 | static inline int __cfs_hash_theta_int(int theta) | 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 | /** iterate over all buckets in @bds (array of struct cfs_hash_bd) */ | 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 | for (i = 0; i < n && (bds)[i].bd_bucket != NULL; i++) | 844 | for (i = 0; i < n && (bds)[i].bd_bucket != NULL; i++) |
| 853 | 845 | ||
| 854 | /** iterate over all buckets of @hs */ | 846 | /** iterate over all buckets of @hs */ |
| 855 | #define cfs_hash_for_each_bucket(hs, bd, pos) \ | 847 | #define cfs_hash_for_each_bucket(hs, bd, pos) \ |
| 856 | for (pos = 0; \ | 848 | for (pos = 0; \ |
| 857 | pos < CFS_HASH_NBKT(hs) && \ | 849 | pos < CFS_HASH_NBKT(hs) && \ |
| 858 | ((bd)->bd_bucket = (hs)->hs_buckets[pos]) != NULL; pos++) | 850 | ((bd)->bd_bucket = (hs)->hs_buckets[pos]) != NULL; pos++) |
| 859 | 851 | ||
| 860 | /** iterate over all hlist of bucket @bd */ | 852 | /** iterate over all hlist of bucket @bd */ |
| 861 | #define cfs_hash_bd_for_each_hlist(hs, bd, hlist) \ | 853 | #define cfs_hash_bd_for_each_hlist(hs, bd, hlist) \ |
| 862 | for ((bd)->bd_offset = 0; \ | 854 | for ((bd)->bd_offset = 0; \ |
| 863 | (bd)->bd_offset < CFS_HASH_BKT_NHLIST(hs) && \ | 855 | (bd)->bd_offset < CFS_HASH_BKT_NHLIST(hs) && \ |
| 864 | (hlist = cfs_hash_bd_hhead(hs, bd)) != NULL; \ | 856 | (hlist = cfs_hash_bd_hhead(hs, bd)) != NULL; \ |
| 865 | (bd)->bd_offset++) | 857 | (bd)->bd_offset++) |
| 866 | 858 | ||
| 867 | /* !__LIBCFS__HASH_H__ */ | 859 | /* !__LIBCFS__HASH_H__ */ |
| @@ -91,7 +91,7 @@ typedef int (*libcfs_kkuc_cb_t)(__u32 data, void *cb_arg); · 90 unmodified lines | |||
| 91 | /* Kernel methods */ | 91 | /* Kernel methods */ |
| 92 | int libcfs_kkuc_msg_put(struct file *fp, void *payload); | 92 | int libcfs_kkuc_msg_put(struct file *fp, void *payload); |
| 93 | int libcfs_kkuc_group_put(int group, void *payload); | 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 | __u32 data); | 95 | __u32 data); |
| 96 | int libcfs_kkuc_group_rem(int uid, int group); | 96 | int libcfs_kkuc_group_rem(int uid, int group); |
| 97 | int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, | 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 | int libcfs_debug_clear_buffer(void); | 185 | int libcfs_debug_clear_buffer(void); |
| 186 | int libcfs_debug_mark_buffer(const char *text); | 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 | * allocate per-cpu-partition data, returned value is an array of pointers, | 189 | * allocate per-cpu-partition data, returned value is an array of pointers, |
| 192 | * variable can be indexed by CPU ID. | 190 | * variable can be indexed by CPU ID. |
| @@ -161,12 +161,6 @@ int LNetEQAlloc(unsigned int count_in, · 160 unmodified lines | |||
| 161 | 161 | ||
| 162 | int LNetEQFree(lnet_handle_eq_t eventq_in); | 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 | int LNetEQPoll(lnet_handle_eq_t *eventqs_in, | 164 | int LNetEQPoll(lnet_handle_eq_t *eventqs_in, |
| 171 | int neq_in, | 165 | int neq_in, |
| 172 | int timeout_ms, | 166 | int timeout_ms, |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | |||
| 23 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 23 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 29 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | |||
| 23 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 23 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 29 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | |||
| 23 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 23 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | * Use is subject to license terms. | 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 | #ifndef _LNET_NIDSTRINGS_H | 28 | #ifndef _LNET_NIDSTRINGS_H |
| 29 | #define _LNET_NIDSTRINGS_H | 29 | #define _LNET_NIDSTRINGS_H |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | return 0; | 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 | MODULE_DESCRIPTION("Kernel OpenIB gen2 LND v2.00"); | 2869 | MODULE_DESCRIPTION("Kernel OpenIB gen2 LND v2.00"); |
| 2870 | MODULE_LICENSE("GPL"); | 2870 | MODULE_LICENSE("GPL"); |
| 2871 | 2871 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | net->ksnn_interfaces[j].ksni_ipaddr = ip; | 2622 | net->ksnn_interfaces[j].ksni_ipaddr = ip; |
| 2623 | net->ksnn_interfaces[j].ksni_netmask = mask; | 2623 | net->ksnn_interfaces[j].ksni_netmask = mask; |
| 2624 | strncpy(&net->ksnn_interfaces[j].ksni_name[0], | 2624 | strlcpy(net->ksnn_interfaces[j].ksni_name, |
| 2625 | names[i], IFNAMSIZ); | 2625 | names[i], sizeof(net->ksnn_interfaces[j].ksni_name)); |
| 2626 | j++; | 2626 | j++; |
| 2627 | } | 2627 | } |
| 2628 | 2628 | ||
| @@ -2805,8 +2805,9 @@ ksocknal_startup(lnet_ni_t *ni) · 176 unmodified lines | |||
| 2805 | goto fail_1; | 2805 | goto fail_1; |
| 2806 | } | 2806 | } |
| 2807 | 2807 | ||
| 2808 | strncpy(&net->ksnn_interfaces[i].ksni_name[0], | 2808 | strlcpy(net->ksnn_interfaces[i].ksni_name, |
| 2809 | ni->ni_interfaces[i], IFNAMSIZ); | 2809 | ni->ni_interfaces[i], |
| 2810 | sizeof(net->ksnn_interfaces[i].ksni_name)); | ||
| 2810 | } | 2811 | } |
| 2811 | net->ksnn_ninterfaces = i; | 2812 | net->ksnn_ninterfaces = i; |
| 2812 | } | 2813 | } |
| @@ -2868,7 +2869,7 @@ ksocknal_module_init(void) · 55 unmodified lines | |||
| 2868 | return 0; | 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 | MODULE_DESCRIPTION("Kernel TCP Socket LND v3.0.0"); | 2873 | MODULE_DESCRIPTION("Kernel TCP Socket LND v3.0.0"); |
| 2873 | MODULE_LICENSE("GPL"); | 2874 | MODULE_LICENSE("GPL"); |
| 2874 | MODULE_VERSION("3.0.0"); | 2875 | MODULE_VERSION("3.0.0"); |
| @@ -679,6 +679,9 @@ int ksocknal_lib_recv_kiov(ksock_conn_t *conn); · 678 unmodified lines | |||
| 679 | int ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem, | 679 | int ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem, |
| 680 | int *rxmem, int *nagle); | 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 | int ksocknal_tunables_init(void); | 685 | int ksocknal_tunables_init(void); |
| 683 | 686 | ||
| 684 | void ksocknal_lib_csum_tx(ksock_tx_t *tx); | 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 | ksocknal_connsock_decref(conn); | 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 | * socket call back in Linux | 584 | * socket call back in Linux |
| 587 | */ | 585 | */ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | lnet_net_unlock(LNET_LOCK_EX); | 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 | static char * | 358 | static char * |
| 369 | lnet_res_type2str(int type) | 359 | lnet_res_type2str(int type) |
| @@ -553,8 +543,11 @@ lnet_prepare(lnet_pid_t requested_pid) · 183 unmodified lines | |||
| 553 | rc = lnet_create_remote_nets_table(); | 543 | rc = lnet_create_remote_nets_table(); |
| 554 | if (rc != 0) | 544 | if (rc != 0) |
| 555 | goto failed; | 545 | goto failed; |
| 556 | 546 | /* | |
| 557 | the_lnet.ln_interface_cookie = lnet_create_interface_cookie(); | 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 | the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(), | 552 | the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(), |
| 560 | sizeof(lnet_counters_t)); | 553 | sizeof(lnet_counters_t)); |
| @@ -1159,7 +1152,6 @@ lnet_init(void) · 598 unmodified lines | |||
| 1159 | lnet_register_lnd(&the_lolnd); | 1152 | lnet_register_lnd(&the_lolnd); |
| 1160 | return 0; | 1153 | return 0; |
| 1161 | } | 1154 | } |
| 1162 | EXPORT_SYMBOL(lnet_init); | ||
| 1163 | 1155 | ||
| 1164 | /** | 1156 | /** |
| 1165 | * Finalize LNet library. | 1157 | * Finalize LNet library. |
| @@ -1183,7 +1175,6 @@ lnet_fini(void) · 17 unmodified lines | |||
| 1183 | 1175 | ||
| 1184 | the_lnet.ln_init = 0; | 1176 | the_lnet.ln_init = 0; |
| 1185 | } | 1177 | } |
| 1186 | EXPORT_SYMBOL(lnet_fini); | ||
| 1187 | 1178 | ||
| 1188 | /** | 1179 | /** |
| 1189 | * Set LNet PID and start LNet interfaces, routing, and forwarding. | 1180 | * Set LNet PID and start LNet interfaces, routing, and forwarding. |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | INIT_LIST_HEAD(&nets); | 650 | INIT_LIST_HEAD(&nets); |
| 651 | 651 | ||
| 652 | /* save a copy of the string for error messages */ | 652 | /* save a copy of the string for error messages */ |
| 653 | strncpy(cmd, str, sizeof(cmd) - 1); | 653 | strncpy(cmd, str, sizeof(cmd)); |
| 654 | cmd[sizeof(cmd) - 1] = 0; | 654 | cmd[sizeof(cmd) - 1] = '\0'; |
| 655 | 655 | ||
| 656 | sep = str; | 656 | sep = str; |
| 657 | for (;;) { | 657 | for (;;) { |
| @@ -972,11 +972,13 @@ lnet_splitnets(char *source, struct list_head *nets) · 314 unmodified lines | |||
| 972 | return 0; | 972 | return 0; |
| 973 | 973 | ||
| 974 | offset += (int)(sep - tb->ltb_text); | 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 | if (tb2 == NULL) | 977 | if (tb2 == NULL) |
| 977 | return -ENOMEM; | 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 | list_add_tail(&tb2->ltb_list, nets); | 982 | list_add_tail(&tb2->ltb_list, nets); |
| 981 | 983 | ||
| 982 | tb = tb2; | 984 | tb = tb2; |
| @@ -1021,8 +1023,8 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) · 38 unmodified lines | |||
| 1021 | tb = list_entry(raw_entries.next, struct lnet_text_buf_t, | 1023 | tb = list_entry(raw_entries.next, struct lnet_text_buf_t, |
| 1022 | ltb_list); | 1024 | ltb_list); |
| 1023 | 1025 | ||
| 1024 | strncpy(source, tb->ltb_text, sizeof(source)-1); | 1026 | strncpy(source, tb->ltb_text, sizeof(source)); |
| 1025 | source[sizeof(source)-1] = 0; | 1027 | source[sizeof(source)-1] = '\0'; |
| 1026 | 1028 | ||
| 1027 | /* replace ltb_text with the network(s) add on match */ | 1029 | /* replace ltb_text with the network(s) add on match */ |
| 1028 | rc = lnet_match_network_tokens(tb->ltb_text, ipaddrs, nip); | 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 | return count; | 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 | static int | 1108 | static int |
| 1113 | lnet_ipaddr_enumerate(__u32 **ipaddrsp) | 1109 | lnet_ipaddr_enumerate(__u32 **ipaddrsp) |
| 1114 | { | 1110 | { |
| @@ -1169,7 +1165,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp) · 54 unmodified lines | |||
| 1169 | rc = nip; | 1165 | rc = nip; |
| 1170 | } | 1166 | } |
| 1171 | } | 1167 | } |
| 1172 | lnet_ipaddr_free_enumeration(ipaddrs, nif); | 1168 | LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); |
| 1173 | } | 1169 | } |
| 1174 | return nip; | 1170 | return nip; |
| 1175 | } | 1171 | } |
| @@ -1195,7 +1191,7 @@ lnet_parse_ip2nets(char **networksp, char *ip2nets) · 19 unmodified lines | |||
| 1195 | } | 1191 | } |
| 1196 | 1192 | ||
| 1197 | rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip); | 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 | if (rc < 0) { | 1196 | if (rc < 0) { |
| 1201 | LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc); | 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 | * at least one event between this event and the last event obtained from the | 282 | * at least one event between this event and the last event obtained from the |
| 283 | * EQ has been dropped due to limited space in the EQ. | 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 | * Block the calling process until there is an event in the EQ. | 287 | * Block the calling process until there is an event in the EQ. |
| @@ -308,15 +299,6 @@ EXPORT_SYMBOL(LNetEQGet); · 11 unmodified lines | |||
| 308 | * at least one event between this event and the last event obtained from the | 299 | * at least one event between this event and the last event obtained from the |
| 309 | * EQ has been dropped due to limited space in the EQ. | 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 | static int | 303 | static int |
| 322 | lnet_eq_wait_locked(int *timeout_ms) | 304 | lnet_eq_wait_locked(int *timeout_ms) |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -1645,7 +1645,6 @@ lnet_msgtyp2str(int type) · 1611 unmodified lines | |||
| 1645 | return "<UNKNOWN>"; | 1645 | return "<UNKNOWN>"; |
| 1646 | } | 1646 | } |
| 1647 | } | 1647 | } |
| 1648 | EXPORT_SYMBOL(lnet_msgtyp2str); | ||
| 1649 | 1648 | ||
| 1650 | void | 1649 | void |
| 1651 | lnet_print_hdr(lnet_hdr_t *hdr) | 1650 | lnet_print_hdr(lnet_hdr_t *hdr) |
| @@ -21,7 +21,7 @@ · 20 unmodified lines | |||
| 21 | * GPL HEADER END | 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 | * This file is part of Lustre, http://www.lustre.org/ | 27 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | |||
| 23 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 23 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 29 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -146,7 +146,7 @@ fini_lnet(void) · 112 unmodified lines | |||
| 146 | lnet_fini(); | 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 | MODULE_DESCRIPTION("LNet v3.1"); | 150 | MODULE_DESCRIPTION("LNet v3.1"); |
| 151 | MODULE_LICENSE("GPL"); | 151 | MODULE_LICENSE("GPL"); |
| 152 | MODULE_VERSION("1.0.0"); | 152 | MODULE_VERSION("1.0.0"); |
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 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 | * This file is part of Portals | 6 | * This file is part of Portals |
| 7 | * http://sourceforge.net/projects/sandiaportals/ | 7 | * http://sourceforge.net/projects/sandiaportals/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -358,7 +358,7 @@ out: · 324 unmodified lines | |||
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | static void | 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 | srpc_bulk_t *blk = rpc->srpc_bulk; | 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 | static int | 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 | __u64 magic = BRW_MAGIC; | 383 | __u64 magic = BRW_MAGIC; |
| 384 | srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply; | 384 | srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply; |
| @@ -925,5 +925,3 @@ out: · 924 unmodified lines | |||
| 925 | 925 | ||
| 926 | return rc; | 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 | msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst; | 612 | msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst; |
| 613 | msrq->mksn_sid = console_session.ses_id; | 613 | msrq->mksn_sid = console_session.ses_id; |
| 614 | msrq->mksn_force = console_session.ses_force; | 614 | msrq->mksn_force = console_session.ses_force; |
| 615 | strncpy(msrq->mksn_name, console_session.ses_name, | 615 | strlcpy(msrq->mksn_name, console_session.ses_name, |
| 616 | strlen(console_session.ses_name)); | 616 | sizeof(msrq->mksn_name)); |
| 617 | break; | 617 | break; |
| 618 | 618 | ||
| 619 | case LST_TRANS_SESEND: | 619 | case LST_TRANS_SESEND: |
| @@ -277,12 +277,6 @@ lstcon_group_find(const char *name, lstcon_group_t **grpp) · 276 unmodified lines | |||
| 277 | return -ENOENT; | 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 | static int | 280 | static int |
| 287 | lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, | 281 | lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, |
| 288 | lstcon_ndlink_t **ndlpp, int create) | 282 | lstcon_ndlink_t **ndlpp, int create) |
| @@ -324,8 +318,6 @@ lstcon_group_ndlink_move(lstcon_group_t *old, · 35 unmodified lines | |||
| 324 | list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]); | 318 | list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]); |
| 325 | list_add_tail(&ndl->ndl_link, &new->grp_ndl_list); | 319 | list_add_tail(&ndl->ndl_link, &new->grp_ndl_list); |
| 326 | new->grp_nnode++; | 320 | new->grp_nnode++; |
| 327 | |||
| 328 | return; | ||
| 329 | } | 321 | } |
| 330 | 322 | ||
| 331 | static void | 323 | static void |
| @@ -436,7 +428,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, · 104 unmodified lines | |||
| 436 | } | 428 | } |
| 437 | 429 | ||
| 438 | if (rc != 0) { | 430 | if (rc != 0) { |
| 439 | lstcon_group_put(tmp); | 431 | lstcon_group_decref(tmp); |
| 440 | return rc; | 432 | return rc; |
| 441 | } | 433 | } |
| 442 | 434 | ||
| @@ -445,7 +437,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, · 2 unmodified lines | |||
| 445 | tmp, lstcon_sesrpc_condition, &trans); | 437 | tmp, lstcon_sesrpc_condition, &trans); |
| 446 | if (rc != 0) { | 438 | if (rc != 0) { |
| 447 | CERROR("Can't create transaction: %d\n", rc); | 439 | CERROR("Can't create transaction: %d\n", rc); |
| 448 | lstcon_group_put(tmp); | 440 | lstcon_group_decref(tmp); |
| 449 | return rc; | 441 | return rc; |
| 450 | } | 442 | } |
| 451 | 443 | ||
| @@ -460,7 +452,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, · 8 unmodified lines | |||
| 460 | lstcon_rpc_trans_destroy(trans); | 452 | lstcon_rpc_trans_destroy(trans); |
| 461 | 453 | ||
| 462 | lstcon_group_move(tmp, grp); | 454 | lstcon_group_move(tmp, grp); |
| 463 | lstcon_group_put(tmp); | 455 | lstcon_group_decref(tmp); |
| 464 | 456 | ||
| 465 | return rc; | 457 | return rc; |
| 466 | } | 458 | } |
| @@ -510,12 +502,12 @@ lstcon_group_nodes_remove(lstcon_group_t *grp, · 43 unmodified lines | |||
| 510 | 502 | ||
| 511 | lstcon_rpc_trans_destroy(trans); | 503 | lstcon_rpc_trans_destroy(trans); |
| 512 | /* release nodes anyway, because we can't rollback status */ | 504 | /* release nodes anyway, because we can't rollback status */ |
| 513 | lstcon_group_put(tmp); | 505 | lstcon_group_decref(tmp); |
| 514 | 506 | ||
| 515 | return rc; | 507 | return rc; |
| 516 | error: | 508 | error: |
| 517 | lstcon_group_move(tmp, grp); | 509 | lstcon_group_move(tmp, grp); |
| 518 | lstcon_group_put(tmp); | 510 | lstcon_group_decref(tmp); |
| 519 | 511 | ||
| 520 | return rc; | 512 | return rc; |
| 521 | } | 513 | } |
| @@ -529,7 +521,7 @@ lstcon_group_add(char *name) · 7 unmodified lines | |||
| 529 | rc = (lstcon_group_find(name, &grp) == 0) ? -EEXIST : 0; | 521 | rc = (lstcon_group_find(name, &grp) == 0) ? -EEXIST : 0; |
| 530 | if (rc != 0) { | 522 | if (rc != 0) { |
| 531 | /* find a group with same name */ | 523 | /* find a group with same name */ |
| 532 | lstcon_group_put(grp); | 524 | lstcon_group_decref(grp); |
| 533 | return rc; | 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 | if (grp->grp_ref > 2) { | 555 | if (grp->grp_ref > 2) { |
| 564 | /* referred by other threads or test */ | 556 | /* referred by other threads or test */ |
| 565 | CDEBUG(D_NET, "Group %s is busy\n", name); | 557 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 566 | lstcon_group_put(grp); | 558 | lstcon_group_decref(grp); |
| 567 | 559 | ||
| 568 | return -EBUSY; | 560 | return -EBUSY; |
| 569 | } | 561 | } |
| 570 | 562 | ||
| 571 | rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up); | 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 | return rc; | 567 | return rc; |
| 576 | } | 568 | } |
| @@ -591,7 +583,7 @@ lstcon_group_del(char *name) · 14 unmodified lines | |||
| 591 | if (grp->grp_ref > 2) { | 583 | if (grp->grp_ref > 2) { |
| 592 | /* referred by others threads or test */ | 584 | /* referred by others threads or test */ |
| 593 | CDEBUG(D_NET, "Group %s is busy\n", name); | 585 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 594 | lstcon_group_put(grp); | 586 | lstcon_group_decref(grp); |
| 595 | return -EBUSY; | 587 | return -EBUSY; |
| 596 | } | 588 | } |
| 597 | 589 | ||
| @@ -600,7 +592,7 @@ lstcon_group_del(char *name) · 2 unmodified lines | |||
| 600 | grp, lstcon_sesrpc_condition, &trans); | 592 | grp, lstcon_sesrpc_condition, &trans); |
| 601 | if (rc != 0) { | 593 | if (rc != 0) { |
| 602 | CERROR("Can't create transaction: %d\n", rc); | 594 | CERROR("Can't create transaction: %d\n", rc); |
| 603 | lstcon_group_put(grp); | 595 | lstcon_group_decref(grp); |
| 604 | return rc; | 596 | return rc; |
| 605 | } | 597 | } |
| 606 | 598 | ||
| @@ -608,10 +600,10 @@ lstcon_group_del(char *name) · 1 unmodified line | |||
| 608 | 600 | ||
| 609 | lstcon_rpc_trans_destroy(trans); | 601 | lstcon_rpc_trans_destroy(trans); |
| 610 | 602 | ||
| 611 | lstcon_group_put(grp); | 603 | lstcon_group_decref(grp); |
| 612 | /* -ref for session, it's destroyed, | 604 | /* -ref for session, it's destroyed, |
| 613 | * status can't be rolled back, destroy group anyway */ | 605 | * status can't be rolled back, destroy group anyway */ |
| 614 | lstcon_group_put(grp); | 606 | lstcon_group_decref(grp); |
| 615 | 607 | ||
| 616 | return rc; | 608 | return rc; |
| 617 | } | 609 | } |
| @@ -631,7 +623,7 @@ lstcon_group_clean(char *name, int args) · 13 unmodified lines | |||
| 631 | if (grp->grp_ref > 2) { | 623 | if (grp->grp_ref > 2) { |
| 632 | /* referred by test */ | 624 | /* referred by test */ |
| 633 | CDEBUG(D_NET, "Group %s is busy\n", name); | 625 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 634 | lstcon_group_put(grp); | 626 | lstcon_group_decref(grp); |
| 635 | return -EBUSY; | 627 | return -EBUSY; |
| 636 | } | 628 | } |
| 637 | 629 | ||
| @@ -640,10 +632,10 @@ lstcon_group_clean(char *name, int args) · 2 unmodified lines | |||
| 640 | 632 | ||
| 641 | lstcon_group_drain(grp, args); | 633 | lstcon_group_drain(grp, args); |
| 642 | 634 | ||
| 643 | lstcon_group_put(grp); | 635 | lstcon_group_decref(grp); |
| 644 | /* release empty group */ | 636 | /* release empty group */ |
| 645 | if (list_empty(&grp->grp_ndl_list)) | 637 | if (list_empty(&grp->grp_ndl_list)) |
| 646 | lstcon_group_put(grp); | 638 | lstcon_group_decref(grp); |
| 647 | 639 | ||
| 648 | return 0; | 640 | return 0; |
| 649 | } | 641 | } |
| @@ -664,16 +656,16 @@ lstcon_nodes_remove(char *name, int count, · 14 unmodified lines | |||
| 664 | if (grp->grp_ref > 2) { | 656 | if (grp->grp_ref > 2) { |
| 665 | /* referred by test */ | 657 | /* referred by test */ |
| 666 | CDEBUG(D_NET, "Group %s is busy\n", name); | 658 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 667 | lstcon_group_put(grp); | 659 | lstcon_group_decref(grp); |
| 668 | return -EBUSY; | 660 | return -EBUSY; |
| 669 | } | 661 | } |
| 670 | 662 | ||
| 671 | rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up); | 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 | /* release empty group */ | 666 | /* release empty group */ |
| 675 | if (list_empty(&grp->grp_ndl_list)) | 667 | if (list_empty(&grp->grp_ndl_list)) |
| 676 | lstcon_group_put(grp); | 668 | lstcon_group_decref(grp); |
| 677 | 669 | ||
| 678 | return rc; | 670 | return rc; |
| 679 | } | 671 | } |
| @@ -694,7 +686,7 @@ lstcon_group_refresh(char *name, struct list_head *result_up) · 14 unmodified lines | |||
| 694 | if (grp->grp_ref > 2) { | 686 | if (grp->grp_ref > 2) { |
| 695 | /* referred by test */ | 687 | /* referred by test */ |
| 696 | CDEBUG(D_NET, "Group %s is busy\n", name); | 688 | CDEBUG(D_NET, "Group %s is busy\n", name); |
| 697 | lstcon_group_put(grp); | 689 | lstcon_group_decref(grp); |
| 698 | return -EBUSY; | 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 | if (rc != 0) { | 697 | if (rc != 0) { |
| 706 | /* local error, return */ | 698 | /* local error, return */ |
| 707 | CDEBUG(D_NET, "Can't create transaction: %d\n", rc); | 699 | CDEBUG(D_NET, "Can't create transaction: %d\n", rc); |
| 708 | lstcon_group_put(grp); | 700 | lstcon_group_decref(grp); |
| 709 | return rc; | 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 | lstcon_rpc_trans_destroy(trans); | 708 | lstcon_rpc_trans_destroy(trans); |
| 717 | /* -ref for me */ | 709 | /* -ref for me */ |
| 718 | lstcon_group_put(grp); | 710 | lstcon_group_decref(grp); |
| 719 | 711 | ||
| 720 | return rc; | 712 | return rc; |
| 721 | } | 713 | } |
| @@ -797,7 +789,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p, · 75 unmodified lines | |||
| 797 | /* verbose query */ | 789 | /* verbose query */ |
| 798 | rc = lstcon_nodes_getent(&grp->grp_ndl_list, | 790 | rc = lstcon_nodes_getent(&grp->grp_ndl_list, |
| 799 | index_p, count_p, dents_up); | 791 | index_p, count_p, dents_up); |
| 800 | lstcon_group_put(grp); | 792 | lstcon_group_decref(grp); |
| 801 | 793 | ||
| 802 | return rc; | 794 | return rc; |
| 803 | } | 795 | } |
| @@ -806,7 +798,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p, · 2 unmodified lines | |||
| 806 | LIBCFS_ALLOC(gentp, sizeof(lstcon_ndlist_ent_t)); | 798 | LIBCFS_ALLOC(gentp, sizeof(lstcon_ndlist_ent_t)); |
| 807 | if (gentp == NULL) { | 799 | if (gentp == NULL) { |
| 808 | CERROR("Can't allocate ndlist_ent\n"); | 800 | CERROR("Can't allocate ndlist_ent\n"); |
| 809 | lstcon_group_put(grp); | 801 | lstcon_group_decref(grp); |
| 810 | 802 | ||
| 811 | return -ENOMEM; | 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 | LIBCFS_FREE(gentp, sizeof(lstcon_ndlist_ent_t)); | 812 | LIBCFS_FREE(gentp, sizeof(lstcon_ndlist_ent_t)); |
| 821 | 813 | ||
| 822 | lstcon_group_put(grp); | 814 | lstcon_group_decref(grp); |
| 823 | 815 | ||
| 824 | return 0; | 816 | return 0; |
| 825 | } | 817 | } |
| @@ -1096,8 +1088,8 @@ lstcon_batch_destroy(lstcon_batch_t *bat) · 270 unmodified lines | |||
| 1096 | 1088 | ||
| 1097 | list_del(&test->tes_link); | 1089 | list_del(&test->tes_link); |
| 1098 | 1090 | ||
| 1099 | lstcon_group_put(test->tes_src_grp); | 1091 | lstcon_group_decref(test->tes_src_grp); |
| 1100 | lstcon_group_put(test->tes_dst_grp); | 1092 | lstcon_group_decref(test->tes_dst_grp); |
| 1101 | 1093 | ||
| 1102 | LIBCFS_FREE(test, offsetof(lstcon_test_t, | 1094 | LIBCFS_FREE(test, offsetof(lstcon_test_t, |
| 1103 | tes_param[test->tes_paramlen])); | 1095 | tes_param[test->tes_paramlen])); |
| @@ -1352,10 +1344,10 @@ out: · 248 unmodified lines | |||
| 1352 | LIBCFS_FREE(test, offsetof(lstcon_test_t, tes_param[paramlen])); | 1344 | LIBCFS_FREE(test, offsetof(lstcon_test_t, tes_param[paramlen])); |
| 1353 | 1345 | ||
| 1354 | if (dst_grp != NULL) | 1346 | if (dst_grp != NULL) |
| 1355 | lstcon_group_put(dst_grp); | 1347 | lstcon_group_decref(dst_grp); |
| 1356 | 1348 | ||
| 1357 | if (src_grp != NULL) | 1349 | if (src_grp != NULL) |
| 1358 | lstcon_group_put(src_grp); | 1350 | lstcon_group_decref(src_grp); |
| 1359 | 1351 | ||
| 1360 | return rc; | 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 | rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up); | 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 | return rc; | 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 | if (rc != 0) { | 1550 | if (rc != 0) { |
| 1559 | lstcon_group_put(tmp); | 1551 | lstcon_group_decref(tmp); |
| 1560 | return rc; | 1552 | return rc; |
| 1561 | } | 1553 | } |
| 1562 | 1554 | ||
| 1563 | rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up); | 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 | return rc; | 1559 | return rc; |
| 1568 | } | 1560 | } |
| @@ -1629,7 +1621,7 @@ lstcon_group_debug(int timeout, char *name, · 60 unmodified lines | |||
| 1629 | 1621 | ||
| 1630 | rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL, | 1622 | rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL, |
| 1631 | timeout, result_up); | 1623 | timeout, result_up); |
| 1632 | lstcon_group_put(grp); | 1624 | lstcon_group_decref(grp); |
| 1633 | 1625 | ||
| 1634 | return rc; | 1626 | return rc; |
| 1635 | } | 1627 | } |
| @@ -1666,14 +1658,14 @@ lstcon_nodes_debug(int timeout, · 30 unmodified lines | |||
| 1666 | } | 1658 | } |
| 1667 | 1659 | ||
| 1668 | if (rc != 0) { | 1660 | if (rc != 0) { |
| 1669 | lstcon_group_put(grp); | 1661 | lstcon_group_decref(grp); |
| 1670 | return rc; | 1662 | return rc; |
| 1671 | } | 1663 | } |
| 1672 | 1664 | ||
| 1673 | rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL, | 1665 | rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL, |
| 1674 | timeout, result_up); | 1666 | timeout, result_up); |
| 1675 | 1667 | ||
| 1676 | lstcon_group_put(grp); | 1668 | lstcon_group_decref(grp); |
| 1677 | 1669 | ||
| 1678 | return rc; | 1670 | return rc; |
| 1679 | } | 1671 | } |
| @@ -1739,7 +1731,8 @@ lstcon_session_new(char *name, int key, unsigned feats, · 59 unmodified lines | |||
| 1739 | console_session.ses_feats_updated = 0; | 1731 | console_session.ses_feats_updated = 0; |
| 1740 | console_session.ses_timeout = (timeout <= 0) ? | 1732 | console_session.ses_timeout = (timeout <= 0) ? |
| 1741 | LST_CONSOLE_TIMEOUT : timeout; | 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 | rc = lstcon_batch_add(LST_DEFAULT_BATCH); | 1737 | rc = lstcon_batch_add(LST_DEFAULT_BATCH); |
| 1745 | if (rc != 0) | 1738 | if (rc != 0) |
| @@ -1847,7 +1840,7 @@ lstcon_session_end(void) · 101 unmodified lines | |||
| 1847 | lstcon_group_t, grp_link); | 1840 | lstcon_group_t, grp_link); |
| 1848 | LASSERT(grp->grp_ref == 1); | 1841 | LASSERT(grp->grp_ref == 1); |
| 1849 | 1842 | ||
| 1850 | lstcon_group_put(grp); | 1843 | lstcon_group_decref(grp); |
| 1851 | } | 1844 | } |
| 1852 | 1845 | ||
| 1853 | /* all nodes should be released */ | 1846 | /* all nodes should be released */ |
| @@ -1891,7 +1884,7 @@ lstcon_session_feats_check(unsigned feats) · 37 unmodified lines | |||
| 1891 | } | 1884 | } |
| 1892 | 1885 | ||
| 1893 | static int | 1886 | static int |
| 1894 | lstcon_acceptor_handle(srpc_server_rpc_t *rpc) | 1887 | lstcon_acceptor_handle(struct srpc_server_rpc *rpc) |
| 1895 | { | 1888 | { |
| 1896 | srpc_msg_t *rep = &rpc->srpc_replymsg; | 1889 | srpc_msg_t *rep = &rpc->srpc_replymsg; |
| 1897 | srpc_msg_t *req = &rpc->srpc_reqstbuf->buf_msg; | 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 | if (grp->grp_userland == 0) | 1952 | if (grp->grp_userland == 0) |
| 1960 | grp->grp_userland = 1; | 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 | jrep->join_timeout = console_session.ses_timeout; | 1957 | jrep->join_timeout = console_session.ses_timeout; |
| 1964 | jrep->join_status = 0; | 1958 | jrep->join_status = 0; |
| 1965 | 1959 | ||
| 1966 | out: | 1960 | out: |
| 1967 | rep->msg_ses_feats = console_session.ses_features; | 1961 | rep->msg_ses_feats = console_session.ses_features; |
| 1968 | if (grp != NULL) | 1962 | if (grp != NULL) |
| 1969 | lstcon_group_put(grp); | 1963 | lstcon_group_decref(grp); |
| 1970 | 1964 | ||
| 1971 | mutex_unlock(&console_session.ses_mutex); | 1965 | mutex_unlock(&console_session.ses_mutex); |
| 1972 | 1966 | ||
| @@ -111,7 +111,7 @@ static struct smoketest_framework { · 110 unmodified lines | |||
| 111 | spinlock_t fw_lock; /* serialise */ | 111 | spinlock_t fw_lock; /* serialise */ |
| 112 | sfw_session_t *fw_session; /* _the_ session */ | 112 | sfw_session_t *fw_session; /* _the_ session */ |
| 113 | int fw_shuttingdown; /* shutdown in progress */ | 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 | } sfw_data; | 115 | } sfw_data; |
| 116 | 116 | ||
| 117 | /* forward ref's */ | 117 | /* forward ref's */ |
| @@ -722,7 +722,7 @@ sfw_unpack_addtest_req(srpc_msg_t *msg) · 604 unmodified lines | |||
| 722 | } | 722 | } |
| 723 | 723 | ||
| 724 | static int | 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 | srpc_msg_t *msg = &rpc->srpc_reqstbuf->buf_msg; | 727 | srpc_msg_t *msg = &rpc->srpc_reqstbuf->buf_msg; |
| 728 | srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; | 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 | void | 1093 | void |
| 1094 | sfw_free_pages(srpc_server_rpc_t *rpc) | 1094 | sfw_free_pages(struct srpc_server_rpc *rpc) |
| 1095 | { | 1095 | { |
| 1096 | srpc_free_bulk(rpc->srpc_bulk); | 1096 | srpc_free_bulk(rpc->srpc_bulk); |
| 1097 | rpc->srpc_bulk = NULL; | 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 | static int | 1114 | static int |
| 1115 | sfw_add_test(srpc_server_rpc_t *rpc) | 1115 | sfw_add_test(struct srpc_server_rpc *rpc) |
| 1116 | { | 1116 | { |
| 1117 | sfw_session_t *sn = sfw_data.fw_session; | 1117 | sfw_session_t *sn = sfw_data.fw_session; |
| 1118 | srpc_test_reply_t *reply = &rpc->srpc_replymsg.msg_body.tes_reply; | 1118 | srpc_test_reply_t *reply = &rpc->srpc_replymsg.msg_body.tes_reply; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | return 0; | 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 | static int | 447 | static int |
| 457 | srpc_post_passive_rqtbuf(int service, int local, void *buf, int len, | 448 | srpc_post_passive_rqtbuf(int service, int local, void *buf, int len, |
| 458 | lnet_handle_md_t *mdh, srpc_event_t *ev) | 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 | ev->ev_data = rpc; | 789 | ev->ev_data = rpc; |
| 799 | ev->ev_type = SRPC_REQUEST_SENT; | 790 | ev->ev_type = SRPC_REQUEST_SENT; |
| 800 | 791 | ||
| 801 | rc = srpc_post_active_rqtbuf(rpc->crpc_dest, rpc->crpc_service, | 792 | rc = srpc_post_active_rdma(srpc_serv_portal(rpc->crpc_service), |
| 802 | &rpc->crpc_reqstmsg, sizeof(srpc_msg_t), | 793 | rpc->crpc_service, &rpc->crpc_reqstmsg, |
| 803 | &rpc->crpc_reqstmdh, ev); | 794 | sizeof(srpc_msg_t), LNET_MD_OP_PUT, |
| 795 | rpc->crpc_dest, LNET_NID_ANY, | ||
| 796 | &rpc->crpc_reqstmdh, ev); | ||
| 804 | if (rc != 0) { | 797 | if (rc != 0) { |
| 805 | LASSERT(rc == -ENOMEM); | 798 | LASSERT(rc == -ENOMEM); |
| 806 | ev->ev_fired = 1; /* no more event expected */ | 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 | static int | 861 | static int |
| 869 | srpc_do_bulk(srpc_server_rpc_t *rpc) | 862 | srpc_do_bulk(struct srpc_server_rpc *rpc) |
| 870 | { | 863 | { |
| 871 | srpc_event_t *ev = &rpc->srpc_ev; | 864 | srpc_event_t *ev = &rpc->srpc_ev; |
| 872 | srpc_bulk_t *bk = rpc->srpc_bulk; | 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 | /* only called from srpc_handle_rpc */ | 888 | /* only called from srpc_handle_rpc */ |
| 896 | static void | 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 | struct srpc_service_cd *scd = rpc->srpc_scd; | 892 | struct srpc_service_cd *scd = rpc->srpc_scd; |
| 900 | struct srpc_service *sv = scd->scd_svc; | 893 | struct srpc_service *sv = scd->scd_svc; |
| @@ -1404,7 +1397,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) · 503 unmodified lines | |||
| 1404 | struct srpc_service_cd *scd; | 1397 | struct srpc_service_cd *scd; |
| 1405 | srpc_event_t *rpcev = ev->md.user_ptr; | 1398 | srpc_event_t *rpcev = ev->md.user_ptr; |
| 1406 | srpc_client_rpc_t *crpc; | 1399 | srpc_client_rpc_t *crpc; |
| 1407 | srpc_server_rpc_t *srpc; | 1400 | struct srpc_server_rpc *srpc; |
| 1408 | srpc_buffer_t *buffer; | 1401 | srpc_buffer_t *buffer; |
| 1409 | srpc_service_t *sv; | 1402 | srpc_service_t *sv; |
| 1410 | srpc_msg_t *msg; | 1403 | srpc_msg_t *msg; |
| @@ -182,7 +182,7 @@ typedef struct swi_workitem { · 181 unmodified lines | |||
| 182 | } swi_workitem_t; | 182 | } swi_workitem_t; |
| 183 | 183 | ||
| 184 | /* server-side state of a RPC */ | 184 | /* server-side state of a RPC */ |
| 185 | typedef struct srpc_server_rpc { | 185 | struct srpc_server_rpc { |
| 186 | /* chain on srpc_service::*_rpcq */ | 186 | /* chain on srpc_service::*_rpcq */ |
| 187 | struct list_head srpc_list; | 187 | struct list_head srpc_list; |
| 188 | struct srpc_service_cd *srpc_scd; | 188 | struct srpc_service_cd *srpc_scd; |
| @@ -198,7 +198,7 @@ typedef struct srpc_server_rpc { · 9 unmodified lines | |||
| 198 | unsigned int srpc_aborted; /* being given up */ | 198 | unsigned int srpc_aborted; /* being given up */ |
| 199 | int srpc_status; | 199 | int srpc_status; |
| 200 | void (*srpc_done)(struct srpc_server_rpc *); | 200 | void (*srpc_done)(struct srpc_server_rpc *); |
| 201 | } srpc_server_rpc_t; | 201 | }; |
| 202 | 202 | ||
| 203 | /* client-side state of a RPC */ | 203 | /* client-side state of a RPC */ |
| 204 | typedef struct srpc_client_rpc { | 204 | typedef struct srpc_client_rpc { |
| @@ -318,8 +318,8 @@ typedef struct srpc_service { · 113 unmodified lines | |||
| 318 | * - sv_handler: process incoming RPC request | 318 | * - sv_handler: process incoming RPC request |
| 319 | * - sv_bulk_ready: notify bulk data | 319 | * - sv_bulk_ready: notify bulk data |
| 320 | */ | 320 | */ |
| 321 | int (*sv_handler) (srpc_server_rpc_t *); | 321 | int (*sv_handler)(struct srpc_server_rpc *); |
| 322 | int (*sv_bulk_ready) (srpc_server_rpc_t *, int); | 322 | int (*sv_bulk_ready)(struct srpc_server_rpc *, int); |
| 323 | } srpc_service_t; | 323 | } srpc_service_t; |
| 324 | 324 | ||
| 325 | typedef struct { | 325 | typedef struct { |
| @@ -423,9 +423,9 @@ void sfw_abort_rpc(srpc_client_rpc_t *rpc); · 97 unmodified lines | |||
| 423 | void sfw_post_rpc(srpc_client_rpc_t *rpc); | 423 | void sfw_post_rpc(srpc_client_rpc_t *rpc); |
| 424 | void sfw_client_rpc_done(srpc_client_rpc_t *rpc); | 424 | void sfw_client_rpc_done(srpc_client_rpc_t *rpc); |
| 425 | void sfw_unpack_message(srpc_msg_t *msg); | 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 | void sfw_add_bulk_page(srpc_bulk_t *bk, struct page *pg, int i); | 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 | int sink); | 429 | int sink); |
| 430 | int sfw_make_session (srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply); | 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 | srpc_bulk_t *srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, | 440 | srpc_bulk_t *srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, |
| 441 | int sink); | 441 | int sink); |
| 442 | int srpc_send_rpc(swi_workitem_t *wi); | 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 | int srpc_add_service(srpc_service_t *sv); | 444 | int srpc_add_service(srpc_service_t *sv); |
| 445 | int srpc_remove_service(srpc_service_t *sv); | 445 | int srpc_remove_service(srpc_service_t *sv); |
| 446 | void srpc_shutdown_service(srpc_service_t *sv); | 446 | void srpc_shutdown_service(srpc_service_t *sv); |
| @@ -585,7 +585,7 @@ swi_state2str (int state) · 138 unmodified lines | |||
| 585 | do { \ | 585 | do { \ |
| 586 | int __I = 2; \ | 586 | int __I = 2; \ |
| 587 | while (!(cond)) { \ | 587 | while (!(cond)) { \ |
| 588 | CDEBUG(IS_PO2(++__I) ? D_WARNING : D_NET, \ | 588 | CDEBUG(is_power_of_2(++__I) ? D_WARNING : D_NET, \ |
| 589 | fmt, ## __VA_ARGS__); \ | 589 | fmt, ## __VA_ARGS__); \ |
| 590 | spin_unlock(&(lock)); \ | 590 | spin_unlock(&(lock)); \ |
| 591 | \ | 591 | \ |
| @@ -44,8 +44,6 @@ · 43 unmodified lines | |||
| 44 | #include "../../include/linux/libcfs/libcfs.h" | 44 | #include "../../include/linux/libcfs/libcfs.h" |
| 45 | 45 | ||
| 46 | /* Functions used internally in module. */ | 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 | extern struct lprocfs_vars seq_client_debugfs_list[]; | 48 | extern struct lprocfs_vars seq_client_debugfs_list[]; |
| 51 | 49 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -142,27 +142,6 @@ out_req: · 108 unmodified lines | |||
| 142 | return rc; | 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 | /* Request sequence-controller node to allocate new meta-sequence. */ | 145 | /* Request sequence-controller node to allocate new meta-sequence. */ |
| 167 | static int seq_client_alloc_meta(const struct lu_env *env, | 146 | static int seq_client_alloc_meta(const struct lu_env *env, |
| 168 | struct lu_client_seq *seq) | 147 | struct lu_client_seq *seq) |
| @@ -483,7 +462,7 @@ static void __exit fid_mod_exit(void) · 314 unmodified lines | |||
| 483 | ldebugfs_remove(&seq_debugfs_dir); | 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 | MODULE_DESCRIPTION("Lustre FID Module"); | 466 | MODULE_DESCRIPTION("Lustre FID Module"); |
| 488 | MODULE_LICENSE("GPL"); | 467 | MODULE_LICENSE("GPL"); |
| 489 | MODULE_VERSION("0.1.0"); | 468 | MODULE_VERSION("0.1.0"); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | * delete given node from list. | 122 | * delete given node from list. |
| 123 | */ | 123 | */ |
| 124 | void fld_cache_entry_delete(struct fld_cache *cache, | 124 | static void fld_cache_entry_delete(struct fld_cache *cache, |
| 125 | struct fld_cache_entry *node) | 125 | struct fld_cache_entry *node) |
| 126 | { | 126 | { |
| 127 | list_del(&node->fce_list); | 127 | list_del(&node->fce_list); |
| 128 | list_del(&node->fce_lru); | 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 | while (cache->fci_cache_count + cache->fci_threshold > | 228 | while (cache->fci_cache_count + cache->fci_threshold > |
| 229 | cache->fci_cache_size && curr != &cache->fci_lru) { | 229 | cache->fci_cache_size && curr != &cache->fci_lru) { |
| 230 | |||
| 231 | flde = list_entry(curr, struct fld_cache_entry, fce_lru); | 230 | flde = list_entry(curr, struct fld_cache_entry, fce_lru); |
| 232 | curr = curr->prev; | 231 | curr = curr->prev; |
| 233 | fld_cache_entry_delete(cache, flde); | 232 | fld_cache_entry_delete(cache, flde); |
| @@ -377,8 +376,8 @@ struct fld_cache_entry · 143 unmodified lines | |||
| 377 | * This function handles all cases of merging and breaking up of | 376 | * This function handles all cases of merging and breaking up of |
| 378 | * ranges. | 377 | * ranges. |
| 379 | */ | 378 | */ |
| 380 | int fld_cache_insert_nolock(struct fld_cache *cache, | 379 | static int fld_cache_insert_nolock(struct fld_cache *cache, |
| 381 | struct fld_cache_entry *f_new) | 380 | struct fld_cache_entry *f_new) |
| 382 | { | 381 | { |
| 383 | struct fld_cache_entry *f_curr; | 382 | struct fld_cache_entry *f_curr; |
| 384 | struct fld_cache_entry *n; | 383 | struct fld_cache_entry *n; |
| @@ -444,36 +443,10 @@ int fld_cache_insert(struct fld_cache *cache, · 59 unmodified lines | |||
| 444 | return rc; | 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 | * Delete FLD entry in FLD cache. | 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 | struct fld_cache_entry | 451 | struct fld_cache_entry |
| 479 | *fld_cache_entry_lookup_nolock(struct fld_cache *cache, | 452 | *fld_cache_entry_lookup_nolock(struct fld_cache *cache, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | struct fld_cache_entry | 156 | struct fld_cache_entry |
| 157 | *fld_cache_entry_create(const struct lu_seq_range *range); | 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 | int fld_cache_lookup(struct fld_cache *cache, | 159 | int fld_cache_lookup(struct fld_cache *cache, |
| 166 | const u64 seq, struct lu_seq_range *range); | 160 | const u64 seq, struct lu_seq_range *range); |
| 167 | 161 | ||
| 168 | struct fld_cache_entry* | 162 | struct fld_cache_entry* |
| 169 | fld_cache_entry_lookup(struct fld_cache *cache, struct lu_seq_range *range); | 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 | struct fld_cache_entry | 165 | struct fld_cache_entry |
| 175 | *fld_cache_entry_lookup_nolock(struct fld_cache *cache, | 166 | *fld_cache_entry_lookup_nolock(struct fld_cache *cache, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | ldebugfs_remove(&fld_debugfs_dir); | 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 | MODULE_DESCRIPTION("Lustre FLD"); | 505 | MODULE_DESCRIPTION("Lustre FLD"); |
| 506 | MODULE_LICENSE("GPL"); | 506 | MODULE_LICENSE("GPL"); |
| 507 | 507 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | struct cl_io *io, struct cl_page_list *plist); | 3127 | struct cl_io *io, struct cl_page_list *plist); |
| 3128 | 3128 | ||
| 3129 | void cl_2queue_init (struct cl_2queue *queue); | 3129 | void cl_2queue_init (struct cl_2queue *queue); |
| 3130 | void cl_2queue_add (struct cl_2queue *queue, struct cl_page *page); | ||
| 3131 | void cl_2queue_disown (const struct lu_env *env, | 3130 | void cl_2queue_disown (const struct lu_env *env, |
| 3132 | struct cl_io *io, struct cl_2queue *queue); | 3131 | struct cl_io *io, struct cl_2queue *queue); |
| 3133 | void cl_2queue_discard (const struct lu_env *env, | 3132 | void cl_2queue_discard (const struct lu_env *env, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | int lprocfs_single_release(struct inode *, struct file *); | 624 | int lprocfs_single_release(struct inode *, struct file *); |
| 625 | int lprocfs_seq_release(struct inode *, struct file *); | 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 | /* write the name##_seq_show function, call LPROC_SEQ_FOPS_RO for read-only | 627 | /* write the name##_seq_show function, call LPROC_SEQ_FOPS_RO for read-only |
| 631 | proc entries; otherwise, you will define name##_seq_write function also for | 628 | proc entries; otherwise, you will define name##_seq_write function also for |
| 632 | a read-write proc entry, and then call LPROC_SEQ_SEQ instead. Finally, | 629 | a read-write proc entry, and then call LPROC_SEQ_SEQ instead. Finally, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | |||
| 26 | /* | 26 | /* |
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 28 | * Use is subject to license terms. |
| 29 | * | ||
| 30 | * Copyright (c) 2014, 2015, Intel Corporation. | ||
| 29 | */ | 31 | */ |
| 30 | /* | 32 | /* |
| 31 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -68,6 +68,7 @@ · 67 unmodified lines | |||
| 68 | everything as string options */ | 68 | everything as string options */ |
| 69 | 69 | ||
| 70 | #define LMD_MAGIC 0xbdacbd03 | 70 | #define LMD_MAGIC 0xbdacbd03 |
| 71 | #define LMD_PARAMS_MAXLEN 4096 | ||
| 71 | 72 | ||
| 72 | /* gleaned from the mount command - no persistent info here */ | 73 | /* gleaned from the mount command - no persistent info here */ |
| 73 | struct lustre_mount_data { | 74 | struct lustre_mount_data { |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -872,8 +872,6 @@ struct ldlm_resource { · 838 unmodified lines | |||
| 872 | */ | 872 | */ |
| 873 | struct mutex lr_lvb_mutex; | 873 | struct mutex lr_lvb_mutex; |
| 874 | int lr_lvb_len; | 874 | int lr_lvb_len; |
| 875 | /** protected by lr_lock */ | ||
| 876 | void *lr_lvb_data; | ||
| 877 | 875 | ||
| 878 | /** When the resource was considered as contended. */ | 876 | /** When the resource was considered as contended. */ |
| 879 | unsigned long lr_contention_time; | 877 | unsigned long lr_contention_time; |
| @@ -76,8 +76,6 @@ extern int · 75 unmodified lines | |||
| 76 | lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, size_t size, | 76 | lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, size_t size, |
| 77 | posix_acl_xattr_header **out); | 77 | posix_acl_xattr_header **out); |
| 78 | extern void | 78 | extern void |
| 79 | lustre_posix_acl_xattr_free(posix_acl_xattr_header *header, int size); | ||
| 80 | extern void | ||
| 81 | lustre_ext_acl_xattr_free(ext_acl_xattr_header *header); | 79 | lustre_ext_acl_xattr_free(ext_acl_xattr_header *header); |
| 82 | extern ext_acl_xattr_header * | 80 | extern ext_acl_xattr_header * |
| 83 | lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size, | 81 | lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | struct llog_handle **lgh, struct llog_logid *logid, | 94 | struct llog_handle **lgh, struct llog_logid *logid, |
| 95 | char *name, enum llog_open_param open_param); | 95 | char *name, enum llog_open_param open_param); |
| 96 | int llog_close(const struct lu_env *env, struct llog_handle *cathandle); | 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 | /* llog_process flags */ | 98 | /* llog_process flags */ |
| 102 | #define LLOG_FLAG_NODEAMON 0x0001 | 99 | #define LLOG_FLAG_NODEAMON 0x0001 |
| @@ -62,12 +62,6 @@ struct mds_group_info { · 61 unmodified lines | |||
| 62 | #define MDD_OBD_NAME "mdd_obd" | 62 | #define MDD_OBD_NAME "mdd_obd" |
| 63 | #define MDD_OBD_UUID "mdd_obd_uuid" | 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 | /* these are local flags, used only on the client, private */ | 65 | /* these are local flags, used only on the client, private */ |
| 72 | #define M_CHECK_STALE 0200000000 | 66 | #define M_CHECK_STALE 0200000000 |
| 73 | 67 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | struct obd_ops { | 965 | struct obd_ops { |
| 966 | struct module *o_owner; | 966 | struct module *owner; |
| 967 | int (*o_iocontrol)(unsigned int cmd, struct obd_export *exp, int len, | 967 | int (*iocontrol)(unsigned int cmd, struct obd_export *exp, int len, |
| 968 | void *karg, void *uarg); | 968 | void *karg, void *uarg); |
| 969 | int (*o_get_info)(const struct lu_env *env, struct obd_export *, | 969 | int (*get_info)(const struct lu_env *env, struct obd_export *, |
| 970 | __u32 keylen, void *key, __u32 *vallen, void *val, | 970 | __u32 keylen, void *key, __u32 *vallen, void *val, |
| 971 | struct lov_stripe_md *lsm); | 971 | struct lov_stripe_md *lsm); |
| 972 | int (*o_set_info_async)(const struct lu_env *, struct obd_export *, | 972 | int (*set_info_async)(const struct lu_env *, struct obd_export *, |
| 973 | __u32 keylen, void *key, | 973 | __u32 keylen, void *key, |
| 974 | __u32 vallen, void *val, | 974 | __u32 vallen, void *val, |
| 975 | struct ptlrpc_request_set *set); | 975 | struct ptlrpc_request_set *set); |
| 976 | int (*o_attach)(struct obd_device *dev, u32 len, void *data); | 976 | int (*attach)(struct obd_device *dev, u32 len, void *data); |
| 977 | int (*o_detach)(struct obd_device *dev); | 977 | int (*detach)(struct obd_device *dev); |
| 978 | int (*o_setup)(struct obd_device *dev, struct lustre_cfg *cfg); | 978 | int (*setup)(struct obd_device *dev, struct lustre_cfg *cfg); |
| 979 | int (*o_precleanup)(struct obd_device *dev, | 979 | int (*precleanup)(struct obd_device *dev, |
| 980 | enum obd_cleanup_stage cleanup_stage); | 980 | enum obd_cleanup_stage cleanup_stage); |
| 981 | int (*o_cleanup)(struct obd_device *dev); | 981 | int (*cleanup)(struct obd_device *dev); |
| 982 | int (*o_process_config)(struct obd_device *dev, u32 len, void *data); | 982 | int (*process_config)(struct obd_device *dev, u32 len, void *data); |
| 983 | int (*o_postrecov)(struct obd_device *dev); | 983 | int (*postrecov)(struct obd_device *dev); |
| 984 | int (*o_add_conn)(struct obd_import *imp, struct obd_uuid *uuid, | 984 | int (*add_conn)(struct obd_import *imp, struct obd_uuid *uuid, |
| 985 | int priority); | 985 | int priority); |
| 986 | int (*o_del_conn)(struct obd_import *imp, struct obd_uuid *uuid); | 986 | int (*del_conn)(struct obd_import *imp, struct obd_uuid *uuid); |
| 987 | /* connect to the target device with given connection | 987 | /* connect to the target device with given connection |
| 988 | * data. @ocd->ocd_connect_flags is modified to reflect flags actually | 988 | * data. @ocd->ocd_connect_flags is modified to reflect flags actually |
| 989 | * granted by the target, which are guaranteed to be a subset of flags | 989 | * granted by the target, which are guaranteed to be a subset of flags |
| 990 | * asked for. If @ocd == NULL, use default parameters. */ | 990 | * asked for. If @ocd == NULL, use default parameters. */ |
| 991 | int (*o_connect)(const struct lu_env *env, | 991 | int (*connect)(const struct lu_env *env, |
| 992 | struct obd_export **exp, struct obd_device *src, | 992 | struct obd_export **exp, struct obd_device *src, |
| 993 | struct obd_uuid *cluuid, struct obd_connect_data *ocd, | 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 | void *localdata); | 999 | void *localdata); |
| 995 | int (*o_reconnect)(const struct lu_env *env, | 1000 | int (*disconnect)(struct obd_export *exp); |
| 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); | ||
| 1001 | 1001 | ||
| 1002 | /* Initialize/finalize fids infrastructure. */ | 1002 | /* Initialize/finalize fids infrastructure. */ |
| 1003 | int (*o_fid_init)(struct obd_device *obd, | 1003 | int (*fid_init)(struct obd_device *obd, |
| 1004 | struct obd_export *exp, enum lu_cli_type type); | 1004 | struct obd_export *exp, enum lu_cli_type type); |
| 1005 | int (*o_fid_fini)(struct obd_device *obd); | 1005 | int (*fid_fini)(struct obd_device *obd); |
| 1006 | 1006 | ||
| 1007 | /* Allocate new fid according to passed @hint. */ | 1007 | /* Allocate new fid according to passed @hint. */ |
| 1008 | int (*o_fid_alloc)(struct obd_export *exp, struct lu_fid *fid, | 1008 | int (*fid_alloc)(struct obd_export *exp, struct lu_fid *fid, |
| 1009 | struct md_op_data *op_data); | 1009 | struct md_op_data *op_data); |
| 1010 | 1010 | ||
| 1011 | /* | 1011 | /* |
| 1012 | * Object with @fid is getting deleted, we may want to do something | 1012 | * Object with @fid is getting deleted, we may want to do something |
| 1013 | * about this. | 1013 | * about this. |
| 1014 | */ | 1014 | */ |
| 1015 | int (*o_statfs)(const struct lu_env *, 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); | 1016 | struct obd_statfs *osfs, __u64 max_age, __u32 flags); |
| 1017 | int (*o_statfs_async)(struct obd_export *exp, struct obd_info *oinfo, | 1017 | int (*statfs_async)(struct obd_export *exp, struct obd_info *oinfo, |
| 1018 | __u64 max_age, struct ptlrpc_request_set *set); | 1018 | __u64 max_age, struct ptlrpc_request_set *set); |
| 1019 | int (*o_packmd)(struct obd_export *exp, struct lov_mds_md **disk_tgt, | 1019 | int (*packmd)(struct obd_export *exp, struct lov_mds_md **disk_tgt, |
| 1020 | struct lov_stripe_md *mem_src); | 1020 | struct lov_stripe_md *mem_src); |
| 1021 | int (*o_unpackmd)(struct obd_export *exp, | 1021 | int (*unpackmd)(struct obd_export *exp, |
| 1022 | struct lov_stripe_md **mem_tgt, | 1022 | struct lov_stripe_md **mem_tgt, |
| 1023 | struct lov_mds_md *disk_src, int disk_len); | 1023 | struct lov_mds_md *disk_src, int disk_len); |
| 1024 | int (*o_preallocate)(struct lustre_handle *, u32 *req, u64 *ids); | 1024 | int (*preallocate)(struct lustre_handle *, u32 *req, u64 *ids); |
| 1025 | int (*o_create)(const struct lu_env *env, struct obd_export *exp, | 1025 | int (*create)(const struct lu_env *env, struct obd_export *exp, |
| 1026 | struct obdo *oa, struct lov_stripe_md **ea, | 1026 | struct obdo *oa, struct lov_stripe_md **ea, |
| 1027 | struct obd_trans_info *oti); | 1027 | struct obd_trans_info *oti); |
| 1028 | int (*o_destroy)(const struct lu_env *env, struct obd_export *exp, | 1028 | int (*destroy)(const struct lu_env *env, struct obd_export *exp, |
| 1029 | struct obdo *oa, struct lov_stripe_md *ea, | 1029 | struct obdo *oa, struct lov_stripe_md *ea, |
| 1030 | struct obd_trans_info *oti, struct obd_export *md_exp); | 1030 | struct obd_trans_info *oti, struct obd_export *md_exp); |
| 1031 | int (*o_setattr)(const struct lu_env *, struct obd_export *exp, | 1031 | int (*setattr)(const struct lu_env *, struct obd_export *exp, |
| 1032 | struct obd_info *oinfo, struct obd_trans_info *oti); | 1032 | struct obd_info *oinfo, struct obd_trans_info *oti); |
| 1033 | int (*o_setattr_async)(struct obd_export *exp, struct obd_info *oinfo, | 1033 | int (*setattr_async)(struct obd_export *exp, struct obd_info *oinfo, |
| 1034 | struct obd_trans_info *oti, | 1034 | struct obd_trans_info *oti, |
| 1035 | struct ptlrpc_request_set *rqset); | 1035 | struct ptlrpc_request_set *rqset); |
| 1036 | int (*o_getattr)(const struct lu_env *env, struct obd_export *exp, | 1036 | int (*getattr)(const struct lu_env *env, struct obd_export *exp, |
| 1037 | struct obd_info *oinfo); | 1037 | struct obd_info *oinfo); |
| 1038 | int (*o_getattr_async)(struct obd_export *exp, struct obd_info *oinfo, | 1038 | int (*getattr_async)(struct obd_export *exp, struct obd_info *oinfo, |
| 1039 | struct ptlrpc_request_set *set); | 1039 | struct ptlrpc_request_set *set); |
| 1040 | int (*o_adjust_kms)(struct obd_export *exp, struct lov_stripe_md *lsm, | 1040 | int (*adjust_kms)(struct obd_export *exp, struct lov_stripe_md *lsm, |
| 1041 | u64 size, int shrink); | 1041 | u64 size, int shrink); |
| 1042 | int (*o_preprw)(const struct lu_env *env, int cmd, | 1042 | int (*preprw)(const struct lu_env *env, int cmd, |
| 1043 | struct obd_export *exp, struct obdo *oa, int objcount, | 1043 | struct obd_export *exp, struct obdo *oa, int objcount, |
| 1044 | struct obd_ioobj *obj, struct niobuf_remote *remote, | 1044 | struct obd_ioobj *obj, struct niobuf_remote *remote, |
| 1045 | int *nr_pages, struct niobuf_local *local, | 1045 | int *nr_pages, struct niobuf_local *local, |
| 1046 | struct obd_trans_info *oti); | 1046 | struct obd_trans_info *oti); |
| 1047 | int (*o_commitrw)(const struct lu_env *env, int cmd, | 1047 | int (*commitrw)(const struct lu_env *env, int cmd, |
| 1048 | struct obd_export *exp, struct obdo *oa, | 1048 | struct obd_export *exp, struct obdo *oa, |
| 1049 | int objcount, struct obd_ioobj *obj, | 1049 | int objcount, struct obd_ioobj *obj, |
| 1050 | struct niobuf_remote *remote, int pages, | 1050 | struct niobuf_remote *remote, int pages, |
| 1051 | struct niobuf_local *local, | 1051 | struct niobuf_local *local, |
| 1052 | struct obd_trans_info *oti, int rc); | 1052 | struct obd_trans_info *oti, int rc); |
| 1053 | int (*o_find_cbdata)(struct obd_export *, struct lov_stripe_md *, | 1053 | int (*find_cbdata)(struct obd_export *, struct lov_stripe_md *, |
| 1054 | ldlm_iterator_t it, void *data); | 1054 | ldlm_iterator_t it, void *data); |
| 1055 | int (*o_init_export)(struct obd_export *exp); | 1055 | int (*init_export)(struct obd_export *exp); |
| 1056 | int (*o_destroy_export)(struct obd_export *exp); | 1056 | int (*destroy_export)(struct obd_export *exp); |
| 1057 | 1057 | ||
| 1058 | /* metadata-only methods */ | 1058 | /* metadata-only methods */ |
| 1059 | int (*o_import_event)(struct obd_device *, struct obd_import *, | 1059 | int (*import_event)(struct obd_device *, struct obd_import *, |
| 1060 | enum obd_import_event); | 1060 | enum obd_import_event); |
| 1061 | 1061 | ||
| 1062 | int (*o_notify)(struct obd_device *obd, struct obd_device *watched, | 1062 | int (*notify)(struct obd_device *obd, struct obd_device *watched, |
| 1063 | enum obd_notify_event ev, void *data); | 1063 | enum obd_notify_event ev, void *data); |
| 1064 | 1064 | ||
| 1065 | int (*o_health_check)(const struct lu_env *env, struct obd_device *); | 1065 | int (*health_check)(const struct lu_env *env, struct obd_device *); |
| 1066 | struct obd_uuid *(*o_get_uuid)(struct obd_export *exp); | 1066 | struct obd_uuid *(*get_uuid)(struct obd_export *exp); |
| 1067 | 1067 | ||
| 1068 | /* quota methods */ | 1068 | /* quota methods */ |
| 1069 | int (*o_quotacheck)(struct obd_device *, struct obd_export *, | 1069 | int (*quotacheck)(struct obd_device *, struct obd_export *, |
| 1070 | struct obd_quotactl *); | ||
| 1071 | int (*o_quotactl)(struct obd_device *, struct obd_export *, | ||
| 1072 | struct obd_quotactl *); | 1070 | struct obd_quotactl *); |
| 1071 | int (*quotactl)(struct obd_device *, struct obd_export *, | ||
| 1072 | struct obd_quotactl *); | ||
| 1073 | 1073 | ||
| 1074 | /* pools methods */ | 1074 | /* pools methods */ |
| 1075 | int (*o_pool_new)(struct obd_device *obd, char *poolname); | 1075 | int (*pool_new)(struct obd_device *obd, char *poolname); |
| 1076 | int (*o_pool_del)(struct obd_device *obd, char *poolname); | 1076 | int (*pool_del)(struct obd_device *obd, char *poolname); |
| 1077 | int (*o_pool_add)(struct obd_device *obd, char *poolname, | 1077 | int (*pool_add)(struct obd_device *obd, char *poolname, |
| 1078 | char *ostname); | 1078 | char *ostname); |
| 1079 | int (*o_pool_rem)(struct obd_device *obd, char *poolname, | 1079 | int (*pool_rem)(struct obd_device *obd, char *poolname, |
| 1080 | char *ostname); | 1080 | char *ostname); |
| 1081 | void (*o_getref)(struct obd_device *obd); | 1081 | void (*getref)(struct obd_device *obd); |
| 1082 | void (*o_putref)(struct obd_device *obd); | 1082 | void (*putref)(struct obd_device *obd); |
| 1083 | /* | 1083 | /* |
| 1084 | * NOTE: If adding ops, add another LPROCFS_OBD_OP_INIT() line | 1084 | * NOTE: If adding ops, add another LPROCFS_OBD_OP_INIT() line |
| 1085 | * to lprocfs_alloc_obd_stats() in obdclass/lprocfs_status.c. | 1085 | * to lprocfs_alloc_obd_stats() in obdclass/lprocfs_status.c. |
| @@ -1124,89 +1124,89 @@ struct md_open_data { · 38 unmodified lines | |||
| 1124 | struct lookup_intent; | 1124 | struct lookup_intent; |
| 1125 | 1125 | ||
| 1126 | struct md_ops { | 1126 | struct md_ops { |
| 1127 | int (*m_getstatus)(struct obd_export *, struct lu_fid *); | 1127 | int (*getstatus)(struct obd_export *, struct lu_fid *); |
| 1128 | int (*m_null_inode)(struct obd_export *, const struct lu_fid *); | 1128 | int (*null_inode)(struct obd_export *, const struct lu_fid *); |
| 1129 | int (*m_find_cbdata)(struct obd_export *, const struct lu_fid *, | 1129 | int (*find_cbdata)(struct obd_export *, const struct lu_fid *, |
| 1130 | ldlm_iterator_t, void *); | 1130 | ldlm_iterator_t, void *); |
| 1131 | int (*m_close)(struct obd_export *, struct md_op_data *, | 1131 | int (*close)(struct obd_export *, struct md_op_data *, |
| 1132 | struct md_open_data *, struct ptlrpc_request **); | 1132 | struct md_open_data *, struct ptlrpc_request **); |
| 1133 | int (*m_create)(struct obd_export *, struct md_op_data *, | 1133 | int (*create)(struct obd_export *, struct md_op_data *, |
| 1134 | const void *, int, int, __u32, __u32, cfs_cap_t, | 1134 | const void *, int, int, __u32, __u32, cfs_cap_t, |
| 1135 | __u64, struct ptlrpc_request **); | 1135 | __u64, struct ptlrpc_request **); |
| 1136 | int (*m_done_writing)(struct obd_export *, struct md_op_data *, | 1136 | int (*done_writing)(struct obd_export *, struct md_op_data *, |
| 1137 | struct md_open_data *); | 1137 | struct md_open_data *); |
| 1138 | int (*m_enqueue)(struct obd_export *, struct ldlm_enqueue_info *, | 1138 | int (*enqueue)(struct obd_export *, struct ldlm_enqueue_info *, |
| 1139 | struct lookup_intent *, struct md_op_data *, | 1139 | struct lookup_intent *, struct md_op_data *, |
| 1140 | struct lustre_handle *, void *, int, | 1140 | struct lustre_handle *, void *, int, |
| 1141 | struct ptlrpc_request **, __u64); | 1141 | struct ptlrpc_request **, __u64); |
| 1142 | int (*m_getattr)(struct obd_export *, struct md_op_data *, | 1142 | int (*getattr)(struct obd_export *, struct md_op_data *, |
| 1143 | struct ptlrpc_request **); | 1143 | struct ptlrpc_request **); |
| 1144 | int (*m_getattr_name)(struct obd_export *, struct md_op_data *, | 1144 | int (*getattr_name)(struct obd_export *, struct md_op_data *, |
| 1145 | struct ptlrpc_request **); | 1145 | struct ptlrpc_request **); |
| 1146 | int (*m_intent_lock)(struct obd_export *, struct md_op_data *, | 1146 | int (*intent_lock)(struct obd_export *, struct md_op_data *, |
| 1147 | void *, int, struct lookup_intent *, int, | 1147 | void *, int, struct lookup_intent *, int, |
| 1148 | struct ptlrpc_request **, | 1148 | struct ptlrpc_request **, |
| 1149 | ldlm_blocking_callback, __u64); | 1149 | ldlm_blocking_callback, __u64); |
| 1150 | int (*m_link)(struct obd_export *, struct md_op_data *, | 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 | struct ptlrpc_request **); | 1154 | struct ptlrpc_request **); |
| 1152 | int (*m_rename)(struct obd_export *, struct md_op_data *, | 1155 | int (*is_subdir)(struct obd_export *, const struct lu_fid *, |
| 1153 | const char *, int, const char *, int, | 1156 | const struct lu_fid *, |
| 1154 | struct ptlrpc_request **); | ||
| 1155 | int (*m_is_subdir)(struct obd_export *, const struct lu_fid *, | ||
| 1156 | const struct lu_fid *, | ||
| 1157 | struct ptlrpc_request **); | 1157 | struct ptlrpc_request **); |
| 1158 | int (*m_setattr)(struct obd_export *, struct md_op_data *, void *, | 1158 | int (*setattr)(struct obd_export *, struct md_op_data *, void *, |
| 1159 | int, void *, int, struct ptlrpc_request **, | 1159 | int, void *, int, struct ptlrpc_request **, |
| 1160 | struct md_open_data **mod); | 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 | struct ptlrpc_request **); | 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 | struct ptlrpc_request **); | 1171 | struct ptlrpc_request **); |
| 1168 | 1172 | ||
| 1169 | int (*m_setxattr)(struct obd_export *, const struct lu_fid *, | 1173 | int (*getxattr)(struct obd_export *, const struct lu_fid *, |
| 1170 | u64, const char *, const char *, int, int, int, __u32, | 1174 | u64, const char *, const char *, int, int, int, |
| 1171 | struct ptlrpc_request **); | 1175 | 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 **); | ||
| 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 *, | 1179 | int (*get_lustre_md)(struct obd_export *, struct ptlrpc_request *, |
| 1180 | struct obd_export *, struct obd_export *, | 1180 | struct obd_export *, struct obd_export *, |
| 1181 | struct lustre_md *); | 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 *, | 1185 | int (*set_open_replay_data)(struct obd_export *, |
| 1186 | struct obd_client_handle *, | 1186 | struct obd_client_handle *, |
| 1187 | struct lookup_intent *); | 1187 | struct lookup_intent *); |
| 1188 | int (*m_clear_open_replay_data)(struct obd_export *, | 1188 | int (*clear_open_replay_data)(struct obd_export *, |
| 1189 | struct obd_client_handle *); | 1189 | struct obd_client_handle *); |
| 1190 | int (*m_set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *); | 1190 | int (*set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *); |
| 1191 | 1191 | ||
| 1192 | ldlm_mode_t (*m_lock_match)(struct obd_export *, __u64, | 1192 | ldlm_mode_t (*lock_match)(struct obd_export *, __u64, |
| 1193 | const struct lu_fid *, ldlm_type_t, | 1193 | const struct lu_fid *, ldlm_type_t, |
| 1194 | ldlm_policy_data_t *, ldlm_mode_t, | 1194 | ldlm_policy_data_t *, ldlm_mode_t, |
| 1195 | struct lustre_handle *); | 1195 | struct lustre_handle *); |
| 1196 | 1196 | ||
| 1197 | int (*m_cancel_unused)(struct obd_export *, const struct lu_fid *, | 1197 | int (*cancel_unused)(struct obd_export *, const struct lu_fid *, |
| 1198 | ldlm_policy_data_t *, ldlm_mode_t, | 1198 | ldlm_policy_data_t *, ldlm_mode_t, |
| 1199 | ldlm_cancel_flags_t flags, void *opaque); | 1199 | ldlm_cancel_flags_t flags, void *opaque); |
| 1200 | 1200 | ||
| 1201 | int (*m_get_remote_perm)(struct obd_export *, const struct lu_fid *, | 1201 | int (*get_remote_perm)(struct obd_export *, const struct lu_fid *, |
| 1202 | __u32, struct ptlrpc_request **); | 1202 | __u32, struct ptlrpc_request **); |
| 1203 | 1203 | ||
| 1204 | int (*m_intent_getattr_async)(struct obd_export *, | 1204 | int (*intent_getattr_async)(struct obd_export *, |
| 1205 | struct md_enqueue_info *, | 1205 | struct md_enqueue_info *, |
| 1206 | struct ldlm_enqueue_info *); | 1206 | struct ldlm_enqueue_info *); |
| 1207 | 1207 | ||
| 1208 | int (*m_revalidate_lock)(struct obd_export *, struct lookup_intent *, | 1208 | int (*revalidate_lock)(struct obd_export *, struct lookup_intent *, |
| 1209 | struct lu_fid *, __u64 *bits); | 1209 | struct lu_fid *, __u64 *bits); |
| 1210 | 1210 | ||
| 1211 | /* | 1211 | /* |
| 1212 | * NOTE: If adding ops, add another LPROCFS_MD_OP_INIT() line to | 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 | return ret; | 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 | /* Select the best checksum algorithm among those supplied in the cksum_types | 136 | /* Select the best checksum algorithm among those supplied in the cksum_types |
| 160 | * input. | 137 | * input. |
| 161 | * | 138 | * |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | void md_from_obdo(struct md_op_data *op_data, struct obdo *oa, u32 valid); | 270 | void md_from_obdo(struct md_op_data *op_data, struct obdo *oa, u32 valid); |
| 271 | 271 | ||
| 272 | #define OBT(dev) (dev)->obd_type | 272 | #define OBT(dev) (dev)->obd_type |
| 273 | #define OBP(dev, op) (dev)->obd_type->typ_dt_ops->o_ ## op | 273 | #define OBP(dev, op) (dev)->obd_type->typ_dt_ops->op |
| 274 | #define MDP(dev, op) (dev)->obd_type->typ_md_ops->m_ ## op | 274 | #define MDP(dev, op) (dev)->obd_type->typ_md_ops->op |
| 275 | #define CTXTP(ctxt, op) (ctxt)->loc_logops->lop_##op | 275 | #define CTXTP(ctxt, op) (ctxt)->loc_logops->lop_##op |
| 276 | 276 | ||
| 277 | /* Ensure obd_setup: used for cleanup which must be called | 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 | #define OBD_COUNTER_OFFSET(op) \ | 303 | #define OBD_COUNTER_OFFSET(op) \ |
| 304 | ((offsetof(struct obd_ops, o_ ## op) - \ | 304 | ((offsetof(struct obd_ops, op) - \ |
| 305 | offsetof(struct obd_ops, o_iocontrol)) \ | 305 | offsetof(struct obd_ops, iocontrol)) \ |
| 306 | / sizeof(((struct obd_ops *)(0))->o_iocontrol)) | 306 | / sizeof(((struct obd_ops *)(0))->iocontrol)) |
| 307 | 307 | ||
| 308 | #define OBD_COUNTER_INCREMENT(obdx, op) \ | 308 | #define OBD_COUNTER_INCREMENT(obdx, op) \ |
| 309 | if ((obdx)->obd_stats != NULL) { \ | 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 | #define MD_COUNTER_OFFSET(op) \ | 326 | #define MD_COUNTER_OFFSET(op) \ |
| 327 | ((offsetof(struct md_ops, m_ ## op) - \ | 327 | ((offsetof(struct md_ops, op) - \ |
| 328 | offsetof(struct md_ops, m_getstatus)) \ | 328 | offsetof(struct md_ops, getstatus)) \ |
| 329 | / sizeof(((struct md_ops *)(0))->m_getstatus)) | 329 | / sizeof(((struct md_ops *)(0))->getstatus)) |
| 330 | 330 | ||
| 331 | #define MD_COUNTER_INCREMENT(obdx, op) \ | 331 | #define MD_COUNTER_INCREMENT(obdx, op) \ |
| 332 | if ((obd)->md_stats != NULL) { \ | 332 | if ((obd)->md_stats != NULL) { \ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | struct inode *inode = ccc_object_inode(obj); | 428 | struct inode *inode = ccc_object_inode(obj); |
| 429 | 429 | ||
| 430 | cl_isize_lock(inode); | 430 | ll_inode_size_lock(inode); |
| 431 | cl_object_attr_lock(obj); | 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 | struct inode *inode = ccc_object_inode(obj); | 436 | struct inode *inode = ccc_object_inode(obj); |
| 437 | 437 | ||
| 438 | cl_object_attr_unlock(obj); | 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 | return (e1->start == e2->start) && (e1->end == e2->end); | 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 | static inline __u64 max_u64(__u64 x, __u64 y) | 99 | static inline __u64 max_u64(__u64 x, __u64 y) |
| 112 | { | 100 | { |
| 113 | return x > y ? x : y; | 101 | return x > y ? x : y; |
| @@ -278,14 +266,14 @@ struct interval_node *interval_insert(struct interval_node *node, · 164 unmodified lines | |||
| 278 | p = root; | 266 | p = root; |
| 279 | while (*p) { | 267 | while (*p) { |
| 280 | parent = *p; | 268 | parent = *p; |
| 281 | if (node_equal(parent, node)) | 269 | if (extent_equal(&parent->in_extent, &node->in_extent)) |
| 282 | return parent; | 270 | return parent; |
| 283 | 271 | ||
| 284 | /* max_high field must be updated after each iteration */ | 272 | /* max_high field must be updated after each iteration */ |
| 285 | if (parent->in_max_high < interval_high(node)) | 273 | if (parent->in_max_high < interval_high(node)) |
| 286 | parent->in_max_high = interval_high(node); | 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 | p = &parent->in_left; | 277 | p = &parent->in_left; |
| 290 | else | 278 | else |
| 291 | p = &parent->in_right; | 279 | p = &parent->in_right; |
| @@ -149,7 +149,7 @@ static inline int lock_mode_to_index(ldlm_mode_t mode) · 148 unmodified lines | |||
| 149 | int index; | 149 | int index; |
| 150 | 150 | ||
| 151 | LASSERT(mode != 0); | 151 | LASSERT(mode != 0); |
| 152 | LASSERT(IS_PO2(mode)); | 152 | LASSERT(is_power_of_2(mode)); |
| 153 | for (index = -1; mode; index++) | 153 | for (index = -1; mode; index++) |
| 154 | mode >>= 1; | 154 | mode >>= 1; |
| 155 | LASSERT(index < LCK_MODE_NUM); | 155 | LASSERT(index < LCK_MODE_NUM); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -176,11 +176,6 @@ enum { · 142 unmodified lines | |||
| 176 | LDLM_POOL_LAST_STAT | 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 | * Calculates suggested grant_step in % of available locks for passed | 180 | * Calculates suggested grant_step in % of available locks for passed |
| 186 | * \a period. This is later used in grant_plan calculations. | 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 | (t >> LDLM_POOL_GSP_STEP_SHIFT)); | 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 | * Recalculates next stats on passed \a pl. | 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 | static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl) | 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 | * Get new SLV and Limit from obd which is updated with coming | 244 | * Get new SLV and Limit from obd which is updated with coming |
| 265 | * RPCs. | 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 | LASSERT(obd != NULL); | 249 | LASSERT(obd != NULL); |
| 269 | read_lock(&obd->obd_pool_lock); | 250 | read_lock(&obd->obd_pool_lock); |
| 270 | pl->pl_server_lock_volume = obd->obd_pool_slv; | 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 | read_unlock(&obd->obd_pool_lock); | 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 | * Do not cancel locks in case lru resize is disabled for this ns. | 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 | ret = 0; | 290 | ret = 0; |
| 309 | goto out; | 291 | goto out; |
| 310 | } | 292 | } |
| @@ -315,7 +297,8 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) · 4 unmodified lines | |||
| 315 | * It may be called when SLV has changed much, this is why we do not | 297 | * It may be called when SLV has changed much, this is why we do not |
| 316 | * take into account pl->pl_recalc_time here. | 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 | out: | 303 | out: |
| 321 | spin_lock(&pl->pl_lock); | 304 | spin_lock(&pl->pl_lock); |
| @@ -341,7 +324,7 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl, · 19 unmodified lines | |||
| 341 | struct ldlm_namespace *ns; | 324 | struct ldlm_namespace *ns; |
| 342 | int unused; | 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 | * Do not cancel locks in case lru resize is disabled for this ns. | 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 | spin_lock(&pl->pl_lock); | 436 | spin_lock(&pl->pl_lock); |
| 454 | slv = pl->pl_server_lock_volume; | 437 | slv = pl->pl_server_lock_volume; |
| 455 | clv = pl->pl_client_lock_volume; | 438 | clv = pl->pl_client_lock_volume; |
| 456 | limit = ldlm_pool_get_limit(pl); | 439 | limit = atomic_read(&pl->pl_limit); |
| 457 | granted = atomic_read(&pl->pl_granted); | 440 | granted = atomic_read(&pl->pl_granted); |
| 458 | grant_rate = atomic_read(&pl->pl_grant_rate); | 441 | grant_rate = atomic_read(&pl->pl_grant_rate); |
| 459 | cancel_rate = atomic_read(&pl->pl_cancel_rate); | 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 | static int ldlm_pool_sysfs_init(struct ldlm_pool *pl) | 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 | int err; | 546 | int err; |
| 563 | 547 | ||
| 564 | init_completion(&pl->pl_kobj_unregister); | 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 | static int ldlm_pool_debugfs_init(struct ldlm_pool *pl) | 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 | struct dentry *debugfs_ns_parent; | 559 | struct dentry *debugfs_ns_parent; |
| 575 | struct lprocfs_vars pool_vars[2]; | 560 | struct lprocfs_vars pool_vars[2]; |
| 576 | char *var_name = NULL; | 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 | snprintf(pl->pl_name, sizeof(pl->pl_name), "ldlm-pool-%s-%d", | 670 | snprintf(pl->pl_name, sizeof(pl->pl_name), "ldlm-pool-%s-%d", |
| 686 | ldlm_ns_name(ns), idx); | 671 | ldlm_ns_name(ns), idx); |
| 687 | 672 | ||
| 688 | ldlm_pool_set_limit(pl, 1); | 673 | atomic_set(&pl->pl_limit, 1); |
| 689 | pl->pl_server_lock_volume = 0; | 674 | pl->pl_server_lock_volume = 0; |
| 690 | pl->pl_ops = &ldlm_cli_pool_ops; | 675 | pl->pl_ops = &ldlm_cli_pool_ops; |
| 691 | pl->pl_recalc_period = LDLM_POOL_CLI_DEF_RECALC_PERIOD; | 676 | pl->pl_recalc_period = LDLM_POOL_CLI_DEF_RECALC_PERIOD; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | CERROR("%s: lvbo_init failed for resource %#llx:%#llx: rc = %d\n", | 1154 | CERROR("%s: lvbo_init failed for resource %#llx:%#llx: rc = %d\n", |
| 1155 | ns->ns_obd->obd_name, name->name[0], | 1155 | ns->ns_obd->obd_name, name->name[0], |
| 1156 | name->name[1], rc); | 1156 | name->name[1], rc); |
| 1157 | kfree(res->lr_lvb_data); | ||
| 1158 | res->lr_lvb_data = NULL; | ||
| 1159 | res->lr_lvb_len = rc; | 1157 | res->lr_lvb_len = rc; |
| 1160 | mutex_unlock(&res->lr_lvb_mutex); | 1158 | mutex_unlock(&res->lr_lvb_mutex); |
| 1161 | ldlm_resource_putref(res); | 1159 | ldlm_resource_putref(res); |
| @@ -94,17 +94,14 @@ static struct kernel_param_ops param_ops_debugmb = { · 93 unmodified lines | |||
| 94 | static unsigned int libcfs_debug_mb; | 94 | static unsigned int libcfs_debug_mb; |
| 95 | module_param(libcfs_debug_mb, debugmb, 0644); | 95 | module_param(libcfs_debug_mb, debugmb, 0644); |
| 96 | MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size."); | 96 | MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size."); |
| 97 | EXPORT_SYMBOL(libcfs_debug_mb); | ||
| 98 | 97 | ||
| 99 | unsigned int libcfs_printk = D_CANTMASK; | 98 | unsigned int libcfs_printk = D_CANTMASK; |
| 100 | module_param(libcfs_printk, uint, 0644); | 99 | module_param(libcfs_printk, uint, 0644); |
| 101 | MODULE_PARM_DESC(libcfs_printk, "Lustre kernel debug console mask"); | 100 | MODULE_PARM_DESC(libcfs_printk, "Lustre kernel debug console mask"); |
| 102 | EXPORT_SYMBOL(libcfs_printk); | ||
| 103 | 101 | ||
| 104 | unsigned int libcfs_console_ratelimit = 1; | 102 | unsigned int libcfs_console_ratelimit = 1; |
| 105 | module_param(libcfs_console_ratelimit, uint, 0644); | 103 | module_param(libcfs_console_ratelimit, uint, 0644); |
| 106 | MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)"); | 104 | MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)"); |
| 107 | EXPORT_SYMBOL(libcfs_console_ratelimit); | ||
| 108 | 105 | ||
| 109 | static int param_set_delay_minmax(const char *val, | 106 | static int param_set_delay_minmax(const char *val, |
| 110 | const struct kernel_param *kp, | 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 | unsigned int libcfs_console_max_delay; | 134 | unsigned int libcfs_console_max_delay; |
| 138 | EXPORT_SYMBOL(libcfs_console_max_delay); | ||
| 139 | unsigned int libcfs_console_min_delay; | 135 | unsigned int libcfs_console_min_delay; |
| 140 | EXPORT_SYMBOL(libcfs_console_min_delay); | ||
| 141 | 136 | ||
| 142 | static int param_set_console_max_delay(const char *val, | 137 | static int param_set_console_max_delay(const char *val, |
| 143 | const struct kernel_param *kp) | 138 | const struct kernel_param *kp) |
| @@ -207,10 +202,8 @@ static struct kernel_param_ops param_ops_uintpos = { · 63 unmodified lines | |||
| 207 | unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF; | 202 | unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF; |
| 208 | module_param(libcfs_console_backoff, uintpos, 0644); | 203 | module_param(libcfs_console_backoff, uintpos, 0644); |
| 209 | MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor"); | 204 | MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor"); |
| 210 | EXPORT_SYMBOL(libcfs_console_backoff); | ||
| 211 | 205 | ||
| 212 | unsigned int libcfs_debug_binary = 1; | 206 | unsigned int libcfs_debug_binary = 1; |
| 213 | EXPORT_SYMBOL(libcfs_debug_binary); | ||
| 214 | 207 | ||
| 215 | unsigned int libcfs_stack = 3 * THREAD_SIZE / 4; | 208 | unsigned int libcfs_stack = 3 * THREAD_SIZE / 4; |
| 216 | EXPORT_SYMBOL(libcfs_stack); | 209 | EXPORT_SYMBOL(libcfs_stack); |
| @@ -221,7 +214,6 @@ EXPORT_SYMBOL(libcfs_catastrophe); · 4 unmodified lines | |||
| 221 | unsigned int libcfs_panic_on_lbug = 1; | 214 | unsigned int libcfs_panic_on_lbug = 1; |
| 222 | module_param(libcfs_panic_on_lbug, uint, 0644); | 215 | module_param(libcfs_panic_on_lbug, uint, 0644); |
| 223 | MODULE_PARM_DESC(libcfs_panic_on_lbug, "Lustre kernel panic on LBUG"); | 216 | MODULE_PARM_DESC(libcfs_panic_on_lbug, "Lustre kernel panic on LBUG"); |
| 224 | EXPORT_SYMBOL(libcfs_panic_on_lbug); | ||
| 225 | 217 | ||
| 226 | static wait_queue_head_t debug_ctlwq; | 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 | if (libcfs_debug_file_path != NULL) { | 506 | if (libcfs_debug_file_path != NULL) { |
| 515 | strncpy(libcfs_debug_file_path_arr, | 507 | strlcpy(libcfs_debug_file_path_arr, |
| 516 | libcfs_debug_file_path, PATH_MAX-1); | 508 | libcfs_debug_file_path, |
| 517 | libcfs_debug_file_path_arr[PATH_MAX - 1] = '\0'; | 509 | sizeof(libcfs_debug_file_path_arr)); |
| 518 | } | 510 | } |
| 519 | 511 | ||
| 520 | /* If libcfs_debug_mb is set to an invalid value or uninitialized | 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 | #undef DEBUG_SUBSYSTEM | 558 | #undef DEBUG_SUBSYSTEM |
| 567 | #define DEBUG_SUBSYSTEM S_LNET | 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 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 26 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 27 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | int ret; | 126 | int ret; |
| 127 | 127 | ||
| 128 | ret = __cfs_fail_check_set(id, value, set); | 128 | ret = __cfs_fail_check_set(id, value, set); |
| 129 | if (ret) { | 129 | if (ret && likely(ms > 0)) { |
| 130 | CERROR("cfs_fail_timeout id %x sleeping for %dms\n", | 130 | CERROR("cfs_fail_timeout id %x sleeping for %dms\n", |
| 131 | id, ms); | 131 | id, ms); |
| 132 | set_current_state(TASK_UNINTERRUPTIBLE); | 132 | set_current_state(TASK_UNINTERRUPTIBLE); |
| @@ -106,9 +106,10 @@ · 105 unmodified lines | |||
| 106 | * Now we support both locked iteration & lockless iteration of hash | 106 | * Now we support both locked iteration & lockless iteration of hash |
| 107 | * table. Also, user can break the iteration by return 1 in callback. | 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 | #include "../../include/linux/libcfs/libcfs.h" | 112 | #include "../../include/linux/libcfs/libcfs.h" |
| 111 | #include <linux/seq_file.h> | ||
| 112 | 113 | ||
| 113 | #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1 | 114 | #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1 |
| 114 | static unsigned int warn_on_depth = 8; | 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 | /** No lock hash */ | 162 | /** No lock hash */ |
| 162 | static struct cfs_hash_lock_ops cfs_hash_nl_lops = { | 163 | static struct cfs_hash_lock_ops cfs_hash_nl_lops = { |
| 163 | .hs_lock = cfs_hash_nl_lock, | 164 | .hs_lock = cfs_hash_nl_lock, |
| 164 | .hs_unlock = cfs_hash_nl_unlock, | 165 | .hs_unlock = cfs_hash_nl_unlock, |
| 165 | .hs_bkt_lock = cfs_hash_nl_lock, | 166 | .hs_bkt_lock = cfs_hash_nl_lock, |
| 166 | .hs_bkt_unlock = cfs_hash_nl_unlock, | 167 | .hs_bkt_unlock = cfs_hash_nl_unlock, |
| 167 | }; | 168 | }; |
| 168 | 169 | ||
| 169 | /** no bucket lock, one spinlock to protect everything */ | 170 | /** no bucket lock, one spinlock to protect everything */ |
| 170 | static struct cfs_hash_lock_ops cfs_hash_nbl_lops = { | 171 | static struct cfs_hash_lock_ops cfs_hash_nbl_lops = { |
| 171 | .hs_lock = cfs_hash_spin_lock, | 172 | .hs_lock = cfs_hash_spin_lock, |
| 172 | .hs_unlock = cfs_hash_spin_unlock, | 173 | .hs_unlock = cfs_hash_spin_unlock, |
| 173 | .hs_bkt_lock = cfs_hash_nl_lock, | 174 | .hs_bkt_lock = cfs_hash_nl_lock, |
| 174 | .hs_bkt_unlock = cfs_hash_nl_unlock, | 175 | .hs_bkt_unlock = cfs_hash_nl_unlock, |
| 175 | }; | 176 | }; |
| 176 | 177 | ||
| 177 | /** spin bucket lock, rehash is enabled */ | 178 | /** spin bucket lock, rehash is enabled */ |
| 178 | static struct cfs_hash_lock_ops cfs_hash_bkt_spin_lops = { | 179 | static struct cfs_hash_lock_ops cfs_hash_bkt_spin_lops = { |
| 179 | .hs_lock = cfs_hash_rw_lock, | 180 | .hs_lock = cfs_hash_rw_lock, |
| 180 | .hs_unlock = cfs_hash_rw_unlock, | 181 | .hs_unlock = cfs_hash_rw_unlock, |
| 181 | .hs_bkt_lock = cfs_hash_spin_lock, | 182 | .hs_bkt_lock = cfs_hash_spin_lock, |
| 182 | .hs_bkt_unlock = cfs_hash_spin_unlock, | 183 | .hs_bkt_unlock = cfs_hash_spin_unlock, |
| 183 | }; | 184 | }; |
| 184 | 185 | ||
| 185 | /** rw bucket lock, rehash is enabled */ | 186 | /** rw bucket lock, rehash is enabled */ |
| 186 | static struct cfs_hash_lock_ops cfs_hash_bkt_rw_lops = { | 187 | static struct cfs_hash_lock_ops cfs_hash_bkt_rw_lops = { |
| 187 | .hs_lock = cfs_hash_rw_lock, | 188 | .hs_lock = cfs_hash_rw_lock, |
| 188 | .hs_unlock = cfs_hash_rw_unlock, | 189 | .hs_unlock = cfs_hash_rw_unlock, |
| 189 | .hs_bkt_lock = cfs_hash_rw_lock, | 190 | .hs_bkt_lock = cfs_hash_rw_lock, |
| 190 | .hs_bkt_unlock = cfs_hash_rw_unlock, | 191 | .hs_bkt_unlock = cfs_hash_rw_unlock, |
| 191 | }; | 192 | }; |
| 192 | 193 | ||
| 193 | /** spin bucket lock, rehash is disabled */ | 194 | /** spin bucket lock, rehash is disabled */ |
| 194 | static struct cfs_hash_lock_ops cfs_hash_nr_bkt_spin_lops = { | 195 | static struct cfs_hash_lock_ops cfs_hash_nr_bkt_spin_lops = { |
| 195 | .hs_lock = cfs_hash_nl_lock, | 196 | .hs_lock = cfs_hash_nl_lock, |
| 196 | .hs_unlock = cfs_hash_nl_unlock, | 197 | .hs_unlock = cfs_hash_nl_unlock, |
| 197 | .hs_bkt_lock = cfs_hash_spin_lock, | 198 | .hs_bkt_lock = cfs_hash_spin_lock, |
| 198 | .hs_bkt_unlock = cfs_hash_spin_unlock, | 199 | .hs_bkt_unlock = cfs_hash_spin_unlock, |
| 199 | }; | 200 | }; |
| 200 | 201 | ||
| 201 | /** rw bucket lock, rehash is disabled */ | 202 | /** rw bucket lock, rehash is disabled */ |
| 202 | static struct cfs_hash_lock_ops cfs_hash_nr_bkt_rw_lops = { | 203 | static struct cfs_hash_lock_ops cfs_hash_nr_bkt_rw_lops = { |
| 203 | .hs_lock = cfs_hash_nl_lock, | 204 | .hs_lock = cfs_hash_nl_lock, |
| 204 | .hs_unlock = cfs_hash_nl_unlock, | 205 | .hs_unlock = cfs_hash_nl_unlock, |
| 205 | .hs_bkt_lock = cfs_hash_rw_lock, | 206 | .hs_bkt_lock = cfs_hash_rw_lock, |
| 206 | .hs_bkt_unlock = cfs_hash_rw_unlock, | 207 | .hs_bkt_unlock = cfs_hash_rw_unlock, |
| 207 | }; | 208 | }; |
| 208 | 209 | ||
| 209 | static void | 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 | struct cfs_hash_head_dep { | 282 | struct cfs_hash_head_dep { |
| 282 | struct hlist_head hd_head; /**< entries list */ | 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 | static int | 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 | struct cfs_hash_dhead { | 330 | struct cfs_hash_dhead { |
| 330 | struct hlist_head dh_head; /**< entries list */ | 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 | static int | 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 | struct cfs_hash_dhead_dep { | 386 | struct cfs_hash_dhead_dep { |
| 386 | struct hlist_head dd_head; /**< entries list */ | 387 | struct hlist_head dd_head; /**< entries list */ |
| 387 | struct hlist_node *dd_tail; /**< the last entry */ | 388 | struct hlist_node *dd_tail; /**< the last entry */ |
| 388 | unsigned int dd_depth; /**< list length */ | 389 | unsigned int dd_depth; /**< list length */ |
| 389 | }; | 390 | }; |
| 390 | 391 | ||
| 391 | static int | 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 | static struct cfs_hash_hlist_ops cfs_hash_hh_hops = { | 439 | static struct cfs_hash_hlist_ops cfs_hash_hh_hops = { |
| 439 | .hop_hhead = cfs_hash_hh_hhead, | 440 | .hop_hhead = cfs_hash_hh_hhead, |
| 440 | .hop_hhead_size = cfs_hash_hh_hhead_size, | 441 | .hop_hhead_size = cfs_hash_hh_hhead_size, |
| 441 | .hop_hnode_add = cfs_hash_hh_hnode_add, | 442 | .hop_hnode_add = cfs_hash_hh_hnode_add, |
| 442 | .hop_hnode_del = cfs_hash_hh_hnode_del, | 443 | .hop_hnode_del = cfs_hash_hh_hnode_del, |
| 443 | }; | 444 | }; |
| 444 | 445 | ||
| 445 | static struct cfs_hash_hlist_ops cfs_hash_hd_hops = { | 446 | static struct cfs_hash_hlist_ops cfs_hash_hd_hops = { |
| 446 | .hop_hhead = cfs_hash_hd_hhead, | 447 | .hop_hhead = cfs_hash_hd_hhead, |
| 447 | .hop_hhead_size = cfs_hash_hd_hhead_size, | 448 | .hop_hhead_size = cfs_hash_hd_hhead_size, |
| 448 | .hop_hnode_add = cfs_hash_hd_hnode_add, | 449 | .hop_hnode_add = cfs_hash_hd_hnode_add, |
| 449 | .hop_hnode_del = cfs_hash_hd_hnode_del, | 450 | .hop_hnode_del = cfs_hash_hd_hnode_del, |
| 450 | }; | 451 | }; |
| 451 | 452 | ||
| 452 | static struct cfs_hash_hlist_ops cfs_hash_dh_hops = { | 453 | static struct cfs_hash_hlist_ops cfs_hash_dh_hops = { |
| 453 | .hop_hhead = cfs_hash_dh_hhead, | 454 | .hop_hhead = cfs_hash_dh_hhead, |
| 454 | .hop_hhead_size = cfs_hash_dh_hhead_size, | 455 | .hop_hhead_size = cfs_hash_dh_hhead_size, |
| 455 | .hop_hnode_add = cfs_hash_dh_hnode_add, | 456 | .hop_hnode_add = cfs_hash_dh_hnode_add, |
| 456 | .hop_hnode_del = cfs_hash_dh_hnode_del, | 457 | .hop_hnode_del = cfs_hash_dh_hnode_del, |
| 457 | }; | 458 | }; |
| 458 | 459 | ||
| 459 | static struct cfs_hash_hlist_ops cfs_hash_dd_hops = { | 460 | static struct cfs_hash_hlist_ops cfs_hash_dd_hops = { |
| 460 | .hop_hhead = cfs_hash_dd_hhead, | 461 | .hop_hhead = cfs_hash_dd_hhead, |
| 461 | .hop_hhead_size = cfs_hash_dd_hhead_size, | 462 | .hop_hhead_size = cfs_hash_dd_hhead_size, |
| 462 | .hop_hnode_add = cfs_hash_dd_hnode_add, | 463 | .hop_hnode_add = cfs_hash_dd_hnode_add, |
| 463 | .hop_hnode_del = cfs_hash_dd_hnode_del, | 464 | .hop_hnode_del = cfs_hash_dd_hnode_del, |
| 464 | }; | 465 | }; |
| 465 | 466 | ||
| 466 | static void | 467 | static void |
| @@ -529,7 +530,7 @@ void · 62 unmodified lines | |||
| 529 | cfs_hash_bd_add_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, | 530 | cfs_hash_bd_add_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, |
| 530 | struct hlist_node *hnode) | 531 | struct hlist_node *hnode) |
| 531 | { | 532 | { |
| 532 | int rc; | 533 | int rc; |
| 533 | 534 | ||
| 534 | rc = hs->hs_hops->hop_hnode_add(hs, bd, hnode); | 535 | rc = hs->hs_hops->hop_hnode_add(hs, bd, hnode); |
| 535 | cfs_hash_bd_dep_record(hs, bd, rc); | 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 | struct cfs_hash_bucket *obkt = bd_old->bd_bucket; | 574 | struct cfs_hash_bucket *obkt = bd_old->bd_bucket; |
| 574 | struct cfs_hash_bucket *nbkt = bd_new->bd_bucket; | 575 | struct cfs_hash_bucket *nbkt = bd_new->bd_bucket; |
| 575 | int rc; | 576 | int rc; |
| 576 | 577 | ||
| 577 | if (cfs_hash_bd_compare(bd_old, bd_new) == 0) | 578 | if (cfs_hash_bd_compare(bd_old, bd_new) == 0) |
| 578 | return; | 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 | if (unlikely(nbkt->hsb_version == 0)) | 594 | if (unlikely(nbkt->hsb_version == 0)) |
| 594 | nbkt->hsb_version++; | 595 | nbkt->hsb_version++; |
| 595 | } | 596 | } |
| 596 | EXPORT_SYMBOL(cfs_hash_bd_move_locked); | ||
| 597 | 597 | ||
| 598 | enum { | 598 | enum { |
| 599 | /** always set, for sanity (avoid ZERO intent) */ | 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 | /** return entry with a ref */ | 601 | /** return entry with a ref */ |
| 602 | CFS_HS_LOOKUP_MASK_REF = BIT(1), | 602 | CFS_HS_LOOKUP_MASK_REF = BIT(1), |
| 603 | /** add entry if not existing */ | 603 | /** add entry if not existing */ |
| 604 | CFS_HS_LOOKUP_MASK_ADD = BIT(2), | 604 | CFS_HS_LOOKUP_MASK_ADD = BIT(2), |
| 605 | /** delete entry, ignore other masks */ | 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 | enum cfs_hash_lookup_intent { | 609 | enum cfs_hash_lookup_intent { |
| 610 | /** return item w/o refcount */ | 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 | /** return item with refcount */ | 612 | /** return item with refcount */ |
| 613 | CFS_HS_LOOKUP_IT_FIND = (CFS_HS_LOOKUP_MASK_FIND | | 613 | CFS_HS_LOOKUP_IT_FIND = (CFS_HS_LOOKUP_MASK_FIND | |
| 614 | CFS_HS_LOOKUP_MASK_REF), | 614 | CFS_HS_LOOKUP_MASK_REF), |
| 615 | /** return item w/o refcount if existed, otherwise add */ | 615 | /** return item w/o refcount if existed, otherwise add */ |
| 616 | CFS_HS_LOOKUP_IT_ADD = (CFS_HS_LOOKUP_MASK_FIND | | 616 | CFS_HS_LOOKUP_IT_ADD = (CFS_HS_LOOKUP_MASK_FIND | |
| 617 | CFS_HS_LOOKUP_MASK_ADD), | 617 | CFS_HS_LOOKUP_MASK_ADD), |
| 618 | /** return item with refcount if existed, otherwise add */ | 618 | /** return item with refcount if existed, otherwise add */ |
| 619 | CFS_HS_LOOKUP_IT_FINDADD = (CFS_HS_LOOKUP_IT_FIND | | 619 | CFS_HS_LOOKUP_IT_FINDADD = (CFS_HS_LOOKUP_IT_FIND | |
| 620 | CFS_HS_LOOKUP_MASK_ADD), | 620 | CFS_HS_LOOKUP_MASK_ADD), |
| 621 | /** delete if existed */ | 621 | /** delete if existed */ |
| 622 | CFS_HS_LOOKUP_IT_FINDDEL = (CFS_HS_LOOKUP_MASK_FIND | | 622 | CFS_HS_LOOKUP_IT_FINDDEL = (CFS_HS_LOOKUP_MASK_FIND | |
| 623 | CFS_HS_LOOKUP_MASK_DEL) | 623 | CFS_HS_LOOKUP_MASK_DEL) |
| 624 | }; | 624 | }; |
| 625 | 625 | ||
| 626 | static struct hlist_node * | 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 | enum cfs_hash_lookup_intent intent) | 629 | enum cfs_hash_lookup_intent intent) |
| 630 | 630 | ||
| 631 | { | 631 | { |
| 632 | struct hlist_head *hhead = cfs_hash_bd_hhead(hs, bd); | 632 | struct hlist_head *hhead = cfs_hash_bd_hhead(hs, bd); |
| 633 | struct hlist_node *ehnode; | 633 | struct hlist_node *ehnode; |
| 634 | struct hlist_node *match; | 634 | struct hlist_node *match; |
| 635 | int intent_add = (intent & CFS_HS_LOOKUP_MASK_ADD) != 0; | 635 | int intent_add = (intent & CFS_HS_LOOKUP_MASK_ADD) != 0; |
| 636 | 636 | ||
| 637 | /* with this function, we can avoid a lot of useless refcount ops, | 637 | /* with this function, we can avoid a lot of useless refcount ops, |
| 638 | * which are expensive atomic operations most time. */ | 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 | struct hlist_node * | 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 | return cfs_hash_bd_lookup_intent(hs, bd, key, NULL, | 671 | return cfs_hash_bd_lookup_intent(hs, bd, key, NULL, |
| 671 | CFS_HS_LOOKUP_IT_FIND); | 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 | EXPORT_SYMBOL(cfs_hash_bd_lookup_locked); | 674 | EXPORT_SYMBOL(cfs_hash_bd_lookup_locked); |
| 674 | 675 | ||
| 675 | struct hlist_node * | 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 | return cfs_hash_bd_lookup_intent(hs, bd, key, NULL, | 680 | return cfs_hash_bd_lookup_intent(hs, bd, key, NULL, |
| 679 | CFS_HS_LOOKUP_IT_PEEK); | 681 | CFS_HS_LOOKUP_IT_PEEK); |
| 680 | } | 682 | } |
| 681 | EXPORT_SYMBOL(cfs_hash_bd_peek_locked); | 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 | static void | 685 | static void |
| 705 | cfs_hash_multi_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, | 686 | cfs_hash_multi_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, |
| 706 | unsigned n, int excl) | 687 | unsigned n, int excl) |
| 707 | { | 688 | { |
| 708 | struct cfs_hash_bucket *prev = NULL; | 689 | struct cfs_hash_bucket *prev = NULL; |
| 709 | int i; | 690 | int i; |
| 710 | 691 | ||
| 711 | /** | 692 | /** |
| 712 | * bds must be ascendantly ordered by bd->bd_bucket->hsb_index. | 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 | unsigned n, int excl) | 710 | unsigned n, int excl) |
| 730 | { | 711 | { |
| 731 | struct cfs_hash_bucket *prev = NULL; | 712 | struct cfs_hash_bucket *prev = NULL; |
| 732 | int i; | 713 | int i; |
| 733 | 714 | ||
| 734 | cfs_hash_for_each_bd(bds, n, i) { | 715 | cfs_hash_for_each_bd(bds, n, i) { |
| 735 | if (prev != bds[i].bd_bucket) { | 716 | if (prev != bds[i].bd_bucket) { |
| @@ -743,8 +724,8 @@ static struct hlist_node * · 7 unmodified lines | |||
| 743 | cfs_hash_multi_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, | 724 | cfs_hash_multi_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, |
| 744 | unsigned n, const void *key) | 725 | unsigned n, const void *key) |
| 745 | { | 726 | { |
| 746 | struct hlist_node *ehnode; | 727 | struct hlist_node *ehnode; |
| 747 | unsigned i; | 728 | unsigned i; |
| 748 | 729 | ||
| 749 | cfs_hash_for_each_bd(bds, n, i) { | 730 | cfs_hash_for_each_bd(bds, n, i) { |
| 750 | ehnode = cfs_hash_bd_lookup_intent(hs, &bds[i], key, NULL, | 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 | static struct hlist_node * | 739 | static struct hlist_node * |
| 759 | cfs_hash_multi_bd_findadd_locked(struct cfs_hash *hs, | 740 | cfs_hash_multi_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, |
| 760 | struct cfs_hash_bd *bds, unsigned n, const void *key, | 741 | unsigned n, const void *key, |
| 761 | struct hlist_node *hnode, int noref) | 742 | struct hlist_node *hnode, int noref) |
| 762 | { | 743 | { |
| 763 | struct hlist_node *ehnode; | 744 | struct hlist_node *ehnode; |
| 764 | int intent; | 745 | int intent; |
| 765 | unsigned i; | 746 | unsigned i; |
| 766 | 747 | ||
| 767 | LASSERT(hnode != NULL); | 748 | LASSERT(hnode != NULL); |
| 768 | intent = (!noref * CFS_HS_LOOKUP_MASK_REF) | CFS_HS_LOOKUP_IT_PEEK; | 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 | if (i == 1) { /* only one bucket */ | 758 | if (i == 1) { /* only one bucket */ |
| 778 | cfs_hash_bd_add_locked(hs, &bds[0], hnode); | 759 | cfs_hash_bd_add_locked(hs, &bds[0], hnode); |
| 779 | } else { | 760 | } else { |
| 780 | struct cfs_hash_bd mybd; | 761 | struct cfs_hash_bd mybd; |
| 781 | 762 | ||
| 782 | cfs_hash_bd_get(hs, key, &mybd); | 763 | cfs_hash_bd_get(hs, key, &mybd); |
| 783 | cfs_hash_bd_add_locked(hs, &mybd, hnode); | 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 | unsigned n, const void *key, | 772 | unsigned n, const void *key, |
| 792 | struct hlist_node *hnode) | 773 | struct hlist_node *hnode) |
| 793 | { | 774 | { |
| 794 | struct hlist_node *ehnode; | 775 | struct hlist_node *ehnode; |
| 795 | unsigned i; | 776 | unsigned int i; |
| 796 | 777 | ||
| 797 | cfs_hash_for_each_bd(bds, n, i) { | 778 | cfs_hash_for_each_bd(bds, n, i) { |
| 798 | ehnode = cfs_hash_bd_lookup_intent(hs, &bds[i], key, hnode, | 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 | static void | 787 | static void |
| 807 | cfs_hash_bd_order(struct cfs_hash_bd *bd1, struct cfs_hash_bd *bd2) | 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 | if (bd2->bd_bucket == NULL) | 792 | if (bd2->bd_bucket == NULL) |
| 812 | return; | 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 | void | 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 | /* NB: caller should hold hs_lock.rw if REHASH is set */ | 818 | /* NB: caller should hold hs_lock.rw if REHASH is set */ |
| 837 | cfs_hash_bd_from_key(hs, hs->hs_buckets, | 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 | cfs_hash_bd_order(&bds[0], &bds[1]); | 831 | cfs_hash_bd_order(&bds[0], &bds[1]); |
| 850 | } | 832 | } |
| 851 | EXPORT_SYMBOL(cfs_hash_dual_bd_get); | ||
| 852 | 833 | ||
| 853 | void | 834 | void |
| 854 | cfs_hash_dual_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl) | 835 | cfs_hash_dual_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl) |
| 855 | { | 836 | { |
| 856 | cfs_hash_multi_bd_lock(hs, bds, 2, excl); | 837 | cfs_hash_multi_bd_lock(hs, bds, 2, excl); |
| 857 | } | 838 | } |
| 858 | EXPORT_SYMBOL(cfs_hash_dual_bd_lock); | ||
| 859 | 839 | ||
| 860 | void | 840 | void |
| 861 | cfs_hash_dual_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl) | 841 | cfs_hash_dual_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl) |
| 862 | { | 842 | { |
| 863 | cfs_hash_multi_bd_unlock(hs, bds, 2, excl); | 843 | cfs_hash_multi_bd_unlock(hs, bds, 2, excl); |
| 864 | } | 844 | } |
| 865 | EXPORT_SYMBOL(cfs_hash_dual_bd_unlock); | ||
| 866 | 845 | ||
| 867 | struct hlist_node * | 846 | struct hlist_node * |
| 868 | cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, | 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 | return cfs_hash_multi_bd_lookup_locked(hs, bds, 2, key); | 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 | struct hlist_node * | 853 | struct hlist_node * |
| 876 | cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, | 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 | return cfs_hash_multi_bd_findadd_locked(hs, bds, 2, key, | 858 | return cfs_hash_multi_bd_findadd_locked(hs, bds, 2, key, |
| 881 | hnode, noref); | 859 | hnode, noref); |
| 882 | } | 860 | } |
| 883 | EXPORT_SYMBOL(cfs_hash_dual_bd_findadd_locked); | ||
| 884 | 861 | ||
| 885 | struct hlist_node * | 862 | struct hlist_node * |
| 886 | cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds, | 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 | return cfs_hash_multi_bd_finddel_locked(hs, bds, 2, key, hnode); | 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 | static void | 869 | static void |
| 894 | cfs_hash_buckets_free(struct cfs_hash_bucket **buckets, | 870 | cfs_hash_buckets_free(struct cfs_hash_bucket **buckets, |
| 895 | int bkt_size, int prev_size, int size) | 871 | int bkt_size, int prev_size, int size) |
| 896 | { | 872 | { |
| 897 | int i; | 873 | int i; |
| 898 | 874 | ||
| 899 | for (i = prev_size; i < size; i++) { | 875 | for (i = prev_size; i < size; i++) { |
| 900 | if (buckets[i] != NULL) | 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 | unsigned int old_size, unsigned int new_size) | 890 | unsigned int old_size, unsigned int new_size) |
| 915 | { | 891 | { |
| 916 | struct cfs_hash_bucket **new_bkts; | 892 | struct cfs_hash_bucket **new_bkts; |
| 917 | int i; | 893 | int i; |
| 918 | 894 | ||
| 919 | LASSERT(old_size == 0 || old_bkts != NULL); | 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 | for (i = old_size; i < new_size; i++) { | 909 | for (i = old_size; i < new_size; i++) { |
| 934 | struct hlist_head *hhead; | 910 | struct hlist_head *hhead; |
| 935 | struct cfs_hash_bd bd; | 911 | struct cfs_hash_bd bd; |
| 936 | 912 | ||
| 937 | LIBCFS_ALLOC(new_bkts[i], cfs_hash_bkt_size(hs)); | 913 | LIBCFS_ALLOC(new_bkts[i], cfs_hash_bkt_size(hs)); |
| 938 | if (new_bkts[i] == NULL) { | 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 | * @max_bits - Maximum allowed hash table resize, in bits | 945 | * @max_bits - Maximum allowed hash table resize, in bits |
| 970 | * @ops - Registered hash table operations | 946 | * @ops - Registered hash table operations |
| 971 | * @flags - CFS_HASH_REHASH enable synamic hash resizing | 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 | static int cfs_hash_rehash_worker(cfs_workitem_t *wi); | 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 | static int cfs_hash_dep_print(cfs_workitem_t *wi) | 953 | static int cfs_hash_dep_print(cfs_workitem_t *wi) |
| 978 | { | 954 | { |
| 979 | struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_dep_wi); | 955 | struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_dep_wi); |
| 980 | int dep; | 956 | int dep; |
| 981 | int bkt; | 957 | int bkt; |
| 982 | int off; | 958 | int off; |
| 983 | int bits; | 959 | int bits; |
| 984 | 960 | ||
| 985 | spin_lock(&hs->hs_dep_lock); | 961 | spin_lock(&hs->hs_dep_lock); |
| 986 | dep = hs->hs_dep_max; | 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 | struct cfs_hash_ops *ops, unsigned flags) | 1007 | struct cfs_hash_ops *ops, unsigned flags) |
| 1032 | { | 1008 | { |
| 1033 | struct cfs_hash *hs; | 1009 | struct cfs_hash *hs; |
| 1034 | int len; | 1010 | int len; |
| 1035 | 1011 | ||
| 1036 | CLASSERT(CFS_HASH_THETA_BITS < 15); | 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 | if (hs == NULL) | 1038 | if (hs == NULL) |
| 1063 | return NULL; | 1039 | return NULL; |
| 1064 | 1040 | ||
| 1065 | strncpy(hs->hs_name, name, len); | 1041 | strlcpy(hs->hs_name, name, len); |
| 1066 | hs->hs_name[len - 1] = '\0'; | ||
| 1067 | hs->hs_flags = flags; | 1042 | hs->hs_flags = flags; |
| 1068 | 1043 | ||
| 1069 | atomic_set(&hs->hs_refcount, 1); | 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 | hs->hs_max_bits = (__u8)max_bits; | 1052 | hs->hs_max_bits = (__u8)max_bits; |
| 1078 | hs->hs_bkt_bits = (__u8)bkt_bits; | 1053 | hs->hs_bkt_bits = (__u8)bkt_bits; |
| 1079 | 1054 | ||
| 1080 | hs->hs_ops = ops; | 1055 | hs->hs_ops = ops; |
| 1081 | hs->hs_extra_bytes = extra_bytes; | 1056 | hs->hs_extra_bytes = extra_bytes; |
| 1082 | hs->hs_rehash_bits = 0; | 1057 | hs->hs_rehash_bits = 0; |
| 1083 | cfs_wi_init(&hs->hs_rehash_wi, hs, cfs_hash_rehash_worker); | 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 | static void | 1077 | static void |
| 1103 | cfs_hash_destroy(struct cfs_hash *hs) | 1078 | cfs_hash_destroy(struct cfs_hash *hs) |
| 1104 | { | 1079 | { |
| 1105 | struct hlist_node *hnode; | 1080 | struct hlist_node *hnode; |
| 1106 | struct hlist_node *pos; | 1081 | struct hlist_node *pos; |
| 1107 | struct cfs_hash_bd bd; | 1082 | struct cfs_hash_bd bd; |
| 1108 | int i; | 1083 | int i; |
| 1109 | 1084 | ||
| 1110 | LASSERT(hs != NULL); | 1085 | LASSERT(hs != NULL); |
| 1111 | LASSERT(!cfs_hash_is_exiting(hs) && | 1086 | LASSERT(!cfs_hash_is_exiting(hs) && |
| @@ -1223,8 +1198,8 @@ cfs_hash_rehash_inline(struct cfs_hash *hs) · 111 unmodified lines | |||
| 1223 | void | 1198 | void |
| 1224 | cfs_hash_add(struct cfs_hash *hs, const void *key, struct hlist_node *hnode) | 1199 | cfs_hash_add(struct cfs_hash *hs, const void *key, struct hlist_node *hnode) |
| 1225 | { | 1200 | { |
| 1226 | struct cfs_hash_bd bd; | 1201 | struct cfs_hash_bd bd; |
| 1227 | int bits; | 1202 | int bits; |
| 1228 | 1203 | ||
| 1229 | LASSERT(hlist_unhashed(hnode)); | 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 | struct hlist_node *hnode, int noref) | 1223 | struct hlist_node *hnode, int noref) |
| 1249 | { | 1224 | { |
| 1250 | struct hlist_node *ehnode; | 1225 | struct hlist_node *ehnode; |
| 1251 | struct cfs_hash_bd bds[2]; | 1226 | struct cfs_hash_bd bds[2]; |
| 1252 | int bits = 0; | 1227 | int bits = 0; |
| 1253 | 1228 | ||
| 1254 | LASSERT(hlist_unhashed(hnode)); | 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 | hnode, noref); | 1236 | hnode, noref); |
| 1262 | cfs_hash_dual_bd_unlock(hs, bds, 1); | 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 | bits = cfs_hash_rehash_bits(hs); | 1240 | bits = cfs_hash_rehash_bits(hs); |
| 1266 | cfs_hash_unlock(hs, 0); | 1241 | cfs_hash_unlock(hs, 0); |
| 1267 | if (bits > 0) | 1242 | if (bits > 0) |
| @@ -1276,7 +1251,8 @@ cfs_hash_find_or_add(struct cfs_hash *hs, const void *key, · 8 unmodified lines | |||
| 1276 | * Returns 0 on success or -EALREADY on key collisions. | 1251 | * Returns 0 on success or -EALREADY on key collisions. |
| 1277 | */ | 1252 | */ |
| 1278 | int | 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 | return cfs_hash_find_or_add(hs, key, hnode, 1) != hnode ? | 1257 | return cfs_hash_find_or_add(hs, key, hnode, 1) != hnode ? |
| 1282 | -EALREADY : 0; | 1258 | -EALREADY : 0; |
| @@ -1309,9 +1285,9 @@ EXPORT_SYMBOL(cfs_hash_findadd_unique); · 26 unmodified lines | |||
| 1309 | void * | 1285 | void * |
| 1310 | cfs_hash_del(struct cfs_hash *hs, const void *key, struct hlist_node *hnode) | 1286 | cfs_hash_del(struct cfs_hash *hs, const void *key, struct hlist_node *hnode) |
| 1311 | { | 1287 | { |
| 1312 | void *obj = NULL; | 1288 | void *obj = NULL; |
| 1313 | int bits = 0; | 1289 | int bits = 0; |
| 1314 | struct cfs_hash_bd bds[2]; | 1290 | struct cfs_hash_bd bds[2]; |
| 1315 | 1291 | ||
| 1316 | cfs_hash_lock(hs, 0); | 1292 | cfs_hash_lock(hs, 0); |
| 1317 | cfs_hash_dual_bd_get_and_lock(hs, key, bds, 1); | 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 | void * | 1340 | void * |
| 1365 | cfs_hash_lookup(struct cfs_hash *hs, const void *key) | 1341 | cfs_hash_lookup(struct cfs_hash *hs, const void *key) |
| 1366 | { | 1342 | { |
| 1367 | void *obj = NULL; | 1343 | void *obj = NULL; |
| 1368 | struct hlist_node *hnode; | 1344 | struct hlist_node *hnode; |
| 1369 | struct cfs_hash_bd bds[2]; | 1345 | struct cfs_hash_bd bds[2]; |
| 1370 | 1346 | ||
| 1371 | cfs_hash_lock(hs, 0); | 1347 | cfs_hash_lock(hs, 0); |
| 1372 | cfs_hash_dual_bd_get_and_lock(hs, key, bds, 0); | 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 | EXPORT_SYMBOL(cfs_hash_lookup); | 1359 | EXPORT_SYMBOL(cfs_hash_lookup); |
| 1384 | 1360 | ||
| 1385 | static void | 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 | LASSERT(!cfs_hash_is_exiting(hs)); | 1364 | LASSERT(!cfs_hash_is_exiting(hs)); |
| 1388 | 1365 | ||
| 1389 | if (!cfs_hash_with_rehash(hs)) | 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 | static void | 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 | int remained; | 1390 | int remained; |
| 1413 | int bits; | 1391 | int bits; |
| 1414 | 1392 | ||
| @@ -1439,14 +1417,15 @@ cfs_hash_for_each_exit(struct cfs_hash *hs) { · 24 unmodified lines | |||
| 1439 | */ | 1417 | */ |
| 1440 | static __u64 | 1418 | static __u64 |
| 1441 | cfs_hash_for_each_tight(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, | 1419 | cfs_hash_for_each_tight(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, |
| 1442 | void *data, int remove_safe) { | 1420 | void *data, int remove_safe) |
| 1443 | struct hlist_node *hnode; | 1421 | { |
| 1444 | struct hlist_node *pos; | 1422 | struct hlist_node *hnode; |
| 1445 | struct cfs_hash_bd bd; | 1423 | struct hlist_node *pos; |
| 1446 | __u64 count = 0; | 1424 | struct cfs_hash_bd bd; |
| 1447 | int excl = !!remove_safe; | 1425 | __u64 count = 0; |
| 1448 | int loop = 0; | 1426 | int excl = !!remove_safe; |
| 1449 | int i; | 1427 | int loop = 0; |
| 1428 | int i; | ||
| 1450 | 1429 | ||
| 1451 | cfs_hash_for_each_enter(hs); | 1430 | cfs_hash_for_each_enter(hs); |
| 1452 | 1431 | ||
| @@ -1514,8 +1493,8 @@ void · 61 unmodified lines | |||
| 1514 | cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t func, void *data) | 1493 | cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t func, void *data) |
| 1515 | { | 1494 | { |
| 1516 | struct cfs_hash_cond_arg arg = { | 1495 | struct cfs_hash_cond_arg arg = { |
| 1517 | .func = func, | 1496 | .func = func, |
| 1518 | .arg = data, | 1497 | .arg = data, |
| 1519 | }; | 1498 | }; |
| 1520 | 1499 | ||
| 1521 | cfs_hash_for_each_tight(hs, cfs_hash_cond_del_locked, &arg, 1); | 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 | EXPORT_SYMBOL(cfs_hash_cond_del); | 1502 | EXPORT_SYMBOL(cfs_hash_cond_del); |
| 1524 | 1503 | ||
| 1525 | void | 1504 | void |
| 1526 | cfs_hash_for_each(struct cfs_hash *hs, | 1505 | cfs_hash_for_each(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, |
| 1527 | cfs_hash_for_each_cb_t func, void *data) | 1506 | void *data) |
| 1528 | { | 1507 | { |
| 1529 | cfs_hash_for_each_tight(hs, func, data, 0); | 1508 | cfs_hash_for_each_tight(hs, func, data, 0); |
| 1530 | } | 1509 | } |
| 1531 | EXPORT_SYMBOL(cfs_hash_for_each); | 1510 | EXPORT_SYMBOL(cfs_hash_for_each); |
| 1532 | 1511 | ||
| 1533 | void | 1512 | void |
| 1534 | cfs_hash_for_each_safe(struct cfs_hash *hs, | 1513 | cfs_hash_for_each_safe(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, |
| 1535 | cfs_hash_for_each_cb_t func, void *data) { | 1514 | void *data) |
| 1515 | { | ||
| 1536 | cfs_hash_for_each_tight(hs, func, data, 1); | 1516 | cfs_hash_for_each_tight(hs, func, data, 1); |
| 1537 | } | 1517 | } |
| 1538 | EXPORT_SYMBOL(cfs_hash_for_each_safe); | 1518 | EXPORT_SYMBOL(cfs_hash_for_each_safe); |
| @@ -1581,15 +1561,16 @@ EXPORT_SYMBOL(cfs_hash_size_get); · 42 unmodified lines | |||
| 1581 | */ | 1561 | */ |
| 1582 | static int | 1562 | static int |
| 1583 | cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, | 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 | struct hlist_node *hnode; | 1566 | struct hlist_node *hnode; |
| 1586 | struct hlist_node *tmp; | 1567 | struct hlist_node *tmp; |
| 1587 | struct cfs_hash_bd bd; | 1568 | struct cfs_hash_bd bd; |
| 1588 | __u32 version; | 1569 | __u32 version; |
| 1589 | int count = 0; | 1570 | int count = 0; |
| 1590 | int stop_on_change; | 1571 | int stop_on_change; |
| 1591 | int rc; | 1572 | int rc; |
| 1592 | int i; | 1573 | int i; |
| 1593 | 1574 | ||
| 1594 | stop_on_change = cfs_hash_with_rehash_key(hs) || | 1575 | stop_on_change = cfs_hash_with_rehash_key(hs) || |
| 1595 | !cfs_hash_with_no_itemref(hs) || | 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 | int | 1628 | int |
| 1648 | cfs_hash_for_each_nolock(struct cfs_hash *hs, | 1629 | cfs_hash_for_each_nolock(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, |
| 1649 | cfs_hash_for_each_cb_t func, void *data) { | 1630 | void *data) |
| 1631 | { | ||
| 1650 | if (cfs_hash_with_no_lock(hs) || | 1632 | if (cfs_hash_with_no_lock(hs) || |
| 1651 | cfs_hash_with_rehash_key(hs) || | 1633 | cfs_hash_with_rehash_key(hs) || |
| 1652 | !cfs_hash_with_no_itemref(hs)) | 1634 | !cfs_hash_with_no_itemref(hs)) |
| @@ -1677,9 +1659,10 @@ EXPORT_SYMBOL(cfs_hash_for_each_nolock); · 24 unmodified lines | |||
| 1677 | * the required locking is in place to prevent concurrent insertions. | 1659 | * the required locking is in place to prevent concurrent insertions. |
| 1678 | */ | 1660 | */ |
| 1679 | int | 1661 | int |
| 1680 | cfs_hash_for_each_empty(struct cfs_hash *hs, | 1662 | cfs_hash_for_each_empty(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, |
| 1681 | cfs_hash_for_each_cb_t func, void *data) { | 1663 | void *data) |
| 1682 | unsigned i = 0; | 1664 | { |
| 1665 | unsigned i = 0; | ||
| 1683 | 1666 | ||
| 1684 | if (cfs_hash_with_no_lock(hs)) | 1667 | if (cfs_hash_with_no_lock(hs)) |
| 1685 | return -EOPNOTSUPP; | 1668 | return -EOPNOTSUPP; |
| @@ -1703,9 +1686,9 @@ void · 17 unmodified lines | |||
| 1703 | cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex, | 1686 | cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex, |
| 1704 | cfs_hash_for_each_cb_t func, void *data) | 1687 | cfs_hash_for_each_cb_t func, void *data) |
| 1705 | { | 1688 | { |
| 1706 | struct hlist_head *hhead; | 1689 | struct hlist_head *hhead; |
| 1707 | struct hlist_node *hnode; | 1690 | struct hlist_node *hnode; |
| 1708 | struct cfs_hash_bd bd; | 1691 | struct cfs_hash_bd bd; |
| 1709 | 1692 | ||
| 1710 | cfs_hash_for_each_enter(hs); | 1693 | cfs_hash_for_each_enter(hs); |
| 1711 | cfs_hash_lock(hs, 0); | 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 | break; | 1704 | break; |
| 1722 | } | 1705 | } |
| 1723 | cfs_hash_bd_unlock(hs, &bd, 0); | 1706 | cfs_hash_bd_unlock(hs, &bd, 0); |
| 1724 | out: | 1707 | out: |
| 1725 | cfs_hash_unlock(hs, 0); | 1708 | cfs_hash_unlock(hs, 0); |
| 1726 | cfs_hash_for_each_exit(hs); | 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 | void | 1720 | void |
| 1738 | cfs_hash_for_each_key(struct cfs_hash *hs, const void *key, | 1721 | cfs_hash_for_each_key(struct cfs_hash *hs, const void *key, |
| 1739 | cfs_hash_for_each_cb_t func, void *data) { | 1722 | cfs_hash_for_each_cb_t func, void *data) |
| 1740 | struct hlist_node *hnode; | 1723 | { |
| 1741 | struct cfs_hash_bd bds[2]; | 1724 | struct hlist_node *hnode; |
| 1742 | unsigned i; | 1725 | struct cfs_hash_bd bds[2]; |
| 1726 | unsigned int i; | ||
| 1743 | 1727 | ||
| 1744 | cfs_hash_lock(hs, 0); | 1728 | cfs_hash_lock(hs, 0); |
| 1745 | 1729 | ||
| @@ -1777,7 +1761,7 @@ EXPORT_SYMBOL(cfs_hash_for_each_key); · 31 unmodified lines | |||
| 1777 | void | 1761 | void |
| 1778 | cfs_hash_rehash_cancel_locked(struct cfs_hash *hs) | 1762 | cfs_hash_rehash_cancel_locked(struct cfs_hash *hs) |
| 1779 | { | 1763 | { |
| 1780 | int i; | 1764 | int i; |
| 1781 | 1765 | ||
| 1782 | /* need hold cfs_hash_lock(hs, 1) */ | 1766 | /* need hold cfs_hash_lock(hs, 1) */ |
| 1783 | LASSERT(cfs_hash_with_rehash(hs) && | 1767 | LASSERT(cfs_hash_with_rehash(hs) && |
| @@ -1794,14 +1778,13 @@ cfs_hash_rehash_cancel_locked(struct cfs_hash *hs) · 10 unmodified lines | |||
| 1794 | for (i = 2; cfs_hash_is_rehashing(hs); i++) { | 1778 | for (i = 2; cfs_hash_is_rehashing(hs); i++) { |
| 1795 | cfs_hash_unlock(hs, 1); | 1779 | cfs_hash_unlock(hs, 1); |
| 1796 | /* raise console warning while waiting too long */ | 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 | "hash %s is still rehashing, rescheded %d\n", | 1782 | "hash %s is still rehashing, rescheded %d\n", |
| 1799 | hs->hs_name, i - 1); | 1783 | hs->hs_name, i - 1); |
| 1800 | cond_resched(); | 1784 | cond_resched(); |
| 1801 | cfs_hash_lock(hs, 1); | 1785 | cfs_hash_lock(hs, 1); |
| 1802 | } | 1786 | } |
| 1803 | } | 1787 | } |
| 1804 | EXPORT_SYMBOL(cfs_hash_rehash_cancel_locked); | ||
| 1805 | 1788 | ||
| 1806 | void | 1789 | void |
| 1807 | cfs_hash_rehash_cancel(struct cfs_hash *hs) | 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 | cfs_hash_rehash_cancel_locked(hs); | 1793 | cfs_hash_rehash_cancel_locked(hs); |
| 1811 | cfs_hash_unlock(hs, 1); | 1794 | cfs_hash_unlock(hs, 1); |
| 1812 | } | 1795 | } |
| 1813 | EXPORT_SYMBOL(cfs_hash_rehash_cancel); | ||
| 1814 | 1796 | ||
| 1815 | int | 1797 | int |
| 1816 | cfs_hash_rehash(struct cfs_hash *hs, int do_rehash) | 1798 | cfs_hash_rehash(struct cfs_hash *hs, int do_rehash) |
| 1817 | { | 1799 | { |
| 1818 | int rc; | 1800 | int rc; |
| 1819 | 1801 | ||
| 1820 | LASSERT(cfs_hash_with_rehash(hs) && !cfs_hash_with_no_lock(hs)); | 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 | return cfs_hash_rehash_worker(&hs->hs_rehash_wi); | 1823 | return cfs_hash_rehash_worker(&hs->hs_rehash_wi); |
| 1842 | } | 1824 | } |
| 1843 | EXPORT_SYMBOL(cfs_hash_rehash); | ||
| 1844 | 1825 | ||
| 1845 | static int | 1826 | static int |
| 1846 | cfs_hash_rehash_bd(struct cfs_hash *hs, struct cfs_hash_bd *old) | 1827 | cfs_hash_rehash_bd(struct cfs_hash *hs, struct cfs_hash_bd *old) |
| 1847 | { | 1828 | { |
| 1848 | struct cfs_hash_bd new; | 1829 | struct cfs_hash_bd new; |
| 1849 | struct hlist_head *hhead; | 1830 | struct hlist_head *hhead; |
| 1850 | struct hlist_node *hnode; | 1831 | struct hlist_node *hnode; |
| 1851 | struct hlist_node *pos; | 1832 | struct hlist_node *pos; |
| 1852 | void *key; | 1833 | void *key; |
| 1853 | int c = 0; | 1834 | int c = 0; |
| 1854 | 1835 | ||
| 1855 | /* hold cfs_hash_lock(hs, 1), so don't need any bucket lock */ | 1836 | /* hold cfs_hash_lock(hs, 1), so don't need any bucket lock */ |
| 1856 | cfs_hash_bd_for_each_hlist(hs, old, hhead) { | 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 | static int | 1857 | static int |
| 1877 | cfs_hash_rehash_worker(cfs_workitem_t *wi) | 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 | struct cfs_hash_bucket **bkts; | 1861 | struct cfs_hash_bucket **bkts; |
| 1881 | struct cfs_hash_bd bd; | 1862 | struct cfs_hash_bd bd; |
| 1882 | unsigned int old_size; | 1863 | unsigned int old_size; |
| 1883 | unsigned int new_size; | 1864 | unsigned int new_size; |
| 1884 | int bsize; | 1865 | int bsize; |
| 1885 | int count = 0; | 1866 | int count = 0; |
| 1886 | int rc = 0; | 1867 | int rc = 0; |
| 1887 | int i; | 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 | cfs_hash_lock(hs, 0); | 1872 | cfs_hash_lock(hs, 0); |
| 1892 | LASSERT(cfs_hash_is_rehashing(hs)); | 1873 | LASSERT(cfs_hash_is_rehashing(hs)); |
| @@ -1958,7 +1939,7 @@ cfs_hash_rehash_worker(cfs_workitem_t *wi) · 65 unmodified lines | |||
| 1958 | hs->hs_rehash_buckets = NULL; | 1939 | hs->hs_rehash_buckets = NULL; |
| 1959 | 1940 | ||
| 1960 | hs->hs_cur_bits = hs->hs_rehash_bits; | 1941 | hs->hs_cur_bits = hs->hs_rehash_bits; |
| 1961 | out: | 1942 | out: |
| 1962 | hs->hs_rehash_bits = 0; | 1943 | hs->hs_rehash_bits = 0; |
| 1963 | if (rc == -ESRCH) /* never be scheduled again */ | 1944 | if (rc == -ESRCH) /* never be scheduled again */ |
| 1964 | cfs_wi_exit(cfs_sched_rehash, wi); | 1945 | cfs_wi_exit(cfs_sched_rehash, wi); |
| @@ -1986,9 +1967,9 @@ cfs_hash_rehash_worker(cfs_workitem_t *wi) · 21 unmodified lines | |||
| 1986 | void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key, | 1967 | void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key, |
| 1987 | void *new_key, struct hlist_node *hnode) | 1968 | void *new_key, struct hlist_node *hnode) |
| 1988 | { | 1969 | { |
| 1989 | struct cfs_hash_bd bds[3]; | 1970 | struct cfs_hash_bd bds[3]; |
| 1990 | struct cfs_hash_bd old_bds[2]; | 1971 | struct cfs_hash_bd old_bds[2]; |
| 1991 | struct cfs_hash_bd new_bd; | 1972 | struct cfs_hash_bd new_bd; |
| 1992 | 1973 | ||
| 1993 | LASSERT(!hlist_unhashed(hnode)); | 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 | /* overwrite key inside locks, otherwise may screw up with | 1996 | /* overwrite key inside locks, otherwise may screw up with |
| 2016 | * other operations, i.e: rehash */ | 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 | cfs_hash_multi_bd_unlock(hs, bds, 3, 1); | 2000 | cfs_hash_multi_bd_unlock(hs, bds, 3, 1); |
| 2020 | cfs_hash_unlock(hs, 0); | 2001 | cfs_hash_unlock(hs, 0); |
| @@ -2054,12 +2035,12 @@ cfs_hash_full_nbkt(struct cfs_hash *hs) · 33 unmodified lines | |||
| 2054 | 2035 | ||
| 2055 | void cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m) | 2036 | void cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m) |
| 2056 | { | 2037 | { |
| 2057 | int dist[8] = { 0, }; | 2038 | int dist[8] = { 0, }; |
| 2058 | int maxdep = -1; | 2039 | int maxdep = -1; |
| 2059 | int maxdepb = -1; | 2040 | int maxdepb = -1; |
| 2060 | int total = 0; | 2041 | int total = 0; |
| 2061 | int theta; | 2042 | int theta; |
| 2062 | int i; | 2043 | int i; |
| 2063 | 2044 | ||
| 2064 | cfs_hash_lock(hs, 0); | 2045 | cfs_hash_lock(hs, 0); |
| 2065 | theta = __cfs_hash_theta(hs); | 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 | * If you hash function results in a non-uniform hash the will | 2066 | * If you hash function results in a non-uniform hash the will |
| 2086 | * be observable by outlier bucks in the distribution histogram. | 2067 | * be observable by outlier bucks in the distribution histogram. |
| 2087 | * | 2068 | * |
| 2088 | * Uniform hash distribution: 128/128/0/0/0/0/0/0 | 2069 | * Uniform hash distribution: 128/128/0/0/0/0/0/0 |
| 2089 | * Non-Uniform hash distribution: 128/125/0/0/0/0/2/1 | 2070 | * Non-Uniform hash distribution: 128/125/0/0/0/0/2/1 |
| 2090 | */ | 2071 | */ |
| 2091 | for (i = 0; i < cfs_hash_full_nbkt(hs); i++) { | 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 | bd.bd_bucket = cfs_hash_full_bkts(hs)[i]; | 2075 | bd.bd_bucket = cfs_hash_full_bkts(hs)[i]; |
| 2095 | cfs_hash_bd_lock(hs, &bd, 0); | 2076 | cfs_hash_bd_lock(hs, &bd, 0); |
| @@ -110,7 +110,8 @@ static DECLARE_RWSEM(kg_sem); · 109 unmodified lines | |||
| 110 | * @param uid identifier for this receiver | 110 | * @param uid identifier for this receiver |
| 111 | * @param group group number | 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 | struct kkuc_reg *reg; | 116 | struct kkuc_reg *reg; |
| 116 | 117 | ||
| @@ -21,7 +21,7 @@ · 20 unmodified lines | |||
| 21 | * GPL HEADER END | 21 | * GPL HEADER END |
| 22 | */ | 22 | */ |
| 23 | /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | return arr->va_ptrs[cpt]; | 135 | return arr->va_ptrs[cpt]; |
| 136 | } | 136 | } |
| 137 | EXPORT_SYMBOL(cfs_percpt_current); | ||
| 138 | 137 | ||
| 139 | void * | 138 | void * |
| 140 | cfs_percpt_index(void *vars, int idx) | 139 | cfs_percpt_index(void *vars, int idx) |
| @@ -146,7 +145,6 @@ cfs_percpt_index(void *vars, int idx) · 5 unmodified lines | |||
| 146 | LASSERT(idx >= 0 && idx < arr->va_count); | 145 | LASSERT(idx >= 0 && idx < arr->va_count); |
| 147 | return arr->va_ptrs[idx]; | 146 | return arr->va_ptrs[idx]; |
| 148 | } | 147 | } |
| 149 | EXPORT_SYMBOL(cfs_percpt_index); | ||
| 150 | 148 | ||
| 151 | /* | 149 | /* |
| 152 | * free variable array, see more detail in cfs_array_alloc | 150 | * free variable array, see more detail in cfs_array_alloc |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -22,7 +22,8 @@ · 21 unmodified lines | |||
| 22 | */ | 22 | */ |
| 23 | /* | 23 | /* |
| 24 | * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | static struct cfs_cpt_data cpt_data; | 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 | void | 82 | void |
| 99 | cfs_cpt_table_free(struct cfs_cpt_table *cptab) | 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 | mutex_lock(&cpt_data.cpt_mutex); | 410 | mutex_lock(&cpt_data.cpt_mutex); |
| 427 | 411 | ||
| 428 | mask = cpt_data.cpt_cpumask; | 412 | mask = cpt_data.cpt_cpumask; |
| 429 | cfs_node_to_cpumask(node, mask); | 413 | cpumask_copy(mask, cpumask_of_node(node)); |
| 430 | 414 | ||
| 431 | rc = cfs_cpt_set_cpumask(cptab, cpt, mask); | 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 | mutex_lock(&cpt_data.cpt_mutex); | 434 | mutex_lock(&cpt_data.cpt_mutex); |
| 451 | 435 | ||
| 452 | mask = cpt_data.cpt_cpumask; | 436 | mask = cpt_data.cpt_cpumask; |
| 453 | cfs_node_to_cpumask(node, mask); | 437 | cpumask_copy(mask, cpumask_of_node(node)); |
| 454 | 438 | ||
| 455 | cfs_cpt_unset_cpumask(cptab, cpt, mask); | 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 | cpu = cpumask_first(node); | 627 | cpu = cpumask_first(node); |
| 644 | 628 | ||
| 645 | /* get cpumask for cores in the same socket */ | 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 | cpumask_and(socket, socket, node); | 631 | cpumask_and(socket, socket, node); |
| 648 | 632 | ||
| 649 | LASSERT(!cpumask_empty(socket)); | 633 | LASSERT(!cpumask_empty(socket)); |
| @@ -652,7 +636,7 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt, · 2 unmodified lines | |||
| 652 | int i; | 636 | int i; |
| 653 | 637 | ||
| 654 | /* get cpumask for hts in the same core */ | 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 | cpumask_and(core, core, node); | 640 | cpumask_and(core, core, node); |
| 657 | 641 | ||
| 658 | LASSERT(!cpumask_empty(core)); | 642 | LASSERT(!cpumask_empty(core)); |
| @@ -769,7 +753,7 @@ cfs_cpt_table_create(int ncpt) · 110 unmodified lines | |||
| 769 | } | 753 | } |
| 770 | 754 | ||
| 771 | for_each_online_node(i) { | 755 | for_each_online_node(i) { |
| 772 | cfs_node_to_cpumask(i, mask); | 756 | cpumask_copy(mask, cpumask_of_node(i)); |
| 773 | 757 | ||
| 774 | while (!cpumask_empty(mask)) { | 758 | while (!cpumask_empty(mask)) { |
| 775 | struct cfs_cpu_partition *part; | 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 | mutex_lock(&cpt_data.cpt_mutex); | 953 | mutex_lock(&cpt_data.cpt_mutex); |
| 970 | /* if all HTs in a core are offline, it may break affinity */ | 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 | warn = cpumask_any_and(cpt_data.cpt_cpumask, | 957 | warn = cpumask_any_and(cpt_data.cpt_cpumask, |
| 973 | cpu_online_mask) >= nr_cpu_ids; | 958 | cpu_online_mask) >= nr_cpu_ids; |
| 974 | mutex_unlock(&cpt_data.cpt_mutex); | 959 | mutex_unlock(&cpt_data.cpt_mutex); |
| @@ -37,11 +37,6 @@ · 36 unmodified lines | |||
| 37 | #define CHKSUM_BLOCK_SIZE 1 | 37 | #define CHKSUM_BLOCK_SIZE 1 |
| 38 | #define CHKSUM_DIGEST_SIZE 4 | 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 | static int adler32_cra_init(struct crypto_tfm *tfm) | 40 | static int adler32_cra_init(struct crypto_tfm *tfm) |
| 46 | { | 41 | { |
| 47 | u32 *key = crypto_tfm_ctx(tfm); | 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 | u32 *cksump = shash_desc_ctx(desc); | 75 | u32 *cksump = shash_desc_ctx(desc); |
| 81 | 76 | ||
| 82 | *cksump = __adler32(*cksump, data, len); | 77 | *cksump = zlib_adler32(*cksump, data, len); |
| 83 | return 0; | 78 | return 0; |
| 84 | } | 79 | } |
| 85 | 80 | ||
| 86 | static int __adler32_finup(u32 *cksump, const u8 *data, unsigned int len, | 81 | static int __adler32_finup(u32 *cksump, const u8 *data, unsigned int len, |
| 87 | u8 *out) | 82 | u8 *out) |
| 88 | { | 83 | { |
| 89 | *(u32 *)out = __adler32(*cksump, data, len); | 84 | *(u32 *)out = zlib_adler32(*cksump, data, len); |
| 90 | return 0; | 85 | return 0; |
| 91 | } | 86 | } |
| 92 | 87 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | atomic_notifier_chain_unregister(&panic_notifier_list, &libcfs_panic_notifier); | 195 | atomic_notifier_chain_unregister(&panic_notifier_list, &libcfs_panic_notifier); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | EXPORT_SYMBOL(libcfs_run_upcall); | ||
| 199 | EXPORT_SYMBOL(libcfs_run_lbug_upcall); | 198 | EXPORT_SYMBOL(libcfs_run_lbug_upcall); |
| 200 | EXPORT_SYMBOL(lbug_with_loc); | 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 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -62,7 +62,7 @@ · 28 unmodified lines | |||
| 62 | #include "../../include/linux/lnet/lnet.h" | 62 | #include "../../include/linux/lnet/lnet.h" |
| 63 | #include "tracefile.h" | 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 | MODULE_DESCRIPTION("Portals v3.1"); | 66 | MODULE_DESCRIPTION("Portals v3.1"); |
| 67 | MODULE_LICENSE("GPL"); | 67 | MODULE_LICENSE("GPL"); |
| 68 | 68 | ||
| @@ -375,7 +375,7 @@ static int __proc_dobitmasks(void *data, int write, · 306 unmodified lines | |||
| 375 | } else { | 375 | } else { |
| 376 | rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob); | 376 | rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob); |
| 377 | if (rc < 0) { | 377 | if (rc < 0) { |
| 378 | cfs_trace_free_string_buffer(tmpstr, tmpstrlen); | 378 | kfree(tmpstr); |
| 379 | return rc; | 379 | return rc; |
| 380 | } | 380 | } |
| 381 | 381 | ||
| @@ -385,7 +385,7 @@ static int __proc_dobitmasks(void *data, int write, · 3 unmodified lines | |||
| 385 | *mask |= D_EMERG; | 385 | *mask |= D_EMERG; |
| 386 | } | 386 | } |
| 387 | 387 | ||
| 388 | cfs_trace_free_string_buffer(tmpstr, tmpstrlen); | 388 | kfree(tmpstr); |
| 389 | return rc; | 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 | pgcount + 1, tcd->tcd_cur_pages); | 199 | pgcount + 1, tcd->tcd_cur_pages); |
| 200 | 200 | ||
| 201 | INIT_LIST_HEAD(&pc.pc_pages); | 201 | INIT_LIST_HEAD(&pc.pc_pages); |
| 202 | spin_lock_init(&pc.pc_lock); | ||
| 203 | 202 | ||
| 204 | list_for_each_entry_safe(tage, tmp, &tcd->tcd_pages, linkage) { | 203 | list_for_each_entry_safe(tage, tmp, &tcd->tcd_pages, linkage) { |
| 205 | if (pgcount-- == 0) | 204 | if (pgcount-- == 0) |
| @@ -451,7 +450,7 @@ console: · 245 unmodified lines | |||
| 451 | cfs_print_to_console(&header, mask, | 450 | cfs_print_to_console(&header, mask, |
| 452 | string_buf, needed, file, msgdata->msg_fn); | 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 | if (cdls != NULL && cdls->cdls_count != 0) { | 456 | if (cdls != NULL && cdls->cdls_count != 0) { |
| @@ -465,7 +464,7 @@ console: · 7 unmodified lines | |||
| 465 | cfs_print_to_console(&header, mask, | 464 | cfs_print_to_console(&header, mask, |
| 466 | string_buf, needed, file, msgdata->msg_fn); | 465 | string_buf, needed, file, msgdata->msg_fn); |
| 467 | 466 | ||
| 468 | cfs_trace_put_console_buffer(string_buf); | 467 | put_cpu(); |
| 469 | cdls->cdls_count = 0; | 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 | struct cfs_trace_cpu_data *tcd; | 521 | struct cfs_trace_cpu_data *tcd; |
| 523 | int i, cpu; | 522 | int i, cpu; |
| 524 | 523 | ||
| 525 | spin_lock(&pc->pc_lock); | ||
| 526 | for_each_possible_cpu(cpu) { | 524 | for_each_possible_cpu(cpu) { |
| 527 | cfs_tcd_for_each_type_lock(tcd, i, cpu) { | 525 | cfs_tcd_for_each_type_lock(tcd, i, cpu) { |
| 528 | list_splice_init(&tcd->tcd_pages, &pc->pc_pages); | 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 | static void collect_pages(struct page_collection *pc) | 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 | struct cfs_trace_page *tmp; | 552 | struct cfs_trace_page *tmp; |
| 556 | int i, cpu; | 553 | int i, cpu; |
| 557 | 554 | ||
| 558 | spin_lock(&pc->pc_lock); | ||
| 559 | for_each_possible_cpu(cpu) { | 555 | for_each_possible_cpu(cpu) { |
| 560 | cfs_tcd_for_each_type_lock(tcd, i, cpu) { | 556 | cfs_tcd_for_each_type_lock(tcd, i, cpu) { |
| 561 | cur_head = tcd->tcd_pages.next; | 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 | static void put_pages_back(struct page_collection *pc) | 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 | struct cfs_trace_page *tage; | 587 | struct cfs_trace_page *tage; |
| 593 | struct cfs_trace_page *tmp; | 588 | struct cfs_trace_page *tmp; |
| 594 | 589 | ||
| 595 | spin_lock(&pc->pc_lock); | ||
| 596 | list_for_each_entry_safe(tage, tmp, &pc->pc_pages, linkage) { | 590 | list_for_each_entry_safe(tage, tmp, &pc->pc_pages, linkage) { |
| 597 | 591 | ||
| 598 | __LASSERT_TAGE_INVARIANT(tage); | 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 | tcd->tcd_cur_daemon_pages--; | 610 | tcd->tcd_cur_daemon_pages--; |
| 617 | } | 611 | } |
| 618 | } | 612 | } |
| 619 | spin_unlock(&pc->pc_lock); | ||
| 620 | } | 613 | } |
| 621 | 614 | ||
| 622 | static void put_pages_on_daemon_list(struct page_collection *pc) | 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 | struct cfs_trace_page *tage; | 629 | struct cfs_trace_page *tage; |
| 637 | struct cfs_trace_page *tmp; | 630 | struct cfs_trace_page *tmp; |
| 638 | 631 | ||
| 639 | spin_lock_init(&pc.pc_lock); | ||
| 640 | |||
| 641 | pc.pc_want_daemon_pages = 1; | 632 | pc.pc_want_daemon_pages = 1; |
| 642 | collect_pages(&pc); | 633 | collect_pages(&pc); |
| 643 | list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { | 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 | goto out; | 683 | goto out; |
| 693 | } | 684 | } |
| 694 | 685 | ||
| 695 | spin_lock_init(&pc.pc_lock); | ||
| 696 | pc.pc_want_daemon_pages = 1; | 686 | pc.pc_want_daemon_pages = 1; |
| 697 | collect_pages(&pc); | 687 | collect_pages(&pc); |
| 698 | if (list_empty(&pc.pc_pages)) { | 688 | if (list_empty(&pc.pc_pages)) { |
| @@ -739,8 +729,6 @@ void cfs_trace_flush_pages(void) · 40 unmodified lines | |||
| 739 | struct cfs_trace_page *tage; | 729 | struct cfs_trace_page *tage; |
| 740 | struct cfs_trace_page *tmp; | 730 | struct cfs_trace_page *tmp; |
| 741 | 731 | ||
| 742 | spin_lock_init(&pc.pc_lock); | ||
| 743 | |||
| 744 | pc.pc_want_daemon_pages = 1; | 732 | pc.pc_want_daemon_pages = 1; |
| 745 | collect_pages(&pc); | 733 | collect_pages(&pc); |
| 746 | list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { | 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 | return 0; | 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 | int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob) | 808 | int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob) |
| 826 | { | 809 | { |
| 827 | char *str; | 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 | rc = cfs_tracefile_dump_all_pages(str); | 826 | rc = cfs_tracefile_dump_all_pages(str); |
| 844 | out: | 827 | out: |
| 845 | cfs_trace_free_string_buffer(str, usr_str_nob + 1); | 828 | kfree(str); |
| 846 | return rc; | 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 | if (rc == 0) | 881 | if (rc == 0) |
| 899 | rc = cfs_trace_daemon_command(str); | 882 | rc = cfs_trace_daemon_command(str); |
| 900 | 883 | ||
| 901 | cfs_trace_free_string_buffer(str, usr_str_nob + 1); | 884 | kfree(str); |
| 902 | return rc; | 885 | return rc; |
| 903 | } | 886 | } |
| 904 | 887 | ||
| @@ -970,7 +953,6 @@ static int tracefiled(void *arg) · 65 unmodified lines | |||
| 970 | /* we're started late enough that we pick up init's fs context */ | 953 | /* we're started late enough that we pick up init's fs context */ |
| 971 | /* this is so broken in uml? what on earth is going on? */ | 954 | /* this is so broken in uml? what on earth is going on? */ |
| 972 | 955 | ||
| 973 | spin_lock_init(&pc.pc_lock); | ||
| 974 | complete(&tctl->tctl_start); | 956 | complete(&tctl->tctl_start); |
| 975 | 957 | ||
| 976 | while (1) { | 958 | while (1) { |
| @@ -1170,7 +1152,6 @@ static void cfs_trace_cleanup(void) · 193 unmodified lines | |||
| 1170 | struct page_collection pc; | 1152 | struct page_collection pc; |
| 1171 | 1153 | ||
| 1172 | INIT_LIST_HEAD(&pc.pc_pages); | 1154 | INIT_LIST_HEAD(&pc.pc_pages); |
| 1173 | spin_lock_init(&pc.pc_lock); | ||
| 1174 | 1155 | ||
| 1175 | trace_cleanup_on_all_cpus(); | 1156 | trace_cleanup_on_all_cpus(); |
| 1176 | 1157 | ||
| @@ -39,7 +39,12 @@ · 38 unmodified lines | |||
| 39 | 39 | ||
| 40 | #include "../../include/linux/libcfs/libcfs.h" | 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 | /* trace file lock routines */ | 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 | int cfs_trace_copyout_string(char __user *usr_buffer, int usr_buffer_nob, | 75 | int cfs_trace_copyout_string(char __user *usr_buffer, int usr_buffer_nob, |
| 71 | const char *knl_str, char *append); | 76 | const char *knl_str, char *append); |
| 72 | int cfs_trace_allocate_string_buffer(char **str, int nob); | 77 | int cfs_trace_allocate_string_buffer(char **str, int nob); |
| 73 | void cfs_trace_free_string_buffer(char *str, int nob); | ||
| 74 | int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob); | 78 | int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob); |
| 75 | int cfs_trace_daemon_command(char *str); | 79 | int cfs_trace_daemon_command(char *str); |
| 76 | int cfs_trace_daemon_command_usrstr(void __user *usr_str, int usr_str_nob); | 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 | * be moved there */ | 199 | * be moved there */ |
| 196 | struct page_collection { | 200 | struct page_collection { |
| 197 | struct list_head pc_pages; | 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 | * if this flag is set, collect_pages() will spill both | 203 | * if this flag is set, collect_pages() will spill both |
| 208 | * ->tcd_daemon_pages and ->tcd_pages to the ->pc_pages. Otherwise, | 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 | int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking); | 256 | int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking); |
| 261 | void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking); | 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 | extern char *cfs_trace_console_buffers[NR_CPUS][CFS_TCD_TYPE_MAX]; | 259 | extern char *cfs_trace_console_buffers[NR_CPUS][CFS_TCD_TYPE_MAX]; |
| 271 | cfs_trace_buf_type_t cfs_trace_buf_idx_get(void); | 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 | return cfs_trace_console_buffers[i][j]; | 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 | static inline struct cfs_trace_cpu_data * | 271 | static inline struct cfs_trace_cpu_data * |
| 289 | cfs_trace_get_tcd(void) | 272 | cfs_trace_get_tcd(void) |
| 290 | { | 273 | { |
| @@ -86,32 +86,20 @@ static struct cfs_workitem_data { · 85 unmodified lines | |||
| 86 | int wi_stopping; | 86 | int wi_stopping; |
| 87 | } cfs_wi_data; | 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 | static inline int | 89 | static inline int |
| 102 | cfs_wi_sched_cansleep(struct cfs_wi_sched *sched) | 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 | if (sched->ws_stopping) { | 93 | if (sched->ws_stopping) { |
| 106 | cfs_wi_sched_unlock(sched); | 94 | spin_unlock(&sched->ws_lock); |
| 107 | return 0; | 95 | return 0; |
| 108 | } | 96 | } |
| 109 | 97 | ||
| 110 | if (!list_empty(&sched->ws_runq)) { | 98 | if (!list_empty(&sched->ws_runq)) { |
| 111 | cfs_wi_sched_unlock(sched); | 99 | spin_unlock(&sched->ws_lock); |
| 112 | return 0; | 100 | return 0; |
| 113 | } | 101 | } |
| 114 | cfs_wi_sched_unlock(sched); | 102 | spin_unlock(&sched->ws_lock); |
| 115 | return 1; | 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 | LASSERT(!in_interrupt()); /* because we use plain spinlock */ | 113 | LASSERT(!in_interrupt()); /* because we use plain spinlock */ |
| 126 | LASSERT(!sched->ws_stopping); | 114 | LASSERT(!sched->ws_stopping); |
| 127 | 115 | ||
| 128 | cfs_wi_sched_lock(sched); | 116 | spin_lock(&sched->ws_lock); |
| 129 | 117 | ||
| 130 | LASSERT(wi->wi_running); | 118 | LASSERT(wi->wi_running); |
| 131 | if (wi->wi_scheduled) { /* cancel pending schedules */ | 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 | LASSERT(list_empty(&wi->wi_list)); | 127 | LASSERT(list_empty(&wi->wi_list)); |
| 140 | 128 | ||
| 141 | wi->wi_scheduled = 1; /* LBUG future schedule attempts */ | 129 | wi->wi_scheduled = 1; /* LBUG future schedule attempts */ |
| 142 | cfs_wi_sched_unlock(sched); | 130 | spin_unlock(&sched->ws_lock); |
| 143 | 131 | ||
| 144 | return; | 132 | return; |
| 145 | } | 133 | } |
| @@ -161,7 +149,7 @@ cfs_wi_deschedule(struct cfs_wi_sched *sched, cfs_workitem_t *wi) · 15 unmodified lines | |||
| 161 | * means the workitem will not be scheduled and will not have | 149 | * means the workitem will not be scheduled and will not have |
| 162 | * any race with wi_action. | 150 | * any race with wi_action. |
| 163 | */ | 151 | */ |
| 164 | cfs_wi_sched_lock(sched); | 152 | spin_lock(&sched->ws_lock); |
| 165 | 153 | ||
| 166 | rc = !(wi->wi_running); | 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 | LASSERT (list_empty(&wi->wi_list)); | 166 | LASSERT (list_empty(&wi->wi_list)); |
| 179 | 167 | ||
| 180 | cfs_wi_sched_unlock(sched); | 168 | spin_unlock(&sched->ws_lock); |
| 181 | return rc; | 169 | return rc; |
| 182 | } | 170 | } |
| 183 | EXPORT_SYMBOL(cfs_wi_deschedule); | 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 | LASSERT(!in_interrupt()); /* because we use plain spinlock */ | 183 | LASSERT(!in_interrupt()); /* because we use plain spinlock */ |
| 196 | LASSERT(!sched->ws_stopping); | 184 | LASSERT(!sched->ws_stopping); |
| 197 | 185 | ||
| 198 | cfs_wi_sched_lock(sched); | 186 | spin_lock(&sched->ws_lock); |
| 199 | 187 | ||
| 200 | if (!wi->wi_scheduled) { | 188 | if (!wi->wi_scheduled) { |
| 201 | LASSERT (list_empty(&wi->wi_list)); | 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 | LASSERT (!list_empty(&wi->wi_list)); | 201 | LASSERT (!list_empty(&wi->wi_list)); |
| 214 | cfs_wi_sched_unlock(sched); | 202 | spin_unlock(&sched->ws_lock); |
| 215 | return; | 203 | return; |
| 216 | } | 204 | } |
| 217 | EXPORT_SYMBOL(cfs_wi_schedule); | 205 | EXPORT_SYMBOL(cfs_wi_schedule); |
| @@ -225,7 +213,9 @@ cfs_wi_scheduler (void *arg) · 7 unmodified lines | |||
| 225 | 213 | ||
| 226 | /* CPT affinity scheduler? */ | 214 | /* CPT affinity scheduler? */ |
| 227 | if (sched->ws_cptab != NULL) | 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 | spin_lock(&cfs_wi_data.wi_glock); | 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 | spin_unlock(&cfs_wi_data.wi_glock); | 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 | while (!sched->ws_stopping) { | 230 | while (!sched->ws_stopping) { |
| 241 | int nloops = 0; | 231 | int nloops = 0; |
| @@ -256,12 +246,12 @@ cfs_wi_scheduler (void *arg) · 14 unmodified lines | |||
| 256 | wi->wi_running = 1; | 246 | wi->wi_running = 1; |
| 257 | wi->wi_scheduled = 0; | 247 | wi->wi_scheduled = 0; |
| 258 | 248 | ||
| 259 | cfs_wi_sched_unlock(sched); | 249 | spin_unlock(&sched->ws_lock); |
| 260 | nloops++; | 250 | nloops++; |
| 261 | 251 | ||
| 262 | rc = (*wi->wi_action) (wi); | 252 | rc = (*wi->wi_action) (wi); |
| 263 | 253 | ||
| 264 | cfs_wi_sched_lock(sched); | 254 | spin_lock(&sched->ws_lock); |
| 265 | if (rc != 0) /* WI should be dead, even be freed! */ | 255 | if (rc != 0) /* WI should be dead, even be freed! */ |
| 266 | continue; | 256 | continue; |
| 267 | 257 | ||
| @@ -276,21 +266,21 @@ cfs_wi_scheduler (void *arg) · 8 unmodified lines | |||
| 276 | } | 266 | } |
| 277 | 267 | ||
| 278 | if (!list_empty(&sched->ws_runq)) { | 268 | if (!list_empty(&sched->ws_runq)) { |
| 279 | cfs_wi_sched_unlock(sched); | 269 | spin_unlock(&sched->ws_lock); |
| 280 | /* don't sleep because some workitems still | 270 | /* don't sleep because some workitems still |
| 281 | * expect me to come back soon */ | 271 | * expect me to come back soon */ |
| 282 | cond_resched(); | 272 | cond_resched(); |
| 283 | cfs_wi_sched_lock(sched); | 273 | spin_lock(&sched->ws_lock); |
| 284 | continue; | 274 | continue; |
| 285 | } | 275 | } |
| 286 | 276 | ||
| 287 | cfs_wi_sched_unlock(sched); | 277 | spin_unlock(&sched->ws_lock); |
| 288 | rc = wait_event_interruptible_exclusive(sched->ws_waitq, | 278 | rc = wait_event_interruptible_exclusive(sched->ws_waitq, |
| 289 | !cfs_wi_sched_cansleep(sched)); | 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 | spin_lock(&cfs_wi_data.wi_glock); | 285 | spin_lock(&cfs_wi_data.wi_glock); |
| 296 | sched->ws_nthreads--; | 286 | sched->ws_nthreads--; |
| @@ -325,7 +315,7 @@ cfs_wi_sched_destroy(struct cfs_wi_sched *sched) · 28 unmodified lines | |||
| 325 | 315 | ||
| 326 | spin_lock(&cfs_wi_data.wi_glock); | 316 | spin_lock(&cfs_wi_data.wi_glock); |
| 327 | while (sched->ws_nthreads > 0) { | 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 | "waiting for %d threads of WI sched[%s] to terminate\n", | 319 | "waiting for %d threads of WI sched[%s] to terminate\n", |
| 330 | sched->ws_nthreads, sched->ws_name); | 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 | if (sched == NULL) | 350 | if (sched == NULL) |
| 361 | return -ENOMEM; | 351 | return -ENOMEM; |
| 362 | 352 | ||
| 363 | strncpy(sched->ws_name, name, CFS_WS_NAME_LEN); | 353 | strlcpy(sched->ws_name, name, CFS_WS_NAME_LEN); |
| 364 | sched->ws_name[CFS_WS_NAME_LEN - 1] = '\0'; | 354 | |
| 365 | sched->ws_cptab = cptab; | 355 | sched->ws_cptab = cptab; |
| 366 | sched->ws_cpt = cpt; | 356 | sched->ws_cpt = cpt; |
| 367 | 357 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | return rc; | 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 | void ll_release_page(struct page *page, int remove) | 242 | void ll_release_page(struct page *page, int remove) |
| 249 | { | 243 | { |
| 250 | kunmap(page); | 244 | kunmap(page); |
| @@ -432,7 +426,8 @@ struct page *ll_get_dir_page(struct inode *dir, __u64 hash, · 181 unmodified lines | |||
| 432 | goto fail; | 426 | goto fail; |
| 433 | } | 427 | } |
| 434 | if (!PageChecked(page)) | 428 | if (!PageChecked(page)) |
| 435 | ll_check_page(dir, page); | 429 | /* XXX: check page format later */ |
| 430 | SetPageChecked(page); | ||
| 436 | if (PageError(page)) { | 431 | if (PageError(page)) { |
| 437 | CERROR("page error: "DFID" at %llu: rc %d\n", | 432 | CERROR("page error: "DFID" at %llu: rc %d\n", |
| 438 | PFID(ll_inode2fid(dir)), hash, -5); | 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 | if (!msp) | 636 | if (!msp) |
| 642 | return -ENOMEM; | 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 | rc = obd_set_info_async(NULL, mgc, sizeof(KEY_SET_INFO), KEY_SET_INFO, | 640 | rc = obd_set_info_async(NULL, mgc, sizeof(KEY_SET_INFO), KEY_SET_INFO, |
| 646 | sizeof(struct mgs_send_param), msp, NULL); | 641 | sizeof(struct mgs_send_param), msp, NULL); |
| 647 | if (rc) | 642 | if (rc) |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | return LUSTRE_FPRIVATE(attr->ia_file); | 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 | static inline void cl_isize_write_nolock(struct inode *inode, loff_t kms) | 1288 | static inline void cl_isize_write_nolock(struct inode *inode, loff_t kms) |
| 1299 | { | 1289 | { |
| 1300 | LASSERT(mutex_is_locked(&ll_i2info(inode)->lli_size_mutex)); | 1290 | LASSERT(mutex_is_locked(&ll_i2info(inode)->lli_size_mutex)); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | module_param(max_loop, int, 0444); | 878 | module_param(max_loop, int, 0444); |
| 879 | MODULE_PARM_DESC(max_loop, "maximum of lloop_device"); | 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 | MODULE_DESCRIPTION("Lustre virtual block device"); | 881 | MODULE_DESCRIPTION("Lustre virtual block device"); |
| 882 | MODULE_LICENSE("GPL"); | 882 | MODULE_LICENSE("GPL"); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | retval = NULL; | 554 | retval = NULL; |
| 555 | else | 555 | else |
| 556 | retval = dentry; | 556 | retval = dentry; |
| 557 | goto out; | ||
| 558 | out: | 557 | out: |
| 559 | if (req) | 558 | if (req) |
| 560 | ptlrpc_req_finished(req); | 559 | ptlrpc_req_finished(req); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | return; | 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 | /* Stride Read-ahead window will be increased inc_len according to | 883 | /* Stride Read-ahead window will be increased inc_len according to |
| 892 | * stride I/O pattern */ | 884 | * stride I/O pattern */ |
| 893 | static void ras_stride_increase_window(struct ll_readahead_state *ras, | 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 | window_len += step * ras->ras_stride_length + left; | 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 | ras->ras_window_len = window_len; | 919 | ras->ras_window_len = window_len; |
| 926 | 920 | ||
| 927 | RAS_CDEBUG(ras); | 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 | if (likely(do_io)) { | 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 | * Set page clip to tell transfer formation engine | 307 | * Set page clip to tell transfer formation engine |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -87,11 +87,6 @@ struct ll_sa_entry { · 53 unmodified lines | |||
| 87 | static unsigned int sai_generation; | 87 | static unsigned int sai_generation; |
| 88 | static DEFINE_SPINLOCK(sai_generation_lock); | 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 | * The entry only can be released by the caller, it is necessary to hold lock. | 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 | return (inode != NULL && S_ISREG(inode->i_mode) && sai->sai_agl_valid); | 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 | static inline int sa_sent_full(struct ll_statahead_info *sai) | 136 | static inline int sa_sent_full(struct ll_statahead_info *sai) |
| 156 | { | 137 | { |
| 157 | return atomic_read(&sai->sai_cache_count) >= sai->sai_max; | 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 | LASSERT(list_empty(&entry->se_link)); | 313 | LASSERT(list_empty(&entry->se_link)); |
| 333 | LASSERT(list_empty(&entry->se_list)); | 314 | LASSERT(list_empty(&entry->se_list)); |
| 334 | LASSERT(ll_sa_entry_unhashed(entry)); | 315 | LASSERT(list_empty(&entry->se_hash)); |
| 335 | 316 | ||
| 336 | ll_sa_entry_cleanup(sai, entry); | 317 | ll_sa_entry_cleanup(sai, entry); |
| 337 | iput(entry->se_inode); | 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 | struct ll_inode_info *lli = ll_i2info(sai->sai_inode); | 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 | LASSERT(!list_empty(&entry->se_link)); | 331 | LASSERT(!list_empty(&entry->se_link)); |
| 351 | 332 | ||
| 352 | ll_sa_entry_unhash(sai, entry); | 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 | igrab(inode); | 429 | igrab(inode); |
| 449 | spin_lock(&parent->lli_agl_lock); | 430 | spin_lock(&parent->lli_agl_lock); |
| 450 | if (agl_list_empty(sai)) | 431 | if (list_empty(&sai->sai_entries_agl)) |
| 451 | added = 1; | 432 | added = 1; |
| 452 | list_add_tail(&child->lli_agl_list, &sai->sai_entries_agl); | 433 | list_add_tail(&child->lli_agl_list, &sai->sai_entries_agl); |
| 453 | spin_unlock(&parent->lli_agl_lock); | 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 | do_sa_entry_fini(sai, entry); | 518 | do_sa_entry_fini(sai, entry); |
| 538 | 519 | ||
| 539 | LASSERT(list_empty(&sai->sai_entries)); | 520 | LASSERT(list_empty(&sai->sai_entries)); |
| 540 | LASSERT(sa_received_empty(sai)); | 521 | LASSERT(list_empty(&sai->sai_entries_received)); |
| 541 | LASSERT(list_empty(&sai->sai_entries_stated)); | 522 | LASSERT(list_empty(&sai->sai_entries_stated)); |
| 542 | 523 | ||
| 543 | LASSERT(atomic_read(&sai->sai_cache_count) == 0); | 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 | iput(inode); | 527 | iput(inode); |
| 547 | kfree(sai); | 528 | kfree(sai); |
| @@ -621,11 +602,12 @@ static void ll_post_statahead(struct ll_statahead_info *sai) · 73 unmodified lines | |||
| 621 | int rc = 0; | 602 | int rc = 0; |
| 622 | 603 | ||
| 623 | spin_lock(&lli->lli_sa_lock); | 604 | spin_lock(&lli->lli_sa_lock); |
| 624 | if (unlikely(sa_received_empty(sai))) { | 605 | if (unlikely(list_empty(&sai->sai_entries_received))) { |
| 625 | spin_unlock(&lli->lli_sa_lock); | 606 | spin_unlock(&lli->lli_sa_lock); |
| 626 | return; | 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 | atomic_inc(&entry->se_refcount); | 611 | atomic_inc(&entry->se_refcount); |
| 630 | list_del_init(&entry->se_list); | 612 | list_del_init(&entry->se_list); |
| 631 | spin_unlock(&lli->lli_sa_lock); | 613 | spin_unlock(&lli->lli_sa_lock); |
| @@ -756,7 +738,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, · 124 unmodified lines | |||
| 756 | * for readpage and other tries to enqueue lock on child | 738 | * for readpage and other tries to enqueue lock on child |
| 757 | * with parent's lock held, for example: unlink. */ | 739 | * with parent's lock held, for example: unlink. */ |
| 758 | entry->se_handle = handle; | 740 | entry->se_handle = handle; |
| 759 | wakeup = sa_received_empty(sai); | 741 | wakeup = list_empty(&sai->sai_entries_received); |
| 760 | list_add_tail(&entry->se_list, | 742 | list_add_tail(&entry->se_list, |
| 761 | &sai->sai_entries_received); | 743 | &sai->sai_entries_received); |
| 762 | } | 744 | } |
| @@ -973,7 +955,7 @@ static int ll_agl_thread(void *arg) · 210 unmodified lines | |||
| 973 | 955 | ||
| 974 | while (1) { | 956 | while (1) { |
| 975 | l_wait_event(thread->t_ctl_waitq, | 957 | l_wait_event(thread->t_ctl_waitq, |
| 976 | !agl_list_empty(sai) || | 958 | !list_empty(&sai->sai_entries_agl) || |
| 977 | !thread_is_running(thread), | 959 | !thread_is_running(thread), |
| 978 | &lwi); | 960 | &lwi); |
| 979 | 961 | ||
| @@ -983,8 +965,9 @@ static int ll_agl_thread(void *arg) · 3 unmodified lines | |||
| 983 | spin_lock(&plli->lli_agl_lock); | 965 | spin_lock(&plli->lli_agl_lock); |
| 984 | /* The statahead thread maybe help to process AGL entries, | 966 | /* The statahead thread maybe help to process AGL entries, |
| 985 | * so check whether list empty again. */ | 967 | * so check whether list empty again. */ |
| 986 | if (!agl_list_empty(sai)) { | 968 | if (!list_empty(&sai->sai_entries_agl)) { |
| 987 | clli = agl_first_entry(sai); | 969 | clli = list_entry(sai->sai_entries_agl.next, |
| 970 | struct ll_inode_info, lli_agl_list); | ||
| 988 | list_del_init(&clli->lli_agl_list); | 971 | list_del_init(&clli->lli_agl_list); |
| 989 | spin_unlock(&plli->lli_agl_lock); | 972 | spin_unlock(&plli->lli_agl_lock); |
| 990 | ll_agl_trigger(&clli->lli_vfs_inode, sai); | 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 | spin_lock(&plli->lli_agl_lock); | 979 | spin_lock(&plli->lli_agl_lock); |
| 997 | sai->sai_agl_valid = 0; | 980 | sai->sai_agl_valid = 0; |
| 998 | while (!agl_list_empty(sai)) { | 981 | while (!list_empty(&sai->sai_entries_agl)) { |
| 999 | clli = agl_first_entry(sai); | 982 | clli = list_entry(sai->sai_entries_agl.next, |
| 983 | struct ll_inode_info, lli_agl_list); | ||
| 1000 | list_del_init(&clli->lli_agl_list); | 984 | list_del_init(&clli->lli_agl_list); |
| 1001 | spin_unlock(&plli->lli_agl_lock); | 985 | spin_unlock(&plli->lli_agl_lock); |
| 1002 | clli->lli_agl_index = 0; | 986 | clli->lli_agl_index = 0; |
| @@ -1136,13 +1120,13 @@ static int ll_statahead_thread(void *arg) · 133 unmodified lines | |||
| 1136 | keep_it: | 1120 | keep_it: |
| 1137 | l_wait_event(thread->t_ctl_waitq, | 1121 | l_wait_event(thread->t_ctl_waitq, |
| 1138 | !sa_sent_full(sai) || | 1122 | !sa_sent_full(sai) || |
| 1139 | !sa_received_empty(sai) || | 1123 | !list_empty(&sai->sai_entries_received) || |
| 1140 | !agl_list_empty(sai) || | 1124 | !list_empty(&sai->sai_entries_agl) || |
| 1141 | !thread_is_running(thread), | 1125 | !thread_is_running(thread), |
| 1142 | &lwi); | 1126 | &lwi); |
| 1143 | 1127 | ||
| 1144 | interpret_it: | 1128 | interpret_it: |
| 1145 | while (!sa_received_empty(sai)) | 1129 | while (!list_empty(&sai->sai_entries_received)) |
| 1146 | ll_post_statahead(sai); | 1130 | ll_post_statahead(sai); |
| 1147 | 1131 | ||
| 1148 | if (unlikely(!thread_is_running(thread))) { | 1132 | if (unlikely(!thread_is_running(thread))) { |
| @@ -1156,14 +1140,15 @@ interpret_it: · 7 unmodified lines | |||
| 1156 | * to process the AGL entries. */ | 1140 | * to process the AGL entries. */ |
| 1157 | if (sa_sent_full(sai)) { | 1141 | if (sa_sent_full(sai)) { |
| 1158 | spin_lock(&plli->lli_agl_lock); | 1142 | spin_lock(&plli->lli_agl_lock); |
| 1159 | while (!agl_list_empty(sai)) { | 1143 | while (!list_empty(&sai->sai_entries_agl)) { |
| 1160 | clli = agl_first_entry(sai); | 1144 | clli = list_entry(sai->sai_entries_agl.next, |
| 1145 | struct ll_inode_info, lli_agl_list); | ||
| 1161 | list_del_init(&clli->lli_agl_list); | 1146 | list_del_init(&clli->lli_agl_list); |
| 1162 | spin_unlock(&plli->lli_agl_lock); | 1147 | spin_unlock(&plli->lli_agl_lock); |
| 1163 | ll_agl_trigger(&clli->lli_vfs_inode, | 1148 | ll_agl_trigger(&clli->lli_vfs_inode, |
| 1164 | sai); | 1149 | sai); |
| 1165 | 1150 | ||
| 1166 | if (!sa_received_empty(sai)) | 1151 | if (!list_empty(&sai->sai_entries_received)) |
| 1167 | goto interpret_it; | 1152 | goto interpret_it; |
| 1168 | 1153 | ||
| 1169 | if (unlikely( | 1154 | if (unlikely( |
| @@ -1194,12 +1179,12 @@ do_it: · 24 unmodified lines | |||
| 1194 | ll_release_page(page, 0); | 1179 | ll_release_page(page, 0); |
| 1195 | while (1) { | 1180 | while (1) { |
| 1196 | l_wait_event(thread->t_ctl_waitq, | 1181 | l_wait_event(thread->t_ctl_waitq, |
| 1197 | !sa_received_empty(sai) || | 1182 | !list_empty(&sai->sai_entries_received) || |
| 1198 | sai->sai_sent == sai->sai_replied || | 1183 | sai->sai_sent == sai->sai_replied || |
| 1199 | !thread_is_running(thread), | 1184 | !thread_is_running(thread), |
| 1200 | &lwi); | 1185 | &lwi); |
| 1201 | 1186 | ||
| 1202 | while (!sa_received_empty(sai)) | 1187 | while (!list_empty(&sai->sai_entries_received)) |
| 1203 | ll_post_statahead(sai); | 1188 | ll_post_statahead(sai); |
| 1204 | 1189 | ||
| 1205 | if (unlikely(!thread_is_running(thread))) { | 1190 | if (unlikely(!thread_is_running(thread))) { |
| @@ -1208,14 +1193,15 @@ do_it: · 2 unmodified lines | |||
| 1208 | } | 1193 | } |
| 1209 | 1194 | ||
| 1210 | if (sai->sai_sent == sai->sai_replied && | 1195 | if (sai->sai_sent == sai->sai_replied && |
| 1211 | sa_received_empty(sai)) | 1196 | list_empty(&sai->sai_entries_received)) |
| 1212 | break; | 1197 | break; |
| 1213 | } | 1198 | } |
| 1214 | 1199 | ||
| 1215 | spin_lock(&plli->lli_agl_lock); | 1200 | spin_lock(&plli->lli_agl_lock); |
| 1216 | while (!agl_list_empty(sai) && | 1201 | while (!list_empty(&sai->sai_entries_agl) && |
| 1217 | thread_is_running(thread)) { | 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 | list_del_init(&clli->lli_agl_list); | 1205 | list_del_init(&clli->lli_agl_list); |
| 1220 | spin_unlock(&plli->lli_agl_lock); | 1206 | spin_unlock(&plli->lli_agl_lock); |
| 1221 | ll_agl_trigger(&clli->lli_vfs_inode, sai); | 1207 | ll_agl_trigger(&clli->lli_vfs_inode, sai); |
| @@ -1260,12 +1246,12 @@ out: · 38 unmodified lines | |||
| 1260 | } | 1246 | } |
| 1261 | ll_dir_chain_fini(&chain); | 1247 | ll_dir_chain_fini(&chain); |
| 1262 | spin_lock(&plli->lli_sa_lock); | 1248 | spin_lock(&plli->lli_sa_lock); |
| 1263 | if (!sa_received_empty(sai)) { | 1249 | if (!list_empty(&sai->sai_entries_received)) { |
| 1264 | thread_set_flags(thread, SVC_STOPPING); | 1250 | thread_set_flags(thread, SVC_STOPPING); |
| 1265 | spin_unlock(&plli->lli_sa_lock); | 1251 | spin_unlock(&plli->lli_sa_lock); |
| 1266 | 1252 | ||
| 1267 | /* To release the resources held by received entries. */ | 1253 | /* To release the resources held by received entries. */ |
| 1268 | while (!sa_received_empty(sai)) | 1254 | while (!list_empty(&sai->sai_entries_received)) |
| 1269 | ll_post_statahead(sai); | 1255 | ll_post_statahead(sai); |
| 1270 | 1256 | ||
| 1271 | spin_lock(&plli->lli_sa_lock); | 1257 | spin_lock(&plli->lli_sa_lock); |
| @@ -205,7 +205,7 @@ static void __exit exit_lustre_lite(void) · 204 unmodified lines | |||
| 205 | kmem_cache_destroy(ll_file_data_slab); | 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 | MODULE_DESCRIPTION("Lustre Lite Client File System"); | 209 | MODULE_DESCRIPTION("Lustre Lite Client File System"); |
| 210 | MODULE_LICENSE("GPL"); | 210 | MODULE_LICENSE("GPL"); |
| 211 | 211 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | |||
| 26 | /* | 26 | /* |
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 28 | * Use is subject to license terms. |
| 29 | * | ||
| 30 | * Copyright (c) 2013, 2015, Intel Corporation. | ||
| 29 | */ | 31 | */ |
| 30 | /* | 32 | /* |
| 31 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | * Add page into the queue even when it is marked uptodate above. | 849 | * Add page into the queue even when it is marked uptodate above. |
| 850 | * this will unlock it automatically as part of cl_page_list_disown(). | 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 | if (sbi->ll_ra_info.ra_max_pages_per_file && | 853 | if (sbi->ll_ra_info.ra_max_pages_per_file && |
| 854 | sbi->ll_ra_info.ra_max_pages) | 854 | sbi->ll_ra_info.ra_max_pages) |
| 855 | ll_readahead(env, io, ras, | 855 | ll_readahead(env, io, ras, |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | |||
| 26 | /* | 26 | /* |
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 28 | * Use is subject to license terms. |
| 29 | * | ||
| 30 | * Copyright (c) 2014, 2015, Intel Corporation. | ||
| 29 | */ | 31 | */ |
| 30 | /* | 32 | /* |
| 31 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | ll_i2suppgid(inode), &req); | 193 | ll_i2suppgid(inode), &req); |
| 194 | #ifdef CONFIG_FS_POSIX_ACL | 194 | #ifdef CONFIG_FS_POSIX_ACL |
| 195 | if (new_value != NULL) | 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 | if (acl != NULL) | 200 | if (acl != NULL) |
| 198 | lustre_ext_acl_xattr_free(acl); | 201 | lustre_ext_acl_xattr_free(acl); |
| 199 | #endif | 202 | #endif |
| @@ -1,6 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright 2012 Xyratex Technology Limited | 2 | * Copyright 2012 Xyratex Technology Limited |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2013, 2015, Intel Corporation. | ||
| 5 | * | ||
| 4 | * Author: Andrew Perepechko <Andrew_Perepechko@xyratex.com> | 6 | * Author: Andrew Perepechko <Andrew_Perepechko@xyratex.com> |
| 5 | * | 7 | * |
| 6 | */ | 8 | */ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -156,11 +156,11 @@ out: · 122 unmodified lines | |||
| 156 | * IT_OPEN is intended to open (and create, possible) an object. Parent (pid) | 156 | * IT_OPEN is intended to open (and create, possible) an object. Parent (pid) |
| 157 | * may be split dir. | 157 | * may be split dir. |
| 158 | */ | 158 | */ |
| 159 | int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, | 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, | 160 | void *lmm, int lmmsize, struct lookup_intent *it, |
| 161 | int flags, struct ptlrpc_request **reqp, | 161 | int flags, struct ptlrpc_request **reqp, |
| 162 | ldlm_blocking_callback cb_blocking, | 162 | ldlm_blocking_callback cb_blocking, |
| 163 | __u64 extra_lock_flags) | 163 | __u64 extra_lock_flags) |
| 164 | { | 164 | { |
| 165 | struct obd_device *obd = exp->exp_obd; | 165 | struct obd_device *obd = exp->exp_obd; |
| 166 | struct lmv_obd *lmv = &obd->u.lmv; | 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 | * Handler for: getattr, lookup and revalidate cases. | 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, | 242 | static int lmv_intent_lookup(struct obd_export *exp, |
| 243 | void *lmm, int lmmsize, struct lookup_intent *it, | 243 | struct md_op_data *op_data, |
| 244 | int flags, struct ptlrpc_request **reqp, | 244 | void *lmm, int lmmsize, struct lookup_intent *it, |
| 245 | ldlm_blocking_callback cb_blocking, | 245 | int flags, struct ptlrpc_request **reqp, |
| 246 | __u64 extra_lock_flags) | 246 | ldlm_blocking_callback cb_blocking, |
| 247 | __u64 extra_lock_flags) | ||
| 247 | { | 248 | { |
| 248 | struct obd_device *obd = exp->exp_obd; | 249 | struct obd_device *obd = exp->exp_obd; |
| 249 | struct lmv_obd *lmv = &obd->u.lmv; | 250 | struct lmv_obd *lmv = &obd->u.lmv; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | ldlm_blocking_callback cb_blocking, | 56 | ldlm_blocking_callback cb_blocking, |
| 57 | __u64 extra_lock_flags); | 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 | int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds); | 59 | int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds); |
| 74 | int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds); | 60 | int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds); |
| 75 | int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, | 61 | int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | static struct obd_ops lmv_obd_ops = { | 2746 | static struct obd_ops lmv_obd_ops = { |
| 2747 | .o_owner = THIS_MODULE, | 2747 | .owner = THIS_MODULE, |
| 2748 | .o_setup = lmv_setup, | 2748 | .setup = lmv_setup, |
| 2749 | .o_cleanup = lmv_cleanup, | 2749 | .cleanup = lmv_cleanup, |
| 2750 | .o_precleanup = lmv_precleanup, | 2750 | .precleanup = lmv_precleanup, |
| 2751 | .o_process_config = lmv_process_config, | 2751 | .process_config = lmv_process_config, |
| 2752 | .o_connect = lmv_connect, | 2752 | .connect = lmv_connect, |
| 2753 | .o_disconnect = lmv_disconnect, | 2753 | .disconnect = lmv_disconnect, |
| 2754 | .o_statfs = lmv_statfs, | 2754 | .statfs = lmv_statfs, |
| 2755 | .o_get_info = lmv_get_info, | 2755 | .get_info = lmv_get_info, |
| 2756 | .o_set_info_async = lmv_set_info_async, | 2756 | .set_info_async = lmv_set_info_async, |
| 2757 | .o_packmd = lmv_packmd, | 2757 | .packmd = lmv_packmd, |
| 2758 | .o_unpackmd = lmv_unpackmd, | 2758 | .unpackmd = lmv_unpackmd, |
| 2759 | .o_notify = lmv_notify, | 2759 | .notify = lmv_notify, |
| 2760 | .o_get_uuid = lmv_get_uuid, | 2760 | .get_uuid = lmv_get_uuid, |
| 2761 | .o_iocontrol = lmv_iocontrol, | 2761 | .iocontrol = lmv_iocontrol, |
| 2762 | .o_quotacheck = lmv_quotacheck, | 2762 | .quotacheck = lmv_quotacheck, |
| 2763 | .o_quotactl = lmv_quotactl | 2763 | .quotactl = lmv_quotactl |
| 2764 | }; | 2764 | }; |
| 2765 | 2765 | ||
| 2766 | static struct md_ops lmv_md_ops = { | 2766 | static struct md_ops lmv_md_ops = { |
| 2767 | .m_getstatus = lmv_getstatus, | 2767 | .getstatus = lmv_getstatus, |
| 2768 | .m_null_inode = lmv_null_inode, | 2768 | .null_inode = lmv_null_inode, |
| 2769 | .m_find_cbdata = lmv_find_cbdata, | 2769 | .find_cbdata = lmv_find_cbdata, |
| 2770 | .m_close = lmv_close, | 2770 | .close = lmv_close, |
| 2771 | .m_create = lmv_create, | 2771 | .create = lmv_create, |
| 2772 | .m_done_writing = lmv_done_writing, | 2772 | .done_writing = lmv_done_writing, |
| 2773 | .m_enqueue = lmv_enqueue, | 2773 | .enqueue = lmv_enqueue, |
| 2774 | .m_getattr = lmv_getattr, | 2774 | .getattr = lmv_getattr, |
| 2775 | .m_getxattr = lmv_getxattr, | 2775 | .getxattr = lmv_getxattr, |
| 2776 | .m_getattr_name = lmv_getattr_name, | 2776 | .getattr_name = lmv_getattr_name, |
| 2777 | .m_intent_lock = lmv_intent_lock, | 2777 | .intent_lock = lmv_intent_lock, |
| 2778 | .m_link = lmv_link, | 2778 | .link = lmv_link, |
| 2779 | .m_rename = lmv_rename, | 2779 | .rename = lmv_rename, |
| 2780 | .m_setattr = lmv_setattr, | 2780 | .setattr = lmv_setattr, |
| 2781 | .m_setxattr = lmv_setxattr, | 2781 | .setxattr = lmv_setxattr, |
| 2782 | .m_sync = lmv_sync, | 2782 | .sync = lmv_sync, |
| 2783 | .m_readpage = lmv_readpage, | 2783 | .readpage = lmv_readpage, |
| 2784 | .m_unlink = lmv_unlink, | 2784 | .unlink = lmv_unlink, |
| 2785 | .m_init_ea_size = lmv_init_ea_size, | 2785 | .init_ea_size = lmv_init_ea_size, |
| 2786 | .m_cancel_unused = lmv_cancel_unused, | 2786 | .cancel_unused = lmv_cancel_unused, |
| 2787 | .m_set_lock_data = lmv_set_lock_data, | 2787 | .set_lock_data = lmv_set_lock_data, |
| 2788 | .m_lock_match = lmv_lock_match, | 2788 | .lock_match = lmv_lock_match, |
| 2789 | .m_get_lustre_md = lmv_get_lustre_md, | 2789 | .get_lustre_md = lmv_get_lustre_md, |
| 2790 | .m_free_lustre_md = lmv_free_lustre_md, | 2790 | .free_lustre_md = lmv_free_lustre_md, |
| 2791 | .m_set_open_replay_data = lmv_set_open_replay_data, | 2791 | .set_open_replay_data = lmv_set_open_replay_data, |
| 2792 | .m_clear_open_replay_data = lmv_clear_open_replay_data, | 2792 | .clear_open_replay_data = lmv_clear_open_replay_data, |
| 2793 | .m_get_remote_perm = lmv_get_remote_perm, | 2793 | .get_remote_perm = lmv_get_remote_perm, |
| 2794 | .m_intent_getattr_async = lmv_intent_getattr_async, | 2794 | .intent_getattr_async = lmv_intent_getattr_async, |
| 2795 | .m_revalidate_lock = lmv_revalidate_lock | 2795 | .revalidate_lock = lmv_revalidate_lock |
| 2796 | }; | 2796 | }; |
| 2797 | 2797 | ||
| 2798 | static int __init lmv_init(void) | 2798 | static int __init lmv_init(void) |
| @@ -2812,7 +2812,7 @@ static void lmv_exit(void) · 13 unmodified lines | |||
| 2812 | class_unregister_type(LUSTRE_LMV_NAME); | 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 | MODULE_DESCRIPTION("Lustre Logical Metadata Volume OBD driver"); | 2816 | MODULE_DESCRIPTION("Lustre Logical Metadata Volume OBD driver"); |
| 2817 | MODULE_LICENSE("GPL"); | 2817 | MODULE_LICENSE("GPL"); |
| 2818 | 2818 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | /* lov_qos.c */ | 151 | /* lov_qos.c */ |
| 152 | #define LOV_USES_ASSIGNED_STRIPE 0 | 152 | #define LOV_USES_ASSIGNED_STRIPE 0 |
| 153 | #define LOV_USES_DEFAULT_STRIPE 1 | 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 | /* lov_request.c */ | 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 | int lov_update_common_set(struct lov_request_set *set, | 156 | int lov_update_common_set(struct lov_request_set *set, |
| 169 | struct lov_request *req, int rc); | 157 | struct lov_request *req, int rc); |
| 170 | int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx); | ||
| 171 | int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, | 158 | int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, |
| 172 | struct lov_request_set **reqset); | 159 | struct lov_request_set **reqset); |
| 173 | int lov_fini_getattr_set(struct lov_request_set *set); | 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 | int lov_fini_setattr_set(struct lov_request_set *set); | 171 | int lov_fini_setattr_set(struct lov_request_set *set); |
| 185 | int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo, | 172 | int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo, |
| 186 | struct lov_request_set **reqset); | 173 | struct lov_request_set **reqset); |
| 187 | void lov_update_statfs(struct obd_statfs *osfs, struct obd_statfs *lov_sfs, | ||
| 188 | int success); | ||
| 189 | int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs, | 174 | int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs, |
| 190 | int success); | 175 | int success); |
| 191 | int lov_fini_statfs_set(struct lov_request_set *set); | 176 | int lov_fini_statfs_set(struct lov_request_set *set); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -2277,35 +2277,35 @@ out: · 2243 unmodified lines | |||
| 2277 | } | 2277 | } |
| 2278 | 2278 | ||
| 2279 | static struct obd_ops lov_obd_ops = { | 2279 | static struct obd_ops lov_obd_ops = { |
| 2280 | .o_owner = THIS_MODULE, | 2280 | .owner = THIS_MODULE, |
| 2281 | .o_setup = lov_setup, | 2281 | .setup = lov_setup, |
| 2282 | .o_precleanup = lov_precleanup, | 2282 | .precleanup = lov_precleanup, |
| 2283 | .o_cleanup = lov_cleanup, | 2283 | .cleanup = lov_cleanup, |
| 2284 | /*.o_process_config = lov_process_config,*/ | 2284 | /*.process_config = lov_process_config,*/ |
| 2285 | .o_connect = lov_connect, | 2285 | .connect = lov_connect, |
| 2286 | .o_disconnect = lov_disconnect, | 2286 | .disconnect = lov_disconnect, |
| 2287 | .o_statfs = lov_statfs, | 2287 | .statfs = lov_statfs, |
| 2288 | .o_statfs_async = lov_statfs_async, | 2288 | .statfs_async = lov_statfs_async, |
| 2289 | .o_packmd = lov_packmd, | 2289 | .packmd = lov_packmd, |
| 2290 | .o_unpackmd = lov_unpackmd, | 2290 | .unpackmd = lov_unpackmd, |
| 2291 | .o_create = lov_create, | 2291 | .create = lov_create, |
| 2292 | .o_destroy = lov_destroy, | 2292 | .destroy = lov_destroy, |
| 2293 | .o_getattr_async = lov_getattr_async, | 2293 | .getattr_async = lov_getattr_async, |
| 2294 | .o_setattr_async = lov_setattr_async, | 2294 | .setattr_async = lov_setattr_async, |
| 2295 | .o_adjust_kms = lov_adjust_kms, | 2295 | .adjust_kms = lov_adjust_kms, |
| 2296 | .o_find_cbdata = lov_find_cbdata, | 2296 | .find_cbdata = lov_find_cbdata, |
| 2297 | .o_iocontrol = lov_iocontrol, | 2297 | .iocontrol = lov_iocontrol, |
| 2298 | .o_get_info = lov_get_info, | 2298 | .get_info = lov_get_info, |
| 2299 | .o_set_info_async = lov_set_info_async, | 2299 | .set_info_async = lov_set_info_async, |
| 2300 | .o_notify = lov_notify, | 2300 | .notify = lov_notify, |
| 2301 | .o_pool_new = lov_pool_new, | 2301 | .pool_new = lov_pool_new, |
| 2302 | .o_pool_rem = lov_pool_remove, | 2302 | .pool_rem = lov_pool_remove, |
| 2303 | .o_pool_add = lov_pool_add, | 2303 | .pool_add = lov_pool_add, |
| 2304 | .o_pool_del = lov_pool_del, | 2304 | .pool_del = lov_pool_del, |
| 2305 | .o_getref = lov_getref, | 2305 | .getref = lov_getref, |
| 2306 | .o_putref = lov_putref, | 2306 | .putref = lov_putref, |
| 2307 | .o_quotactl = lov_quotactl, | 2307 | .quotactl = lov_quotactl, |
| 2308 | .o_quotacheck = lov_quotacheck, | 2308 | .quotacheck = lov_quotacheck, |
| 2309 | }; | 2309 | }; |
| 2310 | 2310 | ||
| 2311 | struct kmem_cache *lov_oinfo_slab; | 2311 | struct kmem_cache *lov_oinfo_slab; |
| @@ -2352,7 +2352,7 @@ static void /*__exit*/ lov_exit(void) · 40 unmodified lines | |||
| 2352 | lu_kmem_fini(lov_caches); | 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 | MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver"); | 2356 | MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver"); |
| 2357 | MODULE_LICENSE("GPL"); | 2357 | MODULE_LICENSE("GPL"); |
| 2358 | MODULE_VERSION(LUSTRE_VERSION_STRING); | 2358 | MODULE_VERSION(LUSTRE_VERSION_STRING); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | int rc; | 258 | int rc; |
| 259 | 259 | ||
| 260 | if (lsm_op_find(le32_to_cpu(*(__u32 *)lmm)) == NULL) { | 260 | if (lsm_op_find(le32_to_cpu(*(__u32 *)lmm)) == NULL) { |
| 261 | char *buffer; | ||
| 262 | int sz; | ||
| 263 | |||
| 264 | CERROR("bad disk LOV MAGIC: 0x%08X; dumping LMM (size=%d):\n", | 261 | CERROR("bad disk LOV MAGIC: 0x%08X; dumping LMM (size=%d):\n", |
| 265 | le32_to_cpu(*(__u32 *)lmm), lmm_bytes); | 262 | le32_to_cpu(*(__u32 *)lmm), lmm_bytes); |
| 266 | sz = lmm_bytes * 2 + 1; | 263 | CERROR("%*phN\n", lmm_bytes, lmm); |
| 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 | } | ||
| 277 | return -EINVAL; | 264 | return -EINVAL; |
| 278 | } | 265 | } |
| 279 | rc = lsm_op_find(le32_to_cpu(*(__u32 *)lmm))->lsm_lmm_verify(lmm, | 266 | rc = lsm_op_find(le32_to_cpu(*(__u32 *)lmm))->lsm_lmm_verify(lmm, |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | if (!new_pool) | 412 | if (!new_pool) |
| 413 | return -ENOMEM; | 413 | return -ENOMEM; |
| 414 | 414 | ||
| 415 | strncpy(new_pool->pool_name, poolname, LOV_MAXPOOLNAME); | 415 | strlcpy(new_pool->pool_name, poolname, sizeof(new_pool->pool_name)); |
| 416 | new_pool->pool_name[LOV_MAXPOOLNAME] = '\0'; | ||
| 417 | new_pool->pool_lobd = obd; | 416 | new_pool->pool_lobd = obd; |
| 418 | /* ref count init to 1 because when created a pool is always used | 417 | /* ref count init to 1 because when created a pool is always used |
| 419 | * up to deletion | 418 | * up to deletion |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | kfree(set); | 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 | int completes = atomic_read(&set->set_completes); | 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 | return 0; | 89 | return 0; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | void lov_update_set(struct lov_request_set *set, | 92 | static void lov_update_set(struct lov_request_set *set, |
| 93 | struct lov_request *req, int rc) | 93 | struct lov_request *req, int rc) |
| 94 | { | 94 | { |
| 95 | req->rq_complete = 1; | 95 | req->rq_complete = 1; |
| 96 | req->rq_rc = rc; | 96 | req->rq_rc = rc; |
| @@ -118,7 +118,8 @@ int lov_update_common_set(struct lov_request_set *set, · 21 unmodified lines | |||
| 118 | return rc; | 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 | list_add_tail(&req->rq_link, &set->set_list); | 124 | list_add_tail(&req->rq_link, &set->set_list); |
| 124 | set->set_count++; | 125 | set->set_count++; |
| @@ -144,7 +145,7 @@ static int lov_check_set(struct lov_obd *lov, int idx) · 19 unmodified lines | |||
| 144 | * If the OSC has not yet had a chance to connect to the OST the first time, | 145 | * If the OSC has not yet had a chance to connect to the OST the first time, |
| 145 | * wait once for it to connect instead of returning an error. | 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 | wait_queue_head_t waitq; | 150 | wait_queue_head_t waitq; |
| 150 | struct l_wait_info lwi; | 151 | struct l_wait_info lwi; |
| @@ -591,8 +592,9 @@ int lov_fini_statfs_set(struct lov_request_set *set) · 440 unmodified lines | |||
| 591 | return rc; | 592 | return rc; |
| 592 | } | 593 | } |
| 593 | 594 | ||
| 594 | void lov_update_statfs(struct obd_statfs *osfs, struct obd_statfs *lov_sfs, | 595 | static void lov_update_statfs(struct obd_statfs *osfs, |
| 595 | int success) | 596 | struct obd_statfs *lov_sfs, |
| 597 | int success) | ||
| 596 | { | 598 | { |
| 597 | int shift = 0, quit = 0; | 599 | int shift = 0, quit = 0; |
| 598 | __u64 tmp; | 600 | __u64 tmp; |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | |||
| 26 | /* | 26 | /* |
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 28 | * Use is subject to license terms. |
| 29 | * | ||
| 30 | * Copyright (c) 2013, 2015, Intel Corporation. | ||
| 29 | */ | 31 | */ |
| 30 | /* | 32 | /* |
| 31 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | LUSTRE_RW_ATTR(max_rpcs_in_flight); | 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 | LPROC_SEQ_FOPS_WR_ONLY(mdc, ping); | 85 | LPROC_SEQ_FOPS_WR_ONLY(mdc, ping); |
| 162 | 86 | ||
| 163 | LPROC_SEQ_FOPS_RO_TYPE(mdc, connect_flags); | 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 | { "timeouts", &mdc_timeouts_fops, NULL, 0 }, | 120 | { "timeouts", &mdc_timeouts_fops, NULL, 0 }, |
| 197 | { "import", &mdc_import_fops, NULL, 0 }, | 121 | { "import", &mdc_import_fops, NULL, 0 }, |
| 198 | { "state", &mdc_state_fops, NULL, 0 }, | 122 | { "state", &mdc_state_fops, NULL, 0 }, |
| 199 | { "hsm_nl", &mdc_kuc_fops, NULL, 0200 }, | ||
| 200 | { "pinger_recov", &mdc_pinger_recov_fops, NULL, 0 }, | 123 | { "pinger_recov", &mdc_pinger_recov_fops, NULL, 0 }, |
| 201 | { NULL } | 124 | { NULL } |
| 202 | }; | 125 | }; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, | 45 | void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, |
| 46 | __u64 valid, int ea_size, __u32 suppgid, int flags); | 46 | __u64 valid, int ea_size, __u32 suppgid, int flags); |
| 47 | int mdc_pack_req(struct ptlrpc_request *req, int version, int opc); | ||
| 48 | void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid, | 47 | void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid, |
| 49 | const struct lu_fid *cfid, int flags); | 48 | const struct lu_fid *cfid, int flags); |
| 50 | void mdc_swap_layouts_pack(struct ptlrpc_request *req, | 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 | __u32 mode, __u64 rdev, __u64 flags, const void *data, | 61 | __u32 mode, __u64 rdev, __u64 flags, const void *data, |
| 63 | int datalen); | 62 | int datalen); |
| 64 | void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data); | 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 | void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data); | 64 | void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data); |
| 67 | void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, | 65 | void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, |
| 68 | const char *old, int oldlen, const char *new, int newlen); | 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 | /* mdc/mdc_request.c */ | 95 | /* mdc/mdc_request.c */ |
| 98 | int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, | 96 | int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, |
| 99 | struct md_op_data *op_data); | 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 | struct obd_client_handle; | 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 | int mdc_set_open_replay_data(struct obd_export *exp, | 100 | int mdc_set_open_replay_data(struct obd_export *exp, |
| 114 | struct obd_client_handle *och, | 101 | struct obd_client_handle *och, |
| 115 | struct lookup_intent *it); | 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 | void mdc_commit_open(struct ptlrpc_request *req); | 104 | void mdc_commit_open(struct ptlrpc_request *req); |
| 120 | void mdc_replay_open(struct ptlrpc_request *req); | 105 | void mdc_replay_open(struct ptlrpc_request *req); |
| 121 | 106 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | #define mdc_unpack_acl(req, md) 0 | 447 | #define mdc_unpack_acl(req, md) 0 |
| 448 | #endif | 448 | #endif |
| 449 | 449 | ||
| 450 | int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req, | 450 | static int mdc_get_lustre_md(struct obd_export *exp, |
| 451 | struct obd_export *dt_exp, struct obd_export *md_exp, | 451 | struct ptlrpc_request *req, |
| 452 | struct lustre_md *md) | 452 | struct obd_export *dt_exp, |
| 453 | struct obd_export *md_exp, | ||
| 454 | struct lustre_md *md) | ||
| 453 | { | 455 | { |
| 454 | struct req_capsule *pill = &req->rq_pill; | 456 | struct req_capsule *pill = &req->rq_pill; |
| 455 | int rc; | 457 | int rc; |
| @@ -573,7 +575,7 @@ out: · 117 unmodified lines | |||
| 573 | return rc; | 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 | return 0; | 580 | return 0; |
| 579 | } | 581 | } |
| @@ -737,8 +739,8 @@ static void mdc_free_open(struct md_open_data *mod) · 157 unmodified lines | |||
| 737 | ptlrpc_request_committed(mod->mod_close_req, committed); | 739 | ptlrpc_request_committed(mod->mod_close_req, committed); |
| 738 | } | 740 | } |
| 739 | 741 | ||
| 740 | int mdc_clear_open_replay_data(struct obd_export *exp, | 742 | static int mdc_clear_open_replay_data(struct obd_export *exp, |
| 741 | struct obd_client_handle *och) | 743 | struct obd_client_handle *och) |
| 742 | { | 744 | { |
| 743 | struct md_open_data *mod = och->och_mod; | 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 | ptlrpc_request_set_replen(req); | 1181 | ptlrpc_request_set_replen(req); |
| 1180 | 1182 | ||
| 1181 | rc = mdc_queue_wait(req); | 1183 | rc = mdc_queue_wait(req); |
| 1182 | goto out; | ||
| 1183 | out: | 1184 | out: |
| 1184 | ptlrpc_req_finished(req); | 1185 | ptlrpc_req_finished(req); |
| 1185 | return rc; | 1186 | return rc; |
| @@ -1214,7 +1215,6 @@ static int mdc_ioc_hsm_ct_register(struct obd_import *imp, __u32 archives) · 28 unmodified lines | |||
| 1214 | ptlrpc_request_set_replen(req); | 1215 | ptlrpc_request_set_replen(req); |
| 1215 | 1216 | ||
| 1216 | rc = mdc_queue_wait(req); | 1217 | rc = mdc_queue_wait(req); |
| 1217 | goto out; | ||
| 1218 | out: | 1218 | out: |
| 1219 | ptlrpc_req_finished(req); | 1219 | ptlrpc_req_finished(req); |
| 1220 | return rc; | 1220 | return rc; |
| @@ -1280,7 +1280,6 @@ static int mdc_ioc_hsm_ct_unregister(struct obd_import *imp) · 59 unmodified lines | |||
| 1280 | ptlrpc_request_set_replen(req); | 1280 | ptlrpc_request_set_replen(req); |
| 1281 | 1281 | ||
| 1282 | rc = mdc_queue_wait(req); | 1282 | rc = mdc_queue_wait(req); |
| 1283 | goto out; | ||
| 1284 | out: | 1283 | out: |
| 1285 | ptlrpc_req_finished(req); | 1284 | ptlrpc_req_finished(req); |
| 1286 | return rc; | 1285 | return rc; |
| @@ -1360,8 +1359,6 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp, · 73 unmodified lines | |||
| 1360 | ptlrpc_request_set_replen(req); | 1359 | ptlrpc_request_set_replen(req); |
| 1361 | 1360 | ||
| 1362 | rc = mdc_queue_wait(req); | 1361 | rc = mdc_queue_wait(req); |
| 1363 | goto out; | ||
| 1364 | |||
| 1365 | out: | 1362 | out: |
| 1366 | ptlrpc_req_finished(req); | 1363 | ptlrpc_req_finished(req); |
| 1367 | return rc; | 1364 | return rc; |
| @@ -1425,8 +1422,6 @@ static int mdc_ioc_hsm_request(struct obd_export *exp, · 57 unmodified lines | |||
| 1425 | ptlrpc_request_set_replen(req); | 1422 | ptlrpc_request_set_replen(req); |
| 1426 | 1423 | ||
| 1427 | rc = mdc_queue_wait(req); | 1424 | rc = mdc_queue_wait(req); |
| 1428 | goto out; | ||
| 1429 | |||
| 1430 | out: | 1425 | out: |
| 1431 | ptlrpc_req_finished(req); | 1426 | ptlrpc_req_finished(req); |
| 1432 | return rc; | 1427 | return rc; |
| @@ -2035,17 +2030,6 @@ static int mdc_hsm_ct_reregister(__u32 data, void *cb_arg) · 602 unmodified lines | |||
| 2035 | return ((rc != 0) && (rc != -EEXIST)) ? rc : 0; | 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 | static int mdc_set_info_async(const struct lu_env *env, | 2033 | static int mdc_set_info_async(const struct lu_env *env, |
| 2050 | struct obd_export *exp, | 2034 | struct obd_export *exp, |
| 2051 | u32 keylen, void *key, | 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 | rc = obd_notify_observer(obd, obd, OBD_NOTIFY_ACTIVE, NULL); | 2192 | rc = obd_notify_observer(obd, obd, OBD_NOTIFY_ACTIVE, NULL); |
| 2209 | /* redo the kuc registration after reconnecting */ | 2193 | /* redo the kuc registration after reconnecting */ |
| 2210 | if (rc == 0) | 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 | break; | 2199 | break; |
| 2213 | case IMP_EVENT_OCD: | 2200 | case IMP_EVENT_OCD: |
| 2214 | rc = obd_notify_observer(obd, obd, OBD_NOTIFY_OCD, NULL); | 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 | static struct obd_ops mdc_obd_ops = { | 2449 | static struct obd_ops mdc_obd_ops = { |
| 2463 | .o_owner = THIS_MODULE, | 2450 | .owner = THIS_MODULE, |
| 2464 | .o_setup = mdc_setup, | 2451 | .setup = mdc_setup, |
| 2465 | .o_precleanup = mdc_precleanup, | 2452 | .precleanup = mdc_precleanup, |
| 2466 | .o_cleanup = mdc_cleanup, | 2453 | .cleanup = mdc_cleanup, |
| 2467 | .o_add_conn = client_import_add_conn, | 2454 | .add_conn = client_import_add_conn, |
| 2468 | .o_del_conn = client_import_del_conn, | 2455 | .del_conn = client_import_del_conn, |
| 2469 | .o_connect = client_connect_import, | 2456 | .connect = client_connect_import, |
| 2470 | .o_disconnect = client_disconnect_export, | 2457 | .disconnect = client_disconnect_export, |
| 2471 | .o_iocontrol = mdc_iocontrol, | 2458 | .iocontrol = mdc_iocontrol, |
| 2472 | .o_set_info_async = mdc_set_info_async, | 2459 | .set_info_async = mdc_set_info_async, |
| 2473 | .o_statfs = mdc_statfs, | 2460 | .statfs = mdc_statfs, |
| 2474 | .o_fid_init = client_fid_init, | 2461 | .fid_init = client_fid_init, |
| 2475 | .o_fid_fini = client_fid_fini, | 2462 | .fid_fini = client_fid_fini, |
| 2476 | .o_fid_alloc = mdc_fid_alloc, | 2463 | .fid_alloc = mdc_fid_alloc, |
| 2477 | .o_import_event = mdc_import_event, | 2464 | .import_event = mdc_import_event, |
| 2478 | .o_get_info = mdc_get_info, | 2465 | .get_info = mdc_get_info, |
| 2479 | .o_process_config = mdc_process_config, | 2466 | .process_config = mdc_process_config, |
| 2480 | .o_get_uuid = mdc_get_uuid, | 2467 | .get_uuid = mdc_get_uuid, |
| 2481 | .o_quotactl = mdc_quotactl, | 2468 | .quotactl = mdc_quotactl, |
| 2482 | .o_quotacheck = mdc_quotacheck | 2469 | .quotacheck = mdc_quotacheck |
| 2483 | }; | 2470 | }; |
| 2484 | 2471 | ||
| 2485 | static struct md_ops mdc_md_ops = { | 2472 | static struct md_ops mdc_md_ops = { |
| 2486 | .m_getstatus = mdc_getstatus, | 2473 | .getstatus = mdc_getstatus, |
| 2487 | .m_null_inode = mdc_null_inode, | 2474 | .null_inode = mdc_null_inode, |
| 2488 | .m_find_cbdata = mdc_find_cbdata, | 2475 | .find_cbdata = mdc_find_cbdata, |
| 2489 | .m_close = mdc_close, | 2476 | .close = mdc_close, |
| 2490 | .m_create = mdc_create, | 2477 | .create = mdc_create, |
| 2491 | .m_done_writing = mdc_done_writing, | 2478 | .done_writing = mdc_done_writing, |
| 2492 | .m_enqueue = mdc_enqueue, | 2479 | .enqueue = mdc_enqueue, |
| 2493 | .m_getattr = mdc_getattr, | 2480 | .getattr = mdc_getattr, |
| 2494 | .m_getattr_name = mdc_getattr_name, | 2481 | .getattr_name = mdc_getattr_name, |
| 2495 | .m_intent_lock = mdc_intent_lock, | 2482 | .intent_lock = mdc_intent_lock, |
| 2496 | .m_link = mdc_link, | 2483 | .link = mdc_link, |
| 2497 | .m_is_subdir = mdc_is_subdir, | 2484 | .is_subdir = mdc_is_subdir, |
| 2498 | .m_rename = mdc_rename, | 2485 | .rename = mdc_rename, |
| 2499 | .m_setattr = mdc_setattr, | 2486 | .setattr = mdc_setattr, |
| 2500 | .m_setxattr = mdc_setxattr, | 2487 | .setxattr = mdc_setxattr, |
| 2501 | .m_getxattr = mdc_getxattr, | 2488 | .getxattr = mdc_getxattr, |
| 2502 | .m_sync = mdc_sync, | 2489 | .sync = mdc_sync, |
| 2503 | .m_readpage = mdc_readpage, | 2490 | .readpage = mdc_readpage, |
| 2504 | .m_unlink = mdc_unlink, | 2491 | .unlink = mdc_unlink, |
| 2505 | .m_cancel_unused = mdc_cancel_unused, | 2492 | .cancel_unused = mdc_cancel_unused, |
| 2506 | .m_init_ea_size = mdc_init_ea_size, | 2493 | .init_ea_size = mdc_init_ea_size, |
| 2507 | .m_set_lock_data = mdc_set_lock_data, | 2494 | .set_lock_data = mdc_set_lock_data, |
| 2508 | .m_lock_match = mdc_lock_match, | 2495 | .lock_match = mdc_lock_match, |
| 2509 | .m_get_lustre_md = mdc_get_lustre_md, | 2496 | .get_lustre_md = mdc_get_lustre_md, |
| 2510 | .m_free_lustre_md = mdc_free_lustre_md, | 2497 | .free_lustre_md = mdc_free_lustre_md, |
| 2511 | .m_set_open_replay_data = mdc_set_open_replay_data, | 2498 | .set_open_replay_data = mdc_set_open_replay_data, |
| 2512 | .m_clear_open_replay_data = mdc_clear_open_replay_data, | 2499 | .clear_open_replay_data = mdc_clear_open_replay_data, |
| 2513 | .m_get_remote_perm = mdc_get_remote_perm, | 2500 | .get_remote_perm = mdc_get_remote_perm, |
| 2514 | .m_intent_getattr_async = mdc_intent_getattr_async, | 2501 | .intent_getattr_async = mdc_intent_getattr_async, |
| 2515 | .m_revalidate_lock = mdc_revalidate_lock | 2502 | .revalidate_lock = mdc_revalidate_lock |
| 2516 | }; | 2503 | }; |
| 2517 | 2504 | ||
| 2518 | static int __init mdc_init(void) | 2505 | static int __init mdc_init(void) |
| @@ -2530,7 +2517,7 @@ static void /*__exit*/ mdc_exit(void) · 11 unmodified lines | |||
| 2530 | class_unregister_type(LUSTRE_MDC_NAME); | 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 | MODULE_DESCRIPTION("Lustre Metadata Client"); | 2521 | MODULE_DESCRIPTION("Lustre Metadata Client"); |
| 2535 | MODULE_LICENSE("GPL"); | 2522 | MODULE_LICENSE("GPL"); |
| 2536 | 2523 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | spin_unlock(&config_list_lock); | 464 | spin_unlock(&config_list_lock); |
| 465 | 465 | ||
| 466 | LPROCFS_CLIMP_EXIT(obd); | 466 | up_read(&obd->u.cli.cl_sem); |
| 467 | return 0; | 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 | struct page **pages; | 1293 | struct page **pages; |
| 1294 | int nrpages; | 1294 | int nrpages; |
| 1295 | bool eof = true; | 1295 | bool eof = true; |
| 1296 | bool mne_swab = false; | 1296 | bool mne_swab; |
| 1297 | int i; | 1297 | int i; |
| 1298 | int ealen; | 1298 | int ealen; |
| 1299 | int rc; | 1299 | int rc; |
| @@ -1698,20 +1698,20 @@ out: · 398 unmodified lines | |||
| 1698 | } | 1698 | } |
| 1699 | 1699 | ||
| 1700 | static struct obd_ops mgc_obd_ops = { | 1700 | static struct obd_ops mgc_obd_ops = { |
| 1701 | .o_owner = THIS_MODULE, | 1701 | .owner = THIS_MODULE, |
| 1702 | .o_setup = mgc_setup, | 1702 | .setup = mgc_setup, |
| 1703 | .o_precleanup = mgc_precleanup, | 1703 | .precleanup = mgc_precleanup, |
| 1704 | .o_cleanup = mgc_cleanup, | 1704 | .cleanup = mgc_cleanup, |
| 1705 | .o_add_conn = client_import_add_conn, | 1705 | .add_conn = client_import_add_conn, |
| 1706 | .o_del_conn = client_import_del_conn, | 1706 | .del_conn = client_import_del_conn, |
| 1707 | .o_connect = client_connect_import, | 1707 | .connect = client_connect_import, |
| 1708 | .o_disconnect = client_disconnect_export, | 1708 | .disconnect = client_disconnect_export, |
| 1709 | /* .o_enqueue = mgc_enqueue, */ | 1709 | /* .enqueue = mgc_enqueue, */ |
| 1710 | /* .o_iocontrol = mgc_iocontrol, */ | 1710 | /* .iocontrol = mgc_iocontrol, */ |
| 1711 | .o_set_info_async = mgc_set_info_async, | 1711 | .set_info_async = mgc_set_info_async, |
| 1712 | .o_get_info = mgc_get_info, | 1712 | .get_info = mgc_get_info, |
| 1713 | .o_import_event = mgc_import_event, | 1713 | .import_event = mgc_import_event, |
| 1714 | .o_process_config = mgc_process_config, | 1714 | .process_config = mgc_process_config, |
| 1715 | }; | 1715 | }; |
| 1716 | 1716 | ||
| 1717 | static int __init mgc_init(void) | 1717 | static int __init mgc_init(void) |
| @@ -1725,7 +1725,7 @@ static void /*__exit*/ mgc_exit(void) · 7 unmodified lines | |||
| 1725 | class_unregister_type(LUSTRE_MGC_NAME); | 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 | MODULE_DESCRIPTION("Lustre Management Client"); | 1729 | MODULE_DESCRIPTION("Lustre Management Client"); |
| 1730 | MODULE_LICENSE("GPL"); | 1730 | MODULE_LICENSE("GPL"); |
| 1731 | 1731 | ||
| @@ -235,15 +235,6 @@ _out: · 234 unmodified lines | |||
| 235 | } | 235 | } |
| 236 | EXPORT_SYMBOL(lustre_posix_acl_xattr_filter); | 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 | * Release the extended ACL space. | 239 | * Release the extended ACL space. |
| 249 | */ | 240 | */ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | EXPORT_SYMBOL(cl_io_rw_init); | 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 | static int cl_lock_descr_sort(const struct cl_lock_descr *d0, | 239 | static int cl_lock_descr_sort(const struct cl_lock_descr *d0, |
| 246 | const struct cl_lock_descr *d1) | 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 | __diff_normalize(d0->cld_start, d1->cld_start); | 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 | int ret; | 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 | if (ret) | 254 | if (ret) |
| 259 | return ret; | 255 | return ret; |
| 260 | if (d0->cld_end < d1->cld_start) | 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 | EXPORT_SYMBOL(cl_2queue_init); | 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 | * Disown pages in both lists of a 2-queue. | 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 | void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page) | 1249 | void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page) |
| 1263 | { | 1250 | { |
| 1264 | cl_2queue_init(queue); | 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 | EXPORT_SYMBOL(cl_2queue_init_page); | 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 | * \see cl_lock_mutex_get() | 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 | int result; | 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 | result = -EBUSY; | 705 | result = -EBUSY; |
| 706 | return result; | 706 | return result; |
| 707 | } | 707 | } |
| 708 | EXPORT_SYMBOL(cl_lock_mutex_try); | ||
| 709 | 708 | ||
| 710 | /** | 709 | /** |
| 711 | {* Unlocks cl_lock object. | 710 | {* Unlocks cl_lock object. |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | return container_of(env, struct cl_env, ce_lu); | 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 | struct lu_env *env; | 709 | struct lu_env *env; |
| 710 | struct cl_env *cle; | 710 | struct cl_env *cle; |
| @@ -724,7 +724,6 @@ struct lu_env *cl_env_peek(int *refcheck) · 13 unmodified lines | |||
| 724 | CDEBUG(D_OTHER, "%d@%p\n", cle ? cle->ce_ref : 0, cle); | 724 | CDEBUG(D_OTHER, "%d@%p\n", cle ? cle->ce_ref : 0, cle); |
| 725 | return env; | 725 | return env; |
| 726 | } | 726 | } |
| 727 | EXPORT_SYMBOL(cl_env_peek); | ||
| 728 | 727 | ||
| 729 | /** | 728 | /** |
| 730 | * Returns lu_env: if there already is an environment associated with the | 729 | * Returns lu_env: if there already is an environment associated with the |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 33 | * This file is part of Lustre, http://www.lustre.org/ |
| @@ -576,7 +576,7 @@ static void cleanup_obdclass(void) · 542 unmodified lines | |||
| 576 | obd_zombie_impexp_stop(); | 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 | MODULE_DESCRIPTION("Lustre Class Driver Build Version: " BUILD_VERSION); | 580 | MODULE_DESCRIPTION("Lustre Class Driver Build Version: " BUILD_VERSION); |
| 581 | MODULE_LICENSE("GPL"); | 581 | MODULE_LICENSE("GPL"); |
| 582 | MODULE_VERSION(LUSTRE_VERSION_STRING); | 582 | MODULE_VERSION(LUSTRE_VERSION_STRING); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. | 27 | * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. |
| 28 | * Use is subject to license terms. | 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 | * This file is part of Lustre, http://www.lustre.org/ | 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 | if (type) { | 132 | if (type) { |
| 133 | spin_lock(&type->obd_type_lock); | 133 | spin_lock(&type->obd_type_lock); |
| 134 | type->typ_refcnt++; | 134 | type->typ_refcnt++; |
| 135 | try_module_get(type->typ_dt_ops->o_owner); | 135 | try_module_get(type->typ_dt_ops->owner); |
| 136 | spin_unlock(&type->obd_type_lock); | 136 | spin_unlock(&type->obd_type_lock); |
| 137 | } | 137 | } |
| 138 | return type; | 138 | return type; |
| @@ -143,7 +143,7 @@ void class_put_type(struct obd_type *type) · 4 unmodified lines | |||
| 143 | LASSERT(type); | 143 | LASSERT(type); |
| 144 | spin_lock(&type->obd_type_lock); | 144 | spin_lock(&type->obd_type_lock); |
| 145 | type->typ_refcnt--; | 145 | type->typ_refcnt--; |
| 146 | module_put(type->typ_dt_ops->o_owner); | 146 | module_put(type->typ_dt_ops->owner); |
| 147 | spin_unlock(&type->obd_type_lock); | 147 | spin_unlock(&type->obd_type_lock); |
| 148 | } | 148 | } |
| 149 | EXPORT_SYMBOL(class_put_type); | 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 | struct lu_device_type *ldt) | 155 | struct lu_device_type *ldt) |
| 156 | { | 156 | { |
| 157 | struct obd_type *type; | 157 | struct obd_type *type; |
| 158 | int rc = 0; | 158 | int rc; |
| 159 | 159 | ||
| 160 | /* sanity check */ | 160 | /* sanity check */ |
| 161 | LASSERT(strnlen(name, CLASS_MAX_NAME) < CLASS_MAX_NAME); | 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.