From a9fd053b56c6bb14972ab7a19da0b575fe4c5d66 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 19 Nov 2015 10:15:17 +0100 Subject: iio: st_sensors: support active-low interrupts Most ST MEMS Sensors that support interrupts can also handle sending an active low interrupt, i.e. going from high to low on data ready (or other interrupt) and thus triggering on a falling edge to the interrupt controller. Set up logic to inspect the interrupt line we get for a sensor: if it is triggering on rising edge, leave everything alone, but if it triggers on falling edges, set up active low, and if unsupported configurations appear: warn with errors and reconfigure the interrupt to a rising edge, which all interrupt generating sensors support. Create a local header for st_sensors_core.h to share functions between the sensor core and the trigger setup code. Cc: Giuseppe Barba Cc: Denis Ciocca Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- include/linux/iio/common/st_sensors.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 2fe939c73cd2..6670c3d25c58 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -119,6 +119,8 @@ struct st_sensor_bdu { * @addr: address of the register. * @mask_int1: mask to enable/disable IRQ on INT1 pin. * @mask_int2: mask to enable/disable IRQ on INT2 pin. + * @addr_ihl: address to enable/disable active low on the INT lines. + * @mask_ihl: mask to enable/disable active low on the INT lines. * struct ig1 - represents the Interrupt Generator 1 of sensors. * @en_addr: address of the enable ig1 register. * @en_mask: mask to write the on/off value for enable. @@ -127,6 +129,8 @@ struct st_sensor_data_ready_irq { u8 addr; u8 mask_int1; u8 mask_int2; + u8 addr_ihl; + u8 mask_ihl; struct { u8 en_addr; u8 en_mask; -- cgit v1.2.3-71-gd317 From 131497acd88a4456d99247cee457baefd2817835 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Delgado Date: Sat, 16 Jan 2016 14:24:07 +0100 Subject: iio: add ad5761 DAC driver ad5761 is a 1-channel DAC with configurable output range. The driver uses the regulator interface for its voltage ref. It shares its register layout with ad5761r, ad5721 and ad5721r. Differences: ad5761* are 16 bit, ad5721* are 12 bits. ad57*1r have an internal reference. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Jonathan Cameron --- CREDITS | 1 + drivers/iio/dac/Kconfig | 10 + drivers/iio/dac/Makefile | 1 + drivers/iio/dac/ad5761.c | 430 +++++++++++++++++++++++++++++++++++ include/linux/platform_data/ad5761.h | 44 ++++ 5 files changed, 486 insertions(+) create mode 100644 drivers/iio/dac/ad5761.c create mode 100644 include/linux/platform_data/ad5761.h (limited to 'include/linux') diff --git a/CREDITS b/CREDITS index 8207cc62ee9d..44ea433d70a1 100644 --- a/CREDITS +++ b/CREDITS @@ -3035,6 +3035,7 @@ D: PLX USB338x driver D: PCA9634 driver D: Option GTM671WFS D: Fintek F81216A +D: AD5761 iio driver D: Various kernel hacks S: Qtechnology A/S S: Valby Langgade 142 diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 5263c5125fbb..5dc71505da61 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -111,6 +111,16 @@ config AD5755 To compile this driver as a module, choose M here: the module will be called ad5755. +config AD5761 + tristate "Analog Devices AD5761/61R/21/21R DAC driver" + depends on SPI_MASTER + help + Say yes here to build support for Analog Devices AD5761, AD5761R, AD5721, + AD5721R Digital to Analog Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5761. + config AD5764 tristate "Analog Devices AD5764/64R/44/44R DAC driver" depends on SPI_MASTER diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 63ae05633e0c..cb525b53fc7b 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_AD5504) += ad5504.o obj-$(CONFIG_AD5446) += ad5446.o obj-$(CONFIG_AD5449) += ad5449.o obj-$(CONFIG_AD5755) += ad5755.o +obj-$(CONFIG_AD5761) += ad5761.o obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5686) += ad5686.o diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c new file mode 100644 index 000000000000..d6510d6928b3 --- /dev/null +++ b/drivers/iio/dac/ad5761.c @@ -0,0 +1,430 @@ +/* + * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter + * + * Copyright 2016 Qtechnology A/S + * 2016 Ricardo Ribalda + * + * Licensed under the GPL-2. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define AD5761_ADDR(addr) ((addr & 0xf) << 16) +#define AD5761_ADDR_NOOP 0x0 +#define AD5761_ADDR_DAC_WRITE 0x3 +#define AD5761_ADDR_CTRL_WRITE_REG 0x4 +#define AD5761_ADDR_SW_DATA_RESET 0x7 +#define AD5761_ADDR_DAC_READ 0xb +#define AD5761_ADDR_CTRL_READ_REG 0xc +#define AD5761_ADDR_SW_FULL_RESET 0xf + +#define AD5761_CTRL_USE_INTVREF BIT(5) +#define AD5761_CTRL_ETS BIT(6) + +/** + * struct ad5761_chip_info - chip specific information + * @int_vref: Value of the internal reference voltage in mV - 0 if external + * reference voltage is used + * @channel: channel specification +*/ + +struct ad5761_chip_info { + unsigned long int_vref; + const struct iio_chan_spec channel; +}; + +struct ad5761_range_params { + int m; + int c; +}; + +enum ad5761_supported_device_ids { + ID_AD5721, + ID_AD5721R, + ID_AD5761, + ID_AD5761R, +}; + +/** + * struct ad5761_state - driver instance specific data + * @spi: spi_device + * @vref_reg: reference voltage regulator + * @use_intref: true when the internal voltage reference is used + * @vref: actual voltage reference in mVolts + * @range: output range mode used + * @data: cache aligned spi buffer + */ +struct ad5761_state { + struct spi_device *spi; + struct regulator *vref_reg; + + bool use_intref; + int vref; + enum ad5761_voltage_range range; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + __be32 d32; + u8 d8[4]; + } data[3] ____cacheline_aligned; +}; + +static const struct ad5761_range_params ad5761_range_params[] = { + [AD5761_VOLTAGE_RANGE_M10V_10V] = { + .m = 80, + .c = 40, + }, + [AD5761_VOLTAGE_RANGE_0V_10V] = { + .m = 40, + .c = 0, + }, + [AD5761_VOLTAGE_RANGE_M5V_5V] = { + .m = 40, + .c = 20, + }, + [AD5761_VOLTAGE_RANGE_0V_5V] = { + .m = 20, + .c = 0, + }, + [AD5761_VOLTAGE_RANGE_M2V5_7V5] = { + .m = 40, + .c = 10, + }, + [AD5761_VOLTAGE_RANGE_M3V_3V] = { + .m = 24, + .c = 12, + }, + [AD5761_VOLTAGE_RANGE_0V_16V] = { + .m = 64, + .c = 0, + }, + [AD5761_VOLTAGE_RANGE_0V_20V] = { + .m = 80, + .c = 0, + }, +}; + +static int _ad5761_spi_write(struct ad5761_state *st, u8 addr, u16 val) +{ + st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr) | val); + + return spi_write(st->spi, &st->data[0].d8[1], 3); +} + +static int ad5761_spi_write(struct iio_dev *indio_dev, u8 addr, u16 val) +{ + struct ad5761_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + ret = _ad5761_spi_write(st, addr, val); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int _ad5761_spi_read(struct ad5761_state *st, u8 addr, u16 *val) +{ + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = &st->data[0].d8[1], + .bits_per_word = 8, + .len = 3, + .cs_change = true, + }, { + .tx_buf = &st->data[1].d8[1], + .rx_buf = &st->data[2].d8[1], + .bits_per_word = 8, + .len = 3, + }, + }; + + st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr)); + st->data[1].d32 = cpu_to_be32(AD5761_ADDR(AD5761_ADDR_NOOP)); + + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); + + *val = be32_to_cpu(st->data[2].d32); + + return ret; +} + +static int ad5761_spi_read(struct iio_dev *indio_dev, u8 addr, u16 *val) +{ + struct ad5761_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + ret = _ad5761_spi_read(st, addr, val); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5761_spi_set_range(struct ad5761_state *st, + enum ad5761_voltage_range range) +{ + u16 aux; + int ret; + + aux = (range & 0x7) | AD5761_CTRL_ETS; + + if (st->use_intref) + aux |= AD5761_CTRL_USE_INTVREF; + + ret = _ad5761_spi_write(st, AD5761_ADDR_SW_FULL_RESET, 0); + if (ret) + return ret; + + ret = _ad5761_spi_write(st, AD5761_ADDR_CTRL_WRITE_REG, aux); + if (ret) + return ret; + + st->range = range; + + return 0; +} + +static int ad5761_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct ad5761_state *st; + int ret; + u16 aux; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = ad5761_spi_read(indio_dev, AD5761_ADDR_DAC_READ, &aux); + if (ret) + return ret; + *val = aux >> chan->scan_type.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + st = iio_priv(indio_dev); + *val = st->vref * ad5761_range_params[st->range].m; + *val /= 10; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + st = iio_priv(indio_dev); + *val = -(1 << chan->scan_type.realbits); + *val *= ad5761_range_params[st->range].c; + *val /= ad5761_range_params[st->range].m; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ad5761_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + u16 aux; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + if (val2 || (val << chan->scan_type.shift) > 0xffff || val < 0) + return -EINVAL; + + aux = val << chan->scan_type.shift; + + return ad5761_spi_write(indio_dev, AD5761_ADDR_DAC_WRITE, aux); +} + +static const struct iio_info ad5761_info = { + .read_raw = &ad5761_read_raw, + .write_raw = &ad5761_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD5761_CHAN(_bits) { \ + .type = IIO_VOLTAGE, \ + .output = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = (_bits), \ + .storagebits = 16, \ + .shift = 16 - (_bits), \ + }, \ +} + +static const struct ad5761_chip_info ad5761_chip_infos[] = { + [ID_AD5721] = { + .int_vref = 0, + .channel = AD5761_CHAN(12), + }, + [ID_AD5721R] = { + .int_vref = 2500, + .channel = AD5761_CHAN(12), + }, + [ID_AD5761] = { + .int_vref = 0, + .channel = AD5761_CHAN(16), + }, + [ID_AD5761R] = { + .int_vref = 2500, + .channel = AD5761_CHAN(16), + }, +}; + +static int ad5761_get_vref(struct ad5761_state *st, + const struct ad5761_chip_info *chip_info) +{ + int ret; + + st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref"); + if (PTR_ERR(st->vref_reg) == -ENODEV) { + /* Use Internal regulator */ + if (!chip_info->int_vref) { + dev_err(&st->spi->dev, + "Voltage reference not found\n"); + return -EIO; + } + + st->use_intref = true; + st->vref = chip_info->int_vref; + return 0; + } + + if (IS_ERR(st->vref_reg)) { + dev_err(&st->spi->dev, + "Error getting voltage reference regulator\n"); + return PTR_ERR(st->vref_reg); + } + + ret = regulator_enable(st->vref_reg); + if (ret) { + dev_err(&st->spi->dev, + "Failed to enable voltage reference\n"); + return ret; + } + + ret = regulator_get_voltage(st->vref_reg); + if (ret < 0) { + dev_err(&st->spi->dev, + "Failed to get voltage reference value\n"); + goto disable_regulator_vref; + } + + if (ret < 2000000 || ret > 3000000) { + dev_warn(&st->spi->dev, + "Invalid external voltage ref. value %d uV\n", ret); + ret = -EIO; + goto disable_regulator_vref; + } + + st->vref = ret / 1000; + st->use_intref = false; + + return 0; + +disable_regulator_vref: + regulator_disable(st->vref_reg); + st->vref_reg = NULL; + return ret; +} + +static int ad5761_probe(struct spi_device *spi) +{ + struct iio_dev *iio_dev; + struct ad5761_state *st; + int ret; + const struct ad5761_chip_info *chip_info = + &ad5761_chip_infos[spi_get_device_id(spi)->driver_data]; + enum ad5761_voltage_range voltage_range = AD5761_VOLTAGE_RANGE_0V_5V; + struct ad5761_platform_data *pdata = dev_get_platdata(&spi->dev); + + iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!iio_dev) + return -ENOMEM; + + st = iio_priv(iio_dev); + + st->spi = spi; + spi_set_drvdata(spi, iio_dev); + + ret = ad5761_get_vref(st, chip_info); + if (ret) + return ret; + + if (pdata) + voltage_range = pdata->voltage_range; + + ret = ad5761_spi_set_range(st, voltage_range); + if (ret) + goto disable_regulator_err; + + iio_dev->dev.parent = &spi->dev; + iio_dev->info = &ad5761_info; + iio_dev->modes = INDIO_DIRECT_MODE; + iio_dev->channels = &chip_info->channel; + iio_dev->num_channels = 1; + iio_dev->name = spi_get_device_id(st->spi)->name; + ret = iio_device_register(iio_dev); + if (ret) + goto disable_regulator_err; + + return 0; + +disable_regulator_err: + if (!IS_ERR_OR_NULL(st->vref_reg)) + regulator_disable(st->vref_reg); + + return ret; +} + +static int ad5761_remove(struct spi_device *spi) +{ + struct iio_dev *iio_dev = spi_get_drvdata(spi); + struct ad5761_state *st = iio_priv(iio_dev); + + iio_device_unregister(iio_dev); + + if (!IS_ERR_OR_NULL(st->vref_reg)) + regulator_disable(st->vref_reg); + + return 0; +} + +static const struct spi_device_id ad5761_id[] = { + {"ad5721", ID_AD5721}, + {"ad5721r", ID_AD5721R}, + {"ad5761", ID_AD5761}, + {"ad5761r", ID_AD5761R}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5761_id); + +static struct spi_driver ad5761_driver = { + .driver = { + .name = "ad5761", + }, + .probe = ad5761_probe, + .remove = ad5761_remove, + .id_table = ad5761_id, +}; +module_spi_driver(ad5761_driver); + +MODULE_AUTHOR("Ricardo Ribalda "); +MODULE_DESCRIPTION("Analog Devices AD5721, AD5721R, AD5761, AD5761R driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/platform_data/ad5761.h b/include/linux/platform_data/ad5761.h new file mode 100644 index 000000000000..7bd8ed7d978e --- /dev/null +++ b/include/linux/platform_data/ad5761.h @@ -0,0 +1,44 @@ +/* + * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter + * + * Copyright 2016 Qtechnology A/S + * 2016 Ricardo Ribalda + * + * Licensed under the GPL-2. + */ +#ifndef __LINUX_PLATFORM_DATA_AD5761_H__ +#define __LINUX_PLATFORM_DATA_AD5761_H__ + +/** + * enum ad5761_voltage_range - Voltage range the AD5761 is configured for. + * @AD5761_VOLTAGE_RANGE_M10V_10V: -10V to 10V + * @AD5761_VOLTAGE_RANGE_0V_10V: 0V to 10V + * @AD5761_VOLTAGE_RANGE_M5V_5V: -5V to 5V + * @AD5761_VOLTAGE_RANGE_0V_5V: 0V to 5V + * @AD5761_VOLTAGE_RANGE_M2V5_7V5: -2.5V to 7.5V + * @AD5761_VOLTAGE_RANGE_M3V_3V: -3V to 3V + * @AD5761_VOLTAGE_RANGE_0V_16V: 0V to 16V + * @AD5761_VOLTAGE_RANGE_0V_20V: 0V to 20V + */ + +enum ad5761_voltage_range { + AD5761_VOLTAGE_RANGE_M10V_10V, + AD5761_VOLTAGE_RANGE_0V_10V, + AD5761_VOLTAGE_RANGE_M5V_5V, + AD5761_VOLTAGE_RANGE_0V_5V, + AD5761_VOLTAGE_RANGE_M2V5_7V5, + AD5761_VOLTAGE_RANGE_M3V_3V, + AD5761_VOLTAGE_RANGE_0V_16V, + AD5761_VOLTAGE_RANGE_0V_20V, +}; + +/** + * struct ad5761_platform_data - AD5761 DAC driver platform data + * @voltage_range: Voltage range the AD5761 is configured for + */ + +struct ad5761_platform_data { + enum ad5761_voltage_range voltage_range; +}; + +#endif -- cgit v1.2.3-71-gd317 From b55b54b5db330e36cd465adb3fbe274ffb1061d3 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:21 -0200 Subject: staging/android: remove struct sync_pt struct sync_pt was just wrapping around struct fence and creating an extra abstraction layer. The only two members of struct sync_pt, child_list and active_list, were moved to struct fence in an earlier commit. After removing those two members struct sync_pt is nothing more than struct fence, so remove it all and use struct fence directly. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sw_sync.c | 23 ++++---- drivers/staging/android/sw_sync.h | 8 +-- drivers/staging/android/sync.c | 101 +++++++++++++++-------------------- drivers/staging/android/sync.h | 63 +++++++--------------- drivers/staging/android/sync_debug.c | 49 ++++++++--------- drivers/staging/android/trace/sync.h | 14 ++--- include/linux/fence.h | 2 + 7 files changed, 113 insertions(+), 147 deletions(-) (limited to 'include/linux') diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index f491dbce5696..3bee959b41d8 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -25,7 +25,7 @@ #include "sw_sync.h" -struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) +struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) { struct sw_sync_pt *pt; @@ -34,23 +34,23 @@ struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) pt->value = value; - return (struct sync_pt *)pt; + return (struct fence *)pt; } EXPORT_SYMBOL(sw_sync_pt_create); -static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt) +static int sw_sync_fence_has_signaled(struct fence *fence) { - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; struct sw_sync_timeline *obj = - (struct sw_sync_timeline *)sync_pt_parent(sync_pt); + (struct sw_sync_timeline *)fence_parent(fence); return (pt->value > obj->value) ? 0 : 1; } -static int sw_sync_fill_driver_data(struct sync_pt *sync_pt, +static int sw_sync_fill_driver_data(struct fence *fence, void *data, int size) { - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; if (size < sizeof(pt->value)) return -ENOMEM; @@ -68,20 +68,19 @@ static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline, snprintf(str, size, "%d", timeline->value); } -static void sw_sync_pt_value_str(struct sync_pt *sync_pt, - char *str, int size) +static void sw_sync_fence_value_str(struct fence *fence, char *str, int size) { - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; snprintf(str, size, "%d", pt->value); } static struct sync_timeline_ops sw_sync_timeline_ops = { .driver_name = "sw_sync", - .has_signaled = sw_sync_pt_has_signaled, + .has_signaled = sw_sync_fence_has_signaled, .fill_driver_data = sw_sync_fill_driver_data, .timeline_value_str = sw_sync_timeline_value_str, - .pt_value_str = sw_sync_pt_value_str, + .fence_value_str = sw_sync_fence_value_str, }; struct sw_sync_timeline *sw_sync_timeline_create(const char *name) diff --git a/drivers/staging/android/sw_sync.h b/drivers/staging/android/sw_sync.h index c87ae9ebf267..e18667bfb0ca 100644 --- a/drivers/staging/android/sw_sync.h +++ b/drivers/staging/android/sw_sync.h @@ -29,7 +29,7 @@ struct sw_sync_timeline { }; struct sw_sync_pt { - struct sync_pt pt; + struct fence pt; u32 value; }; @@ -38,7 +38,7 @@ struct sw_sync_pt { struct sw_sync_timeline *sw_sync_timeline_create(const char *name); void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc); -struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value); +struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value); #else static inline struct sw_sync_timeline *sw_sync_timeline_create(const char *name) { @@ -49,8 +49,8 @@ static inline void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc) { } -static inline struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, - u32 value) +static inline struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, + u32 value) { return NULL; } diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 22b1d9b03fd6..3c2c8d07df62 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -102,51 +102,45 @@ void sync_timeline_signal(struct sync_timeline *obj) { unsigned long flags; LIST_HEAD(signaled_pts); - struct sync_pt *pt, *next; + struct fence *fence, *next; trace_sync_timeline(obj); spin_lock_irqsave(&obj->child_list_lock, flags); - list_for_each_entry_safe(pt, next, &obj->active_list_head, + list_for_each_entry_safe(fence, next, &obj->active_list_head, active_list) { - if (fence_is_signaled_locked(&pt->base)) - list_del_init(&pt->active_list); + if (fence_is_signaled_locked(fence)) + list_del_init(&fence->active_list); } spin_unlock_irqrestore(&obj->child_list_lock, flags); } EXPORT_SYMBOL(sync_timeline_signal); -struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size) +struct fence *sync_pt_create(struct sync_timeline *obj, int size) { unsigned long flags; - struct sync_pt *pt; + struct fence *fence; - if (size < sizeof(struct sync_pt)) + if (size < sizeof(*fence)) return NULL; - pt = kzalloc(size, GFP_KERNEL); - if (!pt) + fence = kzalloc(size, GFP_KERNEL); + if (!fence) return NULL; spin_lock_irqsave(&obj->child_list_lock, flags); sync_timeline_get(obj); - fence_init(&pt->base, &android_fence_ops, &obj->child_list_lock, + fence_init(fence, &android_fence_ops, &obj->child_list_lock, obj->context, ++obj->value); - list_add_tail(&pt->child_list, &obj->child_list_head); - INIT_LIST_HEAD(&pt->active_list); + list_add_tail(&fence->child_list, &obj->child_list_head); + INIT_LIST_HEAD(&fence->active_list); spin_unlock_irqrestore(&obj->child_list_lock, flags); - return pt; + return fence; } EXPORT_SYMBOL(sync_pt_create); -void sync_pt_free(struct sync_pt *pt) -{ - fence_put(&pt->base); -} -EXPORT_SYMBOL(sync_pt_free); - static struct sync_file *sync_file_alloc(int size, const char *name) { struct sync_file *sync_file; @@ -184,8 +178,8 @@ static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) wake_up_all(&sync_file->wq); } -/* TODO: implement a create which takes more that one sync_pt */ -struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) +/* TODO: implement a create which takes more that one fence */ +struct sync_file *sync_file_create_dma(const char *name, struct fence *fence) { struct sync_file *sync_file; @@ -197,9 +191,10 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) sync_file->num_fences = 1; atomic_set(&sync_file->status, 1); - sync_file->cbs[0].fence = pt; + sync_file->cbs[0].fence = fence; sync_file->cbs[0].sync_file = sync_file; - if (fence_add_callback(pt, &sync_file->cbs[0].cb, fence_check_cb_func)) + if (fence_add_callback(fence, &sync_file->cbs[0].cb, + fence_check_cb_func)) atomic_dec(&sync_file->status); sync_file_debug_add(sync_file); @@ -208,9 +203,9 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) } EXPORT_SYMBOL(sync_file_create_dma); -struct sync_file *sync_file_create(const char *name, struct sync_pt *pt) +struct sync_file *sync_file_create(const char *name, struct fence *fence) { - return sync_file_create_dma(name, &pt->base); + return sync_file_create_dma(name, fence); } EXPORT_SYMBOL(sync_file_create); @@ -245,14 +240,14 @@ void sync_file_install(struct sync_file *sync_file, int fd) EXPORT_SYMBOL(sync_file_install); static void sync_file_add_pt(struct sync_file *sync_file, int *i, - struct fence *pt) + struct fence *fence) { - sync_file->cbs[*i].fence = pt; + sync_file->cbs[*i].fence = fence; sync_file->cbs[*i].sync_file = sync_file; - if (!fence_add_callback(pt, &sync_file->cbs[*i].cb, + if (!fence_add_callback(fence, &sync_file->cbs[*i].cb, fence_check_cb_func)) { - fence_get(pt); + fence_get(fence); (*i)++; } } @@ -328,7 +323,7 @@ int sync_file_wait(struct sync_file *sync_file, long timeout) trace_sync_wait(sync_file, 1); for (i = 0; i < sync_file->num_fences; ++i) - trace_sync_pt(sync_file->cbs[i].fence); + trace_fence(sync_file->cbs[i].fence); ret = wait_event_interruptible_timeout(sync_file->wq, atomic_read(&sync_file->status) <= 0, timeout); @@ -356,43 +351,39 @@ EXPORT_SYMBOL(sync_file_wait); static const char *android_fence_get_driver_name(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); return parent->ops->driver_name; } static const char *android_fence_get_timeline_name(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); return parent->name; } static void android_fence_release(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); unsigned long flags; spin_lock_irqsave(fence->lock, flags); - list_del(&pt->child_list); - if (WARN_ON_ONCE(!list_empty(&pt->active_list))) - list_del(&pt->active_list); + list_del(&fence->child_list); + if (WARN_ON_ONCE(!list_empty(&fence->active_list))) + list_del(&fence->active_list); spin_unlock_irqrestore(fence->lock, flags); sync_timeline_put(parent); - fence_free(&pt->base); + fence_free(fence); } static bool android_fence_signaled(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); int ret; - ret = parent->ops->has_signaled(pt); + ret = parent->ops->has_signaled(fence); if (ret < 0) fence->status = ret; return ret; @@ -400,46 +391,42 @@ static bool android_fence_signaled(struct fence *fence) static bool android_fence_enable_signaling(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); if (android_fence_signaled(fence)) return false; - list_add_tail(&pt->active_list, &parent->active_list_head); + list_add_tail(&fence->active_list, &parent->active_list_head); return true; } static int android_fence_fill_driver_data(struct fence *fence, void *data, int size) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); if (!parent->ops->fill_driver_data) return 0; - return parent->ops->fill_driver_data(pt, data, size); + return parent->ops->fill_driver_data(fence, data, size); } static void android_fence_value_str(struct fence *fence, char *str, int size) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); - if (!parent->ops->pt_value_str) { + if (!parent->ops->fence_value_str) { if (size) *str = 0; return; } - parent->ops->pt_value_str(pt, str, size); + parent->ops->fence_value_str(fence, str, size); } static void android_fence_timeline_value_str(struct fence *fence, char *str, int size) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); if (!parent->ops->timeline_value_str) { if (size) @@ -624,9 +611,9 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, len = sizeof(struct sync_file_info_data); for (i = 0; i < sync_file->num_fences; ++i) { - struct fence *pt = sync_file->cbs[i].fence; + struct fence *fence = sync_file->cbs[i].fence; - ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len); + ret = sync_fill_pt_info(fence, (u8 *)data + len, size - len); if (ret < 0) goto out; diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index a18d1e3365fb..8cdac1a12e4f 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -24,7 +24,6 @@ #include "uapi/sync.h" struct sync_timeline; -struct sync_pt; struct sync_file; /** @@ -39,23 +38,23 @@ struct sync_file; * as specified by size. This information is returned * to userspace by SYNC_IOC_FENCE_INFO. * @timeline_value_str: fill str with the value of the sync_timeline's counter - * @pt_value_str: fill str with the value of the sync_pt + * @fence_value_str: fill str with the value of the fence */ struct sync_timeline_ops { const char *driver_name; /* required */ - int (*has_signaled)(struct sync_pt *pt); + int (*has_signaled)(struct fence *fence); /* optional */ - int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size); + int (*fill_driver_data)(struct fence *fence, void *data, int size); /* optional */ void (*timeline_value_str)(struct sync_timeline *timeline, char *str, int size); /* optional */ - void (*pt_value_str)(struct sync_pt *pt, char *str, int size); + void (*fence_value_str)(struct fence *fence, char *str, int size); }; /** @@ -66,7 +65,7 @@ struct sync_timeline_ops { * @destroyed: set when sync_timeline is destroyed * @child_list_head: list of children sync_pts for this sync_timeline * @child_list_lock: lock protecting @child_list_head, destroyed, and - * sync_pt.status + * fence.status * @active_list_head: list of active (unsignaled/errored) sync_pts * @sync_timeline_list: membership in global sync_timeline_list */ @@ -89,22 +88,9 @@ struct sync_timeline { #endif }; -/** - * struct sync_pt - sync point - * @base: base fence class - * @child_list: membership in sync_timeline.child_list_head - * @active_list: membership in sync_timeline.active_list_head - */ -struct sync_pt { - struct fence base; - - struct list_head child_list; - struct list_head active_list; -}; - -static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt) +static inline struct sync_timeline *fence_parent(struct fence *fence) { - return container_of(pt->base.lock, struct sync_timeline, + return container_of(fence->lock, struct sync_timeline, child_list_lock); } @@ -164,7 +150,7 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, * * A sync implementation should call this when the @obj is going away * (i.e. module unload.) @obj won't actually be freed until all its children - * sync_pts are freed. + * fences are freed. */ void sync_timeline_destroy(struct sync_timeline *obj); @@ -172,41 +158,32 @@ void sync_timeline_destroy(struct sync_timeline *obj); * sync_timeline_signal() - signal a status change on a sync_timeline * @obj: sync_timeline to signal * - * A sync implementation should call this any time one of it's sync_pts + * A sync implementation should call this any time one of it's fences * has signaled or has an error condition. */ void sync_timeline_signal(struct sync_timeline *obj); /** * sync_pt_create() - creates a sync pt - * @parent: sync_pt's parent sync_timeline + * @parent: fence's parent sync_timeline * @size: size to allocate for this pt * - * Creates a new sync_pt as a child of @parent. @size bytes will be + * Creates a new fence as a child of @parent. @size bytes will be * allocated allowing for implementation specific data to be kept after - * the generic sync_timeline struct. Returns the sync_pt object or + * the generic sync_timeline struct. Returns the fence object or * NULL in case of error. */ -struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size); +struct fence *sync_pt_create(struct sync_timeline *parent, int size); /** - * sync_pt_free() - frees a sync pt - * @pt: sync_pt to free + * sync_fence_create() - creates a sync fence + * @name: name of fence to create + * @fence: fence to add to the sync_fence * - * This should only be called on sync_pts which have been created but - * not added to a fence. - */ -void sync_pt_free(struct sync_pt *pt); - -/** - * sync_file_create() - creates a sync file - * @name: name of file to create - * @pt: sync_pt to add to the file - * - * Creates a sync_file containg @pt. Once this is called, the sync_file takes - * ownership of @pt. + * Creates a sync_file containg @fence. Once this is called, the sync_file + * takes ownership of @fence. */ -struct sync_file *sync_file_create(const char *name, struct sync_pt *pt); +struct sync_file *sync_file_create(const char *name, struct fence *fence); /** * sync_file_create_dma() - creates a sync file from dma-fence @@ -228,7 +205,7 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt); * @a: sync_file a * @b: sync_file b * - * Creates a new sync_file which contains copies of all the sync_pts in both + * Creates a new sync_file which contains copies of all the fences in both * @a and @b. @a and @b remain valid, independent sync_file. Returns the * new merged sync_file or NULL in case of error. */ diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 85ae98a63a1e..fd13f1e885e5 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -85,39 +85,40 @@ static const char *sync_status_str(int status) return "error"; } -static void sync_print_pt(struct seq_file *s, struct fence *pt, bool fence) +static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show) { int status = 1; + struct sync_timeline *parent = fence_parent(fence); - if (fence_is_signaled_locked(pt)) - status = pt->status; + if (fence_is_signaled_locked(fence)) + status = fence->status; - seq_printf(s, " %s%spt %s", - fence && pt->ops->get_timeline_name ? - pt->ops->get_timeline_name(pt) : "", - fence ? "_" : "", + seq_printf(s, " %s%sfence %s", + show ? parent->name : "", + show ? "_" : "", sync_status_str(status)); if (status <= 0) { struct timespec64 ts64 = - ktime_to_timespec64(pt->timestamp); + ktime_to_timespec64(fence->timestamp); seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); } - if ((!fence || pt->ops->timeline_value_str) && - pt->ops->fence_value_str) { + if ((!fence || fence->ops->timeline_value_str) && + fence->ops->fence_value_str) { char value[64]; bool success; - pt->ops->fence_value_str(pt, value, sizeof(value)); + fence->ops->fence_value_str(fence, value, sizeof(value)); success = strlen(value); if (success) seq_printf(s, ": %s", value); if (success && fence) { - pt->ops->timeline_value_str(pt, value, sizeof(value)); + fence->ops->timeline_value_str(fence, value, + sizeof(value)); if (strlen(value)) seq_printf(s, " / %s", value); @@ -145,25 +146,25 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) spin_lock_irqsave(&obj->child_list_lock, flags); list_for_each(pos, &obj->child_list_head) { - struct sync_pt *pt = - container_of(pos, struct sync_pt, child_list); - sync_print_pt(s, &pt->base, false); + struct fence *fence = + container_of(pos, struct fence, child_list); + sync_print_fence(s, fence, false); } spin_unlock_irqrestore(&obj->child_list_lock, flags); } static void sync_print_sync_file(struct seq_file *s, struct sync_file *sync_file) - { +{ int i; seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, sync_status_str(atomic_read(&sync_file->status))); for (i = 0; i < sync_file->num_fences; ++i) - sync_print_pt(s, sync_file->cbs[i].fence, true); - } - + sync_print_fence(s, sync_file->cbs[i].fence, true); +} + static int sync_debugfs_show(struct seq_file *s, void *unused) { unsigned long flags; @@ -244,7 +245,7 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, { int fd = get_unused_fd_flags(O_CLOEXEC); int err; - struct sync_pt *pt; + struct fence *fence; struct sync_file *sync_file; struct sw_sync_create_fence_data data; @@ -256,16 +257,16 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, goto err; } - pt = sw_sync_pt_create(obj, data.value); - if (!pt) { + fence = sw_sync_pt_create(obj, data.value); + if (!fence) { err = -ENOMEM; goto err; } data.name[sizeof(data.name) - 1] = '\0'; - sync_file = sync_file_create(data.name, pt); + sync_file = sync_file_create(data.name, fence); if (!sync_file) { - sync_pt_free(pt); + fence_put(fence); err = -ENOMEM; goto err; } diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h index 80f5da4f2aa5..87c60e9f584e 100644 --- a/drivers/staging/android/trace/sync.h +++ b/drivers/staging/android/trace/sync.h @@ -53,20 +53,20 @@ TRACE_EVENT(sync_wait, __get_str(name), __entry->status) ); -TRACE_EVENT(sync_pt, - TP_PROTO(struct fence *pt), +TRACE_EVENT(fence, + TP_PROTO(struct fence *fence), - TP_ARGS(pt), + TP_ARGS(fence), TP_STRUCT__entry( - __string(timeline, pt->ops->get_timeline_name(pt)) + __string(timeline, fence->ops->get_timeline_name(fence)) __array(char, value, 32) ), TP_fast_assign( - __assign_str(timeline, pt->ops->get_timeline_name(pt)); - if (pt->ops->fence_value_str) { - pt->ops->fence_value_str(pt, __entry->value, + __assign_str(timeline, fence->ops->get_timeline_name(fence)); + if (fence->ops->fence_value_str) { + fence->ops->fence_value_str(fence, __entry->value, sizeof(__entry->value)); } else { __entry->value[0] = '\0'; diff --git a/include/linux/fence.h b/include/linux/fence.h index bb522011383b..605bd88246a6 100644 --- a/include/linux/fence.h +++ b/include/linux/fence.h @@ -79,6 +79,8 @@ struct fence { unsigned long flags; ktime_t timestamp; int status; + struct list_head child_list; + struct list_head active_list; }; enum fence_flag_bits { -- cgit v1.2.3-71-gd317 From 9b1b282ccd8195e3264dbb3cd15b9d60b6345230 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:19 -0600 Subject: irqdomain: Added domain bus token DOMAIN_BUS_FSL_MC_MSI Since an FSL-MC bus is a new bus type that is neither PCI nor PLATFORM, we need a new domain bus token to disambiguate the IRQ domain for FSL-MC MSIs. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- include/linux/irqdomain.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 04579d9fbce4..0934d06c8b00 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -74,6 +74,7 @@ enum irq_domain_bus_token { DOMAIN_BUS_PCI_MSI, DOMAIN_BUS_PLATFORM_MSI, DOMAIN_BUS_NEXUS, + DOMAIN_BUS_FSL_MC_MSI, }; /** -- cgit v1.2.3-71-gd317 From 550308e48cddbc2aa74f7236941b17b55b2e78e9 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:20 -0600 Subject: fsl-mc: msi: Added FSL-MC-specific member to the msi_desc's union FSL-MC is a bus type different from PCI and platform, so it needs its own member in the msi_desc's union. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- include/linux/msi.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include/linux') diff --git a/include/linux/msi.h b/include/linux/msi.h index a2a0068a8387..8b425c66305a 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -32,6 +32,14 @@ struct platform_msi_desc { u16 msi_index; }; +/** + * fsl_mc_msi_desc - FSL-MC device specific msi descriptor data + * @msi_index: The index of the MSI descriptor + */ +struct fsl_mc_msi_desc { + u16 msi_index; +}; + /** * struct msi_desc - Descriptor structure for MSI based interrupts * @list: List head for management @@ -87,6 +95,7 @@ struct msi_desc { * tree wide cleanup. */ struct platform_msi_desc platform; + struct fsl_mc_msi_desc fsl_mc; }; }; -- cgit v1.2.3-71-gd317 From 0118de7b4c04cba1b275d889ad14a39950f30021 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 8 Feb 2016 17:03:15 +0200 Subject: iio: Fix documentation for iio_dev mlock mlock *must* be used by core and drivers to protect access to devices state changes. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- include/linux/iio/iio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index b5894118755f..ce9e9c1adf34 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -448,7 +448,7 @@ struct iio_buffer_setup_ops { * @buffer: [DRIVER] any buffer present * @buffer_list: [INTERN] list of all buffers currently attached * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux - * @mlock: [INTERN] lock used to prevent simultaneous device state + * @mlock: [DRIVER] lock used to prevent simultaneous device state * changes * @available_scan_masks: [DRIVER] optional array of allowed bitmasks * @masklength: [INTERN] the length of the mask established from -- cgit v1.2.3-71-gd317 From 3347a0656e7a83b959b1d0ad5396fb4f9c9b2a0e Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Mon, 15 Feb 2016 12:47:42 -0500 Subject: iio: Fix typos in the struct iio_event_spec documentation comments This patch fixes a few minor typos in the documentation comments for the scan_type member of the iio_event_spec structure. The sign member name was improperly capitalized as "Sign" in the comments. The storagebits member name was improperly listed as "storage_bits" in the comments. The endianness member entry in the comments was moved after the repeat member entry in order to maintain consistency with the actual struct iio_event_spec layout. Signed-off-by: William Breathitt Gray Signed-off-by: Jonathan Cameron --- include/linux/iio/iio.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index ce9e9c1adf34..b2b16772c651 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -180,18 +180,18 @@ struct iio_event_spec { * @address: Driver specific identifier. * @scan_index: Monotonic index to give ordering in scans when read * from a buffer. - * @scan_type: Sign: 's' or 'u' to specify signed or unsigned + * @scan_type: sign: 's' or 'u' to specify signed or unsigned * realbits: Number of valid bits of data - * storage_bits: Realbits + padding + * storagebits: Realbits + padding * shift: Shift right by this before masking out * realbits. - * endianness: little or big endian * repeat: Number of times real/storage bits * repeats. When the repeat element is * more than 1, then the type element in * sysfs will show a repeat value. * Otherwise, the number of repetitions is * omitted. + * endianness: little or big endian * @info_mask_separate: What information is to be exported that is specific to * this channel. * @info_mask_shared_by_type: What information is to be exported that is shared -- cgit v1.2.3-71-gd317 From cb77659272af51e80099c93b0e65abbf43bdaad5 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Sun, 14 Feb 2016 19:13:52 -0500 Subject: staging/lustre: proper support of NFS anonymous dentries NFS can ask to encode dentries that are not connected to the root. The fix check for parent is NULL and encode a file handle accordingly. Reviewed-on: http://review.whamcloud.com/8347 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4231 Reviewed-by: Fan Yong Reviewed-by: James Simmons Reviewed-by: Jian Yu Signed-off-by: Dmitry Eremin Signed-off-by: Oleg Drokin Acked-by: Jeff Layton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_nfs.c | 30 ++++++++++++++----------- include/linux/exportfs.h | 6 +++++ 2 files changed, 23 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 248441215794..74a88685e9dd 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -142,10 +142,11 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren struct inode *inode; struct dentry *result; - CDEBUG(D_INFO, "Get dentry for fid: "DFID"\n", PFID(fid)); if (!fid_is_sane(fid)) return ERR_PTR(-ESTALE); + CDEBUG(D_INFO, "Get dentry for fid: " DFID "\n", PFID(fid)); + inode = search_inode_for_lustre(sb, fid); if (IS_ERR(inode)) return ERR_CAST(inode); @@ -161,7 +162,7 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren * We have to find the parent to tell MDS how to init lov objects. */ if (S_ISREG(inode->i_mode) && !ll_i2info(inode)->lli_has_smd && - parent != NULL) { + parent && !fid_is_zero(parent)) { struct ll_inode_info *lli = ll_i2info(inode); spin_lock(&lli->lli_lock); @@ -175,8 +176,6 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren return result; } -#define LUSTRE_NFS_FID 0x97 - /** * \a connectable - is nfsd will connect himself or this should be done * at lustre @@ -189,20 +188,25 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren static int ll_encode_fh(struct inode *inode, __u32 *fh, int *plen, struct inode *parent) { + int fileid_len = sizeof(struct lustre_nfs_fid) / 4; struct lustre_nfs_fid *nfs_fid = (void *)fh; CDEBUG(D_INFO, "encoding for (%lu,"DFID") maxlen=%d minlen=%d\n", - inode->i_ino, PFID(ll_inode2fid(inode)), *plen, - (int)sizeof(struct lustre_nfs_fid)); + inode->i_ino, PFID(ll_inode2fid(inode)), *plen, fileid_len); - if (*plen < sizeof(struct lustre_nfs_fid) / 4) - return 255; + if (*plen < fileid_len) { + *plen = fileid_len; + return FILEID_INVALID; + } nfs_fid->lnf_child = *ll_inode2fid(inode); - nfs_fid->lnf_parent = *ll_inode2fid(parent); - *plen = sizeof(struct lustre_nfs_fid) / 4; + if (parent) + nfs_fid->lnf_parent = *ll_inode2fid(parent); + else + fid_zero(&nfs_fid->lnf_parent); + *plen = fileid_len; - return LUSTRE_NFS_FID; + return FILEID_LUSTRE; } static int ll_nfs_get_name_filldir(struct dir_context *ctx, const char *name, @@ -261,7 +265,7 @@ static struct dentry *ll_fh_to_dentry(struct super_block *sb, struct fid *fid, { struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid; - if (fh_type != LUSTRE_NFS_FID) + if (fh_type != FILEID_LUSTRE) return ERR_PTR(-EPROTO); return ll_iget_for_nfs(sb, &nfs_fid->lnf_child, &nfs_fid->lnf_parent); @@ -272,7 +276,7 @@ static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid, { struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid; - if (fh_type != LUSTRE_NFS_FID) + if (fh_type != FILEID_LUSTRE) return ERR_PTR(-EPROTO); return ll_iget_for_nfs(sb, &nfs_fid->lnf_parent, NULL); diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index fa05e04c5531..d8414502edb4 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -96,6 +96,12 @@ enum fid_type { */ FILEID_FAT_WITH_PARENT = 0x72, + /* + * 128 bit child FID (struct lu_fid) + * 128 bit parent FID (struct lu_fid) + */ + FILEID_LUSTRE = 0x97, + /* * Filesystems must not use 0xff file ID. */ -- cgit v1.2.3-71-gd317